Compare commits

...

10 Commits
2.0.0 ... 2.0.2

Author SHA1 Message Date
Stefan Prodan
b0bbd16a77 Merge pull request #28 from stefanprodan/prep-2.0.2
Release v2.0.2
2019-08-06 22:58:51 +03:00
stefanprodan
7564949695 Add e2e docs 2019-08-06 22:53:20 +03:00
stefanprodan
d34da2ab91 Release v2.0.2 2019-08-06 22:15:19 +03:00
stefanprodan
182156d9b4 Add build step to e2e tests 2019-08-06 22:13:19 +03:00
Stefan Prodan
e0864b6e20 Merge pull request #27 from stefanprodan/ci
Migrate to CircleCI and run e2e tests with Kubernetes Kind
2019-08-06 21:59:13 +03:00
stefanprodan
de2a9c464a Release v2.0.1 2019-08-06 21:53:16 +03:00
stefanprodan
fed04ad692 Add e2e testing with Kubernetes Kind and Helm 2019-08-06 21:36:25 +03:00
stefanprodan
c907163073 Add JWT test to helm chart 2019-08-06 21:08:54 +03:00
stefanprodan
67578338c9 Toggle timeline background based on version 2019-08-06 20:46:17 +03:00
stefanprodan
0c27729000 Migrate CI to CircleCI 2019-08-06 20:36:57 +03:00
16 changed files with 207 additions and 65 deletions

View File

@@ -1,5 +1,47 @@
version: 2.1
jobs:
e2e-kubernetes:
machine: true
steps:
- checkout
- run:
name: Build podinfo container
command: e2e/build.sh
- run:
name: Start Kubernetes Kind cluster
command: e2e/bootstrap.sh
- run:
name: Install podinfo with Helm
command: e2e/install.sh
- run:
name: Run Helm tests
command: e2e/test.sh
push-container:
docker:
- image: circleci/golang:1.12
working_directory: ~/build
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run: make build-container
- run: |
if [ -z "$CIRCLE_TAG" ]; then
echo "Not a release, skipping container push";
else
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
make push-container;
fi
push-binary:
docker:
- image: circleci/golang:1.12
steps:
- checkout
- run: curl -sL https://git.io/goreleaser | bash
push-helm-charts:
docker:
- image: circleci/golang:1.12
@@ -40,11 +82,29 @@ jobs:
else
echo "Not a release! Skip charts publish"
fi
workflows:
version: 2
build-test:
jobs:
- e2e-kubernetes
release:
jobs:
- push-binary:
filters:
branches:
ignore: /.*/
tags:
ignore: /^chart.*/
- push-container:
filters:
branches:
ignore: /.*/
tags:
ignore: /^chart.*/
- push-helm-charts:
requires:
- push-container
filters:
branches:
ignore: /.*/

View File

@@ -1,32 +0,0 @@
sudo: required
language: go
go:
- 1.12.x
services:
- docker
addons:
apt:
packages:
- docker-ce
script:
- make build-container
after_success:
- if [ -z "$TRAVIS_TAG" ]; then
echo "Not a release, skipping container push";
else
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
make push-container;
fi
deploy:
- provider: script
skip_cleanup: true
script: curl -sL http://git.io/goreleaser | bash
on:
tags: true

View File

