def wait_for_deployment(self, name: str, namespace: str = "default"): app_client = kubernetes.client.AppsV1Api(self._client) def _ready_callback(): try: response = app_client.read_namespaced_deployment_status( name=name, namespace=namespace) except kubernetes.client.ApiException: raise RuntimeError(f"Deployment {name} no longer exists!") conditions = response.status.conditions if conditions is None: return False statuses = {i.type: eval(i.status) for i in conditions} try: if statuses["Available"]: return True except KeyError: raise ValueError("Couldn't find readiness status") try: if not statuses["Progressing"]: raise RuntimeError( f"Deployment {name} stopped progressing") except KeyError: pass finally: return False wait_for(_ready_callback, f"Waiting for deployment {name} to deploy", f"Deployment {name} ready")
def remove_deployment(self, name: str, namespace: str = "default"): app_client = kubernetes.client.AppsV1Api(self._client) def _try_cmd(cmd): try: cmd(name=name, namespace=namespace) except Exception as e: try: body = yaml.safe_load(e.body) if body["code"] == 404: return True else: return False except AttributeError: raise e except Exception: raise return False _try_cmd(app_client.delete_namespaced_deployment) def _deleted_callback(): return _try_cmd(app_client.read_namespaced_deployment) wait_for(_deleted_callback, f"Waiting for deployment {name} to delete", f"Deployment {name} deleted")
def delete_resource(raised): if keep: return elif raised: print(f"Encountered error, removing {resource_msg}") wait_for( partial(resource_delete_submit_callback, resource), f"Waiting for {resource_msg} to become available to delete", f"{resource_msg} delete request submitted") wait_for(partial(resource_delete_done_callback, resource), f"Waiting for {resource_type} {resource.name} to delete", f"{resource_type} {resource.name} deleted") self.resources.pop(resource.name)
def delete_resource(self, resource): resource_msg = self._make_resource_message(resource) wait_for( resource.submit_delete, f"Waiting for {resource_msg} to become available to delete", f"{resource_msg} delete request submitted", ) wait_for( resource.is_deleted, f"Waiting for {resource_msg} to delete", f"{resource_msg} deleted", ) self._resources.pop(resource.name)
def create_resource(self, resource): if type(resource).__name__ != self.managed_resource_type.__name__: raise TypeError("{} cannot manage resource {}".format( type(self).__name__, type(resource).__name__)) resource = Resource.create(resource, self) resource_msg = self._make_resource_message(resource) wait_for( resource.is_ready, f"Waiting for {resource_msg} to become ready", f"{resource_msg} ready", ) self._resources[resource.name] = resource return resource
def remove_deployment(self, name: str, namespace: str = "default"): app_client = kubernetes.client.AppsV1Api(self._client) def _try_cmd(cmd): for _ in range(2): with self._maybe_refresh() as body: cmd(name=name, namespace=namespace) if body and body["code"] == 404: return True elif not body or body["code"] != 401: break return False _try_cmd(app_client.delete_namespaced_deployment) def _deleted_callback(): return _try_cmd(app_client.read_namespaced_deployment) wait_for( _deleted_callback, f"Waiting for deployment {name} to delete", f"Deployment {name} deleted", )
def manage_resource(self, resource, parent=None, keep=False): parent = parent or self resource = Resource(resource, parent, auth_token=self.auth_token) resource.create() resource_type = snakeify(resource.resource_type).replace("_", " ") resource_msg = resource_type + " " + resource.name wait_for(partial(resource_ready_callback, resource), f"Waiting for {resource_msg} to become ready", f"{resource_msg} ready") def delete_resource(raised): if keep: return elif raised: print(f"Encountered error, removing {resource_msg}") wait_for( partial(resource_delete_submit_callback, resource), f"Waiting for {resource_msg} to become available to delete", f"{resource_msg} delete request submitted") wait_for(partial(resource_delete_done_callback, resource), f"Waiting for {resource_type} {resource.name} to delete", f"{resource_type} {resource.name} deleted") self.resources.pop(resource.name) self.resources[resource.name] = resource raised = False try: yield resource except Exception: raised = True raise finally: delete_resource(raised)
def wait_for_service(self, name: str, namespace: str = "default"): core_client = kubernetes.client.CoreV1Api(self._client) def _ready_callback(): try: response = core_client.read_namespaced_service_status( name=name, namespace=namespace) except kubernetes.client.ApiException: raise RuntimeError(f"Service {name} no longer exists!") ip = response.status.load_balancer.ingress[0].ip return ip or False return wait_for(_ready_callback, f"Waiting for service {name} to be ready", f"Service {name} ready")