K8s Profile mod on demand 02/102602/3
authorLukasz Rajewski <lukasz.rajewski@orange.com>
Fri, 28 Feb 2020 14:24:52 +0000 (15:24 +0100)
committerLukasz Rajewski <lukasz.rajewski@orange.com>
Tue, 3 Mar 2020 10:20:41 +0000 (11:20 +0100)
This change provides an example of
modificatioin of k8s profile on demand.
In here the ssh service of vPGN is
created on demand and user can decide
about the number of ssh exposed port

Change-Id: Ie734e4f832d6a07ff53a0f108aed74a43d325b22
Issue-ID: INT-1458
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com>
heat/vFW_CNF_CDS/templates/cba/Definitions/data_types.json
heat/vFW_CNF_CDS/templates/cba/Definitions/resources_definition_types.json
heat/vFW_CNF_CDS/templates/cba/Definitions/vFW_CNF_CDS.json
heat/vFW_CNF_CDS/templates/cba/Scripts/kotlin/KotlinK8sProfileUpload.kt
heat/vFW_CNF_CDS/templates/cba/Templates/k8s-profiles/ssh-service-mapping.json [new file with mode: 0644]
heat/vFW_CNF_CDS/templates/cba/Templates/k8s-profiles/ssh-service-template.vtl

index 52d89c1..988d059 100644 (file)
           "type" : "string",
           "default" : "default"
         },
+        "vpg-management-port" : {
+          "description" : "SSH external port of ssh. When 0 ssh service will not be exposed",
+          "type" : "string",
+          "default": "0"
+        },
         "vnf_name" : {
           "description" : "",
           "required" : false,
index ba31cfc..17e4dcb 100644 (file)
       }
     }
   },
+  "vpg-management-port" : {
+    "tags" : "vpg-management-port",
+    "name" : "vpg-management-port",
+    "property" : {
+      "description" : "vpg-management-port",
+      "type" : "string"
+    },
+    "updated-by" : "Rajewski, Lukasz <lukasz.rajewski@orange.com>",
+    "sources" : {
+      "input" : {
+        "type" : "source-input"
+      },
+      "default" : {
+        "type" : "source-default",
+        "properties" : { }
+      }
+    }
+  },
   "key_name" : {
     "tags" : "key_name",
     "name" : "key_name",
index 0040e28..673c086 100644 (file)
       "url" : "http://multicloud-k8s:9015"
     },
     "profile-upload-properties" : {
-      "assignment-params" : {
+      "assignment-params": {
         "get_attribute" : [ "resource-assignment", "assignment-params" ]
       },
-      "api-access" : "*multicloud-k8s-api"
+      "profile-modification-decision-data": {
+        "get_input" : "vpg-management-port"
+      },
+      "profile-artifacts": {
+        "get_attribute" : [ "profile-modification", "assignment-params" ]
+      },
+      "api-access": "*multicloud-k8s-api"
     },
     "config-deploy-properties" : {
       "resolution-key" : {
           "resource-assignment" : {
             "description" : "Resource Assign Workflow",
             "target" : "resource-assignment",
-            "activities" : [ {
-              "call_operation" : "ResourceResolutionComponent.process"
-            } ],
-            "on_success" : [ "profile-upload" ]
+            "activities": [
+              {
+                "call_operation": "ResourceResolutionComponent.process"
+              }
+            ],
+            "on_success": [
+              "profile-modification"
+            ]
+          },
+          "profile-modification" : {
+            "description" : "Profile Modification Resources",
+            "target" : "profile-modification",
+            "activities": [
+              {
+                "call_operation": "ResourceResolutionComponent.process"
+              }
+            ],
+            "on_success": [
+              "profile-upload"
+            ]
           },
           "profile-upload" : {
             "description" : "Upload K8s Profile",
             "target" : "profile-upload",
-            "activities" : [ {
-              "call_operation" : "ComponentScriptExecutor.process"
-            } ]
+            "activities": [
+              {
+                "call_operation": "ComponentScriptExecutor.process"
+              }
+            ]
           }
         },
         "inputs" : {
           }
         }
       },
