deploymentconfig.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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. def add_env_value(self, key, value):
  66. ''' add key, value pair to env array '''
  67. rval = False
  68. env = self.get_env_vars()
  69. if env:
  70. env.append({'name': key, 'value': value})
  71. rval = True
  72. else:
  73. result = self.put(DeploymentConfig.env_path, {'name': key, 'value': value})
  74. rval = result[0]
  75. return rval
  76. def exists_env_value(self, key, value):
  77. ''' return whether a key, value pair exists '''
  78. results = self.get_env_vars()
  79. if not results:
  80. return False
  81. for result in results:
  82. if result['name'] == key:
  83. if 'value' not in result:
  84. if value == "" or value is None:
  85. return True
  86. elif result['value'] == value:
  87. return True
  88. return False
  89. def exists_env_key(self, key):
  90. ''' return whether a key, value pair exists '''
  91. results = self.get_env_vars()
  92. if not results:
  93. return False
  94. for result in results:
  95. if result['name'] == key:
  96. return True
  97. return False
  98. def get_env_var(self, key):
  99. '''return a environment variables '''
  100. results = self.get(DeploymentConfig.env_path) or []
  101. if not results:
  102. return None
  103. for env_var in results:
  104. if env_var['name'] == key:
  105. return env_var
  106. return None
  107. def get_env_vars(self):
  108. '''return a environment variables '''
  109. return self.get(DeploymentConfig.env_path) or []
  110. def delete_env_var(self, keys):
  111. '''delete a list of keys '''
  112. if not isinstance(keys, list):
  113. keys = [keys]
  114. env_vars_array = self.get_env_vars()
  115. modified = False
  116. idx = None
  117. for key in keys:
  118. for env_idx, env_var in enumerate(env_vars_array):
  119. if env_var['name'] == key:
  120. idx = env_idx
  121. break
  122. if idx:
  123. modified = True
  124. del env_vars_array[idx]
  125. if modified:
  126. return True
  127. return False
  128. def update_env_var(self, key, value):
  129. '''place an env in the env var list'''
  130. env_vars_array = self.get_env_vars()
  131. idx = None
  132. for env_idx, env_var in enumerate(env_vars_array):
  133. if env_var['name'] == key:
  134. idx = env_idx
  135. break
  136. if idx:
  137. env_vars_array[idx]['value'] = value
  138. else:
  139. self.add_env_value(key, value)
  140. return True
  141. def exists_volume_mount(self, volume_mount):
  142. ''' return whether a volume mount exists '''
  143. exist_volume_mounts = self.get_volume_mounts()
  144. if not exist_volume_mounts:
  145. return False
  146. volume_mount_found = False
  147. for exist_volume_mount in exist_volume_mounts:
  148. if exist_volume_mount['name'] == volume_mount['name']:
  149. volume_mount_found = True
  150. break
  151. return volume_mount_found
  152. def exists_volume(self, volume):
  153. ''' return whether a volume exists '''
  154. exist_volumes = self.get_volumes()
  155. volume_found = False
  156. for exist_volume in exist_volumes:
  157. if exist_volume['name'] == volume['name']:
  158. volume_found = True
  159. break
  160. return volume_found
  161. def find_volume_by_name(self, volume, mounts=False):
  162. ''' return the index of a volume '''
  163. volumes = []
  164. if mounts:
  165. volumes = self.get_volume_mounts()
  166. else:
  167. volumes = self.get_volumes()
  168. for exist_volume in volumes:
  169. if exist_volume['name'] == volume['name']:
  170. return exist_volume
  171. return None
  172. def get_replicas(self):
  173. ''' return replicas setting '''
  174. return self.get(DeploymentConfig.replicas_path)
  175. def get_volume_mounts(self):
  176. '''return volume mount information '''
  177. return self.get_volumes(mounts=True)
  178. def get_volumes(self, mounts=False):
  179. '''return volume mount information '''
  180. if mounts:
  181. return self.get(DeploymentConfig.volume_mounts_path) or []
  182. return self.get(DeploymentConfig.volumes_path) or []
  183. def delete_volume_by_name(self, volume):
  184. '''delete a volume '''
  185. modified = False
  186. exist_volume_mounts = self.get_volume_mounts()
  187. exist_volumes = self.get_volumes()
  188. del_idx = None
  189. for idx, exist_volume in enumerate(exist_volumes):
  190. if 'name' in exist_volume and exist_volume['name'] == volume['name']:
  191. del_idx = idx
  192. break
  193. if del_idx != None:
  194. del exist_volumes[del_idx]
  195. modified = True
  196. del_idx = None
  197. for idx, exist_volume_mount in enumerate(exist_volume_mounts):
  198. if 'name' in exist_volume_mount and exist_volume_mount['name'] == volume['name']:
  199. del_idx = idx
  200. break
  201. if del_idx != None:
  202. del exist_volume_mounts[idx]
  203. modified = True
  204. return modified
  205. def add_volume_mount(self, volume_mount):
  206. ''' add a volume or volume mount to the proper location '''
  207. exist_volume_mounts = self.get_volume_mounts()
  208. if not exist_volume_mounts and volume_mount:
  209. self.put(DeploymentConfig.volume_mounts_path, [volume_mount])
  210. else:
  211. exist_volume_mounts.append(volume_mount)
  212. def add_volume(self, volume):
  213. ''' add a volume or volume mount to the proper location '''
  214. exist_volumes = self.get_volumes()
  215. if not volume:
  216. return
  217. if not exist_volumes:
  218. self.put(DeploymentConfig.volumes_path, [volume])
  219. else:
  220. exist_volumes.append(volume)
  221. def update_replicas(self, replicas):
  222. ''' update replicas value '''
  223. self.put(DeploymentConfig.replicas_path, replicas)
  224. def update_volume(self, volume):
  225. '''place an env in the env var list'''
  226. exist_volumes = self.get_volumes()
  227. if not volume:
  228. return False
  229. # update the volume
  230. update_idx = None
  231. for idx, exist_vol in enumerate(exist_volumes):
  232. if exist_vol['name'] == volume['name']:
  233. update_idx = idx
  234. break
  235. if update_idx != None:
  236. exist_volumes[update_idx] = volume
  237. else:
  238. self.add_volume(volume)
  239. return True
  240. def update_volume_mount(self, volume_mount):
  241. '''place an env in the env var list'''
  242. modified = False
  243. exist_volume_mounts = self.get_volume_mounts()
  244. if not volume_mount:
  245. return False
  246. # update the volume mount
  247. for exist_vol_mount in exist_volume_mounts:
  248. if exist_vol_mount['name'] == volume_mount['name']:
  249. if 'mountPath' in exist_vol_mount and \
  250. str(exist_vol_mount['mountPath']) != str(volume_mount['mountPath']):
  251. exist_vol_mount['mountPath'] = volume_mount['mountPath']
  252. modified = True
  253. break
  254. if not modified:
  255. self.add_volume_mount(volume_mount)
  256. modified = True
  257. return modified
  258. def needs_update_volume(self, volume, volume_mount):
  259. ''' verify a volume update is needed '''
  260. exist_volume = self.find_volume_by_name(volume)
  261. exist_volume_mount = self.find_volume_by_name(volume, mounts=True)
  262. results = []
  263. results.append(exist_volume['name'] == volume['name'])
  264. if 'secret' in volume:
  265. results.append('secret' in exist_volume)
  266. results.append(exist_volume['secret']['secretName'] == volume['secret']['secretName'])
  267. results.append(exist_volume_mount['name'] == volume_mount['name'])
  268. results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath'])
  269. elif 'emptyDir' in volume:
  270. results.append(exist_volume_mount['name'] == volume['name'])
  271. results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath'])
  272. elif 'persistentVolumeClaim' in volume:
  273. pvc = 'persistentVolumeClaim'
  274. results.append(pvc in exist_volume)
  275. if results[-1]:
  276. results.append(exist_volume[pvc]['claimName'] == volume[pvc]['claimName'])
  277. if 'claimSize' in volume[pvc]:
  278. results.append(exist_volume[pvc]['claimSize'] == volume[pvc]['claimSize'])
  279. elif 'hostpath' in volume:
  280. results.append('hostPath' in exist_volume)
  281. results.append(exist_volume['hostPath']['path'] == volume_mount['mountPath'])
  282. return not all(results)
  283. def needs_update_replicas(self, replicas):
  284. ''' verify whether a replica update is needed '''
  285. current_reps = self.get(DeploymentConfig.replicas_path)
  286. return not current_reps == replicas