From 7c435133c7212bdab0eebd793c12532251e89f7c Mon Sep 17 00:00:00 2001 From: kosta709 Date: Wed, 19 Apr 2017 07:39:46 -0500 Subject: [PATCH 1/5] added template.sh --- cf-deploy-kubernetes.sh | 23 ++--- template.sh | 184 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 11 deletions(-) create mode 100755 template.sh diff --git a/cf-deploy-kubernetes.sh b/cf-deploy-kubernetes.sh index c9f459c..940188f 100755 --- a/cf-deploy-kubernetes.sh +++ b/cf-deploy-kubernetes.sh @@ -1,5 +1,10 @@ #!/bin/bash +fatal() { + echo "ERROR: $1" + exit 1 +} + readonly DEFAULT_NAMESPACE=default deployment_file=${1:-deployment.yml} @@ -9,11 +14,13 @@ deployment_file=${1:-deployment.yml} [ -z "$KUBERNETES_USER" ] && echo "Please set KUBERNETES_USER" && exit 1; [ -z "$KUBERNETES_PASSWORD" ] && echo "Please set KUBERNETES_PASSWORD" && exit 1; [ -z "$KUBERNETES_SERVER" ] && echo "Please set KUBERNETES_SERVER" && exit 1; -[ -z "$DOCKER_IMAGE_TAG" ] && echo "Please set DOCKER_IMAGE_TAG" && exit 1; +# [ -z "$DOCKER_IMAGE_TAG" ] && echo "Please set DOCKER_IMAGE_TAG" && exit 1; [ ! -f "${deployment_file}" ] && echo "Couldn't find $deployment_file file at $(pwd)" && exit 1; -sed -i "s/\$DOCKER_IMAGE_TAG/$DOCKER_IMAGE_TAG/g" $deployment_file -sed -i "s/\$UNIQ_ID/$(date '+%y-%m-%d_%H:%M:%S')/g" $deployment_file + + +DEPLOYMENT_FILE=$(date '+%y-%m-%d_%H:%M:%S')-${deployment_file} +$(dirname $0)/template.sh "$deployment_file" > "$DEPLOYMENT_FILE" || fatal "Failed to apply deployment template on $deployment_file" echo "---> Setting up Kubernetes credentials..." @@ -22,15 +29,9 @@ kubectl config set-cluster foo.kubernetes.com --insecure-skip-tls-verify=true -- kubectl config set-context foo.kubernetes.com/deployer --user=deployer --namespace=$DEFAULT_NAMESPACE --cluster=foo.kubernetes.com kubectl config use-context foo.kubernetes.com/deployer +echo "---> Submittinig a deployment to Kubernetes..." +kubectl apply -f "$DEPLOYMENT_FILE" || fatal "Deployment Failed" -# Check if the cloned dir already exists from previous builds -if [ "$FORCE_RE_CREATE_RESOURCE" == "true" ]; then - echo "---> Submittinig a deployment to Kubernetes with --force flag..." - kubectl apply -f $deployment_file --force -else - echo "---> Submittinig a deployment to Kubernetes..." - kubectl apply -f $deployment_file -fi echo "---> Waiting for a succesful deployment status..." diff --git a/template.sh b/template.sh new file mode 100755 index 0000000..57b6522 --- /dev/null +++ b/template.sh @@ -0,0 +1,184 @@ +#!/bin/bash +# +# Very simple templating system that replaces {{VAR}} by the value of $VAR. +# Supports default values by writting {{VAR=value}} in the template. +# +# Copyright (c) 2017 Sébastien Lavoie +# Copyright (c) 2017 Johan Haleby +# +# By: https://github.com/johanhaleby/bash-templater +# Version: https://github.com/johanhaleby/bash-templater/commit/5ac655d554238ac70b08ee4361d699ea9954c941 + +# Replaces all {{VAR}} by the $VAR value in a template file and outputs it + +readonly PROGNAME=$(basename $0) + +config_file="" +print_only="false" +silent="false" + +usage="${PROGNAME} [-h] [-d] [-f] [-s] -- +where: + -h, --help + Show this help text + -p, --print-envs + Don't do anything, just print the result of the variable expansion(s) + -e, --env-file + Specify a file to read variables from + -s, --silent + Don't print warning messages (for example if no variables are found) +examples: + VAR1=Something VAR2=1.2.3 ${PROGNAME} test.txt + ${PROGNAME} test.txt -e my-variables.txt + ${PROGNAME} test.txt -e my-variables.txt > new-test.txt" + +if [ $# -eq 0 ]; then + echo "$usage" + exit 1 +fi + +while [[ $1 =~ ^(-(h|p|e|s)|--(help|print-envs|env-file|silent)) ]] +do + key=$1 + value=$2 + + case $key in + -h|--help) + echo "$usage" + exit 0 + ;; + -p|--print) + print_only="true" + ;; + -e|--env-file) + config_file="$2" + shift + ;; + -s|--silent) + silent="true" + ;; + *) + echo "Usage ERROR: Invalid Option $key" + echo "$usage" + exit 1 + ;; + esac + shift # past argument or value +done + + +if [[ ! -f "${1}" ]]; then + echo "You need to specify a template file" >&2 + echo "$usage" + exit 1 +fi + +template="${1}" + +if [ "$#" -ne 0 ]; then + while [ "$#" -gt 0 ] + do + case "$1" in + -h|--help) + echo "$usage" + exit 0 + ;; + -p|--print-envs) + print_only="true" + ;; + -f|--file) + config_file="$2" + ;; + -s|--silent) + silent="true" + ;; + --) + break + ;; + -*) + echo "Invalid option '$1'. Use --help to see the valid options" >&2 + exit 1 + ;; + # an option argument, continue + *) ;; + esac + shift + done +fi + +vars=$(grep -oE '\{\{[A-Za-z0-9_]+\}\}' "${template}" | sort | uniq | sed -e 's/^{{//' -e 's/}}$//') + +if [[ -z "$vars" ]]; then + if [ "$silent" == "false" ]; then + echo "Warning: No variable was found in ${template}, syntax is {{VAR}}" >&2 + fi + cat ${template} + exit 0 +fi + +# Load variables from file if needed +if [ "${config_file}" != "" ]; then + if [[ ! -f "${config_file}" ]]; then + echo "The file ${config_file} does not exists" >&2 + echo "$usage" + exit 1 + fi + + # Create temp file where & and "space" is escaped + tmpfile=`mktemp` + sed -e "s;\&;\\\&;g" -e "s;\ ;\\\ ;g" "${config_file}" > $tmpfile + source $tmpfile +fi + +var_value() { + eval echo \$$1 +} + +replaces="" + +# Reads default values defined as {{VAR=value}} and delete those lines +# There are evaluated, so you can do {{PATH=$HOME}} or {{PATH=`pwd`}} +# You can even reference variables defined in the template before +defaults=$(grep -oE '^\{\{[A-Za-z0-9_]+=.+\}\}' "${template}" | sed -e 's/^{{//' -e 's/}}$//') + +for default in $defaults; do + var=$(echo "$default" | grep -oE "^[A-Za-z0-9_]+") + current=`var_value $var` + + # Replace only if var is not set + if [[ -z "$current" ]]; then + eval $default + fi + + # remove define line + replaces="-e '/^{{$var=/d' $replaces" + vars="$vars +$current" +done + +vars=$(echo $vars | sort | uniq) + +if [[ "$print_only" == "true" ]]; then + for var in $vars; do + value=`var_value $var` + echo "$var = $value" + done + exit 0 +fi + +# Replace all {{VAR}} by $VAR value +for var in $vars; do + value=`var_value $var` + if [[ -z "$value" ]]; then + if [ $silent == "false" ]; then + echo "Warning: $var is not defined and no default is set, replacing by empty" >&2 + fi + fi + + # Escape slashes + value=$(echo "$value" | sed 's/\//\\\//g'); + replaces="-e 's/{{$var}}/${value}/g' $replaces" +done + +escaped_template_path=$(echo $template | sed 's/ /\\ /g') +eval sed $replaces "$escaped_template_path" From 0b43585307942fec8cd7621d41a41979136ef79e Mon Sep 17 00:00:00 2001 From: kosta709 Date: Wed, 19 Apr 2017 08:01:24 -0500 Subject: [PATCH 2/5] updated readme --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index edd050b..7a0c5d4 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,10 @@ Kubernetes configuration: 1. The application is deployed using the Kubernetes deployment API (versus the the replication controller directly). For more information read http://kubernetes.io/docs/user-guide/deployments/ -2. The tested codebase has a yaml file that describes the Kubernetes deployment +2. The tested codebase has a yaml file (i.e. deployment.yml) that describes the Kubernetes deployment parameters and configuration of your application. -3. At the moment, only the basic username/pass authentication is supported. +3. The script processes deployment.yml as a simple template where all `{{ ENV_VARIABLE }}` are replaced with a value of $ENV_VARIABLE deployment.yml +4. At the moment, only the basic username/pass authentication is supported. # Configuration @@ -28,9 +29,59 @@ before failing the build. Defaults to 120 (secs). 3. KUBERNETES_PASSWORD - The password for the Kubernetes cluster. Mandatory. 4. KUBERNETES_SERVER - The server (HTTPS endpoint) of the Kubernetes cluster's API. Mandatory. -5. DOCKER_IMAGE_TAG - The docker tag to use for the deployment. Requires the -`deployment.yml` file to specify a `$DOCKER_IMAGE_TAG` variable so it can be -substitutes at deployment time. -6. FORCE_RE_CREATE_RESOURCE - Will force re-creation of the deployment +# Usage in codefresh +### deployment.yml + +```yaml +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: api-svc +spec: + replicas: 1 + template: + metadata: + annotations: + revision: "{{CF_REVISION}}" + labels: + app: api-svc + spec: + containers: + - name: apisvc + image: myrepo/apisvc:{{CF_BRANCH}} + ports: + - containerPort: 80 + name: http + +``` + +### codefresh.yml +```yaml +--- +version: '1.0' + +steps: + build: + type: build + working-directory: ${{initial-clone}} + image-name: $docker-image + tag: ${{CF_BRANCH}} + push: + type: push + candidate: ${{build}} + tag: ${{CF_BRANCH}} + + deploy-to-kubernetes: + image: codefresh/cf-deploy-kubernetes + tag: latest + working-directory: ${{initial-clone}} + commands: + - /cf-deploy-kubernetes deployment.yml + environment: + - KUBERNETES_USER=${{KUBERNETES_USER}} + - KUBERNETES_PASSWORD=${{KUBERNETES_PASSWORD}} + - KUBERNETES_SERVER=${{KUBERNETES_SERVER}} +``` From 5df61dab4f6b288f0a06fbfb09437dec9bdade74 Mon Sep 17 00:00:00 2001 From: kosta709 Date: Wed, 19 Apr 2017 08:06:56 -0500 Subject: [PATCH 3/5] updated readme --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 7a0c5d4..fd7a643 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,6 @@ This is the source code for the `codefresh/cf-deploy-kubernetes` container. This container is used to demonstrate a Kubernetes deployment using Codefresh.io -For a complete example, check: -https://github.com/codefresh-io/cf-deploy-kubernetes-demo - # Assumptions The deployment script makes the following assumptions about your application and @@ -30,7 +27,7 @@ before failing the build. Defaults to 120 (secs). 4. KUBERNETES_SERVER - The server (HTTPS endpoint) of the Kubernetes cluster's API. Mandatory. -# Usage in codefresh +# Usage in codefresh.io ### deployment.yml From 357b788c03b03904c87aae324a3363f73da9c69b Mon Sep 17 00:00:00 2001 From: kosta709 Date: Wed, 19 Apr 2017 08:18:15 -0500 Subject: [PATCH 4/5] fixed deploy filename --- cf-deploy-kubernetes.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cf-deploy-kubernetes.sh b/cf-deploy-kubernetes.sh index 940188f..ca664ed 100755 --- a/cf-deploy-kubernetes.sh +++ b/cf-deploy-kubernetes.sh @@ -19,7 +19,7 @@ deployment_file=${1:-deployment.yml} [ ! -f "${deployment_file}" ] && echo "Couldn't find $deployment_file file at $(pwd)" && exit 1; -DEPLOYMENT_FILE=$(date '+%y-%m-%d_%H:%M:%S')-${deployment_file} +DEPLOYMENT_FILE=${deployment_file}-$(date '+%y-%m-%d_%H-%M-%S').yml $(dirname $0)/template.sh "$deployment_file" > "$DEPLOYMENT_FILE" || fatal "Failed to apply deployment template on $deployment_file" From c9fe4bc1adbd74919b4c834490071c7ece9190da Mon Sep 17 00:00:00 2001 From: kosta709 Date: Wed, 19 Apr 2017 08:23:52 -0500 Subject: [PATCH 5/5] fixed dockerfile --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e0f0f8c..14b7a4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,11 +19,13 @@ RUN tar xf "${GCLOUD_SDK_FILENAME}" && \ /google-cloud-sdk/bin/gcloud components install -q kubectl; ADD cf-deploy-kubernetes.sh /cf-deploy-kubernetes +ADD template.sh /template.sh # Set the default path to include all the commands RUN \ ln -s /google-cloud-sdk/bin/kubectl /usr/local/bin/kubectl && \ - chmod +x /cf-deploy-kubernetes + chmod +x /cf-deploy-kubernetes && \ + chmod +x /template.sh CMD ["bash"]