Loading src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java +3 −3 Original line number Diff line number Diff line Loading @@ -429,7 +429,7 @@ public class KubernetesClientResource { // logger.debug("Deploy the following CR NORMALIZED:" ); // logger.debug("{}", crspec ); try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { try { GenericKubernetesResource gkr = Serialization.unmarshal( crspec ); headers.forEach(((hname, hval) ->{ Loading Loading @@ -468,7 +468,7 @@ public class KubernetesClientResource { .withName( nameSpacename ) .addToLabels("org.etsi.osl", "org.etsi.osl") .endMetadata().build(); k8s.namespaces().resource(ns).create(); kubernetesClient.namespaces().resource(ns).create(); }catch (Exception e) { Loading @@ -492,7 +492,7 @@ public class KubernetesClientResource { logger.debug("Object to deploy:{}", gkr.toString() ); Resource<GenericKubernetesResource> dummyObject = k8s.resource( gkr ); Resource<GenericKubernetesResource> dummyObject = kubernetesClient.resource( gkr ); GenericKubernetesResource result = dummyObject.create(); Loading src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java +217 −29 Original line number Diff line number Diff line package org.etsi.osl.cridge; import static io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext.v1CRDFromCustomResourceType; import static org.junit.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.camel.CamelContext; import org.apache.camel.RoutesBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.dataformat.JsonLibrary; import org.apache.commons.io.IOUtils; import org.etsi.osl.tmf.ri639.model.ResourceCreate; import org.junit.Rule; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; Loading @@ -23,22 +37,43 @@ import jakarta.annotation.PostConstruct; import org.springframework.test.context.event.RecordApplicationEvents; import org.springframework.test.context.event.annotation.BeforeTestClass; import org.springframework.test.context.junit4.SpringRunner; import io.fabric8.kubernetes.api.model.Condition; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.api.model.ListMeta; import io.fabric8.kubernetes.api.model.ListMetaBuilder; import io.fabric8.kubernetes.api.model.NamedContext; import io.fabric8.kubernetes.api.model.NamedContextBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.WatchEvent; import io.fabric8.kubernetes.api.model.WatchEventBuilder; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionList; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionListBuilder; import io.fabric8.kubernetes.api.model.resource.v1alpha2.ResourceHandle; import io.fabric8.kubernetes.api.model.resource.v1alpha2.ResourceHandleBuilder; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; 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.Resource; import io.fabric8.kubernetes.client.extension.ExtensionAdapter.ClientFactory; import io.fabric8.kubernetes.client.http.HttpClient.Factory; import io.fabric8.kubernetes.client.impl.ResourceHandler; import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.SharedInformerFactory; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesClientBuilderCustomizer; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.kubernetes.client.server.mock.KubernetesServer; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.internal.KubernetesDeserializer; import io.fabric8.kubernetes.client.impl.Handlers; @RecordApplicationEvents @RunWith(SpringRunner.class) Loading @@ -57,6 +92,9 @@ public class CridgeIntegrationTest { private static KubernetesMockServer server; @Autowired KubernetesClientResource kubernetesClientResource; @Autowired CatalogClient catalogClient; Loading @@ -72,10 +110,10 @@ public class CridgeIntegrationTest { private SCMocked scmocked = new SCMocked(); private KubernetesClient kubernetesClient; private static KubernetesClient kubernetesClient; @Autowired KubernetesClientResource aKubernetesClientResource; KubernetesClientResource kubernetesClientResource; RoutesBuilder builder = new RouteBuilder() { @Override Loading Loading @@ -107,7 +145,7 @@ public class CridgeIntegrationTest { kubernetesClient.getConfiguration().setCurrentContext(nctx); aKubernetesClientResource.setKubernetesClient(kubernetesClient); kubernetesClientResource.setKubernetesClient(kubernetesClient); logger.info("Starting preparedForTheTest kubernetesClient.toString() {} ", kubernetesClient.toString()); logger.info("Starting preparedForTheTest for cluster getContexts {} ", Loading @@ -116,23 +154,18 @@ public class CridgeIntegrationTest { ListMeta metada = new ListMetaBuilder().build(); // Given CustomResourceDefinitionList list = new CustomResourceDefinitionListBuilder() .withMetadata(metada ) .build(); CustomResourceDefinitionList list = new CustomResourceDefinitionListBuilder().withMetadata(metada).build(); // the following expects are for the sharedIndexInformers in the beginning server.expect() .get() server.expect().get() .withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions?resourceVersion=0") .andReturn(HttpURLConnection.HTTP_OK, list ) .once(); .andReturn(HttpURLConnection.HTTP_OK, list).once(); server.expect() .get() .withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, list ) .once(); server.expect().get().withPath( "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, list).once(); try { camelContext.addRoutes(builder); Loading @@ -142,21 +175,176 @@ public class CridgeIntegrationTest { } } @BeforeTestClass public void beforeTestClass(ContextRefreshedEvent event) { logger.info("=============== beforeTestClass ============================="); @Test public void testCRDRegister() throws Exception { logger.info("===============TEST testCRDRegister ============================="); CustomResourceDefinition crdMyCalc = v1CRDFromCustomResourceType(MyCalculator.class).build(); server.expect().post().withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); // When CustomResourceDefinition createdCronTabCrd = routesPreparation.kubernetesClient.apiextensions() .v1().customResourceDefinitions().resource(crdMyCalc).create(); // Then assertNotNull(createdCronTabCrd); } } @Test public void testCRDEPLOY() throws Exception { logger.info("===============TEST testCRDEPLOY ============================="); // CustomResourceDefinition cronTabCrd = routesPreparation.kubernetesClient.apiextensions().v1() // .customResourceDefinitions() // .load(new BufferedInputStream(new FileInputStream("src/test/resources/crontab-crd.yaml"))) // .item(); //prepare CR_SPEC request CustomResourceDefinition crdMyCalc = v1CRDFromCustomResourceType(MyCalculator.class).build(); Map<String, Object> map = new HashMap<>(); map.put("currentContextCluster", "testCluster"); map.put("clusterMasterURL", server.getHostName()); map.put("org.etsi.osl.serviceId", "sid-xxx-xxx-xxx"); map.put("org.etsi.osl.resourceId", "rid-xxx-xxx-xxx"); map.put("org.etsi.osl.prefixName", "crrid12345"); map.put("org.etsi.osl.serviceOrderId", "orderid-xxx-xxx-xxx"); map.put("org.etsi.osl.namespace", "orderid-xxx-xxx-xxx"); map.put("org.etsi.osl.statusCheckFieldName", "_CR_CHECK_FIELD"); map.put("org.etsi.osl.statusCheckValueStandby", "_CR_CHECKVAL_STANDBY"); map.put("org.etsi.osl.statusCheckValueAlarm", "_CR_CHECKVAL_ALARM"); map.put("org.etsi.osl.statusCheckValueAvailable", "_CR_CHECKVAL_AVAILABLE"); map.put("org.etsi.osl.statusCheckValueReserved", "_CR_CHECKVAL_RESERVED"); map.put("org.etsi.osl.statusCheckValueUnknown", "_CR_CHECKVAL_UNKNOWN"); map.put("org.etsi.osl.statusCheckValueSuspended", "_CR_CHECKVAL_SUSPENDED"); String _CR_SPEC = Serialization.asYaml(getMyCalculator("test-resource")); //First check for an invalid context cluster String response = kubernetesClientResource.deployCR(map, _CR_SPEC); assertEquals("SEE OTHER", response); //Now try for the correct context cluster map.put("currentContextCluster", kubernetesClientResource.getKubernetesContextDefinition().getCurrentContextCluster()); map.put("clusterMasterURL", kubernetesClientResource.getKubernetesContextDefinition().getMasterURL()); // server api expectations server.expect().get() .withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?resourceVersion=0") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get().withPath( "/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get() .withPath("/apis/stable.example.com/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get().withPath( "/apis/stable.example.com/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators/amycalculator") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().post().withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_CREATED, crdMyCalc).once(); server.expect().post() .withPath( "/apis/examples.osl.etsi.org/v1alpha1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_CREATED, crdMyCalc).once(); //register the resource handler KubernetesClient client = routesPreparation.kubernetesClient; client.getKubernetesSerialization().registerKubernetesResource("examples.osl.etsi.org/v1alpha1", "MyCalculator", MyCalculator.class); //make the deployment test! response = kubernetesClientResource.deployCR(map, _CR_SPEC); assertEquals("OK", response); } @Test public void testCatalog() throws Exception { logger.info("===============TEST testCatalog ============================="); public void testCRWithWatch() throws Exception { // useful blog // https://itnext.io/mock-kubernetes-api-server-in-java-using-fabric8-kubernetes-mock-server-81a75cf6c47c // Given KubernetesClient client = routesPreparation.kubernetesClient; server.expect().withPath( "/apis/examples.osl.etsi.org/v1alpha1/namespaces/orderid-xxx-xxx-xxx/mycalculators?allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open().waitFor(10L) .andEmit(new WatchEvent(getMyCalculator("amycalculator"), "ADDED")).waitFor(20L) .andEmit(new WatchEventBuilder().withNewStatusObject() .withMessage("410 - the event requested is outdated") .withCode(HttpURLConnection.HTTP_GONE).endStatusObject().build()) .done().always(); MixedOperation<MyCalculator, KubernetesResourceList<MyCalculator>, Resource<MyCalculator>> userAclClient = client.resources(MyCalculator.class); // When CountDownLatch eventRecieved = new CountDownLatch(1); client.getKubernetesSerialization().registerKubernetesResource("examples.osl.etsi.org/v1alpha1", "MyCalculator", MyCalculator.class); Watch watch = userAclClient.inNamespace("orderid-xxx-xxx-xxx").watch(new Watcher<MyCalculator>() { @Override public void eventReceived(Action action, MyCalculator calc) { if (action.name().contains("ADDED")) { eventRecieved.countDown(); logger.info( "===============CountDownLatch eventRecieved.countDown ADDED {}=============================", Serialization.asYaml(calc)); } } @Override public void onClose(WatcherException e) {} }); // Then eventRecieved.await(30, TimeUnit.SECONDS); Assertions.assertEquals(0, eventRecieved.getCount()); watch.close(); } private KubernetesResource getMyCalculator(String resourceName) { MyCalculatorSpec spec = new MyCalculatorSpec(); spec.setAction("amycalculator"); MyCalculator createdMyCalcL = new MyCalculator(); createdMyCalcL.setMetadata(new ObjectMetaBuilder().withName(resourceName).build()); createdMyCalcL.setSpec(spec); Condition condition = new Condition(); condition.setMessage("Last reconciliation succeeded"); condition.setReason("Successful"); condition.setStatus("True"); condition.setType("Successful"); MyCalculatorStatus status = new MyCalculatorStatus(); status.setCondition(new Condition[] {condition}); createdMyCalcL.setStatus(status); return createdMyCalcL; } Loading src/test/java/org/etsi/osl/cridge/MyCalculator.java 0 → 100644 +13 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.client.CustomResource; import io.fabric8.kubernetes.model.annotation.Group; import io.fabric8.kubernetes.model.annotation.Version; @Version("v1alpha1") // -> CRD Version @Group("examples.osl.etsi.org") // -> CRD Group public class MyCalculator // -> CRD Kind (if not provided in @Kind annotation) extends CustomResource<MyCalculatorSpec, MyCalculatorStatus> implements Namespaced { } // -> CRD scope Namespaced No newline at end of file src/test/java/org/etsi/osl/cridge/MyCalculatorSpec.java 0 → 100644 +47 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; public class MyCalculatorSpec { private int parama; private int paramb; private String action; /** * @return the parama */ public int getParama() { return parama; } /** * @param parama the parama to set */ public void setParama(int parama) { this.parama = parama; } /** * @return the paramb */ public int getParamb() { return paramb; } /** * @param paramb the paramb to set */ public void setParamb(int paramb) { this.paramb = paramb; } /** * @return the action */ public String getAction() { return action; } /** * @param action the action to set */ public void setAction(String action) { this.action = action; } } No newline at end of file src/test/java/org/etsi/osl/cridge/MyCalculatorStatus.java 0 → 100644 +54 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; import io.fabric8.kubernetes.api.model.Condition; public class MyCalculatorStatus { private int result; private String status; Condition[] condition; /** * @return the result */ public int getResult() { return result; } /** * @param result the result to set */ public void setResult(int result) { this.result = result; } /** * @return the status */ public String getStatus() { return status; } /** * @param status the status to set */ public void setStatus(String status) { this.status = status; } /** * @return the condition */ public Condition[] getCondition() { return condition; } /** * @param condition the condition to set */ public void setCondition(Condition[] condition) { this.condition = condition; } } Loading
src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java +3 −3 Original line number Diff line number Diff line Loading @@ -429,7 +429,7 @@ public class KubernetesClientResource { // logger.debug("Deploy the following CR NORMALIZED:" ); // logger.debug("{}", crspec ); try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { try { GenericKubernetesResource gkr = Serialization.unmarshal( crspec ); headers.forEach(((hname, hval) ->{ Loading Loading @@ -468,7 +468,7 @@ public class KubernetesClientResource { .withName( nameSpacename ) .addToLabels("org.etsi.osl", "org.etsi.osl") .endMetadata().build(); k8s.namespaces().resource(ns).create(); kubernetesClient.namespaces().resource(ns).create(); }catch (Exception e) { Loading @@ -492,7 +492,7 @@ public class KubernetesClientResource { logger.debug("Object to deploy:{}", gkr.toString() ); Resource<GenericKubernetesResource> dummyObject = k8s.resource( gkr ); Resource<GenericKubernetesResource> dummyObject = kubernetesClient.resource( gkr ); GenericKubernetesResource result = dummyObject.create(); Loading
src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java +217 −29 Original line number Diff line number Diff line package org.etsi.osl.cridge; import static io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext.v1CRDFromCustomResourceType; import static org.junit.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.camel.CamelContext; import org.apache.camel.RoutesBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.dataformat.JsonLibrary; import org.apache.commons.io.IOUtils; import org.etsi.osl.tmf.ri639.model.ResourceCreate; import org.junit.Rule; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; Loading @@ -23,22 +37,43 @@ import jakarta.annotation.PostConstruct; import org.springframework.test.context.event.RecordApplicationEvents; import org.springframework.test.context.event.annotation.BeforeTestClass; import org.springframework.test.context.junit4.SpringRunner; import io.fabric8.kubernetes.api.model.Condition; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.api.model.ListMeta; import io.fabric8.kubernetes.api.model.ListMetaBuilder; import io.fabric8.kubernetes.api.model.NamedContext; import io.fabric8.kubernetes.api.model.NamedContextBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.WatchEvent; import io.fabric8.kubernetes.api.model.WatchEventBuilder; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionList; import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionListBuilder; import io.fabric8.kubernetes.api.model.resource.v1alpha2.ResourceHandle; import io.fabric8.kubernetes.api.model.resource.v1alpha2.ResourceHandleBuilder; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; 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.Resource; import io.fabric8.kubernetes.client.extension.ExtensionAdapter.ClientFactory; import io.fabric8.kubernetes.client.http.HttpClient.Factory; import io.fabric8.kubernetes.client.impl.ResourceHandler; import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.SharedInformerFactory; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesClientBuilderCustomizer; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.kubernetes.client.server.mock.KubernetesServer; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.internal.KubernetesDeserializer; import io.fabric8.kubernetes.client.impl.Handlers; @RecordApplicationEvents @RunWith(SpringRunner.class) Loading @@ -57,6 +92,9 @@ public class CridgeIntegrationTest { private static KubernetesMockServer server; @Autowired KubernetesClientResource kubernetesClientResource; @Autowired CatalogClient catalogClient; Loading @@ -72,10 +110,10 @@ public class CridgeIntegrationTest { private SCMocked scmocked = new SCMocked(); private KubernetesClient kubernetesClient; private static KubernetesClient kubernetesClient; @Autowired KubernetesClientResource aKubernetesClientResource; KubernetesClientResource kubernetesClientResource; RoutesBuilder builder = new RouteBuilder() { @Override Loading Loading @@ -107,7 +145,7 @@ public class CridgeIntegrationTest { kubernetesClient.getConfiguration().setCurrentContext(nctx); aKubernetesClientResource.setKubernetesClient(kubernetesClient); kubernetesClientResource.setKubernetesClient(kubernetesClient); logger.info("Starting preparedForTheTest kubernetesClient.toString() {} ", kubernetesClient.toString()); logger.info("Starting preparedForTheTest for cluster getContexts {} ", Loading @@ -116,23 +154,18 @@ public class CridgeIntegrationTest { ListMeta metada = new ListMetaBuilder().build(); // Given CustomResourceDefinitionList list = new CustomResourceDefinitionListBuilder() .withMetadata(metada ) .build(); CustomResourceDefinitionList list = new CustomResourceDefinitionListBuilder().withMetadata(metada).build(); // the following expects are for the sharedIndexInformers in the beginning server.expect() .get() server.expect().get() .withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions?resourceVersion=0") .andReturn(HttpURLConnection.HTTP_OK, list ) .once(); .andReturn(HttpURLConnection.HTTP_OK, list).once(); server.expect() .get() .withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, list ) .once(); server.expect().get().withPath( "/apis/apiextensions.k8s.io/v1/customresourcedefinitions?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, list).once(); try { camelContext.addRoutes(builder); Loading @@ -142,21 +175,176 @@ public class CridgeIntegrationTest { } } @BeforeTestClass public void beforeTestClass(ContextRefreshedEvent event) { logger.info("=============== beforeTestClass ============================="); @Test public void testCRDRegister() throws Exception { logger.info("===============TEST testCRDRegister ============================="); CustomResourceDefinition crdMyCalc = v1CRDFromCustomResourceType(MyCalculator.class).build(); server.expect().post().withPath("/apis/apiextensions.k8s.io/v1/customresourcedefinitions") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); // When CustomResourceDefinition createdCronTabCrd = routesPreparation.kubernetesClient.apiextensions() .v1().customResourceDefinitions().resource(crdMyCalc).create(); // Then assertNotNull(createdCronTabCrd); } } @Test public void testCRDEPLOY() throws Exception { logger.info("===============TEST testCRDEPLOY ============================="); // CustomResourceDefinition cronTabCrd = routesPreparation.kubernetesClient.apiextensions().v1() // .customResourceDefinitions() // .load(new BufferedInputStream(new FileInputStream("src/test/resources/crontab-crd.yaml"))) // .item(); //prepare CR_SPEC request CustomResourceDefinition crdMyCalc = v1CRDFromCustomResourceType(MyCalculator.class).build(); Map<String, Object> map = new HashMap<>(); map.put("currentContextCluster", "testCluster"); map.put("clusterMasterURL", server.getHostName()); map.put("org.etsi.osl.serviceId", "sid-xxx-xxx-xxx"); map.put("org.etsi.osl.resourceId", "rid-xxx-xxx-xxx"); map.put("org.etsi.osl.prefixName", "crrid12345"); map.put("org.etsi.osl.serviceOrderId", "orderid-xxx-xxx-xxx"); map.put("org.etsi.osl.namespace", "orderid-xxx-xxx-xxx"); map.put("org.etsi.osl.statusCheckFieldName", "_CR_CHECK_FIELD"); map.put("org.etsi.osl.statusCheckValueStandby", "_CR_CHECKVAL_STANDBY"); map.put("org.etsi.osl.statusCheckValueAlarm", "_CR_CHECKVAL_ALARM"); map.put("org.etsi.osl.statusCheckValueAvailable", "_CR_CHECKVAL_AVAILABLE"); map.put("org.etsi.osl.statusCheckValueReserved", "_CR_CHECKVAL_RESERVED"); map.put("org.etsi.osl.statusCheckValueUnknown", "_CR_CHECKVAL_UNKNOWN"); map.put("org.etsi.osl.statusCheckValueSuspended", "_CR_CHECKVAL_SUSPENDED"); String _CR_SPEC = Serialization.asYaml(getMyCalculator("test-resource")); //First check for an invalid context cluster String response = kubernetesClientResource.deployCR(map, _CR_SPEC); assertEquals("SEE OTHER", response); //Now try for the correct context cluster map.put("currentContextCluster", kubernetesClientResource.getKubernetesContextDefinition().getCurrentContextCluster()); map.put("clusterMasterURL", kubernetesClientResource.getKubernetesContextDefinition().getMasterURL()); // server api expectations server.expect().get() .withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?resourceVersion=0") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get().withPath( "/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get() .withPath("/apis/stable.example.com/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().get().withPath( "/apis/stable.example.com/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators/amycalculator") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); server.expect().post().withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_CREATED, crdMyCalc).once(); server.expect().post() .withPath( "/apis/examples.osl.etsi.org/v1alpha1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_CREATED, crdMyCalc).once(); //register the resource handler KubernetesClient client = routesPreparation.kubernetesClient; client.getKubernetesSerialization().registerKubernetesResource("examples.osl.etsi.org/v1alpha1", "MyCalculator", MyCalculator.class); //make the deployment test! response = kubernetesClientResource.deployCR(map, _CR_SPEC); assertEquals("OK", response); } @Test public void testCatalog() throws Exception { logger.info("===============TEST testCatalog ============================="); public void testCRWithWatch() throws Exception { // useful blog // https://itnext.io/mock-kubernetes-api-server-in-java-using-fabric8-kubernetes-mock-server-81a75cf6c47c // Given KubernetesClient client = routesPreparation.kubernetesClient; server.expect().withPath( "/apis/examples.osl.etsi.org/v1alpha1/namespaces/orderid-xxx-xxx-xxx/mycalculators?allowWatchBookmarks=true&watch=true") .andUpgradeToWebSocket().open().waitFor(10L) .andEmit(new WatchEvent(getMyCalculator("amycalculator"), "ADDED")).waitFor(20L) .andEmit(new WatchEventBuilder().withNewStatusObject() .withMessage("410 - the event requested is outdated") .withCode(HttpURLConnection.HTTP_GONE).endStatusObject().build()) .done().always(); MixedOperation<MyCalculator, KubernetesResourceList<MyCalculator>, Resource<MyCalculator>> userAclClient = client.resources(MyCalculator.class); // When CountDownLatch eventRecieved = new CountDownLatch(1); client.getKubernetesSerialization().registerKubernetesResource("examples.osl.etsi.org/v1alpha1", "MyCalculator", MyCalculator.class); Watch watch = userAclClient.inNamespace("orderid-xxx-xxx-xxx").watch(new Watcher<MyCalculator>() { @Override public void eventReceived(Action action, MyCalculator calc) { if (action.name().contains("ADDED")) { eventRecieved.countDown(); logger.info( "===============CountDownLatch eventRecieved.countDown ADDED {}=============================", Serialization.asYaml(calc)); } } @Override public void onClose(WatcherException e) {} }); // Then eventRecieved.await(30, TimeUnit.SECONDS); Assertions.assertEquals(0, eventRecieved.getCount()); watch.close(); } private KubernetesResource getMyCalculator(String resourceName) { MyCalculatorSpec spec = new MyCalculatorSpec(); spec.setAction("amycalculator"); MyCalculator createdMyCalcL = new MyCalculator(); createdMyCalcL.setMetadata(new ObjectMetaBuilder().withName(resourceName).build()); createdMyCalcL.setSpec(spec); Condition condition = new Condition(); condition.setMessage("Last reconciliation succeeded"); condition.setReason("Successful"); condition.setStatus("True"); condition.setType("Successful"); MyCalculatorStatus status = new MyCalculatorStatus(); status.setCondition(new Condition[] {condition}); createdMyCalcL.setStatus(status); return createdMyCalcL; } Loading
src/test/java/org/etsi/osl/cridge/MyCalculator.java 0 → 100644 +13 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.client.CustomResource; import io.fabric8.kubernetes.model.annotation.Group; import io.fabric8.kubernetes.model.annotation.Version; @Version("v1alpha1") // -> CRD Version @Group("examples.osl.etsi.org") // -> CRD Group public class MyCalculator // -> CRD Kind (if not provided in @Kind annotation) extends CustomResource<MyCalculatorSpec, MyCalculatorStatus> implements Namespaced { } // -> CRD scope Namespaced No newline at end of file
src/test/java/org/etsi/osl/cridge/MyCalculatorSpec.java 0 → 100644 +47 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; public class MyCalculatorSpec { private int parama; private int paramb; private String action; /** * @return the parama */ public int getParama() { return parama; } /** * @param parama the parama to set */ public void setParama(int parama) { this.parama = parama; } /** * @return the paramb */ public int getParamb() { return paramb; } /** * @param paramb the paramb to set */ public void setParamb(int paramb) { this.paramb = paramb; } /** * @return the action */ public String getAction() { return action; } /** * @param action the action to set */ public void setAction(String action) { this.action = action; } } No newline at end of file
src/test/java/org/etsi/osl/cridge/MyCalculatorStatus.java 0 → 100644 +54 −0 Original line number Diff line number Diff line package org.etsi.osl.cridge; import io.fabric8.kubernetes.api.model.Condition; public class MyCalculatorStatus { private int result; private String status; Condition[] condition; /** * @return the result */ public int getResult() { return result; } /** * @param result the result to set */ public void setResult(int result) { this.result = result; } /** * @return the status */ public String getStatus() { return status; } /** * @param status the status to set */ public void setStatus(String status) { this.status = status; } /** * @return the condition */ public Condition[] getCondition() { return condition; } /** * @param condition the condition to set */ public void setCondition(Condition[] condition) { this.condition = condition; } }