Init Helm repo

This commit is contained in:
stefanprodan
2019-08-06 16:07:32 +03:00
parent 6c8a85a5ab
commit 3dc9ac574e
1307 changed files with 37 additions and 367385 deletions

View File

@@ -1,38 +1,5 @@
version: 2
jobs:
build:
docker:
- image: errordeveloper/skaffold:66cc263ef18f107adce245b8fc622a8ea46385f2
steps:
- checkout
- setup_remote_docker: {docker_layer_caching: true}
- run:
name: Run unit tests and build the image with Skaffold
command: skaffold build --profile=test
deploy:
docker:
- image: errordeveloper/skaffold:66cc263ef18f107adce245b8fc622a8ea46385f2
steps:
- checkout
- setup_remote_docker: {docker_layer_caching: true}
- run:
name: Build and push the image to the registry with Skaffold
command: |
if [[ -z "${CIRCLE_PULL_REQUEST}" ]] && [[ "${CIRCLE_PROJECT_USERNAME}" = "stefanprodan" ]] ; then
echo $REGISTRY_PASSWORD | docker login --username $REGISTRY_USERNAME --password-stdin
skaffold build --profile=production
else
echo "Do not push image"
fi
workflows:
version: 2
main:
jobs:
- build
- deploy:
requires: [build]
filters:
branches: {only: [master]}
branches:
ignore: gh-pages

View File

@@ -1,9 +0,0 @@
docs
deploy
charts
cloudbuild.yaml
skaffold.yaml
.gitignore
.travis.yml
LICENSE
README.md

View File

@@ -1,104 +0,0 @@
---
kind: pipeline
name: linux-amd64
platform:
os: linux
arch: amd64
steps:
- name: build
image: plugins/docker:linux-amd64
settings:
dry_run: true
dockerfile: Dockerfile.ci
repo: stefanprodan/podinfo
tag: linux-amd64
when:
event:
- push
- pull_request
- name: push-commit
image: plugins/docker:linux-amd64
settings:
dockerfile: Dockerfile.arm
repo: stefanprodan/podinfo
tag: "amd64-${DRONE_COMMIT_SHA:0:8}"
username:
from_secret: DOCKER_USERNAME
password:
from_secret: DOCKER_PASSWORD
when:
branch:
- master
---
kind: pipeline
name: linux-arm64
platform:
os: linux
arch: arm64
steps:
- name: build
image: plugins/docker:linux-arm64
settings:
dry_run: true
dockerfile: Dockerfile.arm
repo: stefanprodan/podinfo
tag: linux-arm64
when:
event:
- push
- pull_request
- name: push-commit
image: plugins/docker:linux-arm64
settings:
dockerfile: Dockerfile.arm
repo: stefanprodan/podinfo
tag: "arm64-${DRONE_COMMIT_SHA:0:8}"
username:
from_secret: DOCKER_USERNAME
password:
from_secret: DOCKER_PASSWORD
when:
branch:
- master
---
kind: pipeline
name: linux-arm
platform:
os: linux
arch: arm
steps:
- name: build
image: plugins/docker:linux-arm
settings:
dry_run: true
dockerfile: Dockerfile.arm
repo: stefanprodan/podinfo
tag: linux-arm
when:
event:
- push
- pull_request
- name: push-commit
image: plugins/docker:linux-arm
settings:
dockerfile: Dockerfile.arm
repo: stefanprodan/podinfo
tag: "arm-${DRONE_COMMIT_SHA:0:8}"
username:
from_secret: DOCKER_USERNAME
password:
from_secret: DOCKER_PASSWORD
when:
branch:
- master

View File