@@ -6,18 +6,18 @@ TAG?=latest
NAME:=podinfo
DOCKER_REPOSITORY:=stefanprodan
DOCKER_IMAGE_NAME:=$(DOCKER_REPOSITORY)/$(NAME)
GITCOMMIT:=$(shell git describe --dirty --always)
GIT_COMMIT:=$(shell git describe --dirty --always)
VERSION:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"')
run:
GO111MODULE=on go run cmd/podinfo/*
GO111MODULE=on go run -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" cmd/podinfo/* --level=debug
test:
GO111MODULE=on go test -v -race ./...
build:
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$${GIT_COMMIT}" -a -o ./bin/podinfo ./cmd/podinfo/*
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$${GIT_COMMIT}" -a -o ./bin/podcli ./cmd/podcli/*
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" -a -o ./bin/podinfo ./cmd/podinfo/*
GO111MODULE=on GIT_COMMIT=$$(git rev-list -1 HEAD) && GO111MODULE=on CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" -a -o ./bin/podcli ./cmd/podcli/*
build-charts:
helm lint charts/*
@@ -26,6 +26,13 @@ build-charts:
build-container:
docker build -t $(DOCKER_IMAGE_NAME):$(VERSION) .
test-container:
@docker rm -f podinfo || true
@docker run -dp 9898:9898 --name=podinfo $(DOCKER_IMAGE_NAME):$(VERSION)
@docker ps
@TOKEN=$$(curl -sd 'test' localhost:9898/token | jq -r .token) && \
curl -sH "Authorization: Bearer $${TOKEN}" localhost:9898/token/validate | grep test
push-container:
docker push $(DOCKER_IMAGE_NAME):$(VERSION)
docker tag $(DOCKER_IMAGE_NAME):$(VERSION) quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)

View File

@@ -1,6 +1,6 @@
# podinfo
[![Build Status](https://travis-ci.org/stefanprodan/podinfo.svg?branch=master)](https://travis-ci.org/stefanprodan/podinfo)
[![CircleCI](https://circleci.com/gh/stefanprodan/podinfo.svg?style=svg)](https://circleci.com/gh/stefanprodan/podinfo)
[![Docker Pulls](https://img.shields.io/docker/pulls/stefanprodan/podinfo)](https://hub.docker.com/r/stefanprodan/podinfo)
Podinfo is a tiny web application made with Go
@@ -16,7 +16,8 @@ Specifications:
* Structured logging with zap
* 12-factor app with viper
* Fault injection (random errors and latency)
* Helm chart
* Helm and Kustomize installers
* End-to-End testing with Kubernetes Kind and Helm
Web API:
@@ -41,6 +42,10 @@ Web API:
* `GET /ws/echo` echos content via websockets `podcli ws ws://localhost:9898/ws/echo`
* `GET /chunked/{seconds}` uses `transfer-encoding` type `chunked` to give a partial response and then waits for the specified period
Web UI:
![podinfo-ui](https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/screens/podinfo-ui.png)
### Guides
* [Automated canary deployments with Flagger and Istio](https://medium.com/google-cloud/automated-canary-deployments-with-flagger-and-istio-ac747827f9d1)
@@ -57,9 +62,12 @@ helm repo add sp https://stefanprodan.github.io/podinfo
helm upgrade --install --wait frontend \
--namespace test \
--set replicaCount=2 \
--set backend=http://backend-podinfo:9898/echo \
sp/podinfo
helm test frontend --cleanup
helm upgrade --install --wait backend \
--namespace test \
--set hpa.enabled=true \

View File

@@ -1,6 +1,6 @@
apiVersion: v1
version: 2.0.0
appVersion: 2.0.0
version: 2.0.2
appVersion: 2.0.2
name: podinfo
engine: gotpl
description: Podinfo Helm chart for Kubernetes

View File

@@ -58,7 +58,7 @@ spec:
- check
- http
- localhost:{{ .Values.service.containerPort }}/healthz
initialDelaySeconds: 5
initialDelaySeconds: 1
timeoutSeconds: 5
readinessProbe:
exec:
@@ -67,7 +67,7 @@ spec:
- check
- http
- localhost:{{ .Values.service.containerPort }}/readyz
initialDelaySeconds: 5
initialDelaySeconds: 1
timeoutSeconds: 5
volumeMounts:
- name: data

View File

@@ -1,7 +1,7 @@
apiVersion: v1
kind: Pod
metadata:
name: {{ template "podinfo.fullname" . }}-storage-test-{{ randAlphaNum 5 | lower }}
name: {{ template "podinfo.fullname" . }}-jwt-test-{{ randAlphaNum 5 | lower }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
@@ -13,7 +13,7 @@ spec:
containers:
- name: tools
image: giantswarm/tiny-tools
command: ["/bin/sh", "/scripts/ping.sh"]
command: ["/bin/sh", "/scripts/test.sh"]
env:
- name: PODINFO_SVC
value: {{ template "podinfo.fullname" . }}:{{ .Values.service.externalPort }}
@@ -36,6 +36,8 @@ metadata:
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app: {{ template "podinfo.name" . }}
data:
ping.sh: |
test.sh: |
#!/bin/sh
curl -sS ${PODINFO_SVC}/store/$(curl -sSd 'test' ${PODINFO_SVC}/store | jq -r .hash) |grep test
echo "testing ${PODINFO_SVC}/token"
TOKEN=$(curl -sd 'test' ${PODINFO_SVC}/token | jq -r .token) && \
curl -H "Authorization: Bearer ${TOKEN}" ${PODINFO_SVC}/token/validate | grep test

View File

@@ -12,7 +12,7 @@ faults:
image:
repository: quay.io/stefanprodan/podinfo
tag: 2.0.0
tag: 2.0.2
pullPolicy: IfNotPresent
service:

35
e2e/README.md Normal file
View File

@@ -0,0 +1,35 @@
# podinfo end-to-end testing
The e2e testing infrastructure is powered by CircleCI and [Kubernetes Kind](https://github.com/kubernetes-sigs/kind).
### CI workflow
* download go modules
* run unit tests
* build container
* install kubectl, helm and Kubernetes Kind CLIs
* create local Kubernetes cluster with kind
* deploy Tiller on the local cluster
* load podinfo image onto the local cluster
* deploy podinfo with Helm
* run Helm tests
```yaml
jobs:
e2e-kubernetes:
machine: true
steps:
- checkout
- run:
name: Build podinfo container
command: e2e/build.sh
- run:
name: Start Kubernetes Kind cluster
command: e2e/bootstrap.sh
- run:
name: Install podinfo with Helm
command: e2e/install.sh
- run:
name: Run Helm tests
command: e2e/test.sh
```

34
e2e/bootstrap.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
KIND_VERSION=v0.4.0
if [[ "$1" ]]; then
KIND_VERSION=$1
fi
echo ">>> Installing kubectl"
curl -sLO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
chmod +x kubectl && \
sudo mv kubectl /usr/local/bin/
echo ">>> Installing kind"
curl -sSLo kind "https://github.com/kubernetes-sigs/kind/releases/download/$KIND_VERSION/kind-linux-amd64"
chmod +x kind
sudo mv kind /usr/local/bin/kind
echo ">>> Creating kind cluster"
kind create cluster --wait 5m
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
kubectl get pods --all-namespaces
echo ">>> Installing Helm"
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
echo '>>> Installing Tiller'
kubectl --namespace kube-system create sa tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller --upgrade --wait

6
e2e/build.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -o errexit
docker build -t test/podinfo:latest .

14
e2e/install.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
echo '>>> Loading image in Kind'
kind load docker-image test/podinfo:latest
echo '>>> Installing'
helm upgrade -i podinfo ${REPO_ROOT}/charts/podinfo --namespace=default
kubectl set image deployment/podinfo podinfo=test/podinfo:latest
kubectl rollout status deployment/podinfo

12
e2e/test.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -o errexit
REPO_ROOT=$(git rev-parse --show-toplevel)
export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
echo '>>> Testing'
helm test podinfo
echo '>>> Test logs'
kubectl logs -l app=podinfo

View File

@@ -24,7 +24,7 @@ spec:
spec:
containers:
- name: podinfod
image: quay.io/stefanprodan/podinfo:2.0.0
image: quay.io/stefanprodan/podinfo:2.0.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9898

View File

@@ -1,4 +1,4 @@
package version
var VERSION = "2.0.0"
var VERSION = "2.0.2"
var REVISION = "unknown"

View File

@@ -96,9 +96,9 @@
},
methods: {
getInfo: function() {
var xhr = new XMLHttpRequest()
var self = this
xhr.open('GET', "api/info")
const xhr = new XMLHttpRequest();
let self = this;
xhr.open('GET', "api/info")
xhr.onload = function () {
data = JSON.parse(xhr.responseText)
if (self.info.version) {
@@ -107,22 +107,18 @@
}
}
self.info = data
self.info.color = parseInt(data.version.split('.').reverse()[0], 10) === 0
? 'blue'
: 'green'
self.info.color = 'cyan'
document.title = data.hostname
if ((self.calls % 2) === 0) {
self.tlColor1 = parseInt(data.version.split('.').reverse()[0], 10) === 0
? 'blue'
: 'green'
self.tlColor2 = 'grey'
self.tlName1 = data.version
} else {
self.tlColor1 = 'grey'
self.tlColor2 = parseInt(data.version.split('.').reverse()[0], 10) === 0
let verColor = (parseInt(data.version.split('.').reverse()[0], 10) % 2 === 0)
? 'blue'
: 'green'
if ((self.calls % 2) === 0) {
self.tlColor2 += ' lighten-2'
self.tlColor1 = verColor
self.tlName1 = data.version
} else {
self.tlColor1 += ' lighten-2'
self.tlColor2 = verColor
self.tlName2 = data.version
}
self.calls++