deploymentconfig.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. # pylint: skip-file
  2. # flake8: noqa
  3. # pylint: disable=too-many-public-methods
  4. class DeploymentConfig(Yedit):
  5. ''' Class to model an openshift DeploymentConfig'''
  6. default_deployment_config = '''
  7. apiVersion: v1
  8. kind: DeploymentConfig
  9. metadata:
  10. name: default_dc
  11. namespace: default
  12. spec:
  13. replicas: 0
  14. selector:
  15. default_dc: default_dc
  16. strategy:
  17. resources: {}
  18. rollingParams:
  19. intervalSeconds: 1
  20. maxSurge: 0
  21. maxUnavailable: 25%
  22. timeoutSeconds: 600
  23. updatePercent: -25
  24. updatePeriodSeconds: 1
  25. type: Rolling
  26. template:
  27. metadata:
  28. spec:
  29. containers:
  30. - env:
  31. - name: default
  32. value: default
  33. image: default
  34. imagePullPolicy: IfNotPresent
  35. name: default_dc
  36. ports:
  37. - containerPort: 8000
  38. hostPort: 8000
  39. protocol: TCP
  40. name: default_port
  41. resources: {}
  42. terminationMessagePath: /dev/termination-log
  43. dnsPolicy: ClusterFirst
  44. hostNetwork: true
  45. nodeSelector:
  46. type: compute
  47. restartPolicy: Always
  48. securityContext: {}
  49. serviceAccount: default
  50. serviceAccountName: default
  51. terminationGracePeriodSeconds: 30
  52. triggers:
  53. - type: ConfigChange
  54. '''
  55. replicas_path = "spec.replicas"
  56. env_path = "spec.template.spec.containers[0].env"
  57. volumes_path = "spec.template.spec.volumes"
  58. container_path = "spec.template.spec.containers"
  59. volume_mounts_path = "spec.template.spec.containers[0].volumeMounts"
  60. def __init__(self, content=None):
  61. ''' Constructor for deploymentconfig '''
  62. if not content:
  63. content = DeploymentConfig.default_deployment_config
  64. super(DeploymentConfig, self).__init__(content=content)
  65. # pylint: disable=no-member
  66. def add_env_value(self, key, value):
  67. ''' add key, value pair to env array '''
  68. rval = False
  69. env = self.get_env_vars()
  70. if env:
  71. env.append({'name': key, 'value': value})
  72. rval = True
  73. else:
  74. result = self.put(DeploymentConfig.env_path, {'name': key, 'value': value})
  75. rval = result[0]
  76. return rval
  77. def exists_env_value(self, key, value):
  78. ''' return whether a key, value pair exists '''
  79. results = self.get_env_vars()
  80. if not results:
  81. return False
  82. for result in results:
  83. if result['name'] == key and result['value'] == value:
  84. return True
  85. return False
  86. def exists_env_key(self, key):
  87. ''' return whether a key, value pair exists '''
  88. results = self.get_env_vars()
  89. if not results:
  90. return False
  91. for result in results:
  92. if result['name'] == key:
  93. return True
  94. return False
  95. def get_env_vars(self):
  96. '''return a environment variables '''
  97. return self.get(DeploymentConfig.env_path) or []
  98. def delete_env_var(self, keys):
  99. '''delete a list of keys '''
  100. if not isinstance(keys, list):
  101. keys = [keys]
  102. env_vars_array = self.get_env_vars()
  103. modified = False
  104. idx = None
  105. for key in keys:
  106. for env_idx, env_var in enumerate(env_vars_array):
  107. if env_var['name'] == key:
  108. idx = env_idx
  109. break
  110. if idx:
  111. modified = True
  112. del env_vars_array[idx]
  113. if modified:
  114. return True
  115. return False
  116. def update_env_var(self, key, value):
  117. '''place an env in the env var list'''
  118. env_vars_array = self.get_env_vars()
  119. idx = None
  120. for env_idx, env_var in enumerate(env_vars_array):
  121. if env_var['name'] == key:
  122. idx = env_idx
  123. break
  124. if idx:
  125. env_vars_array[idx]['value'] = value
  126. else:
  127. self.add_env_value(key, value)
  128. return True
  129. def exists_volume_mount(self, volume_mount):
  130. ''' return whether a volume mount exists '''
  131. exist_volume_mounts = self.get_volume_mounts()
  132. if not exist_volume_mounts:
  133. return False
  134. volume_mount_found = False
  135. for exist_volume_mount in exist_volume_mounts:
  136. if exist_volume_mount['name'] == volume_mount['name']:
  137. volume_mount_found = True
  138. break
  139. return volume_mount_found
  140. def exists_volume(self, volume):
  141. ''' return whether a volume exists '''
  142. exist_volumes = self.get_volumes()
  143. volume_found = False
  144. for exist_volume in exist_volumes:
  145. if exist_volume['name'] == volume['name']:
  146. volume_found = True
  147. break
  148. return volume_found
  149. def find_volume_by_name(self, volume, mounts=False):
  150. ''' return the index of a volume '''
  151. volumes = []
  152. if mounts:
  153. volumes = self.get_volume_mounts()
  154. else:
  155. volumes = self.get_volumes()
  156. for exist_volume in volumes:
  157. if exist_volume['name'] == volume['name']:
  158. return exist_volume
  159. return None
  160. def get_replicas(self):
  161. ''' return replicas setting '''
  162. return self.get(DeploymentConfig.replicas_path)
  163. def get_volume_mounts(self):
  164. '''return volume mount information '''
  165. return self.get_volumes(mounts=True)
  166. def get_volumes(self, mounts=False):
  167. '''return volume mount information '''
  168. if mounts:
  169. return self.get(DeploymentConfig.volume_mounts_path) or []
  170. return self.get(DeploymentConfig.volumes_path) or []
  171. def delete_volume_by_name(self, volume):
  172. '''delete a volume '''
  173. modified = False
  174. exist_volume_mounts = self.get_volume_mounts()
  175. exist_volumes = self.get_volumes()
  176. del_idx = None
  177. for idx, exist_volume in enumerate(exist_volumes):
  178. if 'name' in exist_volume and exist_volume['name'] == volume['name']:
  179. del_idx = idx
  180. break
  181. if del_idx != None:
  182. del exist_volumes[del_idx]
  183. modified = True
  184. del_idx = None
  185. for idx, exist_volume_mount in enumerate(exist_volume_mounts):
  186. if 'name' in exist_volume_mount and exist_volume_mount['name'] == volume['name']:
  187. del_idx = idx
  188. break
  189. if del_idx != None:
  190. del exist_volume_mounts[idx]
  191. modified = True
  192. return modified
  193. def add_volume_mount(self, volume_mount):
  194. ''' add a volume or volume mount to the proper location '''
  195. exist_volume_mounts = self.get_volume_mounts()
  196. if not exist_volume_mounts and volume_mount:
  197. self.put(DeploymentConfig.volume_mounts_path, [volume_mount])
  198. else:
  199. exist_volume_mounts.append(volume_mount)
  200. def add_volume(self, volume):
  201. ''' add a volume or volume mount to the proper location '''
  202. exist_volumes = self.get_volumes()
  203. if not volume:
  204. return
  205. if not exist_volumes:
  206. self.put(DeploymentConfig.volumes_path, [volume])
  207. else:
  208. exist_volumes.append(volume)
  209. def update_replicas(self, replicas):
  210. ''' update replicas value '''
  211. self.put(DeploymentConfig.replicas_path, replicas)
  212. def update_volume(self, volume):
  213. '''place an env in the env var list'''
  214. exist_volumes = self.get_volumes()
  215. if not volume:
  216. return False
  217. # update the volume
  218. update_idx = None
  219. for idx, exist_vol in enumerate(exist_volumes):
  220. if exist_vol['name'] == volume['name']:
  221. update_idx = idx
  222. break
  223. if update_idx != None:
  224. exist_volumes[update_idx] = volume
  225. else:
  226. self.add_volume(volume)
  227. return True
  228. def update_volume_mount(self, volume_mount):
  229. '''place an env in the env var list'''
  230. modified = False
  231. exist_volume_mounts = self.get_volume_mounts()
  232. if not volume_mount:
  233. return False
  234. # update the volume mount
  235. for exist_vol_mount in exist_volume_mounts:
  236. if exist_vol_mount['name'] == volume_mount['name']:
  237. if 'mountPath' in exist_vol_mount and \
  238. str(exist_vol_mount['mountPath']) != str(volume_mount['mountPath']):
  239. exist_vol_mount['mountPath'] = volume_mount['mountPath']
  240. modified = True
  241. break
  242. if not modified:
  243. self.add_volume_mount(volume_mount)
  244. modified = True
  245. return modified
  246. def needs_update_volume(self, volume, volume_mount):
  247. ''' verify a volume update is needed '''
  248. exist_volume = self.find_volume_by_name(volume)
  249. exist_volume_mount = self.find_volume_by_name(volume, mounts=True)
  250. results = []
  251. results.append(exist_volume['name'] == volume['name'])
  252. if 'secret' in volume:
  253. results.append('secret' in exist_volume)
  254. results.append(exist_volume['secret']['secretName'] == volume['secret']['secretName'])
  255. results.append(exist_volume_mount['name'] == volume_mount['name'])
  256. results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath'])
  257. elif 'emptyDir' in volume:
  258. results.append(exist_volume_mount['name'] == volume['name'])
  259. results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath'])
  260. elif 'persistentVolumeClaim' in volume:
  261. pvc = 'persistentVolumeClaim'
  262. results.append(pvc in exist_volume)
  263. if results[-1]:
  264. results.append(exist_volume[pvc]['claimName'] == volume[pvc]['claimName'])
  265. if 'claimSize' in volume[pvc]:
  266. results.append(exist_volume[pvc]['claimSize'] == volume[pvc]['claimSize'])
  267. elif 'hostpath' in volume:
  268. results.append('hostPath' in exist_volume)
  269. results.append(exist_volume['hostPath']['path'] == volume_mount['mountPath'])
  270. return not all(results)
  271. def needs_update_replicas(self, replicas):
  272. ''' verify whether a replica update is needed '''
  273. current_reps = self.get(DeploymentConfig.replicas_path)
  274. return not current_reps == replicas