oc_process.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # pylint: skip-file
  2. # flake8: noqa
  3. # pylint: disable=too-many-instance-attributes
  4. class OCProcess(OpenShiftCLI):
  5. ''' Class to wrap the oc command line tools '''
  6. # pylint allows 5. we need 6
  7. # pylint: disable=too-many-arguments
  8. def __init__(self,
  9. namespace,
  10. tname=None,
  11. params=None,
  12. create=False,
  13. kubeconfig='/etc/origin/master/admin.kubeconfig',
  14. tdata=None,
  15. verbose=False):
  16. ''' Constructor for OpenshiftOC '''
  17. super(OCProcess, self).__init__(namespace, kubeconfig)
  18. self.namespace = namespace
  19. self.name = tname
  20. self.data = tdata
  21. self.params = params
  22. self.create = create
  23. self.kubeconfig = kubeconfig
  24. self.verbose = verbose
  25. self._template = None
  26. @property
  27. def template(self):
  28. '''template property'''
  29. if self._template is None:
  30. results = self._process(self.name, False, self.params, self.data)
  31. if results['returncode'] != 0:
  32. raise OpenShiftCLIError('Error processing template [%s].' % self.name)
  33. self._template = results['results']['items']
  34. return self._template
  35. def get(self):
  36. '''get the template'''
  37. results = self._get('template', self.name)
  38. if results['returncode'] != 0:
  39. # Does the template exist??
  40. if 'not found' in results['stderr']:
  41. results['returncode'] = 0
  42. results['exists'] = False
  43. results['results'] = []
  44. return results
  45. def delete(self, obj):
  46. '''delete a resource'''
  47. return self._delete(obj['kind'], obj['metadata']['name'])
  48. def create_obj(self, obj):
  49. '''create a resource'''
  50. return self._create_from_content(obj['metadata']['name'], obj)
  51. def process(self, create=None):
  52. '''process a template'''
  53. do_create = False
  54. if create != None:
  55. do_create = create
  56. else:
  57. do_create = self.create
  58. return self._process(self.name, do_create, self.params, self.data)
  59. def exists(self):
  60. '''return whether the template exists'''
  61. # Always return true if we're being passed template data
  62. if self.data:
  63. return True
  64. t_results = self._get('template', self.name)
  65. if t_results['returncode'] != 0:
  66. # Does the template exist??
  67. if 'not found' in t_results['stderr']:
  68. return False
  69. else:
  70. raise OpenShiftCLIError('Something went wrong. %s' % t_results)
  71. return True
  72. def needs_update(self):
  73. '''attempt to process the template and return it for comparison with oc objects'''
  74. obj_results = []
  75. for obj in self.template:
  76. # build a list of types to skip
  77. skip = []
  78. if obj['kind'] == 'ServiceAccount':
  79. skip.extend(['secrets', 'imagePullSecrets'])
  80. if obj['kind'] == 'BuildConfig':
  81. skip.extend(['lastTriggeredImageID'])
  82. if obj['kind'] == 'ImageStream':
  83. skip.extend(['generation'])
  84. if obj['kind'] == 'DeploymentConfig':
  85. skip.extend(['lastTriggeredImage'])
  86. # fetch the current object
  87. curr_obj_results = self._get(obj['kind'], obj['metadata']['name'])
  88. if curr_obj_results['returncode'] != 0:
  89. # Does the template exist??
  90. if 'not found' in curr_obj_results['stderr']:
  91. obj_results.append((obj, True))
  92. continue
  93. # check the generated object against the existing object
  94. if not Utils.check_def_equal(obj, curr_obj_results['results'][0], skip_keys=skip):
  95. obj_results.append((obj, True))
  96. continue
  97. obj_results.append((obj, False))
  98. return obj_results
  99. # pylint: disable=too-many-return-statements
  100. @staticmethod
  101. def run_ansible(params, check_mode):
  102. '''run the ansible idempotent code'''
  103. ocprocess = OCProcess(params['namespace'],
  104. params['template_name'],
  105. params['params'],
  106. params['create'],
  107. kubeconfig=params['kubeconfig'],
  108. tdata=params['content'],
  109. verbose=params['debug'])
  110. state = params['state']
  111. api_rval = ocprocess.get()
  112. if state == 'list':
  113. if api_rval['returncode'] != 0:
  114. return {"failed": True, "msg" : api_rval}
  115. return {"changed" : False, "results": api_rval, "state": "list"}
  116. elif state == 'present':
  117. if check_mode and params['create']:
  118. return {"changed": True, 'msg': "CHECK_MODE: Would have processed template."}
  119. if not ocprocess.exists() or not params['reconcile']:
  120. #FIXME: this code will never get run in a way that succeeds when
  121. # module.params['reconcile'] is true. Because oc_process doesn't
  122. # create the actual template, the check of ocprocess.exists()
  123. # is meaningless. Either it's already here and this code
  124. # won't be run, or this code will fail because there is no
  125. # template available for oc process to use. Have we conflated
  126. # the template's existence with the existence of the objects
  127. # it describes?
  128. # Create it here
  129. api_rval = ocprocess.process()
  130. if api_rval['returncode'] != 0:
  131. return {"failed": True, "msg": api_rval}
  132. if params['create']:
  133. return {"changed": True, "results": api_rval, "state": "present"}
  134. return {"changed": False, "results": api_rval, "state": "present"}
  135. # verify results
  136. update = False
  137. rval = []
  138. all_results = ocprocess.needs_update()
  139. for obj, status in all_results:
  140. if status:
  141. ocprocess.delete(obj)
  142. results = ocprocess.create_obj(obj)
  143. results['kind'] = obj['kind']
  144. rval.append(results)
  145. update = True
  146. if not update:
  147. return {"changed": update, "results": api_rval, "state": "present"}
  148. for cmd in rval:
  149. if cmd['returncode'] != 0:
  150. return {"failed": True, "changed": update, "results": rval, "state": "present"}
  151. return {"changed": update, "results": rval, "state": "present"}