oc_secret.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # pylint: skip-file
  2. # flake8: noqa
  3. # pylint: skip-file
  4. # pylint: disable=wrong-import-position,wrong-import-order
  5. import base64
  6. # pylint: disable=too-many-arguments
  7. class OCSecret(OpenShiftCLI):
  8. ''' Class to wrap the oc command line tools
  9. '''
  10. def __init__(self,
  11. namespace,
  12. secret_name=None,
  13. secret_type=None,
  14. decode=False,
  15. kubeconfig='/etc/origin/master/admin.kubeconfig',
  16. verbose=False):
  17. ''' Constructor for OpenshiftOC '''
  18. super(OCSecret, self).__init__(namespace, kubeconfig=kubeconfig, verbose=verbose)
  19. self.name = secret_name
  20. self.type = secret_type
  21. self.decode = decode
  22. def get(self):
  23. '''return a secret by name '''
  24. results = self._get('secrets', self.name)
  25. results['decoded'] = {}
  26. results['exists'] = False
  27. if results['returncode'] == 0 and results['results'][0]:
  28. results['exists'] = True
  29. if self.decode:
  30. if 'data' in results['results'][0]:
  31. for sname, value in results['results'][0]['data'].items():
  32. results['decoded'][sname] = base64.b64decode(value)
  33. if results['returncode'] != 0 and '"%s" not found' % self.name in results['stderr']:
  34. results['returncode'] = 0
  35. return results
  36. def delete(self):
  37. '''delete a secret by name'''
  38. return self._delete('secrets', self.name)
  39. def create(self, files=None, contents=None):
  40. '''Create a secret '''
  41. if not files:
  42. files = Utils.create_tmp_files_from_contents(contents)
  43. secrets = ["%s=%s" % (sfile['name'], sfile['path']) for sfile in files]
  44. cmd = ['secrets', 'new', self.name]
  45. if self.type is not None:
  46. cmd.append("--type=%s" % (self.type))
  47. cmd.extend(secrets)
  48. results = self.openshift_cmd(cmd)
  49. return results
  50. def update(self, files, force=False):
  51. '''run update secret
  52. This receives a list of file names and converts it into a secret.
  53. The secret is then written to disk and passed into the `oc replace` command.
  54. '''
  55. secret = self.prep_secret(files)
  56. if secret['returncode'] != 0:
  57. return secret
  58. sfile_path = '/tmp/%s' % self.name
  59. with open(sfile_path, 'w') as sfd:
  60. sfd.write(json.dumps(secret['results']))
  61. atexit.register(Utils.cleanup, [sfile_path])
  62. return self._replace(sfile_path, force=force)
  63. def prep_secret(self, files=None, contents=None):
  64. ''' return what the secret would look like if created
  65. This is accomplished by passing -ojson. This will most likely change in the future
  66. '''
  67. if not files:
  68. files = Utils.create_tmp_files_from_contents(contents)
  69. secrets = ["%s=%s" % (sfile['name'], sfile['path']) for sfile in files]
  70. cmd = ['-ojson', 'secrets', 'new', self.name]
  71. if self.type is not None:
  72. cmd.extend(["--type=%s" % (self.type)])
  73. cmd.extend(secrets)
  74. return self.openshift_cmd(cmd, output=True)
  75. @staticmethod
  76. # pylint: disable=too-many-return-statements,too-many-branches
  77. # TODO: This function should be refactored into its individual parts.
  78. def run_ansible(params, check_mode):
  79. '''run the ansible idempotent code'''
  80. ocsecret = OCSecret(params['namespace'],
  81. params['name'],
  82. params['type'],
  83. params['decode'],
  84. kubeconfig=params['kubeconfig'],
  85. verbose=params['debug'])
  86. state = params['state']
  87. api_rval = ocsecret.get()
  88. #####
  89. # Get
  90. #####
  91. if state == 'list':
  92. return {'changed': False, 'results': api_rval, state: 'list'}
  93. if not params['name']:
  94. return {'failed': True,
  95. 'msg': 'Please specify a name when state is absent|present.'}
  96. ########
  97. # Delete
  98. ########
  99. if state == 'absent':
  100. if not Utils.exists(api_rval['results'], params['name']):
  101. return {'changed': False, 'state': 'absent'}
  102. if check_mode:
  103. return {'changed': True, 'msg': 'Would have performed a delete.'}
  104. api_rval = ocsecret.delete()
  105. return {'changed': True, 'results': api_rval, 'state': 'absent'}
  106. if state == 'present':
  107. if params['files']:
  108. files = params['files']
  109. elif params['contents']:
  110. files = Utils.create_tmp_files_from_contents(params['contents'])
  111. else:
  112. return {'failed': True,
  113. 'msg': 'Either specify files or contents.'}
  114. ########
  115. # Create
  116. ########
  117. if not Utils.exists(api_rval['results'], params['name']):
  118. if check_mode:
  119. return {'changed': True,
  120. 'msg': 'Would have performed a create.'}
  121. api_rval = ocsecret.create(files, params['contents'])
  122. # Remove files
  123. if files and params['delete_after']:
  124. Utils.cleanup([ftmp['path'] for ftmp in files])
  125. if api_rval['returncode'] != 0:
  126. return {'failed': True,
  127. 'msg': api_rval}
  128. return {'changed': True,
  129. 'results': api_rval,
  130. 'state': 'present'}
  131. ########
  132. # Update
  133. ########
  134. secret = ocsecret.prep_secret(params['files'], params['contents'])
  135. if secret['returncode'] != 0:
  136. return {'failed': True, 'msg': secret}
  137. if Utils.check_def_equal(secret['results'], api_rval['results'][0]):
  138. # Remove files
  139. if files and params['delete_after']:
  140. Utils.cleanup([ftmp['path'] for ftmp in files])
  141. return {'changed': False,
  142. 'results': secret['results'],
  143. 'state': 'present'}
  144. if check_mode:
  145. return {'changed': True,
  146. 'msg': 'Would have performed an update.'}
  147. api_rval = ocsecret.update(files, force=params['force'])
  148. # Remove files
  149. if secret and params['delete_after']:
  150. Utils.cleanup([ftmp['path'] for ftmp in files])
  151. if api_rval['returncode'] != 0:
  152. return {'failed': True,
  153. 'msg': api_rval}
  154. return {'changed': True,
  155. 'results': api_rval,
  156. 'state': 'present'}
  157. return {'failed': True,
  158. 'changed': False,
  159. 'msg': 'Unknown state passed. %s' % state,
  160. 'state': 'unknown'}