diff --git a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractor.java b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractor.java index 0a053185ab9..c8ea9239c94 100644 --- a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractor.java +++ b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractor.java @@ -17,6 +17,7 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; @@ -36,6 +37,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.TreeMap; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -82,6 +84,7 @@ public class KubernetesAttributesExtractor implements AttributeExtractor crdContexts; + private Map pluralToKind = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); public KubernetesAttributesExtractor() { this(Collections.emptyList()); @@ -165,29 +168,30 @@ public AttributeSet extract(String s) { } @Override - public AttributeSet extract(HasMetadata o) { - AttributeSet attributes = extractMetadataAttributes(o); - if (!Utils.isNullOrEmpty(o.getKind())) { - attributes = attributes.add(new Attribute(KIND, o.getKind().toLowerCase(Locale.ROOT))); + public AttributeSet extract(HasMetadata hasMetadata) { + AttributeSet metadataAttributes = new AttributeSet(); + if (!Utils.isNullOrEmpty(hasMetadata.getMetadata().getName())) { + metadataAttributes = metadataAttributes.add(new Attribute(NAME, hasMetadata.getMetadata().getName())); } - return attributes; - } - - protected AttributeSet extractMetadataAttributes(HasMetadata hasMetadata) { - AttributeSet metadataAttributes = new AttributeSet(); - if (!Utils.isNullOrEmpty(hasMetadata.getMetadata().getName())) { - metadataAttributes = metadataAttributes.add(new Attribute(NAME, hasMetadata.getMetadata().getName())); - } - if (!Utils.isNullOrEmpty(hasMetadata.getMetadata().getNamespace())) { - metadataAttributes = metadataAttributes.add(new Attribute(NAMESPACE, hasMetadata.getMetadata().getNamespace())); - } + if (!Utils.isNullOrEmpty(hasMetadata.getMetadata().getNamespace())) { + metadataAttributes = metadataAttributes.add(new Attribute(NAMESPACE, hasMetadata.getMetadata().getNamespace())); + } if (hasMetadata.getMetadata().getLabels() != null) { for (Map.Entry label : hasMetadata.getMetadata().getLabels().entrySet()) { metadataAttributes = metadataAttributes.add(new Attribute(LABEL_KEY_PREFIX + label.getKey(), label.getValue())); } } + if (!Utils.isNullOrEmpty(hasMetadata.getKind())) { + String kind = hasMetadata.getKind().toLowerCase(Locale.ROOT); + metadataAttributes = metadataAttributes.add(new Attribute(KIND, kind)); + if (hasMetadata instanceof GenericKubernetesResource) { + pluralToKind.put(getPluralForKind(hasMetadata.getKind(), hasMetadata.getApiVersion()), kind); + } else { + pluralToKind.put(hasMetadata.getPlural(), kind); + } + } return metadataAttributes; } @@ -217,37 +221,29 @@ private Map extract(Matcher m) { return attributes; } - private String resolveKindFromPlural(String kind) { - String result = getCustomResourceKindFromPlural(kind); + private String resolveKindFromPlural(String plural) { + String result = getCustomResourceKindFromPlural(plural); if (result != null) { return result; } - return getKindFromPluralForKubernetesTypes(kind); + return pluralToKind.getOrDefault(plural, plural.substring(0, plural.length() - 1)); } - private static String getKindFromPluralForKubernetesTypes(String kind) { - //Poor mans to singular. - //Special Case for PodSecurityPolicies and NetworkPolicies because - //we need to return PodSecurityPolicy and NetworkPolicy respectively - //because it is returning PodSecurityPolicie and NetworkPolicie now - //Right now not adding generalised case of "ies" because it may break other resource not sure - - if (kind.endsWith("ses")) { - kind = kind.substring(0, kind.length() - 2); - } - else if (kind.equalsIgnoreCase("PodSecurityPolicies") || - kind.equalsIgnoreCase("NetworkPolicies")){ - kind = kind.substring(0, kind.length() - 3) + "y"; - } else if (kind.equalsIgnoreCase("securityContextConstraints") || - kind.equalsIgnoreCase("endpoints")){ - // do nothing - // because its a case which is ending with s but its name is - // like that, it is not plural - } - else if (kind.endsWith("s")) { - kind = kind.substring(0, kind.length() - 1); + /** + * Find the plural for standard types by consulting the deserializer + */ + private static String getPluralForKind(String kind, String apiVersion) { + GenericKubernetesResource gkr = new GenericKubernetesResource(); + gkr.setApiVersion(apiVersion); + gkr.setKind(kind); + try { + HasMetadata result = Serialization.unmarshal(new ByteArrayInputStream(Serialization.asJson(gkr).getBytes(StandardCharsets.UTF_8))); + if (result != null) { + return result.getPlural(); + } + } catch (KubernetesClientException e) { } - return kind; + return kind + "s"; } private static AttributeSet extractQueryParameters(HttpUrl url) { @@ -301,7 +297,7 @@ static GenericKubernetesResource toKubernetesResource(String s) { private String getCustomResourceKindFromPlural(String plural) { CustomResourceDefinitionContext crdContext = crdContexts.get(plural); - return crdContext != null && crdContext.getKind() != null ? crdContext.getKind().toLowerCase() : null; + return crdContext != null && crdContext.getKind() != null ? crdContext.getKind().toLowerCase(Locale.ROOT) : null; } /** diff --git a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractor.java b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractor.java deleted file mode 100644 index ae727de32fb..00000000000 --- a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractor.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (C) 2015 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.fabric8.kubernetes.client.server.mock; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; -import io.fabric8.mockwebserver.crud.AttributeSet; - -import java.util.Collections; -import java.util.List; - -public class KubernetesCrudAttributesExtractor extends KubernetesAttributesExtractor { - public KubernetesCrudAttributesExtractor() { - super(Collections.emptyList()); - } - - public KubernetesCrudAttributesExtractor(List crdContexts) { - super(crdContexts); - } - - @Override - public AttributeSet extract(HasMetadata hasMetadata) { - return extractMetadataAttributes(hasMetadata); - } -} diff --git a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudDispatcher.java b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudDispatcher.java index b451caa0c3c..a194dce6a74 100644 --- a/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudDispatcher.java +++ b/kubernetes-server-mock/src/main/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudDispatcher.java @@ -28,7 +28,6 @@ import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; import io.fabric8.kubernetes.client.dsl.base.OperationSupport; -import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import io.fabric8.mockwebserver.Context; @@ -88,10 +87,10 @@ public KubernetesCrudDispatcher() { } public KubernetesCrudDispatcher(List crdContexts) { - this(new KubernetesCrudAttributesExtractor(crdContexts), new KubernetesResponseComposer()); + this(new KubernetesAttributesExtractor(crdContexts), new KubernetesResponseComposer()); } - public KubernetesCrudDispatcher(KubernetesCrudAttributesExtractor attributeExtractor, ResponseComposer responseComposer) { + public KubernetesCrudDispatcher(KubernetesAttributesExtractor attributeExtractor, ResponseComposer responseComposer) { super(new Context(Serialization.jsonMapper()), attributeExtractor, responseComposer); this.kubernetesAttributesExtractor = attributeExtractor; crdProcessor = new CustomResourceDefinitionProcessor(kubernetesAttributesExtractor); @@ -513,7 +512,10 @@ private MockResponse getUnprocessableEntityMockResponse(String s, HasMetadata h, } private String getStatusBody(HasMetadata h, int code, Exception ex) { - String kind = Utils.getNonNullOrElse(KubernetesResourceUtil.getKind(h), "Unknown"); + String kind = "Unknown"; + if (h != null && Utils.isNotNullOrEmpty(h.getKind())) { + kind = h.getKind(); + } Status status = new StatusBuilder().withStatus("Failure") .withReason("Invalid") .withMessage(kind + " is invalid") diff --git a/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractorTest.java b/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractorTest.java index 98c87a5a404..69d5bf89d98 100644 --- a/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractorTest.java +++ b/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesAttributesExtractorTest.java @@ -26,11 +26,12 @@ import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; import org.junit.jupiter.api.Test; - +import io.fabric8.kubernetes.api.model.EndpointsBuilder; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.extensions.IngressBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.mockwebserver.crud.Attribute; import io.fabric8.mockwebserver.crud.AttributeSet; @@ -146,6 +147,7 @@ public void shouldHandleExtensions() { @Test public void shouldHandleIngress() { KubernetesAttributesExtractor extractor = new KubernetesAttributesExtractor(); + extractor.extract(new IngressBuilder().withNewMetadata().endMetadata().build()); AttributeSet attributes = extractor.fromPath("/apis/extensions/v1beta1/namespaces/myns/ingresses/myingress"); AttributeSet expected = new AttributeSet(); @@ -158,6 +160,7 @@ public void shouldHandleIngress() { @Test public void shouldHandleEndpoints() { KubernetesAttributesExtractor extractor = new KubernetesAttributesExtractor(); + extractor.extract(new EndpointsBuilder().withNewMetadata().endMetadata().build()); AttributeSet attributes = extractor.fromPath("/api/v1/namespaces/myns/endpoints"); AttributeSet expected = new AttributeSet(); @@ -169,6 +172,7 @@ public void shouldHandleEndpoints() { @Test public void shouldHandleIngresses() { KubernetesAttributesExtractor extractor = new KubernetesAttributesExtractor(); + extractor.extract(new IngressBuilder().withNewMetadata().endMetadata().build()); AttributeSet attributes = extractor.fromPath("/apis/extensions/v1beta1/namespaces/myns/ingresses"); AttributeSet expected = new AttributeSet(); diff --git a/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractorTest.java b/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractorTest.java deleted file mode 100644 index 9650c493a1b..00000000000 --- a/kubernetes-server-mock/src/test/java/io/fabric8/kubernetes/client/server/mock/KubernetesCrudAttributesExtractorTest.java +++ /dev/null @@ -1,600 +0,0 @@ -/** - * Copyright (C) 2015 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.fabric8.kubernetes.client.server.mock; - -import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.PodList; -import io.fabric8.kubernetes.api.model.PodStatusBuilder; -import io.fabric8.kubernetes.api.model.apps.Deployment; -import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientException; -import io.fabric8.kubernetes.client.Watch; -import io.fabric8.kubernetes.client.Watcher; -import io.fabric8.kubernetes.client.WatcherException; -import io.fabric8.kubernetes.client.dsl.MixedOperation; -import io.fabric8.kubernetes.client.dsl.PodResource; -import io.fabric8.mockwebserver.crud.Attribute; -import io.fabric8.mockwebserver.crud.AttributeSet; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class KubernetesCrudAttributesExtractorTest { - - @Test - public void shouldHandleNamespacedPathWithResource() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/namespaces/myns/pods/mypod"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "pod")); - expected = expected.add(new Attribute("namespace", "myns")); - expected = expected.add(new Attribute("name", "mypod")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleNamespacedPath() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/namespaces/myns/pods"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "pod")); - expected = expected.add(new Attribute("namespace", "myns")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleNonNamespacedPath() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/nodes/mynode"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "node")); - expected = expected.add(new Attribute("name", "mynode")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandlePathWithParameters() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/pods?labelSelector=testKey%3DtestValue"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "pod")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleResource() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - Pod pod = new PodBuilder().withNewMetadata().withName("mypod").withNamespace("myns").endMetadata().build(); - - AttributeSet attributes = extractor.extract(pod); - - AttributeSet expected1 = new AttributeSet(); - expected1 = expected1.add(new Attribute("kind", "pod")); - expected1 = expected1.add(new Attribute("namespace", "myns")); - expected1 = expected1.add(new Attribute("name", "mypod")); - assertFalse(attributes.matches(expected1)); - - AttributeSet expected2 = new AttributeSet(); - expected2 = expected2.add(new Attribute("namespace", "myns")); - expected2 = expected2.add(new Attribute("name", "mypod")); - assertTrue(attributes.matches(expected2)); - } - - @Test - public void shouldHandleResourceWithLabel() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - Map labels = new HashMap<>(); - labels.put("name", "myname"); - Pod pod = new PodBuilder().withNewMetadata().withLabels(labels).endMetadata().build(); - - AttributeSet attributes = extractor.extract(pod); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("labels:name", "myname")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleKindWithoutVersion() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/pods"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "pod")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleExtensions() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/apis/apps/v1/deployments"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "deployment")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleIngress() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/apis/extensions/v1beta1/namespaces/myns/ingresses/myingress"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "ingress")); - expected = expected.add(new Attribute("namespace", "myns")); - expected = expected.add(new Attribute("name", "myingress")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleEndpoints() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/namespaces/myns/endpoints"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "endpoints")); - expected = expected.add(new Attribute("namespace", "myns")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleIngresses() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/apis/extensions/v1beta1/namespaces/myns/ingresses"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "ingress")); - expected = expected.add(new Attribute("namespace", "myns")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleApiGroups() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor - .fromPath("/apis/autoscaling/v1/namespaces/myns/horizontalpodautoscalers/myhpa"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "horizontalpodautoscaler")); - expected = expected.add(new Attribute("namespace", "myns")); - expected = expected.add(new Attribute("name", "myhpa")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleCrds() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/apis/test.com/v1/namespaces/myns/crds/mycrd"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("kind", "crd")); - expected = expected.add(new Attribute("namespace", "myns")); - expected = expected.add(new Attribute("name", "mycrd")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleLabelSelectorsWithOneLabel() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromPath("/api/v1/namespaces/myns/pods/mypod?labelSelector=name%3Dmyname"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("labels:name", "myname")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleLabelSelectorsWithDoubleEquals() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor - .fromPath("/api/v1/namespaces/myns/pods/mypod?labelSelector=name%3D%3Dmyname"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("labels:name", "myname")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleLabelSelectorsWithTwoLabels() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor - .fromPath("/api/v1/namespaces/myns/pods/mypod?labelSelector=name%3Dmyname,age%3D37"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("labels:name", "myname")); - expected = expected.add(new Attribute("labels:age", "37")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldHandleLabelSelectorsWithADomain() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor - .fromPath("/api/v1/namespaces/myns/pods/mypod?labelSelector=example.com/name%3Dmyname"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("labels:example.com/name", "myname")); - assertTrue(attributes.matches(expected)); - } - - @Test - public void shouldGenerateMetadata() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withGenerateName("prefix") - .endMetadata().build(); - kubernetesClient.apps().deployments().create(deployment1); - - Deployment result = kubernetesClient.apps().deployments().list() - .getItems().get(0); - - assertTrue(result.getMetadata().getName().startsWith("prefix")); - assertNotNull(result.getMetadata().getNamespace()); - assertNotNull(result.getMetadata().getUid()); - assertNotNull(result.getMetadata().getResourceVersion()); - assertNotNull(result.getMetadata().getCreationTimestamp()); - assertNotNull(result.getMetadata().getGeneration()); - } - - @Test - public void replaceNonExistent() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .withStatus(new PodStatusBuilder().withHostIP("x").build()) - .build(); - PodResource podResource = kubernetesClient.pods().inNamespace("test").withName("name"); - KubernetesClientException result = assertThrows(KubernetesClientException.class, - () -> podResource.replace(pod)); - assertEquals(HttpURLConnection.HTTP_NOT_FOUND, result.getCode()); - } - - @Test - void nonSubresourceStatusHandling() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .withStatus(new PodStatusBuilder().withHostIP("x").build()) - .build(); - Pod result = kubernetesClient.pods().create(pod); - - // should be non-null after create because it's not a crd marked as a status subresource - assertNotNull(result.getStatus()); - - Map labels = new HashMap<>(); - labels.put("app", "core"); - - pod.getMetadata().setLabels(labels); - - result = kubernetesClient.pods() - .inNamespace(pod.getMetadata().getNamespace()) - .withName(pod.getMetadata().getName()) - .replace(pod); - - String originalUid = result.getMetadata().getUid(); - - // should be non-null after replace - assertNotNull(result.getStatus()); - - // should be a no-op - assertNotNull(kubernetesClient.pods().replaceStatus(pod).getStatus()); - - labels.put("other", "label"); - pod.getStatus().setHostIP("y"); - result = kubernetesClient.pods() - .inNamespace(pod.getMetadata().getNamespace()) - .withName(pod.getMetadata().getName()) - .replace(pod); - - // should replace the existing - assertEquals("y", result.getStatus().getHostIP()); - - labels.put("another", "label"); - pod.getStatus().setHostIP("z"); - result = kubernetesClient.pods() - .inNamespace(pod.getMetadata().getNamespace()) - .withName(pod.getMetadata().getName()) - .patch(pod); - - // should replace the existing - assertEquals("z", result.getStatus().getHostIP()); - - assertEquals(originalUid, result.getMetadata().getUid()); - } - - @Test - public void jsonPatchStatus() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .build(); - Pod result = kubernetesClient.pods().create(pod); - - // should be null after create - assertNull(result.getStatus()); - - pod.setStatus(new PodStatusBuilder().withHostIP("1.2.3.4").build()); - Map labels = new HashMap<>(); - labels.put("app", "core"); - - pod.getMetadata().setLabels(labels); - - result = kubernetesClient.pods() - .inNamespace(pod.getMetadata().getNamespace()) - .withName(pod.getMetadata().getName()) - .editStatus(p->pod); - - assertNotNull(result.getStatus().getHostIP()); - assertNull(result.getMetadata().getLabels()); - } - - /** - * merge patch is not supported yet - */ - @Test - public void patchStatus() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .build(); - Pod result = kubernetesClient.pods().create(pod); - - // should be null after create - assertNull(result.getStatus()); - - pod.setStatus(new PodStatusBuilder().withHostIP("1.2.3.4").build()); - Map labels = new HashMap<>(); - labels.put("app", "core"); - - pod.getMetadata().setLabels(labels); - - KubernetesClientException exception = assertThrows(KubernetesClientException.class, () -> kubernetesClient.pods() - .inNamespace(pod.getMetadata().getNamespace()) - .withName(pod.getMetadata().getName()) - .patchStatus(pod)); - Assertions.assertEquals(HttpURLConnection.HTTP_UNSUPPORTED_TYPE, exception.getCode()); - - } - - @Test - public void createConflict() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .withStatus(new PodStatusBuilder().withHostIP("x").build()) - .build(); - MixedOperation> podOp = kubernetesClient.pods(); - podOp.create(pod); - KubernetesClientException exception = assertThrows(KubernetesClientException.class, () -> podOp.create(pod)); - Assertions.assertEquals(HttpURLConnection.HTTP_CONFLICT, exception.getCode()); - } - - @Test - public void testDuplicateUpdateEvent() throws Exception { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Pod pod = new PodBuilder().withNewMetadata() - .withName("name") - .endMetadata() - .withStatus(new PodStatusBuilder().withHostIP("x").build()) - .build(); - CountDownLatch latch = new CountDownLatch(1); - AtomicBoolean updated = new AtomicBoolean(); - Watcher watcher = new Watcher () { - - @Override - public void eventReceived(Action action, Pod resource) { - if (action == Action.DELETED) { - latch.countDown(); - } - if (action == Action.MODIFIED) { - updated.set(true); - } - } - - @Override - public void onClose(WatcherException cause) { - - } - - }; - Watch watch = kubernetesClient.pods().watch(watcher); - try { - MixedOperation> podOp = kubernetesClient.pods(); - podOp.create(pod); - // should not emit an event - podOp.createOrReplace(pod); - podOp.delete(pod); - latch.await(10, TimeUnit.SECONDS); - assertFalse(updated.get()); - } finally { - watch.close(); - } - } - - // https://github.com/fabric8io/kubernetes-client/issues/1688 - - @Test - public void getDeploymentsWithLabels() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Map labels = new HashMap<>(); - labels.put("app", "core"); - labels.put("apiVersion", "1.7.1"); - labels.put("keepUntil", "12000"); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withName("withKeepUntil").addToLabels(labels) - .endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment1); - - labels.remove("keepUntil"); - Deployment deployment2 = new DeploymentBuilder().withNewMetadata().withName("withoutKeepUntil") - .addToLabels(labels).endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment2); - - List deployments = kubernetesClient.apps().deployments().withLabel("app", "core").list().getItems(); - assertTrue(deployments.stream().filter(d -> d.getMetadata().getName().equals("withKeepUntil")).findFirst() - .isPresent()); - assertTrue(deployments.stream().filter(d -> d.getMetadata().getName().equals("withoutKeepUntil")).findFirst() - .isPresent()); - } - - @Test - public void getDeploymentsWithoutLabels() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Map labels = new HashMap<>(); - labels.put("app", "core"); - labels.put("apiVersion", "1.7.1"); - labels.put("keepUntil", "12000"); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withName("withKeepUntil").addToLabels(labels) - .endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment1); - - labels.remove("keepUntil"); - Deployment deployment2 = new DeploymentBuilder().withNewMetadata().withName("withoutKeepUntil") - .addToLabels(labels).endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment2); - - List deployments = kubernetesClient.apps().deployments().withoutLabel("keepUntil", "12000").list() - .getItems(); - assertFalse(deployments.stream().filter(d -> d.getMetadata().getName().equals("withKeepUntil")).findFirst() - .isPresent()); - assertTrue(deployments.stream().filter(d -> d.getMetadata().getName().equals("withoutKeepUntil")).findFirst() - .isPresent()); - } - - @Test - public void getDeploymentsWithAndWithoutLabels() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Map labels = new HashMap<>(); - labels.put("app", "core"); - labels.put("apiVersion", "1.7.1"); - labels.put("keepUntil", "12000"); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withName("withKeepUntil").addToLabels(labels) - .endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment1); - - labels.remove("keepUntil"); - Deployment deployment2 = new DeploymentBuilder().withNewMetadata().withName("withoutKeepUntil") - .addToLabels(labels).endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment2); - - List deployments = kubernetesClient.apps().deployments().withLabel("app", "core") - .withoutLabel("keepUntil", "12000").list().getItems(); - assertFalse(deployments.stream().filter(d -> d.getMetadata().getName().equals("withKeepUntil")).findFirst() - .isPresent()); - assertTrue(deployments.stream().filter(d -> d.getMetadata().getName().equals("withoutKeepUntil")).findFirst() - .isPresent()); - } - - @Test - public void shouldFilterBasedOnLabelExists() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Map labels = new HashMap<>(); - labels.put("app", "core"); - labels.put("apiVersion", "1.7.1"); - labels.put("keepUntil", "12000"); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withName("withKeepUntil").addToLabels(labels) - .endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment1); - - labels.remove("keepUntil"); - Deployment deployment2 = new DeploymentBuilder().withNewMetadata().withName("withoutKeepUntil") - .addToLabels(labels).endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment2); - - List deployments = kubernetesClient.apps().deployments().withLabel("keepUntil").list().getItems(); - assertTrue(deployments.stream().anyMatch(d -> d.getMetadata().getName().equals("withKeepUntil"))); - assertTrue(deployments.stream().noneMatch(d -> d.getMetadata().getName().equals("withoutKeepUntil"))); - } - - @Test - public void shouldFilterBasedOnLabelNotExists() { - KubernetesServer kubernetesServer = new KubernetesServer(false, true); - kubernetesServer.before(); - KubernetesClient kubernetesClient = kubernetesServer.getClient(); - Map labels = new HashMap<>(); - labels.put("app", "core"); - labels.put("apiVersion", "1.7.1"); - labels.put("keepUntil", "12000"); - Deployment deployment1 = new DeploymentBuilder().withNewMetadata().withName("withKeepUntil").addToLabels(labels) - .endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment1); - - labels.remove("keepUntil"); - Deployment deployment2 = new DeploymentBuilder().withNewMetadata().withName("withoutKeepUntil") - .addToLabels(labels).endMetadata().withNewStatus().withReadyReplicas(2).endStatus().build(); - kubernetesClient.apps().deployments().create(deployment2); - - List deployments = kubernetesClient.apps().deployments().withoutLabel("keepUntil").list().getItems(); - assertEquals(1, deployments.size()); - assertEquals("withoutKeepUntil", deployments.get(0).getMetadata().getName()); - } - - @Test - public void shouldExtractRawMetadata() { - KubernetesCrudAttributesExtractor extractor = new KubernetesCrudAttributesExtractor(); - AttributeSet attributes = extractor.fromResource("{\"apiVersion\":1, \"kind\":\"mykind\", \"metadata\":{\"name\":\"foo\",\"uid\":\"1b089078-51c7-4ff8-a3c9-a8a54246b94c\",\"resourceVersion\":\"1\",\"generation\":1,\"creationTimestamp\":\"2021-05-13T12:06:41.191989Z\"},\"spec\":\"initial\"}"); - - AttributeSet expected = new AttributeSet(); - expected = expected.add(new Attribute("name", "foo")); - assertTrue(attributes.matches(expected)); - } - -}