Add vCluster build in stage 3 81/15281/8
authormesaj <juanmanuel.mesamendez.ext@telefonica.com>
Wed, 16 Jul 2025 07:41:44 +0000 (09:41 +0200)
committermesaj <juanmanuel.mesamendez.ext@telefonica.com>
Mon, 21 Jul 2025 09:38:17 +0000 (11:38 +0200)
Change-Id: I30fdfdaa67c0c71cff62a90003f41eb0bb8c53e3
Signed-off-by: mesaj <juanmanuel.mesamendez.ext@telefonica.com>
jenkins/ci-pipelines/ci_stage_3.groovy

index 4f0a55a..11b4755 100644 (file)
@@ -108,6 +108,89 @@ class DockerRunner implements Serializable {
     }
 }
 
+/* -------------------------------------------------------------------
+ *  create_vcluster  – spin up a vcluster in the target OSM cluster
+ * @params:
+ *  tagName - The OSM test docker image tag to use
+ *  kubeconfigPath - The path of the OSM kubernetes master configuration
+ *                   file
+ ** Usage:
+ *    create_vcluster(containerName, env.OSM_KUBECONFIG_PATH)
+ * ------------------------------------------------------------------- */
+void create_vcluster(String tagName, String kubeconfigPath) {
+    def dr     = new DockerRunner(this)
+    def mounts = ["${kubeconfigPath}:/root/.kube/config"]
+    def envs   = ["KUBECONFIG=/root/.kube/config"]
+    def image  = "opensourcemano/tests:${tagName}"
+
+    // 1) create vcluster namespace
+    dr.run(
+        image   : image,
+        entry   : "kubectl",
+        envVars : envs,
+        mounts  : mounts,
+        cmd     : "create namespace vcluster || true"
+    )
+    println("Namespace 'vcluster' ensured")
+
+    // 2) create vcluster
+    dr.run(
+        image   : image,
+        entry   : "vcluster",
+        envVars : envs,
+        mounts  : mounts,
+        cmd     : "create e2e -n vcluster --connect=false -f /etc/vcluster.yaml"
+    )
+    println("vcluster 'e2e' created")
+
+    // 3) poll until Status is Running
+    int maxWaitMinutes = 2
+    long deadline = System.currentTimeMillis() + (maxWaitMinutes * 60 * 1000)
+    boolean running = false
+    String lastOut = ''
+
+    while (System.currentTimeMillis() < deadline) {
+        try {
+            lastOut = dr.run(
+                image   : image,
+                entry   : "/bin/sh",
+                envVars : envs,
+                mounts  : mounts,
+                cmd     : '''-c "vcluster list --output json | jq -r \'.[] | select(.Name==\\\"e2e\\\") | .Status\'"'''
+            ).trim()
+        } catch (Exception e) {
+            println("Polling command failed: ${e.message}. Will retry.")
+            lastOut = "Error: ${e.message}"
+        }
+
+        println("Polling for vcluster status. Current status: '${lastOut}'")
+
+        if (lastOut == 'Running') {
+            running = true
+            break // Exit the while loop
+        }
+
+        sleep 10 // Wait 10 seconds before the next poll
+    }
+
+    if (!running) {
+        println("vcluster status after timeout: ${lastOut}")
+        throw new Exception("vcluster 'e2e' did not reach 'Running' state within ${maxWaitMinutes} minutes.")
+    }
+
+    // 4) get vcluster kubeconfig
+    env.VCLUSTER_KUBECONFIG_PATH = "${WORKSPACE}/kubeconfig/vcluster_config"
+    dr.run(
+        image   : image,
+        entry   : "vcluster",
+        envVars : envs,
+        mounts  : mounts,
+        cmd     : "connect e2e -n vcluster --server e2e.vcluster.svc.cluster.local:443 --print > ${env.VCLUSTER_KUBECONFIG_PATH}"
+    )
+
+    println("vcluster 'e2e' is Running ✔")
+}
+
 void register_etsi_vim_account(
     String tagName,
     String osmHostname,
@@ -368,27 +451,35 @@ void run_robot_systest(String tagName,
     try {
         withCredentials([usernamePassword(credentialsId: 'gitlab-oci-test',
                         passwordVariable: 'OCI_REGISTRY_PSW', usernameVariable: 'OCI_REGISTRY_USR')]) {
+
+            def baseEnvVars = [
+                "OSM_HOSTNAME=${osmHostname}",
+                "PROMETHEUS_HOSTNAME=${prometheusHostname}",
+                PROMETHEUS_PORT_VAR ? "${PROMETHEUS_PORT_VAR}" : null,
+                JUJU_PASSWORD_VAR ? "${JUJU_PASSWORD_VAR}" : null,
+                "OCI_REGISTRY_URL=${ociRegistryUrl}",
+                "OCI_REGISTRY_USER=${OCI_REGISTRY_USR}",
+                "OCI_REGISTRY_PASSWORD=${OCI_REGISTRY_PSW}"
+            ].findAll { it != null }
+            def baseMounts = [
+                "${clouds}:/etc/openstack/clouds.yaml",
+                "${osmRSAfile}:/root/osm_id_rsa",
+                "${kubeconfig}:/root/.kube/config",
+                "${tempdir}:/robot-systest/reports",
+                "${portmappingfile}:/root/port-mapping.yaml",
+                "${hostfilemount}"
+            ].findAll { it != null }
+
+            // Convert and merge extra parameters
+            def extraEnvVarsList = extraEnvVars?.collect { key, value -> "${key}=${value}" } ?: []
+            def extraVolMountsList = extraVolMounts?.collect { hostPath, containerPath -> "${hostPath}:${containerPath}" } ?: []
+
             def dr = new DockerRunner(this)
             dr.run(
                 image   : "opensourcemano/tests:${tagName}",
-                envVars : [
-                    "OSM_HOSTNAME=${osmHostname}",
-                    "PROMETHEUS_HOSTNAME=${prometheusHostname}",
-                    "${PROMETHEUS_PORT_VAR}",
-                    "${JUJU_PASSWORD_VAR}",
-                    "OCI_REGISTRY_URL=${ociRegistryUrl}",
-                    "OCI_REGISTRY_USER=${OCI_REGISTRY_USR}",
-                    "OCI_REGISTRY_PASSWORD=${OCI_REGISTRY_PSW}"
-                ],
+                envVars : baseEnvVars + extraEnvVarsList,
                 envFile : "${environmentFile}",
-                mounts  : [
-                    "${clouds}:/etc/openstack/clouds.yaml",
-                    "${osmRSAfile}:/root/osm_id_rsa",
-                    "${kubeconfig}:/root/.kube/config",
-                    "${tempdir}:/robot-systest/reports",
-                    "${portmappingfile}:/root/port-mapping.yaml",
-                    "${hostfilemount}"
-                ],
+                mounts  : baseMounts + extraVolMountsList,
                 cmd     : "-t ${testName}"
             )
         }
@@ -900,6 +991,32 @@ node("${params.NODE}") {
                         OSM_HOSTNAME=nbi.${remote.host}.nip.io ~/.local/bin/osm vim-list
                     """
                 } // stage("OSM Health")
+///////////////////////////////////////////////////////////////////////////////////////
+// Get OSM Kubeconfig and store it for future usage
+///////////////////////////////////////////////////////////////////////////////////////
+                stage('OSM Get kubeconfig') {
+                  // Delete always kubecofig directory to ensure it is clean.
+                  sh '''
+                    rm -rf "${WORKSPACE}/kubeconfig"
+                    mkdir -p "${WORKSPACE}/kubeconfig"
+                  '''
+                  env.OSM_KUBECONFIG_PATH = "${WORKSPACE}/kubeconfig/osm_config"
+                  sshGet  remote: remote,
+                          from:  "/home/ubuntu/.kube/config",
+                          into:  env.OSM_KUBECONFIG_PATH,
+                          override: true
+                  sh "cat ${env.OSM_KUBECONFIG_PATH}"
+                } // stage('OSM Get kubeconfig')
+
+///////////////////////////////////////////////////////////////////////////////////////
+// Create vCluster for GitOps test execution
+///////////////////////////////////////////////////////////////////////////////////////
+                stage('Create vCluster') {
+                  // create an isolated vcluster for the E2E tests
+                  create_vcluster(containerName, env.OSM_KUBECONFIG_PATH)
+                  // Verify vCluster kubeconfig is available
+                  sh "cat ${env.VCLUSTER_KUBECONFIG_PATH}"
+                } // stage('Create vCluster')
             } // if ( params.DO_INSTALL )
 ///////////////////////////////////////////////////////////////////////////////////////
 // Execute Robot tests
@@ -957,7 +1074,11 @@ EOF"""
                             jujuPassword,
                             SSH_KEY,
                             params.ROBOT_PASS_THRESHOLD,
-                            params.ROBOT_UNSTABLE_THRESHOLD
+                            params.ROBOT_UNSTABLE_THRESHOLD,
+                            // extraEnvVars map of extra environment variables
+                            ['CLUSTER_KUBECONFIG_CREDENTIALS': '/robot-systest/cluster-kubeconfig.yaml'],
+                            // extraVolMounts map of extra volume mounts
+                            [(env.VCLUSTER_KUBECONFIG_PATH): '/robot-systest/cluster-kubeconfig.yaml']
                         )
                     } // stage("System Integration Test")
                 } finally {