Skip to content

Commit 2cd26a2

Browse files
authored
Merge pull request #1 from codefresh-io/real-template
Real template
2 parents 684fe91 + c9fe4bc commit 2cd26a2

File tree

4 files changed

+256
-21
lines changed

4 files changed

+256
-21
lines changed

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ RUN tar xf "${GCLOUD_SDK_FILENAME}" && \
1919
/google-cloud-sdk/bin/gcloud components install -q kubectl;
2020

2121
ADD cf-deploy-kubernetes.sh /cf-deploy-kubernetes
22+
ADD template.sh /template.sh
2223

2324
# Set the default path to include all the commands
2425
RUN \
2526
ln -s /google-cloud-sdk/bin/kubectl /usr/local/bin/kubectl && \
26-
chmod +x /cf-deploy-kubernetes
27+
chmod +x /cf-deploy-kubernetes && \
28+
chmod +x /template.sh
2729

2830
CMD ["bash"]
2931

README.md

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
This is the source code for the `codefresh/cf-deploy-kubernetes` container.
44
This container is used to demonstrate a Kubernetes deployment using Codefresh.io
55

6-
For a complete example, check:
7-
https://github.com/codefresh-io/cf-deploy-kubernetes-demo
8-
96
# Assumptions
107

118
The deployment script makes the following assumptions about your application and
@@ -14,9 +11,10 @@ Kubernetes configuration:
1411
1. The application is deployed using the Kubernetes deployment API (versus the
1512
the replication controller directly). For more information read
1613
http://kubernetes.io/docs/user-guide/deployments/
17-
2. The tested codebase has a yaml file that describes the Kubernetes deployment
14+
2. The tested codebase has a yaml file (i.e. deployment.yml) that describes the Kubernetes deployment
1815
parameters and configuration of your application.
19-
3. At the moment, only the basic username/pass authentication is supported.
16+
3. The script processes deployment.yml as a simple template where all `{{ ENV_VARIABLE }}` are replaced with a value of $ENV_VARIABLE deployment.yml
17+
4. At the moment, only the basic username/pass authentication is supported.
2018

2119
# Configuration
2220

@@ -28,9 +26,59 @@ before failing the build. Defaults to 120 (secs).
2826
3. KUBERNETES_PASSWORD - The password for the Kubernetes cluster. Mandatory.
2927
4. KUBERNETES_SERVER - The server (HTTPS endpoint) of the Kubernetes cluster's
3028
API. Mandatory.
31-
5. DOCKER_IMAGE_TAG - The docker tag to use for the deployment. Requires the
32-
`deployment.yml` file to specify a `$DOCKER_IMAGE_TAG` variable so it can be
33-
substitutes at deployment time.
34-
6. FORCE_RE_CREATE_RESOURCE - Will force re-creation of the deployment
3529

30+
# Usage in codefresh.io
31+
32+
### deployment.yml
33+
34+
```yaml
35+
---
36+
apiVersion: extensions/v1beta1
37+
kind: Deployment
38+
metadata:
39+
name: api-svc
40+
spec:
41+
replicas: 1
42+
template:
43+
metadata:
44+
annotations:
45+
revision: "{{CF_REVISION}}"
46+
labels:
47+
app: api-svc
48+
spec:
49+
containers:
50+
- name: apisvc
51+
image: myrepo/apisvc:{{CF_BRANCH}}
52+
ports:
53+
- containerPort: 80
54+
name: http
55+
56+
```
57+
58+
### codefresh.yml
59+
```yaml
60+
---
61+
version: '1.0'
62+
63+
steps:
64+
build:
65+
type: build
66+
working-directory: ${{initial-clone}}
67+
image-name: $docker-image
68+
tag: ${{CF_BRANCH}}
69+
push:
70+
type: push
71+
candidate: ${{build}}
72+
tag: ${{CF_BRANCH}}
3673

74+
deploy-to-kubernetes:
75+
image: codefresh/cf-deploy-kubernetes
76+
tag: latest
77+
working-directory: ${{initial-clone}}
78+
commands:
79+
- /cf-deploy-kubernetes deployment.yml
80+
environment:
81+
- KUBERNETES_USER=${{KUBERNETES_USER}}
82+
- KUBERNETES_PASSWORD=${{KUBERNETES_PASSWORD}}
83+
- KUBERNETES_SERVER=${{KUBERNETES_SERVER}}
84+
```

cf-deploy-kubernetes.sh

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#!/bin/bash
22

