-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test clean for resubmission pipeline #1292
Changes from all commits
b882f08
1ca8c43
480caee
a1f20bb
0a1deb2
8ce7fa2
3952d72
670015a
6a88f43
13210d4
0472831
8fe6b2e
a8c14d1
1a6ca22
921a84d
fff8d5a
cebd678
f93e594
e2e4e57
a814a1a
daf3df9
478dddd
6cddcfe
4f8231f
0600944
6c6f932
59dbacc
b67ae28
4aaf990
38b5933
351d8b8
8a5ff2e
964041c
9f8fd95
57ae823
0ec7e11
016aa1e
fcc6ef1
cb04027
23667ba
7efd262
9a575b3
2cef053
7aa247f
8d0c8cc
379e129
ae629fb
717e970
9e2846b
f307d3d
781e900
5627616
9341bfa
6bbafad
a84d2f6
3815da6
5dc51c1
7aa70ce
35ae887
38cc406
f6321f0
39fec46
905ebca
060989e
438db0c
b9983ef
f496ae7
9bb0069
58c0532
9867173
3a47cf8
22107e5
7e5849e
395609e
19f28fa
f083cf5
123902d
27e1525
27b84e0
eaa86f2
e59de7f
05044cb
5446571
d94da1a
ab08a90
3e3f083
749abb5
d534e53
982ec5c
4d545a2
4efe288
5296aff
f386c2f
4fe0b91
ed69b13
f4d6018
9230312
2c5e5ec
140c88a
a0f096d
12301f9
cce1179
23287e9
df0a7e6
a63b4b2
ba80a92
a4208c4
a7402c6
852f8f7
1b520a1
31e477b
08cd6c1
d885185
dfb8024
b5ffa5b
d389e21
4573c0d
e57741d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Validate test environment cleaner | ||
|
||
on: | ||
pull_request: | ||
paths: | ||
- 'jenkins_pipelines/scripts/test_environment_cleaner/**' | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Validate api manager script | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set up Python 3.11 | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.11' | ||
|
||
- name: Install dependencies | ||
run: | | ||
python3.11 -m pip install --upgrade pip | ||
pip3.11 install -r jenkins_pipelines/scripts/test_environment_cleaner/requirements.txt | ||
|
||
- name: Run tests | ||
run: cd jenkins_pipelines/scripts/test_environment_cleaner; ./run_tests.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
def run(params) { | ||
timestamps { | ||
// Define paths and environment variables for reusability | ||
GString TestEnvironmentCleanerProgram = "${WORKSPACE}/susemanager-ci/jenkins_pipelines/scripts/test_environment_cleaner/test_environment_cleaner_program/TestEnvironmentCleaner.py" | ||
GString resultdir = "${WORKSPACE}/results" | ||
GString resultdirbuild = "${resultdir}/${BUILD_NUMBER}" | ||
GString exports = "export BUILD_NUMBER=${BUILD_NUMBER}; export BUILD_VALIDATION=true; " | ||
String container_repository = params.container_repository ?: null | ||
String product_version = null | ||
String controllerHostname = null | ||
String serverHostname = null | ||
GString targetedTfFile = "${WORKSPACE}/../${params.targeted_project}/results/sumaform/main.tf" | ||
GString targetedTfStateFile = "${WORKSPACE}/../${params.targeted_project}/results/sumaform/terraform.tfstate" | ||
GString targetedTerraformDirPath = "${WORKSPACE}/../${params.targeted_project}/results/sumaform/" | ||
GString localSumaformDirPath = "${resultdir}/sumaform/" | ||
GString localTfStateFile = "${localSumaformDirPath}/terraform.tfstate" | ||
GString logFile = "${resultdirbuild}/sumaform.log" | ||
|
||
// Construct the --tf-resources-to-delete argument dynamically | ||
ArrayList defaultResourcesToDelete = [] | ||
if (params.clean_proxy) { | ||
defaultResourcesToDelete.add('proxy') | ||
} | ||
if (params.clean_monitoring_server) { | ||
defaultResourcesToDelete.add('monitoring-server') | ||
} | ||
if (params.clean_retail) { | ||
defaultResourcesToDelete.add('retail') | ||
maximenoel8 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
String defaultResourcesToDeleteArgs = defaultResourcesToDelete.isEmpty() ? '' : "--default-resources-to-delete ${defaultResourcesToDelete.join(' ')}" | ||
|
||
GString commonParams = "--outputdir ${resultdir} --tf ${targetedTfFile} --gitfolder ${resultdir}/sumaform" | ||
|
||
// Define shared environment variables for terraform calls | ||
GString environmentVars = """ | ||
set -x | ||
source /home/jenkins/.credentials | ||
export TF_VAR_CONTAINER_REPOSITORY=${container_repository} | ||
export TERRAFORM=${terraform_bin} | ||
export TERRAFORM_PLUGINS=${terraform_bin_plugins} | ||
""" | ||
|
||
try { | ||
stage('Clone terracumber, susemanager-ci and sumaform') { | ||
|
||
// Prevent rebuild option | ||
if (currentBuild.getBuildCauses().toString().contains("RebuildCause")) { | ||
error "Rebuild is blocked for this job." | ||
} | ||
|
||
// Create a directory to store the build results (if it does not exist). Needed for first run | ||
sh "mkdir -p ${resultdir}" | ||
git url: params.terracumber_gitrepo, branch: params.terracumber_ref | ||
dir("susemanager-ci") { | ||
checkout scm | ||
} | ||
|
||
// Clone sumaform | ||
sh "set +x; source /home/jenkins/.credentials set -x; ${WORKSPACE}/terracumber-cli ${commonParams} --gitrepo ${params.sumaform_gitrepo} --gitref ${params.sumaform_ref} --runstep gitsync" | ||
|
||
// Set product version | ||
if (params.targeted_project.contains("5.0")) { | ||
product_version = '5.0' | ||
} else if (params.targeted_project.contains("4.3")) { | ||
product_version = '4.3' | ||
} else if (params.targeted_project.contains("uyuni")) { | ||
product_version = 'uyuni' | ||
} else if (params.targeted_project.contains("5.1")) { | ||
product_version = '5.1' | ||
} else if (params.targeted_project.contains("head")) { | ||
product_version = 'head' | ||
} | ||
else { | ||
// Use the `error` step instead of `throw` | ||
error("Error: targeted_project must contain either 'head', '5.1', '5.0', '4.3' or uyuni.") | ||
} | ||
} | ||
|
||
stage('Confirm Environment Cleanup') { | ||
// Ask the user what environment they are cleaning, ensuring the answer matches params.targeted_project | ||
def environmentChoice = input( | ||
message: 'What environment are you cleaning?', | ||
parameters: [ | ||
string(name: 'Environment_Name', description: 'Enter the name of the environment you are cleaning.') | ||
] | ||
) | ||
|
||
// Validate that the user entered the correct environment | ||
if (environmentChoice != params.targeted_project) { | ||
error("The environment name entered does not match the targeted project. Aborting pipeline.") | ||
} | ||
} | ||
|
||
stage("Copy terraform files from ${params.targeted_project}"){ | ||
// Copy tfstate and terraform directory to the result directory | ||
sh """ | ||
cp ${targetedTfStateFile} ${localTfStateFile} | ||
cp -r ${targetedTerraformDirPath}.terraform ${localSumaformDirPath} | ||
""" | ||
maximenoel8 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
} | ||
|
||
stage("Extract the controller and server hostname") { | ||
try { | ||
controllerHostname = sh( | ||
script: """ | ||
set -e | ||
cd ${localSumaformDirPath} | ||
terraform output -json configuration | jq -r '.controller.hostname' | ||
""", | ||
returnStdout: true | ||
).trim() | ||
|
||
serverHostname = sh( | ||
script: """ | ||
set -e | ||
cd ${localSumaformDirPath} | ||
terraform output -json configuration | jq -r '.server.hostname' | ||
""", | ||
returnStdout: true | ||
).trim() | ||
|
||
// Print the values for confirmation | ||
echo "Extracted controller hostname: ${controllerHostname}" | ||
echo "Extracted server hostname: ${serverHostname}" | ||
|
||
} catch (Exception e) { | ||
error("Failed to extract hostnames: ${e.message}") | ||
} | ||
|
||
} | ||
|
||
GString programCall = "${TestEnvironmentCleanerProgram} --url ${serverHostname} --product_version ${product_version} ${defaultResourcesToDeleteArgs} --mode" | ||
|
||
stage('Delete the systems') { | ||
sh(script: "${programCall} delete_systems") | ||
} | ||
stage('Delete config projects') { | ||
sh(script: "${programCall} delete_config_projects") | ||
} | ||
stage('Delete software channels') { | ||
sh(script: "${programCall} delete_software_channels") | ||
} | ||
stage('Delete activation keys') { | ||
sh(script: "${programCall} delete_activation_keys") | ||
} | ||
stage('Delete minion users') { | ||
sh(script: "${programCall} delete_users") | ||
} | ||
stage('Delete channel repositories') { | ||
sh(script: "${programCall} delete_repositories") | ||
} | ||
stage('Delete salt keys') { | ||
sh(script: "${programCall} delete_salt_keys") | ||
} | ||
|
||
stage('Delete ssh know hosts') { | ||
sh(script: "${TestEnvironmentCleanerProgram} --url ${serverHostname} --product_version ${product_version} --mode delete_known_hosts") | ||
} | ||
|
||
stage('Delete distributions folders') { | ||
sh(script: "${TestEnvironmentCleanerProgram} --url ${serverHostname} --product_version ${product_version} --mode delete_distributions") | ||
} | ||
|
||
stage('Delete client VMs') { | ||
|
||
// Construct the --tf-resources-to-delete argument dynamically | ||
ArrayList tfResourcesToDelete = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can reuse the lists at line 20 and 31. |
||
if (params.clean_proxy) { | ||
tfResourcesToDelete.add('proxy') | ||
} | ||
if (params.clean_monitoring_server) { | ||
tfResourcesToDelete.add('monitoring-server') | ||
} | ||
if (params.clean_retail) { | ||
tfResourcesToDelete.add('retail') | ||
} | ||
|
||
// Join the resources into a comma-separated string if there are any to delete | ||
String tfResourcesToDeleteArg = defaultResourcesToDelete.isEmpty() ? '' : "--tf-resources-to-delete ${defaultResourcesToDelete.join(' ')}" | ||
|
||
// Execute Terracumber CLI to deploy the environment without clients | ||
sh """ | ||
${environmentVars} | ||
set +x | ||
${WORKSPACE}/terracumber-cli ${commonParams} --logfile ${logFile} --init --sumaform-backend ${sumaform_backend} --use-tf-resource-cleaner --init --runstep provision ${tfResourcesToDeleteArg} | ||
""" | ||
} | ||
|
||
stage('Redeploy the environment with new client VMs') { | ||
|
||
// Run Terracumber to deploy the environment | ||
sh """ | ||
${environmentVars} | ||
set +x | ||
${WORKSPACE}/terracumber-cli ${commonParams} --logfile ${resultdirbuild}/sumaform.log --init --sumaform-backend ${sumaform_backend} --runstep provision | ||
""" | ||
} | ||
|
||
stage('Copy the new custom repository json file to controller') { | ||
if (params.push_new_custom_repositories) { | ||
// Generate custom_repositories.json file in the workspace from the value passed by parameter | ||
if (params.custom_repositories?.trim()) { | ||
writeFile file: 'custom_repositories.json', text: params.custom_repositories, encoding: "UTF-8" | ||
} | ||
|
||
// Generate custom_repositories.json file in the workspace using a Python script - MI Identifiers passed by parameter | ||
if (params.mi_ids?.trim()) { | ||
node('manager-jenkins-node') { | ||
checkout scm | ||
res_python_script_ = sh(script: "python3 jenkins_pipelines/scripts/json_generator/maintenance_json_generator.py --mi_ids ${params.mi_ids}", returnStatus: true) | ||
echo "Build Validation JSON script return code:\n ${json_content}" | ||
if (res_python_script != 0) { | ||
error("MI IDs (${params.mi_ids}) passed by parameter are wrong (or already released)") | ||
} | ||
} | ||
} | ||
sh(script: "${TestEnvironmentCleanerProgram} --url ${controllerHostname} --product_version ${product_version} --mode update_custom_repositories") | ||
} | ||
} | ||
|
||
stage('Sanity check') { | ||
sh "${WORKSPACE}/terracumber-cli ${commonParams} --logfile ${resultdirbuild}/testsuite.log --runstep cucumber --cucumber-cmd 'cd /root/spacewalk/testsuite; ${exports} rake cucumber:build_validation_sanity_check'" | ||
} | ||
|
||
} | ||
finally { | ||
stage('Copy back tfstate') { | ||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { | ||
sh "cp ${localTfStateFile} ${targetedTfStateFile}" | ||
} | ||
} | ||
Comment on lines
+229
to
+233
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if copying the old tfstate will be enough if there is a failure... |
||
|
||
stage('Rename tfstate to avoid copying it between runs') { | ||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { | ||
sh "mv ${localTfStateFile} ${localTfStateFile}.old" | ||
sh "cp ${localTfStateFile}.old ${resultdirbuild}" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return this |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/usr/bin/env groovy | ||
|
||
node { | ||
// Default node | ||
String nodeName = 'sumaform-cucumber' | ||
|
||
// Check the value of targeted_project and adjust the nodeName accordingly | ||
if (params.targeted_project.contains('PRV')) { | ||
nodeName = 'sumaform-cucumber-provo' // Use this for PRV projects | ||
} else if (params.targeted_project.contains('NUE')) { | ||
nodeName = 'sumaform-cucumber' // Use this for NUE projects | ||
} | ||
|
||
// Run on the selected node | ||
node(nodeName) { | ||
properties([ | ||
buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '3')), | ||
disableConcurrentBuilds(), | ||
parameters([ | ||
choice(name: 'targeted_project', choices: [ | ||
'default', | ||
'manager-4.3-qe-build-validation-NUE', | ||
'manager-5.0-qe-build-validation-NUE', | ||
'manager-5.0-qe-build-validation-weekly-NUE', | ||
'uyuni-master-qe-build-validation-NUE', | ||
'manager-4.3-qe-build-validation-PRV', | ||
'manager-5.0-qe-build-validation-PRV', | ||
'uyuni-master-qe-build-validation-PRV' | ||
], description: 'Path to the tf file to be used'), | ||
string(name: 'sumaform_gitrepo', defaultValue: 'https://github.com/uyuni-project/sumaform.git', description: 'Sumaform Git Repository'), | ||
string(name: 'sumaform_ref', defaultValue: 'master', description: 'Sumaform Git reference (branch, tag...)'), | ||
string(name: 'terracumber_gitrepo', defaultValue: 'https://github.com/uyuni-project/terracumber.git', description: 'Terracumber Git Repository'), | ||
string(name: 'terracumber_ref', defaultValue: 'master', description: 'Terracumber Git ref (branch, tag...)'), | ||
string(name: 'container_repository', defaultValue: 'registry.suse.de/suse/sle-15-sp6/update/products/manager50/update/containerfile', description: 'Proxy and server container registry'), | ||
booleanParam(name: 'clean_proxy', defaultValue: false, description: 'Clean Proxy, will remove all the artefacts related to Proxy and redeploy Proxy'), | ||
booleanParam(name: 'clean_monitoring_server', defaultValue: false, description: 'Clean Monitoring Server, will remove all the artefacts related to Monitoring Server and redeploy Monitoring Server'), | ||
booleanParam(name: 'clean_retail', defaultValue: false, description: 'Clean Retails artefacts, and redeploy terminal and dhcp if applicable'), | ||
booleanParam(name: 'push_new_custom_repositories', defaultValue: false, description: 'Push the new custom_repositories.json to controller'), | ||
text(name: 'mi_ids', defaultValue: '', description: 'MI Identifiers separated by comma or whitespaces (Option A)'), | ||
text(name: 'custom_repositories', defaultValue: '{}', description: 'MU Repositories in json format (Option B)') | ||
]) | ||
]) | ||
|
||
stage('Checkout pipeline') { | ||
checkout scm | ||
} | ||
|
||
// Define environment variables | ||
env.sumaform_backend = 'libvirt' | ||
env.terraform_bin = '/usr/bin/terraform' | ||
env.terraform_bin_plugins = '/usr/bin' | ||
|
||
// Load and run the pipeline | ||
def pipeline = load "jenkins_pipelines/environments/common/pipeline-build-validation-cleanup.groovy" | ||
pipeline.run(params) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# SUSE Manager API and SSH Management Script | ||
|
||
This Python script provides a command-line interface to manage various resources and configurations on a SUSE Manager server through the XML-RPC API and SSH commands. | ||
The script enables testers to perform resource cleanup, SSH-based file management, and update custom repositories remotely. | ||
|
||
## Prerequisites | ||
|
||
- **Python 3.11**: Ensure Python 3.11 is installed. | ||
- **Dependencies**: Install the required packages using: | ||
|
||
```bash | ||
pip3.11 install -r test_environment_cleaner/requirements.txt | ||
``` | ||
|
||
## Usage | ||
|
||
```commandline | ||
python3.11 TestEnvironmentCleaner.py --url <SUSE_Manager_URL> --mode <operation_mode> [options] | ||
``` | ||
|
||
### Command-Line Arguments | ||
|
||
- `--url`: (Required) URL of the SUSE Manager XML-RPC API. | ||
- `--mode`: (Required) Operation mode. Choose one of the following: | ||
`delete_users`: Deletes user accounts. | ||
`delete_activation_keys`: Deletes activation keys. | ||
`delete_config_projects`: Deletes configuration projects. | ||
`delete_software_channels`: Deletes software channels. | ||
`delete_systems`: Deletes managed systems. | ||
`delete_repositories`: Deletes repositories. | ||
`delete_salt_keys`: Deletes Salt keys. | ||
`full_cleanup`: Runs a complete cleanup of selected resources. | ||
`delete_distributions`: Deletes distributions from the server. | ||
`delete_known_hosts`: Deletes known SSH hosts in server. | ||
`update_custom_repositories`: Updates custom repositories in controller. | ||
- `--default-resources-to-delete`: Optional list of resources (proxy, monitoring-server, retail) to enforce deletion during API cleanup operations. | ||
- `--product_version`: SUSE Manager version (head, 5.1, 5.0, 4.3 or uyuni). Used for handling different paths in specific operations. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
argparse | ||
logging | ||
paramiko |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/bash | ||
|
||
# Set the PYTHONPATH to include the necessary directories | ||
export PYTHONPATH=$(pwd)/test_environment_cleaner_program | ||
|
||
# Run the tests | ||
python3.11 -m unittest discover -s tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! I did not know about this syntax in Groovy!