@@ -1,17 +0,0 @@
FROM docker:stable
LABEL "name"="Docker tag and push action"
LABEL "maintainer"="Stefan Prodan <support@weave.works>"
LABEL "version"="1.0.0"
LABEL "com.github.actions.icon"="package"
LABEL "com.github.actions.color"="green"
LABEL "com.github.actions.name"="Docker Publish"
LABEL "com.github.actions.description"="This is an Action to run docker tag and push commands."
RUN apk add --no-cache ca-certificates bash git curl \
&& rm -rf /var/cache/apk/*
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
DOCKER_TAG="latest"
if [[ "${GITHUB_REF}" == "refs/tags"* ]]; then
DOCKER_TAG=$(echo ${GITHUB_REF} | rev | cut -d/ -f1 | rev)
else
DOCKER_TAG=$(echo ${GITHUB_REF} | rev | cut -d/ -f1 | rev)-$(echo ${GITHUB_SHA} | head -c7)
fi
if [[ "$1" == "build" ]]; then
docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} \
--build-arg REPOSITORY=${GITHUB_REPOSITORY} \
--build-arg SHA=${GITHUB_SHA} -f $2 .
echo "Docker image tagged as ${DOCKER_IMAGE}:${DOCKER_TAG}"
fi
if [[ "$1" == "push" ]]; then
docker push ${DOCKER_IMAGE}:${DOCKER_TAG}
echo "Docker image pushed to ${DOCKER_IMAGE}:${DOCKER_TAG}"
fi

View File

@@ -1,20 +0,0 @@
FROM golang:1.11
LABEL "name"="golang tools action"
LABEL "maintainer"="Stefan Prodan <support@weave.works>"
LABEL "version"="1.11.0"
LABEL "com.github.actions.icon"="code"
LABEL "com.github.actions.color"="green-dark"
LABEL "com.github.actions.name"="Go Tools"
LABEL "com.github.actions.description"="This is an Action to run go and dep commands."
ENV DEP_VERSION="v0.5.0"
RUN curl -fL -o /usr/local/bin/dep https://github.com/golang/dep/releases/download/${DEP_VERSION}/dep-linux-amd64 \
&& chmod +x /usr/local/bin/dep
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
set -e
APP_DIR="/go/src/github.com/${GITHUB_REPOSITORY}/"
mkdir -p ${APP_DIR} && cp -r ./ ${APP_DIR} && cd ${APP_DIR}
if [[ "$1" == "fmt" ]]; then
echo "Running go fmt"
files=$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*") 2>&1)
if [ "$files" ]; then
echo "These files did not pass the gofmt check:"
echo ${files}
exit 1
fi
fi
if [[ "$1" == "test" ]]; then
echo "Running go test"
go test $(go list ./... | grep -v /vendor/) -race -coverprofile=coverage.txt -covermode=atomic
cat coverage.txt
fi

35
.github/main.workflow vendored
View File

@@ -1,35 +0,0 @@
workflow "Publish container" {
on = "push"
resolves = ["Push"]
}
action "Lint" {
uses = "./.github/actions/golang"
args = "fmt"
}
action "Test" {
needs = ["Lint"]
uses = "./.github/actions/golang"
args = "test"
}
action "Build" {
needs = ["Test"]
uses = "./.github/actions/docker"
secrets = ["DOCKER_IMAGE"]
args = ["build", "Dockerfile.gh"]
}
action "Login" {
needs = ["Build"]
uses = "actions/docker/login@master"
secrets = ["DOCKER_USERNAME", "DOCKER_PASSWORD"]
}
action "Push" {
needs = ["Login"]
uses = "./.github/actions/docker"
secrets = ["DOCKER_IMAGE"]
args = "push"
}

21
.gitignore vendored
View File

@@ -1,21 +0,0 @@
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.DS_Store
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
.idea/
release/
build/
gcloud/
dist/

View File

@@ -1,21 +0,0 @@
builds:
- main: ./cmd/podcli
binary: podcli
ldflags: -s -w -X github.com/stefanprodan/k8s-podinfo/pkg/version.REVISION={{.Commit}}
goos:
- windows
- darwin
- linux
goarch:
- amd64
env:
- CGO_ENABLED=0
ignore:
- goos: darwin
goarch: 386
- goos: windows
goarch: 386
archive:
name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
files:
- none*

View File

@@ -1,52 +0,0 @@
sudo: required
language: go
go:
- 1.11.x
services:
- docker
addons:
apt:
packages:
- docker-ce
before_install:
- make dep
# - go get sigs.k8s.io/kind
# - curl -LO 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
# - kind create cluster
# - export KUBECONFIG="$(kind get kubeconfig-path --name="1")"
# - ./kubectl cluster-info
# - docker build -t podinfo:test -f Dockerfile.ci .
# - ./kubectl run podinfo --image=podinfo:test --port=9898 --image-pull-policy=Never -- ./podinfo --port=9898
# - sleep 5
# - ./kubectl describe deployment podinfo
# - ./kubectl describe po
script:
- make test
- make build docker-build
after_success:
- if [ -z "$DOCKER_USER" ]; then
echo "PR build, skipping Docker Hub push";
else
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
make docker-push;
fi
- if [ -z "$QUAY_USER" ]; then
echo "PR build, skipping Quay push";
else
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
make quay-push;
fi
deploy:
- provider: script
skip_cleanup: true
script: curl -sL http://git.io/goreleaser | bash
on:
tags: true

View File

@@ -1,16 +0,0 @@
FROM alpine:3.7
RUN addgroup -S app \
&& adduser -S -g app app \
&& apk --no-cache add \
curl openssl netcat-openbsd
WORKDIR /home/app
COPY ./ui ./ui
ADD podinfo .
RUN chown -R app:app ./
USER app
CMD ["./podinfo"]

View File

@@ -1,33 +0,0 @@
FROM golang:1.11 as builder
RUN mkdir -p /go/src/github.com/stefanprodan/k8s-podinfo/
WORKDIR /go/src/github.com/stefanprodan/k8s-podinfo
COPY . .
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && CGO_ENABLED=0 GOOS=linux \
go build -ldflags "-s -w -X github.com/stefanprodan/k8s-podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
-a -installsuffix cgo -o podinfo ./cmd/podinfo
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && CGO_ENABLED=0 GOOS=linux \
go build -ldflags "-s -w -X github.com/stefanprodan/k8s-podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
-a -installsuffix cgo -o podcli ./cmd/podcli
FROM alpine:3.8
RUN addgroup -S app \
&& adduser -S -g app app \
&& apk --no-cache add \
curl openssl netcat-openbsd
WORKDIR /home/app
COPY --from=builder /go/src/github.com/stefanprodan/k8s-podinfo/podinfo .
COPY --from=builder /go/src/github.com/stefanprodan/k8s-podinfo/podcli /usr/local/bin/podcli
COPY ./ui ./ui
RUN chown -R app:app ./
USER app
CMD ["./podinfo"]

View File

@@ -1,6 +0,0 @@
FROM alpine:3.7
COPY ./ui ./ui
ADD podinfo /podinfo
CMD ["./podinfo"]

View File

@@ -1,37 +0,0 @@
FROM golang:1.11 as builder
RUN mkdir -p /go/src/github.com/stefanprodan/k8s-podinfo/
WORKDIR /go/src/github.com/stefanprodan/k8s-podinfo
COPY . .
RUN go test $(go list ./... | grep -v integration | grep -v /vendor/ | grep -v /template/) -cover
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && \
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w \
-X github.com/stefanprodan/k8s-podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
-a -installsuffix cgo -o podinfo ./cmd/podinfo
RUN GIT_COMMIT=$(git rev-list -1 HEAD) && \
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w \
-X github.com/stefanprodan/k8s-podinfo/pkg/version.REVISION=${GIT_COMMIT}" \
-a -installsuffix cgo -o podcli ./cmd/podcli
FROM alpine:3.8
RUN addgroup -S app \
&& adduser -S -g app app \
&& apk --no-cache add \
curl openssl netcat-openbsd
WORKDIR /home/app
COPY --from=builder /go/src/github.com/stefanprodan/k8s-podinfo/podinfo .
COPY --from=builder /go/src/github.com/stefanprodan/k8s-podinfo/podcli /usr/local/bin/podcli
COPY ./ui ./ui
RUN chown -R app:app ./
USER app
CMD ["./podinfo"]

View File

@@ -1,39 +0,0 @@
FROM golang:1.11 as builder
ARG REPOSITORY
ARG SHA
RUN mkdir -p /go/src/github.com/${REPOSITORY}/
WORKDIR /go/src/github.com/${REPOSITORY}
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
-ldflags "-s -w -X github.com/${REPOSITORY}/pkg/version.REVISION=${SHA}" \
-a -installsuffix cgo -o podinfo ./cmd/podinfo \
&& mv podinfo /usr/local/bin/podinfo
RUN CGO_ENABLED=0 GOOS=linux go build \
-ldflags "-s -w -X github.com/${REPOSITORY}/pkg/version.REVISION=${SHA}" \
-a -installsuffix cgo -o podcli ./cmd/podcli \
&& mv podcli /usr/local/bin/podcli
FROM alpine:3.8
RUN addgroup -S app \
&& adduser -S -g app app \
&& apk --no-cache add \
curl openssl netcat-openbsd
WORKDIR /home/app
COPY --from=builder /usr/local/bin/podinfo .
COPY --from=builder /usr/local/bin/podcli /usr/local/bin/podcli
COPY ./ui ./ui
RUN chown -R app:app ./
USER app
CMD ["./podinfo"]

449
Gopkg.lock generated
View File

@@ -1,449 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:a281ff052e060998bc715e444e448f6762a6da3e20e68c689dd8696e2894a5fd"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/ini",
"internal/s3err",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/s3",
"service/sts",
]
pruneopts = "UT"
revision = "f76d9803fd695eebf74cb23c460287fa496efc21"
version = "v1.15.63"
[[projects]]
branch = "master"
digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
name = "github.com/beorn7/perks"
packages = ["quantile"]
pruneopts = "UT"
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
branch = "master"
digest = "1:37011b20a70e205b93ebea5287e1afa5618db54bf3998c36ff5a8e4b146a170a"
name = "github.com/bgentry/go-netrc"
packages = ["netrc"]
pruneopts = "UT"
revision = "9fd32a8b3d3d3f9d43c341bfe098430e07609480"
[[projects]]
digest = "1:b95738a1e6ace058b5b8544303c0871fc01d224ef0d672f778f696265d0f2917"
name = "github.com/chzyer/readline"
packages = ["."]
pruneopts = "UT"
revision = "62c6fe6193755f722b8b8788aa7357be55a50ff1"
version = "v1.4"
[[projects]]
digest = "1:76dc72490af7174349349838f2fe118996381b31ea83243812a97e5a0fd5ed55"
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
pruneopts = "UT"
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
digest = "1:865079840386857c809b72ce300be7580cb50d3d3129ce11bf9aa6ca2bc1934a"
name = "github.com/fatih/color"
packages = ["."]
pruneopts = "UT"
revision = "5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4"
version = "v1.7.0"
[[projects]]
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
pruneopts = "UT"
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d"
name = "github.com/golang/protobuf"
packages = ["proto"]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
name = "github.com/gorilla/context"
packages = ["."]
pruneopts = "UT"
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
version = "v1.1.1"
[[projects]]
digest = "1:e73f5b0152105f18bc131fba127d9949305c8693f8a762588a82a48f61756f5f"
name = "github.com/gorilla/mux"
packages = ["."]
pruneopts = "UT"
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
version = "v1.6.2"
[[projects]]
digest = "1:7b5c6e2eeaa9ae5907c391a91c132abfd5c9e8a784a341b5625e750c67e6825d"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
[[projects]]
digest = "1:f47d6109c2034cb16bd62b220e18afd5aa9d5a1630fe5d937ad96a4fb7cbb277"
name = "github.com/hashicorp/go-cleanhttp"
packages = ["."]
pruneopts = "UT"
revision = "e8ab9daed8d1ddd2d3c4efba338fe2eeae2e4f18"
version = "v0.5.0"
[[projects]]
branch = "master"
digest = "1:724d270a4cac0945dedb8de6357625a9d976cb640d381d3dab3144cec295db26"
name = "github.com/hashicorp/go-getter"
packages = [
".",
"helper/url",
]
pruneopts = "UT"
revision = "4bda8fa99001c61db3cad96b421d4c12a81f256d"
[[projects]]
digest = "1:605c47454db9040e30b20dc1b29e3e9d42d6ee742545729cdef74afb1b898ad0"
name = "github.com/hashicorp/go-safetemp"
packages = ["."]
pruneopts = "UT"
revision = "c9a55de4fe06c920a71964b53cfe3dd293a3c743"
version = "v1.0.0"
[[projects]]
digest = "1:77395dd3847dac9c45118c668f5dab85aedf0163dc3b38aea6578c5cf0d502f9"
name = "github.com/hashicorp/go-version"
packages = ["."]
pruneopts = "UT"
revision = "b5a281d3160aa11950a6182bd9a9dc2cb1e02d50"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
"json/parser",
"json/scanner",
"json/token",
]
pruneopts = "UT"
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = "UT"
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
digest = "1:e22af8c7518e1eab6f2eab2b7d7558927f816262586cd6ed9f349c97a6c285c4"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = "UT"
revision = "0b12d6b5"
[[projects]]
digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7"
name = "github.com/magiconair/properties"
packages = ["."]
pruneopts = "UT"
revision = "c2353362d570a7bfa228149c62842019201cfb71"
version = "v1.8.0"
[[projects]]
digest = "1:c658e84ad3916da105a761660dcaeb01e63416c8ec7bc62256a9b411a05fcd67"
name = "github.com/mattn/go-colorable"
packages = ["."]
pruneopts = "UT"
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
digest = "1:0981502f9816113c9c8c4ac301583841855c8cf4da8c72f696b3ebedf6d0e4e5"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = "UT"
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
version = "v0.0.4"
[[projects]]
digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
pruneopts = "UT"
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
version = "v1.0.1"
[[projects]]
digest = "1:78bbb1ba5b7c3f2ed0ea1eab57bdd3859aec7e177811563edc41198a760b06af"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
pruneopts = "UT"
revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
version = "v1.0.0"
[[projects]]
digest = "1:42eb1f52b84a06820cedc9baec2e710bfbda3ee6dac6cdb97f8b9a5066134ec6"
name = "github.com/mitchellh/go-testing-interface"
packages = ["."]
pruneopts = "UT"
revision = "6d0b8010fcc857872e42fc6c931227569016843c"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = "UT"
revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac"
[[projects]]
digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e"
name = "github.com/pelletier/go-toml"
packages = ["."]
pruneopts = "UT"
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.2.0"
[[projects]]
digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
"prometheus/promhttp",
]
pruneopts = "UT"
revision = "c5b7fccd204277076155f10851dad72b76a49317"
version = "v0.8.0"
[[projects]]
branch = "master"
digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
name = "github.com/prometheus/client_model"
packages = ["go"]
pruneopts = "UT"
revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
[[projects]]
branch = "master"
digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
name = "github.com/prometheus/common"
packages = [
"expfmt",
"internal/bitbucket.org/ww/goautoneg",
"model",
]
pruneopts = "UT"
revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
[[projects]]
branch = "master"
digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290"
name = "github.com/prometheus/procfs"
packages = [
".",
"internal/util",
"nfs",
"xfs",
]
pruneopts = "UT"
revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92"
[[projects]]
digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84"
name = "github.com/spf13/afero"
packages = [
".",
"mem",
]
pruneopts = "UT"
revision = "787d034dfe70e44075ccc060d346146ef53270ad"
version = "v1.1.1"
[[projects]]
digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f"
name = "github.com/spf13/cast"
packages = ["."]
pruneopts = "UT"
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = "UT"
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
version = "v0.0.3"
[[projects]]
branch = "master"
digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
pruneopts = "UT"
revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2"
[[projects]]
digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = "UT"
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
version = "v1.0.2"
[[projects]]
digest = "1:4fc8a61287ccfb4286e1ca5ad2ce3b0b301d746053bf44ac38cf34e40ae10372"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = "UT"
revision = "907c19d40d9a6c9bb55f040ff4ae45271a4754b9"
version = "v1.1.0"
[[projects]]
digest = "1:4aeb3860275fa1fd60cccfb5a6ef85da438bf17402e1e84412ade4d4b55066a0"
name = "github.com/ulikunitz/xz"
packages = [
".",
"internal/hash",
"internal/xlog",
"lzma",
]
pruneopts = "UT"
revision = "0c6b41e72360850ca4f98dc341fd999726ea007f"
version = "v0.5.4"
[[projects]]
digest = "1:3c1a69cdae3501bf75e76d0d86dc6f2b0a7421bc205c0cb7b96b19eed464a34d"
name = "go.uber.org/atomic"
packages = ["."]
pruneopts = "UT"
revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289"
version = "v1.3.2"
[[projects]]
digest = "1:60bf2a5e347af463c42ed31a493d817f8a72f102543060ed992754e689805d1a"
name = "go.uber.org/multierr"
packages = ["."]
pruneopts = "UT"
revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a"
version = "v1.1.0"
[[projects]]
digest = "1:c52caf7bd44f92e54627a31b85baf06a68333a196b3d8d241480a774733dcf8b"
name = "go.uber.org/zap"
packages = [
".",
"buffer",
"internal/bufferpool",
"internal/color",
"internal/exit",
"zapcore",
]
pruneopts = "UT"
revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982"
version = "v1.9.1"
[[projects]]
branch = "master"
digest = "1:e3e7f51633f98fce9404940f74dfd65cf306ee173ddf5a8b247c9c830e42b38a"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = "UT"
revision = "1a700e749ce29638d0bbcb531cce1094ea096bd3"
[[projects]]
digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295"
name = "golang.org/x/text"
packages = [
"internal/gen",
"internal/triegen",
"internal/ucd",
"transform",
"unicode/cldr",
"unicode/norm",
]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/chzyer/readline",
"github.com/dgrijalva/jwt-go",
"github.com/fatih/color",
"github.com/fsnotify/fsnotify",
"github.com/gorilla/mux",
"github.com/gorilla/websocket",
"github.com/hashicorp/go-getter",
"github.com/prometheus/client_golang/prometheus",
"github.com/prometheus/client_golang/prometheus/promhttp",
"github.com/spf13/cobra",
"github.com/spf13/pflag",
"github.com/spf13/viper",
"go.uber.org/zap",
"go.uber.org/zap/zapcore",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,39 +0,0 @@
[[constraint]]
name = "github.com/prometheus/client_golang"
version = "0.8.0"
[[constraint]]
name = "github.com/gorilla/mux"
version = "v1.6.2"
[[constraint]]
name = "github.com/gorilla/websocket"
version = "v1.4.0"
[[constraint]]
name = "go.uber.org/zap"
version = "v1.9.1"
[[override]]
name = "github.com/fsnotify/fsnotify"
version = "1.2.9"
[[constraint]]
name = "github.com/spf13/pflag"
version = "v1.0.2"
[[constraint]]
name = "github.com/spf13/viper"
version = "v1.1.0"
[[constraint]]
name = "github.com/spf13/cobra"
version = "v0.0.3"
[[constraint]]
name = "github.com/dgrijalva/jwt-go"
version = "v3.2.0"
[prune]
go-tests = true
unused-packages = true

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Stefan Prodan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

114
Makefile
View File

@@ -1,114 +0,0 @@
# Makefile for releasing Alpine multi-arch Docker images
#
# The release version is controlled from pkg/version
EMPTY:=
SPACE:=$(EMPTY) $(EMPTY)
COMMA:=$(EMPTY),$(EMPTY)
NAME:=podinfo
DOCKER_REPOSITORY:=stefanprodan
DOCKER_IMAGE_NAME:=$(DOCKER_REPOSITORY)/$(NAME)
GITREPO:=github.com/stefanprodan/k8s-podinfo
GITCOMMIT:=$(shell git describe --dirty --always)
VERSION:=$(shell grep 'VERSION' pkg/version/version.go | awk '{ print $$4 }' | tr -d '"')
LINUX_ARCH:=arm arm64 ppc64le s390x amd64
PLATFORMS:=$(subst $(SPACE),$(COMMA),$(foreach arch,$(LINUX_ARCH),linux/$(arch)))
.PHONY: build
build:
@echo Cleaning old builds
@rm -rf build && mkdir build
@echo Building: linux/$(LINUX_ARCH) $(VERSION) ;\
for arch in $(LINUX_ARCH); do \
mkdir -p build/linux/$$arch && CGO_ENABLED=0 GOOS=linux GOARCH=$$arch go build -ldflags="-s -w -X $(GITREPO)/pkg/version.REVISION=$(GITCOMMIT)" -o build/linux/$$arch/$(NAME) ./cmd/$(NAME) ;\
cp -r ui/ build/linux/$$arch/ui;\
done
.PHONY: tar
tar: build
@echo Cleaning old releases
@rm -rf release && mkdir release
for arch in $(LINUX_ARCH); do \
tar -zcf release/$(NAME)_$(VERSION)_linux_$$arch.tgz -C build/linux/$$arch $(NAME) ;\
done
.PHONY: docker-build
docker-build: tar
# Steps:
# 1. Copy appropriate podinfo binary to build/docker/linux/<arch>
# 2. Copy Dockerfile to build/docker/linux/<arch>
# 3. Replace base image from alpine:latest to <arch>/alpine:latest
# 4. Comment RUN in Dockerfile
# <arch>:
# arm: arm32v6
# arm64: arm64v8
rm -rf build/docker
@for arch in $(LINUX_ARCH); do \
mkdir -p build/docker/linux/$$arch ;\
tar -xzf release/$(NAME)_$(VERSION)_linux_$$arch.tgz -C build/docker/linux/$$arch ;\
cp -r ui/ build/docker/linux/$$arch/ui;\
if [ $$arch == amd64 ]; then \
cp Dockerfile build/docker/linux/$$arch ;\
cp Dockerfile build/docker/linux/$$arch/Dockerfile.in ;\
else \
cp Dockerfile.build build/docker/linux/$$arch/Dockerfile ;\
cp Dockerfile.build build/docker/linux/$$arch/Dockerfile.in ;\
case $$arch in \
arm) \
BASEIMAGE=arm32v6 ;\
;; \
arm64) \
BASEIMAGE=arm64v8 ;\
;; \
*) \
BASEIMAGE=$$arch ;\
;; \
esac ;\
sed -e "s/alpine:latest/$$BASEIMAGE\\/alpine:latest/" -e "s/^\\s*RUN/#RUN/" build/docker/linux/$$arch/Dockerfile.in > build/docker/linux/$$arch/Dockerfile ;\
fi ;\
docker build -t $(NAME) build/docker/linux/$$arch ;\
docker tag $(NAME) $(DOCKER_IMAGE_NAME):$(NAME)-$$arch ;\
done
.PHONY: docker-push
docker-push:
@echo Pushing: $(VERSION) to $(DOCKER_IMAGE_NAME)
for arch in $(LINUX_ARCH); do \
docker push $(DOCKER_IMAGE_NAME):$(NAME)-$$arch ;\
done
manifest-tool push from-args --platforms $(PLATFORMS) --template $(DOCKER_IMAGE_NAME):podinfo-ARCH --target $(DOCKER_IMAGE_NAME):$(VERSION)
manifest-tool push from-args --platforms $(PLATFORMS) --template $(DOCKER_IMAGE_NAME):podinfo-ARCH --target $(DOCKER_IMAGE_NAME):latest
.PHONY: quay-push
quay-push:
@echo Pushing: $(VERSION) to quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
@docker build -t quay.io/$(DOCKER_IMAGE_NAME):$(VERSION) -f Dockerfile.ci . ; docker push quay.io/$(DOCKER_IMAGE_NAME):$(VERSION)
.PHONY: clean
clean:
rm -rf release
rm -rf build
.PHONY: gcr-build
gcr-build:
docker build -t gcr.io/$(DOCKER_IMAGE_NAME):$(VERSION) -f Dockerfile.ci .
.PHONY: test
test:
go test -v -race ./...
.PHONY: dep
dep:
go get -u github.com/golang/dep/cmd/dep
go get -u github.com/estesp/manifest-tool
.PHONY: charts
charts:
cd charts/ && helm package podinfo/
cd charts/ && helm package podinfo-istio/
cd charts/ && helm package loadtest/
cd charts/ && helm package ambassador/
cd charts/ && helm package grafana/
cd charts/ && helm package ngrok/
mv charts/*.tgz docs/
helm repo index docs --url https://stefanprodan.github.io/k8s-podinfo --merge ./docs/index.yaml

View File

@@ -1,17 +0,0 @@
DOCKER_IMAGE?=stefanprodan/k8s-podinfo
DOCKER_TAG?=$(shell git symbolic-ref --short HEAD)
GIT_REPOSITORY?=stefanprodan/k8s-podinfo
GIT_SHA:=$(shell git describe --dirty --always)
.PHONY: all
all: test build
.PHONY: test
test:
go test ./...
.PHONY: build
build:
docker build -t $(DOCKER_IMAGE):$(DOCKER_TAG) \
--build-arg REPOSITORY=${GIT_REPOSITORY} \
--build-arg SHA=${GIT_SHA} -f Dockerfile.gh .

View File

@@ -1,52 +0,0 @@
# k8s-podinfo
Podinfo is a tiny web application made with Go
that showcases best practices of running microservices in Kubernetes.
Specifications:
* Release automation (Make/TravisCI/CircleCI/Quay.io/Google Cloud Container Builder/Skaffold/Weave Flux)
* Multi-platform Docker image (amd64/arm/arm64/ppc64le/s390x)
* Health checks (readiness and liveness)
* Graceful shutdown on interrupt signals
* File watcher for secrets and configmaps
* Instrumented with Prometheus
* Tracing with Istio and Jaeger
* Structured logging with zap
* 12-factor app with viper
* Fault injection (random errors and latency)
* Helm chart
Web API:
* `GET /` prints runtime information
* `GET /version` prints podinfo version and git commit hash
* `GET /metrics` return HTTP requests duration and Go runtime metrics
* `GET /healthz` used by Kubernetes liveness probe
* `GET /readyz` used by Kubernetes readiness probe
* `POST /readyz/enable` signals the Kubernetes LB that this instance is ready to receive traffic
* `POST /readyz/disable` signals the Kubernetes LB to stop sending requests to this instance
* `GET /status/{code}` returns the status code
* `GET /panic` crashes the process with exit code 255
* `POST /echo` forwards the call to the backend service and echos the posted content
* `GET /env` returns the environment variables as a JSON array
* `GET /headers` returns a JSON with the request HTTP headers
* `GET /delay/{seconds}` waits for the specified period
* `POST /token` issues a JWT token valid for one minute `JWT=$(curl -sd 'anon' podinfo:9898/token | jq -r .token)`
* `GET /token/validate` validates the JWT token `curl -H "Authorization: Bearer $JWT" podinfo:9898/token/validate`
* `GET /configs` returns a JSON with configmaps and/or secrets mounted in the `config` volume
* `POST /store` writes the posted content to disk at /data/hash and returns the SHA1 hash of the content
* `GET /store/{hash}` returns the content of the file /data/hash if exists
* `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
### Guides
* [Deploy and upgrade with Helm](docs/1-deploy.md)
* [Horizontal Pod Auto-scaling](docs/2-autoscaling.md)
* [Monitoring and alerting with Prometheus](docs/3-monitoring.md)
* [StatefulSets with local persistent volumes](docs/4-statefulsets.md)
* [Expose Kubernetes services over HTTPS with Ngrok](docs/6-ngrok.md)
* [A/B Testing with Ambassador API Gateway](docs/5-canary.md)
* [Canary Deployments with Istio](docs/7-istio.md)
* [GitHub Actions CI demo](docs/8-gh-actions.md)

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,11 +0,0 @@
apiVersion: v1
appVersion: "0.29.0"
description: A Helm chart for Datawire Ambassador
name: ambassador
version: 0.1.0
sources:
- https://github.com/datawire/ambassador
maintainers:
- name: stefanprodan
email: stefanprodan@users.noreply.github.com
engine: gotpl

View File

@@ -1,63 +0,0 @@
# Ambassador
Ambassador is an open source, Kubernetes-native [microservices API gateway](https://www.getambassador.io/about/microservices-api-gateways) built on the [Envoy Proxy](https://www.envoyproxy.io/).
## TL;DR;
```console
$ helm install stable/ambassador
```
## Introduction
This chart bootstraps an [Ambassador](https://www.getambassador.io) deployment on
a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
## Prerequisites
- Kubernetes 1.7+
## Installing the Chart
To install the chart with the release name `my-release`:
```console
$ helm install --name my-release stable/ambassador
```
The command deploys Ambassador API gateway on the Kubernetes cluster in the default configuration.
The [configuration](#configuration) section lists the parameters that can be configured during installation.
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete --purge my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following tables lists the configurable parameters of the Ambassador chart and their default values.
| Parameter | Description | Default |
| ------------------------------- | ------------------------------------------ | ---------------------------------------------------------- |
| `image` | Image | `quay.io/datawire/ambassador`
| `imageTag` | Image tag | `0.29.0`
| `imagePullPolicy` | Image pull policy | `IfNotPresent`
| `replicaCount` | Number of Ambassador replicas | `1`
| `resources` | CPU/memory resource requests/limits | None
| `rbac.create` | If `true`, create and use RBAC resources | `true`
| `serviceAccount.create` | If `true`, create a new service account | `true`
| `serviceAccount.name` | Service account to be used | `ambassador`
| `service.type` | Service type to be used | `LoadBalancer`
| `adminService.create` | If `true`, create a service for Ambassador's admin UI | `true`
| `adminService.type` | Ambassador's admin service type to be used | `ClusterIP`
| `exporter.image` | Prometheus exporter image | `datawire/prom-statsd-exporter:0.6.0`
| `timing.restart` | The minimum number of seconds between Envoy restarts | `15`
| `timing.drain` | The number of seconds that the Envoy will wait for open connections to drain on a restart | `5`
| `timing.shutdown` | The number of seconds that Ambassador will wait for the old Envoy to clean up and exit on a restart | `10`

View File

@@ -1,15 +0,0 @@
1. Get the application URL by running these commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "ambassador.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ template "ambassador.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "ambassador.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "ambassador.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
{{- end }}

View File

@@ -1,43 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "ambassador.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "ambassador.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ambassador.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "ambassador.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "ambassador.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

View File

@@ -1,21 +0,0 @@
{{- if .Values.adminService.create -}}
apiVersion: v1
kind: Service
metadata:
name: {{ template "ambassador.fullname" . }}-admin
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: {{ .Values.adminService.type }}
ports:
- port: 8877
targetPort: admin
protocol: TCP
name: admin
selector:
app: {{ template "ambassador.name" . }}
release: {{ .Release.Name }}
{{- end -}}

View File

@@ -1,78 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "ambassador.fullname" . }}
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "ambassador.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "ambassador.name" . }}
release: {{ .Release.Name }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9102"
spec:
serviceAccountName: {{ template "ambassador.serviceAccountName" . }}
containers:
- name: statsd-sink
image: "{{ .Values.exporter.image }}"
ports:
- name: metrics
containerPort: 9102
- name: ambassador
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
- name: admin
containerPort: 8877
env:
- name: AMBASSADOR_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AMBASSADOR_RESTART_TIME
value: {{ .Values.timing.restart | quote }}
- name: AMBASSADOR_DRAIN_TIME
value: {{ .Values.timing.drain | quote }}
- name: AMBASSADOR_SHUTDOWN_TIME
value: {{ .Values.timing.shutdown | quote }}
livenessProbe:
httpGet:
path: /ambassador/v0/check_alive
port: admin
initialDelaySeconds: 30
periodSeconds: 3
readinessProbe:
httpGet:
path: /ambassador/v0/check_ready
port: admin
initialDelaySeconds: 30
periodSeconds: 3
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

View File

@@ -1,42 +0,0 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: {{ template "ambassador.fullname" . }}
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups: [""]
resources:
- services
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- configmaps
verbs: ["create", "update", "patch", "get", "list", "watch"]
- apiGroups: [""]
resources:
- secrets
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ template "ambassador.fullname" . }}
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "ambassador.fullname" . }}
subjects:
- name: {{ template "ambassador.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
kind: ServiceAccount
{{- end -}}

View File

@@ -1,23 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "ambassador.fullname" . }}
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
- port: 443
targetPort: https
protocol: TCP
name: https
selector:
app: {{ template "ambassador.name" . }}
release: {{ .Release.Name }}

View File

@@ -1,11 +0,0 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "ambassador.serviceAccountName" . }}
labels:
app: {{ template "ambassador.name" . }}
chart: {{ template "ambassador.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- end -}}

View File

@@ -1,56 +0,0 @@
# Default values for ambassador.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: quay.io/datawire/ambassador
tag: 0.29.0
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 80
adminService:
create: true
type: ClusterIP
rbac:
# Specifies whether RBAC resources should be created
create: true
serviceAccount:
# Specifies whether a service account should be created
create: true
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
resources: {}
# If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
exporter:
image: datawire/prom-statsd-exporter:0.6.0
timing:
# sets the minimum number of seconds between Envoy restarts
restart: 15
# sets the number of seconds that the Envoy will wait for open connections to drain on a restart
drain: 5
# sets the number of seconds that Ambassador will wait for the old Envoy to clean up and exit on a restart
shutdown: 10

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,5 +0,0 @@
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: grafana
version: 0.1.0

View File

@@ -1,65 +0,0 @@
# Weave Cloud Grafana
Grafana v5 with Kubernetes dashboards and Prometheus and Weave Cloud data sources.
## Installing the Chart
To install the chart with the release name `my-release`:
```console
$ helm install stable/grafana --name my-release \
--set service.type=NodePort \
--set token=WEAVE-TOKEN \
--set password=admin
```
The command deploys Grafana on the Kubernetes cluster in the default namespace.
The [configuration](#configuration) section lists the parameters that can be configured during installation.
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete --purge my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following tables lists the configurable parameters of the Grafana chart and their default values.
Parameter | Description | Default
--- | --- | ---
`image.repository` | Image repository | `grafana/grafana`
`image.pullPolicy` | Image pull policy | `IfNotPresent`
`image.tag` | Image tag | `5.0.1`
`replicaCount` | desired number of pods | `1`
`resources` | pod resources | `none`
`tolerations` | List of node taints to tolerate | `[]`
`affinity` | node/pod affinities | `node`
`nodeSelector` | node labels for pod assignment | `{}`
`service.type` | type of service | `LoadBalancer`
`url` | Prometheus URL, used when Weave token is empty | `http://prometheus:9090`
`token` | Weave Cloud token | `none`
`user` | Grafana admin username | `admin`
`password` | Grafana admin password | `none`
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
$ helm install stable/grafana --name my-release \
--set=token=WEAVE-TOKEN \
--set password=admin
```
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
```console
$ helm install stable/grafana --name my-release -f values.yaml
```
> **Tip**: You can use the default [values.yaml](values.yaml)
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,817 +0,0 @@
{
"annotations": {
"list": [
{
"$$hashKey": "object:246",
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 1,
"id": null,
"iteration": 1521457664773,
"links": [],
"panels": [
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"rgba(245, 54, 54, 0.9)",
"rgba(237, 129, 40, 0.89)",
"rgba(50, 172, 45, 0.97)"
],
"datasource": "prometheus",
"editable": true,
"error": false,
"format": "none",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 4,
"w": 8,
"x": 0,
"y": 0
},
"id": 8,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "cores",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": true
},
"tableColumn": "",
"targets": [
{
"expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m])) ",
"format": "time_series",
"intervalFactor": 2,
"refId": "A",
"step": 600
}
],
"thresholds": "",
"title": "CPU",
"type": "singlestat",
"valueFontSize": "110%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "avg"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"rgba(245, 54, 54, 0.9)",
"rgba(237, 129, 40, 0.89)",
"rgba(50, 172, 45, 0.97)"
],
"datasource": "prometheus",
"editable": true,
"error": false,
"format": "none",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 4,
"w": 8,
"x": 8,
"y": 0
},
"id": 9,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "GB",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "80%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": true
},
"tableColumn": "",
"targets": [
{
"expr": "sum(container_memory_usage_bytes{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}) / 1024^3",
"format": "time_series",
"intervalFactor": 2,
"refId": "A",
"step": 600
}
],
"thresholds": "",
"title": "Memory",
"type": "singlestat",
"valueFontSize": "110%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "avg"
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"rgba(245, 54, 54, 0.9)",
"rgba(237, 129, 40, 0.89)",
"rgba(50, 172, 45, 0.97)"
],
"datasource": "prometheus",
"editable": true,
"error": false,
"format": "Bps",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": false,
"thresholdLabels": false,
"thresholdMarkers": false
},
"gridPos": {
"h": 4,
"w": 8,
"x": 16,
"y": 0
},
"id": 7,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": true
},
"tableColumn": "",
"targets": [
{
"expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m])) ",
"format": "time_series",
"intervalFactor": 2,
"refId": "A",
"step": 600
}
],
"thresholds": "",
"title": "Network",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "avg"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "prometheus",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"gridPos": {
"h": 6,
"w": 20,
"x": 0,
"y": 4
},
"id": 1,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"hideZero": false,
"max": false,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "max(kube_deployment_status_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "current replicas",
"refId": "A",
"step": 30
},
{
"expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "available",
"refId": "B",
"step": 30
},
{
"expr": "max(kube_deployment_status_replicas_unavailable{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "unavailable",
"refId": "C",
"step": 30
},
{
"expr": "min(kube_deployment_status_replicas_updated{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "updated",
"refId": "D",
"step": 30
},
{
"expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "desired",
"refId": "E",
"step": 30
}
],
"thresholds": [],
"timeFrom": null,
"timeShift": null,
"title": "Replicas",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"transparent": false,
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "none",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": false
}
]
},
{
"cacheTimeout": null,
"colorBackground": false,
"colorValue": false,
"colors": [
"rgba(245, 54, 54, 0.9)",
"rgba(237, 129, 40, 0.89)",
"rgba(50, 172, 45, 0.97)"
],
"datasource": "prometheus",
"editable": true,
"error": false,
"format": "percent",
"gauge": {
"maxValue": 100,
"minValue": 0,
"show": true,
"thresholdLabels": false,
"thresholdMarkers": true
},
"gridPos": {
"h": 6,
"w": 4,
"x": 20,
"y": 4
},
"id": 11,
"interval": null,
"links": [],
"mappingType": 1,
"mappingTypes": [
{
"name": "value to text",
"value": 1
},
{
"name": "range to text",
"value": 2
}
],
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
"prefixFontSize": "50%",
"rangeMaps": [
{
"from": "null",
"text": "N/A",
"to": "null"
}
],
"sparkline": {
"fillColor": "rgba(31, 118, 189, 0.18)",
"full": false,
"lineColor": "rgb(31, 120, 193)",
"show": false
},
"tableColumn": "",
"targets": [
{
"expr": "(min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod))\n/\n(min(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)) * 100\n",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "",
"refId": "A",
"step": 600
}
],
"thresholds": "50,80",
"title": "Availability",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
{
"op": "=",
"text": "N/A",
"value": "null"
}
],
"valueName": "avg"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "prometheus",
"fill": 1,
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 10
},
"id": 10,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"max": false,
"min": false,
"rightSide": true,
"show": true,
"sort": "current",
"sortDesc": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sort_desc(\n\nsum by (pod_name) (rate(container_cpu_usage_seconds_total{image!=\"\",container_name!=\"POD\",namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[1m])) \n\n)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{ pod_name }}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeShift": null,
"title": "Pods CPU",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "none",
"label": "cores",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "prometheus",
"fill": 1,
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 16
},
"id": 13,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"max": false,
"min": false,
"rightSide": true,
"show": true,
"sort": "current",
"sortDesc": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sort_desc(\n\nsum by (pod_name) (container_memory_working_set_bytes{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}) \n\n)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{ pod_name }}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeShift": null,
"title": "Pods Memory",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "bytes",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "prometheus",
"fill": 1,
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 22
},
"id": 12,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"max": false,
"min": false,
"rightSide": true,
"show": true,
"sort": "current",
"sortDesc": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sort_desc(\n\nsum by (pod_name) (rate (container_network_receive_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[1m])) \n+\nsum by (pod_name) (rate (container_network_transmit_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[1m]))\n)",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{ pod_name }}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeShift": null,
"title": "Pods Network I/O",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "Bps",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"refresh": "30s",
"schemaVersion": 16,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"allValue": ".*",
"current": {
"text": "default",
"value": "default"
},
"datasource": "prometheus",
"hide": 0,
"includeAll": false,
"label": "Namespace",
"multi": false,
"name": "deployment_namespace",
"options": [],
"query": "label_values(kube_deployment_metadata_generation, namespace)",
"refresh": 1,
"regex": "",
"sort": 0,
"tagValuesQuery": null,
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"allValue": null,
"current": {
"text": "ga-podinfo",
"value": "ga-podinfo"
},
"datasource": "prometheus",
"hide": 0,
"includeAll": false,
"label": "Deployment",
"multi": false,
"name": "deployment_name",
"options": [],
"query": "label_values(kube_deployment_metadata_generation{namespace=\"$deployment_namespace\"}, deployment)",
"refresh": 1,
"regex": "",
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "deployment",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Deployments",
"uid": "sgRyigkik",
"version": 2
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +0,0 @@
1. Get the application URL by running these commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ template "grafana.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "grafana.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
{{- end }}

View File

@@ -1,32 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "grafana.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "grafana.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "grafana.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -1,6 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "grafana.fullname" . }}-dashboards
data:
{{ (.Files.Glob "dashboards/*").AsConfig | indent 2 }}

View File

@@ -1,32 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "grafana.fullname" . }}-datasources
data:
datasources.yaml: |-
apiVersion: 1
deleteDatasources:
- name: prometheus
{{- if .Values.token }}
datasources:
- name: prometheus
type: prometheus
access: proxy
url: https://cloud.weave.works/api/prom
isDefault: true
editable: true
version: 1
basicAuth: true
basicAuthUser: weave
basicAuthPassword: {{ .Values.token }}
{{- else }}
datasources:
- name: prometheus
type: prometheus
access: proxy
url: {{ .Values.url }}
isDefault: true
editable: true
version: 1
{{- end }}

View File

@@ -1,81 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "grafana.fullname" . }}
labels:
app: {{ template "grafana.fullname" . }}
chart: {{ template "grafana.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "grafana.fullname" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "grafana.fullname" . }}
release: {{ .Release.Name }}
annotations:
prometheus.io/scrape: 'false'
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 3000
protocol: TCP
# livenessProbe:
# httpGet:
# path: /
# port: http
# readinessProbe:
# httpGet:
# path: /
# port: http
env:
- name: GF_SECURITY_ADMIN_USER
value: {{ .Values.user }}
- name: GF_SECURITY_ADMIN_PASSWORD
value: {{ .Values.password }}
- name: GF_PATHS_PROVISIONING
value: /etc/grafana/provisioning/
volumeMounts:
- name: grafana
mountPath: /var/lib/grafana
- name: dashboards
mountPath: /etc/grafana/dashboards
- name: datasources
mountPath: /etc/grafana/provisioning/datasources
- name: providers
mountPath: /etc/grafana/provisioning/dashboards
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: grafana
emptyDir: {}
- name: dashboards
configMap:
name: {{ template "grafana.fullname" . }}-dashboards
- name: providers
configMap:
name: {{ template "grafana.fullname" . }}-providers
- name: datasources
configMap:
name: {{ template "grafana.fullname" . }}-datasources

View File

@@ -1,17 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "grafana.fullname" . }}-providers
data:
providers.yaml: |+
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
options:
path: /etc/grafana/dashboards

View File

@@ -1,19 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "grafana.fullname" . }}
labels:
app: {{ template "grafana.name" . }}
chart: {{ template "grafana.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app: {{ template "grafana.fullname" . }}
release: {{ .Release.Name }}

View File

@@ -1,34 +0,0 @@
# Default values for grafana.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: grafana/grafana
tag: 5.0.1
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
user: admin
password:
url: http://prometheus:9090
token:

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,5 +0,0 @@
apiVersion: v1
appVersion: "1.0"
description: Hey load test Helm chart for Kubernetes
name: loadtest
version: 0.1.0

View File

@@ -1 +0,0 @@
{{ template "loadtest.fullname" . }} has been deployed successfully!

View File

@@ -1,32 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "loadtest.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "loadtest.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "loadtest.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -1,31 +0,0 @@
{{- $fullname := include "loadtest.fullname" . -}}
{{- $name := include "loadtest.name" . -}}
{{- $chart := include "loadtest.chart" . -}}
{{- $image := .Values.image -}}
{{- range $test := .Values.tests }}
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: {{ $fullname }}-{{ .name }}
labels:
app: {{ $name }}
chart: {{ $chart }}
spec:
schedule: "*/1 * * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
containers:
- name: loadtest
image: {{ $image }}
args:
- /bin/sh
- -c
- "hey -z 58s {{ $test.cmd }} {{ $test.url }}"
restartPolicy: OnFailure
{{- end -}}

