Commit 92f741f8 authored by Christos Tranoris's avatar Christos Tranoris
Browse files

a cr deployment test

parent e2e8b65a
Loading
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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) ->{
@@ -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) {
@@ -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();      
      
+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;
@@ -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)
@@ -57,6 +92,9 @@ public class CridgeIntegrationTest {

  private static KubernetesMockServer server;

  @Autowired
  KubernetesClientResource kubernetesClientResource;

  @Autowired
  CatalogClient catalogClient;

@@ -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
@@ -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 {} ",
@@ -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);
@@ -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;
  }


+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
+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
+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