Skip to content

Commit

Permalink
Add new Jenkins workflow for build packer. (#3368)
Browse files Browse the repository at this point in the history
Signed-off-by: Zelin Hao <[email protected]>
  • Loading branch information
zelinh authored Apr 12, 2023
1 parent a4269c7 commit ea4cb8f
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 3 deletions.
78 changes: 78 additions & 0 deletions jenkins/packer/packer-build.jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
lib = library(identifier: '[email protected]', retriever: modernSCM([
$class: 'GitSCMSource',
remote: 'https://github.com/opensearch-project/opensearch-build-libraries.git',
]))

pipeline {
options {
timeout(time: 4, unit: 'HOURS')
}
agent {
docker {
label 'Jenkins-Agent-Ubuntu2004-X64-M52xlarge-Docker-Builder'
image 'opensearchstaging/ci-runner:ubuntu2004-x64-docker-buildx0.6.3-qemu5.0-awscli1.22-jdk11-v2'
alwaysPull true
}
}
parameters {
string(
name: 'PACKER_TEMPLATE_NAME',
description: 'The packer template file name of Jenkins agent. e.g. jenkins-agent-al2-arm64.json. Files exist in https://github.com/opensearch-project/opensearch-ci/tree/main/packer',
trim: true
)
}
stages {
stage('Parameters Check') {
steps {
script {
currentBuild.description = "$PACKER_TEMPLATE_NAME"
if (PACKER_TEMPLATE_NAME.isEmpty()) {
currentBuild.result = 'ABORTED'
error("PACKER_TEMPLATE_NAME parameter cannot be empty.")
}
print("Passing parameter checks.")
}
}
}
stage('packer-build') {
environment {
PACKER_BUILD_GIT_REPOSITORY_REFERENCE = "main"
PACKER_BUILD_GIT_REPOSITORY = "https://github.com/opensearch-project/opensearch-ci"
}
steps {
script {
print("Getting $PACKER_TEMPLATE_NAME from $PACKER_BUILD_GIT_REPOSITORY repository with reference $PACKER_BUILD_GIT_REPOSITORY_REFERENCE")
checkout([$class: 'GitSCM', branches: [[name: PACKER_BUILD_GIT_REPOSITORY_REFERENCE ]], userRemoteConfigs: [[url: PACKER_BUILD_GIT_REPOSITORY ]]])
def packer_jenkins_agent_json = readJSON file: "./packer/$PACKER_TEMPLATE_NAME"
withCredentials([
string(credentialsId: 'jenkins-agent-vpc-id', variable: 'vpc_id'),
string(credentialsId: 'jenkins-agent-subnet-id', variable: 'subnet_id'),
string(credentialsId: 'jenkins-agent-sg-id', variable: 'sg_id')
]){
packer_jenkins_agent_json["variables"]["build-vpc"] = vpc_id
packer_jenkins_agent_json["variables"]["build-subnet"] = subnet_id
packer_jenkins_agent_json["variables"]["build-secgrp"] = sg_id
}
def PACKER_TEMPLATE_NAME_SUBSTITUTE = "substitute_" + "$PACKER_TEMPLATE_NAME"
print("$PACKER_TEMPLATE_NAME_SUBSTITUTE")
writeJSON file: "./packer/$PACKER_TEMPLATE_NAME_SUBSTITUTE", json: packer_jenkins_agent_json, pretty: 2

// Start to build packer
withCredentials([string(credentialsId: 'jenkins-aws-account-public', variable: 'AWS_ACCOUNT_PUBLIC')]) {
withAWS(role: 'opensearch-packer', roleAccount: "${AWS_ACCOUNT_PUBLIC}", duration: 3600, roleSessionName: 'jenkins-session', useNode: true) {
sh ("cd packer && packer build -color=false $PACKER_TEMPLATE_NAME_SUBSTITUTE")
}
}

}
}
post() {
always {
script {
postCleanup()
}
}
}
}
}
}
6 changes: 3 additions & 3 deletions tests/jenkins/TestDockerBuild.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ class TestDockerBuild extends BuildPipelineTest {

assertJobStatusSuccess()

// Ensure the entire docker commanbd is executed in an external shell script exactelly once
// Ensure the entire docker command is executed in an external shell script exactly once
def dockerLoginCommand = getCommands('docker').findAll {
shCommand -> shCommand.contains('docker logout && echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin && eval $DOCKER_BUILD_SCRIPT_WITH_COMMANDS')
}
assertThat(dockerLoginCommand.size(), equalTo(1))

// Validate the docker-build.sh is called with correct predefined credential
assertCallStack().contains("docker-build.sh(echo Account: jenkins-staging-dockerhub-credential)")

Expand All @@ -79,5 +79,5 @@ class TestDockerBuild extends BuildPipelineTest {

return shCurlCommands
}

}
111 changes: 111 additions & 0 deletions tests/jenkins/TestPackerBuild.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/


import jenkins.tests.BuildPipelineTest
import org.junit.Before
import org.junit.Test
import static com.lesfurets.jenkins.unit.MethodCall.callArgsToString
import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.CoreMatchers.hasItem
import static com.lesfurets.jenkins.unit.global.lib.GitSource.gitSource
import static com.lesfurets.jenkins.unit.global.lib.LibraryConfiguration.library


class TestPackerBuild extends BuildPipelineTest {

// Variables
String packerBuildGitRespository = 'https://github.com/opensearch-project/opensearch-ci'
String packerBuildGitRespositoryReference = 'main'
String packerTemplateName = 'jenkins-agent-al2-arm64.json'

@Override
@Before
void setUp() {

helper.registerSharedLibrary(
library().name('jenkins')
.defaultVersion('2.2.0')
.allowOverride(true)
.implicit(true)
.targetPath('vars')
.retriever(gitSource('https://github.com/opensearch-project/opensearch-build-libraries.git'))
.build()
)

super.setUp()

binding.setVariable('PACKER_TEMPLATE_NAME', packerTemplateName)
def sample_json = [
"variables" : [
"name-base" : "Jenkins-Agent-AL2-X64" ,
"os-version" : "AL2" ,
"build-region" : "us-east-1" ,
"build-vpc" : "vpc-<>" ,
"build-subnet" : "subnet-<>" ,
"build-secgrp" : "sg-<>" ,
"build-time" : "{{isotime \"2006-01-02T03-04-05Z\"}}" ,
"aws_ami_region" : "us-east-1"
]
]
helper.registerAllowedMethod("readJSON", [Map.class], {c -> sample_json})
def sample_json_output = [
"variables" : [
"name-base" : "Jenkins-Agent-AL2-X64" ,
"os-version" : "AL2" ,
"build-region" : "us-east-1" ,
"build-vpc" : "vpc-123" ,
"build-subnet" : "subnet-123" ,
"build-secgrp" : "sg-123" ,
"build-time" : "{{isotime \"2006-01-02T03-04-05Z\"}}" ,
"aws_ami_region" : "us-east-1"
]
]
helper.registerAllowedMethod("writeJSON", [Map.class], {c -> sample_json_output})
helper.registerAllowedMethod("checkout", [Map], {})
helper.registerAllowedMethod("git", [Map])
helper.registerAllowedMethod("withCredentials", [Map, Closure], { args, closure ->
closure.delegate = delegate
return helper.callClosure(closure)
})
helper.registerAllowedMethod("withAWS", [Map, Closure], { args, closure ->
closure.delegate = delegate
return helper.callClosure(closure)
})
helper.addShMock("cd packer && packer build -color=false substitute_jenkins-agent-al2-arm64.json") { script ->
return [stdout: "", exitValue: 0]
}
}

@Test
void PackerBuildRegression() {
super.testPipeline('jenkins/packer/packer-build.jenkinsfile',
'tests/jenkins/jenkinsjob-regression-files/packer/packer-build.jenkinsfile')

def gitCheckoutCommands = getCommands('checkout', 'GitSCM').findAll {
shCommand -> shCommand.contains('git')
}
assertThat(gitCheckoutCommands, hasItem("{\$class=GitSCM, branches=[{name=main}], userRemoteConfigs=[{url=https://github.com/opensearch-project/opensearch-ci}]}".toString()))

def aws = getCommands('withAWS', 'packer')
assertThat(aws, hasItem('{role=opensearch-packer, roleAccount=AWS_ACCOUNT_PUBLIC, duration=3600, roleSessionName=jenkins-session, useNode=true}, groovy.lang.Closure'))

def packerCommands = getCommands('sh', 'packer')
assertThat(packerCommands, hasItem('cd packer && packer build -color=false substitute_jenkins-agent-al2-arm64.json'))

}

def getCommands(method, text) {
def shCommands = helper.callStack.findAll { call ->
call.methodName == method
}.collect { call ->
callArgsToString(call)
}.findAll { command ->
command.contains(text)
}
return shCommands
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
packer-build.run()
packer-build.modernSCM({$class=GitSCMSource, remote=https://github.com/opensearch-project/opensearch-build-libraries.git})
packer-build.library({[email protected], retriever=null})
packer-build.pipeline(groovy.lang.Closure)
packer-build.timeout({time=4, unit=HOURS})
packer-build.echo(Executing on agent [docker:[alwaysPull:true, args:, containerPerStageRoot:false, label:Jenkins-Agent-Ubuntu2004-X64-M52xlarge-Docker-Builder, image:opensearchstaging/ci-runner:ubuntu2004-x64-docker-buildx0.6.3-qemu5.0-awscli1.22-jdk11-v2, reuseNode:false, stages:[:]]])
packer-build.stage(Parameters Check, groovy.lang.Closure)
packer-build.script(groovy.lang.Closure)
packer-build.stage(packer-build, groovy.lang.Closure)
packer-build.script(groovy.lang.Closure)
packer-build.checkout({$class=GitSCM, branches=[{name=main}], userRemoteConfigs=[{url=https://github.com/opensearch-project/opensearch-ci}]})
packer-build.readJSON({file=./packer/jenkins-agent-al2-arm64.json})
packer-build.string({credentialsId=jenkins-agent-vpc-id, variable=vpc_id})
packer-build.string({credentialsId=jenkins-agent-subnet-id, variable=subnet_id})
packer-build.string({credentialsId=jenkins-agent-sg-id, variable=sg_id})
packer-build.withCredentials([vpc_id, subnet_id, sg_id], groovy.lang.Closure)
packer-build.writeJSON({file=./packer/substitute_jenkins-agent-al2-arm64.json, json={variables={name-base=Jenkins-Agent-AL2-X64, os-version=AL2, build-region=us-east-1, build-vpc=vpc_id, build-subnet=subnet_id, build-secgrp=sg_id, build-time={{isotime "2006-01-02T03-04-05Z"}}, aws_ami_region=us-east-1}}, pretty=2})
packer-build.string({credentialsId=jenkins-aws-account-public, variable=AWS_ACCOUNT_PUBLIC})
packer-build.withCredentials([AWS_ACCOUNT_PUBLIC], groovy.lang.Closure)
packer-build.withAWS({role=opensearch-packer, roleAccount=AWS_ACCOUNT_PUBLIC, duration=3600, roleSessionName=jenkins-session, useNode=true}, groovy.lang.Closure)
packer-build.sh(cd packer && packer build -color=false substitute_jenkins-agent-al2-arm64.json)
packer-build.script(groovy.lang.Closure)
packer-build.postCleanup()
postCleanup.cleanWs({disableDeferredWipeout=true, deleteDirs=true})

0 comments on commit ea4cb8f

Please sign in to comment.