oc_secret.py 6.6 KB

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