diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ef27ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +bin/build.sh +bin/destroy.sh +bin/install.sh +bin/rebuild.sh +bin/rerun.sh +bin/run.sh +bin/test.sh +bin/build.sh +bin/destroy.sh +bin/install.sh +bin/rebuild.sh +bin/rerun.sh +bin/run.sh +bin/start.sh +bin/stop.sh +bin/test.sh diff --git a/BINSCRIPTS.md b/BINSCRIPTS.md new file mode 100644 index 0000000..8569b7d --- /dev/null +++ b/BINSCRIPTS.md @@ -0,0 +1,41 @@ +# util + +This repository is intended to be downloaded into a container repository during development for convenience purposes. Since the major mechanisms of developing to the Docker container construction lifecycle are identical across container images, this repository allows for consistency and additional ease of use across all container images. + +## Install + +If you are reading this file in BINSCRIPTS.md, your container project is likely to be util-enabled. + +To use these scripts yourself, issue this command: + +``` +curl "https://github.internet2.edu/raw/docker/util/master/bin/install.sh?token=AAAAEddkrL9MeeA6VWcNn_PgV30r4lD1ks5XogeiwA%3D%3D" | bash +``` + +### common.bash + +The installation process will create a common.bash file. This file should be the central, canonical authority for management of environment variables. While a subprocess may override them, the files in common.bash should be treated as authoritative defaults. Processes (e.g. `docker build`, `bats`, inside `Jenkinsfile`) can read this file and process the results therein. + +You should edit this file to change the image name, and add any other helpful environment variables. + +### Jenkinsfile + +This will also install a Jenkinsfile to your repository, if it doesn't have one. This will ensure that your Jenkins pipeline can leverage these scripts in the way intended. Ensuring the commands that you issue on your laptop match the commands issued by the build pipeline is critical to ensure predictable, reliable results. + +## Use + + +### Building + +#### build.sh +`bin/build.sh ` +#### destroy.sh +#### rebuild.sh + +### Running +### rerun.sh +### run.sh + + +### Testing +#### test.sh \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 88735c9..37293f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,55 @@ FROM centos:centos7 +ENV REFRESHED_AT 2016-11-07 # Define args and set a default value -ARG maintainer=tier +ARG maintainer=my ARG imagename=centos7base +ARG version=1.0 MAINTAINER $maintainer LABEL Vendor="Internet2" LABEL ImageType="Base" LABEL ImageName=$imagename LABEL ImageOS=centos7 -LABEL Version=1.0 +LABEL Version=$version LABEL Build docker build --rm --tag $maintainer/$imagename . +# +# UTC Timezone & Networking +# +RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime \ + && echo "NETWORKING=yes" > /etc/sysconfig/network + # Install base deps -RUN yum -y install epel-release && yum -y update && yum clean all -RUN yum -y install --setopt=tsflags=nodocs epel-release && \ - yum -y install net-tools wget curl tar unzip mlocate logrotate strace telnet man unzip vim wget rsyslog cron \ - yum -y update && yum clean all +RUN rm -fr /var/cache/yum/* && yum clean all && yum -y install --setopt=tsflags=nodocs epel-release && \ + yum -y install net-tools wget curl tar unzip mlocate logrotate strace telnet man unzip vim wget rsyslog cron && \ + yum clean all && \ + mkdir -p \ + /opt/autoexec/bin \ + /opt/autoexec/onbuild \ + /opt/autoexec/firstrun \ + /opt/bin \ + /opt/etc \ + /opt/log \ + /opt/tier + +# Install Trusted Certificates +RUN update-ca-trust force-enable +ADD ./cert/InCommon.crt /etc/pki/ca-trust/source/anchors/ +RUN update-ca-trust extract + +ADD container_files/bin/firstrun.sh /opt/autoexec/bin/firstrun.sh +ADD container_files/bin/onbuild.sh /opt/autoexec/bin/onbuild.sh +ADD container_files/bin/stub.sh /opt/autoexec/firstrun/stub.sh +ADD container_files/bin/stub.sh /opt/autoexec/onbuild/stub.sh + # Set default environment variables. -ENV HOME /root +ENV HOME /opt/tier # Allow triggerable events on the first time running RUN touch /tmp/firsttimerunning # Define working directory. -WORKDIR /root +WORKDIR /opt/tier diff --git a/Jenkinsfile b/Jenkinsfile index d8ecc99..dda7869 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,14 +1,86 @@ -node { +node('docker') { stage 'Checkout' checkout scm - - stage 'Base' - sh './build_image.sh' + stage 'Acquire util' + + sh 'mkdir -p tmp && mkdir -p bin' + dir('tmp'){ + git([ url: "https://github.internet2.edu/docker/util.git", + credentialsId: "jenkins-github-access-token" ]) + sh 'mv ./bin/* ../bin/.' + } + sh 'rm -rf tmp' + stage 'Setting build context' + + def maintainer = maintainer() + def imagename = imagename() + def tag + + // Tag images created on master branch with 'latest' + if(env.BRANCH_NAME == "master"){ + tag = "latest" + }else{ + tag = env.BRANCH_NAME + } + + if(!imagename){ + echo "You must define an imagename in common.bash" + currentBuild.result = 'FAILURE' + } + if(maintainer){ + echo "Building ${maintainer}:${tag} for ${maintainer}" + } + + stage 'BUILD: Base' + + try{ + sh 'bin/build.sh &> debug' + } catch(error) { + def error_details = readFile('./debug'); + def message = "BUILD ERROR: There was a problem building ${imagename}:${tag}. \n\n ${error_details}" + sh "rm -f ./debug" + handleError(message) + } + + stage 'TEST: Base' + + try{ + sh 'bin/test.sh &> debug' + } catch(error) { + def error_details = readFile('./debug'); + def message = "BUILD ERROR: There was a problem building ${imagename}:${tag}. \n\n ${error_details}" + sh "rm -f ./debug" + handleError(message) + } + + stage 'SHIP: Base' + + docker.withRegistry('https://registry.hub.docker.com/', "dockerhub-$maintainer") { + def baseImg = docker.build("$maintainer/$imagename") + baseImg.push("$tag") + } - stage 'Tests' + stage 'Notify' - sh '/usr/local/bin/bats tests/base.bats' + slackSend color: 'good', message: "$maintainer/$imagename:$tag pushed to DockerHub" +} + +def maintainer() { + def matcher = readFile('common.bash') =~ 'maintainer="(.+)"' + matcher ? matcher[0][1] : 'tier' +} + +def imagename() { + def matcher = readFile('common.bash') =~ 'imagename="(.+)"' + matcher ? matcher[0][1] : null +} -} \ No newline at end of file +def handleError(String message){ + echo "${message}" + currentBuild.setResult("FAILED") + slackSend color: 'danger', message: "${message}" + //step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'chris.bynum@levvel.io', sendToIndividuals: true]) + sh 'exit 1' +} diff --git a/README.md b/README.md index 99032bb..5cbde40 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,8 @@ Internet2 managed CentOS 7 base image ## purpose -This container allows I2/TIER to insulate itself against upstream changes from CentOS managed images that may be unwanted. It can also be used to trigger global changes (e.g. a new InCommon.crt) when appropriate. \ No newline at end of file +This container allows I2/TIER to insulate itself against upstream changes from CentOS managed images that may be unwanted. It can also be used to trigger global changes (e.g. a new InCommon.crt) when appropriate. + +## autorun + +You are encouraged to include /opt/autorun/bin/onbuild.sh when closing your Dockerfiles, and to include /opt/autorun/bin/firstrun.sh in your CMD entrypoints. \ No newline at end of file diff --git a/build_image.sh b/build_image.sh deleted file mode 100755 index 41dcb5b..0000000 --- a/build_image.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -source common.sh . - -echo "Building new Docker image($maintainer/$imagename)" -docker build --rm -t $maintainer/$imagename --build-arg maintainer=$maintainer --build-arg imagename=$imagename . diff --git a/cert/InCommon.crt b/cert/InCommon.crt new file mode 100644 index 0000000..edcc20e --- /dev/null +++ b/cert/InCommon.crt @@ -0,0 +1,91 @@ +-----BEGIN CERTIFICATE----- +MIIF+TCCA+GgAwIBAgIQRyDQ+oVGGn4XoWQCkYRjdDANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQx +MDA2MDAwMDAwWhcNMjQxMDA1MjM1OTU5WjB2MQswCQYDVQQGEwJVUzELMAkGA1UE +CBMCTUkxEjAQBgNVBAcTCUFubiBBcmJvcjESMBAGA1UEChMJSW50ZXJuZXQyMREw +DwYDVQQLEwhJbkNvbW1vbjEfMB0GA1UEAxMWSW5Db21tb24gUlNBIFNlcnZlciBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJwb8bsvf2MYFVFRVA+e +xU5NEFj6MJsXKZDmMwysE1N8VJG06thum4ltuzM+j9INpun5uukNDBqeso7JcC7v +HgV9lestjaKpTbOc5/MZNrun8XzmCB5hJ0R6lvSoNNviQsil2zfVtefkQnI/tBPP +iwckRR6MkYNGuQmm/BijBgLsNI0yZpUn6uGX6Ns1oytW61fo8BBZ321wDGZq0GTl +qKOYMa0dYtX6kuOaQ80tNfvZnjNbRX3EhigsZhLI2w8ZMA0/6fDqSl5AB8f2IHpT +eIFken5FahZv9JNYyWL7KSd9oX8hzudPR9aKVuDjZvjs3YncJowZaDuNi+L7RyML +fzcCAwEAAaOCAW4wggFqMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvAnfKyA2bL +MB0GA1UdDgQWBBQeBaN3j2yW4luHS6a0hqxxAAznODAOBgNVHQ8BAf8EBAMCAYYw +EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH +AwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECAjBQBgNVHR8ESTBHMEWgQ6BB +hj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2VydGlmaWNh +dGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUFBzAChjNo +dHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1c3RDQS5j +cnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZI +hvcNAQEMBQADggIBAC0RBjjW29dYaK+qOGcXjeIT16MUJNkGE+vrkS/fT2ctyNMU +11ZlUp5uH5gIjppIG8GLWZqjV5vbhvhZQPwZsHURKsISNrqOcooGTie3jVgU0W+0 ++Wj8mN2knCVANt69F2YrA394gbGAdJ5fOrQmL2pIhDY0jqco74fzYefbZ/VS29fR +5jBxu4uj1P+5ZImem4Gbj1e4ZEzVBhmO55GFfBjRidj26h1oFBHZ7heDH1Bjzw72 +hipu47Gkyfr2NEx3KoCGMLCj3Btx7ASn5Ji8FoU+hCazwOU1VX55mKPU1I2250Lo +RCASN18JyfsD5PVldJbtyrmz9gn/TKbRXTr80U2q5JhyvjhLf4lOJo/UzL5WCXED +Smyj4jWG3R7Z8TED9xNNCxGBMXnMete+3PvzdhssvbORDwBZByogQ9xL2LUZFI/i +eoQp0UM/L8zfP527vWjEzuDN5xwxMnhi+vCToh7J159o5ah29mP+aJnvujbXEnGa +nrNxHzu+AGOePV8hwrGGG7hOIcPDQwkuYwzN/xT29iLp/cqf9ZhEtkGcQcIImH3b +oJ8ifsCnSbu0GB9L06Yqh7lcyvKDTEADslIaeSEINxhO2Y1fmcYFX/Fqrrp1WnhH +OjplXuXE0OPa0utaKC25Aplgom88L2Z8mEWcyfoB7zKOfD759AN7JKZWCYwk +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFdzCCBF+gAwIBAgIQE+oocFv07O0MNmMJgGFDNjANBgkqhkiG9w0BAQwFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow +gYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK +ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYD +VQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sIs9CsVw127c0n00yt +UINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnGvDoZtF+mvX2do2NC +tnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQIjy8/hPwhxR79uQf +jtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfbIWax1Jt4A8BQOujM +8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0tyA9yn8iNK5+O2hm +AUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97Exwzf4TKuzJM7UXiV +Z4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNVicQNwZNUMBkTrNN9 +N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5D9kCnusSTJV882sF +qV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJWBp/kjbmUZIO8yZ9 +HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ5lhCLkMaTLTwJUdZ ++gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzGKAgEJTm4Diup8kyX +HAc/DVL17e8vgg8CAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTv +A73gJMtUGjAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/ +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1Ud +HwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4 +dGVybmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0 +dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAJNl9jeD +lQ9ew4IcH9Z35zyKwKoJ8OkLJvHgwmp1ocd5yblSYMgpEg7wrQPWCcR23+WmgZWn +RtqCV6mVksW2jwMibDN3wXsyF24HzloUQToFJBv2FAY7qCUkDrvMKnXduXBBP3zQ +YzYhBx9G/2CkkeFnvN4ffhkUyWNnkepnB2u0j4vAbkN9w6GAbLIevFOFfdyQoaS8 +Le9Gclc1Bb+7RrtubTeZtv8jkpHGbkD4jylW6l/VXxRTrPBPYer3IsynVgviuDQf +Jtl7GQVoP7o81DgGotPmjw7jtHFtQELFhLRAlSv0ZaBIefYdgWOWnU914Ph85I6p +0fKtirOMxyHNwu8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/cleanup_and_stop.sh b/cleanup_and_stop.sh deleted file mode 100755 index 38eae72..0000000 --- a/cleanup_and_stop.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -source common.sh . - -echo "Cleaning up Docker image($maintainer/$imagename)" -docker rmi $maintainer/$imagename >> /dev/null - -exit 0 - diff --git a/common.sh b/common.bash similarity index 77% rename from common.sh rename to common.bash index 960ef7d..f62c497 100644 --- a/common.sh +++ b/common.bash @@ -1,2 +1,3 @@ maintainer="tier" imagename="centos7base" +version=1.0 diff --git a/container_files/bin/firstrun.sh b/container_files/bin/firstrun.sh new file mode 100755 index 0000000..97f9d92 --- /dev/null +++ b/container_files/bin/firstrun.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +for file in /opt/autoexec/firstrun/* +do + exec "$file" >> /opt/log/autoexec.firstrun.log +done \ No newline at end of file diff --git a/container_files/bin/onbuild.sh b/container_files/bin/onbuild.sh new file mode 100755 index 0000000..07d014a --- /dev/null +++ b/container_files/bin/onbuild.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +for file in /opt/autoexec/onbuild/* +do + exec "$file" >> /opt/log/autoexec.build.log +done \ No newline at end of file diff --git a/container_files/bin/stub.sh b/container_files/bin/stub.sh new file mode 100755 index 0000000..08ba7a6 --- /dev/null +++ b/container_files/bin/stub.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 'test' \ No newline at end of file diff --git a/tests/base.bats b/tests/base.bats index 1ede21d..1777cce 100644 --- a/tests/base.bats +++ b/tests/base.bats @@ -1,6 +1,40 @@ #!/usr/bin/env bats -@test "addition using bc" { - result="$(echo 2+2 | bc)" - [ "$result" -eq 4 ] +load ../common + + +@test "Base container is running" { + run docker inspect $maintainer/$imagename + [ "$status" -eq 0 ] +} + +@test "curl can connect to InCommon cert chain site successfully" { + run docker run -i $maintainer/$imagename curl -o /dev/null --silent --head --write-out '%{http_code}\n' https://github.internet2.edu/ + echo ${output} + [ "$status" -eq 0 ] + [[ ${output} == *"302"* || ${output} == *"200"* ]] +} + +@test "Onbuild support script" { + docker run -i $maintainer/$imagename find /opt/autoexec/bin/onbuild.sh +} + +@test "Onbuild support home" { + docker run -i $maintainer/$imagename find /opt/autoexec/onbuild +} + +@test "Firstrun support bin" { + docker run -i $maintainer/$imagename find /opt/autoexec/bin/firstrun.sh +} + +@test "Firstrun support home" { + docker run -i $maintainer/$imagename find /opt/autoexec/firstrun +} + +@test "Onbuild terminates correctly" { + docker run -i $maintainer/$imagename /opt/autoexec/bin/onbuild.sh +} + +@test "First run terminates correctly" { + docker run -i $maintainer/$imagename /opt/autoexec/bin/firstrun.sh } \ No newline at end of file