openshift-python-wrapper 4.11.61__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. ocp_resources/__init__.py +0 -0
  2. ocp_resources/api_service.py +9 -0
  3. ocp_resources/backup.py +52 -0
  4. ocp_resources/benchmark.py +92 -0
  5. ocp_resources/catalog_source.py +63 -0
  6. ocp_resources/catalog_source_config.py +86 -0
  7. ocp_resources/cdi.py +13 -0
  8. ocp_resources/cdi_config.py +52 -0
  9. ocp_resources/chaos_engine.py +30 -0
  10. ocp_resources/chaos_result.py +11 -0
  11. ocp_resources/cluster_operator.py +5 -0
  12. ocp_resources/cluster_role.py +70 -0
  13. ocp_resources/cluster_role_binding.py +36 -0
  14. ocp_resources/cluster_service_version.py +8 -0
  15. ocp_resources/cluster_version.py +5 -0
  16. ocp_resources/configmap.py +37 -0
  17. ocp_resources/console_cli_download.py +9 -0
  18. ocp_resources/console_plugin.py +9 -0
  19. ocp_resources/console_quick_start.py +9 -0
  20. ocp_resources/constants.py +26 -0
  21. ocp_resources/csidriver.py +9 -0
  22. ocp_resources/custom_resource_definition.py +5 -0
  23. ocp_resources/daemonset.py +61 -0
  24. ocp_resources/data_import_cron.py +100 -0
  25. ocp_resources/data_source.py +59 -0
  26. ocp_resources/datavolume.py +275 -0
  27. ocp_resources/deployment.py +65 -0
  28. ocp_resources/destination_rule.py +11 -0
  29. ocp_resources/event.py +114 -0
  30. ocp_resources/forklift_controller.py +10 -0
  31. ocp_resources/gateway.py +11 -0
  32. ocp_resources/hook.py +52 -0
  33. ocp_resources/host.py +64 -0
  34. ocp_resources/hostpath_provisioner.py +50 -0
  35. ocp_resources/hyperconverged.py +43 -0
  36. ocp_resources/image.py +9 -0
  37. ocp_resources/image_content_source_policy.py +9 -0
  38. ocp_resources/image_stream.py +48 -0
  39. ocp_resources/imagestreamtag.py +9 -0
  40. ocp_resources/infrastructure.py +18 -0
  41. ocp_resources/installplan.py +8 -0
  42. ocp_resources/job.py +65 -0
  43. ocp_resources/kube_descheduler.py +65 -0
  44. ocp_resources/kubevirt.py +5 -0
  45. ocp_resources/kubevirt_common_templates_bundle.py +5 -0
  46. ocp_resources/kubevirt_metrics_aggregation.py +5 -0
  47. ocp_resources/kubevirt_node_labeller_bundle.py +5 -0
  48. ocp_resources/kubevirt_template_validaotr.py +5 -0
  49. ocp_resources/logger.py +76 -0
  50. ocp_resources/machine.py +50 -0
  51. ocp_resources/machine_config.py +5 -0
  52. ocp_resources/machine_config_pool.py +9 -0
  53. ocp_resources/machine_health_check.py +76 -0
  54. ocp_resources/machine_set.py +189 -0
  55. ocp_resources/migration.py +63 -0
  56. ocp_resources/migration_policy.py +66 -0
  57. ocp_resources/mtv.py +171 -0
  58. ocp_resources/mutating_webhook_config.py +9 -0
  59. ocp_resources/namespace.py +40 -0
  60. ocp_resources/network.py +5 -0
  61. ocp_resources/network_addons_config.py +9 -0
  62. ocp_resources/network_attachment_definition.py +24 -0
  63. ocp_resources/network_map.py +64 -0
  64. ocp_resources/network_policy.py +9 -0
  65. ocp_resources/nmstate.py +9 -0
  66. ocp_resources/node.py +41 -0
  67. ocp_resources/node_health_check.py +10 -0
  68. ocp_resources/node_maintenance.py +40 -0
  69. ocp_resources/node_network_configuration_enactment.py +20 -0
  70. ocp_resources/node_network_configuration_policy.py +472 -0
  71. ocp_resources/node_network_state.py +121 -0
  72. ocp_resources/oauth.py +9 -0
  73. ocp_resources/operator_condition.py +5 -0
  74. ocp_resources/operator_group.py +37 -0
  75. ocp_resources/operator_hub.py +5 -0
  76. ocp_resources/operator_source.py +50 -0
  77. ocp_resources/package_manifest.py +5 -0
  78. ocp_resources/peer_authentication.py +18 -0
  79. ocp_resources/persistent_volume.py +27 -0
  80. ocp_resources/persistent_volume_claim.py +103 -0
  81. ocp_resources/plan.py +143 -0
  82. ocp_resources/pod.py +175 -0
  83. ocp_resources/pod_disruption_budget.py +53 -0
  84. ocp_resources/priority_class.py +48 -0
  85. ocp_resources/project.py +60 -0
  86. ocp_resources/prometheus.py +9 -0
  87. ocp_resources/prometheus_rule.py +9 -0
  88. ocp_resources/provider.py +59 -0
  89. ocp_resources/replicaset.py +11 -0
  90. ocp_resources/resource.py +1383 -0
  91. ocp_resources/restore.py +52 -0
  92. ocp_resources/role.py +11 -0
  93. ocp_resources/role_binding.py +67 -0
  94. ocp_resources/route.py +76 -0
  95. ocp_resources/secret.py +75 -0
  96. ocp_resources/security_context_constraints.py +9 -0
  97. ocp_resources/service.py +16 -0
  98. ocp_resources/service_account.py +9 -0
  99. ocp_resources/service_mesh_control_plane.py +11 -0
  100. ocp_resources/service_mesh_member_roll.py +14 -0
  101. ocp_resources/service_monitor.py +9 -0
  102. ocp_resources/sriov_network.py +54 -0
  103. ocp_resources/sriov_network_node_policy.py +67 -0
  104. ocp_resources/sriov_network_node_state.py +44 -0
  105. ocp_resources/ssp.py +9 -0
  106. ocp_resources/storage_class.py +47 -0
  107. ocp_resources/storage_map.py +67 -0
  108. ocp_resources/storage_profile.py +7 -0
  109. ocp_resources/subscription.py +66 -0
  110. ocp_resources/tekton_tasks.py +9 -0
  111. ocp_resources/template.py +74 -0
  112. ocp_resources/upload_token_request.py +39 -0
  113. ocp_resources/utils.py +278 -0
  114. ocp_resources/validating_webhook_config.py +9 -0
  115. ocp_resources/virtual_machine.py +177 -0
  116. ocp_resources/virtual_machine_Instance_replica_set.py +9 -0
  117. ocp_resources/virtual_machine_cluster_flavor.py +5 -0
  118. ocp_resources/virtual_machine_flavor.py +5 -0
  119. ocp_resources/virtual_machine_import.py +307 -0
  120. ocp_resources/virtual_machine_instance.py +322 -0
  121. ocp_resources/virtual_machine_instance_migration.py +36 -0
  122. ocp_resources/virtual_machine_instance_preset.py +9 -0
  123. ocp_resources/virtual_machine_restore.py +99 -0
  124. ocp_resources/virtual_machine_snapshot.py +96 -0
  125. ocp_resources/virtual_service.py +11 -0
  126. ocp_resources/vm_import_config.py +9 -0
  127. ocp_resources/volume_snapshot.py +9 -0
  128. ocp_resources/volume_snapshot_class.py +9 -0
  129. openshift_python_wrapper-4.11.61.dist-info/LICENSE +201 -0
  130. openshift_python_wrapper-4.11.61.dist-info/METADATA +188 -0
  131. openshift_python_wrapper-4.11.61.dist-info/RECORD +132 -0
  132. openshift_python_wrapper-4.11.61.dist-info/WHEEL +4 -0
