From ffdb7e840b8090e57a3c5c535acffd9f9c0b2344 Mon Sep 17 00:00:00 2001 From: Dimitrios Giannopoulos Date: Fri, 30 Aug 2024 13:54:29 +0000 Subject: [PATCH 01/11] fix: strictly compare between strings --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bb7d754..40be386 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ include: - ci-templates/default.yml - ci-templates/build.yml rules: - - if: '$CI_COMMIT_REF_PROTECTED && $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "develop"' + - if: '$CI_COMMIT_REF_PROTECTED == "true" && $CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "develop"' - project: osl/code/org.etsi.osl.main ref: develop @@ -29,7 +29,7 @@ include: - ci-templates/default.yml - ci-templates/build_unprotected.yml rules: - - if: '$CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "develop" && !$CI_COMMIT_REF_PROTECTED' + - if: '$CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_PROTECTED == "false"' maven_build: extends: .maven_build -- GitLab From 0d7c637f7c8b85d060c91964e101476d54941d0b Mon Sep 17 00:00:00 2001 From: trantzas Date: Tue, 17 Sep 2024 19:30:10 +0000 Subject: [PATCH 02/11] Development preparation for release 2024Q4 --- Dockerfile | 4 ++-- pom.xml | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index f44060e..697956e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,5 +2,5 @@ FROM ibm-semeru-runtimes:open-17.0.7_7-jdk MAINTAINER openslice.io RUN mkdir /opt/shareclasses RUN mkdir -p /opt/openslice/lib/ -COPY target/org.etsi.osl.cridge-1.0.0-exec.jar /opt/openslice/lib/ -CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.0.0-exec.jar"] +COPY target/org.etsi.osl.cridge-1.1.0-SNAPSHOT-exec.jar /opt/openslice/lib/ +CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.1.0-SNAPSHOT-exec.jar"] diff --git a/pom.xml b/pom.xml index 76e6d7e..91792e1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,14 +5,20 @@ org.etsi.osl org.etsi.osl.main - 1.0.0 + 2024Q4-SNAPSHOT ../org.etsi.osl.main org.etsi.osl.cridge org.etsi.osl.cridge - https://osl.etsi.org + ${org.etsi.osl.cridge.version} + + + OpenSlice by ETSI + https://osl.etsi.org + + -- GitLab From 36528b65fc7258239c2b19efb280eee60337263a Mon Sep 17 00:00:00 2001 From: Rafael Direito Date: Tue, 8 Oct 2024 18:47:04 +0000 Subject: [PATCH 03/11] Added missing dependency. Closes #13 --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 91792e1..b6db3f9 100644 --- a/pom.xml +++ b/pom.xml @@ -103,6 +103,12 @@ spring-boot-starter-actuator + + org.bouncycastle + bcpkix-jdk15on + 1.70 + + -- GitLab From 1a94dcdb04c72de81b0b77b0f90a24e13fc5a680 Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Thu, 24 Oct 2024 15:24:25 +0300 Subject: [PATCH 04/11] fix for #14 --- .../osl/cridge/KubernetesClientResource.java | 147 +---- .../org/etsi/osl/cridge/NamespaceWatcher.java | 516 ++++++++++++++++++ .../osl/cridge/CridgeIntegrationTest.java | 65 ++- 3 files changed, 578 insertions(+), 150 deletions(-) create mode 100644 src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java diff --git a/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java b/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java index 088cd98..3f76ded 100644 --- a/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java +++ b/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java @@ -51,13 +51,13 @@ public class KubernetesClientResource { @Autowired CatalogClient catalogClient; + private KubernetesContextDefinition kubernetesContextDefinition = null; private ResourceSpecification kubernetesCRDV1ResourceSpec = null; private ResourceSpecification kubernetesCRV1ResourceSpec = null; - private ResourceSpecification kubernetesSecretResourceSpec = null; /** @@ -108,10 +108,7 @@ public class KubernetesClientResource { KubernetesCRV1.OSL_KUBCRV1_RSPEC_CATEGORY, KubernetesCRV1.OSL_KUBCRV1_RSPEC_VERSION); - kubernetesSecretResourceSpec = catalogClient.retrieveResourceSpecByNameCategoryVersion( - KubernetesSecret.OSL_KUBSECRET_RSPEC_NAME, - KubernetesSecret.OSL_KUBSECRET_RSPEC_CATEGORY, - KubernetesSecret.OSL_KUBSECRET_RSPEC_VERSION); + } return kubernetesContextDefinition; @@ -341,62 +338,7 @@ public class KubernetesClientResource { } - KubernetesSecret KubernetesSecret2OpensliceResource(Secret secret) { - - String baseCRD = String.format( "%s@%s@%s@%s", - secret.getKind(), - secret.getApiVersion(), - kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster(), - kubernetesClient.getMasterUrl().toExternalForm()); - - KubernetesSecret kcrv = KubernetesSecret.builder() - .osl_KUBCRD_RSPEC_UUID( kubernetesSecretResourceSpec.getUuid() ) - .name( secret.getMetadata().getName() - + "@" - + secret.getMetadata().getNamespace() - + "@" - + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() - + "@" + - kubernetesClient.getMasterUrl().toExternalForm() ) - .version( secret.getApiVersion() ) - .currentContextCluster( kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() ) - .clusterMasterURL( kubernetesClient.getMasterUrl().toString() ) - .fullResourceName( "" ) - .namespace( Serialization.asJson( secret.getMetadata().getNamespace()) ) - .kind( secret.getKind() ) - .apiGroup( secret.getPlural() ) - .uID( secret.getMetadata().getUid() ) - .metadata(Serialization.asJson( secret.getMetadata()) ) //.metadata( gkr.getMetadata().toString() ) - .description( - String.format( "A secret in namespace %s on %s", secret.getMetadata().getNamespace(), baseCRD )) - .build(); - - - secret.getMetadata().getLabels().forEach((pk, pv) -> { - logger.debug("\t label: {} {} ", pk, pv); - kcrv.getProperties().put( pk , pv); - - }); - - - if (secret.getData() != null) - secret.getData().forEach((kPropName, vProVal) -> { - logger.debug("propName={} propValue={} ", kPropName, vProVal ); - kcrv.getData().put(kPropName, vProVal); - }); - if (secret.getStringData() != null) - secret.getStringData().forEach((kPropName, vProVal) -> { - logger.debug("propName={} propValue={} ", kPropName, vProVal ); - kcrv.getProperties().put(kPropName, vProVal); - }); - - kcrv.setDataObj( Serialization.asYaml( secret.getData() ) ); - kcrv.setYaml( Serialization.asYaml( secret ) ); - kcrv.setJson( Serialization.asJson( secret ) ); - - return kcrv; - } @@ -475,7 +417,9 @@ public class KubernetesClientResource { */ if ( this.watchersForNamespaces.get(nameSpacename) == null ) { - SharedIndexInformer result = createWatchersFornamespace( nameSpacename, headers ); + + //SharedIndexInformer result = createWatchersFornamespace( nameSpacename, headers ); + NamespaceWatcher result = NamespaceWatcher.getNew( kubernetesClient, catalogClient, nameSpacename, headers); this.watchersForNamespaces.put(nameSpacename, result); } @@ -498,87 +442,6 @@ public class KubernetesClientResource { } - /** - * if the equivalent namespace for the service order is successfully created the create - * related wathcers for secrets, services, configmaps, pods, etc - * 1) we need to create domainmodels for these - * 2) we add them as support resources to our initial resource - * @param nameSpacename - * @param headers - * @return - */ - private SharedIndexInformer createWatchersFornamespace(String nameSpacename, Map headers) { - //watcher for secrets - - SharedIndexInformer shixInformer = - this.getKubernetesClient() - .secrets().inNamespace(nameSpacename).inform(new ResourceEventHandler() { - - @Override - public void onAdd(Secret obj) { - logger.debug("Added Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", - obj.getKind(), - obj.getMetadata().getName(), - obj.getMetadata().getUid(), - obj.getMetadata().getNamespace()); - - headers.forEach(((hname, hval) ->{ - if (hval instanceof String s) { - if ( hname.contains("org.etsi.osl")) { - logger.debug("Header: {} = {} ", hname, s ); - if ( obj.getMetadata() == null ) { - obj.setMetadata( new ObjectMeta()); - obj.getMetadata().setLabels( new HashMap()); - } - obj.getMetadata().getLabels().put(hname, s); - } - } - })); - - updateKubernetesSecretResourceInOSLCatalog( obj ); - - - } - - @Override - public void onUpdate(Secret oldObj, Secret newObj) { - logger.debug("onUpdate Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", - newObj.getKind(), - newObj.getMetadata().getName(), - newObj.getMetadata().getUid(), - newObj.getMetadata().getNamespace()); - updateKubernetesSecretResourceInOSLCatalog( newObj ); - - } - - @Override - public void onDelete(Secret obj, boolean deletedFinalStateUnknown) { - logger.debug("onDelete Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", - obj.getKind(), - obj.getMetadata().getName(), - obj.getMetadata().getUid(), - obj.getMetadata().getNamespace()); - updateKubernetesSecretResourceInOSLCatalog( obj ); - - } - - - }, 30 * 1000L); // resync period (set 0 for no resync); - - shixInformer.start(); - - return shixInformer; - - } - - private void updateKubernetesSecretResourceInOSLCatalog(Secret resource) { - ResourceCreate rs = this - .KubernetesSecret2OpensliceResource( resource ) - .toResourceCreate(); - - catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); - - } diff --git a/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java new file mode 100644 index 0000000..6156125 --- /dev/null +++ b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java @@ -0,0 +1,516 @@ +package org.etsi.osl.cridge; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.etsi.osl.domain.model.kubernetes.KubernetesConfigMap; +import org.etsi.osl.domain.model.kubernetes.KubernetesSecret; +import org.etsi.osl.domain.model.kubernetes.KubernetesService; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecification; +import org.etsi.osl.tmf.ri639.model.ResourceCreate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.api.model.Secret; +import io.fabric8.kubernetes.api.model.Service; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.ResourceEventHandler; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import io.fabric8.kubernetes.client.utils.Serialization; + +public class NamespaceWatcher { + + + private static final Logger logger = LoggerFactory.getLogger( "org.etsi.osl.cridge" ); + + private KubernetesClient kubernetesClient; + + private CatalogClient catalogClient; + + private String nameSpacename; + + private Map headers; + + private ResourceSpecification kubernetesSecretResourceSpec = null; + + private ResourceSpecification kubernetesServiceResourceSpec = null; + + private ResourceSpecification kubernetesConfigMapResourceSpec = null; + + List< SharedIndexInformer> informers = new ArrayList<>(); + + + public NamespaceWatcher(KubernetesClient kubernetesClient, CatalogClient catalogClient, String anameSpacename, Map aheaders) { + super(); + this.kubernetesClient = kubernetesClient; + this.catalogClient = catalogClient; + this.nameSpacename = anameSpacename; + this.headers = aheaders; + + kubernetesSecretResourceSpec = catalogClient.retrieveResourceSpecByNameCategoryVersion( + KubernetesSecret.OSL_KUBSECRET_RSPEC_NAME, + KubernetesSecret.OSL_KUBSECRET_RSPEC_CATEGORY, + KubernetesSecret.OSL_KUBSECRET_RSPEC_VERSION); + + kubernetesServiceResourceSpec = catalogClient.retrieveResourceSpecByNameCategoryVersion( + KubernetesService.OSL_KUBSERVICE_RSPEC_NAME, + KubernetesService.OSL_KUBSERVICE_RSPEC_CATEGORY, + KubernetesService.OSL_KUBSERVICE_RSPEC_VERSION); + + + kubernetesConfigMapResourceSpec = catalogClient.retrieveResourceSpecByNameCategoryVersion( + KubernetesConfigMap.OSL_KUBCMAP_RSPEC_NAME, + KubernetesConfigMap.OSL_KUBCMAP_RSPEC_CATEGORY, + KubernetesConfigMap.OSL_KUBCMAP_RSPEC_VERSION); + } + + public static NamespaceWatcher getNew(KubernetesClient kubernetesClient2, CatalogClient catalogClient2, String anameSpacename, Map aheaders) { + + NamespaceWatcher aNamespaceWatchers = new NamespaceWatcher(kubernetesClient2, catalogClient2, anameSpacename, aheaders); + + SharedIndexInformer rSecret = aNamespaceWatchers.createSecretWatchersFornamespace(anameSpacename, aheaders); + aNamespaceWatchers.informers.add( rSecret ); + + SharedIndexInformer rService = aNamespaceWatchers.createServiceWatcherssForNamespace(anameSpacename, aheaders); + aNamespaceWatchers.informers.add( rService ); + + SharedIndexInformer rCMap = aNamespaceWatchers.createConfigMapWatcherssForNamespace(anameSpacename, aheaders); + aNamespaceWatchers.informers.add( rService ); + + + return aNamespaceWatchers; + + } + + + + + + /** + * if the equivalent namespace for the service order is successfully created the create + * related wathcers for secrets, services, configmaps, pods, etc + * 1) we need to create domainmodels for these + * 2) we add them as support resources to our initial resource + * @param nameSpacename + * @param headers + * @return + */ + + + private SharedIndexInformer createSecretWatchersFornamespace(String nameSpacename, Map headers) { + //watcher for secrets + SharedIndexInformer shixInformer = this.kubernetesClient.secrets().inNamespace(nameSpacename).inform(new ResourceEventHandler() { + + @Override + public void onAdd(Secret obj) { + logger.debug("Added Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + + headers.forEach(((hname, hval) ->{ + if (hval instanceof String s) { + if ( hname.contains("org.etsi.osl")) { + logger.debug("Header: {} = {} ", hname, s ); + if ( obj.getMetadata() == null ) { + obj.setMetadata( new ObjectMeta()); + obj.getMetadata().setLabels( new HashMap()); + } + obj.getMetadata().getLabels().put(hname, s); + } + } + })); + + updateKubernetesSecretResourceInOSLCatalog( obj ); + + + } + + @Override + public void onUpdate(Secret oldObj, Secret newObj) { + logger.debug("onUpdate Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + newObj.getKind(), + newObj.getMetadata().getName(), + newObj.getMetadata().getUid(), + newObj.getMetadata().getNamespace()); + updateKubernetesSecretResourceInOSLCatalog( newObj ); + + } + + @Override + public void onDelete(Secret obj, boolean deletedFinalStateUnknown) { + logger.debug("onDelete Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + updateKubernetesSecretResourceInOSLCatalog( obj ); + + } + + + }, 30 * 1000L); // resync period (set 0 for no resync); + + shixInformer.start(); + + return shixInformer; + + } + + + + + private void updateKubernetesSecretResourceInOSLCatalog(Secret resource) { + ResourceCreate rs = this.KubernetesSecret2OpensliceResource( resource ).toResourceCreate(); + catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); + + } + + + public KubernetesSecret KubernetesSecret2OpensliceResource(Secret secret) { + + + String baseCRD = String.format( "%s@%s@%s@%s", + secret.getKind(), + secret.getApiVersion(), + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster(), + kubernetesClient.getMasterUrl().toExternalForm()); + + KubernetesSecret kcrv = KubernetesSecret.builder().osl_KUBCRD_RSPEC_UUID( kubernetesSecretResourceSpec.getUuid() ) + .name( secret.getMetadata().getName() + + "@" + + secret.getMetadata().getNamespace() + + "@" + + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() + + "@" + + kubernetesClient.getMasterUrl().toExternalForm() ) + .version( secret.getApiVersion() ) + .currentContextCluster( kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() ) + .clusterMasterURL( kubernetesClient.getMasterUrl().toString() ) + .fullResourceName( "" ) + .namespace( Serialization.asJson( secret.getMetadata().getNamespace()) ) + .kind( secret.getKind() ) + .apiGroup( secret.getPlural() ) + .uID( secret.getMetadata().getUid() ) + .metadata(Serialization.asJson( secret.getMetadata()) ) //.metadata( gkr.getMetadata().toString() ) + .description( + String.format( "A secret in namespace %s on %s", secret.getMetadata().getNamespace(), baseCRD )) + .build(); + + + secret.getMetadata().getLabels().forEach((pk, pv) -> { + logger.debug("\t label: {} {} ", pk, pv); + kcrv.getProperties().put( pk , pv); + + }); + + + if (secret.getData() != null) + secret.getData().forEach((kPropName, vProVal) -> { + logger.debug("propName={} propValue={} ", kPropName, vProVal ); + kcrv.getData().put(kPropName, vProVal); + }); + if (secret.getStringData() != null) + secret.getStringData().forEach((kPropName, vProVal) -> { + logger.debug("propName={} propValue={} ", kPropName, vProVal ); + kcrv.getProperties().put(kPropName, vProVal); + }); + + kcrv.setDataObj( Serialization.asYaml( secret.getData() ) ); + kcrv.setYaml( Serialization.asYaml( secret ) ); + kcrv.setJson( Serialization.asJson( secret ) ); + + return kcrv; + } + + + + + + /******************* + * + * Services Watcher + * + *******************/ + private SharedIndexInformer createServiceWatcherssForNamespace(String nameSpacename, Map headers) { + //watcher for secrets + SharedIndexInformer shixInformer = this.kubernetesClient.services().inNamespace(nameSpacename).inform(new ResourceEventHandler() { + + @Override + public void onAdd(Service obj) { + logger.debug("Added Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + + headers.forEach(((hname, hval) ->{ + if (hval instanceof String s) { + if ( hname.contains("org.etsi.osl")) { + logger.debug("Header: {} = {} ", hname, s ); + if ( obj.getMetadata() == null ) { + obj.setMetadata( new ObjectMeta()); + obj.getMetadata().setLabels( new HashMap()); + } + obj.getMetadata().getLabels().put(hname, s); + } + } + })); + + updateKubernetesServiceResourceInOSLCatalog( obj ); + + + } + + @Override + public void onUpdate(Service oldObj, Service newObj) { + logger.debug("onUpdate Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + newObj.getKind(), + newObj.getMetadata().getName(), + newObj.getMetadata().getUid(), + newObj.getMetadata().getNamespace()); + updateKubernetesServiceResourceInOSLCatalog( newObj ); + + } + + @Override + public void onDelete(Service obj, boolean deletedFinalStateUnknown) { + logger.debug("onDelete Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + updateKubernetesServiceResourceInOSLCatalog( obj ); + + } + + + }, 30 * 1000L); // resync period (set 0 for no resync); + + shixInformer.start(); + + return shixInformer; + + } + + + + private void updateKubernetesServiceResourceInOSLCatalog(Service resource) { + ResourceCreate rs = this.KubernetesService2OpensliceResource( resource ).toResourceCreate(); + catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); + + } + + + KubernetesService KubernetesService2OpensliceResource(Service serv) { + + String baseCRD = String.format( "%s@%s@%s@%s", + serv.getKind(), + serv.getApiVersion(), + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster(), + kubernetesClient.getMasterUrl().toExternalForm()); + + KubernetesService kcrv = KubernetesService.builder().osl_KUBCRD_RSPEC_UUID( kubernetesServiceResourceSpec.getUuid() ) + .name( serv.getMetadata().getName() + + "@" + + serv.getMetadata().getNamespace() + + "@" + + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() + + "@" + + kubernetesClient.getMasterUrl().toExternalForm() ) + .version( serv.getApiVersion() ) + .currentContextCluster( kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() ) + .clusterMasterURL( kubernetesClient.getMasterUrl().toString() ) + .fullResourceName( "" ) + .namespace( Serialization.asJson( serv.getMetadata().getNamespace()) ) + .kind( serv.getKind() ) + .apiGroup( serv.getPlural() ) + .uID( serv.getMetadata().getUid() ) + .metadata(Serialization.asJson( serv.getMetadata()) ) //.metadata( gkr.getMetadata().toString() ) + .description( + String.format( "A service in namespace %s on %s", serv.getMetadata().getNamespace(), baseCRD )) + .build(); + + + serv.getMetadata().getLabels().forEach((pk, pv) -> { + logger.debug("\t label: {} {} ", pk, pv); + kcrv.getProperties().put( pk , pv); + + }); + + + kcrv.setSpecObj( Serialization.asYaml( serv.getSpec() ) ); + kcrv.setStatusObj( Serialization.asYaml( serv.getStatus() ) ); + kcrv.setYaml( Serialization.asYaml( serv ) ); + kcrv.setJson( Serialization.asJson( serv ) ); + + // Convert YAML to Map + Map resultMap = yamlToMap( kcrv.getSpecObj() ); + kcrv.setSpec(resultMap); + + resultMap = yamlToMap( kcrv.getStatusObj() ); + kcrv.setStatus(resultMap); + + return kcrv; + } + + + public static Map yamlToMap(String yamlString) { + Yaml yaml = new Yaml(); + Map yamlMap = yaml.load(new StringReader(yamlString)); + + // Create a result map that will contain flattened key-value pairs + Map resultMap = new LinkedHashMap<>(); + + // Call the recursive method to flatten the map + flattenMap("", yamlMap, resultMap); + + return resultMap; + } + + // Recursive method to flatten the YAML structure + private static void flattenMap(String prefix, Map sourceMap, Map resultMap) { + for (Map.Entry entry : sourceMap.entrySet()) { + String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Map) { + // Recursively flatten nested maps + flattenMap(key, (Map) value, resultMap); + } else { + // Convert value to String and put it in the resultMap + resultMap.put(key, value.toString()); + } + } + } + + + + /******************* + * + * ConfigMap Watcher + * + *******************/ + private SharedIndexInformer createConfigMapWatcherssForNamespace(String nameSpacename, Map headers) { + //watcher for secrets + SharedIndexInformer shixInformer = this.kubernetesClient.configMaps().inNamespace(nameSpacename).inform(new ResourceEventHandler() { + + @Override + public void onAdd(ConfigMap obj) { + logger.debug("Added Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + + headers.forEach(((hname, hval) ->{ + if (hval instanceof String s) { + if ( hname.contains("org.etsi.osl")) { + logger.debug("Header: {} = {} ", hname, s ); + if ( obj.getMetadata() == null ) { + obj.setMetadata( new ObjectMeta()); + obj.getMetadata().setLabels( new HashMap()); + } + obj.getMetadata().getLabels().put(hname, s); + } + } + })); + + updateKubernetesConfigMapResourceInOSLCatalog( obj ); + + + } + + @Override + public void onUpdate(ConfigMap oldObj, ConfigMap newObj) { + logger.debug("onUpdate Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + newObj.getKind(), + newObj.getMetadata().getName(), + newObj.getMetadata().getUid(), + newObj.getMetadata().getNamespace()); + updateKubernetesConfigMapResourceInOSLCatalog( newObj ); + + } + + @Override + public void onDelete(ConfigMap obj, boolean deletedFinalStateUnknown) { + logger.debug("onDelete Namespace watcher Resource Kind:{} Name:{} UID:{} Namespace:{}", + obj.getKind(), + obj.getMetadata().getName(), + obj.getMetadata().getUid(), + obj.getMetadata().getNamespace()); + updateKubernetesConfigMapResourceInOSLCatalog( obj ); + + } + + + }, 30 * 1000L); // resync period (set 0 for no resync); + + shixInformer.start(); + + return shixInformer; + + } + + private void updateKubernetesConfigMapResourceInOSLCatalog(ConfigMap resource) { + ResourceCreate rs = this.KubernetesConfigMap2OpensliceResource( resource ).toResourceCreate(); + catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); + + } + + KubernetesConfigMap KubernetesConfigMap2OpensliceResource(ConfigMap cmap) { + + + String baseCRD = String.format( "%s@%s@%s@%s", + cmap.getKind(), + cmap.getApiVersion(), + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster(), + kubernetesClient.getMasterUrl().toExternalForm()); + + KubernetesConfigMap kcrv = KubernetesConfigMap.builder().osl_KUBCRD_RSPEC_UUID( kubernetesConfigMapResourceSpec.getUuid() ) + .name( cmap.getMetadata().getName() + + "@" + + cmap.getMetadata().getNamespace() + + "@" + + kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() + + "@" + + kubernetesClient.getMasterUrl().toExternalForm() ) + .version( cmap.getApiVersion() ) + .currentContextCluster( kubernetesClient.getConfiguration().getCurrentContext().getContext().getCluster() ) + .clusterMasterURL( kubernetesClient.getMasterUrl().toString() ) + .fullResourceName( "" ) + .namespace( Serialization.asJson( cmap.getMetadata().getNamespace()) ) + .kind( cmap.getKind() ) + .apiGroup( cmap.getPlural() ) + .uID( cmap.getMetadata().getUid() ) + .metadata(Serialization.asJson( cmap.getMetadata()) ) //.metadata( gkr.getMetadata().toString() ) + .description( + String.format( "A configMap in namespace %s on %s", cmap.getMetadata().getNamespace(), baseCRD )) + .build(); + + + cmap.getMetadata().getLabels().forEach((pk, pv) -> { + logger.debug("\t label: {} {} ", pk, pv); + kcrv.getProperties().put( pk , pv); + + }); + + + kcrv.setDataObj( Serialization.asYaml( cmap.getData() ) ); + kcrv.setYaml( Serialization.asYaml( cmap ) ); + kcrv.setJson( Serialization.asJson( cmap ) ); + + // Convert YAML to Map + Map resultMap = yamlToMap( kcrv.getDataObj() ); + kcrv.setData(resultMap); + + return kcrv; + } + +} diff --git a/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java b/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java index 3ebb8ae..5da5d06 100644 --- a/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java +++ b/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java @@ -41,11 +41,13 @@ import io.fabric8.kubernetes.api.model.NamedContextBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.SecretBuilder; +import io.fabric8.kubernetes.api.model.ServiceList; 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.apiextensions.v1.ConversionRequestFluent.V1beta1ServiceReferenceObjectsNested; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; @@ -226,12 +228,61 @@ public class CridgeIntegrationTest { // server api expectations server.expect().get() .withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?resourceVersion=0") - .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); - + .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).always(); + server.expect().get().withPath( "/api/v1/namespaces/orderid-xxx-xxx-xxx/secrets?allowWatchBookmarks=true&timeoutSeconds=600&watch=true") - .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); + .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).always(); + server.expect().get().withPath( + "/api/v1/namespaces/orderid-xxx-xxx-xxx/services?allowWatchBookmarks=true&resourceVersion=12345&timeoutSeconds=600&watch=true") + .andReturn(HttpURLConnection.HTTP_OK, "{\r\n" + + " \"kind\": \"ServiceList\",\r\n" + + " \"apiVersion\": \"v1\",\r\n" + + " \"metadata\": {\r\n" + + " \"resourceVersion\": \"12345\"\r\n" + + " },\r\n" + + " \"items\": []\r\n" + + " }").always(); + + // server api expectations + server.expect().get() + .withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/services?resourceVersion=0") + .andReturn(HttpURLConnection.HTTP_OK , "{\r\n" + + " \"kind\": \"ServiceList\",\r\n" + + " \"apiVersion\": \"v1\",\r\n" + + " \"metadata\": {\r\n" + + " \"resourceVersion\": \"12345\"\r\n" + + " },\r\n" + + " \"items\": []\r\n" + + " }").always(); + + + + server.expect().get().withPath( + "/api/v1/namespaces/orderid-xxx-xxx-xxx/configmaps?allowWatchBookmarks=true&resourceVersion=12345&timeoutSeconds=600&watch=true") + .andReturn(HttpURLConnection.HTTP_OK, "{\r\n" + + " \"kind\": \"ConfigMapList\",\r\n" + + " \"apiVersion\": \"v1\",\r\n" + + " \"metadata\": {\r\n" + + " \"resourceVersion\": \"12345\"\r\n" + + " },\r\n" + + " \"items\": []\r\n" + + " }").always(); + + // server api expectations + server.expect().get() + .withPath("/api/v1/namespaces/orderid-xxx-xxx-xxx/configmaps?resourceVersion=0") + .andReturn(HttpURLConnection.HTTP_OK , "{\r\n" + + " \"kind\": \"ConfigMapList\",\r\n" + + " \"apiVersion\": \"v1\",\r\n" + + " \"metadata\": {\r\n" + + " \"resourceVersion\": \"12345\"\r\n" + + " },\r\n" + + " \"items\": []\r\n" + + " }").always(); + + server.expect().get() .withPath("/apis/stable.example.com/v1/namespaces/orderid-xxx-xxx-xxx/mycalculators") .andReturn(HttpURLConnection.HTTP_OK, crdMyCalc).once(); @@ -392,12 +443,10 @@ public class CridgeIntegrationTest { Secret secretCreated = routesPreparation.kubernetesClient.secrets().inNamespace("default") .resource(secret1).create(); + - KubernetesSecret value = - kubernetesClientResource.KubernetesSecret2OpensliceResource(secretCreated); - - assertEquals("Secret", value.getKind()); - assertEquals("v1", value.getVersion()); + assertEquals("Secret", secretCreated.getKind()); + assertEquals("v1", secretCreated.getApiVersion() ); } -- GitLab From 5f9797af83987fcb74308c5ae8ad28064aee312e Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Fri, 25 Oct 2024 20:17:52 +0300 Subject: [PATCH 05/11] fix for #15 --- src/main/java/org/etsi/osl/cridge/CatalogClient.java | 6 +++--- src/main/resources/application.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/etsi/osl/cridge/CatalogClient.java b/src/main/java/org/etsi/osl/cridge/CatalogClient.java index 0527c11..9500084 100644 --- a/src/main/java/org/etsi/osl/cridge/CatalogClient.java +++ b/src/main/java/org/etsi/osl/cridge/CatalogClient.java @@ -36,8 +36,8 @@ public class CatalogClient extends RouteBuilder{ @Value("${CATALOG_GET_RESOURCESPEC_BY_ID}") private String CATALOG_GET_RESOURCESPEC_BY_ID = ""; - @Value("${CATALOG_GET_RESOURCESPEC_BY_ΝAME_CATEGORY}") - private String CATALOG_GET_RESOURCESPEC_BY_ΝAME_CATEGORY = ""; + @Value("${CATALOG_GET_RESOURCESPEC_BY_NAME_CATEGORY}") + private String CATALOG_GET_RESOURCESPEC_BY_NAME_CATEGORY = ""; @Value("${CATALOG_UPDADD_RESOURCESPEC}") @@ -87,7 +87,7 @@ public class CatalogClient extends RouteBuilder{ map.put( "acategory", aCategory); map.put( "aversion", aVersion); Object response = - template.requestBodyAndHeaders( CATALOG_GET_RESOURCESPEC_BY_ΝAME_CATEGORY, null, map); + template.requestBodyAndHeaders( CATALOG_GET_RESOURCESPEC_BY_NAME_CATEGORY, null, map); if ( !(response instanceof String)) { logger.error("Resource Specification object is wrong."); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3dcfe7f..3f2d1dd 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -38,7 +38,7 @@ CATALOG_ADD_RESOURCESPEC: "jms:queue:CATALOG.ADD.RESOURCESPEC" CATALOG_UPD_RESOURCESPEC: "jms:queue:CATALOG.UPD.RESOURCESPEC" CATALOG_UPDADD_RESOURCESPEC: "jms:queue:CATALOG.UPDADD.RESOURCESPEC" CATALOG_GET_RESOURCESPEC_BY_ID: "jms:queue:CATALOG.GET.RESOURCESPEC_BY_ID" -CATALOG_GET_RESOURCESPEC_BY_ΝAME_CATEGORY: "jms:queue:CATALOG.GET.RESOURCESPEC_BY_ΝAME_CATEGORY" +CATALOG_GET_RESOURCESPEC_BY_NAME_CATEGORY: "jms:queue:CATALOG.GET.RESOURCESPEC_BY_NAME_CATEGORY" #CRD ACTIONS -- GitLab From 07f648507ed3c74ca5e279ac31e3921519b7bf99 Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Wed, 30 Oct 2024 13:32:09 +0200 Subject: [PATCH 06/11] fix for #15 --- src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java b/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java index 3ebb8ae..60b22df 100644 --- a/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java +++ b/src/test/java/org/etsi/osl/cridge/CridgeIntegrationTest.java @@ -66,7 +66,7 @@ import io.fabric8.kubernetes.client.utils.Serialization; "kubernetes.master = test_kube", "spring.activemq.brokerUrl = vm://embedded?broker.persistent=false,useShutdownHook=false", "CATALOG_GET_RESOURCESPEC_BY_ID = direct:get_rspec_byid", - "CATALOG_GET_RESOURCESPEC_BY_ΝAME_CATEGORY = direct:get_rspec_byNameCategory", + "CATALOG_GET_RESOURCESPEC_BY_NAME_CATEGORY = direct:get_rspec_byNameCategory", "CATALOG_UPDADD_RESOURCE = direct:updadd_resource",}) -- GitLab From adf29b91c3d19992084d8289bb009cb70265170b Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Mon, 4 Nov 2024 13:00:30 +0200 Subject: [PATCH 07/11] remove yaml --- src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java index 6156125..f47bfce 100644 --- a/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java +++ b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java @@ -223,7 +223,7 @@ public class NamespaceWatcher { }); kcrv.setDataObj( Serialization.asYaml( secret.getData() ) ); - kcrv.setYaml( Serialization.asYaml( secret ) ); + //kcrv.setYaml( Serialization.asYaml( secret ) ); kcrv.setJson( Serialization.asJson( secret ) ); return kcrv; @@ -347,7 +347,7 @@ public class NamespaceWatcher { kcrv.setSpecObj( Serialization.asYaml( serv.getSpec() ) ); kcrv.setStatusObj( Serialization.asYaml( serv.getStatus() ) ); - kcrv.setYaml( Serialization.asYaml( serv ) ); + //kcrv.setYaml( Serialization.asYaml( serv ) ); kcrv.setJson( Serialization.asJson( serv ) ); // Convert YAML to Map @@ -503,7 +503,7 @@ public class NamespaceWatcher { kcrv.setDataObj( Serialization.asYaml( cmap.getData() ) ); - kcrv.setYaml( Serialization.asYaml( cmap ) ); + //kcrv.setYaml( Serialization.asYaml( cmap ) ); kcrv.setJson( Serialization.asJson( cmap ) ); // Convert YAML to Map -- GitLab From 6e1287866dd7743d61303a0eccd8cc0004ed005b Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Thu, 21 Nov 2024 16:53:29 +0200 Subject: [PATCH 08/11] fix for #18 --- src/main/resources/application.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3f2d1dd..ff80f2b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,6 +12,7 @@ spring: max-connections: 100 packages: trust-all: true + autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration server: port: 0 -- GitLab From bc9c0eb64ee90a8a35f4c3881776617409138dbb Mon Sep 17 00:00:00 2001 From: Dimitrios Giannopoulos Date: Fri, 22 Nov 2024 16:22:12 +0000 Subject: [PATCH 09/11] Standalone cridge with Helm --- helm/cridge/.helmignore | 23 +++++++ helm/cridge/Chart.yaml | 23 +++++++ .../org.etsi.osl.cridge/kubeconfig.yaml.empty | 19 ++++++ helm/cridge/templates/_helpers.tpl | 62 +++++++++++++++++++ helm/cridge/templates/deployment.yaml | 57 +++++++++++++++++ helm/cridge/templates/secret.yaml | 28 +++++++++ helm/cridge/values.yaml | 32 ++++++++++ 7 files changed, 244 insertions(+) create mode 100644 helm/cridge/.helmignore create mode 100644 helm/cridge/Chart.yaml create mode 100644 helm/cridge/files/org.etsi.osl.cridge/kubeconfig.yaml.empty create mode 100644 helm/cridge/templates/_helpers.tpl create mode 100644 helm/cridge/templates/deployment.yaml create mode 100644 helm/cridge/templates/secret.yaml create mode 100644 helm/cridge/values.yaml diff --git a/helm/cridge/.helmignore b/helm/cridge/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/cridge/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/cridge/Chart.yaml b/helm/cridge/Chart.yaml new file mode 100644 index 0000000..b2f5982 --- /dev/null +++ b/helm/cridge/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +name: cridge +description: Cridge Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +appVersion: 2024Q4-SNAPSHOT diff --git a/helm/cridge/files/org.etsi.osl.cridge/kubeconfig.yaml.empty b/helm/cridge/files/org.etsi.osl.cridge/kubeconfig.yaml.empty new file mode 100644 index 0000000..1176403 --- /dev/null +++ b/helm/cridge/files/org.etsi.osl.cridge/kubeconfig.yaml.empty @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Config +clusters: +- name: development-cluster + cluster: + certificate-authority: path/to/ca.crt # Path to certificate authority file + server: https://123.45.67.89:6443 # Cluster API server address +contexts: +- name: dev-user@development-cluster + context: + cluster: development-cluster + namespace: development # Default namespace + user: dev-user +current-context: dev-user@development-cluster +users: +- name: dev-user + user: + client-certificate: path/to/cert.crt # Path to the client certificate + client-key: path/to/key.key # Path to the client key diff --git a/helm/cridge/templates/_helpers.tpl b/helm/cridge/templates/_helpers.tpl new file mode 100644 index 0000000..89f9f71 --- /dev/null +++ b/helm/cridge/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "openslice.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "openslice.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "openslice.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "openslice.labels" -}} +helm.sh/chart: {{ include "openslice.chart" . }} +{{ include "openslice.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "openslice.selectorLabels" -}} +app.kubernetes.io/name: {{ include "openslice.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "openslice.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "openslice.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/cridge/templates/deployment.yaml b/helm/cridge/templates/deployment.yaml new file mode 100644 index 0000000..0353795 --- /dev/null +++ b/helm/cridge/templates/deployment.yaml @@ -0,0 +1,57 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-cridge +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.cridge.repository }}:{{ .Values.image.cridge.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.cridge.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-cridge + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "{{ .Values.oscreds.activemq.brokerUrl }}", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.spring.logLevel | default "INFO" }}", + "logging.level.org.etsi.osl.cridge" : "{{ .Values.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + securityContext: + {{- if .Values.securityContext.enabled }} + allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }} + capabilities: + drop: {{ .Values.securityContext.capabilities.drop }} + seccompProfile: + type: {{ .Values.securityContext.seccompProfile.type }} + {{- end }} + volumeMounts: + - name: kubeconfig + readOnly: true + mountPath: /root/.kube + restartPolicy: Always + volumes: + - name: kubeconfig + secret: + secretName: {{ include "openslice.fullname" . }}-kubeconfig diff --git a/helm/cridge/templates/secret.yaml b/helm/cridge/templates/secret.yaml new file mode 100644 index 0000000..5d0e729 --- /dev/null +++ b/helm/cridge/templates/secret.yaml @@ -0,0 +1,28 @@ +{{- $kubeconfigBase64 := .Values.kubeconfig.base64 | default "" -}} +{{- $kubeconfigFile := .Values.kubeconfig.raw | default (.Files.Get "files/org.etsi.osl.cridge/kubeconfig.yaml") -}} +{{- $kubeconfig := "" -}} + +{{- if $kubeconfigBase64 }} + {{- $kubeconfig = $kubeconfigBase64 | b64dec }} +{{- else if $kubeconfigFile }} + {{- $kubeconfig = $kubeconfigFile }} +{{- end }} + +apiVersion: v1 +kind: Secret +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-kubeconfig +type: Opaque +data: + config: |- + {{- if $kubeconfig }} + {{ $kubeconfig | b64enc | nindent 4 }} + {{- else }} + {{- required "A kubeconfig file is required." ($kubeconfig | b64enc) | nindent 4 }} + {{- end }} diff --git a/helm/cridge/values.yaml b/helm/cridge/values.yaml new file mode 100644 index 0000000..1d87a53 --- /dev/null +++ b/helm/cridge/values.yaml @@ -0,0 +1,32 @@ +# Default values for cridge. + +replicaCount: 1 + +image: + cridge: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.cridge + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "develop" + +oscreds: + activemq: + brokerUrl: tcp://openslice-artemis:61616?jms.watchTopicAdvisories=false # Where the cridge should connect to + user: artemis + password: artemis + +logLevel: INFO +spring: + loglevel: INFO + +securityContext: + enabled: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault + +kubeconfig: + base64: "" # Provide base64-encoded kubeconfig here if available + raw: "" # Provide raw kubeconfig here if available -- GitLab From 468cc4abc5e49ac116798bfc4fe10b498f9eb322 Mon Sep 17 00:00:00 2001 From: Christos Tranoris Date: Wed, 18 Dec 2024 09:27:08 +0200 Subject: [PATCH 10/11] fix for #19 --- .../org/etsi/osl/cridge/CRRouteBuilder.java | 8 +-- .../osl/cridge/KubernetesClientResource.java | 23 ++++++- .../org/etsi/osl/cridge/NamespaceWatcher.java | 61 +++++++++++++++---- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/etsi/osl/cridge/CRRouteBuilder.java b/src/main/java/org/etsi/osl/cridge/CRRouteBuilder.java index 78ec06a..8323709 100644 --- a/src/main/java/org/etsi/osl/cridge/CRRouteBuilder.java +++ b/src/main/java/org/etsi/osl/cridge/CRRouteBuilder.java @@ -57,8 +57,8 @@ public class CRRouteBuilder extends RouteBuilder{ .bean( kubernetesClientResource, "patchCR(${headers}, ${body})") .convertBodyTo( String.class ); - // every 3600000 ms (60 minutes) - from( "timer://processUpdateResources?period=3600000" ) + // every 120000 ms (2 minutes) + from( "timer://processUpdateResources?period=120000" ) .log(LoggingLevel.INFO, log, " process nameSpacesTobeDeleted!") .to("log:DEBUG?showBody=true&showHeaders=true") .bean( CRRouteBuilder.class , "processNameSpacesTobeDeleted()"); @@ -72,8 +72,8 @@ public class CRRouteBuilder extends RouteBuilder{ Date currentTime = new Date(); //get current time long diffInMillies = Math.abs(currentTime .getTime() - datetime.getTime()); - long diff = TimeUnit.HOURS.convert(diffInMillies, TimeUnit.MILLISECONDS); - if (diff<=2) { //after 2 hours this namespace will be deleted + long diff = TimeUnit.MINUTES.convert(diffInMillies, TimeUnit.MILLISECONDS); + if (diff<=2) { //after 2 minutes this namespace will be deleted return; } diff --git a/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java b/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java index 3f76ded..4546d74 100644 --- a/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java +++ b/src/main/java/org/etsi/osl/cridge/KubernetesClientResource.java @@ -66,7 +66,7 @@ public class KubernetesClientResource { */ private ConcurrentHashMap nameSpacesTobeDeleted = new ConcurrentHashMap<>(); - private Map watchersForNamespaces = new HashMap<>(); + private Map watchersForNamespaces = new HashMap<>(); @@ -481,7 +481,13 @@ public class KubernetesClientResource { this.nameSpacesTobeDeleted.put(nameSpacename, new Date() ); + NamespaceWatcher watchersForNamespace = this.watchersForNamespaces.get(nameSpacename); + if ( watchersForNamespace!= null) { + watchersForNamespace.disableNamespace( nameSpacename ); + } + this.watchersForNamespaces.remove(nameSpacename); + }catch (Exception e) { e.printStackTrace(); @@ -519,8 +525,19 @@ public class KubernetesClientResource { } } })); - gkr.getMetadata().setNamespace( (String) headers.get("org.etsi.osl.namespace") ); //set default namespace the service Order ID if a namespace is not there - gkr.getMetadata().setName( (String) headers.get("org.etsi.osl.prefixName") ) ; + + //we must change and assign a name to the resource + if ( headers.get("org.etsi.osl.prefixId") !=null ) { + gkr.getMetadata().setName( (String) headers.get("org.etsi.osl.prefixName") ) ; + }else { + //it must start with an alpha character + gkr.getMetadata().setName( "cr" + ((String) headers.get("org.etsi.osl.resourceId")).substring(0, 8) ) ; + } + + + if ( gkr.getMetadata().getNamespace() == null || gkr.getMetadata().getNamespace().equals("") ) { + gkr.getMetadata().setNamespace( (String) headers.get("org.etsi.osl.serviceOrderId") ); //set default namespace the service Order ID if a namespace is not there + } logger.debug("{}", gkr.toString() ); diff --git a/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java index f47bfce..1e1ea08 100644 --- a/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java +++ b/src/main/java/org/etsi/osl/cridge/NamespaceWatcher.java @@ -11,6 +11,7 @@ import org.etsi.osl.domain.model.kubernetes.KubernetesSecret; import org.etsi.osl.domain.model.kubernetes.KubernetesService; import org.etsi.osl.tmf.rcm634.model.ResourceSpecification; import org.etsi.osl.tmf.ri639.model.ResourceCreate; +import org.etsi.osl.tmf.ri639.model.ResourceStatusType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; @@ -127,7 +128,7 @@ public class NamespaceWatcher { } })); - updateKubernetesSecretResourceInOSLCatalog( obj ); + updateKubernetesSecretResourceInOSLCatalog( obj, false ); } @@ -139,7 +140,7 @@ public class NamespaceWatcher { newObj.getMetadata().getName(), newObj.getMetadata().getUid(), newObj.getMetadata().getNamespace()); - updateKubernetesSecretResourceInOSLCatalog( newObj ); + updateKubernetesSecretResourceInOSLCatalog( newObj, false ); } @@ -150,7 +151,7 @@ public class NamespaceWatcher { obj.getMetadata().getName(), obj.getMetadata().getUid(), obj.getMetadata().getNamespace()); - updateKubernetesSecretResourceInOSLCatalog( obj ); + updateKubernetesSecretResourceInOSLCatalog( obj, true ); } @@ -166,8 +167,15 @@ public class NamespaceWatcher { - private void updateKubernetesSecretResourceInOSLCatalog(Secret resource) { + private void updateKubernetesSecretResourceInOSLCatalog(Secret resource, boolean toDelete) { +// if (this.informers.size() == 0) { +// logger.debug("Informers are 0. Will exit updateKubernetesSecretResourceInOSLCatalog"); +// return; +// } ResourceCreate rs = this.KubernetesSecret2OpensliceResource( resource ).toResourceCreate(); + if (toDelete) { + rs.setResourceStatus(ResourceStatusType.SUSPENDED); + } catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); } @@ -263,7 +271,7 @@ public class NamespaceWatcher { } })); - updateKubernetesServiceResourceInOSLCatalog( obj ); + updateKubernetesServiceResourceInOSLCatalog( obj, false ); } @@ -275,7 +283,7 @@ public class NamespaceWatcher { newObj.getMetadata().getName(), newObj.getMetadata().getUid(), newObj.getMetadata().getNamespace()); - updateKubernetesServiceResourceInOSLCatalog( newObj ); + updateKubernetesServiceResourceInOSLCatalog( newObj, false ); } @@ -286,7 +294,7 @@ public class NamespaceWatcher { obj.getMetadata().getName(), obj.getMetadata().getUid(), obj.getMetadata().getNamespace()); - updateKubernetesServiceResourceInOSLCatalog( obj ); + updateKubernetesServiceResourceInOSLCatalog( obj, true ); } @@ -301,8 +309,15 @@ public class NamespaceWatcher { - private void updateKubernetesServiceResourceInOSLCatalog(Service resource) { + private void updateKubernetesServiceResourceInOSLCatalog(Service resource, boolean toDelete) { +// if (this.informers.size() == 0) { +// logger.debug("Informers are 0. Will exit updateKubernetesServiceResourceInOSLCatalog"); +// return; +// } ResourceCreate rs = this.KubernetesService2OpensliceResource( resource ).toResourceCreate(); + if (toDelete) { + rs.setResourceStatus(ResourceStatusType.SUSPENDED); + } catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); } @@ -422,7 +437,7 @@ public class NamespaceWatcher { } })); - updateKubernetesConfigMapResourceInOSLCatalog( obj ); + updateKubernetesConfigMapResourceInOSLCatalog( obj, false ); } @@ -434,7 +449,7 @@ public class NamespaceWatcher { newObj.getMetadata().getName(), newObj.getMetadata().getUid(), newObj.getMetadata().getNamespace()); - updateKubernetesConfigMapResourceInOSLCatalog( newObj ); + updateKubernetesConfigMapResourceInOSLCatalog( newObj, false ); } @@ -445,7 +460,7 @@ public class NamespaceWatcher { obj.getMetadata().getName(), obj.getMetadata().getUid(), obj.getMetadata().getNamespace()); - updateKubernetesConfigMapResourceInOSLCatalog( obj ); + updateKubernetesConfigMapResourceInOSLCatalog( obj, true ); } @@ -458,8 +473,15 @@ public class NamespaceWatcher { } - private void updateKubernetesConfigMapResourceInOSLCatalog(ConfigMap resource) { + private void updateKubernetesConfigMapResourceInOSLCatalog(ConfigMap resource, boolean toDelete) { +// if (this.informers.size() == 0) { +// logger.debug("Informers are 0. Will exit updateKubernetesConfigMapResourceInOSLCatalog"); +// return; +// } ResourceCreate rs = this.KubernetesConfigMap2OpensliceResource( resource ).toResourceCreate(); + if (toDelete) { + rs.setResourceStatus(ResourceStatusType.SUSPENDED); + } catalogClient.createOrUpdateResourceByNameCategoryVersion( rs ); } @@ -513,4 +535,19 @@ public class NamespaceWatcher { return kcrv; } + + public void disableNamespace(String ns) { + this.kubernetesClient.configMaps().inNamespace(ns).delete(); + this.kubernetesClient.secrets().inNamespace(ns).delete(); + this.kubernetesClient.services().inNamespace(ns).delete(); + +// for (SharedIndexInformer sharedIndexInformer : informers) { +// sharedIndexInformer.stop(); +// sharedIndexInformer.close(); +// +// } +// this.informers.clear(); + + } + } -- GitLab From f2e0a030fd9756ce643bec1144f82941f15d163c Mon Sep 17 00:00:00 2001 From: trantzas Date: Tue, 14 Jan 2025 13:47:07 +0000 Subject: [PATCH 11/11] Preparing the 2024Q4_RC: - Remove -SNAPSHOT from parent's version at pom.xml - Remove -SNAPSHOT from Dockerfile's jar references --- Dockerfile | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 697956e..6cffc0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,5 +2,5 @@ FROM ibm-semeru-runtimes:open-17.0.7_7-jdk MAINTAINER openslice.io RUN mkdir /opt/shareclasses RUN mkdir -p /opt/openslice/lib/ -COPY target/org.etsi.osl.cridge-1.1.0-SNAPSHOT-exec.jar /opt/openslice/lib/ -CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.1.0-SNAPSHOT-exec.jar"] +COPY target/org.etsi.osl.cridge-1.1.0-exec.jar /opt/openslice/lib/ +CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.1.0-exec.jar"] diff --git a/pom.xml b/pom.xml index b6db3f9..56b90c4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.etsi.osl org.etsi.osl.main - 2024Q4-SNAPSHOT + 2024Q4 ../org.etsi.osl.main -- GitLab