3+
fatal() {
4+
echo "ERROR: $1"
5+
exit 1
6+
}
7+
38
readonly DEFAULT_NAMESPACE=default
49

510
deployment_file=${1:-deployment.yml}
@@ -9,11 +14,13 @@ deployment_file=${1:-deployment.yml}
914
[ -z "$KUBERNETES_USER" ] && echo "Please set KUBERNETES_USER" && exit 1;
1015
[ -z "$KUBERNETES_PASSWORD" ] && echo "Please set KUBERNETES_PASSWORD" && exit 1;
1116
[ -z "$KUBERNETES_SERVER" ] && echo "Please set KUBERNETES_SERVER" && exit 1;
12-
[ -z "$DOCKER_IMAGE_TAG" ] && echo "Please set DOCKER_IMAGE_TAG" && exit 1;
17+
# [ -z "$DOCKER_IMAGE_TAG" ] && echo "Please set DOCKER_IMAGE_TAG" && exit 1;
1318

1419
[ ! -f "${deployment_file}" ] && echo "Couldn't find $deployment_file file at $(pwd)" && exit 1;
15-
sed -i "s/\$DOCKER_IMAGE_TAG/$DOCKER_IMAGE_TAG/g" $deployment_file
16-
sed -i "s/\$UNIQ_ID/$(date '+%y-%m-%d_%H:%M:%S')/g" $deployment_file
20+
21+
22+
DEPLOYMENT_FILE=${deployment_file}-$(date '+%y-%m-%d_%H-%M-%S').yml
23+
$(dirname $0)/template.sh "$deployment_file" > "$DEPLOYMENT_FILE" || fatal "Failed to apply deployment template on $deployment_file"
1724

1825

1926
echo "---> Setting up Kubernetes credentials..."
@@ -22,15 +29,9 @@ kubectl config set-cluster foo.kubernetes.com --insecure-skip-tls-verify=true --
2229
kubectl config set-context foo.kubernetes.com/deployer --user=deployer --namespace=$DEFAULT_NAMESPACE --cluster=foo.kubernetes.com
2330
kubectl config use-context foo.kubernetes.com/deployer
2431

32+
echo "---> Submittinig a deployment to Kubernetes..."
33+
kubectl apply -f "$DEPLOYMENT_FILE" || fatal "Deployment Failed"
2534

26-
# Check if the cloned dir already exists from previous builds
27-
if [ "$FORCE_RE_CREATE_RESOURCE" == "true" ]; then
28-
echo "---> Submittinig a deployment to Kubernetes with --force flag..."
29-
kubectl apply -f $deployment_file --force
30-
else
31-
echo "---> Submittinig a deployment to Kubernetes..."
32-
kubectl apply -f $deployment_file
33-
fi
3435

3536
echo "---> Waiting for a succesful deployment status..."
3637

