Skip to content

Commit 782c941

Browse files
author
Ken Simon
committed
WIP: CI Tests
Signed-off-by: Ken Simon <[email protected]>
1 parent 9f8937e commit 782c941

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

Dockerfile.ci

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FROM alpine:3.5
2+
3+
RUN apk add --no-cache curl
4+
# curl kubectl instead of ADD'ing it, since we want to cache the layer
5+
RUN curl -sfL \
6+
-o /usr/local/bin/kubectl \
7+
https://storage.googleapis.com/kubernetes-release/release/v1.6.1/bin/linux/amd64/kubectl \
8+
&& chmod +x /usr/local/bin/kubectl
9+
10+
RUN mkdir -p /ci && \
11+
mkdir -p /aws && \
12+
apk add --no-cache \
13+
bash \
14+
git \
15+
ca-certificates \
16+
groff \
17+
less \
18+
python \
19+
py-pip \
20+
openssh-client \
21+
jq \
22+
bind-tools \
23+
&& pip install awscli
24+
25+
VOLUME /src
26+
WORKDIR /src
27+
ENTRYPOINT ./ci/k8s-tests.sh

ci/k8s-tests.sh

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#!/bin/bash
2+
3+
# Copyright 2017 by the contributors
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# This runs integration tests for the local repository, deploying it to
18+
# CloudFormation and testing various bits of functionality underneath.
19+
20+
set -o errexit
21+
set -o nounset
22+
set -o pipefail
23+
set -o verbose
24+
25+
if ! grep -q Alpine /etc/issue 2>/dev/null; then
26+
echo "This script is must be run in a docker container (and will make changes to the filesystem, including /root/.ssh). Exiting."
27+
exit 1
28+
fi
29+
30+
function try_n_times() {
31+
num_times=$1
32+
cmd=$2
33+
34+
for i in $(seq 1 $num_times); do
35+
if [[ $i -le $num_times ]]; then
36+
eval "$cmd" && break || (test $i -lt $num_times && sleep 1 || return 1)
37+
fi
38+
done
39+
}
40+
41+
# Overridable parameters
42+
REGION="${REGION:-us-west-2}"
43+
AZ="${AZ:-us-west-2c}"
44+
S3_BUCKET="${S3_BUCKET:-"heptio-aws-quickstart-test"}"
45+
S3_PREFIX="${S3_PREFIX:-"heptio/kubernetes"}"
46+
SSH_KEY="${SSH_KEY:-/tmp/ssh/id_rsa}"
47+
SSH_KEY_NAME="${SSH_KEY_NAME:-jenkins}"
48+
STACK_NAME="${STACK_NAME:-}"
49+
50+
# Fall back on the git shasum for the stack name
51+
if [[ -z "${STACK_NAME}" ]]; then
52+
STACK_NAME="qs-ci-$(git rev-parse --short HEAD)"
53+
fi
54+
55+
# Set/ensure env vars needed by AWS, etc
56+
export AWS_DEFAULT_REGION="${REGION}"
57+
58+
# Setup ssh. Due to SSH being incredibly paranoid about filesystem permissions
59+
# we just create our own ssh directory and set it from there. (This also
60+
# allows the docker volume mounts to be read-only.)
61+
mkdir -p /root/.ssh
62+
chmod 0700 /root/.ssh
63+
cp "${SSH_KEY}" /root/.ssh/identity
64+
export SSH_KEY=/root/.ssh/identity
65+
chmod 0600 $SSH_KEY
66+
67+
aws --version
68+
kubectl version --client
69+
70+
aws s3 sync --acl=public-read --delete ./templates "s3://${S3_BUCKET}/${S3_PREFIX}/${STACK_NAME}/templates/"
71+
aws s3 sync --acl=public-read --delete ./scripts "s3://${S3_BUCKET}/${S3_PREFIX}/${STACK_NAME}/scripts/"
72+
73+
# TODO: maybe do a calico test and a weave test as separate runs
74+
aws cloudformation create-stack \
75+
--disable-rollback \
76+
--region "${REGION}" \
77+
--stack-name "${STACK_NAME}" \
78+
--template-url "https://${S3_BUCKET}.s3.amazonaws.com/${S3_PREFIX}/${STACK_NAME}/templates/kubernetes-cluster-with-new-vpc.template" \
79+
--parameters \
80+
ParameterKey=AvailabilityZone,ParameterValue="${AZ}" \
81+
ParameterKey=KeyName,ParameterValue="${SSH_KEY_NAME}" \
82+
ParameterKey=QSS3BucketName,ParameterValue="${S3_BUCKET}" \
83+
ParameterKey=QSS3KeyPrefix,ParameterValue="${S3_PREFIX}/${STACK_NAME}" \
84+
ParameterKey=AdminIngressLocation,ParameterValue=0.0.0.0/0 \
85+
ParameterKey=NetworkingProvider,ParameterValue=calico \
86+
--capabilities=CAPABILITY_IAM
87+
88+
aws cloudformation wait stack-create-complete --stack-name "${STACK_NAME}"
89+
90+
# Pre-load the SSH host keys
91+
BASTION_IP=$(aws cloudformation describe-stacks \
92+
--query 'Stacks[*].Outputs[?OutputKey == `BastionHostPublicIp`].OutputValue' \
93+
--output text --stack-name $STACK_NAME
94+
)
95+
MASTER_IP=$(aws cloudformation describe-stacks \
96+
--query 'Stacks[*].Outputs[?OutputKey == `MasterPrivateIp`].OutputValue' \
97+
--output text --stack-name $STACK_NAME
98+
)
99+
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no -o ProxyCommand="ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no ubuntu@${BASTION_IP} nc %h %p" ubuntu@${MASTER_IP} exit 0
100+
101+
# TODO: this is a hack... GetKubeConfigCommand has a fake
102+
# "SSH_KEY=path/to/blah.pem" output, we want to override that with our actual
103+
# one.
104+
KUBECONFIG_COMMAND=$(aws cloudformation describe-stacks \
105+
--query 'Stacks[*].Outputs[?OutputKey == `GetKubeConfigCommand`].OutputValue' \
106+
--output text --stack-name $STACK_NAME \
107+
| sed "s!path/to/${SSH_KEY_NAME}.pem!${SSH_KEY}!"
108+
)
109+
110+
# Other than that, just run the command as the Output suggests
111+
eval "${KUBECONFIG_COMMAND}"
112+
113+
# It should have copied a "kubeconfig" file to our current directory
114+
export KUBECONFIG=./kubeconfig
115+
116+
########################
117+
# K8S tests start here #
118+
########################
119+
120+
function cleanup() {
121+
kubectl delete svc nginx || true
122+
}
123+
trap cleanup EXIT
124+
125+
# Sanity check
126+
kubectl get nodes
127+
128+
# Check if any pods aren't in state "Running"
129+
function check_all_pods_running() {
130+
NONRUNNING_PODS=$(kubectl get pods \
131+
--all-namespaces \
132+
-o template \
133+
--template='{{range .items}}{{if ne .status.phase "Running"}}{{.metadata.name}} {{.status.phase}}{{"\n"}}{{end}}{{end}}'
134+
)
135+
test -z "${NONRUNNING_PODS}"
136+
return 0
137+
}
138+
try_n_times 60 check_all_pods_running
139+
140+
# Deploy a service
141+
kubectl run nginx --image=nginx --port=80
142+
kubectl expose deployment nginx --type=LoadBalancer --port 80
143+
144+
GET_LB_CMD="kubectl get svc -o template --template='{{range .status.loadBalancer.ingress}}{{.hostname}}{{end}}' nginx"
145+
try_n_times 30 "$GET_LB_CMD | grep -q '.'"
146+
LB_ADDR=$(eval "${GET_LB_CMD}")
147+
148+
# Wait for DNS propagation, up to 10mins
149+
try_n_times 600 "host ${LB_ADDR}"
150+
151+
# Fetch the service
152+
curl -s -L -f http://${LB_ADDR}

try_n_times.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
function try_n_times() {
4+
num_times=$1
5+
cmd=$2
6+
7+
for i in $(seq 1 $num_times); do
8+
if [[ $i -le $num_times ]]; then
9+
eval "$cmd" && break || (test $i -lt $num_times && sleep 1)
10+
fi
11+
done
12+
}
13+
14+
function do_something() {
15+
echo running stuff
16+
false
17+
}
18+
19+
try_n_times 3 "do_something"

0 commit comments

Comments
 (0)