+      "profile-modification" : {
+        "type" : "component-resource-resolution",
+        "interfaces" : {
+          "ResourceResolutionComponent" : {
+            "operations" : {
+              "process" : {
+                "inputs" : {
+                  "artifact-prefix-names" : [ "ssh-service" ]
+                }
+              }
+            }
+          }
+        },
+        "artifacts" : {
+          "ssh-service-template" : {
+            "type" : "artifact-template-velocity",
+            "file" : "Templates/k8s-profiles/ssh-service-template.vtl"
+          },
+          "ssh-service-mapping" : {
+            "type" : "artifact-mapping-resource",
+            "file" : "Templates/k8s-profiles/ssh-service-mapping.json"
+          }
+        }
+      },
       "profile-upload" : {
         "type" : "component-script-executor",
         "interfaces" : {
index 22e4b33..d47b476 100644 (file)
@@ -42,6 +42,7 @@ import org.springframework.web.client.RestTemplate
 import com.fasterxml.jackson.annotation.JsonIgnore
 import com.fasterxml.jackson.annotation.JsonProperty
 import java.util.ArrayList
+import java.util.LinkedHashMap
 import java.io.IOException
 import java.io.File
 import java.nio.file.Files
@@ -52,6 +53,7 @@ import org.springframework.http.MediaType
 import java.nio.charset.Charset
 import java.util.Base64
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.yaml.snakeyaml.Yaml
 
 open class K8sProfileUpload : AbstractScriptComponentFunction() {
 
@@ -102,7 +104,7 @@ open class K8sProfileUpload : AbstractScriptComponentFunction() {
                 if (api.hasProfile(k8sRbProfileName)) {
                     log.info("Profile Already Existing - skipping upload")
                 } else {
-                    val profileFilePath: Path = prepareProfileFile(k8sRbProfileName)
+                    val profileFilePath: Path = prepareProfileFile(k8sRbProfileName, prefix.equals("vpkg"))
 
                     var profile = K8sProfile()
                     profile.profileName = k8sRbProfileName
@@ -118,7 +120,7 @@ open class K8sProfileUpload : AbstractScriptComponentFunction() {
         }
     }
 
-    fun prepareProfileFile(k8sRbProfileName: String): Path {
+    fun prepareProfileFile(k8sRbProfileName: String, profileModificationAllowed: Boolean): Path {
         val bluePrintContext = bluePrintRuntimeService.bluePrintContext()
         val bluePrintBasePath: String = bluePrintContext.rootPath
         var profileFilePath: Path = Paths.get(bluePrintBasePath.plus(File.separator).plus("Templates").plus(File.separator).plus("k8s-profiles").plus(File.separator).plus("${k8sRbProfileName}.tar.gz"))
@@ -138,7 +140,40 @@ open class K8sProfileUpload : AbstractScriptComponentFunction() {
 
         log.info("${profileFilePath.toString()} decompression completed")
 
-        //Here we can add extra files inside the archive
+        if (profileModificationAllowed) {
+            //Here we can add extra files inside the archive
+            val profileModificationDecisionData = getDynamicProperties("profile-modification-decision-data")
+            log.info("Profile modification decision data: ${profileModificationDecisionData}")
+            if (profileModificationDecisionData != null && profileModificationDecisionData.asText().toInt() > 0) {
+                log.info("Modification of profile content")
+
+                val profileArtifacts = getDynamicProperties("profile-artifacts")
+                val sshServiceFileContent = profileArtifacts.get("ssh-service").asText()
+                val sshServiceFileName = "ssh-service.yaml"
+                val serviceFilePath = tempProfilePath.toString().plus(File.separator).plus(sshServiceFileName)
+                File(serviceFilePath).bufferedWriter().use { out -> out.write(sshServiceFileContent) }
+                val manifestFileName = tempProfilePath.toString().plus(File.separator).plus("manifest.yaml")
+                var finalManifest = ""
+                File(manifestFileName).bufferedReader().use { inr ->
+                    val manifestYaml = Yaml()
+                    val manifestObject: Map<String, Any> = manifestYaml.load(inr)
+                    val typeObject: MutableMap<String, Any> = manifestObject.get("type") as MutableMap<String, Any>
+                    if (!typeObject.containsKey("configresource"))
+                        typeObject.put("configresource", ArrayList<LinkedHashMap<String, Any>>())
+                    val configFiles: MutableList<LinkedHashMap<String, Any>> = typeObject.get("configresource") as MutableList<LinkedHashMap<String, Any>>
+                    val sshConfigFile = LinkedHashMap<String, Any>()
+                    sshConfigFile.put("filepath", sshServiceFileName)
+                    sshConfigFile.put("chartpath", "vpkg/templates/${sshServiceFileName}")
+                    configFiles.add(sshConfigFile)
+                    finalManifest = manifestYaml.dump(manifestObject)
+                }
+                File(manifestFileName).bufferedWriter().use { out -> out.write(finalManifest) }
+                log.info("Modified K8s profile manifest file")
+                log.info(finalManifest)
+                log.info("Modification of profile completed")
+            }
+        }
+
         profileFilePath = Paths.get(tempMainPath.toString().plus(File.separator).plus("${k8sRbProfileName}.tar.gz"))
 
         if (!BluePrintArchiveUtils.compress(decompressedProfile, profileFilePath.toFile(),
diff --git a/heat/vFW_CNF_CDS/templates/cba/Templates/k8s-profiles/ssh-service-mapping.json b/heat/vFW_CNF_CDS/templates/cba/Templates/k8s-profiles/ssh-service-mapping.json
new file mode 100644 (file)
index 0000000..1960e0e
--- /dev/null
@@ -0,0 +1,15 @@
+[
+  {
+    "name": "vpg-management-port",
+    "property": {
+      "description": "The number of node port for ssh service of vpg. 0 means that ssh service will not be exposed",
+      "type": "string",
+      "default": "0"
+    },
+    "input-param": false,
+    "dictionary-name": "vpg-management-port",
+    "dictionary-source": "default",
+    "dependencies": [
+    ]
+  }
+]
\ No newline at end of file
index 190af7e..98cc9e7 100644 (file)
@@ -11,7 +11,7 @@ spec:
   type: NodePort
   ports:
     - port: 22
-      nodePort: 30022 #TemplateMe
+      nodePort: ${vpg-management-port}
   selector:
     vf-module-name: {{ .Values.vpg_name_0 }}
     release: {{ .Release.Name }}