From 55b21cd9d7f85cfbd9aa88dc5c6758c9dea2011c Mon Sep 17 00:00:00 2001 From: Geri Jennings Date: Mon, 10 Sep 2018 12:46:25 -0400 Subject: [PATCH] Adding Jenkins pipeline Add a Jenkins pipeline to this repository that will run the start scripts and fail on error. Currently only GKE is supported, with plans to support OpenShift in the future. --- .gitignore | 1 + Jenkinsfile | 40 ++++++++++ ci/Dockerfile | 26 ++++++ ci/platform_login | 29 +++++++ ci/secrets.yml | 33 ++++++++ ci/test | 196 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 325 insertions(+) create mode 100644 Jenkinsfile create mode 100644 ci/Dockerfile create mode 100755 ci/platform_login create mode 100644 ci/secrets.yml create mode 100755 ci/test diff --git a/.gitignore b/.gitignore index be28c7b..39e36a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ policy/generated/* webapp/summon*.gz pg/schema.sql test_app_summon/secrets.yml +output/ diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..fc32c0a --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,40 @@ +#!/usr/bin/env groovy + +pipeline { + agent { label 'executor-v2' } + + options { + timestamps() + buildDiscarder(logRotator(numToKeepStr: '30')) + } + + stages { + stage('Deploy Demos') { + parallel { + stage('GKE and v4 Conjur') { + steps { + sh 'cd ci && summon -e gke ./test gke 4' + } + } + + stage('GKE and v5 Conjur') { + steps { + sh 'cd ci && summon -e gke ./test gke 5' + } + } + } + + post { + always { + archiveArtifacts artifacts: 'output/*' + } + } + } + } + + post { + always { + cleanupAndNotify(currentBuild.currentResult) + } + } +} diff --git a/ci/Dockerfile b/ci/Dockerfile new file mode 100644 index 0000000..30e0b13 --- /dev/null +++ b/ci/Dockerfile @@ -0,0 +1,26 @@ +FROM google/cloud-sdk + +RUN mkdir -p /src +WORKDIR /src + +# Install Docker client +RUN apt-get update -y && \ + apt-get install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common wget && \ + curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | apt-key add - && \ + add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" && \ + apt-get update && \ + apt-get install -y docker-ce && \ + rm -rf /var/lib/apt/lists/* + +# Install kubectl CLI +ARG KUBECTL_CLI_URL +RUN wget -O /usr/local/bin/kubectl ${KUBECTL_CLI_URL:-https://storage.googleapis.com/kubernetes-release/release/v1.7.6/bin/linux/amd64/kubectl} && \ + chmod +x /usr/local/bin/kubectl + +# Install OpenShift oc CLI +ARG OPENSHIFT_CLI_URL +RUN mkdir -p ocbin && \ + wget -O oc.tar.gz ${OPENSHIFT_CLI_URL:-https://github.com/openshift/origin/releases/download/v3.7.2/openshift-origin-client-tools-v3.7.2-282e43f-linux-64bit.tar.gz} && \ + tar xvf oc.tar.gz --strip-components=1 -C ocbin && \ + mv ocbin/oc /usr/local/bin/oc && \ + rm -rf ocbin oc.tar.gz diff --git a/ci/platform_login b/ci/platform_login new file mode 100755 index 0000000..e2531cc --- /dev/null +++ b/ci/platform_login @@ -0,0 +1,29 @@ +#!/bin/bash + +set -euo pipefail +IFS=$'\n\t' + +function main() { + # Log in to platform + if [[ "$PLATFORM" = "kubernetes" ]]; then + gcloud auth activate-service-account \ + --key-file $GCLOUD_SERVICE_KEY + gcloud container clusters get-credentials \ + $GCLOUD_CLUSTER_NAME \ + --zone $GCLOUD_ZONE \ + --project $GCLOUD_PROJECT_NAME + docker login $DOCKER_REGISTRY_URL \ + -u oauth2accesstoken \ + -p "$(gcloud auth print-access-token)" + elif [[ "$PLATFORM" = "openshift" ]]; then + oc login $OPENSHIFT_URL \ + --username=$OPENSHIFT_USERNAME \ + --password=$OPENSHIFT_PASSWORD \ + --insecure-skip-tls-verify=true + docker login \ + -u _ -p "$(oc whoami -t)" \ + $DOCKER_REGISTRY_PATH + fi +} + +main diff --git a/ci/secrets.yml b/ci/secrets.yml new file mode 100644 index 0000000..86ac586 --- /dev/null +++ b/ci/secrets.yml @@ -0,0 +1,33 @@ +common: + CONJUR_ACCOUNT: my-account + CONJUR_ADMIN_PASSWORD: SuperSecret + + KUBECTL_CLI_URL: https://storage.googleapis.com/kubernetes-release/release/v1.7.6/bin/linux/amd64/kubectl + OPENSHIFT_CLI_URL: https://github.com/openshift/origin/releases/download/v3.7.2/openshift-origin-client-tools-v3.7.2-282e43f-linux-64bit.tar.gz + +gke: + GCLOUD_CLUSTER_NAME: !var ci/google-container-engine-testbed/gcloud-cluster-name + GCLOUD_ZONE: !var ci/google-container-engine-testbed/gcloud-zone + GCLOUD_PROJECT_NAME: !var ci/google-container-engine-testbed/gcloud-project-name + GCLOUD_SERVICE_KEY: !var:file ci/google-container-engine-testbed/gcloud-service-key + + OPENSHIFT_URL: "" + OPENSHIFT_USERNAME: "" + OPENSHIFT_PASSWORD: "" + + PLATFORM: kubernetes + DOCKER_REGISTRY_URL: us.gcr.io + DOCKER_REGISTRY_PATH: us.gcr.io/conjur-gke-dev + +oc: + GCLOUD_CLUSTER_NAME: "" + GCLOUD_ZONE: "" + GCLOUD_PROJECT_NAME: "" + GCLOUD_SERVICE_KEY: "" + + OPENSHIFT_URL: master.openshift37.itci.conjur.net:8443 + OPENSHIFT_USERNAME: admin + OPENSHIFT_PASSWORD: !var ci/openshift37/users/admin/password + + PLATFORM: openshift + DOCKER_REGISTRY_PATH: docker-registry-default.apps.openshift37.itci.conjur.net diff --git a/ci/test b/ci/test new file mode 100755 index 0000000..e083c32 --- /dev/null +++ b/ci/test @@ -0,0 +1,196 @@ +#!/bin/bash + +# Usage: +# summon -e [platform] ./test [platform] [conjur version] +# platform: gke or oc +# conjur version: 4 or 5 + +set -euo pipefail +IFS=$'\n\t' + +# Clean up when script completes +function finish { + announce 'Wrapping up and removing test environment' + + # TODO update log check for demo instead of deploy + if [[ "$PLATFORM" = "kubernetes" ]]; then + #kubectl logs "$(kubectl get pods -l role=master --no-headers | awk '{print $1}')" > "output/$TEST_PLATFORM-authn-k8s-logs.txt" + echo "Log check not yet implemented." + elif [[ "$PLATFORM" = "openshift" ]]; then + { + pod_name="$(oc get pods -l role=master --no-headers | awk '{print $1}')" + oc logs $pod_name > "output/$PLATFORM-authn-k8s-logs.txt" + } || { + echo "Logs could not be extracted from pod '$pod_name'" + touch "output/$PLATFORM-authn-k8s-logs.txt" # so Jenkins artifact collection doesn't fail + } + fi + + pushd .. + ./stop + + pushd kubernetes-conjur-deploy-$UNIQUE_TEST_ID + ./stop + popd + rm -rf kubernetes-conjur-deploy-$UNIQUE_TEST_ID + popd + + # TODO add this to cleanup (must happen in authenticated Docker) + #deleteRegistryImage "$DOCKER_REGISTRY_PATH/haproxy:$CONJUR_NAMESPACE_NAME" + #deleteRegistryImage "$DOCKER_REGISTRY_PATH/conjur-appliance:$CONJUR_NAMESPACE_NAME" +} +trap finish EXIT + +# Verify that arguments are passed to the script +function printUsage() { + echo "---" + echo "Usage:" + echo "summon -e [platform] ./test [platform] [conjur version]" + echo "platform: gke or oc" + echo "conjur version: 4 or 5" + + exit 1 +} + +# Parse input arguments +if [ $# -ne 2 ]; then + echo "Invalid number of arguments." + printUsage +fi + +TEST_PLATFORM="$1" +CONJUR_VERSION="$2" + +export TEST_PLATFORM +export CONJUR_VERSION + +function main() { + announce 'Checking arguments' + checkArguments + + announce 'Preparing test environment' + prepareTestEnvironment + + announce 'Deploying Conjur' + deployConjur + + announce 'Deploying demo' + deployDemo +} + +function deployConjur() { + pushd .. + git clone git@github.com:cyberark/kubernetes-conjur-deploy kubernetes-conjur-deploy-$UNIQUE_TEST_ID + popd + + runDockerCommand "cd kubernetes-conjur-deploy-$UNIQUE_TEST_ID && ./start" +} + +function deployDemo() { + runDockerCommand "./start" +} + +# Sets additional required environment variables that aren't available in the +# secrets.yml file, and performs other preparatory steps +function prepareTestEnvironment() { + # Set environment variables + local registry='registry2.itci.conjur.net/conjur-appliance' + + export UNIQUE_TEST_ID="$(uuidgen | tr "[:upper:]" "[:lower:]" | head -c 10)" + + export CONJUR_NAMESPACE_NAME=conjur-$PLATFORM-$CONJUR_VERSION-$UNIQUE_TEST_ID-test + export AUTHENTICATOR_ID=conjur-$PLATFORM-$CONJUR_VERSION-$UNIQUE_TEST_ID-test + export TEST_APP_NAMESPACE_NAME=test-app-$PLATFORM-$CONJUR_VERSION-$UNIQUE_TEST_ID + + export MINIKUBE=false + + export CONJUR_DEMO_TEST_IMAGE=conjur-demo-$PLATFORM-$CONJUR_VERSION-$UNIQUE_TEST_ID + + if [[ "$CONJUR_VERSION" = "4" ]]; then + export CONJUR_APPLIANCE_IMAGE=$registry:4.9-stable + else + export CONJUR_APPLIANCE_IMAGE=$registry:5.0-stable + fi + + # Create directory for pod logs + # TODO remove? + mkdir -p output + + # Prepare Docker images + docker pull $CONJUR_APPLIANCE_IMAGE + docker build -t $CONJUR_DEMO_TEST_IMAGE:$CONJUR_NAMESPACE_NAME \ + -f Dockerfile \ + --build-arg OPENSHIFT_CLI_URL=$OPENSHIFT_CLI_URL \ + --build-arg KUBECTL_CLI_URL=$KUBECTL_CLI_URL \ + . +} + +# Delete an image from GCR, unless it is has multiple tags pointing to it +# This means another parallel build is using the image and we should +# just untag it to be deleted by the later job +function deleteRegistryImage() { + local image=$1 + + if [[ "$PLATFORM" = "kubernetes" ]]; then + runDockerCommand " + gcloud container images delete -q \"$image\" || \ + gcloud container images untag -q \"$image\" || \ + true + " + fi +} + +function runDockerCommand() { + docker run --rm \ + -e CONJUR_VERSION \ + -e CONJUR_APPLIANCE_IMAGE \ + -e CONJUR_NAMESPACE_NAME \ + -e CONJUR_ACCOUNT \ + -e CONJUR_ADMIN_PASSWORD \ + -e AUTHENTICATOR_ID \ + -e TEST_APP_NAMESPACE_NAME \ + -e PLATFORM \ + -e DOCKER_REGISTRY_URL \ + -e DOCKER_REGISTRY_PATH \ + -e MINIKUBE \ + -e GCLOUD_SERVICE_KEY=/tmp$GCLOUD_SERVICE_KEY \ + -e GCLOUD_CLUSTER_NAME \ + -e GCLOUD_ZONE \ + -e GCLOUD_PROJECT_NAME \ + -e OPENSHIFT_URL \ + -e OPENSHIFT_USERNAME \ + -e OPENSHIFT_PASSWORD \ + -v $GCLOUD_SERVICE_KEY:/tmp$GCLOUD_SERVICE_KEY \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ~/.config:/root/.config \ + -v "$PWD/..":/src \ + -w /src \ + $CONJUR_DEMO_TEST_IMAGE:$CONJUR_NAMESPACE_NAME \ + bash -c " + ./ci/platform_login + $1 + " +} + +function announce() { + echo "++++++++++++++++++++++++++++++++++++++" + echo "" + echo "$@" + echo "" + echo "++++++++++++++++++++++++++++++++++++++" +} + +# Check that the argument values are valid +function checkArguments() { + if [[ "$TEST_PLATFORM" != "gke" && "$TEST_PLATFORM" != "oc" ]]; then + echo "The only valid platform values are 'gke' and 'oc'" + elif [[ "$CONJUR_VERSION" != "4" && "$CONJUR_VERSION" != "5" ]]; then + echo "The only valid Conjur version values are '4' and '5'." + else + return 0 + fi + + printUsage +} + +main