oc_storageclass.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. # pylint: skip-file
  2. # flake8: noqa
  3. # pylint: disable=too-many-instance-attributes
  4. class OCStorageClass(OpenShiftCLI):
  5. ''' Class to wrap the oc command line tools '''
  6. kind = 'storageclass'
  7. # pylint allows 5
  8. # pylint: disable=too-many-arguments
  9. def __init__(self,
  10. config,
  11. verbose=False):
  12. ''' Constructor for OCStorageClass '''
  13. super(OCStorageClass, self).__init__(None, kubeconfig=config.kubeconfig, verbose=verbose)
  14. self.config = config
  15. self.storage_class = None
  16. def exists(self):
  17. ''' return whether a storageclass exists'''
  18. if self.storage_class:
  19. return True
  20. return False
  21. def get(self):
  22. '''return storageclass '''
  23. result = self._get(self.kind, self.config.name)
  24. if result['returncode'] == 0:
  25. self.storage_class = StorageClass(content=result['results'][0])
  26. elif '\"%s\" not found' % self.config.name in result['stderr']:
  27. result['returncode'] = 0
  28. result['results'] = [{}]
  29. return result
  30. def delete(self):
  31. '''delete the object'''
  32. return self._delete(self.kind, self.config.name)
  33. def create(self):
  34. '''create the object'''
  35. return self._create_from_content(self.config.name, self.config.data)
  36. def update(self):
  37. '''update the object'''
  38. # parameters are currently unable to be updated. need to delete and recreate
  39. self.delete()
  40. # pause here and attempt to wait for delete.
  41. # Better option would be to poll
  42. import time
  43. time.sleep(5)
  44. return self.create()
  45. def needs_update(self):
  46. ''' verify an update is needed '''
  47. # check if params have updated
  48. if self.storage_class.get_parameters() != self.config.parameters:
  49. return True
  50. for anno_key, anno_value in self.storage_class.get_annotations().items():
  51. if 'is-default-class' in anno_key and anno_value != self.config.default_storage_class:
  52. return True
  53. return False
  54. @staticmethod
  55. def provisioner_name_qualified(provisioner_name):
  56. pattern = re.compile(r'^[a-z0-9A-Z-_.]+\/[a-z0-9A-Z-_.]+$')
  57. return pattern.match(provisioner_name)
  58. @staticmethod
  59. # pylint: disable=too-many-return-statements,too-many-branches
  60. # TODO: This function should be refactored into its individual parts.
  61. def run_ansible(params, check_mode):
  62. '''run the ansible idempotent code'''
  63. # Make sure that the provisioner is fully qualified before using it
  64. # E.g. if 'aws-efs' is provided as a provisioner, convert it to 'kubernetes.io/aws-efs'
  65. # but if the name is already qualified (e.g. 'openshift.org/aws-efs') then leave it be.
  66. raw_provisioner_name = params['provisioner']
  67. if OCStorageClass.provisioner_name_qualified(raw_provisioner_name):
  68. qualified_provisioner_name = raw_provisioner_name
  69. else:
  70. qualified_provisioner_name = "kubernetes.io/{}".format(params['provisioner'])
  71. rconfig = StorageClassConfig(params['name'],
  72. provisioner=qualified_provisioner_name,
  73. parameters=params['parameters'],
  74. annotations=params['annotations'],
  75. api_version="storage.k8s.io/{}".format(params['api_version']),
  76. default_storage_class=params.get('default_storage_class', 'false'),
  77. kubeconfig=params['kubeconfig'],
  78. )
  79. oc_sc = OCStorageClass(rconfig, verbose=params['debug'])
  80. state = params['state']
  81. api_rval = oc_sc.get()
  82. #####
  83. # Get
  84. #####
  85. if state == 'list':
  86. return {'changed': False, 'results': api_rval['results'], 'state': 'list'}
  87. ########
  88. # Delete
  89. ########
  90. if state == 'absent':
  91. if oc_sc.exists():
  92. if check_mode:
  93. return {'changed': True, 'msg': 'Would have performed a delete.'}
  94. api_rval = oc_sc.delete()
  95. return {'changed': True, 'results': api_rval, 'state': 'absent'}
  96. return {'changed': False, 'state': 'absent'}
  97. if state == 'present':
  98. ########
  99. # Create
  100. ########
  101. if not oc_sc.exists():
  102. if check_mode:
  103. return {'changed': True, 'msg': 'Would have performed a create.'}
  104. # Create it here
  105. api_rval = oc_sc.create()
  106. if api_rval['returncode'] != 0:
  107. return {'failed': True, 'msg': api_rval}
  108. # return the created object
  109. api_rval = oc_sc.get()
  110. if api_rval['returncode'] != 0:
  111. return {'failed': True, 'msg': api_rval}
  112. return {'changed': True, 'results': api_rval, 'state': 'present'}
  113. ########
  114. # Update
  115. ########
  116. if oc_sc.needs_update():
  117. api_rval = oc_sc.update()
  118. if api_rval['returncode'] != 0:
  119. return {'failed': True, 'msg': api_rval}
  120. # return the created object
  121. api_rval = oc_sc.get()
  122. if api_rval['returncode'] != 0:
  123. return {'failed': True, 'msg': api_rval}
  124. return {'changed': True, 'results': api_rval, 'state': 'present'}
  125. return {'changed': False, 'results': api_rval, 'state': 'present'}
  126. return {'failed': True,
  127. 'changed': False,
  128. 'msg': 'Unknown state passed. %s' % state,
  129. 'state': 'unknown'}