def test_deployment(): api_mock = MagicMock(spec=NamespacedAPIObject, name="APIMock") scalable_mock = {'spec': {'replicas': 3}} api_mock.obj = MagicMock(name="APIObjMock") d = Deployment(api_mock, scalable_mock) r = d.replicas assert r == 3 d.replicas = 10 assert scalable_mock['spec']['replicas'] == 10
def test_deployment(): api_mock = MagicMock(spec=NamespacedAPIObject, name="APIMock") scalable_mock = {"spec": {"replicas": 3}} api_mock.obj = MagicMock(name="APIObjMock") d = Deployment(api_mock, scalable_mock) r = d.replicas assert r == 3 d.replicas = 10 assert scalable_mock["spec"]["replicas"] == 10
def delete(body, meta, spec, status, **kwargs): api = K8SApi.from_env() deployment_name = f"{meta['name']}-{LAYER}" logger.info(f"Deleting deployment {deployment_name} ...") try: deployment = Deployment.objects(api).filter( namespace=meta["namespace"]).get(name=deployment_name) deployment.delete() except ObjectDoesNotExist: logger.warning(f"Deployment {deployment_name} doesn't exist") logger.info(f"Deleting deployment {deployment_name} ... done!") service_name = f"{meta['name']}" logger.info(f"Deleting service {service_name} ...") try: service = Service.objects(api).filter(namespace=meta["namespace"]).get( name=service_name) service.delete() except ObjectDoesNotExist: logger.warning(f"Service {service_name} doesn't exist") logger.info(f"Deleting service {service_name} ... done!") api.session.close() return {'job1-status': 100}
def create_helloworld_deployment(api, organization_name, tenant_name, space_name, deployment_name): obj = yaml.safe_load(f""" apiVersion: apps/v1 kind: Deployment metadata: namespace: org-{organization_name}-tenant-{tenant_name}-space-{space_name} name: {deployment_name} spec: selector: matchLabels: app: {deployment_name} replicas: 1 template: metadata: labels: app: {deployment_name} spec: containers: - name: {deployment_name} image: nginxinc/nginx-unprivileged ports: - containerPort: 8080 """) return Deployment(api, obj)
def test_within_grace_period(): now = datetime.now(timezone.utc) ts = now - timedelta(minutes=5) deploy = Deployment( None, {"metadata": {"creationTimestamp": ts.strftime("%Y-%m-%dT%H:%M:%SZ")}} ) assert within_grace_period(deploy, 900, now) assert not within_grace_period(deploy, 180, now)
def create(body, meta, spec, status, **kwargs): api = K8SApi.from_env() logger.info("Creating deployment ...") deployment_data = create_deployment_data(meta, spec) kopf.adopt(deployment_data) # kopf.label(pod_data, {'application': 'kopf-example-10'}) deployment = Deployment(api, deployment_data) if deployment.exists(): deployment.update() else: deployment.create() logger.info("Creating deployment ... done!") logger.info("Creating service ...") service_data = create_service_data(meta, spec) kopf.adopt(service_data) service = Service(api, service_data) if service.exists(): service.update() else: service.create() logger.info("Creating service ... done!") api.session.close() return {'job1-status': 100}
def test_list_deployments(api, requests_mock): with requests_mock as rsps: rsps.add(responses.GET, 'https://localhost:9443/apis/apps/v1/namespaces/default/deployments', json={'items': []}) assert list(Deployment.objects(api)) == [] assert len(rsps.calls) == 1 # ensure that we passed the token specified in kubeconfig.. assert rsps.calls[0].request.headers['Authorization'] == 'Bearer testtoken'
def delete(namespace, names, logger): api = HTTPClient(KubeConfig.from_file()) for name in names: deploy = Deployment.objects(api, namespace=namespace).get(name=name) deploy.delete() logger.info(f'delete Deployment: {str(deploy)}') service = Service.objects(api, namespace=namespace).get(name=name) service.delete() logger.info(f'delete Service: {str(service)}')
def test_list_and_patch_deployments(api, requests_mock): with requests_mock as rsps: rsps.add( responses.GET, "https://localhost:9443/apis/apps/v1/namespaces/default/deployments", json={ "items": [{ "metadata": { "name": "deploy-1" }, "spec": { "replicas": 3 } }] }, ) deployments = list(Deployment.objects(api)) assert len(deployments) == 1 deploy = deployments[0] assert deploy.name == "deploy-1" assert deploy.namespace == "default" assert deploy.replicas == 3 deploy.replicas = 2 rsps.add( responses.PATCH, "https://localhost:9443/apis/apps/v1/namespaces/default/deployments/deploy-1", json={ "metadata": { "name": "deploy-1", "labels": { "a": "b" } }, "spec": { "replicas": 2 }, }, ) deploy.patch({"metadata": {"labels": {"a": "b"}}}) assert len(rsps.calls) == 2 assert json.loads(rsps.calls[-1].request.body) == { "metadata": { "labels": { "a": "b" } } } assert deploy.labels["a"] == "b"
def _restart_deploy(secretName, namespace): deploys = Deployment.objects(api, namespace=namespace) for deploy in deploys: if 'bazinga.io/secretz' in deploy.annotations: j = json.dumps(deploy.obj) if 'envFrom' in j: if secretName in j: print( f"Restart deployment {deploy.namespace}/{deploy.name}..." ) deploy.obj['spec']['template']['metadata']['annotations'][ 'secretz.bazinga.io/restartAt'] = f"{datetime.now().isoformat()}" deploy.update()
def test_list_and_update_deployments(api, requests_mock): with requests_mock as rsps: rsps.add( responses.GET, 'https://localhost:9443/apis/apps/v1/namespaces/default/deployments', json={ 'items': [{ 'metadata': { 'name': 'deploy-1' }, 'spec': { 'replicas': 3 } }] }) deployments = list(Deployment.objects(api)) assert len(deployments) == 1 deploy = deployments[0] assert deploy.name == 'deploy-1' assert deploy.namespace == 'default' assert deploy.replicas == 3 deploy.replicas = 2 rsps.add( responses.PATCH, 'https://localhost:9443/apis/apps/v1/namespaces/default/deployments/deploy-1', json={ 'items': [{ 'metadata': { 'name': 'deploy-1' }, 'spec': { 'replicas': 2 } }] }) deploy.update() assert len(rsps.calls) == 2 assert json.loads(rsps.calls[-1].request.body) == { "metadata": { "name": "deploy-1" }, "spec": { "replicas": 2 } }
def test_within_grace_period_without_deployment_time_annotation(): now = datetime.now(timezone.utc) creation_time = now - timedelta(days=7) # without annotation set deploy = Deployment( None, { "metadata": { "creationTimestamp": creation_time.strftime("%Y-%m-%dT%H:%M:%SZ") } }, ) assert not within_grace_period( deploy, 900, now, deployment_time_annotation=ANNOTATION_NAME) assert not within_grace_period( deploy, 180, now, deployment_time_annotation=ANNOTATION_NAME)
def test_patch_subresource(api, requests_mock): with requests_mock as rsps: rsps.add( responses.GET, "https://localhost:9443/apis/apps/v1/namespaces/default/deployments", json={"items": [{ "metadata": { "name": "deploy-1" } }]}, ) deployments = list(Deployment.objects(api)) assert len(deployments) == 1 deploy = deployments[0] assert deploy.name == "deploy-1" assert deploy.namespace == "default" rsps.add( responses.PATCH, "https://localhost:9443/apis/apps/v1/namespaces/default/deployments/deploy-1/status", json={ "metadata": { "name": "deploy-1" }, "status": { "field": "field" } }, ) deploy.patch({"status": {"field": "field"}}, subresource="status") assert len(rsps.calls) == 2 assert json.loads(rsps.calls[-1].request.body) == { "status": { "field": "field" }, }
def test_list_and_patch_deployments(api, requests_mock): with requests_mock as rsps: rsps.add(responses.GET, 'https://localhost:9443/apis/apps/v1/namespaces/default/deployments', json={'items': [{'metadata': {'name': 'deploy-1'}, 'spec': {'replicas': 3}}]}) deployments = list(Deployment.objects(api)) assert len(deployments) == 1 deploy = deployments[0] assert deploy.name == 'deploy-1' assert deploy.namespace == 'default' assert deploy.replicas == 3 deploy.replicas = 2 rsps.add(responses.PATCH, 'https://localhost:9443/apis/apps/v1/namespaces/default/deployments/deploy-1', json={'metadata': {'name': 'deploy-1', 'labels': {'a': 'b'}}, 'spec': {'replicas': 2}}) deploy.patch({'metadata': {'labels': {'a': 'b'}}}) assert len(rsps.calls) == 2 assert json.loads(rsps.calls[-1].request.body) == {"metadata": {"labels": {"a": "b"}}} assert deploy.labels['a'] == 'b'
def test_within_grace_period_wrong_deployment_time_annotation(): now = datetime.now(timezone.utc) creation_time = now - timedelta(days=7) deploy = Deployment( None, { "metadata": { # name & namespace must be set as it will be logged (warning message) "name": "my-deploy", "namespace": "my-ns", "creationTimestamp": creation_time.strftime("%Y-%m-%dT%H:%M:%SZ"), "annotations": { ANNOTATION_NAME: "some-invalid-value" }, } }, ) assert not within_grace_period( deploy, 900, now, deployment_time_annotation=ANNOTATION_NAME) assert not within_grace_period( deploy, 180, now, deployment_time_annotation=ANNOTATION_NAME)
def update(body, meta, spec, status, **kwargs): api = K8SApi.from_env() logger.info(f"Updating fog rollout {meta['name']} ...") deployment_data = create_deployment_data(meta, spec) kopf.adopt(deployment_data) deployment = Deployment(api, deployment_data) if deployment.exists(): logger.info(f"Updating deployment {deployment.name} ...") deployment.update() logger.info(f"Updating deployment {deployment.name} ... done!") else: logger.warning(f"Deployment {deployment.name} doesn't exist") logger.info(f"Creating deployment {deployment.name} ...") deployment.create() logger.info(f"Creating deployment {deployment.name} ... done!") service_data = create_service_data(meta, spec) kopf.adopt(service_data) service = Service(api, service_data) if service.exists(): logger.info(f"Updating service {service.name} ...") service.update() logger.info(f"Updating service {service.name} ... done!") else: logger.warning(f"Service {service.name} doesn't exist") logger.info(f"Creating service {service.name} ...") service.create() logger.info(f"Creating service {service.name} ... done!") logger.info(f"Updating fog rollout {meta['name']} ... done!") api.session.close() return {'job1-status': 100}
def deployments_get(name): deployment = Deployment.objects(api).get(name=name) return render_template('deployment_get.html', deployment=deployment)
def deployments_list(): deployments = Deployment.objects(api).filter(namespace='default') return render_template('deployment_list.html', deployments=deployments)
def get_deployment_generation(kube_cluster, deployment_name, namespace) -> str: hello_deployment: Deployment = (Deployment.objects( kube_cluster.kube_client).filter( namespace=namespace).get_by_name(deployment_name)) return str(hello_deployment.obj["status"]["observedGeneration"])