View File

@@ -1,11 +0,0 @@
# Default values for loadtest.
image: stefanprodan/loadtest:latest
tests:
- name: "blue"
url: "https://canary.istio.weavedx.com/api/echo"
cmd: "-h2 -m POST -d '{test: 1}' -H 'X-API-Version: 0.6.0' -c 50 -q 5"
- name: "green"
url: "https://canary.istio.weavedx.com/api/echo"
cmd: "-h2 -m POST -d '{test: 2}' -H 'X-API-Version: 0.6.1' -c 10 -q 5"

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,5 +0,0 @@
apiVersion: v1
appVersion: "1.0"
description: A Ngrok Helm chart for Kubernetes
name: ngrok
version: 0.2.0

View File

@@ -1,64 +0,0 @@
# Ngrok
Expose Kubernetes service with [Ngrok](https://ngrok.com).
## Installing the Chart
To install the chart with the release name `my-release`:
```console
$ helm install sp/ngrok --name my-release \
--set token=NGROK-TOKEN \
--set expose.service=podinfo:9898
```
The command deploys Ngrok on the Kubernetes cluster in the default namespace.
The [configuration](#configuration) section lists the parameters that can be configured during installation.
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete --purge my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following tables lists the configurable parameters of the Grafana chart and their default values.
Parameter | Description | Default
--- | --- | ---
`image.repository` | Image repository | `stefanprodan/ngrok`
`image.pullPolicy` | Image pull policy | `IfNotPresent`
`image.tag` | Image tag | `latest`
`replicaCount` | desired number of pods | `1`
`tolerations` | List of node taints to tolerate | `[]`
`affinity` | node/pod affinities | `node`
`nodeSelector` | node labels for pod assignment | `{}`
`service.type` | type of service | `ClusterIP`
`token` | Ngrok auth token | `none`
`expose.service` | Service address to be exposed as in `service-name:port` | `none`
`subdomain` | Ngrok subdomain | `none`
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
$ helm upgrade --install --wait tunel \
--set token=NGROK-TOKEN \
--set service.type=NodePort \
--set expose.service=podinfo:9898 \
sp/ngrok
```
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
```console
$ helm install sp/grafana --name my-release -f values.yaml
```
> **Tip**: You can use the default [values.yaml](values.yaml)
```

View File

@@ -1,15 +0,0 @@
1. Get the application URL by running these commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "ngrok.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ template "ngrok.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "ngrok.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "ngrok.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
{{- end }}

View File

@@ -1,32 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "ngrok.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "ngrok.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ngrok.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -1,12 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "ngrok.fullname" . }}
data:
ngrok.yml: |-
web_addr: 0.0.0.0:4040
update: false
log: stdout
{{- if .Values.token }}
authtoken: {{ .Values.token }}
{{- end }}

