diff --git a/Dockerfile b/Dockerfile index 5732826b130ce2b32c4e7512c3b8b5e5782d823d..e9b81ab8d75b6b46a74026cbf97cd34d49ccd6dd 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.2.0-SNAPSHOT-exec.jar /opt/openslice/lib/ -CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.2.0-SNAPSHOT-exec.jar"] +COPY target/org.etsi.osl.cridge-1.0.0-SNAPSHOT-exec.jar /opt/openslice/lib/ +CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.cridge-1.0.0-SNAPSHOT-exec.jar"] diff --git a/docs/K8aas_example.md b/docs/K8aas_example.md new file mode 100644 index 0000000000000000000000000000000000000000..3bda09f3d2c97bc372fade5e96c49cebc3ed6b18 --- /dev/null +++ b/docs/K8aas_example.md @@ -0,0 +1,92 @@ +@startuml +actor Participant as caller +boundary OSLAPI as oslapirest +control OSLC as oslapi +control OSOM as osom +control CRIDGE as cridge +control MGMK8S as mgtk8s +control ARGOCD as argo +control K8SaaSCRD as k88ascrd + +caller -> oslapirest : Create Service Order for K8SaaS spec\n (With ACKNOWLEDGED state) +oslapirest -> oslapi: Create\nService\nOrder +osom -> oslapi: Fetch ACK\norders +activate osom +osom -> osom: Process orders +osom -> cridge: Deploy CR App +note right + This CR is matched with equivalent + Resource in RI (ref resourceId) +end note +cridge -// mgtk8s: Create CR +note right + here we label this CR with resourceId +end note +cridge -> cridge: Start watching\nSO namespace +cridge -> osom: response OK +osom -> oslapi: Order is INPROGRESS \n (services are created\nin RESERVED) + +mgtk8s -> argo: Create CR +argo -> k88ascrd: Create CR +argo -// mgtk8s: CR status +mgtk8s -// cridge: CRs watch +group sync and reconciliation + cridge -// oslapi: Update equivalent resource in RI of this CR\n(ref resourceId) + oslapi -> oslapi: EVENT_RESOURCE_STATE_CHANGED + mgtk8s -// cridge: Secrets watch + cridge -// oslapi: Add/Update equivalent secret resource in RI of this CR\n(ref resourceId) + note right + org.etsi.osl.* labels are added + so this resource can be managed by OSL + end note + oslapi -> oslapi: EVENT_RESOURCE_STATE_CHANGED + note left + SIM638 needs to take this event in case + this Resource is related + to a specific supporting resource + (see resourceStateChangedEvent() and + updateResourceFromKubernetesLabel() ) + Any resources that has characteristic org.etsi.osl.serviceId equals to a service + are automatically added as supportingResources of this Service + end note +end + +osom -> osom: Wait all Active or Failures +note left +Wait for all services and +underlying resources +to be Active or Failed +end note +osom -> osom: Order is COMPLETED +osom -> oslapi: Order is COMPLETED +deactivate osom + +group sync and reconciliation (continuous process) + mgtk8s -// cridge: CRs watch + cridge -// oslapi: Update equivalent resource in RI of this CR\n(ref resourceId) + oslapi -> oslapi: EVENT_RESOURCE_STATE_CHANGED + mgtk8s -// cridge: Secrets watch + cridge -// oslapi: Add/Update equivalent secret resource in RI of this CR\n(ref resourceId) + oslapi -> oslapi: EVENT_RESOURCE_STATE_CHANGED +end + + + +caller -> oslapirest : request Service Order (by id) +activate caller +caller <- oslapirest : Service Order +caller -> caller : examine supportingService list +caller -> oslapirest : request Service (by id) +activate caller #FFDDDD +group focus only on the Resource Facing Service +caller -> caller : examine supportingResource list of this RFS +caller -> oslapirest : request Resource (by id) (tf-output@...) +caller <- oslapirest : Resource from Inventory +caller -> caller :get characteristics kubeconf +caller -> oslapirest : request Resource (by id) (tfstate-...) +caller <- oslapirest : Resource from Inventory +caller -> caller :get characteristic tfstate +end +deactivate caller +deactivate caller +@enduml diff --git a/docs/WatcherService_diagrams.md b/docs/WatcherService_diagrams.md new file mode 100644 index 0000000000000000000000000000000000000000..df50156b7804b81cd3652156f712eaf956c3fbb6 --- /dev/null +++ b/docs/WatcherService_diagrams.md @@ -0,0 +1,43 @@ +@startuml +participant "WatcherService" as Watcher +participant "SharedInformerFactory" as InformerFactory +participant "SharedIndexInformer<CRD>" as IndexInformer +participant "CustomResourceDefinition" as CRD +participant "ResourceEventHandler<CRD>" as EventHandler +database "CatalogClient" as Catalog + +Watcher -> InformerFactory : getKubernetesClient().informers() +activate InformerFactory +InformerFactory --> Watcher : sharedInformerFactory +deactivate InformerFactory + +Watcher -> IndexInformer : sharedInformerFactory.sharedIndexInformerFor(CRD, 30 * 1000L) +activate IndexInformer +IndexInformer --> Watcher : shixInformer +deactivate IndexInformer + +Watcher -> IndexInformer : addEventHandler(new ResourceEventHandler<CRD>()) +activate IndexInformer +IndexInformer -> EventHandler : onAdd(CRD) +activate EventHandler +EventHandler -> Catalog : createOrUpdateResourceSpecByNameCategoryVersion() +EventHandler -> Catalog : createOrUpdateResourceByNameCategoryVersion() +activate Catalog +Catalog --> EventHandler : Response +deactivate Catalog +EventHandler --> IndexInformer : onAdd Completed +EventHandler -> Watcher : createCRDSharedIndexInformer +deactivate EventHandler + +IndexInformer -> EventHandler : onUpdate(oldCRD, newCRD) +activate EventHandler +EventHandler --> IndexInformer : onUpdate Completed +deactivate EventHandler + +IndexInformer -> EventHandler : onDelete(CRD, deletedFinalStateUnknown) +activate EventHandler +EventHandler --> IndexInformer : onDelete Completed +deactivate EventHandler + +deactivate IndexInformer +@enduml \ No newline at end of file diff --git a/docs/kubernetesClientResource_diagrams.md b/docs/kubernetesClientResource_diagrams.md new file mode 100644 index 0000000000000000000000000000000000000000..22dbf6ac9c6233e2eb5820eba500e0818aeb549b --- /dev/null +++ b/docs/kubernetesClientResource_diagrams.md @@ -0,0 +1,53 @@ +@startuml +queue MQ +control "KubernetesClientResource" as KubeClientResource +participant "KubernetesClient" as KubeClient +entity "GenericKubernetesResource" as ResourceObj +participant "Namespace" as NamespaceDB + +MQ -> KubeClientResource : deployCR(headers, crspec) + +alt check if this cridge can handle the CRSPEC\ncurrentContextCluster, clusterMasterURL + + KubeClientResource --> MQ : Response (SEE OTHER) +end + +activate KubeClientResource + +KubeClientResource -> KubeClient : new KubernetesClientBuilder() +activate KubeClient +KubeClient --> KubeClientResource : k8s +deactivate KubeClient + + +KubeClientResource -> NamespaceDB : Try creating Namespace +activate NamespaceDB +NamespaceDB --> KubeClientResource : Namespace Created / Exists +deactivate NamespaceDB + +KubeClientResource -> KubeClientResource : createWatchersFornamespace() + + +activate KubeClientResource + + +KubeClientResource -> SharedInformer : KubernetesClient.secrets().inNamespace(nameSpacename).inform(new ResourceEventHandler<>()) + +loop For each Secret Event + SharedInformer -> EventHandler : onAdd()/onUpdate()/onDelete() + activate EventHandler + EventHandler -> KubeClientResource : updateKubernetesSecretResourceInOSLCatalog + deactivate EventHandler +end + +deactivate KubeClientResource + + +KubeClientResource -> ResourceObj : k8s.resource(gkr) +activate ResourceObj +ResourceObj --> KubeClientResource : Creation Response +deactivate ResourceObj + +KubeClientResource --> MQ : Response (OK / FAIL) +deactivate KubeClientResource +@enduml diff --git a/pom.xml b/pom.xml index 3939768ba9c657351a2f08112bbf92a7280221f5..5dc46fc4e406f7ad8985f65a8b9438c7b9ea58c2 100644 --- a/pom.xml +++ b/pom.xml @@ -9,8 +9,8 @@ <relativePath>../org.etsi.osl.main</relativePath> </parent> - <artifactId>org.etsi.osl.cridge</artifactId> + <artifactId>org.etsi.osl.cridge</artifactId> <name>org.etsi.osl.cridge</name> <url>http://openslice.io</url> @@ -103,12 +103,12 @@ <dependency> <groupId>org.etsi.osl</groupId> <artifactId>org.etsi.osl.model.tmf</artifactId> - <version>${project.version}</version> + <version>${org.etsi.osl.model.tmf.version}</version> </dependency> <dependency> <groupId>org.etsi.osl</groupId> <artifactId>org.etsi.osl.model.k8s</artifactId> - <version>${project.version}</version> + <version>${org.etsi.osl.model.k8s.version}</version> </dependency> diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000000000000000000000000000000000000..74229cd400fb31f76673214d76c0256f438e4ccc --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,11 @@ + ___ ____ _ _ + / _ \ _ __ ___ _ __ / ___|| (_) ___ ___ + | | | | '_ \ / _ \ '_ \\___ \| | |/ __/ _ \ + | |_| | |_) | __/ | | |___) | | | (_| __/ + \___/| .__/ \___|_| |_|____/|_|_|\___\___| + |_| + __ __________________ + / / __ __ / __/_ __/ __/ _/ + / _ \/ // / / _/ / / _\ \_/ / + /_.__/\_, / /___/ /_/ /___/___/ + /___/ \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/cridge/CreateResource.java b/src/test/java/org/etsi/osl/cridge/CreateResource.java deleted file mode 100644 index ec7fb90820906adb538a651c39f4c5ac6c8941f9..0000000000000000000000000000000000000000 --- a/src/test/java/org/etsi/osl/cridge/CreateResource.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.etsi.osl.cridge; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.fabric8.kubernetes.api.model.GenericKubernetesResourceBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; -import io.fabric8.kubernetes.client.dsl.Resource; - -public class CreateResource { - - public static void main(String[] args) { - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - - /** - * 1st approach with GenericKubernetesResource - */ -// ResourceDefinitionContext context = new ResourceDefinitionContext.Builder() -// .withGroup("stable.example.com") -// .withVersion("v1") -// .withKind("CronTab") -// .withPlural("crontabs") -// .withNamespaced(true) -// .build(); -// -// k8s.genericKubernetesResources(context) -// .inNamespace("default") -// .resource(genericKubernetesResource) -// .create(); - /** - * 2nd approach with GenericKubernetesResource - */ - Map<String, Object> spec = new HashMap<>(); - spec.put("title", "my-awesome-book title"); - spec.put("author", "TestAuthor"); - spec.put("isbn", "0077000007"); - - GenericKubernetesResource genericKubernetesResource = new GenericKubernetesResourceBuilder() - .withApiVersion("testing.fabric8.io/v1alpha1").withKind("Book").withNewMetadata() - .withName("my-new-book-object-" + UUID.randomUUID().toString()).withNamespace("testakis") - .endMetadata().addToAdditionalProperties("spec", spec).build(); - - Resource<GenericKubernetesResource> dummyObject = k8s.resource(genericKubernetesResource); - // Create Custom Resource - dummyObject.create(); - - } - } - -} diff --git a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkins.java b/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkins.java deleted file mode 100644 index 58fe4bbc23283cc989abe252642b7d0950ab5be5..0000000000000000000000000000000000000000 --- a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkins.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.etsi.osl.cridge; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.fabric8.kubernetes.api.model.GenericKubernetesResourceBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; -import io.fabric8.kubernetes.client.utils.Serialization; -import io.fabric8.kubernetes.client.dsl.Resource; - -public class CreateResourceArgoJenkins { - - - // @formatter:off - public static void main(String[] args) { - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - - String yamlfile = -""" -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: openslice-jenkins - namespace: argocd - finalizers: - - resources-finalizer.argocd.argoproj.io -spec: - project: default - destination: - namespace: default #update namespace name if you wish - name: in-cluster #update cluster name if its different - source: - repoURL: https://charts.jenkins.io - targetRevision: "4.6.1" - chart: jenkins - helm: - values: | - controller: - service: - type: ClusterIP -operation: - initiatedBy: - username: %s - sync: - prune: true - syncStrategy: - hook: {} - -""".formatted( "myuser" ); - - - System.out.println( yamlfile ); - GenericKubernetesResource gkr = Serialization.unmarshal(yamlfile); - - - Resource<GenericKubernetesResource> dummyObject = k8s.resource( gkr ); - dummyObject.create(); - -/* - * to delete we need: - * kubectl patch app openslice-jenkins -n argocd -p '{"metadata": {"finalizers": ["resources-finalizer.argocd.argoproj.io"]}}' --type merge - * kubectl delete app openslice-jenkins -n argocd - */ - - } - } - -} diff --git a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkinsProgram.java b/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkinsProgram.java deleted file mode 100644 index cc5e85980a251cd0fde10c9a3899b13dd082b9c9..0000000000000000000000000000000000000000 --- a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoJenkinsProgram.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.etsi.osl.cridge; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.camel.util.json.JsonObject; - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.fabric8.kubernetes.api.model.GenericKubernetesResourceBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; -import io.fabric8.kubernetes.client.utils.Serialization; -import io.fabric8.kubernetes.client.dsl.Resource; - -public class CreateResourceArgoJenkinsProgram { - - // @formatter:off - public static void main(String[] args) { - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - - - - JsonObject objSpec = new JsonObject(); - - objSpec.put("project", "default"); - //obj.put("num", Integer.valueOf(100)); - - JsonObject objdestination = new JsonObject(); - objdestination.put("namespace", "default"); - objdestination.put("name", "in-cluster"); - objSpec.put("destination", objdestination); - - JsonObject objsource = new JsonObject(); - objsource.put("repoURL", "https://charts.jenkins.io"); - objsource.put("targetRevision", "4.6.1"); - objsource.put("chart", "jenkins"); - JsonObject objvalues = new JsonObject(); - objvalues.put("values", "controller:\n service:\n type: ClusterIP\n"); - - - objsource.put("helm", objvalues); - objSpec.put("source", objsource); - - - - JsonObject objOperation = new JsonObject(); - JsonObject intiby = (new JsonObject()); - intiby.put("username", "testadmin"); - objOperation.put("initiatedBy", intiby); - JsonObject objsync = new JsonObject(); - objsync.put("prune", Boolean.valueOf(true)); - JsonObject syncStrategy = (new JsonObject()); - syncStrategy.put("hook", new JsonObject()); - objsync.put("syncStrategy", syncStrategy ); - objOperation.put("sync", objsync ); - - - - GenericKubernetesResource genericKubernetesResource = new GenericKubernetesResourceBuilder() - .withApiVersion("argoproj.io/v1alpha1") - .withKind("Application") - .withNewMetadata() - .withName( "openslice-jenkins" ) - .withNamespace( "argocd" ) - .addToFinalizers("resources-finalizer.argocd.argoproj.io") - .endMetadata() - .addToAdditionalProperties("spec", objSpec) - .addToAdditionalProperties("operation", objOperation) - .build(); - - - System.out.println( Serialization.asYaml( genericKubernetesResource ) ); - - System.out.println( "=============as Json===========================" ); - System.out.println( Serialization.asJson( genericKubernetesResource ) ); - - Resource<GenericKubernetesResource> dummyObject = k8s.resource(genericKubernetesResource); - // Create Custom Resource - dummyObject.create(); - -/* - * to delete we need: - * kubectl patch app ingress-nginx -n argocd -p '{"metadata": {"finalizers": ["resources-finalizer.argocd.argoproj.io"]}}' --type merge - * kubectl delete app ingress-nginx -n argocd - */ - - } - } - -} - - - -/** - * - * -{ - "apiVersion": "argoproj.io/v1alpha1", - "kind": "Application", - "metadata": { - "finalizers": [ - "resources-finalizer.argocd.argoproj.io" - ], - "name": "openslice-jenkins", - "namespace": "argocd" - }, - "spec": { - "project": "default", - "destination": { - "namespace": "default", - "name": "in-cluster" - }, - "source": { - "repoURL": "https://charts.jenkins.io", - "targetRevision": "4.6.1", - "chart": "jenkins", - "helm": { - "values": "controller:\n service:\n type: ClusterIP\n" - } - } - }, - "operation": { - "initiatedBy": { - "username": "testadmin" - }, - "sync": { - "prune": true, - "syncStrategy": { - "hook": {} - } - } - } -} - * - */ diff --git a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoNginx.java b/src/test/java/org/etsi/osl/cridge/CreateResourceArgoNginx.java deleted file mode 100644 index b9834f827be4dbfe82417b614872c83381f12548..0000000000000000000000000000000000000000 --- a/src/test/java/org/etsi/osl/cridge/CreateResourceArgoNginx.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.etsi.osl.cridge; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.fabric8.kubernetes.api.model.GenericKubernetesResourceBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; -import io.fabric8.kubernetes.client.utils.Serialization; -import io.fabric8.kubernetes.client.dsl.Resource; - -public class CreateResourceArgoNginx { - - - // @formatter:off - public static void main(String[] args) { - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - - String yamlfile = -""" -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: ingress-nginx - namespace: argocd -spec: - project: default - destination: - namespace: default - #update namespace name if you wish - name: in-cluster #update cluster name if its different - source: - repoURL: https://kubernetes.github.io/ingress-nginx - targetRevision: "4.4.0" - chart: ingress-nginx - helm: - values: | - controller: - service: - type: ClusterIP -operation: - initiatedBy: - username: %s - - sync: - prune: true - syncStrategy: - hook: {} - -""".formatted( "myuser" ); - - - System.out.println( yamlfile ); - GenericKubernetesResource gkr = Serialization.unmarshal(yamlfile); - - - Resource<GenericKubernetesResource> dummyObject = k8s.resource( gkr ); - dummyObject.create(); - -/* - * to delete we need: - * kubectl patch app ingress-nginx -n argocd -p '{"metadata": {"finalizers": ["resources-finalizer.argocd.argoproj.io"]}}' --type merge - * kubectl delete app ingress-nginx -n argocd - */ - - } - } - -} diff --git a/src/test/java/org/etsi/osl/cridge/GetResourcesOfNamespace.java b/src/test/java/org/etsi/osl/cridge/GetResourcesOfNamespace.java deleted file mode 100644 index 0b7177a60ce70410d91ff0aa1b609726b1029db7..0000000000000000000000000000000000000000 --- a/src/test/java/org/etsi/osl/cridge/GetResourcesOfNamespace.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.etsi.osl.cridge; - -import io.fabric8.kubernetes.api.model.ConfigMap; -import io.fabric8.kubernetes.api.model.Namespace; -import io.fabric8.kubernetes.api.model.NamespaceBuilder; -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.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.Watch; -import io.fabric8.kubernetes.client.Watcher; -import io.fabric8.kubernetes.client.WatcherException; -import io.fabric8.kubernetes.client.Watcher.Action; -import io.fabric8.kubernetes.client.utils.Serialization; - -public class GetResourcesOfNamespace { - - - // @formatter:off - public static void main(String[] args) throws InterruptedException { - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - - - Namespace ns = new NamespaceBuilder() - .withNewMetadata() - .withName( "opencrdtest" ) - .endMetadata().build(); - - - - for (Secret secret : k8s.secrets().inNamespace("opencrdtest").list().getItems() ) { - System.out.println( Serialization.asYaml( secret ) ); - } - - for (Service secret : k8s.services().inNamespace("opencrdtest").list().getItems() ) { - System.out.println( Serialization.asYaml( secret ) ); - } - - for (ConfigMap secret : k8s.configMaps().inNamespace("opencrdtest").list().getItems() ) { - System.out.println( Serialization.asYaml( secret ) ); - } - - - - } - - try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) { - Watch watch = k8s.secrets().inNamespace( "16cce858-2f99-4f8f-afe6-9e1f21a78880").watch( new Watcher<>() { - - @Override - public void eventReceived(Action action, Secret resource) { - - System.out.println(String.format("%s Namespace watcher Resource Kind:%s Name:%s UID:%s Namespace:%s", action.name(), - resource.getKind(), - resource.getMetadata().getName(), - resource.getMetadata().getUid(), - resource.getMetadata().getNamespace())); - //ADDED, DELETED, MODIFIED, BOOKMARK, ERROR - - - } - - - - @Override - public void onClose(WatcherException cause) { - System.out.println(String.format("Closing resources Watcher of nameSpace due to %s "+cause.getMessage())); - return; - } - - }); - Thread.sleep(60 * 1000L); - watch.close(); - } - - - - - } - - - -}