Merge #1529 Update tests to use pipeline-as-a-service

This commit is contained in:
Matt Prahl
2019-12-05 17:49:43 +00:00
9 changed files with 138 additions and 331 deletions

View File

@@ -1,4 +1,2 @@
NAME=mbs-prod-integration-test
KOJI_IMAGE=quay.io/factory2/koji:prod
UMB_IMAGE=docker-registry.upshift.redhat.com/factory2/umb:prod
ENVIRONMENT=prod

View File

@@ -1,4 +1,2 @@
NAME=mbs-stage-integration-test
KOJI_IMAGE=quay.io/factory2/koji:stage
UMB_IMAGE=docker-registry.upshift.redhat.com/factory2/umb:stage
ENVIRONMENT=stage

View File

@@ -45,7 +45,7 @@ pipeline {
skipDefaultCheckout()
}
environment {
PIPELINE_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim()
TRIGGER_NAMESPACE = readFile("/run/secrets/kubernetes.io/serviceaccount/namespace").trim()
PAGURE_API = "${params.PAGURE_URL}/api/0"
PAGURE_REPO_IS_FORK = "${params.PAGURE_REPO_IS_FORK}"
PAGURE_REPO_HOME = "${env.PAGURE_URL}${env.PAGURE_REPO_IS_FORK == 'true' ? '/fork' : ''}/${params.PAGURE_REPO_NAME}"
@@ -60,6 +60,8 @@ pipeline {
// the return value of checkout() is unreliable.
// Not working: env.MBS_GIT_COMMIT = scmVars.GIT_COMMIT
env.MBS_GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
// Set for pagure function from c3i-library
env.GIT_COMMIT = env.MBS_GIT_COMMIT
echo "Build ${params.MBS_GIT_REF}, commit=${env.MBS_GIT_COMMIT}"
// Is the current branch a pull-request? If no, env.PR_NO will be empty.
@@ -122,13 +124,11 @@ pipeline {
// To enable HTML syntax in build description, go to `Jenkins/Global Security/Markup Formatter` and select 'Safe HTML'.
def pagureLink = """<a href="${env.PR_URL}">${currentBuild.displayName}</a>"""
try {
def prInfo = withPagure {
it.getPR(env.PR_NO)
}
def prInfo = pagure.getPR(env.PR_NO)
pagureLink = """<a href="${env.PR_URL}">PR#${env.PR_NO}: ${escapeHtml(prInfo.title)}</a>"""
// set PR status to Pending
if (params.PAGURE_API_KEY_SECRET_NAME)
setBuildStatusOnPagurePR(null, "Build #${env.BUILD_NUMBER} in progress (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.setBuildStatusOnPR(null, "Build #${env.BUILD_NUMBER} in progress (commit: ${env.MBS_GIT_COMMIT.take(8)})")
} catch (Exception e) {
echo "Error using pagure API: ${e}"
}
@@ -138,7 +138,7 @@ pipeline {
currentBuild.description = """<a href="${env.PAGURE_REPO_HOME}/c/${env.MBS_GIT_COMMIT}">${currentBuild.displayName}</a>"""
if (params.PAGURE_API_KEY_SECRET_NAME) {
try {
flagCommit('pending', null, "Build #${env.BUILD_NUMBER} in progress (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.flagCommit('pending', null, "Build #${env.BUILD_NUMBER} in progress (commit: ${env.MBS_GIT_COMMIT.take(8)})")
echo "Updated commit ${env.MBS_GIT_COMMIT} status to PENDING."
} catch (e) {
echo "Error updating commit ${env.MBS_GIT_COMMIT} status to PENDING: ${e}"
@@ -151,24 +151,27 @@ pipeline {
stage('Allocate C3IaaS project') {
when {
expression {
return params.USE_C3IAAS == 'true' &&
params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAMESPACE &&
params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAME
return params.USE_C3IAAS == 'true'
}
}
steps {
script {
if (env.PR_NO) {
env.C3IAAS_NAMESPACE = "c3i-mbs-pr-${env.PR_NO}-git${env.MBS_GIT_COMMIT.take(8)}"
} else {
env.C3IAAS_NAMESPACE = "c3i-mbs-${params.MBS_GIT_REF}-git${env.MBS_GIT_COMMIT.take(8)}"
if (!params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAME ||
!params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAMESPACE) {
error("USE_C3IAAS is set to true but missing C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAME" +
" or C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAMESPACE")
}
echo "Requesting new OpenShift project ${env.C3IAAS_NAMESPACE}..."
if (env.PR_NO) {
env.PIPELINE_ID = "c3i-mbs-pr-${env.PR_NO}-git${env.MBS_GIT_COMMIT.take(8)}"
} else {
env.PIPELINE_ID = "c3i-mbs-${params.MBS_GIT_REF}-git${env.MBS_GIT_COMMIT.take(8)}"
}
echo "Requesting new OpenShift project ${env.PIPELINE_ID}..."
openshift.withCluster() {
openshift.withProject(params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAMESPACE) {
c3i.buildAndWait(script: this, objs: "bc/${params.C3IAAS_REQUEST_PROJECT_BUILD_CONFIG_NAME}",
'-e', "PROJECT_NAME=${env.C3IAAS_NAMESPACE}",
'-e', "ADMIN_GROUPS=system:serviceaccounts:${PIPELINE_NAMESPACE}",
'-e', "PROJECT_NAME=${env.PIPELINE_ID}",
'-e', "ADMIN_GROUPS=system:serviceaccounts:${TRIGGER_NAMESPACE}",
'-e', "LIFETIME_IN_MINUTES=${params.C3IAAS_LIFETIME}"
)
}
@@ -177,10 +180,10 @@ pipeline {
}
post {
success {
echo "Allocated project ${env.C3IAAS_NAMESPACE}"
echo "Allocated project ${env.PIPELINE_ID}"
}
failure {
echo "Failed to allocate ${env.C3IAAS_NAMESPACE} project"
echo "Failed to allocate ${env.PIPELINE_ID} project"
}
}
}
@@ -191,7 +194,7 @@ pipeline {
steps {
script {
openshift.withCluster() {
openshift.withProject(env.C3IAAS_NAMESPACE ?: env.PIPELINE_NAMESPACE) {
openshift.withProject(env.PIPELINE_ID) {
// OpenShift BuildConfig doesn't support specifying a tag name at build time.
// We have to create a new BuildConfig for each image build.
echo 'Creating a BuildConfig for mbs-backend build...'
@@ -204,7 +207,7 @@ pipeline {
// because refspec cannot be customized in an OpenShift build.
'-p', "MBS_GIT_REF=${env.PR_NO ? params.MBS_GIT_REF : env.MBS_GIT_COMMIT}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAME=${params.MBS_BACKEND_IMAGESTREAM_NAME}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAMESPACE=${env.C3IAAS_NAMESPACE ?: env.PIPELINE_NAMESPACE}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAMESPACE=${env.PIPELINE_ID}",
'-p', "MBS_IMAGE_TAG=${env.TEMP_TAG}",
'-p', "EXTRA_RPMS=${params.EXTRA_RPMS}",
'-p', "CREATED=${created}"
@@ -228,13 +231,15 @@ pipeline {
}
cleanup {
script {
if (!env.C3IAAS_NAMESPACE) {
if (params.USE_C3IAAS != 'true') {
openshift.withCluster() {
echo 'Tearing down...'
openshift.selector('bc', [
'app': env.BACKEND_BUILDCONFIG_ID,
'template': 'mbs-backend-build-template',
]).delete()
openshift.withProject(env.PIPELINE_ID) {
echo 'Tearing down...'
openshift.selector('bc', [
'app': env.BACKEND_BUILDCONFIG_ID,
'template': 'mbs-backend-build-template',
]).delete()
}
}
}
}
@@ -248,7 +253,7 @@ pipeline {
steps {
script {
openshift.withCluster() {
openshift.withProject(env.C3IAAS_NAMESPACE ?: env.PIPELINE_NAMESPACE) {
openshift.withProject(env.PIPELINE_ID) {
// OpenShift BuildConfig doesn't support specifying a tag name at build time.
// We have to create a new BuildConfig for each image build.
echo 'Creating a BuildConfig for mbs-frontend build...'
@@ -261,10 +266,10 @@ pipeline {
// because refspec cannot be customized in an OpenShift build.
'-p', "MBS_GIT_REF=${env.PR_NO ? params.MBS_GIT_REF : env.MBS_GIT_COMMIT}",
'-p', "MBS_FRONTEND_IMAGESTREAM_NAME=${params.MBS_FRONTEND_IMAGESTREAM_NAME}",
'-p', "MBS_FRONTEND_IMAGESTREAM_NAMESPACE=${env.C3IAAS_NAMESPACE ?: env.PIPELINE_NAMESPACE}",
'-p', "MBS_FRONTEND_IMAGESTREAM_NAMESPACE=${env.PIPELINE_ID}",
'-p', "MBS_IMAGE_TAG=${env.TEMP_TAG}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAME=${params.MBS_BACKEND_IMAGESTREAM_NAME}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAMESPACE=${env.C3IAAS_NAMESPACE ?: env.PIPELINE_NAMESPACE}",
'-p', "MBS_BACKEND_IMAGESTREAM_NAMESPACE=${env.PIPELINE_ID}",
'-p', "CREATED=${created}"
)
def build = c3i.buildAndWait(script: this, objs: processed, '--from-dir=.')
@@ -311,8 +316,7 @@ pipeline {
'-e', "MBS_FRONTEND_IMAGE=${env.FRONTEND_IMAGE_REF}",
'-e', "TEST_IMAGES=${env.BACKEND_IMAGE_REF},${env.FRONTEND_IMAGE_REF}",
'-e', "IMAGE_IS_SCRATCH=${params.MBS_GIT_REF != params.MBS_MAIN_BRANCH}",
// If env.C3IAAS_NAMESPACE has not been defined, tests will be run in the current namespace
'-e', "TEST_NAMESPACE=${env.C3IAAS_NAMESPACE ?: ''}",
'-e', "TEST_NAMESPACE=${env.PIPELINE_ID}",
'-e', "TESTCASES='${params.TESTCASES}'",
'-e', "CLEANUP=${params.CLEANUP}"
)
@@ -402,8 +406,7 @@ pipeline {
when {
expression {
return "${params.MBS_DEV_IMAGE_TAG}" && params.TAG_INTO_IMAGESTREAM == "true" &&
(params.FORCE_PUBLISH_IMAGE == "true" || params.MBS_GIT_REF == params.MBS_MAIN_BRANCH) &&
!env.C3IAAS_NAMESPACE
(params.FORCE_PUBLISH_IMAGE == "true" || params.MBS_GIT_REF == params.MBS_MAIN_BRANCH)
}
}
steps {
@@ -434,18 +437,20 @@ pipeline {
post {
cleanup {
script {
if (params.CLEANUP == 'true' && !env.C3IAAS_NAMESPACE) {
if (params.CLEANUP == 'true' && params.USE_C3IAAS != 'true') {
openshift.withCluster() {
if (env.BACKEND_IMAGE_TAG) {
echo "Removing tag ${env.BACKEND_IMAGE_TAG} from the ${params.MBS_BACKEND_IMAGESTREAM_NAME} ImageStream..."
openshift.withProject(params.MBS_BACKEND_IMAGESTREAM_NAMESPACE) {
openshift.tag("${params.MBS_BACKEND_IMAGESTREAM_NAME}:${env.BACKEND_IMAGE_TAG}", "-d")
openshift.withProject(env.PIPELINE_ID) {
if (env.BACKEND_IMAGE_TAG) {
echo "Removing tag ${env.BACKEND_IMAGE_TAG} from the ${params.MBS_BACKEND_IMAGESTREAM_NAME} ImageStream..."
openshift.withProject(params.MBS_BACKEND_IMAGESTREAM_NAMESPACE) {
openshift.tag("${params.MBS_BACKEND_IMAGESTREAM_NAME}:${env.BACKEND_IMAGE_TAG}", "-d")
}
}
}
if (env.FRONTEND_IMAGE_TAG) {
echo "Removing tag ${env.FRONTEND_IMAGE_TAG} from the ${params.MBS_FRONTEND_IMAGESTREAM_NAME} ImageStream..."
openshift.withProject(params.MBS_FRONTEND_IMAGESTREAM_NAMESPACE) {
openshift.tag("${params.MBS_FRONTEND_IMAGESTREAM_NAME}:${env.FRONTEND_IMAGE_TAG}", "-d")
if (env.FRONTEND_IMAGE_TAG) {
echo "Removing tag ${env.FRONTEND_IMAGE_TAG} from the ${params.MBS_FRONTEND_IMAGESTREAM_NAME} ImageStream..."
openshift.withProject(params.MBS_FRONTEND_IMAGESTREAM_NAMESPACE) {
openshift.tag("${params.MBS_FRONTEND_IMAGESTREAM_NAME}:${env.FRONTEND_IMAGE_TAG}", "-d")
}
}
}
}
@@ -457,7 +462,7 @@ pipeline {
// on pre-merge workflow success
if (params.PAGURE_API_KEY_SECRET_NAME && env.PR_NO) {
try {
setBuildStatusOnPagurePR(100, "Build #${env.BUILD_NUMBER} successful (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.setBuildStatusOnPR(100, "Build #${env.BUILD_NUMBER} successful (commit: ${env.MBS_GIT_COMMIT.take(8)})")
echo "Updated PR #${env.PR_NO} status to PASS."
} catch (e) {
echo "Error updating PR #${env.PR_NO} status to PASS: ${e}"
@@ -466,7 +471,7 @@ pipeline {
// on post-merge workflow success
if (params.PAGURE_API_KEY_SECRET_NAME && !env.PR_NO) {
try {
flagCommit('success', 100, "Build #${env.BUILD_NUMBER} successful (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.flagCommit('success', 100, "Build #${env.BUILD_NUMBER} successful (commit: ${env.MBS_GIT_COMMIT.take(8)})")
echo "Updated commit ${env.MBS_GIT_COMMIT} status to PASS."
} catch (e) {
echo "Error updating commit ${env.MBS_GIT_COMMIT} status to PASS: ${e}"
@@ -480,17 +485,17 @@ pipeline {
if (params.PAGURE_API_KEY_SECRET_NAME && env.PR_NO) {
// updating Pagure PR flag
try {
setBuildStatusOnPagurePR(0, "Build #${env.BUILD_NUMBER} failed (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.setBuildStatusOnPR(0, "Build #${env.BUILD_NUMBER} failed (commit: ${env.MBS_GIT_COMMIT.take(8)})")
echo "Updated PR #${env.PR_NO} status to FAILURE."
} catch (e) {
echo "Error updating PR #${env.PR_NO} status to FAILURE: ${e}"
}
// making a comment
try {
commentOnPR("""
pagure.commentOnPR("""
Build #${env.BUILD_NUMBER} [failed](${env.BUILD_URL}) (commit: ${env.MBS_GIT_COMMIT}).
Rebase or make new commits to rebuild.
""".stripIndent())
""".stripIndent(), env.PR_NO)
echo "Comment made."
} catch (e) {
echo "Error making a comment on PR #${env.PR_NO}: ${e}"
@@ -501,7 +506,7 @@ pipeline {
// updating Pagure commit flag
if (params.PAGURE_API_KEY_SECRET_NAME) {
try {
flagCommit('failure', 0, "Build #${env.BUILD_NUMBER} failed (commit: ${env.MBS_GIT_COMMIT.take(8)})")
pagure.flagCommit('failure', 0, "Build #${env.BUILD_NUMBER} failed (commit: ${env.MBS_GIT_COMMIT.take(8)})")
echo "Updated commit ${env.MBS_GIT_COMMIT} status to FAILURE."
} catch (e) {
echo "Error updating commit ${env.MBS_GIT_COMMIT} status to FAILURE: ${e}"
@@ -524,38 +529,6 @@ def getPrNo(branch) {
def prMatch = branch =~ /^(?:.+\/)?pull\/(\d+)\/head$/
return prMatch ? prMatch[0][1] : ''
}
def withPagure(args=[:], cl) {
args.apiUrl = env.PAGURE_API
args.repo = env.PAGURE_REPO_NAME
args.isFork = env.PAGURE_REPO_IS_FORK == 'true'
def pagureClient = pagure.client(args)
return cl(pagureClient)
}
def withPagureCreds(args=[:], cl) {
def pagureClient = null
withCredentials([string(credentialsId: "${env.PIPELINE_NAMESPACE}-${env.PAGURE_API_KEY_SECRET_NAME}", variable: 'TOKEN')]) {
args.token = env.TOKEN
pagureClient = withPagure(args, cl)
}
return pagureClient
}
def setBuildStatusOnPagurePR(percent, String comment) {
withPagureCreds {
it.updatePRStatus(username: 'c3i-jenkins', uid: "ci-pre-merge-${env.MBS_GIT_COMMIT.take(8)}",
url: env.BUILD_URL, percent: percent, comment: comment, pr: env.PR_NO)
}
}
def flagCommit(status, percent, comment) {
withPagureCreds {
it.flagCommit(username: 'c3i-jenkins', uid: "ci-post-merge-${env.MBS_GIT_COMMIT.take(8)}", status: status,
url: env.BUILD_URL, percent: percent, comment: comment, commit: env.MBS_GIT_COMMIT)
}
}
def commentOnPR(String comment) {
withPagureCreds {
it.commentOnPR(comment: comment, pr: env.PR_NO)
}
}
def sendBuildStatusEmail(String status) {
def recipient = params.MAIL_ADDRESS
def subject = "Jenkins job ${env.JOB_NAME} #${env.BUILD_NUMBER} ${status}."

View File

@@ -35,20 +35,6 @@ parameters:
displayName: The Koji container image to be tested
description: This field must be in repo:tag or repo@sha256 format
value: quay.io/factory2/koji:latest
- name: UMB_IMAGE
displayName: The UMB container image to be tested
description: This field must be in repo:tag or repo@sha256 format
value: docker-registry.upshift.redhat.com/factory2/umb:latest
- name: USE_KRB5
displayName: Deploy a Kerberos KDC and configure the MBS frontend to require Kerberos authentication.
description: If not set to "true", no KDC will be deployed and MBS will allow anonymous access.
required: true
value: "true"
- name: KRB5_IMAGE
displayName: Kerberos 5 KDC image
description: The image used to deploy a Kerberos 5 KDC, if configured to do so.
required: false
value: quay.io/factory2/krb5-fedora:latest
- name: TEST_IMAGES
displayName: Images being tested
description: >-
@@ -67,6 +53,9 @@ parameters:
Namespace where the Jenkins agent for this test will run, and where
test resources will be created.
required: false
- name: PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE
displayName: Namespace with pipeline-as-a-service build
value: c3i
- name: ENVIRONMENT
displayName: environment name (dev/stage/prod)
required: true
@@ -129,18 +118,10 @@ objects:
value: "${MBS_FRONTEND_IMAGE}"
- name: KOJI_IMAGE
value: "${KOJI_IMAGE}"
- name: UMB_IMAGE
value: "${UMB_IMAGE}"
- name: USE_KRB5
value: "${USE_KRB5}"
- name: KRB5_IMAGE
value: "${KRB5_IMAGE}"
- name: TEST_IMAGES
value: "${TEST_IMAGES}"
- name: IMAGE_IS_SCRATCH
value: "true"
- name: "TEST_ID"
value: ""
- name: JENKINS_AGENT_IMAGE
value: "${JENKINS_AGENT_IMAGE}"
- name: JENKINS_AGENT_CLOUD_NAME
@@ -151,6 +132,8 @@ objects:
value: "${ENVIRONMENT}"
- name: MESSAGING_PROVIDER
value: "${MESSAGING_PROVIDER}"
- name: PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE
value: "${PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE}"
- name: JENKINS_AGENT_SERVICE_ACCOUNT
value: "${NAME}-jenkins-slave"
- name: TESTCASES

View File

@@ -39,15 +39,12 @@ pipeline {
skipDefaultCheckout()
}
environment {
// Jenkins BUILD_TAG could be too long (> 63 characters) for OpenShift to consume
TEST_ID = "${params.TEST_ID ?: UUID.randomUUID().toString().substring(0,7)}"
PIPELINE_ID = "${params.TEST_NAMESPACE}"
}
stages {
stage('Prepare') {
steps {
script {
// Don't set ENVIRONMENT_LABEL in the environment block! Otherwise you will get 2 different UUIDs.
env.ENVIRONMENT_LABEL = "test-${env.TEST_ID}"
// MBS_GIT_REF can be either a regular branch (in the heads/ namespace), a pull request
// branch (in the pull/ namespace), or a full 40-character sha1, which is assumed to
// exist on the master branch.
@@ -87,14 +84,16 @@ pipeline {
}
}
stage('Route suffix') {
when {
expression { !env.PAAS_DOMAIN }
}
steps {
script {
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
openshift.withProject(env.PIPELINE_ID) {
def testroute = openshift.create('route', 'edge', 'test', '--service=test', '--port=8080')
def testhost = testroute.object().spec.host
// trim off the test- prefix
env.ROUTE_SUFFIX = testhost.drop(5)
env.PAAS_DOMAIN = testhost.minus("test-${env.PIPELINE_ID}.")
testroute.delete()
}
}
@@ -102,186 +101,33 @@ pipeline {
}
post {
success {
echo "Routes end with ${env.ROUTE_SUFFIX}"
echo "Routes end with ${env.PAAS_DOMAIN}"
}
}
}
stage('Generate CA') {
steps {
script {
ca.gen_ca()
}
}
}
stage('Deploy KDC') {
when {
expression {
return params.USE_KRB5 == 'true'
}
}
steps {
script {
env.KRB5_DOMAIN = env.ROUTE_SUFFIX.split('\\.', 2).last()
env.KRB5_REALM = env.KRB5_DOMAIN.toUpperCase()
env.KRB5_ADMIN_PASSWORD = UUID.randomUUID().toString().take(12)
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
def deployed = krb5.deploy(script: this, test_id: env.TEST_ID,
realm: env.KRB5_REALM, domain: env.KRB5_DOMAIN,
admin_password: env.KRB5_ADMIN_PASSWORD)
// Wait for the KDC to become available, to allow creation of
// principals and keytabs for subsequent deployments.
c3i.waitForDeployment(script: this, objs: deployed)
def ports = openshift.selector('service', "kerberos-${TEST_ID}").object().spec.ports
def kdcPort = ports.find { it.name == 'kdc-udp' }.nodePort
def adminPort = ports.find { it.name == 'admin' }.nodePort
def kpasswdPort = ports.find { it.name == 'kpasswd-udp' }.nodePort
def krb5Host = "krb5-${TEST_ID}-${env.ROUTE_SUFFIX}"
env.KRB5_KDC_HOST = "${krb5Host}:${kdcPort}"
env.KRB5_ADMIN_HOST = "${krb5Host}:${adminPort}"
env.KRB5_KPASSWD_HOST = "${krb5Host}:${kpasswdPort}"
}
}
}
}
post {
success {
echo "KDC deployed: REALM: ${env.KRB5_REALM} KDC: ${env.KRB5_KDC_HOST}"
}
failure {
echo "KDC deployment FAILED"
}
}
}
stage('Deploy UMB') {
stage('Deploy test environment') {
steps {
script {
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
// The extact hostname doesn't matter, (as long as it resolves to the cluster) because traffic will
// be routed to the pod via the NodePort.
// However, the hostname we use to access the service must be a subjectAltName of the certificate
// being served by the service.
env.UMB_HOST = "umb-${TEST_ID}-${env.ROUTE_SUFFIX}"
ca.gen_ssl_cert("umb-${TEST_ID}-broker", env.UMB_HOST)
def keystore = ca.get_keystore("umb-${TEST_ID}-broker", 'mbskeys')
def truststore = ca.get_truststore('mbstrust')
deployments = umb.deploy(script: this, test_id: env.TEST_ID,
keystore_data: keystore, keystore_password: 'mbskeys',
truststore_data: truststore, truststore_password: 'mbstrust',
broker_image: params.UMB_IMAGE)
def ports = openshift.selector('service', "umb-${TEST_ID}-broker").object().spec.ports
env.UMB_AMQPS_PORT = ports.find { it.name == 'amqps' }.nodePort
env.UMB_STOMP_SSL_PORT = ports.find { it.name == 'stomp-ssl' }.nodePort
openshift.withProject(params.PIPELINE_AS_A_SERVICE_BUILD_NAMESPACE) {
c3i.buildAndWait(script: this, objs: "bc/pipeline-as-a-service",
'-e', "DEFAULT_IMAGE_TAG=${env.ENVIRONMENT}",
'-e', "PIPELINE_ID=${env.PIPELINE_ID}",
'-e', "WAIVERDB_IMAGE=",
'-e', "C3IAAS_PROJECT=",
'-e', "RESULTSDB_IMAGE=",
'-e', "RESULTSDB_UPDATER_IMAGE=",
'-e', "GREENWAVE_IMAGE=",
'-e', "DATAGREPPER_IMAGE=",
'-e', "DATANOMMER_IMAGE=",
'-e', "MBS_BACKEND_IMAGE=${env.MBS_BACKEND_IMAGE}",
'-e', "MBS_FRONTEND_IMAGE=${env.MBS_FRONTEND_IMAGE}",
'-e', "PAAS_DOMAIN=${env.PAAS_DOMAIN}"
)
}
}
}
}
post {
success {
echo "UMB deployed: amqps: ${env.UMB_HOST}:${env.UMB_AMQPS_PORT} stomp-ssl: ${env.UMB_HOST}:${env.UMB_STOMP_SSL_PORT}"
}
failure {
echo "UMB deployment FAILED"
}
}
}
stage('Deploy Koji') {
steps {
script {
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
env.KOJI_SSL_HOST = "koji-${TEST_ID}-hub-${env.ROUTE_SUFFIX}"
def hubcert = ca.get_ssl_cert("koji-${TEST_ID}-hub", env.KOJI_SSL_HOST)
env.KOJI_ADMIN = "mbs-${TEST_ID}-koji-admin"
env.KOJI_MSG_CERT = "koji-${TEST_ID}-msg"
def deployed = koji.deploy(script: this, test_id: env.TEST_ID,
hubca: ca.get_ca_cert(), hubcert: hubcert,
brokerurl: "amqps://${env.UMB_HOST}:${env.UMB_AMQPS_PORT}",
brokercert: ca.get_ssl_cert(env.KOJI_MSG_CERT),
admin_user: env.KOJI_ADMIN,
hub_image: params.KOJI_IMAGE)
deployments = deployments.union(deployed)
}
}
}
}
post {
success {
echo "Koji deployed: hub: https://${env.KOJI_SSL_HOST}/"
}
failure {
echo "Koji deployment FAILED"
}
}
}
stage('Deploy MBS') {
steps {
script {
env.MBS_SSL_HOST = "mbs-${TEST_ID}-frontend-${env.ROUTE_SUFFIX}"
def frontendcert = ca.get_ssl_cert("mbs-${TEST_ID}-frontend", env.MBS_SSL_HOST)
// Required for accessing src.fedoraproject.org
def digicertca = readFile file: 'openshift/integration/koji/resources/certs/DigiCertHighAssuranceEVRootCA.pem'
def cabundle = ca.get_ca_cert().cert + digicertca
def msgcert = ca.get_ssl_cert("mbs-${TEST_ID}-msg")
def kojicert = ca.get_ssl_cert(env.KOJI_ADMIN)
if (params.USE_KRB5 == 'true') {
def krbAdmin = krb5.adminClient()
def krbsvc = "HTTP/${env.MBS_SSL_HOST}"
krbAdmin.addService(krbsvc)
env.MBS_FRONTEND_KEYTAB = krbAdmin.getKeytab(krbsvc)
// Usernames between MBS and Koji need to be consistent,
// so use the Koji admin as the MBS user.
env.KRB5_PRINCIPAL = env.KOJI_ADMIN
env.KRB5_PASSWORD = UUID.randomUUID().toString().take(12)
krbAdmin.addPrincipal(env.KRB5_PRINCIPAL, env.KRB5_PASSWORD)
}
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
def deployed = mbs.deploy(script: this, test_id: env.TEST_ID,
kojicert: kojicert, kojica: ca.get_ca_cert(),
brokercert: msgcert,
frontendcert: frontendcert, frontendca: ca.get_ca_cert(),
cacerts: cabundle,
frontend_keytab: params.USE_KRB5 == 'true' ? env.MBS_FRONTEND_KEYTAB : '',
krb5_conf_configmap: params.USE_KRB5 == 'true' ? "krb5-${TEST_ID}-config" : '',
krb5_user: params.USE_KRB5 == 'true' ? env.KRB5_PRINCIPAL : '',
kojiurl: "https://${env.KOJI_SSL_HOST}",
stompuri: "${env.UMB_HOST}:${env.UMB_STOMP_SSL_PORT}",
backend_image: params.MBS_BACKEND_IMAGE,
frontend_image: params.MBS_FRONTEND_IMAGE)
deployments = deployments.union(deployed)
}
}
}
}
post {
success {
echo "MBS deployed: frontend: https://${env.MBS_SSL_HOST}/"
}
failure {
echo "MBS deployment FAILED"
}
}
}
stage('Wait for deployments') {
steps {
script {
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
c3i.waitForDeployment(script: this, objs: deployments)
}
}
}
}
post {
success {
echo "Deployments complete"
}
failure {
echo 'Deployments FAILED'
}
}
}
stage('Run tests') {
steps {
@@ -334,10 +180,8 @@ pipeline {
}
openshift.withCluster() {
openshift.withProject(params.TEST_NAMESPACE) {
if (deployments) {
echo 'Getting logs from all deployments...'
deployments.logs('--tail=100')
}
echo 'Getting logs from all deployments...'
openshift.selector('pods', ['c3i.redhat.com/pipeline': env.PIPELINE_ID]).logs('--tail 100')
}
}
}
@@ -349,7 +193,7 @@ pipeline {
/* Tear down everything we just created */
echo 'Tearing down test resources...'
openshift.selector('all,pvc,configmap,secret',
['environment': env.ENVIRONMENT_LABEL]).delete('--ignore-not-found=true')
['c3i.redhat.com/pipeline': env.PIPELINE_ID]).delete('--ignore-not-found=true')
}
} else {
echo 'Skipping cleanup'
@@ -359,6 +203,10 @@ pipeline {
}
}
def sendToResultsDB(imageRef, status) {
if (!params.MESSAGING_PROVIDER) {
echo "Message bus is not set. Skipping send of:\nimageRef: ${imageRef}\nstatus: ${status}"
return
}
def (repourl, digest) = imageRef.tokenize('@')
def (registry, reponame) = repourl.split('/', 2)
def image = reponame.split('/').last()

View File

@@ -151,21 +151,19 @@ objects:
// Need to prefix the rev with origin/ for pollSCM to work correctly
def rev = "origin/${polled}"
def scmVars = c3i.clone(repo: env.GIT_URL, branch: polled, rev: rev)
env.MBS_GIT_COMMIT = scmVars.GIT_COMMIT
env.GIT_COMMIT = scmVars.GIT_COMMIT
// setting build display name
def prefix = 'origin/'
def branch = scmVars.GIT_BRANCH.startsWith(prefix) ? scmVars.GIT_BRANCH.substring(prefix.size())
: scmVars.GIT_BRANCH // origin/pull/1234/head -> pull/1234/head, origin/master -> master
env.MBS_GIT_BRANCH = branch
echo "Build on branch=${env.MBS_GIT_BRANCH}, commit=${env.MBS_GIT_COMMIT}"
echo "Build on branch=${env.MBS_GIT_BRANCH}, commit=${env.GIT_COMMIT}"
if (env.PAGURE_POLLING_FOR_PR == 'false') {
currentBuild.displayName = "${env.MBS_GIT_BRANCH}: ${env.MBS_GIT_COMMIT.substring(0, 7)}"
currentBuild.description = """<a href="${env.PAGURE_REPO_HOME}/c/${env.MBS_GIT_COMMIT}">${currentBuild.displayName}</a>"""
currentBuild.displayName = "${env.MBS_GIT_BRANCH}: ${env.GIT_COMMIT.substring(0, 7)}"
currentBuild.description = """<a href="${env.PAGURE_REPO_HOME}/c/${env.GIT_COMMIT}">${currentBuild.displayName}</a>"""
} else if (env.PAGURE_POLLING_FOR_PR == 'true' && branch ==~ /^pull\/[0-9]+\/head$/) {
env.PR_NO = branch.split('/')[1]
def prInfo = withPagure {
it.getPR(env.PR_NO)
}
def prInfo = pagure.getPR(env.PR_NO)
if (prInfo.status == 'Open') {
env.PR_URL = "${env.PAGURE_REPO_HOME}/pull-request/${env.PR_NO}"
// To HTML syntax in build description, go to `Jenkins/Global Security/Markup Formatter` and select 'Safe HTML'.
@@ -212,7 +210,8 @@ objects:
echo 'Starting a MBS build run...'
def devBuild = c3i.build(script: this,
objs: "bc/${env.PAGURE_POLLING_FOR_PR == 'true' ? env.PREMERGE_JOB_NAME : env.POSTMERGE_JOB_NAME}",
'-e', "MBS_GIT_REF=${env.MBS_GIT_BRANCH}"
'-e', "MBS_GIT_REF=${env.MBS_GIT_BRANCH}", '-e', "PAGURE_REPO_IS_FORK=${env.PAGURE_REPO_IS_FORK}",
'-e', "PAGURE_REPO_NAME=${env.PAGURE_REPO_NAME}"
)
c3i.waitForBuildStart(script: this, build: devBuild)
def devBuildInfo = devBuild.object()
@@ -225,10 +224,3 @@ objects:
}
}
}
def withPagure(args=[:], cl) {
args.apiUrl = env.PAGURE_API
args.repo = env.PAGURE_REPO_NAME
args.isFork = env.PAGURE_REPO_IS_FORK == 'true'
def pagureClient = pagure.client(args)
return cl(pagureClient)
}

View File

@@ -2,9 +2,14 @@
import groovy.json.JsonOutput
def runTests() {
def clientcert = ca.get_ssl_cert(env.KOJI_ADMIN)
koji.setConfig("https://${env.KOJI_SSL_HOST}/kojihub", "https://${env.KOJI_SSL_HOST}/kojifiles",
clientcert.cert, clientcert.key, ca.get_ca_cert().cert)
def koji_admin = controller.getVar('KOJI_ADMIN')
def clientcert = controller.httpGet("/ca/${koji_admin}", true)
def koji_ssl_host = controller.getVar('KOJI_HUB_HOST')
def mbs_host = controller.getVar('MBS_FRONTEND_HOST')
def ca_cert = controller.httpGet("/ca/cacert")
koji.setConfig("https://${koji_ssl_host}/kojihub",
"https://${koji_ssl_host}/kojifiles",
clientcert.cert, clientcert.key, ca_cert)
def tags = koji.callMethod("listTags")
if (!tags.any { it.name == "module-f28" }) {
koji.addTag("module-f28")
@@ -15,9 +20,9 @@ def runTests() {
try {
// There's currently no way to query whether a given user has CG access, so just add it
// and hope no one else has already done it.
koji.runCmd("grant-cg-access", env.KOJI_ADMIN, "module-build-service", "--new")
koji.runCmd("grant-cg-access", koji_admin, "module-build-service", "--new")
} catch (ex) {
echo "Granting cg-access to ${env.KOJI_ADMIN} failed, assuming it was already provided in a previous test"
echo "Granting cg-access to ${koji_admin} failed, assuming it was already provided in a previous test"
}
if (!koji.callMethod("listBTypes").any { it.name == "module" }) {
@@ -44,8 +49,8 @@ def runTests() {
documentation: https://fedoraproject.org/wiki/Fedora_Packaging_Guidelines_for_Modules
"""
writeFile file: 'ca-cert.pem', text: ca.get_ca_cert().cert
def url = "https://${env.MBS_SSL_HOST}/module-build-service/1/module-builds/"
writeFile file: 'ca-cert.pem', text: ca_cert
def url = "https://${mbs_host}/module-build-service/1/module-builds/"
def curlargs = """
--cacert ca-cert.pem \
-H 'Content-Type: application/json' \
@@ -55,9 +60,9 @@ def runTests() {
-w '%{http_code}'
""".trim()
def http_code, response
if (env.KRB5_REALM) {
if (controller.getVar("KRB5_REALM")) {
writeFile file: 'buildparams.json', text: JsonOutput.toJson([modulemd: testmodule])
krb5.withKrb {
krb5.withKrb(controller.getKrb5Vars(koji_admin)) {
http_code = sh script: "curl --negotiate -u : $curlargs $url", returnStdout: true
response = readFile file: 'response.json'
}

View File

@@ -1,9 +1,14 @@
// Build an empty module and verify that the CGImport works correctly
def runTests() {
def clientcert = ca.get_ssl_cert(env.KOJI_ADMIN)
koji.setConfig("https://${env.KOJI_SSL_HOST}/kojihub", "https://${env.KOJI_SSL_HOST}/kojifiles",
clientcert.cert, clientcert.key, ca.get_ca_cert().cert)
def koji_admin = controller.getVar('KOJI_ADMIN')
def clientcert = controller.httpGet("/ca/${koji_admin}", true)
def koji_ssl_host = controller.getVar('KOJI_HUB_HOST')
def mbs_host = controller.getVar('MBS_FRONTEND_HOST')
def ca_cert = controller.httpGet("/ca/cacert")
koji.setConfig("https://${koji_ssl_host}/kojihub",
"https://${koji_ssl_host}/kojifiles",
clientcert.cert, clientcert.key, ca_cert)
def tags = koji.callMethod("listTags")
if (!tags.any { it.name == "module-f28" }) {
koji.addTag("module-f28")
@@ -14,17 +19,17 @@ def runTests() {
try {
// There's currently no way to query whether a given user has CG access, so just add it
// and hope no one else has already done it.
koji.runCmd("grant-cg-access", env.KOJI_ADMIN, "module-build-service", "--new")
koji.runCmd("grant-cg-access", koji_admin, "module-build-service", "--new")
} catch (ex) {
echo "Granting cg-access to ${env.KOJI_ADMIN} failed, assuming it was already provided in a previous test"
echo "Granting cg-access to ${koji_admin} failed, assuming it was already provided in a previous test"
}
if (!koji.callMethod("listBTypes").any { it.name == "module" }) {
koji.callMethodLogin("addBType", "module")
}
writeFile file: 'ca-cert.pem', text: ca.get_ca_cert().cert
def url = "https://${env.MBS_SSL_HOST}/module-build-service/1/module-builds/"
writeFile file: 'ca-cert.pem', text: ca_cert
def url = "https://${mbs_host}/module-build-service/1/module-builds/"
def curlargs = """
--cacert ca-cert.pem \
-H 'Content-Type: application/json' \
@@ -34,12 +39,12 @@ def runTests() {
-w '%{http_code}'
""".trim()
def http_code, response
if (env.KRB5_REALM) {
if (controller.getVar("KRB5_REALM")) {
writeFile file: 'buildparams.json', text: """
{"scmurl": "https://src.fedoraproject.org/forks/mikeb/modules/testmodule.git?#8b3fb16160f899ce10905faf570f110d52b91154",
"branch": "empty-f28"}
"""
krb5.withKrb {
krb5.withKrb(controller.getKrb5Vars(koji_admin)) {
http_code = sh script: "curl --negotiate -u : $curlargs $url", returnStdout: true
response = readFile file: 'response.json'
}
@@ -47,7 +52,7 @@ def runTests() {
writeFile file: 'buildparams.json', text: """
{"scmurl": "https://src.fedoraproject.org/forks/mikeb/modules/testmodule.git?#8b3fb16160f899ce10905faf570f110d52b91154",
"branch": "empty-f28",
"owner": "${env.KOJI_ADMIN}"}
"owner": "${koji_admin}"}
"""
http_code = sh script: "curl $curlargs $url", returnStdout: true
response = readFile file: 'response.json'

View File

@@ -1,9 +1,14 @@
// Submit a build to MBS and verify that it initializes Koji correctly
def runTests() {
def clientcert = ca.get_ssl_cert(env.KOJI_ADMIN)
koji.setConfig("https://${env.KOJI_SSL_HOST}/kojihub", "https://${env.KOJI_SSL_HOST}/kojifiles",
clientcert.cert, clientcert.key, ca.get_ca_cert().cert)
def koji_admin = controller.getVar('KOJI_ADMIN')
def clientcert = controller.httpGet("/ca/${koji_admin}", true)
def koji_ssl_host = controller.getVar('KOJI_HUB_HOST')
def mbs_host = controller.getVar('MBS_FRONTEND_HOST')
def ca_cert = controller.httpGet("/ca/cacert")
koji.setConfig("https://${koji_ssl_host}/kojihub",
"https://${koji_ssl_host}/kojifiles",
clientcert.cert, clientcert.key, ca_cert)
def tags = koji.callMethod("listTags")
if (!tags.any { it.name == "module-f28" }) {
koji.addTag("module-f28")
@@ -11,8 +16,8 @@ def runTests() {
if (!tags.any { it.name == "module-f28-build" }) {
koji.addTag("module-f28-build", "--parent=module-f28", "--arches=x86_64")
}
writeFile file: 'ca-cert.pem', text: ca.get_ca_cert().cert
def url = "https://${env.MBS_SSL_HOST}/module-build-service/1/module-builds/"
writeFile file: 'ca-cert.pem', text: ca_cert
def url = "https://${mbs_host}/module-build-service/1/module-builds/"
def curlargs = """
--cacert ca-cert.pem \
-H 'Content-Type: application/json' \
@@ -22,12 +27,12 @@ def runTests() {
-w '%{http_code}'
""".trim()
def http_code, response
if (env.KRB5_REALM) {
if (controller.getVar("KRB5_REALM")) {
writeFile file: 'buildparams.json', text: """
{"scmurl": "https://src.fedoraproject.org/modules/testmodule.git?#9c589780e1dd1698dc64dfa28d30014ad18cad32",
"branch": "f28"}
"""
krb5.withKrb {
krb5.withKrb(controller.getKrb5Vars(koji_admin)) {
http_code = sh script: "curl --negotiate -u : $curlargs $url", returnStdout: true
response = readFile file: 'response.json'
}
@@ -35,7 +40,7 @@ def runTests() {
writeFile file: 'buildparams.json', text: """
{"scmurl": "https://src.fedoraproject.org/modules/testmodule.git?#9c589780e1dd1698dc64dfa28d30014ad18cad32",
"branch": "f28",
"owner": "${env.KOJI_ADMIN}"}
"owner": "${koji_admin}"}
"""
http_code = sh script: "curl $curlargs $url", returnStdout: true
response = readFile file: 'response.json'