After creating a brand new AMI from the latest and greatest FreeBSD, we would be remiss if we did not properly test that it boots and can do a basic build.
This article is continuation of Creating Custom FreeBSD AMIs for Jenkins - Part 1.
This job will be broken down into the following sections:
- Copy the
env.txtfile to populate AMI ID with - Inject the environment variables from the
env.txtfile - Test the image to make sure it contains the packages needed and the compiler works
- Promote the AMI ID to the main AMI used for all the other jobs
- Clean up the old AMIs that are not needed anymore
Create a new Freestyle Project job in Jenkins and name it something like
new-base-AMI-test.
Copy the env.txt file
Under the Build section of the job select Add build step and choose
Copy artifacts from another project.
Set Project name to:
new-base-AMI-build/ARCH=${ARCH},BUILD_NODE=aws,REL=freebsdmain
Set Which build to:
Latest successful build
Set Artifacts to copy to:
env.txt
Inject the environment variables from env.txt
Under the Build section of the job select Add build step and choose
Inject environment variables.
Set the Properties File Path to match the last line above env.txt and
leave the Properties Content section blank.
This will be used to populate the AMI ID in a future step.
Test the image
Under the Build section of the job select Add build step and choose
Execute shell.
For some basic testing, check to make sure the packages necessary are installed and the complier can compile a basic “Hello World” program:
uname -a
pkg info
PKGS="bsdec2-image-upload git jq nginx openjdk12 poudriere-devel rsync"
for p in ${PKGS}; do
pkg info ${p}
done
echo '#include <stdio.h>' >> test.c
echo 'int main() {' >> test.c
echo ' printf("Hello World!\n");' >> test.c
echo ' return 0;' >> test.c
echo '}' >> test.c
cc -o test test.c
./test
Promote the AMI ID to be used by the other jobs
Under the Build section select Add build step and choose Execute system Groovy script.
This will modify the test AMI configured in the cloud section of Jenkins so make sure the names line up:
import jenkins.model.*;
import hudson.model.*
import hudson.AbortException
import hudson.plugins.ec2.*;
def config = new HashMap()
config.putAll(binding.variables)
def logger = config['out']
def envvars = new HashMap()
envvars.putAll(build.getEnvironment(listener))
def newami = envvars['NEWAMI']
def arch = envvars['ARCH']
Jenkins.instance.clouds.each {
println('cloud: ' + it.displayName)
if (it.displayName == 'engineering-aws') {
it.getTemplates().each {
if (it.description == 'FreeBSD-main-' + arch) {
println('description: ' + it.description)
def oldami = it.getAmi()
if (oldami == newami) {
println("Current AMI: " + oldami + "; new AMI: " + newami)
throw new AbortException("AMIs are the same")
}
else {
println("Current AMI id: " + oldami)
it.setAmi(newami)
println("New AMI: " + it.getAmi())
}
}
}
}
}
Jenkins.instance.save()
Clean up old AMIs
Since AWS charges for every little bit and to keep a clean list of images remove any old AMIs that are not needed anymore.
Under the Build section choose Add build step and select the type to be
Execute shell.
export AWS_DEFAULT_REGION=us-east-2
export AWS_DEFAULT_OUTPUT=json
env
if [ "${ARCH}" = "amd64" ]; then
T=x86_64
else
T=arm64
fi
# deregister old AMIs
for ami in $(aws ec2 describe-images --owners self --filters Name=architecture,Values=${T} | jq '.Images[].ImageId' | sed -e 's/"//g'); do
[ "${ami}" = "${NEWAMI}" ] && continue
# Check name matches
NAME=$(aws ec2 describe-images --image-ids ${ami} | jq '.Images[].Name' | sed -e 's/"//g')
#Strip down "FreeBSD main-aarch64-24" to "main-aarch64"
NAME=${NAME##FreeBSD }
NAME=${NAME%-*}
[ "${NAME}" != "main-${ARCH}" ] && continue
SNAP=$(aws ec2 describe-images --image-ids ${ami} | jq '.Images[].BlockDeviceMappings[] | select(.DeviceName == "/dev/sda1") | .Ebs.SnapshotId' | sed -e 's/"//g')
echo "Removing AMI: ${ami}; Name: ${NAME}; Snap: ${SNAP}"
aws ec2 deregister-image --image-id ${ami}
# delete its snap
sleep 1
aws ec2 delete-snapshot --snapshot-id ${SNAP}
done
Configure the build job to trigger this job
In the new-base-AMI-build job add a build trigger to trigger the
new-base-AMI-test job whenever the build is successful.