From f50e808d36329a9e6a77aebc5595f4a28b029220 Mon Sep 17 00:00:00 2001 From: Lars Wander Date: Mon, 30 Oct 2017 15:02:44 -0400 Subject: [PATCH] feat(provider/kubernetes): depend on kubectl where possible --- .../KubernetesDeleteManifestDescription.java | 5 +- .../kubernetes/v2/op/deployer/CanDelete.java | 14 +- .../v2/op/deployer/KubernetesDeployer.java | 2 + .../KubernetesDeploymentDeployer.java | 14 +- .../deployer/KubernetesIngressDeployer.java | 15 +- .../KubernetesReplicaSetDeployer.java | 15 +- .../deployer/KubernetesServiceDeployer.java | 12 +- .../v2/op/job/KubectlJobExecutor.java | 69 ++- .../KubernetesDeleteManifestOperation.java | 4 +- .../v2/security/KubernetesV2Credentials.java | 396 ------------------ 10 files changed, 82 insertions(+), 464 deletions(-) diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/description/manifest/KubernetesDeleteManifestDescription.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/description/manifest/KubernetesDeleteManifestDescription.java index ba4ce43bf8a..39fb8b9598d 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/description/manifest/KubernetesDeleteManifestDescription.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/description/manifest/KubernetesDeleteManifestDescription.java @@ -17,13 +17,12 @@ package com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest; +import io.kubernetes.client.models.V1DeleteOptions; import lombok.Data; import lombok.EqualsAndHashCode; -import java.util.Map; - @EqualsAndHashCode(callSuper = true) @Data public class KubernetesDeleteManifestDescription extends KubernetesManifestOperationDescription { - Map deleteOptions; + V1DeleteOptions options; } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/CanDelete.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/CanDelete.java index 9a346c79826..032be649430 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/CanDelete.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/CanDelete.java @@ -17,10 +17,16 @@ package com.netflix.spinnaker.clouddriver.kubernetes.v2.op.deployer; +import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest.KubernetesKind; +import com.netflix.spinnaker.clouddriver.kubernetes.v2.op.job.KubectlJobExecutor; import com.netflix.spinnaker.clouddriver.kubernetes.v2.security.KubernetesV2Credentials; -import com.netflix.spinnaker.clouddriver.model.ServerGroup.Capacity; +import io.kubernetes.client.models.V1DeleteOptions; -public interface CanDelete { - Class getDeleteOptionsClass(); - void delete(KubernetesV2Credentials credentials, String namespace, String name, T deleteOptions); +public interface CanDelete { + KubernetesKind kind(); + KubectlJobExecutor getJobExecutor(); + + default void delete(KubernetesV2Credentials credentials, String namespace, String name, V1DeleteOptions deleteOptions) { + getJobExecutor().delete(credentials, kind(), namespace, name, deleteOptions); + } } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeployer.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeployer.java index d8dedebdfef..39e0c5e6d0f 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeployer.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeployer.java @@ -26,6 +26,7 @@ import com.netflix.spinnaker.clouddriver.kubernetes.v2.op.job.KubectlJobExecutor; import com.netflix.spinnaker.clouddriver.kubernetes.v2.security.KubernetesV2Credentials; import com.netflix.spinnaker.clouddriver.model.Manifest.Status; +import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; @@ -39,6 +40,7 @@ public abstract class KubernetesDeployer { @Autowired private KubernetesCacheUtils cacheUtils; + @Getter @Autowired protected KubectlJobExecutor jobExecutor; diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeploymentDeployer.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeploymentDeployer.java index a98ff3162e0..cf12e53d577 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeploymentDeployer.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesDeploymentDeployer.java @@ -32,7 +32,7 @@ import org.springframework.stereotype.Component; @Component -public class KubernetesDeploymentDeployer extends KubernetesDeployer implements CanResize, CanDelete { +public class KubernetesDeploymentDeployer extends KubernetesDeployer implements CanResize, CanDelete { @Override public KubernetesKind kind() { return KubernetesKind.DEPLOYMENT; @@ -114,16 +114,6 @@ private Status status(V1beta2Deployment deployment) { @Override public void resize(KubernetesV2Credentials credentials, String namespace, String name, Capacity capacity) { - credentials.resizeDeployment(namespace, name, capacity.getDesired()); - } - - @Override - public Class getDeleteOptionsClass() { - return V1DeleteOptions.class; - } - - @Override - public void delete(KubernetesV2Credentials credentials, String namespace, String name, V1DeleteOptions deleteOptions) { - credentials.deleteDeployment(namespace, name, deleteOptions); + jobExecutor.scale(credentials, kind(), namespace, name, capacity.getDesired()); } } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesIngressDeployer.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesIngressDeployer.java index be9c38f32f7..32198a39329 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesIngressDeployer.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesIngressDeployer.java @@ -20,14 +20,11 @@ import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.KubernetesSpinnakerKindMap.SpinnakerKind; import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest.KubernetesKind; import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest.KubernetesManifest; -import com.netflix.spinnaker.clouddriver.kubernetes.v2.security.KubernetesV2Credentials; -import com.netflix.spinnaker.clouddriver.model.Manifest; import com.netflix.spinnaker.clouddriver.model.Manifest.Status; -import io.kubernetes.client.models.V1DeleteOptions; import org.springframework.stereotype.Component; @Component -public class KubernetesIngressDeployer extends KubernetesDeployer implements CanDelete { +public class KubernetesIngressDeployer extends KubernetesDeployer implements CanDelete { @Override public KubernetesKind kind() { return KubernetesKind.INGRESS; @@ -47,14 +44,4 @@ public SpinnakerKind spinnakerKind() { public Status status(KubernetesManifest manifest) { return Status.stable(); } - - @Override - public Class getDeleteOptionsClass() { - return V1DeleteOptions.class; - } - - @Override - public void delete(KubernetesV2Credentials credentials, String namespace, String name, V1DeleteOptions deleteOptions) { - credentials.deleteIngress(namespace, name, deleteOptions); - } } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesReplicaSetDeployer.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesReplicaSetDeployer.java index dfece96eb57..a258ccc31ca 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesReplicaSetDeployer.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesReplicaSetDeployer.java @@ -24,7 +24,6 @@ import com.netflix.spinnaker.clouddriver.kubernetes.v2.security.KubernetesV2Credentials; import com.netflix.spinnaker.clouddriver.model.Manifest.Status; import com.netflix.spinnaker.clouddriver.model.ServerGroup.Capacity; -import io.kubernetes.client.models.V1DeleteOptions; import io.kubernetes.client.models.V1beta1ReplicaSet; import io.kubernetes.client.models.V1beta1ReplicaSetStatus; import io.kubernetes.client.models.V1beta2ReplicaSet; @@ -34,17 +33,12 @@ import java.util.Map; @Component -public class KubernetesReplicaSetDeployer extends KubernetesDeployer implements CanResize, CanDelete { +public class KubernetesReplicaSetDeployer extends KubernetesDeployer implements CanResize, CanDelete { @Override public KubernetesKind kind() { return KubernetesKind.REPLICA_SET; } - @Override - public Class getDeleteOptionsClass() { - return V1DeleteOptions.class; - } - @Override public boolean versioned() { return true; @@ -121,12 +115,7 @@ private Status status(V1beta2ReplicaSet replicaSet) { @Override public void resize(KubernetesV2Credentials credentials, String namespace, String name, Capacity capacity) { - credentials.resizeReplicaSet(namespace, name, capacity.getDesired()); - } - - @Override - public void delete(KubernetesV2Credentials credentials, String namespace, String name, V1DeleteOptions deleteOptions) { - credentials.deleteReplicaSet(namespace, name, deleteOptions); + jobExecutor.scale(credentials, KubernetesKind.REPLICA_SET, namespace, name, capacity.getDesired()); } public static Map getPodTemplateLabels(KubernetesManifest manifest) { diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesServiceDeployer.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesServiceDeployer.java index f120d73c010..d74ce39a693 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesServiceDeployer.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/deployer/KubernetesServiceDeployer.java @@ -29,7 +29,7 @@ import java.util.Map; @Component -public class KubernetesServiceDeployer extends KubernetesDeployer implements CanDelete { +public class KubernetesServiceDeployer extends KubernetesDeployer implements CanDelete { @Override public KubernetesKind kind() { return KubernetesKind.SERVICE; @@ -50,16 +50,6 @@ public Status status(KubernetesManifest manifest) { return Status.stable(); } - @Override - public Class getDeleteOptionsClass() { - return Void.class; - } - - @Override - public void delete(KubernetesV2Credentials credentials, String namespace, String name, Void deleteOptions) { - credentials.deleteService(namespace, name); - } - public static Map getSelector(KubernetesManifest manifest) { switch (manifest.getApiVersion()) { case V1: diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/job/KubectlJobExecutor.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/job/KubectlJobExecutor.java index 216b3f2f42d..9543bf5f163 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/job/KubectlJobExecutor.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/job/KubectlJobExecutor.java @@ -26,6 +26,7 @@ import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest.KubernetesManifest; import com.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest.KubernetesManifestList; import com.netflix.spinnaker.clouddriver.kubernetes.v2.security.KubernetesV2Credentials; +import io.kubernetes.client.models.V1DeleteOptions; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -42,10 +43,10 @@ public class KubectlJobExecutor { @Value("${kubernetes.kubectl.poll.minSleepMillis:100}") Long minSleepMillis; - @Value("${kubernetes.kubectl.poll.maxSleepMillis:1000}") + @Value("${kubernetes.kubectl.poll.maxSleepMillis:2000}") Long maxSleepMillis; - @Value("${kubernetes.kubectl.poll.timeout:10000}") + @Value("${kubernetes.kubectl.poll.timeoutMillis:100000}") Long timeoutMillis; @Value("${kubernetes.kubectl.poll.maxInterruptRetries:10}") @@ -63,6 +64,57 @@ public class KubectlJobExecutor { this.jobExecutor = jobExecutor; } + public void delete(KubernetesV2Credentials credentials, KubernetesKind kind, String namespace, String name, V1DeleteOptions deleteOptions) { + List command = kubectlNamespacedAuthPrefix(credentials, namespace); + + command.add("delete"); + command.add(kind.toString()); + command.add(name); + + // spinnaker generally accepts deletes of resources that don't exist + command.add("--ignore-not-found=true"); + + if (deleteOptions.isOrphanDependents() != null) { + command.add("--cascade=" + !deleteOptions.isOrphanDependents()); + } + + if (deleteOptions.getGracePeriodSeconds() != null) { + command.add("--grace-period=" + deleteOptions.getGracePeriodSeconds()); + } + + if (StringUtils.isNotEmpty(deleteOptions.getPropagationPolicy())) { + throw new IllegalArgumentException("Propagation policy is not yet supported as a delete option"); + } + + String jobId = jobExecutor.startJob(new JobRequest(command), + System.getenv(), + new ByteArrayInputStream(new byte[0])); + + JobStatus status = backoffWait(jobId, credentials.isDebug()); + + if (status.getResult() != JobStatus.Result.SUCCESS) { + throw new KubectlException("Failed to delete " + kind + "/" + name + " from " + namespace + ": " + status.getStdErr()); + } + } + + public void scale(KubernetesV2Credentials credentials, KubernetesKind kind, String namespace, String name, int replicas) { + List command = kubectlNamespacedAuthPrefix(credentials, namespace); + + command.add("scale"); + command.add(kind.toString() + "/" + name); + command.add("--replicas=" + replicas); + + String jobId = jobExecutor.startJob(new JobRequest(command), + System.getenv(), + new ByteArrayInputStream(new byte[0])); + + JobStatus status = backoffWait(jobId, credentials.isDebug()); + + if (status.getResult() != JobStatus.Result.SUCCESS) { + throw new KubectlException("Failed to scale " + kind + "/" + name + " from " + namespace + ": " + status.getStdErr()); + } + } + public KubernetesManifest get(KubernetesV2Credentials credentials, KubernetesKind kind, String namespace, String name) { List command = kubectlNamespacedGet(credentials, kind, namespace); command.add(name); @@ -74,6 +126,10 @@ public KubernetesManifest get(KubernetesV2Credentials credentials, KubernetesKin JobStatus status = backoffWait(jobId, credentials.isDebug()); if (status.getResult() != JobStatus.Result.SUCCESS) { + if (status.getStdErr().contains("(NotFound)")) { + return null; + } + throw new KubectlException("Failed to read " + kind + " from " + namespace + ": " + status.getStdErr()); } @@ -180,14 +236,12 @@ private List kubectlAuthPrefix(KubernetesV2Credentials credentials) { String kubeconfigFile = credentials.getKubeconfigFile(); if (StringUtils.isNotEmpty(kubeconfigFile)) { - command.add("--kubeconfig"); - command.add(kubeconfigFile); + command.add("--kubeconfig=" + kubeconfigFile); } String context = credentials.getContext(); if (StringUtils.isNotEmpty(context)) { - command.add("--context"); - command.add(context); + command.add("--context=" + context); } return command; @@ -199,8 +253,7 @@ private List kubectlNamespacedAuthPrefix(KubernetesV2Credentials credent namespace = credentials.getDefaultNamespace(); } - command.add("--namespace"); - command.add(namespace); + command.add("--namespace=" + namespace); return command; } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/manifest/KubernetesDeleteManifestOperation.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/manifest/KubernetesDeleteManifestOperation.java index b4f3fcaefc5..32318285d4b 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/manifest/KubernetesDeleteManifestOperation.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/op/manifest/KubernetesDeleteManifestOperation.java @@ -65,12 +65,10 @@ public Void operate(List priorOutputs) { CanDelete canDelete = (CanDelete) deployer; getTask().updateStatus(OP_NAME, "Calling delete operation..."); - Map deleteOptions = description.getDeleteOptions(); - Object convertedDeleteOptions = deleteOptions == null ? null : mapper.convertValue(deleteOptions, (canDelete).getDeleteOptionsClass()); canDelete.delete(credentials, coordinates.getNamespace(), coordinates.getName(), - convertedDeleteOptions); + description.getOptions()); return null; } diff --git a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/security/KubernetesV2Credentials.java b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/security/KubernetesV2Credentials.java index da0945d0197..1ebed7608fd 100644 --- a/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/security/KubernetesV2Credentials.java +++ b/clouddriver-kubernetes/src/main/groovy/com/netflix/spinnaker/clouddriver/kubernetes/v2/security/KubernetesV2Credentials.java @@ -31,18 +31,7 @@ import io.kubernetes.client.apis.AppsV1beta2Api; import io.kubernetes.client.apis.CoreV1Api; import io.kubernetes.client.apis.ExtensionsV1beta1Api; -import io.kubernetes.client.models.AppsV1beta1Deployment; -import io.kubernetes.client.models.V1DeleteOptions; -import io.kubernetes.client.models.V1Pod; -import io.kubernetes.client.models.V1PodList; import io.kubernetes.client.models.V1Service; -import io.kubernetes.client.models.V1ServiceList; -import io.kubernetes.client.models.V1Status; -import io.kubernetes.client.models.V1beta1Ingress; -import io.kubernetes.client.models.V1beta1NetworkPolicy; -import io.kubernetes.client.models.V1beta1NetworkPolicyList; -import io.kubernetes.client.models.V1beta1ReplicaSet; -import io.kubernetes.client.models.V1beta1ReplicaSetList; import io.kubernetes.client.util.Config; import io.kubernetes.client.util.KubeConfig; import lombok.Getter; @@ -258,391 +247,6 @@ public KubernetesSelectorList labelSelectorList(V1Service service) { return list; } - public void createDeployment(AppsV1beta1Deployment deployment) { - final String methodName = "deployments.create"; - final String namespace = deployment.getMetadata().getNamespace(); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return appsV1beta1Api.createNamespacedDeployment(namespace, deployment, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Status deleteDeployment(String namespace, String name, V1DeleteOptions deleteOptions) { - final String methodName = "deployments.delete"; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - return appsV1beta1Api.deleteNamespacedDeployment(name, namespace, deleteOptions, PRETTY, null, null, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void patchDeployment(String namespace, String name, AppsV1beta1Deployment desired) { - AppsV1beta1Deployment current = readDeployment(namespace, name); - patchDeployment(current, desired); - } - - public void patchDeployment(AppsV1beta1Deployment current, AppsV1beta1Deployment desired) { - final String methodName = "deployments.patch"; - final String namespace = current.getMetadata().getNamespace(); - final String name = current.getMetadata().getName(); - final Map[] jsonPatch = determineJsonPatch(current, desired); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return appsV1beta1Api.patchNamespacedDeployment(name, namespace, jsonPatch, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public AppsV1beta1Deployment readDeployment(String namespace, String name) { - final String methodName = "deployments.read"; - final KubernetesApiVersion apiVersion = KubernetesApiVersion.APPS_V1BETA1; - final KubernetesKind kind = KubernetesKind.DEPLOYMENT; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - AppsV1beta1Deployment result = appsV1beta1Api.readNamespacedDeployment(name, namespace, PRETTY, EXACT, EXPORT); - return annotateMissingFields(result, AppsV1beta1Deployment.class, apiVersion, kind); - } catch (ApiException e) { - if (notFound(e)) { - return null; - } - - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void resizeDeployment(String namespace, String name, int replicas) { - AppsV1beta1Deployment deployment = readDeployment(namespace, name); - deployment.getSpec().setReplicas(replicas); - patchDeployment(namespace, name, deployment); - } - - public void createIngress(V1beta1Ingress ingress) { - final String methodName = "ingresses.create"; - final String namespace = ingress.getMetadata().getNamespace(); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.createNamespacedIngress(namespace, ingress, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Status deleteIngress(String namespace, String name, V1DeleteOptions deleteOptions) { - final String methodName = "ingresses.delete"; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.deleteNamespacedIngress(name, namespace, deleteOptions, PRETTY, null, null, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void patchIngress(String namespace, String name, V1beta1Ingress desired) { - V1beta1Ingress current = readIngress(namespace, name); - patchIngress(current, desired); - } - - public void patchIngress(V1beta1Ingress current, V1beta1Ingress desired) { - final String methodName = "ingresses.patch"; - final String namespace = current.getMetadata().getNamespace(); - final String name = current.getMetadata().getName(); - final Map[] jsonPatch = determineJsonPatch(current, desired); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.patchNamespacedIngress(name, namespace, jsonPatch, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1beta1Ingress readIngress(String namespace, String name) { - final String methodName = "ingresses.read"; - final KubernetesApiVersion apiVersion = KubernetesApiVersion.APPS_V1BETA1; - final KubernetesKind kind = KubernetesKind.DEPLOYMENT; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1beta1Ingress result = extensionsV1beta1Api.readNamespacedIngress(name, namespace, PRETTY, EXACT, EXPORT); - return annotateMissingFields(result, V1beta1Ingress.class, apiVersion, kind); - } catch (ApiException e) { - if (notFound(e)) { - return null; - } - - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void createNetworkPolicy(V1beta1NetworkPolicy networkPolicy) { - final String methodName = "networkPolicies.create"; - final String namespace = networkPolicy.getMetadata().getNamespace(); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.createNamespacedNetworkPolicy(namespace, networkPolicy, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Status deleteNetworkPolicy(String namespace, String name, V1DeleteOptions deleteOptions) { - final String methodName = "networkPolicies.delete"; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.deleteNamespacedNetworkPolicy(name, namespace, deleteOptions, PRETTY, null, null, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public List listAllNetworkPolicies(String namespace) { - return listNetworkPolicies(namespace, new KubernetesSelectorList(), new KubernetesSelectorList()); - } - - public List listNetworkPolicies(String namespace, KubernetesSelectorList fieldSelectors, KubernetesSelectorList labelSelectors) { - final String methodName = "networkPolicies.list"; - final String fieldSelectorString = fieldSelectors.toString(); - final String labelSelectorString = labelSelectors.toString(); - final KubernetesApiVersion apiVersion = KubernetesApiVersion.EXTENSIONS_V1BETA1; - final KubernetesKind kind = KubernetesKind.NETWORK_POLICY; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1beta1NetworkPolicyList list = extensionsV1beta1Api.listNamespacedNetworkPolicy(namespace, PRETTY, CONTINUE, fieldSelectorString, INCLUDE_UNINITIALIZED, labelSelectorString, LIMIT, DEFAULT_VERSION, TIMEOUT_SECONDS, WATCH); - return annotateMissingFields(list == null ? new ArrayList<>() : list.getItems(), - V1beta1NetworkPolicy.class, - apiVersion, - kind); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1beta1NetworkPolicy readNetworkPolicy(String namespace, String name) { - final String methodName = "networkPolicies.read"; - final KubernetesApiVersion apiVersion = KubernetesApiVersion.EXTENSIONS_V1BETA1; - final KubernetesKind kind = KubernetesKind.NETWORK_POLICY; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1beta1NetworkPolicy result = extensionsV1beta1Api.readNamespacedNetworkPolicy(name, namespace, PRETTY, EXACT, EXPORT); - return annotateMissingFields(result, V1beta1NetworkPolicy.class, apiVersion, kind); - } catch (ApiException e) { - if (notFound(e)) { - return null; - } - - throw new KubernetesApiException(methodName, e); - } - }); - } - - public List listAllPods(String namespace) { - return listPods(namespace, new KubernetesSelectorList(), new KubernetesSelectorList()); - } - - public List listPods(String namespace, KubernetesSelectorList fieldSelectors, KubernetesSelectorList labelSelectors) { - final String methodName = "pods.list"; - final String fieldSelectorString = fieldSelectors.toString(); - final String labelSelectorString = labelSelectors.toString(); - final KubernetesApiVersion apiVersion = KubernetesApiVersion.V1; - final KubernetesKind kind = KubernetesKind.POD; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1PodList list = coreV1Api.listNamespacedPod(namespace, PRETTY, CONTINUE, fieldSelectorString, INCLUDE_UNINITIALIZED, labelSelectorString, LIMIT, DEFAULT_VERSION, TIMEOUT_SECONDS, WATCH); - return annotateMissingFields(list == null ? new ArrayList<>() : list.getItems(), - V1Pod.class, - apiVersion, - kind); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void createReplicaSet(V1beta1ReplicaSet replicaSet) { - final String methodName = "replicaSets.create"; - final String namespace = replicaSet.getMetadata().getNamespace(); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.createNamespacedReplicaSet(namespace, replicaSet, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Status deleteReplicaSet(String namespace, String name, V1DeleteOptions deleteOptions) { - final String methodName = "replicaSets.delete"; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.deleteNamespacedReplicaSet(name, namespace, deleteOptions, PRETTY, null, null, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public List listAllReplicaSets(String namespace) { - return listReplicaSets(namespace, new KubernetesSelectorList(), new KubernetesSelectorList()); - } - - public List listReplicaSets(String namespace, KubernetesSelectorList fieldSelectors, KubernetesSelectorList labelSelectors) { - final String methodName = "replicaSets.list"; - final String fieldSelectorString = fieldSelectors.toString(); - final String labelSelectorString = labelSelectors.toString(); - final KubernetesApiVersion apiVersion = KubernetesApiVersion.EXTENSIONS_V1BETA1; - final KubernetesKind kind = KubernetesKind.REPLICA_SET; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1beta1ReplicaSetList list = extensionsV1beta1Api.listNamespacedReplicaSet(namespace, PRETTY, CONTINUE, fieldSelectorString, INCLUDE_UNINITIALIZED, labelSelectorString, LIMIT, DEFAULT_VERSION, TIMEOUT_SECONDS, WATCH); - return annotateMissingFields(list == null ? new ArrayList<>() : list.getItems(), - V1beta1ReplicaSet.class, - apiVersion, - kind); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void patchReplicaSet(String namespace, String name, V1beta1ReplicaSet desired) { - V1beta1ReplicaSet current = readReplicaSet(namespace, name); - patchReplicaSet(current, desired); - } - - public void patchReplicaSet(V1beta1ReplicaSet current, V1beta1ReplicaSet desired) { - final String methodName = "replicaSets.patch"; - final String namespace = current.getMetadata().getNamespace(); - final String name = current.getMetadata().getName(); - final Map[] jsonPatch = determineJsonPatch(current, desired); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return extensionsV1beta1Api.patchNamespacedReplicaSet(name, namespace, jsonPatch, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1beta1ReplicaSet readReplicaSet(String namespace, String name) { - final String methodName = "replicaSets.read"; - final KubernetesApiVersion apiVersion = KubernetesApiVersion.EXTENSIONS_V1BETA1; - final KubernetesKind kind = KubernetesKind.REPLICA_SET; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1beta1ReplicaSet result = extensionsV1beta1Api.readNamespacedReplicaSet(name, namespace, PRETTY, EXACT, EXPORT); - return annotateMissingFields(result, V1beta1ReplicaSet.class, apiVersion, kind); - } catch (ApiException e) { - if (notFound(e)) { - return null; - } - - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void resizeReplicaSet(String namespace, String name, int replicas) { - V1beta1ReplicaSet replicaSet = readReplicaSet(namespace, name); - replicaSet.getSpec().setReplicas(replicas); - patchReplicaSet(namespace, name, replicaSet); - } - - public void createService(V1Service service) { - final String methodName = "services.create"; - final String namespace = service.getMetadata().getNamespace(); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return coreV1Api.createNamespacedService(namespace, service, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Status deleteService(String namespace, String name) { - final String methodName = "services.delete"; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - return coreV1Api.deleteNamespacedService(name, namespace, PRETTY); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public List listAllServices(String namespace) { - return listServices(namespace, new KubernetesSelectorList(), new KubernetesSelectorList()); - } - - public List listServices(String namespace, KubernetesSelectorList fieldSelectors, KubernetesSelectorList labelSelectors) { - final String methodName = "services.list"; - final String fieldSelectorString = fieldSelectors.toString(); - final String labelSelectorString = labelSelectors.toString(); - final KubernetesApiVersion apiVersion = KubernetesApiVersion.V1; - final KubernetesKind kind = KubernetesKind.SERVICE; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1ServiceList list = coreV1Api.listNamespacedService(namespace, PRETTY, CONTINUE, fieldSelectorString, INCLUDE_UNINITIALIZED, labelSelectorString, LIMIT, DEFAULT_VERSION, TIMEOUT_SECONDS, WATCH); - return annotateMissingFields(list == null ? new ArrayList<>() : list.getItems(), - V1Service.class, - apiVersion, - kind); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public void patchService(String namespace, String name, V1Service desired) { - V1Service current = readService(namespace, name); - patchService(current, desired); - } - - public void patchService(V1Service current, V1Service desired) { - final String methodName = "services.patch"; - final String namespace = current.getMetadata().getNamespace(); - final String name = current.getMetadata().getName(); - final Map[] jsonPatch = determineJsonPatch(current, desired); - runAndRecordMetrics(methodName, namespace, () -> { - try { - return coreV1Api.patchNamespacedService(name, namespace, jsonPatch, null); - } catch (ApiException e) { - throw new KubernetesApiException(methodName, e); - } - }); - } - - public V1Service readService(String namespace, String name) { - final String methodName = "services.read"; - final KubernetesApiVersion apiVersion = KubernetesApiVersion.V1; - final KubernetesKind kind = KubernetesKind.SERVICE; - return runAndRecordMetrics(methodName, namespace, () -> { - try { - V1Service result = coreV1Api.readNamespacedService(name, namespace, PRETTY, EXACT, EXPORT); - return annotateMissingFields(result, V1Service.class, apiVersion, kind); - } catch (ApiException e) { - if (notFound(e)) { - return null; - } - - throw new KubernetesApiException(methodName, e); - } - }); - } - private T runAndRecordMetrics(String methodName, String namespace, Supplier op) { T result = null; Throwable failure = null;