View File

@@ -1,65 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "ngrok.fullname" . }}
labels:
app: {{ template "ngrok.name" . }}
chart: {{ template "ngrok.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "ngrok.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "ngrok.name" . }}
release: {{ .Release.Name }}
annotations:
prometheus.io/scrape: 'false'
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- ./ngrok
- http
{{- if .Values.subdomain }}
- --subdomain={{ .Values.subdomain }}
{{- end }}
- {{ .Values.expose.service }}
volumeMounts:
- name: config
mountPath: /home/ngrok/.ngrok2
ports:
- name: http
containerPort: 4040
protocol: TCP
livenessProbe:
httpGet:
path: /api/tunnels
port: http
initialDelaySeconds: 10
periodSeconds: 30
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ template "ngrok.fullname" . }}

View File

@@ -1,19 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "ngrok.fullname" . }}
labels:
app: {{ template "ngrok.name" . }}
chart: {{ template "ngrok.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app: {{ template "ngrok.name" . }}
release: {{ .Release.Name }}

View File

@@ -1,27 +0,0 @@
# Default values for ngrok.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: stefanprodan/ngrok
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 4040
expose:
service: ga-podinfo:9898
token: 4i3rDinhLqMHtvez71N9S_38rkS7onwv77VFNZTaUR6
nodeSelector: {}
tolerations: []
affinity: {}
subdomain:

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,12 +0,0 @@
apiVersion: v1
version: 1.2.1
appVersion: 1.2.1
engine: gotpl
name: podinfo-istio
description: Podinfo Helm chart for Istio
home: https://github.com/stefanprodan/k8s-podinfo
maintainers:
- email: stefanprodan@users.noreply.github.com
name: stefanprodan
sources:
- https://github.com/stefanprodan/k8s-podinfo

View File

@@ -1,80 +0,0 @@
# Podinfo Istio
Podinfo is a tiny web application made with Go
that showcases best practices of running microservices in Kubernetes.
## Installing the Chart
Create an Istio enabled namespace:
```console
kubectl create namespace demo
kubectl label namespace demo istio-injection=enabled
```
Create an Istio Gateway in the `istio-system` namespace named `public-gateway`:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: public-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
```
Create the `frontend` release by specifying the external domain name:
```console
helm upgrade frontend --install ./charts/podinfo-istio \
--namespace=demo \
--set host=podinfo.example.com \
--set gateway.name=public-gateway \
--set gateway.create=false \
-f ./charts/podinfo-istio/frontend.yaml
```
Create the `backend` release:
```console
helm upgrade backend --install ./charts/podinfo-istio \
--namespace=demo \
-f ./charts/podinfo-istio/backend.yaml
```
Create the `store` release:
```console
helm upgrade store --install ./charts/podinfo-istio \
--namespace=demo \
-f ./charts/podinfo-istio/store.yaml
```
Start load test:
```console
helm upgrade --install loadtest ./charts/loadtest \
--namespace=loadtesting
```

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env bash
#Usage: fswatch -o ./podinfo-istio/ | xargs -n1 ./podinfo-istio/apply.sh
set -e
MARK='\033[0;32m'
NC='\033[0m'
log (){
echo -e "$(date +%Y-%m-%dT%H:%M:%S%z) ${MARK}${1}${NC}"
}
log "installing frontend"
helm upgrade frontend --install ./podinfo-istio \
--namespace=demo \
--set host=canary.istio.weavedx.com \
--set gateway.name=public-gateway \
--set gateway.create=false \
-f ./podinfo-istio/frontend.yaml
log "installing backend"
helm upgrade backend --install ./podinfo-istio \
--namespace=demo \
-f ./podinfo-istio/backend.yaml
log "installing store"
helm upgrade store --install ./podinfo-istio \
--namespace=demo \
-f ./podinfo-istio/store.yaml
log "finished installing frontend, backend and store"

View File

@@ -1,21 +0,0 @@
# Default values for backend demo.
# expose the blue/green deployments inside the cluster
host: backend
# stable release
blue:
replicas: 2
tag: "1.1.1"
backend: http://store:9898/api/echo
# canary release
green:
replicas: 2
tag: "1.2.0"
routing:
# target green callers
- match:
- sourceLabels:
color: green
backend: http://store:9898/api/echo

View File

@@ -1,39 +0,0 @@
# Default values for frontend demo.
# external domain
host:
exposeHost: true
# no more than one Gateway can be created on a cluster
# if TLS is enabled the istio-ingressgateway-certs secret must exist in istio-system ns
# if you have a Gateway running you can set the name to your own gateway and turn off create
gateway:
name: public-gateway
create: false
tls: true
httpsRedirect: true
# stable release
blue:
replicas: 2
tag: "1.1.1"
message: "Greetings from the blue frontend"
backend: http://backend:9898/api/echo
# canary release
green:
replicas: 2
tag: "1.2.0"
routing:
# target Safari
- match:
- headers:
user-agent:
regex: "^(?!.*Chrome).*Safari.*"
# target API clients by version
- match:
- headers:
x-api-version:
regex: "^(v{0,1})0\\.6\\.([1-9]).*"
message: "Greetings from the green frontend"
backend: http://backend:9898/api/echo

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
# Default values for backend demo.
# expose the store deployment inside the cluster
host: store
# load balance 80/20 between blue and green
blue:
replicas: 2
tag: "1.1.1"
backend: https://httpbin.org/anything
weight: 80
green:
replicas: 2
tag: "1.2.0"
backend: https://httpbin.org/anything
externalServices:
- httpbin.org

View File

@@ -1 +0,0 @@
{{ template "podinfo-istio.fullname" . }} has been deployed successfully!

View File

@@ -1,36 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "podinfo-istio.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
The release name is used as a full name.
*/}}
{{- define "podinfo-istio.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- define "podinfo-istio.blue" -}}
{{- printf "%s-%s" .Release.Name "blue" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "podinfo-istio.green" -}}
{{- printf "%s-%s" .Release.Name "green" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "podinfo-istio.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -1,79 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "podinfo-istio.blue" . }}
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
color: blue
version: {{ .Values.blue.tag }}
spec:
replicas: {{ .Values.blue.replicas }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
app: {{ template "podinfo-istio.fullname" . }}
color: blue
template:
metadata:
labels:
app: {{ template "podinfo-istio.fullname" . }}
color: blue
version: {{ .Values.blue.tag }}
annotations:
prometheus.io/scrape: 'true'
spec:
terminationGracePeriodSeconds: 30
containers:
- name: podinfod
image: "{{ .Values.blue.repository }}:{{ .Values.blue.tag }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
command:
- ./podinfo
- --port={{ .Values.containerPort }}
- --level={{ .Values.logLevel }}
- --random-delay={{ .Values.blue.faults.delay }}
- --random-error={{ .Values.blue.faults.error }}
env:
- name: PODINFO_UI_COLOR
value: blue
{{- if .Values.blue.backend }}
- name: PODINFO_BACKEND_URL
value: {{ .Values.blue.backend }}
{{- end }}
{{- if .Values.blue.message }}
- name: PODINFO_UI_MESSAGE
value: {{ .Values.blue.message }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.containerPort }}
protocol: TCP
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.containerPort }}/healthz
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.containerPort }}/readyz
periodSeconds: 3
volumeMounts:
- name: data
mountPath: /data
resources:
{{ toYaml .Values.resources | indent 12 }}
volumes:
- name: data
emptyDir: {}

View File

@@ -1,20 +0,0 @@
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: {{ template "podinfo-istio.fullname" . }}
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
host: {{ template "podinfo-istio.fullname" . }}
subsets:
- name: blue
labels:
color: blue
{{- if gt .Values.green.replicas 0.0 }}
- name: green
labels:
color: green
{{- end }}

View File

@@ -1,22 +0,0 @@
{{- if .Values.externalServices -}}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: {{ template "podinfo-istio.fullname" . }}-external-svcs
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
hosts:
{{- range .Values.externalServices }}
- {{ . }}
{{- end }}
location: MESH_EXTERNAL
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
{{- end }}

View File

@@ -1,31 +0,0 @@
{{- if .Values.gateway.create -}}
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: {{ .Values.gateway.name }}
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
tls:
httpsRedirect: {{ .Values.gateway.httpsRedirect }}
{{- if .Values.gateway.tls }}
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
{{- end }}
{{- end }}

View File

@@ -1,81 +0,0 @@
{{- if gt .Values.green.replicas 0.0 -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "podinfo-istio.green" . }}
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
color: green
version: {{ .Values.green.tag }}
spec:
replicas: {{ .Values.green.replicas }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
app: {{ template "podinfo-istio.fullname" . }}
color: green
template:
metadata:
labels:
app: {{ template "podinfo-istio.fullname" . }}
color: green
version: {{ .Values.green.tag }}
annotations:
prometheus.io/scrape: 'true'
spec:
terminationGracePeriodSeconds: 30
containers:
- name: podinfod
image: "{{ .Values.green.repository }}:{{ .Values.green.tag }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
command:
- ./podinfo
- --port={{ .Values.containerPort }}
- --level={{ .Values.logLevel }}
- --random-delay={{ .Values.green.faults.delay }}
- --random-error={{ .Values.green.faults.error }}
env:
- name: PODINFO_UI_COLOR
value: green
{{- if .Values.green.backend }}
- name: PODINFO_BACKEND_URL
value: {{ .Values.green.backend }}
{{- end }}
{{- if .Values.green.message }}
- name: PODINFO_UI_MESSAGE
value: {{ .Values.green.message }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.containerPort }}
protocol: TCP
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.containerPort }}/healthz
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.containerPort }}/readyz
periodSeconds: 3
volumeMounts:
- name: data
mountPath: /data
resources:
{{ toYaml .Values.resources | indent 12 }}
volumes:
- name: data
emptyDir: {}
{{- end }}

View File

@@ -1,18 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "podinfo-istio.fullname" . }}
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: ClusterIP
ports:
- port: {{ .Values.containerPort }}
targetPort: http
protocol: TCP
name: http
selector:
app: {{ template "podinfo-istio.fullname" . }}

View File

@@ -1,43 +0,0 @@
{{- $host := .Release.Name -}}
{{- $timeout := .Values.timeout -}}
{{- $greenWeight := (sub 100 (.Values.blue.weight|int)) | int -}}
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: {{ template "podinfo-istio.fullname" . }}
labels:
app: {{ template "podinfo-istio.fullname" . }}
chart: {{ template "podinfo-istio.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
hosts:
- {{ .Values.host }}
{{- if .Values.exposeHost }}
gateways:
- {{ .Values.gateway.name }}.istio-system.svc.cluster.local
{{- end }}
http:
{{- if gt .Values.green.replicas 0.0 }}
{{- range .Values.green.routing }}
- match:
{{ toYaml .match | indent 6 }}
route:
- destination:
host: {{ $host }}
subset: green
timeout: {{ $timeout }}
{{- end }}
{{- end }}
- route:
- destination:
host: {{ template "podinfo-istio.fullname" . }}
subset: blue
weight: {{ .Values.blue.weight }}
{{- if gt .Values.green.replicas 0.0 }}
- destination:
host: {{ template "podinfo-istio.fullname" . }}
subset: green
weight: {{ $greenWeight }}
{{- end }}
timeout: {{ $timeout }}

View File

@@ -1,60 +0,0 @@
# Default values for podinfo-istio.
# host can be an external domain or a local one
host: podinfo
# if the host is an external domain must be exposed via the Gateway
exposeHost: false
timeout: 30s
# creates public-gateway.istio-system.svc.cluster.local
# no more than one Gateway can be created on a cluster
# if TLS is enabled the istio-ingressgateway-certs secret must exist in istio-system ns
# if you have a Gateway running you can set the name to your own gateway and turn off create
gateway:
name: public-gateway
create: false
tls: false
httpsRedirect: false
# authorise external https services
#externalServices:
# - api.github.com
# - apis.google.com
# - googleapis.com
# stable release
# by default all traffic goes to blue
blue:
replicas: 2
repository: quay.io/stefanprodan/podinfo
tag: "1.2.1"
# green must have at at least one replica to set weight under 100
weight: 100
message:
backend:
faults:
delay: false
error: false
# canary release
# disabled with 0 replicas
green:
replicas: 0
repository: quay.io/stefanprodan/podinfo
tag: "1.2.1"
message:
backend:
routing:
faults:
delay: false
error: false
# blue/green common settings
logLevel: info
containerPort: 9898
imagePullPolicy: IfNotPresent
resources:
limits:
requests:
cpu: 1m
memory: 16Mi

View File

@@ -1,21 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

View File

@@ -1,12 +0,0 @@
apiVersion: v1
version: 1.7.0
appVersion: 1.7.1
name: podinfo
engine: gotpl
description: Podinfo Helm chart for Kubernetes
home: https://github.com/stefanprodan/k8s-podinfo
maintainers:
- email: stefanprodan@users.noreply.github.com
name: stefanprodan
sources:
- https://github.com/stefanprodan/k8s-podinfo

View File

@@ -1,81 +0,0 @@
# Podinfo
Podinfo is a tiny web application made with Go
that showcases best practices of running microservices in Kubernetes.
## Installing the Chart
To install the chart with the release name `my-release`:
```console
$ helm repo add sp https://stefanprodan.github.io/k8s-podinfo
$ helm upgrade my-release --install sp/podinfo
```
The command deploys podinfo on the Kubernetes cluster in the default namespace.
The [configuration](#configuration) section lists the parameters that can be configured during installation.
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```console
$ helm delete --purge my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following tables lists the configurable parameters of the podinfo chart and their default values.
Parameter | Description | Default
--- | --- | ---
`affinity` | node/pod affinities | None
`color` | UI color | blue
`backend` | echo backend URL | None
`faults.delay` | random HTTP response delays between 0 and 5 seconds | `false`
`faults.error` | 1/3 chances of a random HTTP response error | `false`
`hpa.enabled` | enables HPA | `false`
`hpa.cpu` | target CPU usage per pod | None
`hpa.memory` | target memory usage per pod | None
`hpa.requests` | target requests per second per pod | None
`hpa.maxReplicas` | maximum pod replicas | `10`
`ingress.hosts` | ingress accepted hostnames | None
`ingress.tls` | ingress TLS configuration | None:
`image.pullPolicy` | image pull policy | `IfNotPresent`
`image.repository` | image repository | `stefanprodan/podinfo`
`image.tag` | image tag | `0.0.1`
`ingress.enabled` | enables ingress | `false`
`ingress.annotations` | ingress annotations | None
`ingress.hosts` | ingress accepted hostnames | None
`ingress.tls` | ingress TLS configuration | None
`message` | UI greetings message | None
`nodeSelector` | node labels for pod assignment | `{}`
`replicaCount` | desired number of pods | `2`
`resources.requests/cpu` | pod CPU request | `1m`
`resources.requests/memory` | pod memory request | `16Mi`
`resources.limits/cpu` | pod CPU limit | None
`resources.limits/memory` | pod memory limit | None
`service.externalPort` | external port for the service | `9898`
`service.internalPort` | internal port for the service | `9898`
`service.nodePort` | node port for the service | `31198`
`service.type` | type of service | `ClusterIP`
`tolerations` | list of node taints to tolerate | `[]`
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```console
$ helm install stable/podinfo --name my-release \
--set=image.tag=0.0.2,service.type=NodePort
```
Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
```console
$ helm install stable/podinfo --name my-release -f values.yaml
```
> **Tip**: You can use the default [values.yaml](values.yaml)
```

View File

@@ -1,19 +0,0 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "podinfo.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ template "podinfo.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "podinfo.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "podinfo.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:{{ .Values.service.externalPort }}
{{- end }}

View File

@@ -1,32 +0,0 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "podinfo.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "podinfo.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "podinfo.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -1,91 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "podinfo.fullname" . }}
labels:
app: {{ template "podinfo.name" . }}
chart: {{ template "podinfo.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
app: {{ template "podinfo.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "podinfo.name" . }}
release: {{ .Release.Name }}
annotations:
prometheus.io/scrape: 'true'
spec:
terminationGracePeriodSeconds: 30
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- ./podinfo
- --port={{ .Values.service.containerPort }}
- --level={{ .Values.logLevel }}
- --random-delay={{ .Values.faults.delay }}
- --random-error={{ .Values.faults.error }}
env:
- name: PODINFO_UI_COLOR
value: {{ .Values.color }}
{{- if .Values.message }}
- name: PODINFO_UI_MESSAGE
value: {{ .Values.message }}
{{- end }}
{{- if .Values.backend }}
- name: PODINFO_BACKEND_URL
value: {{ .Values.backend }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.containerPort }}
protocol: TCP
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.service.containerPort }}/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.service.containerPort }}/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
volumeMounts:
- name: data
mountPath: /data
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: data
emptyDir: {}

View File

@@ -1,32 +0,0 @@
{{- if .Values.hpa.enabled -}}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ template "podinfo.fullname" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1beta2
kind: Deployment
name: {{ template "podinfo.fullname" . }}
minReplicas: {{ .Values.replicaCount }}
maxReplicas: {{ .Values.hpa.maxReplicas }}
metrics:
{{- if .Values.hpa.cpu }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.hpa.cpu }}
{{- end }}
{{- if .Values.hpa.memory }}
- type: Resource
resource:
name: memory
targetAverageValue: {{ .Values.hpa.memory }}
{{- end }}
{{- if .Values.hpa.requests }}
- type: Pod
pods:
metricName: http_requests
targetAverageValue: {{ .Values.hpa.requests }}
{{- end }}
{{- end }}

View File

@@ -1,39 +0,0 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "podinfo.fullname" . -}}
{{- $servicePort := .Values.service.port -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
app: {{ template "podinfo.name" . }}
chart: {{ template "podinfo.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- with .Values.ingress.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ $fullName }}
servicePort: http
{{- end }}
{{- end }}

View File

@@ -1,22 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "podinfo.fullname" . }}
labels:
app: {{ template "podinfo.name" . }}
chart: {{ template "podinfo.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.externalPort }}
targetPort: http
protocol: TCP
name: http
{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
app: {{ template "podinfo.name" . }}
release: {{ .Release.Name }}

View File

@@ -1,18 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
name: {{ template "podinfo.fullname" . }}-service-test-{{ randAlphaNum 5 | lower }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app: {{ template "podinfo.name" . }}
annotations:
"helm.sh/hook": test-success
spec:
containers:
- name: curl
image: radial/busyboxplus:curl
command: ['curl']
args: ['{{ template "podinfo.fullname" . }}:{{ .Values.service.externalPort }}']
restartPolicy: Never

View File

@@ -1,41 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
name: {{ template "podinfo.fullname" . }}-storage-test-{{ randAlphaNum 5 | lower }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app: {{ template "podinfo.name" . }}
annotations:
"helm.sh/hook": test-success
spec:
containers:
- name: tools
image: giantswarm/tiny-tools
command: ["/bin/sh", "/scripts/ping.sh"]
env:
- name: PODINFO_SVC
value: {{ template "podinfo.fullname" . }}:{{ .Values.service.externalPort }}
volumeMounts:
- name: scripts
mountPath: /scripts
restartPolicy: Never
volumes:
- name: scripts
configMap:
name: {{ template "podinfo.fullname" . }}-storage-cfg
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "podinfo.fullname" . }}-storage-cfg
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app: {{ template "podinfo.name" . }}
data:
ping.sh: |
#!/bin/sh
curl -sS ${PODINFO_SVC}/store/$(curl -sSd 'test' ${PODINFO_SVC}/store | jq -r .hash) |grep test

View File

@@ -1,59 +0,0 @@
# Default values for podinfo.
replicaCount: 1
logLevel: info
color: blue
backend: #http://backend-podinfo:9898/echo
message: #UI greetings
faults:
delay: false
error: false
image:
repository: quay.io/stefanprodan/podinfo
tag: 1.7.1
pullPolicy: IfNotPresent
service:
type: ClusterIP
externalPort: 9898
containerPort: 9898
nodePort: 31198
# metrics-server add-on required
hpa:
enabled: false
maxReplicas: 10
# average total CPU usage per pod (1-100)
cpu:
# average memory usage per pod (100Mi-1Gi)
memory:
# average http requests per second per pod (k8s-prometheus-adapter)
requests:
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
path: /
hosts:
- podinfo.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources:
limits:
requests:
cpu: 1m
memory: 16Mi
nodeSelector: {}
tolerations: []
affinity: {}

View File

@@ -1,4 +0,0 @@
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build','-f' , 'Dockerfile.ci', '-t', 'gcr.io/$PROJECT_ID/podinfo:$BRANCH_NAME-$SHORT_SHA', '.']
images: ['gcr.io/$PROJECT_ID/podinfo:$BRANCH_NAME-$SHORT_SHA']

View File

@@ -1,245 +0,0 @@
package main
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/spf13/cobra"
"go.uber.org/zap"
)
var (
retryCount int
retryDelay time.Duration
method string
body string
timeout time.Duration
)
var checkCmd = &cobra.Command{
Use: `check`,
Short: "Health check commands",
Long: "Commands for running health checks",
}
var checkUrlCmd = &cobra.Command{
Use: `http [address]`,
Short: "HTTP(S) health check",
Example: ` check http https://httpbin.org/anything --method=POST --retry=2 --delay=2s --timeout=3s --body='{"test"=1}'`,
RunE: runCheck,
}
var checkTcpCmd = &cobra.Command{
Use: `tcp [address]`,
Short: "TCP health check",
Example: ` check tcp httpbin.org:443 --retry=1 --delay=2s --timeout=2s`,
RunE: runCheckTCP,
}
var checkCertCmd = &cobra.Command{
Use: `cert [address]`,
Short: "SSL/TLS certificate validity check",
Example: ` check cert httpbin.org`,
RunE: runCheckCert,
}
func init() {
checkUrlCmd.Flags().StringVar(&method, "method", "GET", "HTTP method")
checkUrlCmd.Flags().StringVar(&body, "body", "", "HTTP POST/PUT content")
checkUrlCmd.Flags().IntVar(&retryCount, "retry", 0, "times to retry the HTTP call")
checkUrlCmd.Flags().DurationVar(&retryDelay, "delay", 1*time.Second, "wait duration between retries")
checkUrlCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
checkCmd.AddCommand(checkUrlCmd)
checkTcpCmd.Flags().IntVar(&retryCount, "retry", 0, "times to retry the TCP check")
checkTcpCmd.Flags().DurationVar(&retryDelay, "delay", 1*time.Second, "wait duration between retries")
checkTcpCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
checkCmd.AddCommand(checkTcpCmd)
checkCmd.AddCommand(checkCertCmd)
rootCmd.AddCommand(checkCmd)
}
func runCheck(cmd *cobra.Command, args []string) error {
if retryCount < 0 {
return fmt.Errorf("--retry is required")
}
if len(args) < 1 {
return fmt.Errorf("address is required! example: check http https://httpbin.org")
}
address := args[0]
if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") {
address = fmt.Sprintf("http://%s", address)
}
for n := 0; n <= retryCount; n++ {
if n != 1 {
time.Sleep(retryDelay)
}
req, err := http.NewRequest(method, address, bytes.NewBuffer([]byte(body)))
if err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
os.Exit(1)
}
ctx, cancel := context.WithTimeout(req.Context(), timeout)
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
cancel()
if err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
continue
}
if resp.Body != nil {
resp.Body.Close()
}
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
logger.Info("check succeed",
zap.String("address", address),
zap.Int("status code", resp.StatusCode),
zap.String("response size", fmtContentLength(resp.ContentLength)))
os.Exit(0)
} else {
logger.Info("check failed",
zap.String("address", address),
zap.Int("status code", resp.StatusCode))
continue
}
}
os.Exit(1)
return nil
}
func runCheckTCP(cmd *cobra.Command, args []string) error {
if retryCount < 0 {
return fmt.Errorf("--retry is required")
}
if len(args) < 1 {
return fmt.Errorf("address is required! example: check tcp httpbin.org:80")
}
address := args[0]
for n := 0; n <= retryCount; n++ {
if n != 1 {
time.Sleep(retryDelay)
}
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
continue
}
conn.Close()
logger.Info("check succeed", zap.String("address", address))
os.Exit(0)
}
os.Exit(1)
return nil
}
func runCheckCert(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("address is required! example: check cert httpbin.org")
}
host := args[0]
if !strings.HasPrefix(host, "https://") {
host = "https://" + host
}
u, err := url.Parse(host)
if err != nil {
logger.Info("check failed",
zap.String("address", host),
zap.Error(err))
os.Exit(1)
}
address := u.Hostname() + ":443"
ipConn, err := net.DialTimeout("tcp", address, 5*time.Second)
if err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
os.Exit(1)
}
defer ipConn.Close()
conn := tls.Client(ipConn, &tls.Config{
InsecureSkipVerify: true,
ServerName: u.Hostname(),
})
if err = conn.Handshake(); err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
os.Exit(1)
}
defer conn.Close()
addr := conn.RemoteAddr()
_, _, err = net.SplitHostPort(addr.String())
if err != nil {
logger.Info("check failed",
zap.String("address", address),
zap.Error(err))
os.Exit(1)
}
cert := conn.ConnectionState().PeerCertificates[0]
timeNow := time.Now()
if timeNow.After(cert.NotAfter) {
logger.Info("check failed",
zap.String("address", address),
zap.String("issuer", cert.Issuer.CommonName),
zap.String("subject", cert.Subject.CommonName),
zap.Time("expired", cert.NotAfter))
os.Exit(1)
}
logger.Info("check succeed",
zap.String("address", address),
zap.String("issuer", cert.Issuer.CommonName),
zap.String("subject", cert.Subject.CommonName),
zap.Time("notAfter", cert.NotAfter),
zap.Time("notBefore", cert.NotBefore))
return nil
}
func fmtContentLength(b int64) string {
const unit = 1000
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
}

