Compare commits

...

25 Commits
3.2.2 ... 3.3.0

Author SHA1 Message Date
Stefan Prodan
3e6d61e77e Merge pull request #65 from stefanprodan/release-3.3.0
Release v3.3.0
2020-05-16 10:07:12 +03:00
stefanprodan
c7c7d699c9 Release v3.3.0 2020-05-16 10:00:51 +03:00
Stefan Prodan
067751c67d Merge pull request #64 from stefanprodan/cache-api
Add cache API
2020-05-16 09:59:19 +03:00
stefanprodan
73b658d711 Add cache API
- implement cache with Redis
- add cache-server to args and config
- add Redis deployment to webapp overlays
2020-05-16 09:53:17 +03:00
Stefan Prodan
e5516b38cb Merge pull request #63 from stefanprodan/release-3.2.4
Release v3.2.4
2020-05-15 13:17:35 +03:00
stefanprodan
39130004d5 Release v3.2.4 2020-05-15 13:02:08 +03:00
Stefan Prodan
d4b615e3a2 Merge pull request #62 from stefanprodan/base-image
Push base image to Docker Hub
2020-05-15 13:00:18 +03:00
stefanprodan
98e133a7be Push base image to Docker Hub 2020-05-15 12:49:22 +03:00
Stefan Prodan
7674b76dab Merge pull request #60 from seaneagan/helm_test_fault
Support simulating helm test failure and timeout
2020-05-14 23:57:16 +03:00
Stefan Prodan
8fa39d90be Merge pull request #61 from seaneagan/helm3_tests_should_be_jobs
Helm 3 tests should be Jobs
2020-05-14 22:35:33 +03:00
Sean Eagan
638bdc8e83 Helm 3 tests should be Jobs
Without this "helm.sh/hook-delete-policy": before-hook-creation" does not work.
2020-05-14 09:12:53 -05:00
Sean Eagan
b565a67dec Support simulating helm test failure and timeout
This is to support testing of https://github.com/fluxcd/helm-operator/issues/369.
2020-05-13 14:22:24 -05:00
stefanprodan
65d077291b Add reconciler RBAC to webapp manifests 2020-05-01 20:29:55 +03:00
Stefan Prodan
e9d11c247e Merge pull request #58 from ytsarev/quote-message
Quote ui message in deployment template
2020-04-30 23:23:27 +03:00
Yury Tsarev
126ac55801 Quote ui message in deployment template
* To handle rare situation of digit-only message like 270 and
avoid associated failure during helm install
```
ReadString: expects " or n, but found 2, error found in #10 byte of ...|,"value":270},
{"name|..., bigger context ...|se"],"env":[{"name":"PODINFO_UI_MESSAGE","value":270},
```
2020-04-30 21:47:49 +02:00
Stefan Prodan
306aac3e65 Merge pull request #57 from stefanprodan/release-3.2.3
Release v3.2.3
2020-04-29 00:23:16 +03:00
stefanprodan
55318b0c20 Release v3.2.3 2020-04-28 19:20:23 +03:00
Stefan Prodan
1865faf7ce Merge pull request #56 from stefanprodan/webapp-demo
Add webapp demo
2020-04-28 19:18:28 +03:00
stefanprodan
9edd7abbe8 Include webapp demo in release 2020-04-28 19:13:01 +03:00
stefanprodan
1c4acc0b33 Add webapp demo kustomizations 2020-04-28 19:12:44 +03:00
stefanprodan
6274f16b9b Add webapp demo manifests 2020-04-28 19:12:25 +03:00
stefanprodan
93e338a964 Add app common label to kustomization 2020-04-15 12:22:49 +03:00
Stefan Prodan
73b03b77fc Merge pull request #54 from hiddeco/chart/readme-fix
chart: align README with actual values file
2020-04-04 13:36:58 +03:00
Hidde Beydals
0135757fbd chart: remove redundant codeblock opening 2020-04-04 12:32:54 +02:00
Hidde Beydals
ea1fe87d49 chart: align README with actual values file 2020-04-04 12:31:01 +02:00
56 changed files with 1189 additions and 153 deletions

View File

@@ -33,6 +33,7 @@ jobs:
echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin; echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin;
echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io; echo $QUAY_PASS | docker login -u $QUAY_USER --password-stdin quay.io;
make push-container; make push-container;
make push-base;
fi fi
push-binary: push-binary:

10
Dockerfile.base Normal file
View File

@@ -0,0 +1,10 @@
FROM golang:1.14
WORKDIR /workspace
# copy modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache modules
RUN go mod download

View File

@@ -33,6 +33,12 @@ build-charts:
build-container: build-container:
docker build -t $(DOCKER_IMAGE_NAME):$(VERSION) . docker build -t $(DOCKER_IMAGE_NAME):$(VERSION) .
build-base:
docker build -f Dockerfile.base -t $(DOCKER_REPOSITORY)/podinfo-base:latest .
push-base: build-base
docker push $(DOCKER_REPOSITORY)/podinfo-base:latest
test-container: test-container:
@docker rm -f podinfo || true @docker rm -f podinfo || true
@docker run -dp 9898:9898 --name=podinfo $(DOCKER_IMAGE_NAME):$(VERSION) @docker run -dp 9898:9898 --name=podinfo $(DOCKER_IMAGE_NAME):$(VERSION)
@@ -57,6 +63,10 @@ version-set:
sed -i '' "s/appVersion: $$current/appVersion: $$next/g" charts/podinfo/Chart.yaml && \ sed -i '' "s/appVersion: $$current/appVersion: $$next/g" charts/podinfo/Chart.yaml && \
sed -i '' "s/version: $$current/version: $$next/g" charts/podinfo/Chart.yaml && \ sed -i '' "s/version: $$current/version: $$next/g" charts/podinfo/Chart.yaml && \
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" kustomize/deployment.yaml && \ sed -i '' "s/podinfo:$$current/podinfo:$$next/g" kustomize/deployment.yaml && \
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/webapp/frontend/deployment.yaml && \
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/webapp/backend/deployment.yaml && \
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/frontend/deployment.yaml && \
sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/backend/deployment.yaml && \
echo "Version $$next set in code, deployment, chart and kustomize" echo "Version $$next set in code, deployment, chart and kustomize"
release: release:

View File

@@ -41,6 +41,8 @@ Web API:
* `POST /token` issues a JWT token valid for one minute `JWT=$(curl -sd 'anon' podinfo:9898/token | jq -r .token)` * `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 /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 * `GET /configs` returns a JSON with configmaps and/or secrets mounted in the `config` volume
* `POST /cache` saves the posted content to Redis and returns the SHA1 hash of the content
* `GET /store/{hash}` returns the content from Redis if the key exists
* `POST /store` writes the posted content to disk at /data/hash and returns the SHA1 hash of the content * `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 /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 /ws/echo` echos content via websockets `podcli ws ws://localhost:9898/ws/echo`

View File

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

View File

@@ -29,48 +29,56 @@ The command removes all the Kubernetes components associated with the chart and
The following tables lists the configurable parameters of the podinfo chart and their default values. The following tables lists the configurable parameters of the podinfo chart and their default values.
Parameter | Description | Default Parameter | Default | Description
--- | --- | --- --- | --- | ---
`affinity` | node/pod affinities | None `replicaCount` | `1` | Desired number of pods
`backend` | echo backend URL | None `logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error`, `flat` or `panic`
`backends` | echo backend URL array | None `backend` | `None` | Echo backend URL
`faults.delay` | random HTTP response delays between 0 and 5 seconds | `false` `backends` | `[]` | Array of echo backend URLs
`faults.error` | 1/3 chances of a random HTTP response error | `false` `cache` | `None` | Redis address in the format `<host>:<port>`
`faults.unhealthy` | when set, the healthy state is never reached | `false` `ui.color` | `#34577c` | UI color
`faults.unready` | when set, the ready state is never reached | `false` `ui.message` | `None` | UI greetings message
`hpa.enabled` | enables HPA | `false` `ui.logo` | `None` | UI logo
`hpa.cpu` | target CPU usage per pod | None `faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds
`hpa.memory` | target memory usage per pod | None `faults.error` | `false` | 1/3 chances of a random HTTP response error
`hpa.requests` | target requests per second per pod | None `faults.unhealthy` | `false` | When set, the healthy state is never reached
`hpa.maxReplicas` | maximum pod replicas | `10` `faults.unready` | `false` | When set, the ready state is never reached
`image.pullPolicy` | image pull policy | `IfNotPresent` `faults.testFail` | `false` | When set, a helm test is included which always fails
`image.repository` | image repository | `stefanprodan/podinfo` `faults.testTimeout` | `false` | When set, a helm test is included which always times out
`image.tag` | image tag | `<VERSION>` `h2c.enabled` | `false` | Allow upgrading to h2c
`ingress.enabled` | enables ingress | `false` `image.repository` | `stefanprodan/podinfo` | Image repository
`ingress.annotations` | ingress annotations | None `image.tag` | `<VERSION>` | Image tag
`ingress.hosts` | ingress accepted hostnames | None `image.pullPolicy` | `IfNotPresent` | Image pull policy
`ingress.tls` | ingress TLS configuration | None `service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app)
`message` | UI greetings message | None `service.type` | `ClusterIP` | Type of the Kubernetes Service
`nodeSelector` | node labels for pod assignment | `{}` `service.metricsPort` | `9797` | Prometheus metrics endpoint port
`replicaCount` | desired number of pods | `2` `service.httpPort` | `9898` | Container HTTP port
`resources.requests/cpu` | pod CPU request | `1m` `service.externalPort` | `9898` | ClusterIP HTTP port
`resources.requests/memory` | pod memory request | `16Mi` `service.grpcPort` | `9999` | ClusterIP gPRC port
`resources.limits/cpu` | pod CPU limit | None `service.grpcService` | `podinfo` | gPRC service name
`resources.limits/memory` | pod memory limit | None `service.nodePort` | `31198` | NodePort for the HTTP endpoint
`service.enabled` | create Kubernetes service (should be disabled when using Flagger) | `true` `hpa.enabled` | `false` | Enables the Kubernetes HPA
`service.metricsPort` | Prometheus metrics endpoint port | `9797` `hpa.maxReplicas` | `10` | Maximum amount of pods
`service.externalPort` | ClusterIP HTTP port | `9898` `hpa.cpu` | `None` | Target CPU usage per pod
`service.httpPort` | container HTTP port | `9898` `hpa.memory` | `None` | Target memory usage per pod
`service.nodePort` | NodePort for the HTTP endpoint | `31198` `hpa.requests` | `None` | Target HTTP requests per second per pod
`service.grpcPort` | ClusterIP gPRC port | `9999` `serviceAccount.enabled` | `false` | Whether a service account should be created
`service.grpcService` | gPRC service name | `podinfo` `serviceAccount.name` | `None` | The name of the service account to use, if not set and create is true, a name is generated using the fullname template
`service.type` | type of service | `ClusterIP` `linkerd.profile.enabled` | `false` | Create Linkerd service profile
`tolerations` | list of node taints to tolerate | `[]` `serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created
`serviceAccount.enabled` | specifies whether a service account should be created | `false` `serviceMonitor.interval` | `15s` | Prometheus scraping interval
`serviceAccount.name` | the name of the service account to use, if not set and create is true, a name is generated using the fullname template | None `ingress.enabled` | `false` | Enables Ingress
`linkerd.profile.enabled` | create Linkerd service profile | `false` `ingress.annotations` | `{}` | Ingress annotations
`serviceMonitor.enabled` | specifies whether a Prometheus Operator service monitor should be created | `false` `ingress.path` | `/*` | Ingress path
`serviceMonitor.interval` | Prometheus scraping interval | `15s` `ingress.hosts` | `[]` | Ingress accepted hosts
`ingress.tls` | `[]` | Ingress TLS configuration
`resources.requests.cpu` | `1m` | Pod CPU request
`resources.requests.memory` | `16Mi` | Pod memory request
`resources.limits.cpu` | `None` | Pod CPU limit
`resources.limits.memory` | `None` | Pod memory limit
`nodeSelector` | `{}` | Node labels for pod assignment
`tolerations` | `[]` | List of node taints to tolerate
`affinity` | `None` | Node/pod affinities
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
@@ -86,5 +94,3 @@ $ helm install stable/podinfo --name my-release -f values.yaml
``` ```
> **Tip**: You can use the default [values.yaml](values.yaml) > **Tip**: You can use the default [values.yaml](values.yaml)
```

View File

@@ -49,6 +49,9 @@ spec:
{{- range .Values.backends }} {{- range .Values.backends }}
- --backend-url={{ . }} - --backend-url={{ . }}
{{- end }} {{- end }}
{{- if .Values.cache }}
- --cache-server={{ .Values.cache }}
{{- end }}
- --level={{ .Values.logLevel }} - --level={{ .Values.logLevel }}
- --random-delay={{ .Values.faults.delay }} - --random-delay={{ .Values.faults.delay }}
- --random-error={{ .Values.faults.error }} - --random-error={{ .Values.faults.error }}
@@ -64,7 +67,7 @@ spec:
env: env:
{{- if .Values.ui.message }} {{- if .Values.ui.message }}
- name: PODINFO_UI_MESSAGE - name: PODINFO_UI_MESSAGE
value: {{ .Values.ui.message }} value: {{ quote .Values.ui.message }}
{{- end }} {{- end }}
{{- if .Values.ui.logo }} {{- if .Values.ui.logo }}
- name: PODINFO_UI_LOGO - name: PODINFO_UI_LOGO

View File

@@ -0,0 +1,26 @@
{{- if .Values.faults.test }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "podinfo.fullname" . }}-fault-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
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
sidecar.istio.io/inject: "false"
linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec:
template:
spec:
containers:
- name: fault
image: alpine:3.11
command: ['/bin/sh']
args: ['-c', 'exit 1']
restartPolicy: Never
{{- end }}

View File

@@ -1,5 +1,5 @@
apiVersion: v1 apiVersion: batch/v1
kind: Pod kind: Job
metadata: metadata:
name: {{ template "podinfo.fullname" . }}-grpc-test-{{ randAlphaNum 5 | lower }} name: {{ template "podinfo.fullname" . }}-grpc-test-{{ randAlphaNum 5 | lower }}
labels: labels:
@@ -14,9 +14,11 @@ metadata:
linkerd.io/inject: disabled linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec: spec:
containers: template:
- name: grpc-health-probe spec:
image: stefanprodan/grpc_health_probe:v0.3.0 containers:
command: ['grpc_health_probe'] - name: grpc-health-probe
args: ['-addr={{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.grpcPort }}'] image: stefanprodan/grpc_health_probe:v0.3.0
restartPolicy: Never command: ['grpc_health_probe']
args: ['-addr={{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.grpcPort }}']
restartPolicy: Never

View File

@@ -1,5 +1,5 @@
apiVersion: v1 apiVersion: batch/v1
kind: Pod kind: Job
metadata: metadata:
name: {{ template "podinfo.fullname" . }}-jwt-test-{{ randAlphaNum 5 | lower }} name: {{ template "podinfo.fullname" . }}-jwt-test-{{ randAlphaNum 5 | lower }}
labels: labels:
@@ -14,16 +14,18 @@ metadata:
linkerd.io/inject: disabled linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec: spec:
containers: template:
- name: tools spec:
image: giantswarm/tiny-tools containers:
command: - name: tools
- sh image: giantswarm/tiny-tools
- -c command:
- | - sh
TOKEN=$(curl -sd 'test' ${PODINFO_SVC}/token | jq -r .token) && - -c
curl -sH "Authorization: Bearer ${TOKEN}" ${PODINFO_SVC}/token/validate | grep test - |
env: TOKEN=$(curl -sd 'test' ${PODINFO_SVC}/token | jq -r .token) &&
- name: PODINFO_SVC curl -sH "Authorization: Bearer ${TOKEN}" ${PODINFO_SVC}/token/validate | grep test
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}" env:
restartPolicy: Never - name: PODINFO_SVC
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}"
restartPolicy: Never

View File

@@ -1,5 +1,5 @@
apiVersion: v1 apiVersion: batch/v1
kind: Pod kind: Job
metadata: metadata:
name: {{ template "podinfo.fullname" . }}-service-test-{{ randAlphaNum 5 | lower }} name: {{ template "podinfo.fullname" . }}-service-test-{{ randAlphaNum 5 | lower }}
labels: labels:
@@ -14,15 +14,17 @@ metadata:
linkerd.io/inject: disabled linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec: spec:
containers: template:
- name: curl spec:
image: curlimages/curl:7.69.0 containers:
command: - name: curl
- sh image: curlimages/curl:7.69.0
- -c command:
- | - sh
curl -s ${PODINFO_SVC}/api/info | grep version - -c
env: - |
- name: PODINFO_SVC curl -s ${PODINFO_SVC}/api/info | grep version
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}" env:
restartPolicy: Never - name: PODINFO_SVC
value: "{{ template "podinfo.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.externalPort }}"
restartPolicy: Never

View File

@@ -0,0 +1,26 @@
{{- if .Values.faults.test }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "podinfo.fullname" . }}-fault-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
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
sidecar.istio.io/inject: "false"
linkerd.io/inject: disabled
appmesh.k8s.aws/sidecarInjectorWebhook: disabled
spec:
template:
spec:
containers:
- name: fault
image: alpine:3.11
command: ['/bin/sh']
args: ['-c', 'while sleep 3600; do :; done']
restartPolicy: Never
{{- end }}

View File

@@ -4,6 +4,7 @@ replicaCount: 1
logLevel: info logLevel: info
backend: #http://backend-podinfo:9898/echo backend: #http://backend-podinfo:9898/echo
backends: [] backends: []
cache: ""
ui: ui:
color: "#34577c" color: "#34577c"
@@ -15,13 +16,15 @@ faults:
error: false error: false
unhealthy: false unhealthy: false
unready: false unready: false
testFail: false
testTimeout: false
h2c: h2c:
enabled: false enabled: false
image: image:
repository: stefanprodan/podinfo repository: stefanprodan/podinfo
tag: 3.2.2 tag: 3.3.0
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
service: service:

View File

@@ -46,6 +46,7 @@ func main() {
fs.Bool("unready", false, "when set, ready state is never reached") fs.Bool("unready", false, "when set, ready state is never reached")
fs.Int("stress-cpu", 0, "number of CPU cores with 100 load") fs.Int("stress-cpu", 0, "number of CPU cores with 100 load")
fs.Int("stress-memory", 0, "MB of data to load into memory") fs.Int("stress-memory", 0, "MB of data to load into memory")
fs.String("cache-server", "", "Redis address in the format <host>:<port>")
versionFlag := fs.BoolP("version", "v", false, "get version number") versionFlag := fs.BoolP("version", "v", false, "get version number")

32
deploy/README.md Normal file
View File

@@ -0,0 +1,32 @@
# Deploy demo webapp
Demo webapp manifests:
- [common](webapp/common)
- [frontend](webapp/frontend)
- [backend](webapp/backend)
Deploy the demo in `webapp` namespace:
```bash
kubectl apply -f ./webapp/common
kubectl apply -f ./webapp/backend
kubectl apply -f ./webapp/frontend
```
Deploy the demo in the `dev` namespace:
```bash
kustomize build ./overlays/dev | kubectl apply -f-
```
Deploy the demo in the `staging` namespace:
```bash
kustomize build ./overlays/staging | kubectl apply -f-
```
Deploy the demo in the `production` namespace:
```bash
kustomize build ./overlays/production | kubectl apply -f-
```

View File

@@ -0,0 +1,73 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: backend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: backend
spec:
containers:
- name: backend
image: stefanprodan/podinfo:3.3.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 9898
protocol: TCP
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
command:
- ./podinfo
- --port=9898
- --port-metrics=9797
- --grpc-port=9999
- --grpc-service-name=backend
- --level=info
- --cache-server=cache:6379
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 2000m
memory: 512Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,18 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: backend
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- service.yaml
- deployment.yaml
- hpa.yaml

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
port: 9898
protocol: TCP
targetPort: http
- port: 9999
targetPort: grpc
protocol: TCP
name: grpc

57
deploy/bases/cache/deployment.yaml vendored Normal file
View File

@@ -0,0 +1,57 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache
spec:
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
spec:
containers:
- name: redis
image: redis:6.0.1
imagePullPolicy: IfNotPresent
command:
- redis-server
- "/redis-master/redis.conf"
ports:
- name: redis
containerPort: 6379
protocol: TCP
livenessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 1000m
memory: 128Mi
requests:
cpu: 100m
memory: 32Mi
volumeMounts:
- mountPath: /var/lib/redis
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-config
items:
- key: redis.conf
path: redis.conf

9
deploy/bases/cache/kustomization.yaml vendored Normal file
View File

@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- service.yaml
- deployment.yaml
configMapGenerator:
- name: redis-config
files:
- redis.conf

4
deploy/bases/cache/redis.conf vendored Normal file
View File

@@ -0,0 +1,4 @@
maxmemory 64mb
maxmemory-policy allkeys-lru
save ""
appendonly no

13
deploy/bases/cache/service.yaml vendored Normal file
View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: cache
spec:
type: ClusterIP
selector:
app: cache
ports:
- name: redis
port: 6379
protocol: TCP
targetPort: redis

View File

@@ -0,0 +1,72 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: frontend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: frontend
spec:
containers:
- name: frontend
image: stefanprodan/podinfo:3.3.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 9898
protocol: TCP
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
command:
- ./podinfo
- --port=9898
- --port-metrics=9797
- --level=info
- --backend-url=http://backend:9898/echo
- --cache-server=cache:6379
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 1000m
memory: 128Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,18 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
minReplicas: 1
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- service.yaml
- deployment.yaml
- hpa.yaml

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
protocol: TCP
targetPort: http

View File

@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
resources:
- ../../bases/backend
- ../../bases/frontend
- ../../bases/cache
- namespace.yaml
transformers:
- labels.yaml

View File

@@ -0,0 +1,10 @@
apiVersion: builtin
kind: LabelTransformer
metadata:
name: labels
labels:
env: dev
instance: webapp
fieldSpecs:
- path: metadata/labels
create: true

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: dev

View File

@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production
resources:
- ../../bases/backend
- ../../bases/frontend
- ../../bases/cache
- namespace.yaml
transformers:
- labels.yaml

View File

@@ -0,0 +1,10 @@
apiVersion: builtin
kind: LabelTransformer
metadata:
name: labels
labels:
env: production
instance: webapp
fieldSpecs:
- path: metadata/labels
create: true

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: production

View File

@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: staging
resources:
- ../../bases/backend
- ../../bases/frontend
- ../../bases/cache
- namespace.yaml
transformers:
- labels.yaml

View File

@@ -0,0 +1,10 @@
apiVersion: builtin
kind: LabelTransformer
metadata:
name: labels
labels:
env: staging
instance: webapp
fieldSpecs:
- path: metadata/labels
create: true

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: staging

View File

@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: webapp
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: backend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: backend
spec:
serviceAccountName: webapp
containers:
- name: backend
image: stefanprodan/podinfo:3.3.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 9898
protocol: TCP
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
command:
- ./podinfo
- --port=9898
- --port-metrics=9797
- --grpc-port=9999
- --grpc-service-name=backend
- --level=info
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 2000m
memory: 512Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,19 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: backend
namespace: webapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: webapp
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
port: 9898
protocol: TCP
targetPort: http
- port: 9999
targetPort: grpc
protocol: TCP
name: grpc

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: webapp

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: reconciler
namespace: webapp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: reconciler
namespace: webapp
rules:
- apiGroups: ['*']
resources: ['*']
verbs: ['*']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: reconciler
namespace: webapp
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: reconciler
subjects:
- kind: ServiceAccount
name: reconciler
namespace: webapp

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: webapp
namespace: webapp

View File

@@ -0,0 +1,73 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: webapp
spec:
minReadySeconds: 3
revisionHistoryLimit: 5
progressDeadlineSeconds: 60
strategy:
rollingUpdate:
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: frontend
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9797"
labels:
app: frontend
spec:
serviceAccountName: webapp
containers:
- name: frontend
image: stefanprodan/podinfo:3.3.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 9898
protocol: TCP
- name: http-metrics
containerPort: 9797
protocol: TCP
- name: grpc
containerPort: 9999
protocol: TCP
command:
- ./podinfo
- --port=9898
- --port-metrics=9797
- --level=info
- --backend-url=http://backend:9898/echo
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
limits:
cpu: 1000m
memory: 128Mi
requests:
cpu: 100m
memory: 32Mi

View File

@@ -0,0 +1,19 @@
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend
namespace: webapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 1
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 99

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: webapp
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
protocol: TCP
targetPort: http

7
go.mod
View File

@@ -10,17 +10,18 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fatih/color v1.7.0 github.com/fatih/color v1.7.0
github.com/fsnotify/fsnotify v1.4.7 github.com/fsnotify/fsnotify v1.4.7
github.com/go-chi/chi v4.0.3+incompatible // indirect github.com/go-chi/chi v4.1.1+incompatible // indirect
github.com/gomodule/redigo v1.8.1
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/go-getter v1.4.1 github.com/hashicorp/go-getter v1.4.1
github.com/prometheus/client_golang v1.5.1 github.com/prometheus/client_golang v1.5.1
github.com/spf13/cobra v0.0.6 github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.6.2 github.com/spf13/viper v1.6.2
github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e github.com/swaggo/http-swagger v0.0.0-20190614090009-c2865af9083e
github.com/swaggo/swag v1.6.5 github.com/swaggo/swag v1.6.5
go.uber.org/zap v1.10.0 go.uber.org/zap v1.15.0
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
google.golang.org/grpc v1.23.0 google.golang.org/grpc v1.23.0
) )

38
go.sum
View File

@@ -52,6 +52,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -71,8 +72,8 @@ github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NB
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= github.com/go-chi/chi v4.1.1+incompatible h1:MmTgB0R8Bt/jccxp+t6S/1VGIKdJw5J74CK/c9tTfA4=
github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.1.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -111,6 +112,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -123,6 +126,7 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@@ -233,8 +237,11 @@ github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLk
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -248,8 +255,8 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
@@ -268,6 +275,8 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM= github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
@@ -287,6 +296,7 @@ github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@@ -296,12 +306,21 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -312,7 +331,10 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -385,8 +407,13 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -421,6 +448,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
@@ -437,4 +465,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@@ -2,8 +2,6 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: podinfo name: podinfo
labels:
app: podinfo
spec: spec:
minReadySeconds: 3 minReadySeconds: 3
revisionHistoryLimit: 5 revisionHistoryLimit: 5
@@ -25,7 +23,7 @@ spec:
spec: spec:
containers: containers:
- name: podinfod - name: podinfod
image: stefanprodan/podinfo:3.2.2 image: stefanprodan/podinfo:3.3.0
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- name: http - name: http

View File

@@ -2,3 +2,6 @@ resources:
- hpa.yaml - hpa.yaml
- deployment.yaml - deployment.yaml
- service.yaml - service.yaml
commonLabels:
app: podinfo

View File

@@ -2,8 +2,6 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: podinfo name: podinfo
labels:
app: podinfo
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:

93
pkg/api/cache.go Normal file
View File

@@ -0,0 +1,93 @@
package api
import (
"github.com/gomodule/redigo/redis"
"github.com/gorilla/mux"
"go.uber.org/zap"
"io/ioutil"
"net/http"
"time"
)
// Cache godoc
// @Summary Save payload in cache
// @Description writes the posted content in cache and returns the SHA1 hash of the content
// @Tags HTTP API
// @Accept json
// @Produce json
// @Router /cache [post]
// @Success 200 {object} api.MapResponse
func (s *Server) cacheWriteHandler(w http.ResponseWriter, r *http.Request) {
if s.pool == nil {
s.ErrorResponse(w, r, "cache server is offline", http.StatusBadRequest)
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
s.ErrorResponse(w, r, "reading the request body failed", http.StatusBadRequest)
return
}
hash := hash(string(body))
conn := s.pool.Get()
defer conn.Close()
_, err = conn.Do("SET", hash, string(body))
if err != nil {
s.logger.Warn("cache set failed", zap.Error(err))
s.ErrorResponse(w, r, "cache set failed", http.StatusInternalServerError)
return
}
s.JSONResponseCode(w, r, map[string]string{"hash": hash}, http.StatusAccepted)
}
// Cache godoc
// @Summary Get payload from cache
// @Description returns the content from cache if key exists
// @Tags HTTP API
// @Accept json
// @Produce json
// @Router /cache/{hash} [get]
// @Success 200 {string} api.MapResponse
func (s *Server) cacheReadHandler(w http.ResponseWriter, r *http.Request) {
if s.pool == nil {
s.ErrorResponse(w, r, "cache server is offline", http.StatusBadRequest)
return
}
hash := mux.Vars(r)["hash"]
conn := s.pool.Get()
defer conn.Close()
ok, err := redis.Bool(conn.Do("EXISTS", hash))
if err != nil || !ok {
s.ErrorResponse(w, r, "key not found in cache", http.StatusNotFound)
return
}
data, err := redis.String(conn.Do("GET", hash))
if err != nil {
s.logger.Warn("cache get failed", zap.Error(err))
s.ErrorResponse(w, r, "cache get failed", http.StatusInternalServerError)
return
}
s.JSONResponseCode(w, r, map[string]string{"data": data}, http.StatusAccepted)
}
func (s *Server) startCachePool() {
if s.config.CacheServer != "" {
s.pool = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", s.config.CacheServer)
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
}
}
}

View File

@@ -1,12 +1,13 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at // This file was generated by swaggo/swag at
// 2019-08-07 15:52:23.918713 +0300 EEST m=+0.023438272 // 2020-05-16 09:49:23.920068 +0300 EEST m=+0.052088436
package docs package docs
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"strings"
"github.com/alecthomas/template" "github.com/alecthomas/template"
"github.com/swaggo/swag" "github.com/swaggo/swag"
@@ -16,8 +17,8 @@ var doc = `{
"schemes": {{ marshal .Schemes }}, "schemes": {{ marshal .Schemes }},
"swagger": "2.0", "swagger": "2.0",
"info": { "info": {
"description": "Go microservice template for Kubernetes.", "description": "{{.Description}}",
"title": "Podinfo API", "title": "{{.Title}}",
"contact": { "contact": {
"name": "Source Code", "name": "Source Code",
"url": "https://github.com/stefanprodan/podinfo" "url": "https://github.com/stefanprodan/podinfo"
@@ -26,10 +27,10 @@ var doc = `{
"name": "MIT License", "name": "MIT License",
"url": "https://github.com/stefanprodan/podinfo/blob/master/LICENSE" "url": "https://github.com/stefanprodan/podinfo/blob/master/LICENSE"
}, },
"version": "2.0" "version": "{{.Version}}"
}, },
"host": "localhost:9898", "host": "{{.Host}}",
"basePath": "/", "basePath": "{{.BasePath}}",
"paths": { "paths": {
"/": { "/": {
"get": { "get": {
@@ -68,7 +69,6 @@ var doc = `{
"202": { "202": {
"description": "Accepted", "description": "Accepted",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -92,13 +92,58 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.RuntimeResponse" "$ref": "#/definitions/api.RuntimeResponse"
} }
} }
} }
} }
}, },
"/cache": {
"post": {
"description": "writes the posted content in cache and returns the SHA1 hash of the content",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"HTTP API"
],
"summary": "Save payload in cache",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.MapResponse"
}
}
}
}
},
"/cache/{hash}": {
"get": {
"description": "returns the content from cache if key exists",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"HTTP API"
],
"summary": "Get payload from cache",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
}
}
}
},
"/chunked/{seconds}": { "/chunked/{seconds}": {
"get": { "get": {
"description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period", "description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period",
@@ -116,7 +161,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -140,7 +184,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -164,7 +207,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.ArrayResponse" "$ref": "#/definitions/api.ArrayResponse"
} }
} }
@@ -188,7 +230,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.ArrayResponse" "$ref": "#/definitions/api.ArrayResponse"
} }
} }
@@ -333,7 +374,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -357,7 +397,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -404,7 +443,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.TokenResponse" "$ref": "#/definitions/api.TokenResponse"
} }
} }
@@ -428,7 +466,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.TokenValidationResponse" "$ref": "#/definitions/api.TokenValidationResponse"
} }
}, },
@@ -455,7 +492,6 @@ var doc = `{
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -479,7 +515,6 @@ var doc = `{
"202": { "202": {
"description": "Accepted", "description": "Accepted",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -490,11 +525,15 @@ var doc = `{
"definitions": { "definitions": {
"api.ArrayResponse": { "api.ArrayResponse": {
"type": "array", "type": "array",
"items": {} "items": {
"type": "string"
}
}, },
"api.MapResponse": { "api.MapResponse": {
"type": "object", "type": "object",
"additionalProperties": {} "additionalProperties": {
"type": "string"
}
}, },
"api.RuntimeResponse": { "api.RuntimeResponse": {
"type": "object", "type": "object",
@@ -511,6 +550,9 @@ var doc = `{
"hostname": { "hostname": {
"type": "string" "type": "string"
}, },
"logo": {
"type": "string"
},
"message": { "message": {
"type": "string" "type": "string"
}, },
@@ -566,11 +608,21 @@ type swaggerInfo struct {
} }
// SwaggerInfo holds exported Swagger Info so clients can modify it // SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{Schemes: []string{"http", "https"}} var SwaggerInfo = swaggerInfo{
Version: "2.0",
Host: "localhost:9898",
BasePath: "/",
Schemes: []string{"http", "https"},
Title: "Podinfo API",
Description: "Go microservice template for Kubernetes.",
}
type s struct{} type s struct{}
func (s *s) ReadDoc() string { func (s *s) ReadDoc() string {
sInfo := SwaggerInfo
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
t, err := template.New("swagger_info").Funcs(template.FuncMap{ t, err := template.New("swagger_info").Funcs(template.FuncMap{
"marshal": func(v interface{}) string { "marshal": func(v interface{}) string {
a, _ := json.Marshal(v) a, _ := json.Marshal(v)
@@ -582,7 +634,7 @@ func (s *s) ReadDoc() string {
} }
var tpl bytes.Buffer var tpl bytes.Buffer
if err := t.Execute(&tpl, SwaggerInfo); err != nil { if err := t.Execute(&tpl, sInfo); err != nil {
return doc return doc
} }

View File

@@ -1,4 +1,8 @@
{ {
"schemes": [
"http",
"https"
],
"swagger": "2.0", "swagger": "2.0",
"info": { "info": {
"description": "Go microservice template for Kubernetes.", "description": "Go microservice template for Kubernetes.",
@@ -53,7 +57,6 @@
"202": { "202": {
"description": "Accepted", "description": "Accepted",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -77,13 +80,58 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.RuntimeResponse" "$ref": "#/definitions/api.RuntimeResponse"
} }
} }
} }
} }
}, },
"/cache": {
"post": {
"description": "writes the posted content in cache and returns the SHA1 hash of the content",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"HTTP API"
],
"summary": "Save payload in cache",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.MapResponse"
}
}
}
}
},
"/cache/{hash}": {
"get": {
"description": "returns the content from cache if key exists",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"HTTP API"
],
"summary": "Get payload from cache",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
}
}
}
},
"/chunked/{seconds}": { "/chunked/{seconds}": {
"get": { "get": {
"description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period", "description": "uses transfer-encoding type chunked to give a partial response and then waits for the specified period",
@@ -101,7 +149,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -125,7 +172,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -149,7 +195,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.ArrayResponse" "$ref": "#/definitions/api.ArrayResponse"
} }
} }
@@ -173,7 +218,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.ArrayResponse" "$ref": "#/definitions/api.ArrayResponse"
} }
} }
@@ -318,7 +362,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -342,7 +385,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -389,7 +431,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.TokenResponse" "$ref": "#/definitions/api.TokenResponse"
} }
} }
@@ -413,7 +454,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.TokenValidationResponse" "$ref": "#/definitions/api.TokenValidationResponse"
} }
}, },
@@ -440,7 +480,6 @@
"200": { "200": {
"description": "OK", "description": "OK",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -464,7 +503,6 @@
"202": { "202": {
"description": "Accepted", "description": "Accepted",
"schema": { "schema": {
"type": "object",
"$ref": "#/definitions/api.MapResponse" "$ref": "#/definitions/api.MapResponse"
} }
} }
@@ -475,11 +513,15 @@
"definitions": { "definitions": {
"api.ArrayResponse": { "api.ArrayResponse": {
"type": "array", "type": "array",
"items": {} "items": {
"type": "string"
}
}, },
"api.MapResponse": { "api.MapResponse": {
"type": "object", "type": "object",
"additionalProperties": {} "additionalProperties": {
"type": "string"
}
}, },
"api.RuntimeResponse": { "api.RuntimeResponse": {
"type": "object", "type": "object",
@@ -496,6 +538,9 @@
"hostname": { "hostname": {
"type": "string" "type": "string"
}, },
"logo": {
"type": "string"
},
"message": { "message": {
"type": "string" "type": "string"
}, },

View File

@@ -1,10 +1,12 @@
basePath: / basePath: /
definitions: definitions:
api.ArrayResponse: api.ArrayResponse:
items: {} items:
type: string
type: array type: array
api.MapResponse: api.MapResponse:
additionalProperties: {} additionalProperties:
type: string
type: object type: object
api.RuntimeResponse: api.RuntimeResponse:
properties: properties:
@@ -16,6 +18,8 @@ definitions:
type: string type: string
hostname: hostname:
type: string type: string
logo:
type: string
message: message:
type: string type: string
num_cpu: num_cpu:
@@ -80,7 +84,6 @@ paths:
description: Accepted description: Accepted
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Echo summary: Echo
tags: tags:
- HTTP API - HTTP API
@@ -96,10 +99,40 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.RuntimeResponse' $ref: '#/definitions/api.RuntimeResponse'
type: object
summary: Runtime information summary: Runtime information
tags: tags:
- HTTP API - HTTP API
/cache:
post:
consumes:
- application/json
description: writes the posted content in cache and returns the SHA1 hash of
the content
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/api.MapResponse'
summary: Save payload in cache
tags:
- HTTP API
/cache/{hash}:
get:
consumes:
- application/json
description: returns the content from cache if key exists
produces:
- application/json
responses:
"200":
description: OK
schema:
type: string
summary: Get payload from cache
tags:
- HTTP API
/chunked/{seconds}: /chunked/{seconds}:
get: get:
consumes: consumes:
@@ -113,7 +146,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Chunked transfer encoding summary: Chunked transfer encoding
tags: tags:
- HTTP API - HTTP API
@@ -129,7 +161,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Delay summary: Delay
tags: tags:
- HTTP API - HTTP API
@@ -145,7 +176,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.ArrayResponse' $ref: '#/definitions/api.ArrayResponse'
type: object
summary: Environment summary: Environment
tags: tags:
- HTTP API - HTTP API
@@ -161,7 +191,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.ArrayResponse' $ref: '#/definitions/api.ArrayResponse'
type: object
summary: Headers summary: Headers
tags: tags:
- HTTP API - HTTP API
@@ -257,7 +286,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Status code summary: Status code
tags: tags:
- HTTP API - HTTP API
@@ -274,7 +302,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Upload file summary: Upload file
tags: tags:
- HTTP API - HTTP API
@@ -305,7 +332,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.TokenResponse' $ref: '#/definitions/api.TokenResponse'
type: object
summary: Generate JWT token summary: Generate JWT token
tags: tags:
- HTTP API - HTTP API
@@ -321,7 +347,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.TokenValidationResponse' $ref: '#/definitions/api.TokenValidationResponse'
type: object
"401": "401":
description: Unauthorized description: Unauthorized
schema: schema:
@@ -339,7 +364,6 @@ paths:
description: OK description: OK
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Version summary: Version
tags: tags:
- HTTP API - HTTP API
@@ -355,8 +379,10 @@ paths:
description: Accepted description: Accepted
schema: schema:
$ref: '#/definitions/api.MapResponse' $ref: '#/definitions/api.MapResponse'
type: object
summary: Echo over websockets summary: Echo over websockets
tags: tags:
- HTTP API - HTTP API
schemes:
- http
- https
swagger: "2.0" swagger: "2.0"

View File

@@ -3,11 +3,6 @@ package api
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/swaggo/swag"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
@@ -15,13 +10,17 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/gomodule/redigo/redis"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/viper" "github.com/spf13/viper"
_ "github.com/stefanprodan/podinfo/pkg/api/docs" _ "github.com/stefanprodan/podinfo/pkg/api/docs"
"github.com/stefanprodan/podinfo/pkg/fscache" "github.com/stefanprodan/podinfo/pkg/fscache"
httpSwagger "github.com/swaggo/http-swagger" httpSwagger "github.com/swaggo/http-swagger"
"github.com/swaggo/swag"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
) )
// @title Podinfo API // @title Podinfo API
@@ -69,12 +68,14 @@ type Config struct {
Unhealthy bool `mapstructure:"unhealthy"` Unhealthy bool `mapstructure:"unhealthy"`
Unready bool `mapstructure:"unready"` Unready bool `mapstructure:"unready"`
JWTSecret string `mapstructure:"jwt-secret"` JWTSecret string `mapstructure:"jwt-secret"`
CacheServer string `mapstructure:"cache-server"`
} }
type Server struct { type Server struct {
router *mux.Router router *mux.Router
logger *zap.Logger logger *zap.Logger
config *Config config *Config
pool *redis.Pool
} }
func NewServer(config *Config, logger *zap.Logger) (*Server, error) { func NewServer(config *Config, logger *zap.Logger) (*Server, error) {
@@ -103,8 +104,10 @@ func (s *Server) registerHandlers() {
s.router.HandleFunc("/readyz/disable", s.disableReadyHandler).Methods("POST") s.router.HandleFunc("/readyz/disable", s.disableReadyHandler).Methods("POST")
s.router.HandleFunc("/panic", s.panicHandler).Methods("GET") s.router.HandleFunc("/panic", s.panicHandler).Methods("GET")
s.router.HandleFunc("/status/{code:[0-9]+}", s.statusHandler).Methods("GET", "POST", "PUT").Name("status") s.router.HandleFunc("/status/{code:[0-9]+}", s.statusHandler).Methods("GET", "POST", "PUT").Name("status")
s.router.HandleFunc("/store", s.storeWriteHandler).Methods("POST") s.router.HandleFunc("/store", s.storeWriteHandler).Methods("POST", "PUT")
s.router.HandleFunc("/store/{hash}", s.storeReadHandler).Methods("GET").Name("store") s.router.HandleFunc("/store/{hash}", s.storeReadHandler).Methods("GET").Name("store")
s.router.HandleFunc("/cache", s.cacheWriteHandler).Methods("POST", "PUT")
s.router.HandleFunc("/cache/{hash}", s.cacheReadHandler).Methods("GET").Name("cache")
s.router.HandleFunc("/configs", s.configReadHandler).Methods("GET") s.router.HandleFunc("/configs", s.configReadHandler).Methods("GET")
s.router.HandleFunc("/token", s.tokenGenerateHandler).Methods("POST") s.router.HandleFunc("/token", s.tokenGenerateHandler).Methods("POST")
s.router.HandleFunc("/token/validate", s.tokenValidateHandler).Methods("GET") s.router.HandleFunc("/token/validate", s.tokenValidateHandler).Methods("GET")
@@ -176,6 +179,27 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
} }
} }
// start redis connection pool
s.startCachePool()
if s.pool != nil {
ticker := time.NewTicker(30 * time.Second)
go func() {
for {
select {
case <-stopCh:
return
case <-ticker.C:
conn := s.pool.Get()
_, err := redis.String(conn.Do("PING"))
if err != nil {
s.logger.Warn("cache server is offline", zap.Error(err), zap.String("server", s.config.CacheServer))
}
_ = conn.Close()
}
}
}()
}
// run server in background // run server in background
go func() { go func() {
if err := srv.ListenAndServe(); err != http.ErrServerClosed { if err := srv.ListenAndServe(); err != http.ErrServerClosed {
@@ -200,6 +224,11 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
atomic.StoreInt32(&healthy, 0) atomic.StoreInt32(&healthy, 0)
atomic.StoreInt32(&ready, 0) atomic.StoreInt32(&ready, 0)
// close cache pool
if s.pool != nil {
_ = s.pool.Close()
}
s.logger.Info("Shutting down HTTP server", zap.Duration("timeout", s.config.HttpServerShutdownTimeout)) s.logger.Info("Shutting down HTTP server", zap.Duration("timeout", s.config.HttpServerShutdownTimeout))
// wait for Kubernetes readiness probe to remove this instance from the load balancer // wait for Kubernetes readiness probe to remove this instance from the load balancer

View File

@@ -1,4 +1,4 @@
package version package version
var VERSION = "3.2.2" var VERSION = "3.3.0"
var REVISION = "unknown" var REVISION = "unknown"