@@ -0,0 +1,61 @@
1
+ import kubernetes
2
+
3
+ from ocp_resources.constants import PROTOCOL_ERROR_EXCEPTION_DICT, TIMEOUT_4MINUTES
4
+ from ocp_resources.resource import NamespacedResource
5
+ from ocp_resources.utils import TimeoutSampler
6
+
7
+
8
+ class DaemonSet(NamespacedResource):
9
+ """
10
+ DaemonSet object.
11
+ """
12
+
13
+ api_group = NamespacedResource.ApiGroup.APPS
14
+
15
+ def wait_until_deployed(self, timeout=TIMEOUT_4MINUTES):
16
+ """
17
+ Wait until all Pods are deployed and ready.
18
+
19
+ Args:
20
+ timeout (int): Time to wait for the Daemonset.
21
+
22
+ Raises:
23
+ TimeoutExpiredError: If not all the pods are deployed.
24
+ """
25
+ self.logger.info(f"Wait for {self.kind} {self.name} to deploy all desired pods")
26
+ samples = TimeoutSampler(
27
+ wait_timeout=timeout,
28
+ sleep=1,
29
+ exceptions_dict=PROTOCOL_ERROR_EXCEPTION_DICT,
30
+ func=self.api.get,
31
+ field_selector=f"metadata.name=={self.name}",
32
+ namespace=self.namespace,
33
+ )
34
+ for sample in samples:
35
+ if sample.items:
36
+ status = sample.items[0].status
37
+ desired_number_scheduled = status.desiredNumberScheduled
38
+ number_ready = status.numberReady
39
+ if (
40
+ desired_number_scheduled > 0
41
+ and desired_number_scheduled == number_ready
42
+ ):
43
+ return
44
+
45
+ def delete(self, wait=False, timeout=TIMEOUT_4MINUTES, body=None):
46
+ """
47
+ Delete Daemonset
48
+
49
+ Args:
50
+ wait (bool): True to wait for Daemonset to be deleted.
51
+ timeout (int): Time to wait for resource deletion
52
+ body (dict): Content to send for delete()
53
+
54
+ Returns:
55
+ bool: True if delete succeeded, False otherwise.
56
+ """
57
+ super().delete(
58
+ wait=wait,
59
+ timeout=timeout,
60
+ body=kubernetes.client.V1DeleteOptions(propagation_policy="Foreground"),
61
+ )
@@ -0,0 +1,100 @@
1
+ from ocp_resources.constants import TIMEOUT_4MINUTES
2
+ from ocp_resources.resource import NamespacedResource
3
+
4
+
5
+ class DataImportCron(NamespacedResource):
6
+ """
7
+ DataImportCron object.
8
+ """
9
+
10
+ api_group = NamespacedResource.ApiGroup.CDI_KUBEVIRT_IO
11
+
12
+ def __init__(
13
+ self,
14
+ name=None,
15
+ namespace=None,
16
+ client=None,
17
+ image_stream=None,
18
+ url=None,
19
+ cert_configmap=None,
20
+ pull_method=None,
21
+ storage_class=None,
22
+ size=None,
23
+ schedule=None,
24
+ garbage_collect=None,
25
+ managed_data_source=None,
26
+ imports_to_keep=None,
27
+ bind_immediate_annotation=None,
28
+ teardown=True,
29
+ privileged_client=None,
30
+ yaml_file=None,
31
+ delete_timeout=TIMEOUT_4MINUTES,
32
+ **kwargs,
33
+ ):
34
+ super().__init__(
35
+ name=name,
36
+ namespace=namespace,
37
+ client=client,
38
+ teardown=teardown,
39
+ privileged_client=privileged_client,
40
+ yaml_file=yaml_file,
41
+ delete_timeout=delete_timeout,
42
+ **kwargs,
43
+ )
44
+ self.image_stream = image_stream
45
+ self.url = url
46
+ self.cert_configmap = cert_configmap
47
+ self.pull_method = pull_method
48
+ self.storage_class = storage_class
49
+ self.size = size
50
+ self.schedule = schedule
51
+ self.garbage_collect = garbage_collect
52
+ self.managed_data_source = managed_data_source
53
+ self.imports_to_keep = imports_to_keep
54
+ self.bind_immediate_annotation = bind_immediate_annotation
55
+
56
+ def to_dict(self):
57
+ super().to_dict()
58
+ if not self.yaml_file:
59
+ if self.image_stream and self.url:
60
+ raise ValueError("imageStream and url can not coexist")
61
+
62
+ self.res.update(
63
+ {
64
+ "spec": {
65
+ "template": {
66
+ "spec": {
67
+ "source": {
68
+ "registry": {"pullMethod": self.pull_method}
69
+ },
70
+ "storage": {
71
+ "resources": {"requests": {"storage": self.size}}
72
+ },
73
+ }
74
+ }
75
+ }
76
+ }
77
+ )
78
+ spec = self.res["spec"]["template"]["spec"]
79
+ if self.bind_immediate_annotation:
80
+ self.res["metadata"].setdefault("annotations", {}).update(
81
+ {
82
+ f"{NamespacedResource.ApiGroup.CDI_KUBEVIRT_IO}/storage.bind.immediate.requested": "true"
83
+ }
84
+ )
85
+ if self.image_stream:
86
+ spec["source"]["registry"]["imageStream"] = self.image_stream
87
+ if self.url:
88
+ spec["source"]["registry"]["url"] = self.url
89
+ if self.cert_configmap:
90
+ spec["source"]["registry"]["certConfigMap"] = self.cert_configmap
91
+ if self.storage_class:
92
+ spec["storage"]["storageClassName"] = self.storage_class
93
+ if self.schedule:
94
+ self.res["spec"]["schedule"] = self.schedule
95
+ if self.garbage_collect:
96
+ self.res["spec"]["garbageCollect"] = self.garbage_collect
97
+ if self.managed_data_source:
98
+ self.res["spec"]["managedDataSource"] = self.managed_data_source
99
+ if self.imports_to_keep:
100
+ self.res["spec"]["importsToKeep"] = self.imports_to_keep
@@ -0,0 +1,59 @@
1
+ from openshift.dynamic.exceptions import ResourceNotFoundError
2
+
3
+ from ocp_resources.constants import TIMEOUT_4MINUTES
4
+ from ocp_resources.persistent_volume_claim import PersistentVolumeClaim
5
+ from ocp_resources.resource import NamespacedResource
6
+
7
+
8
+ class DataSource(NamespacedResource):
9
+ api_group = NamespacedResource.ApiGroup.CDI_KUBEVIRT_IO
10
+
11
+ def __init__(
12
+ self,
13
+ name=None,
14
+ namespace=None,
15
+ client=None,
16
+ source=None,
17
+ teardown=True,
18
+ yaml_file=None,
19
+ delete_timeout=TIMEOUT_4MINUTES,
20
+ **kwargs,
21
+ ):
22
+ super().__init__(
23
+ name=name,
24
+ namespace=namespace,
25
+ client=client,
26
+ teardown=teardown,
27
+ yaml_file=yaml_file,
28
+ delete_timeout=delete_timeout,
29
+ **kwargs,
30
+ )
31
+ self.source = source
32
+
33
+ def to_dict(self):
34
+ super().to_dict()
35
+ if not self.yaml_file:
36
+ self.res.update(
37
+ {
38
+ "spec": {
39
+ "source": self.source,
40
+ },
41
+ }
42
+ )
43
+
44
+ @property
45
+ def pvc(self):
46
+ data_source_pvc = self.instance.spec.source.pvc
47
+ pvc_name = data_source_pvc.name
48
+ pvc_namespace = data_source_pvc.namespace
49
+ try:
50
+ return PersistentVolumeClaim(
51
+ client=self.client,
52
+ name=pvc_name,
53
+ namespace=pvc_namespace,
54
+ )
55
+ except ResourceNotFoundError:
56
+ self.logger.warning(
57
+ f"dataSource {self.name} is pointing to a non-existing PVC, name: {pvc_name}, "
58
+ f"namespace: {pvc_namespace}"
59
+ )
@@ -0,0 +1,275 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ocp_resources.constants import TIMEOUT_4MINUTES
4
+ from ocp_resources.persistent_volume_claim import PersistentVolumeClaim
5
+ from ocp_resources.resource import NamespacedResource, Resource
6
+ from ocp_resources.utils import TimeoutExpiredError, TimeoutSampler
7
+
8
+
9
+ class DataVolume(NamespacedResource):
10
+ """
11
+ DataVolume object.
12
+ """
13
+
14
+ api_group = NamespacedResource.ApiGroup.CDI_KUBEVIRT_IO
15
+
16
+ class Status(NamespacedResource.Status):
17
+ BLANK = "Blank"
18
+ PVC_BOUND = "PVCBound"
19
+ IMPORT_SCHEDULED = "ImportScheduled"
20
+ ClONE_SCHEDULED = "CloneScheduled"
21
+ UPLOAD_SCHEDULED = "UploadScheduled"
22
+ IMPORT_IN_PROGRESS = "ImportInProgress"
23
+ CLONE_IN_PROGRESS = "CloneInProgress"
24
+ UPLOAD_IN_PROGRESS = "UploadInProgress"
25
+ SNAPSHOT_FOR_SMART_CLONE_IN_PROGRESS = "SnapshotForSmartCloneInProgress"
26
+ SMART_CLONE_PVC_IN_PROGRESS = "SmartClonePVCInProgress"
27
+ UPLOAD_READY = "UploadReady"
28
+ UNKNOWN = "Unknown"
29
+ WAIT_FOR_FIRST_CONSUMER = "WaitForFirstConsumer"
30
+
31
+ class AccessMode:
32
+ """
33
+ AccessMode object.
34
+ """
35
+
36
+ RWO = "ReadWriteOnce"
37
+ ROX = "ReadOnlyMany"
38
+ RWX = "ReadWriteMany"
39
+
40
+ class ContentType:
41
+ """
42
+ ContentType object
43
+ """
44
+
45
+ KUBEVIRT = "kubevirt"
46
+ ARCHIVE = "archive"
47
+
48
+ class VolumeMode:
49
+ """
50
+ VolumeMode object
51
+ """
52
+
53
+ BLOCK = "Block"
54
+ FILE = "Filesystem"
55
+
56
+ class Condition:
57
+ class Type:
58
+ READY = "Ready"
59
+ BOUND = "Bound"
60
+ RUNNING = "Running"
61
+
62
+ class Status(Resource.Condition.Status):
63
+ UNKNOWN = "Unknown"
64
+
65
+ def __init__(
66
+ self,
67
+ name=None,
68
+ namespace=None,
69
+ source=None,
70
+ size=None,
71
+ storage_class=None,
72
+ url=None,
73
+ content_type=ContentType.KUBEVIRT,
74
+ access_modes=None,
75
+ cert_configmap=None,
76
+ secret=None,
77
+ client=None,
78
+ volume_mode=None,
79
+ hostpath_node=None,
80
+ source_pvc=None,
81
+ source_namespace=None,
82
+ multus_annotation=None,
83
+ bind_immediate_annotation=None,
84
+ preallocation=None,
85
+ teardown=True,
86
+ privileged_client=None,
87
+ yaml_file=None,
88
+ delete_timeout=TIMEOUT_4MINUTES,
89
+ api_name="pvc",
90
+ **kwargs,
91
+ ):
92
+ super().__init__(
93
+ name=name,
94
+ namespace=namespace,
95
+ client=client,
96
+ teardown=teardown,
97
+ privileged_client=privileged_client,
98
+ yaml_file=yaml_file,
99
+ delete_timeout=delete_timeout,
100
+ **kwargs,
101
+ )
102
+ self.source = source
103
+ self.url = url
104
+ self.cert_configmap = cert_configmap
105
+ self.secret = secret
106
+ self.content_type = content_type
107
+ self.size = size
108
+ self.access_modes = access_modes
109
+ self.storage_class = storage_class
110
+ self.volume_mode = volume_mode
111
+ self.hostpath_node = hostpath_node
112
+ self.source_pvc = source_pvc
113
+ self.source_namespace = source_namespace
114
+ self.multus_annotation = multus_annotation
115
+ self.bind_immediate_annotation = bind_immediate_annotation
116
+ self.preallocation = preallocation
117
+ self.api_name = api_name
118
+
119
+ def to_dict(self):
120
+ super().to_dict()
121
+ if not self.yaml_file:
122
+ self.res.update(
123
+ {
124
+ "spec": {
125
+ "source": {self.source: {"url": self.url}},
126
+ self.api_name: {
127
+ "resources": {"requests": {"storage": self.size}},
128
+ },
129
+ }
130
+ }
131
+ )
132
+ if self.access_modes:
133
+ self.res["spec"][self.api_name]["accessModes"] = [self.access_modes]
134
+ if self.content_type:
135
+ self.res["spec"]["contentType"] = self.content_type
136
+ if self.storage_class:
137
+ self.res["spec"][self.api_name]["storageClassName"] = self.storage_class
138
+ if self.secret:
139
+ self.res["spec"]["source"][self.source]["secretRef"] = self.secret.name
140
+ if self.volume_mode:
141
+ self.res["spec"][self.api_name]["volumeMode"] = self.volume_mode
142
+ if self.source == "http" or "registry":
143
+ self.res["spec"]["source"][self.source]["url"] = self.url
144
+ if self.cert_configmap:
145
+ self.res["spec"]["source"][self.source][
146
+ "certConfigMap"
147
+ ] = self.cert_configmap
148
+ if self.source == "upload" or self.source == "blank":
149
+ self.res["spec"]["source"][self.source] = {}
150
+ if self.hostpath_node:
151
+ self.res["metadata"].setdefault("annotations", {}).update(
152
+ {
153
+ f"{NamespacedResource.ApiGroup.KUBEVIRT_IO}/provisionOnNode": self.hostpath_node
154
+ }
155
+ )
156
+ if self.multus_annotation:
157
+ self.res["metadata"].setdefault("annotations", {}).update(
158
+ {
159
+ f"{NamespacedResource.ApiGroup.K8S_V1_CNI_CNCF_IO}/networks": self.multus_annotation
160
+ }
161
+ )
162
+ if self.bind_immediate_annotation:
163
+ self.res["metadata"].setdefault("annotations", {}).update(
164
+ {
165
+ f"{NamespacedResource.ApiGroup.CDI_KUBEVIRT_IO}/storage.bind.immediate.requested": "true"
166
+ }
167
+ )
168
+ if self.source == "pvc":
169
+ self.res["spec"]["source"]["pvc"] = {
170
+ "name": self.source_pvc or "dv-source",
171
+ "namespace": self.source_namespace or self.namespace,
172
+ }
173
+ if self.preallocation is not None:
174
+ self.res["spec"]["preallocation"] = self.preallocation
175
+
176
+ def wait_deleted(self, timeout=TIMEOUT_4MINUTES):
177
+ """
178
+ Wait until DataVolume and the PVC created by it are deleted
179
+
180
+ Args:
181
+ timeout (int): Time to wait for the DataVolume and PVC to be deleted.
182
+
183
+ Returns:
184
+ bool: True if DataVolume and its PVC are gone, False if timeout reached.
185
+ """
186
+ super().wait_deleted(timeout=timeout)
187
+ return self.pvc.wait_deleted(timeout=timeout)
188
+
189
+ def wait(self, timeout=600, failure_timeout=120):
190
+ self._check_none_pending_status(failure_timeout=failure_timeout)
191
+
192
+ # If DV's status is not Pending, continue with the flow
193
+ self.wait_for_status(status=self.Status.SUCCEEDED, timeout=timeout)
194
+ self.pvc.wait_for_status(
195
+ status=PersistentVolumeClaim.Status.BOUND, timeout=timeout
196
+ )
197
+
198
+ @property
199
+ def pvc(self):
200
+ return PersistentVolumeClaim(
201
+ client=self.privileged_client or self.client,
202
+ name=self.name,
203
+ namespace=self.namespace,
204
+ )
205
+
206
+ @property
207
+ def scratch_pvc(self):
208
+ return PersistentVolumeClaim(
209
+ name=f"{self.name}-scratch",
210
+ namespace=self.namespace,
211
+ client=self.client,
212
+ )
213
+
214
+ def _check_none_pending_status(self, failure_timeout=120):
215
+ # Avoid waiting for "Succeeded" status if DV's in Pending/None status
216
+ sample = None
217
+ # if garbage collector is enabled, DV will be deleted after success
218
+ try:
219
+ for sample in TimeoutSampler(
220
+ wait_timeout=failure_timeout,
221
+ sleep=10,
222
+ func=lambda: self.exists,
223
+ ):
224
+ # If DV status is Pending (or Status is not yet updated) continue to wait, else exit the wait loop
225
+ if sample and (
226
+ not sample.status
227
+ or sample.status.phase
228
+ in [
229
+ self.Status.PENDING,
230
+ None,
231
+ ]
232
+ ):
233
+ continue
234
+ break
235
+ except TimeoutExpiredError:
236
+ self.logger.error(f"{self.name} status is {sample}")
237
+ raise
238
+
239
+ def wait_for_dv_success(self, timeout=600, failure_timeout=120):
240
+ self.logger.info(f"Wait DV success for {timeout} seconds")
241
+ self._check_none_pending_status(failure_timeout=failure_timeout)
242
+ self.pvc.wait_for_status(
243
+ status=PersistentVolumeClaim.Status.BOUND, timeout=timeout
244
+ )
245
+ # if garbage collector enabled, the DV deleted once succeeded
246
+ try:
247
+ for sample in TimeoutSampler(
248
+ sleep=1,
249
+ wait_timeout=timeout,
250
+ func=lambda: self.exists,
251
+ ):
252
+ # DV reach to success if the status is succeeded or if the DV does not exists
253
+ if sample is None or sample.status.phase == self.Status.SUCCEEDED:
254
+ return
255
+ except TimeoutExpiredError:
256
+ self.logger.error(f"Status of {self.kind} {self.name} is {sample}")
257
+ raise
258
+
259
+ def delete(self, wait=False, timeout=TIMEOUT_4MINUTES, body=None):
260
+ """
261
+ Delete DataVolume
262
+
263
+ Args:
264
+ wait (bool): True to wait for DataVolume and PVC to be deleted.
265
+ timeout (int): Time to wait for resources deletion
266
+ body (dict): Content to send for delete()
267
+
268
+ Returns:
269
+ bool: True if delete succeeded, False otherwise.
270
+ """
271
+ # if garbage collector is enabled, DV will be deleted after success
272
+ if self.exists:
273
+ return super().delete(wait=wait, timeout=timeout, body=body)
274
+ else:
275
+ return self.pvc.delete(wait=wait, timeout=timeout, body=body)
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+ from ocp_resources.constants import PROTOCOL_ERROR_EXCEPTION_DICT, TIMEOUT_4MINUTES
3
+ from ocp_resources.resource import NamespacedResource
4
+ from ocp_resources.utils import TimeoutSampler
5
+
6
+
7
+ class Deployment(NamespacedResource):
8
+ """
9
+ OpenShift Deployment object.
10
+ """
11
+
12
+ api_group = NamespacedResource.ApiGroup.APPS
13
+
14
+ def scale_replicas(self, replica_count=int):
15
+ """
16
+ Update replicas in deployment.
17
+
18
+ Args:
19
+ replica_count (int): Number of replicas.
20
+
21
+ Returns:
22
+ Deployment is updated successfully
23
+ """
24
+ super().to_dict()
25
+ self.res.update({"spec": {"replicas": replica_count}})
26
+
27
+ self.logger.info(f"Set deployment replicas: {replica_count}")
28
+ return self.update(resource_dict=self.res)
29
+
30
+ def wait_for_replicas(self, deployed=True, timeout=TIMEOUT_4MINUTES):
31
+ """
32
+ Wait until all replicas are updated.
33
+
34
+ Args:
35
+ deployed (bool): True for replicas deployed, False for no replicas.
36
+ timeout (int): Time to wait for the deployment.
37
+
38
+ Raises:
39
+ TimeoutExpiredError: If not availableReplicas is equal to replicas.
40
+ """
41
+ self.logger.info(f"Wait for {self.kind} {self.name} to be deployed: {deployed}")
42
+ samples = TimeoutSampler(
43
+ wait_timeout=timeout,
44
+ sleep=1,
45
+ exceptions_dict=PROTOCOL_ERROR_EXCEPTION_DICT,
46
+ func=lambda: self.instance,
47
+ )
48
+ for sample in samples:
49
+ if sample:
50
+ status = sample.status
51
+
52
+ spec_replicas = sample.spec.replicas
53
+ total_replicas = status.replicas or 0
54
+ updated_replicas = status.updatedReplicas or 0
55
+ available_replicas = status.availableReplicas or 0
56
+ ready_replicas = status.readyReplicas or 0
57
+
58
+ if (
59
+ (deployed and spec_replicas)
60
+ and spec_replicas
61
+ == updated_replicas
62
+ == available_replicas
63
+ == ready_replicas
64
+ ) or not (deployed or spec_replicas or total_replicas):
65
+ return
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ocp_resources.resource import NamespacedResource
4
+
5
+
6
+ class DestinationRule(NamespacedResource):
7
+ """
8
+ Destination Rule object.
9
+ """
10
+
11
+ api_group = NamespacedResource.ApiGroup.NETWORKING_ISTIO_IO
ocp_resources/event.py ADDED
@@ -0,0 +1,114 @@
1
+ from ocp_resources.logger import get_logger
2
+
3
+
4
+ LOGGER = get_logger(name=__name__)
5
+
6
+
7
+ class Event:
8
+ """
9
+ Allow read and remove K8s events.
10
+ """
11
+
12
+ api_version = "v1"
13
+
14
+ @classmethod
15
+ def get(
16
+ cls,
17
+ dyn_client,
18
+ namespace=None,
19
+ name=None,
20
+ label_selector=None,
21
+ field_selector=None,
22
+ resource_version=None,
23
+ timeout=None,
24
+ ):
25
+ """
26
+ get - retrieves K8s events.
27
+
28
+ Args:
29
+ dyn_client (DynamicClient): K8s client
30
+ namespace (str): event namespace
31
+ name (str): event name
32
+ label_selector (str): filter events by labels; comma separated string of key=value
33
+ field_selector (str): filter events by fields; comma separated string of key=valueevent fields;
34
+ comma separated string of key=value
35
+ resource_version (str): filter events by their resource's version
36
+ timeout (int): timeout in seconds
37
+
38
+ Returns
39
+ list: event objects
40
+
41
+ example: reading all CSV Warning events in namespace "my-namespace", with reason of "AnEventReason"
42
+ for event in Event.get(
43
+ default_client,
44
+ namespace="my-namespace",
45
+ field_selector="involvedObject.kind==ClusterServiceVersion,type==Warning,reason=AnEventReason",
46
+ timeout=10,
47
+ ):
48
+ print(event.object)
49
+ """
50
+
51
+ LOGGER.info("Reading events")
52
+ LOGGER.debug(
53
+ f"get events parameters: namespace={namespace}, name={name}, label_selector={label_selector}, "
54
+ f"field_selector='{field_selector}', resource_version={resource_version}, timeout={timeout}"
55
+ )
56
+
57
+ event_listener = dyn_client.resources.get(
58
+ api_version=cls.api_version, kind=cls.__name__
59
+ )
60
+ yield from event_listener.watch(
61
+ namespace=namespace,
62
+ name=name,
63
+ label_selector=label_selector,
64
+ field_selector=field_selector,
65
+ resource_version=resource_version,
66
+ timeout=timeout,
67
+ )
68
+
69
+ @classmethod
70
+ def delete_events(
71
+ cls,
72
+ dyn_client,
73
+ namespace=None,
74
+ name=None,
75
+ label_selector=None,
76
+ field_selector=None,
77
+ resource_version=None,
78
+ timeout=None,
79
+ ):
80
+ """
81
+ delete_events - delete K8s events. For example, to cleanup events before test, in order to not get old
82
+ events in the test, in order to prevent false positive test.
83
+
84
+ Args:
85
+ dyn_client (DynamicClient): K8s client
86
+ namespace (str): event namespace
87
+ name (str): event name
88
+ label_selector (str): filter events by labels; comma separated string of key=value
89
+ field_selector (str): filter events by fields; comma separated string of key=valueevent fields;
90
+ comma separated string of key=value
91
+ resource_version (str): filter events by their resource's version
92
+ timeout (int): timeout in seconds
93
+
94
+ Returns
95
+ list: event objects
96
+
97
+ example: deleting all the event with a reason of "AnEventReason", from "my-namespace" namespace
98
+
99
+ def delete_events_before_test(default_client):
100
+ Event.delete_events(default_client, namespace=my-namespace, field_selector="reason=AnEventReason")
101
+ """
102
+ LOGGER.info("Deleting events")
103
+ LOGGER.debug(
104
+ f"delete_events parameters: namespace={namespace}, name={name}, label_selector={label_selector}, "
105
+ f"field_selector='{field_selector}', resource_version={resource_version}, timeout={timeout}"
106
+ )
107
+ dyn_client.resources.get(api_version=cls.api_version, kind=cls.__name__).delete(
108
+ namespace=namespace,
109
+ name=name,
110
+ label_selector=label_selector,
111
+ field_selector=field_selector,
112
+ resource_version=resource_version,
113
+ timeout=timeout,
114
+ )
@@ -0,0 +1,10 @@
1
+ from ocp_resources.mtv import MTV
2
+ from ocp_resources.resource import NamespacedResource
3
+
4
+
5
+ class ForkliftController(NamespacedResource, MTV):
6
+ """
7
+ Migration Toolkit For Virtualization (MTV) ForkliftController Resource
8
+ """
9
+
10
+ api_group = NamespacedResource.ApiGroup.FORKLIFT_KONVEYOR_IO