mirror of
https://github.com/stefanprodan/podinfo.git
synced 2026-02-14 18:29:52 +00:00
Init Helm repo
This commit is contained in:
@@ -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
|
||||
@@ -1,9 +0,0 @@
|
||||
docs
|
||||
deploy
|
||||
charts
|
||||
cloudbuild.yaml
|
||||
skaffold.yaml
|
||||
.gitignore
|
||||
.travis.yml
|
||||
LICENSE
|
||||
README.md
|
||||
104
.drone.yml
104
.drone.yml
@@ -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
|
||||
17
.github/actions/docker/Dockerfile
vendored
17
.github/actions/docker/Dockerfile
vendored
@@ -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"]
|
||||
25
.github/actions/docker/entrypoint.sh
vendored
25
.github/actions/docker/entrypoint.sh
vendored
@@ -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
|
||||
|
||||
20
.github/actions/golang/Dockerfile
vendored
20
.github/actions/golang/Dockerfile
vendored
@@ -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"]
|
||||
|
||||
26
.github/actions/golang/entrypoint.sh
vendored
26
.github/actions/golang/entrypoint.sh
vendored
@@ -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
35
.github/main.workflow
vendored
@@ -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
21
.gitignore
vendored
@@ -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/
|
||||
@@ -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*
|
||||
52
.travis.yml
52
.travis.yml
@@ -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
|
||||
16
Dockerfile
16
Dockerfile
@@ -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"]
|
||||
@@ -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"]
|
||||
@@ -1,6 +0,0 @@
|
||||
FROM alpine:3.7
|
||||
|
||||
COPY ./ui ./ui
|
||||
ADD podinfo /podinfo
|
||||
|
||||
CMD ["./podinfo"]
|
||||
@@ -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"]
|
||||
@@ -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
449
Gopkg.lock
generated
@@ -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
|
||||
39
Gopkg.toml
39
Gopkg.toml
@@ -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
21
LICENSE
@@ -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
114
Makefile
@@ -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
|
||||
17
Makefile.gh
17
Makefile.gh
@@ -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 .
|
||||
52
README.md
52
README.md
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -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 -}}
|
||||
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: A Helm chart for Kubernetes
|
||||
name: grafana
|
||||
version: 0.1.0
|
||||
@@ -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
@@ -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
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -1,6 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "grafana.fullname" . }}-dashboards
|
||||
data:
|
||||
{{ (.Files.Glob "dashboards/*").AsConfig | indent 2 }}
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 }}
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: Hey load test Helm chart for Kubernetes
|
||||
name: loadtest
|
||||
version: 0.1.0
|
||||
@@ -1 +0,0 @@
|
||||
{{ template "loadtest.fullname" . }} has been deployed successfully!
|
||||
@@ -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 -}}
|
||||
@@ -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 -}}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: A Ngrok Helm chart for Kubernetes
|
||||
name: ngrok
|
||||
version: 0.2.0
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -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 }}
|
||||
@@ -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" . }}
|
||||
@@ -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 }}
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
{{ template "podinfo-istio.fullname" . }} has been deployed successfully!
|
||||
@@ -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 -}}
|
||||
|
||||
@@ -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: {}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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" . }}
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 -}}
|
||||
@@ -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: {}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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: {}
|
||||
|
||||
@@ -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']
|
||||
@@ -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])
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
143
cmd/podcli/ws.go
143
cmd/podcli/ws.go
@@ -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
Reference in New Issue
Block a user