diff --git a/lib/ansible/modules/cloud/kubevirt/kubevirt_rs.py b/lib/ansible/modules/cloud/kubevirt/kubevirt_rs.py index 085d3ef535f..4611774ff67 100644 --- a/lib/ansible/modules/cloud/kubevirt/kubevirt_rs.py +++ b/lib/ansible/modules/cloud/kubevirt/kubevirt_rs.py @@ -113,12 +113,6 @@ import traceback from ansible.module_utils.k8s.common import AUTH_ARG_SPEC -try: - from openshift.dynamic.client import ResourceInstance -except ImportError: - # Handled in module_utils - pass - from ansible.module_utils.kubevirt import ( virtdict, KubeVirtRawModule, @@ -143,26 +137,20 @@ class KubeVirtVMIRS(KubeVirtRawModule): argument_spec.update(copy.deepcopy(VMIR_ARG_SPEC)) return argument_spec - def _read_stream(self, resource, watcher, stream, name, replicas): + def wait_for_replicas(self, replicas): """ Wait for ready_replicas to equal the requested number of replicas. """ - if self.params.get('state') == 'absent': - # TODO: Wait for absent - return - + resource = self.find_supported_resource(KIND) return_obj = None - for event in stream: - if event.get('object'): - obj = ResourceInstance(resource, event['object']) - if obj.metadata.name == name and hasattr(obj, 'status'): - if replicas == 0: - if not hasattr(obj.status, 'readyReplicas') or not obj.status.readyReplicas: - return_obj = obj - watcher.stop() - break - if hasattr(obj.status, 'readyReplicas') and obj.status.readyReplicas == replicas: - return_obj = obj - watcher.stop() - break + + for event in resource.watch(namespace=self.namespace, timeout=self.params.get('wait_timeout')): + entity = event['object'] + if entity.metadata.name != self.name: + continue + status = entity.get('status', {}) + readyReplicas = status.get('readyReplicas', 0) + if readyReplicas == replicas: + return_obj = entity + break if not return_obj: self.fail_json(msg="Error fetching the patched object. Try a higher wait_timeout value.") @@ -173,16 +161,6 @@ class KubeVirtVMIRS(KubeVirtRawModule): "the wait_timeout period.".format(return_obj.status.ready_replicas, replicas)) return return_obj.to_dict() - def wait_for_replicas(self): - namespace = self.params.get('namespace') - wait_timeout = self.params.get('wait_timeout') - replicas = self.params.get('replicas') - name = self.name - resource = self.find_supported_resource(KIND) - - w, stream = self._create_stream(resource, namespace, wait_timeout) - return self._read_stream(resource, w, stream, name, replicas) - def execute_module(self): # Parse parameters specific for this module: definition = virtdict() @@ -202,10 +180,17 @@ class KubeVirtVMIRS(KubeVirtRawModule): changed = result_crud['changed'] result = result_crud.pop('result') - # Wait for the replicas: - wait = self.params.get('wait') - if wait: - result = self.wait_for_replicas() + # When creating a new VMIRS object without specifying `replicas`, assume it's '1' to make the + # wait logic work correctly + if changed and result_crud['method'] == 'create' and replicas is None: + replicas = 1 + + # Wait for the new number of ready replicas after a CRUD update + # Note1: doesn't work correctly when reducing number of replicas due to how VMIRS works (as of kubevirt 1.5.0) + # Note2: not the place to wait for the VMIs to get deleted when deleting the VMIRS object; that *might* be + # achievable in execute_crud(); keywords: orphanDependents, propagationPolicy, DeleteOptions + if self.params.get('wait') and replicas is not None and self.params.get('state') == 'present': + result = self.wait_for_replicas(replicas) # Return from the module: self.exit_json(**{