template.sh

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/bin/bash
2+
#
3+
# Very simple templating system that replaces {{VAR}} by the value of $VAR.
4+
# Supports default values by writting {{VAR=value}} in the template.
5+
#
6+
# Copyright (c) 2017 Sébastien Lavoie
7+
# Copyright (c) 2017 Johan Haleby
8+
#
9+
# By: https://github.com/johanhaleby/bash-templater
10+
# Version: https://github.com/johanhaleby/bash-templater/commit/5ac655d554238ac70b08ee4361d699ea9954c941
11+
12+
# Replaces all {{VAR}} by the $VAR value in a template file and outputs it
13+
14+
readonly PROGNAME=$(basename $0)
15+
16+
config_file="<none>"
17+
print_only="false"
18+
silent="false"
19+
20+
usage="${PROGNAME} [-h] [-d] [-f] [-s] --
21+
where:
22+
-h, --help
23+
Show this help text
24+
-p, --print-envs
25+
Don't do anything, just print the result of the variable expansion(s)
26+
-e, --env-file
27+
Specify a file to read variables from
28+
-s, --silent
29+
Don't print warning messages (for example if no variables are found)
30+
examples:
31+
VAR1=Something VAR2=1.2.3 ${PROGNAME} test.txt
32+
${PROGNAME} test.txt -e my-variables.txt
33+
${PROGNAME} test.txt -e my-variables.txt > new-test.txt"
34+
35+
if [ $# -eq 0 ]; then
36+
echo "$usage"
37+
exit 1
38+
fi
39+
40+
while [[ $1 =~ ^(-(h|p|e|s)|--(help|print-envs|env-file|silent)) ]]
41+
do
42+
key=$1
43+
value=$2
44+
45+
case $key in
46+
-h|--help)
47+
echo "$usage"
48+
exit 0
49+
;;
50+
-p|--print)
51+
print_only="true"
52+
;;
53+
-e|--env-file)
54+
config_file="$2"
55+
shift
56+
;;
57+
-s|--silent)
58+
silent="true"
59+
;;
60+
*)
61+
echo "Usage ERROR: Invalid Option $key"
62+
echo "$usage"
63+
exit 1
64+
;;
65+
esac
66+
shift # past argument or value
67+
done
68+
69+
70+
if [[ ! -f "${1}" ]]; then
71+
echo "You need to specify a template file" >&2
72+
echo "$usage"
73+
exit 1
74+
fi
75+
76+
template="${1}"
77+
78+
if [ "$#" -ne 0 ]; then
79+
while [ "$#" -gt 0 ]
80+
do
81+
case "$1" in
82+
-h|--help)
83+
echo "$usage"
84+
exit 0
85+
;;
86+
-p|--print-envs)
87+
print_only="true"
88+
;;
89+
-f|--file)
90+
config_file="$2"
91+
;;
92+
-s|--silent)
93+
silent="true"
94+
;;
95+
--)
96+
break
97+
;;
98+
-*)
99+
echo "Invalid option '$1'. Use --help to see the valid options" >&2
100+
exit 1
101+
;;
102+
# an option argument, continue
103+
*) ;;
104+
esac
105+
shift
106+
done
107+
fi
108+
109+
vars=$(grep -oE '\{\{[A-Za-z0-9_]+\}\}' "${template}" | sort | uniq | sed -e 's/^{{//' -e 's/}}$//')
110+
111+
if [[ -z "$vars" ]]; then
112+
if [ "$silent" == "false" ]; then
113+
echo "Warning: No variable was found in ${template}, syntax is {{VAR}}" >&2
114+
fi
115+
cat ${template}
116+
exit 0
117+
fi
118+
119+
# Load variables from file if needed
120+
if [ "${config_file}" != "<none>" ]; then
121+
if [[ ! -f "${config_file}" ]]; then
122+
echo "The file ${config_file} does not exists" >&2
123+
echo "$usage"
124+
exit 1
125+
fi
126+
127+
# Create temp file where & and "space" is escaped
128+
tmpfile=`mktemp`
129+
sed -e "s;\&;\\\&;g" -e "s;\ ;\\\ ;g" "${config_file}" > $tmpfile
130+
source $tmpfile
131+
fi
132+
133+
var_value() {
134+
eval echo \$$1
135+
}
136+
137+
replaces=""
138+
139+
# Reads default values defined as {{VAR=value}} and delete those lines
140+
# There are evaluated, so you can do {{PATH=$HOME}} or {{PATH=`pwd`}}
141+
# You can even reference variables defined in the template before
142+
defaults=$(grep -oE '^\{\{[A-Za-z0-9_]+=.+\}\}' "${template}" | sed -e 's/^{{//' -e 's/}}$//')
143+
144+
for default in $defaults; do
145+
var=$(echo "$default" | grep -oE "^[A-Za-z0-9_]+")
146+
current=`var_value $var`
147+
148+
# Replace only if var is not set
149+
if [[ -z "$current" ]]; then
150+
eval $default
151+
fi
152+
153+
# remove define line
154+
replaces="-e '/^{{$var=/d' $replaces"
155+
vars="$vars
156+
$current"
157+
done
158+
159+
vars=$(echo $vars | sort | uniq)
160+
161+
if [[ "$print_only" == "true" ]]; then
162+
for var in $vars; do
163+
value=`var_value $var`
164+
echo "$var = $value"
165+
done
166+
exit 0
167+
fi
168+
169+
# Replace all {{VAR}} by $VAR value
170+
for var in $vars; do
171+
value=`var_value $var`
172+
if [[ -z "$value" ]]; then
173+
if [ $silent == "false" ]; then
174+
echo "Warning: $var is not defined and no default is set, replacing by empty" >&2
175+
fi
176+
fi
177+
178+
# Escape slashes
179+
value=$(echo "$value" | sed 's/\//\\\//g');
180+
replaces="-e 's/{{$var}}/${value}/g' $replaces"
181+
done
182+
183+
escaped_template_path=$(echo $template | sed 's/ /\\ /g')
184+
eval sed $replaces "$escaped_template_path"

0 commit comments

Comments
 (0)