View File

@@ -1,365 +0,0 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/hashicorp/go-getter"
"github.com/spf13/cobra"
)
var (
codeProjectName string
codeGitUser string
codeVersion string
codeProjectPath string
)
var codeCmd = &cobra.Command{
Use: `code`,
Short: "Code commands",
}
var codeInitCmd = &cobra.Command{
Use: `init [name]`,
Short: "initialize podinfo code repo",
Example: ` code init demo-app --version=v1.2.0 --git-user=stefanprodan`,
RunE: runCodeInit,
}
func init() {
codeInitCmd.Flags().StringVar(&codeGitUser, "git-user", "", "GitHub user or org")
codeInitCmd.Flags().StringVar(&codeVersion, "version", "master", "podinfo repo tag or branch name")
codeInitCmd.Flags().StringVar(&codeProjectPath, "path", ".", "destination repo")
codeCmd.AddCommand(codeInitCmd)
rootCmd.AddCommand(codeCmd)
}
func runCodeInit(cmd *cobra.Command, args []string) error {
if len(codeGitUser) < 0 {
return fmt.Errorf("--git-user is required")
}
if len(args) < 1 {
return fmt.Errorf("project name is required")
}
codeProjectName = args[0]
pwd, err := os.Getwd()
if err != nil {
log.Fatalf("Error getting pwd: %s", err)
os.Exit(1)
}
tmpPath := "/tmp/k8s-podinfo"
versionName := fmt.Sprintf("k8s-podinfo-%s", codeVersion)
downloadURL := fmt.Sprintf("https://github.com/stefanprodan/k8s-podinfo/archive/%s.zip", codeVersion)
client := &getter.Client{
Src: downloadURL,
Dst: tmpPath,
Pwd: pwd,
Mode: getter.ClientModeAny,
}
fmt.Printf("Downloading %s\n", downloadURL)
if err := client.Get(); err != nil {
log.Fatalf("Error downloading: %s", err)
os.Exit(1)
}
pkgFrom := "github.com/stefanprodan/k8s-podinfo"
pkgTo := fmt.Sprintf("github.com/%s/%s", codeGitUser, codeProjectName)
if err := replaceImports(tmpPath, pkgFrom, pkgTo); err != nil {
log.Fatalf("Error parsing imports: %s", err)
os.Exit(1)
}
dirs := []string{"pkg", "cmd", "ui", "vendor", ".github"}
for _, dir := range dirs {
err = os.MkdirAll(path.Join(codeProjectPath, dir), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
if err := copyDir(path.Join(tmpPath, versionName, dir), path.Join(codeProjectPath, dir)); err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
files := []string{"Gopkg.toml", "Gopkg.lock"}
for _, file := range files {
if err := copyFile(path.Join(tmpPath, versionName, file), path.Join(codeProjectPath, file)); err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
fileContent, err := ioutil.ReadFile(path.Join(codeProjectPath, file))
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
newContent := strings.Replace(string(fileContent), pkgFrom, pkgTo, -1)
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
projFrom := "stefanprodan/k8s-podinfo"
projTo := fmt.Sprintf("%s/%s", codeGitUser, codeProjectName)
makeFiles := []string{"Makefile.gh", "Dockerfile.gh"}
for _, file := range makeFiles {
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
destFile := strings.Replace(file, ".gh", "", -1)
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
err = ioutil.WriteFile(path.Join(codeProjectPath, destFile), []byte(newContent), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
workflows := []string{".github/main.workflow"}
for _, file := range workflows {
fileContent, err := ioutil.ReadFile(path.Join(codeProjectPath, file))
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
newContent := strings.Replace(string(fileContent), "Dockerfile.gh", "Dockerfile", -1)
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
dockerFiles := []string{"Dockerfile.ci"}
for _, file := range dockerFiles {
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
err = ioutil.WriteFile(path.Join(codeProjectPath, file), []byte(newContent), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
travisFiles := []string{"travis.lite.yml"}
for _, file := range travisFiles {
fileContent, err := ioutil.ReadFile(path.Join(tmpPath, versionName, file))
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
destFile := strings.Replace(file, "travis.lite.yml", ".travis.yml", -1)
newContent := strings.Replace(string(fileContent), projFrom, projTo, -1)
err = ioutil.WriteFile(path.Join(codeProjectPath, destFile), []byte(newContent), os.ModePerm)
if err != nil {
log.Fatalf("Error: %s", err)
os.Exit(1)
}
}
err = gitPush()
if err != nil {
log.Fatalf("git push error: %s", err)
os.Exit(1)
}
fmt.Println("Initialization finished")
return nil
}
func gitPush() error {
cmdPush := fmt.Sprintf("git add . && git commit -m \"sync %s\" && git push", codeVersion)
cmd := exec.Command("sh", "-c", cmdPush)
output, err := cmd.Output()
if err != nil {
return err
}
fmt.Println(string(output))
return nil
}
func replaceImports(projectPath string, pkgFrom string, pkgTo string) error {
regexImport, err := regexp.Compile(`(?s)(import(.*?)\)|import.*$)`)
if err != nil {
return err
}
regexImportedPackage, err := regexp.Compile(`"(.*?)"`)
if err != nil {
return err
}
found := []string{}
err = filepath.Walk(projectPath, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == ".go" {
bts, err := ioutil.ReadFile(path)
if err != nil {
return err
}
content := string(bts)
matches := regexImport.FindAllString(content, -1)
isExists := false
isReplaceable:
for _, each := range matches {
for _, eachLine := range strings.Split(each, "\n") {
matchesInline := regexImportedPackage.FindAllString(eachLine, -1)
if err != nil {
return err
}
for _, eachSubline := range matchesInline {
if strings.Contains(eachSubline, pkgFrom) {
isExists = true
break isReplaceable
}
}
}
}
if isExists {
content = strings.Replace(content, `"`+pkgFrom+`"`, `"`+pkgTo+`"`, -1)
content = strings.Replace(content, `"`+pkgFrom+`/`, `"`+pkgTo+`/`, -1)
found = append(found, path)
}
err = ioutil.WriteFile(path, []byte(content), info.Mode())
if err != nil {
return err
}
}
return nil
})
if err != nil {
fmt.Println("ERROR", err.Error())
}
if len(found) == 0 {
fmt.Println("Nothing replaced")
} else {
fmt.Printf("Go imports total %d file replaced\n", len(found))
}
return nil
}
func copyDir(src string, dst string) error {
si, err := os.Stat(src)
if err != nil {
return err
}
if !si.IsDir() {
return fmt.Errorf("source is not a directory")
}
err = os.MkdirAll(dst, si.Mode())
if err != nil {
return err
}
entries, err := ioutil.ReadDir(src)
if err != nil {
return err
}
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
err = copyDir(srcPath, dstPath)
if err != nil {
return err
}
} else {
// Skip symlinks.
if entry.Mode()&os.ModeSymlink != 0 {
continue
}
err = copyFile(srcPath, dstPath)
if err != nil {
return err
}
}
}
return nil
}
func copyFile(src, dst string) (err error) {
in, err := os.Open(src)
if err != nil {
return
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return
}
defer func() {
if e := out.Close(); e != nil {
err = e
}
}()
_, err = io.Copy(out, in)
if err != nil {
return
}
err = out.Sync()
if err != nil {
return
}
si, err := os.Stat(src)
if err != nil {
return
}
err = os.Chmod(dst, si.Mode())
if err != nil {
return
}
return
}

View File

@@ -1,38 +0,0 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
"go.uber.org/zap"
"log"
"os"
"strings"
)
var rootCmd = &cobra.Command{
Use: "podcli",
Short: "podinfo command line",
Long: `
podinfo command line utilities`,
}
var (
logger *zap.Logger
)
func main() {
var err error
logger, err = zap.NewDevelopment()
if err != nil {
log.Fatalf("can't initialize zap logger: %v", err)
}
defer logger.Sync()
rootCmd.SetArgs(os.Args[1:])
if err := rootCmd.Execute(); err != nil {
e := err.Error()
fmt.Println(strings.ToUpper(e[:1]) + e[1:])
os.Exit(1)
}
}

View File

@@ -1,20 +0,0 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
"github.com/stefanprodan/k8s-podinfo/pkg/version"
)
func init() {
rootCmd.AddCommand(versionCmd)
}
var versionCmd = &cobra.Command{
Use: `version`,
Short: "Prints podcli version",
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println(version.VERSION)
return nil
},
}

View File

@@ -1,143 +0,0 @@
package main
import (
"encoding/hex"
"fmt"
"net/http"
"net/url"
"os"
"regexp"
"strings"
"github.com/chzyer/readline"
"github.com/fatih/color"
"github.com/gorilla/websocket"
"github.com/spf13/cobra"
"go.uber.org/zap"
)
var origin string
func init() {
wsCmd.Flags().StringVarP(&origin, "origin", "o", "", "websocket origin")
rootCmd.AddCommand(wsCmd)
}
var wsCmd = &cobra.Command{
Use: `ws [address]`,
Short: "Websocket client",
Example: ` ws localhost:9898/ws/echo`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("address is required")
}
address := args[0]
if !strings.HasPrefix(address, "ws://") && !strings.HasPrefix(address, "wss://") {
address = fmt.Sprintf("ws://%s", address)
}
dest, err := url.Parse(address)
if err != nil {
return err
}
if origin != "" {
} else {
originURL := *dest
if dest.Scheme == "wss" {
originURL.Scheme = "https"
} else {
originURL.Scheme = "http"
}
origin = originURL.String()
}
err = connect(dest.String(), origin, &readline.Config{
Prompt: "> ",
})
if err != nil {
logger.Info("websocket closed", zap.Error(err))
}
return nil
},
}
type session struct {
ws *websocket.Conn
rl *readline.Instance
errChan chan error
}
func connect(url, origin string, rlConf *readline.Config) error {
headers := make(http.Header)
headers.Add("Origin", origin)
ws, _, err := websocket.DefaultDialer.Dial(url, headers)
if err != nil {
return err
}
rl, err := readline.NewEx(rlConf)
if err != nil {
return err
}
defer rl.Close()
sess := &session{
ws: ws,
rl: rl,
errChan: make(chan error),
}
go sess.readConsole()
go sess.readWebsocket()
return <-sess.errChan
}
func (s *session) readConsole() {
for {
line, err := s.rl.Readline()
if err != nil {
s.errChan <- err
return
}
err = s.ws.WriteMessage(websocket.TextMessage, []byte(line))
if err != nil {
s.errChan <- err
return
}
}
}
func bytesToFormattedHex(bytes []byte) string {
text := hex.EncodeToString(bytes)
return regexp.MustCompile("(..)").ReplaceAllString(text, "$1 ")
}
func (s *session) readWebsocket() {
rxSprintf := color.New(color.FgGreen).SprintfFunc()
for {
msgType, buf, err := s.ws.ReadMessage()
if err != nil {
fmt.Fprint(s.rl.Stdout(), rxSprintf("< %s\n", err.Error()))
os.Exit(1)
return
}
var text string
switch msgType {
case websocket.TextMessage:
text = string(buf)
case websocket.BinaryMessage:
text = bytesToFormattedHex(buf)
default:
s.errChan <- fmt.Errorf("unknown websocket frame type: %d", msgType)
return
}
fmt.Fprint(s.rl.Stdout(), rxSprintf("< %s\n", text))
}
}

Some files were not shown because too many files have changed in this diff Show More