diff --git a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/RawCustomResourceIT.java b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/RawCustomResourceIT.java index 88c92afab58..0aec6d7ed10 100644 --- a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/RawCustomResourceIT.java +++ b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/RawCustomResourceIT.java @@ -16,13 +16,29 @@ package io.fabric8.kubernetes; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import io.fabric8.kubernetes.api.model.Status; +import io.fabric8.kubernetes.client.Watcher; +import io.fabric8.kubernetes.client.WatcherException; +import io.fabric8.kubernetes.client.utils.Serialization; +import org.apache.commons.io.FileUtils; import org.arquillian.cube.kubernetes.api.Session; import org.arquillian.cube.kubernetes.impl.requirement.RequiresKubernetes; import org.arquillian.cube.requirement.ArquillianConditionalRunner; @@ -79,14 +95,12 @@ public void testCrud() throws IOException { "\"kind\":\"Animal\",\"metadata\": {\"name\": \"walrus\"}," + "\"spec\": {\"image\": \"my-awesome-walrus-image\"}}"; object = client.customResource(customResourceDefinitionContext).createOrReplace(currentNamespace, rawJsonCustomResourceObj); - assertThat(((HashMap)object.get("metadata")).get("name")).isEqualTo("walrus"); - assertThat(((HashMap)object.get("spec")).get("image")).isEqualTo("my-awesome-walrus-image"); + assertAnimal(object, "walrus", "my-awesome-walrus-image"); // Test replace with object ((HashMap)object.get("spec")).put("image", "new-walrus-image"); object = client.customResource(customResourceDefinitionContext).createOrReplace(currentNamespace, object); - assertThat(((HashMap)object.get("metadata")).get("name")).isEqualTo("walrus"); - assertThat(((HashMap)object.get("spec")).get("image")).isEqualTo("new-walrus-image"); + assertAnimal(object, "walrus", "new-walrus-image"); // Test Get: object = client.customResource(customResourceDefinitionContext).get(currentNamespace, "otter"); @@ -104,16 +118,164 @@ public void testCrud() throws IOException { object = client.customResource(customResourceDefinitionContext).get(currentNamespace, "walrus"); ((HashMap)object.get("spec")).put("image", "my-updated-awesome-walrus-image"); object = client.customResource(customResourceDefinitionContext).edit(currentNamespace, "walrus", new ObjectMapper().writeValueAsString(object)); - assertThat(((HashMap)object.get("spec")).get("image")).isEqualTo("my-updated-awesome-walrus-image"); + assertAnimal(object, "walrus", "my-updated-awesome-walrus-image"); // Test Delete: client.customResource(customResourceDefinitionContext).delete(currentNamespace, "otter"); client.customResource(customResourceDefinitionContext).delete(currentNamespace); } + @Test + public void testCrudUsingMap() throws IOException { + // Create + String name = "bison"; + Map bison = createNewAnimal(name, "wisent"); + bison = client.customResource(customResourceDefinitionContext).create(currentNamespace, bison); + assertAnimal(bison, "bison", "wisent"); + + // Read + bison = client.customResource(customResourceDefinitionContext).get(currentNamespace, name); + assertAnimal(bison, "bison", "wisent"); + + // Update + ((Map)bison.get("spec")).put("image", "bison-bonasus"); + bison = client.customResource(customResourceDefinitionContext).edit(currentNamespace, name, bison); + assertAnimal(bison, "bison", "bison-bonasus"); + + // Delete + Map deletionStatusMap = client.customResource(customResourceDefinitionContext).delete(currentNamespace, name); + assertDeletionStatus(deletionStatusMap, "Success"); + } + + @Test + public void testCrudUsingInputStream() throws IOException { + // Create + String name = "hippo"; + InputStream hippoInputStream = getClass().getResourceAsStream("/rawcustomresourceit-crud-inputstream.yml"); + Map hippoCr = client.customResource(customResourceDefinitionContext).create(currentNamespace, hippoInputStream); + assertAnimal(hippoCr, name, "Hippopotamidae"); + + // Read + hippoCr = client.customResource(customResourceDefinitionContext).get(currentNamespace, name); + assertAnimal(hippoCr, name, "Hippopotamidae"); + + // Update + ((Map)hippoCr.get("spec")).put("image", "river-hippo"); + File updatedHippoManifest = Files.createTempFile("hippo", "yml").toFile(); + FileUtils.writeStringToFile(updatedHippoManifest, Serialization.jsonMapper().writeValueAsString(hippoCr)); + hippoCr = client.customResource(customResourceDefinitionContext).edit(currentNamespace, name, new FileInputStream(updatedHippoManifest)); + assertAnimal(hippoCr, name, "river-hippo"); + + // Delete + Map deletionStatusMap = client.customResource(customResourceDefinitionContext).delete(currentNamespace, name); + assertDeletionStatus(deletionStatusMap, "Success"); + } + + @Test + public void testCrudUsingString() throws IOException { + // Create + String name = "rhino"; + String rhino = "{\"apiVersion\": \"jungle.example.com/v1\"," + + " \"kind\": \"Animal\"," + + " \"metadata\": {\"name\": \"rhino\"}," + + " \"spec\": {\"image\": \"Rhinocerotidae\"}}"; + Map rhinoCr = client.customResource(customResourceDefinitionContext).create(currentNamespace, rhino); + assertAnimal(rhinoCr, name, "Rhinocerotidae"); + + // Read + rhinoCr = client.customResource(customResourceDefinitionContext).get(currentNamespace, name); + assertAnimal(rhinoCr, name, "Rhinocerotidae"); + + // Update + ((Map)rhinoCr.get("spec")).put("image", "rhinoceros"); + String rhinoCrAsStr = Serialization.jsonMapper().writeValueAsString(rhinoCr); + rhinoCr = client.customResource(customResourceDefinitionContext).edit(currentNamespace, name, rhinoCrAsStr); + assertAnimal(rhinoCr, name, "rhinoceros"); + + // Delete + Map deletionStatusMap = client.customResource(customResourceDefinitionContext).delete(currentNamespace, name); + assertDeletionStatus(deletionStatusMap, "Success"); + } + + @Test + public void testWatch() throws IOException, InterruptedException { + // Given + String name = "chital"; + Map deer = createNewAnimal(name, "spotted-deer"); + CountDownLatch creationEventReceived = new CountDownLatch(1); + + // When + client.customResource(customResourceDefinitionContext).watch(currentNamespace, new Watcher() { + @Override + public void eventReceived(Action action, String resource) { + if (resource.contains(name)) { + creationEventReceived.countDown(); + } + } + + @Override + public void onClose(WatcherException cause) { } + }); + client.customResource(customResourceDefinitionContext).create(currentNamespace, deer); + + // Then + assertTrue(creationEventReceived.await(1, TimeUnit.SECONDS)); + } + + @Test + public void testUpdateStatus() throws IOException { + // Given + String name = "black-buck"; + Map deer = createNewAnimal(name, "indian-antelope"); + Map status = new HashMap<>(); + status.put("conservationStatus", "endangered"); + + // When + deer = client.customResource(customResourceDefinitionContext).create(currentNamespace, deer); + await().atMost(5, TimeUnit.SECONDS) + .until(() -> client.customResource(customResourceDefinitionContext).get(currentNamespace, name) != null); + deer.put("status", status); + Map updatedDeer = client.customResource(customResourceDefinitionContext).updateStatus(currentNamespace, name, deer); + + // Then + assertNotNull(updatedDeer); + assertEquals("endangered", ((Map)deer.get("status")).get("conservationStatus").toString()); + } + @After public void cleanup() { // Delete Custom Resource Definition Animals: client.apiextensions().v1beta1().customResourceDefinitions().withName(customResourceDefinitionContext.getName()).delete(); + + } + + private void assertAnimal(Map animal, String name, String image) { + assertNotNull(animal); + assertFalse(animal.isEmpty()); + assertThat(((HashMap)animal.get("metadata")).get("name")).isEqualTo(name); + assertThat(((HashMap)animal.get("spec")).get("image")).isEqualTo(image); + } + + private void assertDeletionStatus(Map deletionStatusAsMap, String status) { + Status deletionStatus = Serialization.jsonMapper().convertValue(deletionStatusAsMap, Status.class); + assertNotNull(deletionStatus); + assertEquals(status, deletionStatus.getStatus()); + } + + private Map createNewAnimal(String name, String image) { + Map crAsMap = new HashMap<>(); + crAsMap.put("apiVersion", "jungle.example.com/v1"); + crAsMap.put("kind", "Animal"); + + Map crMetadata = new HashMap<>(); + crMetadata.put("name", name); + crMetadata.put("labels", Collections.singletonMap("foo", "bar")); + Map crSpec = new HashMap<>(); + crSpec.put("image", image); + + crAsMap.put("metadata", crMetadata); + crAsMap.put("spec", crSpec); + + return crAsMap; } } diff --git a/kubernetes-itests/src/test/resources/rawcustomresourceit-crud-inputstream.yml b/kubernetes-itests/src/test/resources/rawcustomresourceit-crud-inputstream.yml new file mode 100644 index 00000000000..59033bfa733 --- /dev/null +++ b/kubernetes-itests/src/test/resources/rawcustomresourceit-crud-inputstream.yml @@ -0,0 +1,22 @@ +# +# 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. +# + +apiVersion: jungle.example.com/v1 +kind: Animal +metadata: + name: hippo +spec: + image: "Hippopotamidae" diff --git a/kubernetes-itests/src/test/resources/test-rawcustomresource-definition.yml b/kubernetes-itests/src/test/resources/test-rawcustomresource-definition.yml index 4fef4df4b6f..76504e0b7ba 100644 --- a/kubernetes-itests/src/test/resources/test-rawcustomresource-definition.yml +++ b/kubernetes-itests/src/test/resources/test-rawcustomresource-definition.yml @@ -26,6 +26,8 @@ spec: served: true storage: true scope: Namespaced + subresources: + status: {} names: plural: animals singular: animals