diff --git a/Jenkinsfile b/Jenkinsfile index 1a7e8efc..35c6f651 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,19 +21,56 @@ LINT_OUTPUT = '' SCAN_OUTPUT = '' IMAGE_SIZE = 0 RPMversion = '' +GRAVITON3_IMAGE_ARCHIVE = 'marklogic-image.tar' +builtImage = '' +publishImage = '' +latestTag = '' +upgradeDockerImage = '' // Define local funtions +/** + * Determines if the current build is for an ARM image type. + * ARM workers (e.g., Graviton3) are only available for MarkLogic 11. + * @return true if dockerImageType contains 'arm', false otherwise. + */ +@NonCPS +def isArmImage() { + return params.dockerImageType.toLowerCase().contains('arm') +} + /** * Performs pre-build checks: * - Initializes parameters as environment variables. * - Extracts Jira ID from branch name or PR title. * - Checks if the PR is a draft or has requested changes (for PR builds). + * - Validates ARM image types are only used with MarkLogic 11. */ void preBuildCheck() { // Initialize parameters as env variables (workaround for https://issues.jenkins-ci.org/browse/JENKINS-41929) evaluate """${ def script = ''; params.each { k, v -> script += "env.${k} = '''${v}'''\n" }; return script}""" + // Validate ARM images are only supported for MarkLogic 11 + if (env.dockerImageType.contains('arm') && env.marklogicVersion != '11') { + error "ARM images (${env.dockerImageType}) are only supported for MarkLogic 11. Current version: ${env.marklogicVersion}" + } + + // If GRAVITON3_IP is not provided, try to retrieve it from Jenkins credentials + if (!params.GRAVITON3_IP) { + withCredentials([sshUserPrivateKey(credentialsId: 'KUBE_NINJAS_AWS_JENKINS', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'GRAVITON_IP_FROM_SECRET')]) { + env.GRAVITON3_IP = env.GRAVITON_IP_FROM_SECRET + echo "GRAVITON3_IP retrieved from Jenkins credentials: ${env.GRAVITON3_IP}" + } + } else { + env.GRAVITON3_IP = params.GRAVITON3_IP + echo "Using provided GRAVITON3_IP parameter: ${env.GRAVITON3_IP}" + } + + // Validate that ARM builds have GRAVITON3_IP available + if (env.dockerImageType.contains('arm') && !env.GRAVITON3_IP) { + error "ARM image type ${env.dockerImageType} requires GRAVITON3_IP parameter or KUBE_NINJAS_AWS_JENKINS credentials to be configured. Please provide the Graviton3 instance IP or hostname." + } + JIRA_ID = extractJiraID() echo 'Jira ticket number: ' + JIRA_ID @@ -180,6 +217,9 @@ void resultNotification(status) { * Sets RPM, CONVERTERS, and marklogicVersion global variables. */ void copyRPMs() { + // Determine architecture suffix based on image type + def archSuffix = dockerImageType.contains('arm') ? 'aarch64' : 'x86_64' + if (marklogicVersion == "10") { RPMsuffix = "-nightly" RPMbranch = "b10" @@ -205,23 +245,34 @@ void copyRPMs() { } sh """ cd src + ARM_DATE=\$(TZ=America/Los_Angeles date +%Y%m%d) if [ -z ${env.ML_RPM} ]; then - wget --no-verbose https://bed-artifactory.bedford.progress.com:443/artifactory/ml-rpm-tierpoint/${RPMbranch}/server/MarkLogic-${RPMversion}${RPMsuffix}.x86_64.rpm + if [ "${archSuffix}" = "aarch64" ]; then + wget --no-verbose https://bed-artifactory.bedford.progress.com:443/artifactory/ml-rpm-dev-tierpoint/${RPMbranch}/server-arm/MarkLogic-${RPMversion}.\${ARM_DATE}-rhel9.aarch64.rpm + else + wget --no-verbose https://bed-artifactory.bedford.progress.com:443/artifactory/ml-rpm-tierpoint/${RPMbranch}/server/MarkLogic-${RPMversion}${RPMsuffix}.${archSuffix}.rpm + fi else - wget --no-verbose ${ML_RPM} + wget --no-verbose ${ML_RPM} fi - if [ -z ${env.ML_CONVERTERS}]; then - wget --no-verbose https://bed-artifactory.bedford.progress.com:443/artifactory/ml-rpm-tierpoint/${RPMbranch}/converters/MarkLogicConverters-${RPMversion}${RPMsuffix}.x86_64.rpm + if [ -z ${env.ML_CONVERTERS} ]; then + if [ "${archSuffix}" = "aarch64" ]; then + # ARM converters package not yet available in Artifactory - converters can be installed at runtime via INSTALL_CONVERTERS env var + # For now, create a placeholder to allow build to proceed + touch MarkLogicConverters-placeholder.rpm + else + wget --no-verbose https://bed-artifactory.bedford.progress.com:443/artifactory/ml-rpm-tierpoint/${RPMbranch}/converters/MarkLogicConverters-${RPMversion}${RPMsuffix}.${archSuffix}.rpm + fi else - wget --no-verbose ${ML_CONVERTERS} + wget --no-verbose ${ML_CONVERTERS} fi """ script { - // Get the RPM and Converters file names - RPM = sh(returnStdout: true, script: 'cd src;file MarkLogic-*.rpm | cut -d: -f1').trim() - CONVERTERS = sh(returnStdout: true, script: 'cd src;file MarkLogicConverters-*.rpm | cut -d: -f1').trim() - // Extract MarkLogic version from RPM file name - marklogicVersion = sh(returnStdout: true, script: "echo ${RPM}| awk -F \"MarkLogic-\" '{print \$2;}' | awk -F \".x86_64.rpm\" '{print \$1;}' | awk -F \"-rhel\" '{print \$1;}' ").trim() + // Get the RPM and Converters file names for the correct architecture (archSuffix already defined above) + RPM = sh(returnStdout: true, script: "cd src; ls -1 MarkLogic-*.${archSuffix}.rpm 2>/dev/null | head -1").trim() + CONVERTERS = sh(returnStdout: true, script: "cd src; ls -1 MarkLogicConverters-*.${archSuffix}.rpm 2>/dev/null || ls -1 MarkLogicConverters-*.rpm 2>/dev/null | head -1").trim() + // Extract MarkLogic version from RPM file name (handle both x86_64 and aarch64) + marklogicVersion = sh(returnStdout: true, script: "echo ${RPM} | awk -F 'MarkLogic-' '{print \$2;}' | awk -F '.x86_64.rpm' '{print \$1;}' | awk -F '.aarch64.rpm' '{print \$1;}' | awk -F '-rhel' '{print \$1;}'").trim() } } @@ -235,10 +286,12 @@ void buildDockerImage() { publishImage="marklogic/marklogic-server-${dockerImageType}:${marklogicVersion}-${env.dockerImageType}" mlVerShort=marklogicVersion.split("\\.")[0] latestTag="marklogic/marklogic-server-${dockerImageType}:latest-${mlVerShort}" - timeStamp = new Date().format('yyyyMMdd') + // Use Los Angeles time (same as ARM_DATE in copyRPMs) to ensure consistency across UTC/PST boundaries + timeStamp = sh(returnStdout: true, script: "TZ=America/Los_Angeles date +%Y%m%d").trim() timestamptedTag = builtImage.replace('nightly', timeStamp) sh "make build docker_image_type=${dockerImageType} dockerTag=${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} marklogicVersion=${marklogicVersion} dockerVersion=${env.dockerVersion} build_branch=${env.BRANCH_NAME} package=${RPM} converters=${CONVERTERS}" currentBuild.displayName = "#${BUILD_NUMBER}: ${marklogicVersion}-${env.dockerImageType} (${env.dockerVersion})" + echo "Built image: ${builtImage}" } /** @@ -251,6 +304,10 @@ void pullUpgradeDockerImage() { sh """ echo 'dockerImageType is set to ubi-rootless, skipping this stage and Docker upgrade test.' """ + } else if (isArmImage()) { + sh """ + echo 'ARM image type detected. Skipping upgrade test (no previous ARM images available for upgrade testing).' + """ } else { if (upgradeDockerImage != "" ) { sh """ @@ -272,8 +329,14 @@ void pullUpgradeDockerImage() { */ void structureTests() { sh """ - #install container-structure-test 1.16.0 binary - curl -s -LO https://storage.googleapis.com/container-structure-test/v1.16.0/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && mv container-structure-test-linux-amd64 container-structure-test + #install container-structure-test 1.16.0 binary (detect architecture) + ARCH=\$(uname -m) + if [ "\$ARCH" = "aarch64" ]; then + PLATFORM="arm64" + else + PLATFORM="amd64" + fi + curl -s -LO https://storage.googleapis.com/container-structure-test/v1.16.0/container-structure-test-linux-\${PLATFORM} && chmod +x container-structure-test-linux-\${PLATFORM} && mv container-structure-test-linux-\${PLATFORM} container-structure-test make structure-test current_image=marklogic/marklogic-server-${dockerImageType}:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} marklogicVersion=${marklogicVersion} dockerVersion=${env.dockerVersion} build_branch=${env.BRANCH_NAME} docker_image_type=${env.dockerImageType} Jenkins=true """ } @@ -330,15 +393,16 @@ void vulnerabilityScan() { * Requires Artifactory and Azure ACR credentials. */ void publishToInternalRegistry() { + // Use the discovered image tag if available (handles date/time mismatches across day boundaries) + def imageToPublish = env.IMAGE_TO_PUBLISH ?: builtImage + echo "Publishing image: ${imageToPublish}" + withCredentials([usernamePassword(credentialsId: 'builder-credentials-artifactory', passwordVariable: 'docker_password', usernameVariable: 'docker_user')]) { sh """ docker logout ${dockerRegistry} echo "${docker_password}" | docker login --username ${docker_user} --password-stdin ${dockerRegistry} - docker tag ${builtImage} ${dockerRegistry}/${builtImage} - docker tag ${builtImage} ${dockerRegistry}/${publishImage} - docker tag ${builtImage} ${dockerRegistry}/${latestTag} - docker tag ${builtImage} ${dockerRegistry}/${timestamptedTag} - docker push ${dockerRegistry}/${builtImage} + docker tag ${imageToPublish} ${dockerRegistry}/${publishImage} + docker tag ${imageToPublish} ${dockerRegistry}/${latestTag} docker push ${dockerRegistry}/${publishImage} docker push ${dockerRegistry}/${latestTag} docker push ${dockerRegistry}/${timestamptedTag} @@ -370,8 +434,8 @@ void publishToInternalRegistry() { withCredentials([usernamePassword(credentialsId: 'PDC_SANDBOX_USER', passwordVariable: 'docker_password', usernameVariable: 'docker_user')]) { sh """ echo "${docker_password}" | docker login --username ${docker_user} --password-stdin ${pdcSbRegistry} - docker tag ${builtImage} ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} - docker tag ${builtImage} ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType} + docker tag ${imageToPublish} ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} + docker tag ${imageToPublish} ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType} docker push ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} docker push ${pdcSbRegistry}/ml-docker-nightly:${marklogicVersion}-${env.dockerImageType} """ @@ -380,8 +444,8 @@ void publishToInternalRegistry() { withCredentials([usernamePassword(credentialsId: 'pdc-azure-cr', passwordVariable: 'docker_password', usernameVariable: 'docker_user')]) { sh """ echo "${docker_password}" | docker login --username ${docker_user} --password-stdin ${pdcDevRegistry} - docker tag ${builtImage} ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} - docker tag ${builtImage} ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType} + docker tag ${imageToPublish} ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} + docker tag ${imageToPublish} ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType} docker push ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType}-${env.dockerVersion} docker push ${pdcDevRegistry}/marklogicdb-custom:${marklogicVersion}-${env.dockerImageType} """ @@ -436,11 +500,7 @@ void scapScan() { } pipeline { - agent { - label { - label 'cld-docker' - } - } + agent none options { checkoutToSubdirectory '.' buildDiscarder logRotator(artifactDaysToKeepStr: '7', artifactNumToKeepStr: '', daysToKeepStr: '30', numToKeepStr: '') @@ -450,19 +510,26 @@ pipeline { // Trigger nightly builds on the develop branch for every supported version of MarkLogic // and for every supported image type. // Include SCAP scan for rootless images - parameterizedCron( env.BRANCH_NAME == 'develop' ? '''00 04 * * * % marklogicVersion=10;dockerImageType=ubi - 00 04 * * * % marklogicVersion=10;dockerImageType=ubi-rootless;SCAP_SCAN=true - 00 03 * * * % marklogicVersion=11;dockerImageType=ubi - 00 03 * * * % marklogicVersion=11;dockerImageType=ubi-rootless;SCAP_SCAN=true - 00 03 * * * % marklogicVersion=11;dockerImageType=ubi9 - 00 03 * * * % marklogicVersion=11;dockerImageType=ubi9-rootless;SCAP_SCAN=true - 00 02 * * * % marklogicVersion=12;dockerImageType=ubi - 00 02 * * * % marklogicVersion=12;dockerImageType=ubi-rootless;SCAP_SCAN=true - 00 02 * * * % marklogicVersion=12;dockerImageType=ubi9 - 00 02 * * * % marklogicVersion=12;dockerImageType=ubi9-rootless;SCAP_SCAN=true - 00 05 * * 7 % marklogicVersion=10;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency - 30 05 * * 7 % marklogicVersion=11;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency - 00 06 * * 7 % marklogicVersion=12;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency''' : '') + parameterizedCron( + env.BRANCH_NAME == 'develop' ? ''' + 03 04 * * * % marklogicVersion=11;dockerImageType=ubi9-arm + 00 04 * * * % marklogicVersion=11;dockerImageType=ubi9-arm-rootless;SCAP_SCAN=true + 00 04 * * * % marklogicVersion=10;dockerImageType=ubi + 00 04 * * * % marklogicVersion=10;dockerImageType=ubi-rootless;SCAP_SCAN=true + 00 03 * * * % marklogicVersion=11;dockerImageType=ubi + 00 03 * * * % marklogicVersion=11;dockerImageType=ubi-rootless;SCAP_SCAN=true + 00 03 * * * % marklogicVersion=11;dockerImageType=ubi9 + 00 03 * * * % marklogicVersion=11;dockerImageType=ubi9-rootless;SCAP_SCAN=true + 00 02 * * * % marklogicVersion=12;dockerImageType=ubi + 00 02 * * * % marklogicVersion=12;dockerImageType=ubi-rootless;SCAP_SCAN=true + 00 02 * * * % marklogicVersion=12;dockerImageType=ubi9 + 00 02 * * * % marklogicVersion=12;dockerImageType=ubi9-rootless;SCAP_SCAN=true + 00 05 * * 7 % marklogicVersion=10;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency + 30 05 * * 7 % marklogicVersion=11;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency + 00 06 * * 7 % marklogicVersion=12;dockerImageType=ubi;DOCKER_TEST_LIST=Initialized MarkLogic container with latency''' : + env.BRANCH_NAME == 'Docker-ARM-support' ? ''' + 03 04 * * * % marklogicVersion=11;dockerImageType=ubi9-arm + 00 04 * * * % marklogicVersion=11;dockerImageType=ubi9-arm-rootless;SCAP_SCAN=true''' : '') } environment { QA_LICENSE_KEY = credentials('QA_LICENSE_KEY') @@ -470,57 +537,74 @@ pipeline { parameters { string(name: 'emailList', defaultValue: emailList, description: 'List of email for build notification', trim: true) - string(name: 'dockerVersion', defaultValue: '2.2.3', description: 'ML Docker version. This version along with ML rpm package version will be the image tag as {ML_Version}_{dockerVersion}', trim: true) - choice(name: 'dockerImageType', choices: 'ubi-rootless\nubi\nubi9-rootless\nubi9', description: 'Platform type for Docker image. Will be made part of the docker image tag') + string(name: 'dockerVersion', defaultValue: '2.2.4', description: 'ML Docker version. This version along with ML rpm package version will be the image tag as {ML_Version}_{dockerVersion}', trim: true) + choice(name: 'dockerImageType', choices: 'ubi-rootless\nubi\nubi9-rootless\nubi9\nubi9-arm\nubi9-rootless-arm', description: 'Platform type for Docker image. Will be made part of the docker image tag') string(name: 'upgradeDockerImage', defaultValue: '', description: 'Docker image for testing upgrades. Defaults to ubi image if left blank.\n Currently upgrading to ubi-rotless is not supported hence the test is skipped when ubi-rootless image is provided.', trim: true) choice(name: 'marklogicVersion', choices: '12\n11\n10', description: 'MarkLogic Server Branch. used to pick appropriate rpm') string(name: 'ML_RPM', defaultValue: '', description: 'URL for RPM to be used for Image creation. \n If left blank nightly ML rpm will be used.\n Please provide Jenkins accessible path e.g. /project/engineering or /project/qa', trim: true) string(name: 'ML_CONVERTERS', defaultValue: '', description: 'URL for the converters RPM to be included in the image creation \n If left blank the nightly ML Converters Package will be used.', trim: true) booleanParam(name: 'PUBLISH_IMAGE', defaultValue: false, description: 'Publish image to internal registry') booleanParam(name: 'TEST_STRUCTURE', defaultValue: true, description: 'Run container structure tests') - booleanParam(name: 'DOCKER_TESTS', defaultValue: true, description: 'Run docker tests') - string(name: 'DOCKER_TEST_LIST', defaultValue: '', description: 'Comma separated list of test names to run (e.g Test one, Test two). Leave empty to run all tests.', trim: true) + booleanParam(name: 'DOCKER_TESTS', defaultValue: true, description: 'Run docker tests') + string(name: 'DOCKER_TEST_LIST', defaultValue: '', description: 'Comma separated list of test names to run (e.g Test one, Test two). Leave empty to run all tests.', trim: true) booleanParam(name: 'SCAP_SCAN', defaultValue: false, description: 'Run Open SCAP scan on the image.') + string(name: 'GRAVITON3_IP', defaultValue: '', description: '[ARM only] Public IP or hostname of Graviton3 instance. Will pull from secrets by default.', trim: true) } stages { // Stage: Perform initial checks (PR status, Jira ID) stage('Pre-Build-Check') { + agent { node { label 'cld-docker' } } steps { preBuildCheck() } } - // Stage: Download MarkLogic Server and Converters RPMs + // Stage: Download MarkLogic Server and Converters RPMs (ARM builds on x86) stage('Copy-RPMs') { + agent { node { label 'cld-docker' } } steps { copyRPMs() } } // Stage: Build the Docker image + // Save image archive to workspace and stash for cross-agent stages. stage('Build-Image') { + agent { node { label 'cld-docker' } } steps { buildDockerImage() + script { + // Always save image for cases where agents might differ + sh """ + echo "Saving ${builtImage} to ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}..." + docker image save ${builtImage} -o ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE} + ls -lh ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE} + """ + stash name: 'built-image-archive', includes: "${GRAVITON3_IMAGE_ARCHIVE}", allowEmpty: false + } } } // Stage: Pull the base image needed for upgrade testing stage('Pull-Upgrade-Image') { + agent { node { label 'cld-docker' } } steps { pullUpgradeDockerImage() } } - // Stage: Lint Dockerfile and startup scripts + // Stage: Lint Dockerfile and startup scripts (x86 only) stage('Lint') { + agent { node { label 'cld-docker' } } steps { lint() } } - // Stage: Scan the image for vulnerabilities + // Stage: Scan the image for vulnerabilities (x86 only) stage('Scan') { + agent { node { label 'cld-docker' } } steps { echo 'Skipping vulnerability scan due to compatibility issues.' // vulnerabilityScan() @@ -529,43 +613,156 @@ pipeline { // Stage: Run OpenSCAP compliance scan (conditional) stage('SCAP-Scan') { + agent { + node { + label isArmImage() ? 'cld-docker-graviton' : 'cld-docker' + } + } when { + beforeAgent true expression { return params.SCAP_SCAN } } steps { + script { + unstash 'built-image-archive' + // Load image from tar if not already available (applies to all build types) + def imageSource = "${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}" + sh """ + if ! docker image inspect ${builtImage} &>/dev/null; then + echo "Loading image from ${imageSource} for SCAP scan..." + docker image load -i ${imageSource} + else + echo "Image ${builtImage} already available locally" + fi + """ + } scapScan() + stash name: 'scap-results', includes: 'scap/**', allowEmpty: true + } + } + + // Stage: Load image from tar archive (ARM builds only) + stage('Load-Image') { + agent { label 'cld-docker-graviton' } + when { + beforeAgent true + expression { return isArmImage() && env.GRAVITON3_IP } + } + steps { + script { + unstash 'built-image-archive' + sh """ + if ! docker image inspect ${builtImage} &>/dev/null; then + echo "Loading image from ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}..." + docker image load -i ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE} + else + echo "Image ${builtImage} already loaded (likely by SCAP-Scan stage)" + fi + docker images | head -5 + """ + } } } // Stage: Run container structure tests (conditional) stage('Structure-Tests') { + agent { + node { + label isArmImage() ? 'cld-docker-graviton' : 'cld-docker' + } + } when { + beforeAgent true expression { return params.TEST_STRUCTURE } } steps { + script { + unstash 'built-image-archive' + // Load image from tar if not already available (applies to all build types) + def imageSource = "${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}" + sh """ + if ! docker image inspect ${builtImage} &>/dev/null; then + echo "Loading image from ${imageSource} for Structure-Tests..." + docker image load -i ${imageSource} + else + echo "Image ${builtImage} already available locally" + fi + """ + } structureTests() + stash name: 'structure-test-results', includes: 'container-structure-test.xml', allowEmpty: true } } // Stage: Run Docker functional tests (conditional) stage('Docker-Run-Tests') { + agent { + node { + label isArmImage() ? 'cld-docker-graviton' : 'cld-docker' + } + } when { + beforeAgent true expression { return params.DOCKER_TESTS } } steps { + script { + unstash 'built-image-archive' + // Load image from tar if not already available (applies to all build types) + def imageSource = "${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}" + sh """ + if ! docker image inspect ${builtImage} &>/dev/null; then + echo "Loading image from ${imageSource} for Docker-Run-Tests..." + docker image load -i ${imageSource} + else + echo "Image ${builtImage} already available locally" + fi + """ + } dockerTests() + stash name: 'docker-test-results', includes: 'test/test_results/**', allowEmpty: true } } // Stage: Publish image to internal registries (conditional) stage('Publish-Image') { + agent { node { label 'cld-docker' } } when { + beforeAgent true anyOf { branch 'develop' expression { return params.PUBLISH_IMAGE } } } steps { + script { + unstash 'built-image-archive' + // Load image from tar if not already available (applies to all build types) + sh """ + if ! docker image inspect ${builtImage} &>/dev/null; then + echo "Image not found locally, loading from ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE}..." + docker image load -i ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE} + else + echo "Image ${builtImage} already available locally" + fi + """ + + // If builtImage doesn't exist, find the loaded image by repo pattern + def actualImage = sh( + returnStdout: true, + script: """docker images --format 'table {{.Repository}}:{{.Tag}}' | grep "marklogic/marklogic-server-${dockerImageType}:" | head -1""" + ).trim() + + if (!actualImage) { + actualImage = builtImage + echo "Using builtImage tag: ${actualImage}" + } else { + echo "Found loaded image: ${actualImage}" + } + + // Store for use in publishToInternalRegistry + env.IMAGE_TO_PUBLISH = actualImage + } publishToInternalRegistry() // Trigger downstream QA image build job build job: 'KubeNinjas/docker/docker-nightly-builds-qa', wait: false, parameters: [string(name: 'dockerImageType', value: "${dockerImageType}"), string(name: 'marklogicVersion', value: "${RPMversion}")] @@ -574,6 +771,7 @@ pipeline { // Stage: Trigger BlackDuck security scan (conditional) stage('BlackDuck-Scan') { + agent { node { label 'cld-docker' } } when { anyOf { branch 'develop' @@ -585,19 +783,58 @@ pipeline { } } + // Stage: Cleanup ARM agent (ARM builds only) + stage('Cleanup-ARM') { + agent { label 'cld-docker-graviton' } + when { + beforeAgent true + expression { return isArmImage() && env.GRAVITON3_IP } + } + steps { + sh ''' + echo "Cleaning up ARM agent..." + # Stop all running containers + docker stop $(docker ps -a -q) || true + # Docker cleanup + docker system prune --force --all --volumes + docker system df + ''' + } + } + } post { always { - // Clean up the workspace and Docker resources - sh ''' - cd src - rm -rf *.rpm NOTICE.txt - docker stop $(docker ps -a -q) || true - docker system prune --force --all --volumes - docker system df - ''' - publishTestResults() + node('cld-docker') { + // Clean up the workspace and Docker resources + sh """ + # Remove any stale test artifacts before unstash + rm -rf test/test_results scap container-structure-test.xml + # Remove ARM image tar archive + rm -f ${WORKSPACE}/${GRAVITON3_IMAGE_ARCHIVE} + # Remove ARM image if it was built + if [ -n "${builtImage}" ]; then + docker rmi ${builtImage} || true + fi + # Clean up RPMs + if [ -d src ]; then + cd src + rm -rf *.rpm NOTICE.txt + cd .. + fi + # Docker cleanup applies to both agents + docker stop \$(docker ps -a -q) || true + docker system prune --force --all --volumes + docker system df + """ + script { + try { unstash 'structure-test-results' } catch (e) { echo 'No structure test results to unstash.' } + try { unstash 'docker-test-results' } catch (e) { echo 'No docker test results to unstash.' } + try { unstash 'scap-results' } catch (e) { echo 'No SCAP results to unstash.' } + } + publishTestResults() + } } success { resultNotification('✅ Success') diff --git a/Makefile b/Makefile index cc5b405e..47a4a4cd 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -# Copyright © 2018-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. dockerTag?=internal package?=MarkLogic.rpm repo_dir=marklogic -docker_build_options=--compress --platform linux/amd64 +docker_build_options=--compress build_branch?=local docker_image_type?=ubi upgrade_docker_image_type?=ubi @@ -11,6 +11,17 @@ current_image?=${repo_dir}/marklogic-server-${docker_image_type}:${dockerTag} # Latest release tag can be found here: https://github.com/ComplianceAsCode/content/releases open_scap_version?=0.1.79 +#*************************************************************************** +# set docker platform based on the docker image type +#*************************************************************************** +ifeq ($(findstring arm,$(docker_image_type)),arm) + docker_build_options += --platform linux/arm64 + export DOCKER_PLATFORM=linux/arm64 +else + docker_build_options += --platform linux/amd64 + export DOCKER_PLATFORM=linux/amd64 +endif + #*************************************************************************** # build docker image #*************************************************************************** @@ -18,6 +29,13 @@ build: # NOTICE file need to be in the build context to be included in the built image cp NOTICE.txt src/NOTICE.txt +# Install ARM64 emulation support on Linux (assuming Jenkins environment which is not aarch64) +ifeq ($(findstring arm,$(docker_image_type)),arm) +ifeq ($(shell uname -s),Linux) + docker run --privileged --rm tonistiigi/binfmt --install arm64 +endif +endif + # rootless images use the same dependencies as ubi image so we copy the file ifeq ($(docker_image_type),ubi9) cp dockerFiles/marklogic-server-ubi\:base dockerFiles/marklogic-server-ubi9\:base @@ -27,10 +45,15 @@ ifeq ($(findstring rootless,$(docker_image_type)),rootless) cp dockerFiles/marklogic-deps-ubi9\:base dockerFiles/marklogic-deps-ubi9-rootless\:base cp dockerFiles/marklogic-server-ubi-rootless\:base dockerFiles/marklogic-server-ubi9-rootless\:base endif +# ubi9-rootless-arm needs deps from ubi9-arm and server template from ubi-rootless +ifeq ($(docker_image_type),ubi9-rootless-arm) + cp dockerFiles/marklogic-deps-ubi9-arm\:base dockerFiles/marklogic-deps-ubi9-rootless-arm\:base + cp dockerFiles/marklogic-server-ubi-rootless\:base dockerFiles/marklogic-server-ubi9-rootless-arm\:base +endif # retrieve and copy open scap hardening script ifeq ($(findstring rootless,$(docker_image_type)),rootless) - [ -f scap-security-guide-${open_scap_version}.zip ] || curl -Lo scap-security-guide-${open_scap_version}.zip https://github.com/ComplianceAsCode/content/releases/download/v${open_scap_version}/scap-security-guide-${open_scap_version}.zip + [ -f scap-security-guide-${open_scap_version}.zip ] || curl -Lso scap-security-guide-${open_scap_version}.zip https://github.com/ComplianceAsCode/content/releases/download/v${open_scap_version}/scap-security-guide-${open_scap_version}.zip #UBI9 needs a different version of the remediation script ifeq ($(findstring ubi9,$(docker_image_type)),ubi9) unzip -p scap-security-guide-${open_scap_version}.zip scap-security-guide-${open_scap_version}/bash/rhel9-script-cis.sh > src/rhel-script-cis.sh @@ -45,7 +68,7 @@ endif cd src/; docker build ${docker_build_options} -t "${repo_dir}/marklogic-server-${docker_image_type}:${dockerTag}" --build-arg BASE_IMAGE=${repo_dir}/marklogic-deps-${docker_image_type}:${dockerTag} --build-arg ML_RPM=${package} --build-arg ML_USER=marklogic_user --build-arg ML_DOCKER_VERSION=${dockerVersion} --build-arg ML_VERSION=${marklogicVersion} --build-arg ML_CONVERTERS=${converters} --build-arg BUILD_BRANCH=${build_branch} --build-arg ML_DOCKER_TYPE=${docker_image_type} -f ../dockerFiles/marklogic-server-${docker_image_type}:base . # remove temporary files - rm -f dockerFiles/marklogic-deps-ubi-rootless\:base dockerFiles/marklogic-deps-ubi9-rootless\:base dockerFiles/marklogic-server-ubi9-rootless\:base dockerFiles/marklogic-server-ubi9\:base src/NOTICE.txt src/rhel-script-cis.sh + rm -f dockerFiles/marklogic-deps-ubi-rootless\:base dockerFiles/marklogic-deps-ubi9-rootless\:base dockerFiles/marklogic-server-ubi9-rootless\:base dockerFiles/marklogic-server-ubi9\:base dockerFiles/marklogic-deps-ubi9-rootless-arm\:base dockerFiles/marklogic-server-ubi9-rootless-arm\:base src/NOTICE.txt src/rhel-script-cis.sh #*************************************************************************** # strcture test docker images @@ -133,15 +156,21 @@ endif # security scan docker images #*************************************************************************** scap-scan: + # Clean up any existing scap-scan container from previous runs + docker rm -f scap-scan 2>/dev/null || true mkdir -p scap - [ -f scap-security-guide-${open_scap_version}.zip ] || curl -Lo scap-security-guide-${open_scap_version}.zip https://github.com/ComplianceAsCode/content/releases/download/v${open_scap_version}/scap-security-guide-${open_scap_version}.zip + [ -f scap-security-guide-${open_scap_version}.zip ] || curl -Lso scap-security-guide-${open_scap_version}.zip https://github.com/ComplianceAsCode/content/releases/download/v${open_scap_version}/scap-security-guide-${open_scap_version}.zip #UBI9 needs a different version of the evaluation profile ifeq ($(findstring ubi9,$(current_image)),ubi9) unzip -p scap-security-guide-${open_scap_version}.zip scap-security-guide-${open_scap_version}/ssg-rhel9-ds.xml > scap/ssg-rhel-ds.xml else unzip -p scap-security-guide-${open_scap_version}.zip scap-security-guide-${open_scap_version}/ssg-rhel8-ds.xml > scap/ssg-rhel-ds.xml endif - docker run -itd --name scap-scan -v $(PWD)/scap:/scap ${current_image} + docker run -itd --name scap-scan --entrypoint /bin/bash -v $(PWD)/scap:/scap ${current_image} -c "sleep infinity" + # Wait a moment for container to be fully up + sleep 2 + # Verify container is running + docker ps | grep scap-scan || (docker logs scap-scan; exit 1) docker exec -u root scap-scan /bin/bash -c "microdnf update -y; microdnf install -y openscap-scanner" # ensure the file is owned by root in order to avoid permission issues docker exec -u root scap-scan /bin/bash -c "chown root:root /scap/ssg-rhel-ds.xml" diff --git a/NOTICE.txt b/NOTICE.txt index 116953d9..ede40c0f 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,6 +1,6 @@ MarkLogic® Docker Container Image v2 -Copyright © 2018-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. This project is licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at diff --git a/dockerFiles/marklogic-deps-ubi9-arm:base b/dockerFiles/marklogic-deps-ubi9-arm:base new file mode 100644 index 00000000..fe93ab01 --- /dev/null +++ b/dockerFiles/marklogic-deps-ubi9-arm:base @@ -0,0 +1,29 @@ +############################################################### +# +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# +############################################################### + +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7-1771346502 +LABEL "com.marklogic.maintainer"="docker@marklogic.com" + +############################################################### +# install libnsl rpm package +############################################################### + +RUN microdnf -y update \ + && rpm -i https://download.rockylinux.org/pub/rocky/9/BaseOS/aarch64/os/Packages/l/libnsl-2.34-231.el9_7.10.aarch64.rpm + +############################################################### +# install networking, base deps and tzdata for timezone +############################################################### +# hadolint ignore=DL3006 +RUN echo "NETWORKING=yes" > /etc/sysconfig/network \ + && microdnf -y install --setopt install_weak_deps=0 gdb nss libtool-ltdl cpio tzdata util-linux hostname \ + && microdnf clean all + + +############################################################### +# Enable FIPS Mode +############################################################### +RUN update-crypto-policies --set FIPS \ No newline at end of file diff --git a/dockerFiles/marklogic-deps-ubi9:base b/dockerFiles/marklogic-deps-ubi9:base index c0f2394a..5fe0de0a 100644 --- a/dockerFiles/marklogic-deps-ubi9:base +++ b/dockerFiles/marklogic-deps-ubi9:base @@ -1,10 +1,10 @@ ############################################################### # -# Copyright © 2018-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. # ############################################################### -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7-1764794109 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7-1771346502 LABEL "com.marklogic.maintainer"="docker@marklogic.com" ############################################################### diff --git a/dockerFiles/marklogic-deps-ubi:base b/dockerFiles/marklogic-deps-ubi:base index 5abff039..fe415096 100644 --- a/dockerFiles/marklogic-deps-ubi:base +++ b/dockerFiles/marklogic-deps-ubi:base @@ -1,10 +1,10 @@ ############################################################### # -# Copyright © 2018-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. # ############################################################### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10-1765178706 +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10-1771947229 LABEL "com.marklogic.maintainer"="docker@marklogic.com" # MarkLogic version passed from build to enable conditional deps diff --git a/dockerFiles/marklogic-server-ubi-rootless:base b/dockerFiles/marklogic-server-ubi-rootless:base index d1cb4131..3892d6df 100644 --- a/dockerFiles/marklogic-server-ubi-rootless:base +++ b/dockerFiles/marklogic-server-ubi-rootless:base @@ -59,9 +59,15 @@ RUN touch /etc/marklogic.conf \ # Add TINI to serve as PID 1 process ############################################################### ENV TINI_VERSION=v0.19.0 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini -RUN chown ${ML_USER}:users /tini \ - && chmod +x /tini +ARG ML_DOCKER_TYPE=ubi +RUN if [ "${ML_DOCKER_TYPE}" = "ubi9-rootless-arm" ]; then \ + TINI_BIN="tini-arm64"; \ + else \ + TINI_BIN="tini"; \ + fi && \ + curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${TINI_BIN} -o /tini && \ + chown ${ML_USER}:users /tini && \ + chmod +x /tini ############################################################### # second stage for flattening layers @@ -149,7 +155,7 @@ RUN touch /.dockerenv \ ############################################################### WORKDIR / COPY ${ML_CONVERTERS} /tmp/converters.rpm -RUN chown ${ML_USER}:users /tmp/converters.rpm +RUN if [ -s /tmp/converters.rpm ]; then chown ${ML_USER}:users /tmp/converters.rpm; else rm -f /tmp/converters.rpm; fi ############################################################### # Remove optional packages that have known vulnerabilities diff --git a/dockerFiles/marklogic-server-ubi9-arm:base b/dockerFiles/marklogic-server-ubi9-arm:base new file mode 100644 index 00000000..ad81e263 --- /dev/null +++ b/dockerFiles/marklogic-server-ubi9-arm:base @@ -0,0 +1,151 @@ +############################################################### +# +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# +############################################################### + +ARG BASE_IMAGE=marklogic-ubi/marklogic-deps-ubi9-arm:11-internal +FROM ${BASE_IMAGE} AS builder + +############################################################### +# set build args +############################################################### + +ARG ML_RPM=marklogic.rpm +ARG ML_USER="marklogic_user" +ARG ML_VERSION=11-internal +ARG ML_CONVERTERS=marklogic.converters +#################################################### +# inject init, start and clustering scripts +############################################################### + +COPY scripts/start-marklogic.sh /usr/local/bin/start-marklogic.sh + +############################################################### +# install MarkLogic server, sudo, and remove mlcmd packages +############################################################### +COPY ${ML_RPM} /tmp/marklogic-server.rpm +RUN rpm -i /tmp/marklogic-server.rpm \ + && rm /tmp/marklogic-server.rpm \ + && microdnf -y install --setopt install_weak_deps=0 sudo \ + && microdnf -y clean all \ + && rm -rf ./opt/MarkLogic/mlcmd/lib/* \ + && rm -rf ./opt/MarkLogic/mlcmd/ext/* + +############################################################### +# Add TINI to serve as PID 1 process +############################################################### +ENV TINI_VERSION=v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-arm64 /tini +RUN chmod +x /tini + +############################################################### +# Copy converters package +############################################################### +WORKDIR / +COPY ${ML_CONVERTERS} converters.rpm +############################################################### +# create system user +############################################################### + +RUN adduser --gid users --uid 1000 ${ML_USER} \ + && echo ${ML_USER}" ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +############################################################### +# second stage for flattening layers +############################################################### +FROM ${BASE_IMAGE} + +COPY --from=builder / / + +ARG ML_USER="marklogic_user" +ARG ML_VERSION=11-internal +ARG ML_DOCKER_VERSION=local +ARG BUILD_BRANCH=local +ARG ML_DOCKER_TYPE=ubi +############################################################### +# define docker labels +############################################################### + +LABEL "com.marklogic.maintainer"="docker@marklogic.com" +LABEL "com.marklogic.name"="MarkLogic Server ${ML_VERSION}" +LABEL "com.marklogic.docker-version"="${ML_DOCKER_VERSION}" +LABEL "com.marklogic.release-version"="${ML_VERSION}" +LABEL "com.marklogic.build-branch"="${BUILD_BRANCH}" +LABEL "com.marklogic"="MarkLogic" +LABEL "com.marklogic.release-type"="production" +LABEL "com.marklogic.license"="MarkLogic EULA" +LABEL "com.marklogic.license.description"="By subscribing to this product, you agree to the terms and conditions outlined in MarkLogic's End User License Agreement (EULA) here https://developer.marklogic.com/eula " +LABEL "com.marklogic.license.url"="https://developer.marklogic.com/eula" +LABEL "com.marklogic.description"="MarkLogic is the only Enterprise NoSQL database. It is a new generation database built with a flexible data model to store, manage, and search JSON, XML, RDF, and more - without sacrificing enterprise features such as ACID transactions, certified security, backup, and recovery. With these capabilities, MarkLogic is ideally suited for making heterogeneous data integration simpler and faster, and for delivering dynamic content at massive scale. The current release of the MarkLogic Server Developer Docker image includes all features and is limited to developer use." +LABEL docker.cmd="docker run -it -p 7997-8010:7997-8010 -e MARKLOGIC_INIT=true -e MARKLOGIC_ADMIN_USERNAME= -e MARKLOGIC_ADMIN_PASSWORD= --mount src=MarkLogic,dst=/var/opt/MarkLogic progressofficial/marklogic-db:${ML_VERSION}" + +############################################################### +# copy notice file +############################################################### +COPY --chown=${ML_USER}:users NOTICE.txt /home/${ML_USER}/NOTICE.txt + +############################################################### +# set env vars +############################################################### + +ENV MARKLOGIC_INSTALL_DIR=/opt/MarkLogic \ + MARKLOGIC_DATA_DIR=/var/opt/MarkLogic \ + MARKLOGIC_USER=${ML_USER} \ + MARKLOGIC_PID_FILE=/var/run/MarkLogic.pid \ + MARKLOGIC_UMASK=022 \ + LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH:/opt/MarkLogic/lib \ + MARKLOGIC_VERSION="${ML_VERSION}" \ + MARKLOGIC_DOCKER_VERSION="${ML_DOCKER_VERSION}" \ + MARKLOGIC_IMAGE_TYPE="$ML_DOCKER_TYPE" \ + MARKLOGIC_BOOTSTRAP_HOST=bootstrap \ + MARKLOGIC_ADMIN_USERNAME_FILE=mldb_admin_user \ + MARKLOGIC_ADMIN_PASSWORD_FILE=mldb_password_user \ + MARKLOGIC_WALLET_PASSWORD_FILE=mldb_wallet_password \ + BUILD_BRANCH=${BUILD_BRANCH} \ + MARKLOGIC_JOIN_TLS_ENABLED=false \ + OVERWRITE_ML_CONF=true \ + MARKLOGIC_EC2_HOST=0 + +################################################################ +# Set Timezone +################################################################ + +RUN microdnf -y reinstall tzdata + +############################################################### +# Remove optional packages that have known vulnerabilities +############################################################### +RUN for package in vim-minimal cups-client cups-libs tar python3-pip-wheel platform-python python3-libs platform-python-setuptools avahi-libs binutils expat libarchive python3 python3-libs python-unversioned-command binutils-gold; \ + do rpm -e --nodeps $package || true; \ + done; + +############################################################### +# expose MarkLogic server ports +############################################################### + +EXPOSE 25 7997-8010 + +############################################################### +# set system user +############################################################### + +USER ${ML_USER} + +#################################################### +# Set Linux Language Settings +############################################################### + +ENV LANG=en_US.UTF-8 +ENV LC_ALL=C.UTF-8 + +############################################################### +# define volume for persistent MarkLogic server data +############################################################### + +VOLUME /var/opt/MarkLogic + +############################################################### +# set entrypoint +############################################################### +ENTRYPOINT ["/tini", "--", "/usr/local/bin/start-marklogic.sh"] diff --git a/test/docker-tests.robot b/test/docker-tests.robot index 5c97c9fd..8a3f1c40 100644 --- a/test/docker-tests.robot +++ b/test/docker-tests.robot @@ -124,6 +124,7 @@ Initialized MarkLogic container with latency Upgrade MarkLogic container Skip If 'rootless' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for rootless image + Skip If 'arm' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for ARM image Create test container with -e MARKLOGIC_INIT=true ... -e MARKLOGIC_ADMIN_USERNAME=${DEFAULT ADMIN USER} ... -e MARKLOGIC_ADMIN_PASSWORD=${DEFAULT ADMIN PASS} @@ -148,6 +149,7 @@ Upgrade MarkLogic container Upgrade MarkLogic container with init parameter Skip If 'rootless' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for rootless image + Skip If 'arm' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for ARM image Create test container with -e MARKLOGIC_INIT=true ... -e MARKLOGIC_ADMIN_USERNAME=${DEFAULT ADMIN USER} ... -e MARKLOGIC_ADMIN_PASSWORD=${DEFAULT ADMIN PASS} @@ -172,6 +174,7 @@ Upgrade MarkLogic container with init parameter Upgrade MarkLogic container with init and credential parameters Skip If 'rootless' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for rootless image + Skip If 'arm' in '${IMAGE_TYPE}' msg = Skipping Upgrade MarkLogic test for ARM image Create test container with -e MARKLOGIC_INIT=true ... -e MARKLOGIC_ADMIN_USERNAME=${DEFAULT ADMIN USER} ... -e MARKLOGIC_ADMIN_PASSWORD=${DEFAULT ADMIN PASS} @@ -582,6 +585,7 @@ Initialized MarkLogic Server with wallet password and realm [Teardown] Delete container Initialized MarkLogic container with ML converters + Skip If 'arm' in '${IMAGE_TYPE}' msg = Skipping ML converters test for ARM image (converters not available) Create container with -e MARKLOGIC_INIT=true ... -e MARKLOGIC_ADMIN_USERNAME=${DEFAULT ADMIN USER} ... -e MARKLOGIC_ADMIN_PASSWORD=${DEFAULT ADMIN PASS} diff --git a/test/keywords.resource b/test/keywords.resource index f2c71040..cb23823b 100644 --- a/test/keywords.resource +++ b/test/keywords.resource @@ -1,4 +1,4 @@ -# Copyright © 2018-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +# Copyright © 2018-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. *** Settings *** Library Process Library String @@ -8,7 +8,8 @@ Library Collections Library DateTime *** Variables *** -@{DOCKER DEFAULTS} -it -d -p 8000:8000 -p 8001:8001 -p 8002:8002 -p7997:7997 --platform linux/amd64 +${DOCKER_PLATFORM} %{DOCKER_PLATFORM=linux/amd64} +@{DOCKER DEFAULTS} -it -d -p 8000:8000 -p 8001:8001 -p 8002:8002 -p7997:7997 --platform ${DOCKER_PLATFORM} ${DEFAULT ADMIN USER} test_admin ${DEFAULT ADMIN PASS} test_admin_pass ${SPEC CHARS ADMIN PASS} Admin@2$s%^&*! @@ -50,7 +51,7 @@ Create container with latency ... --name ${container name} ... --cap-add NET_ADMIN --entrypoint /bin/bash ... ${TEST_IMAGE} - ... -c sudo microdnf -y install iproute iptables && sudo curl -s -O https://download.rockylinux.org/pub/rocky/8/BaseOS/x86_64/os/Packages/i/iproute-tc-6.2.0-6.el8_10.x86_64.rpm && sudo rpm -i iproute-tc-6.2.0-6.el8_10.x86_64.rpm && sudo tc qdisc add dev lo root netem delay 30000ms && sudo tc qdisc show dev lo && /tini -- /usr/local/bin/start-marklogic.sh + ... -c sudo microdnf -y install iproute iptables && (sudo yum install -y iproute-tc || sudo microdnf install -y iproute) && sudo tc qdisc add dev lo root netem delay 30000ms && sudo tc qdisc show dev lo && /tini -- /usr/local/bin/start-marklogic.sh ... stderr=test_results/stderr-${container name}.txt ... stdout=test_results/stdout-${container name}.txt ... timeout=15000