From 5fde26757bb573d0d58e9f51d343cdd82103e8fa Mon Sep 17 00:00:00 2001 From: mesaj Date: Wed, 16 Jul 2025 09:41:44 +0200 Subject: [PATCH] Add vCluster build in stage 3 Change-Id: I30fdfdaa67c0c71cff62a90003f41eb0bb8c53e3 Signed-off-by: mesaj --- jenkins/ci-pipelines/ci_stage_3.groovy | 157 ++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 18 deletions(-) diff --git a/jenkins/ci-pipelines/ci_stage_3.groovy b/jenkins/ci-pipelines/ci_stage_3.groovy index 4f0a55a3..11b4755f 100644 --- a/jenkins/ci-pipelines/ci_stage_3.groovy +++ b/jenkins/ci-pipelines/ci_stage_3.groovy @@ -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 { -- 2.25.1