mirror of
https://github.com/stefanprodan/podinfo.git
synced 2026-04-07 03:26:54 +00:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b501abd1f0 | ||
|
|
e0a79a4ddd | ||
|
|
be8baac695 | ||
|
|
f539517440 | ||
|
|
01219a196e | ||
|
|
b9acae4064 | ||
|
|
64a8da1836 | ||
|
|
420d0db8bf | ||
|
|
6b67f2bdd6 | ||
|
|
095b1cd251 | ||
|
|
0a27dbe40c | ||
|
|
2da74a4ec2 | ||
|
|
c7ffdba3bd | ||
|
|
06f7cd3777 | ||
|
|
620b9b7e2c | ||
|
|
83deb7fcb7 | ||
|
|
550ee9f7b9 | ||
|
|
dd185df435 | ||
|
|
07a524ba01 | ||
|
|
5d97df9c89 | ||
|
|
a8cadef09b | ||
|
|
32f6e3d8c9 | ||
|
|
77dc46241d | ||
|
|
3a31e973c0 | ||
|
|
e15511a92d | ||
|
|
4656ca0517 | ||
|
|
1f66430364 | ||
|
|
117533e329 | ||
|
|
29827dd944 | ||
|
|
9525259938 | ||
|
|
a53ddbcffc | ||
|
|
e3c8277e58 | ||
|
|
420b2f64b8 | ||
|
|
0a93807324 | ||
|
|
d73d94eec9 | ||
|
|
a723c9447d | ||
|
|
eca2d3a1d9 | ||
|
|
2dfda568b2 | ||
|
|
4d7604ab63 |
4
.github/workflows/cve-scan.yml
vendored
4
.github/workflows/cve-scan.yml
vendored
@@ -16,10 +16,10 @@ jobs:
|
||||
govulncheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: ./.github/actions/runner-cleanup
|
||||
- name: Vulnerability scan
|
||||
id: govulncheck
|
||||
uses: golang/govulncheck-action@v1
|
||||
uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4
|
||||
with:
|
||||
repo-checkout: false
|
||||
|
||||
14
.github/workflows/e2e.yml
vendored
14
.github/workflows/e2e.yml
vendored
@@ -14,11 +14,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Disk Cleanup
|
||||
uses: ./.github/actions/runner-cleanup
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@v1.13.0
|
||||
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
|
||||
with:
|
||||
cluster_name: kind
|
||||
- name: Build container image
|
||||
@@ -26,9 +26,9 @@ jobs:
|
||||
./test/build.sh
|
||||
kind load docker-image test/podinfo:latest
|
||||
- name: Setup Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
|
||||
with:
|
||||
version: v3.17.3
|
||||
version: v4.1.0
|
||||
- name: Deploy
|
||||
run: ./test/deploy.sh
|
||||
- name: Run integration tests
|
||||
@@ -49,12 +49,12 @@ jobs:
|
||||
PODINFO_MODULE_URL: "oci://localhost:5000/podinfo"
|
||||
PODINFO_VERSION: "0.0.0-devel"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: ./.github/actions/runner-cleanup
|
||||
- name: Setup Timoni
|
||||
uses: stefanprodan/timoni/actions/setup@main
|
||||
uses: stefanprodan/timoni/actions/setup@c68e33a34f17c7ca93c7fc6717d61a14819276dc # v0.26.0
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@v1.13.0
|
||||
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
|
||||
with:
|
||||
cluster_name: kind
|
||||
- name: Build container
|
||||
|
||||
43
.github/workflows/release.yml
vendored
43
.github/workflows/release.yml
vendored
@@ -15,16 +15,15 @@ jobs:
|
||||
contents: write # needed to write releases
|
||||
id-token: write # needed for keyless signing
|
||||
packages: write # needed for ghcr access
|
||||
attestations: write # needed for provenance
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: ./.github/actions/runner-cleanup
|
||||
- uses: sigstore/cosign-installer@v4.0.0
|
||||
with:
|
||||
cosign-release: v2.6.1
|
||||
- uses: fluxcd/flux2/action@v2.7.5
|
||||
- uses: stefanprodan/timoni/actions/setup@v0.25.2
|
||||
- uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||
- uses: fluxcd/flux2/action@871be9b40d53627786d3a3835a3ddba1e3234bd2 # v2.8.3
|
||||
- uses: stefanprodan/timoni/actions/setup@c68e33a34f17c7ca93c7fc6717d61a14819276dc # v0.26.0
|
||||
- name: Setup Notation CLI
|
||||
uses: notaryproject/notation-action/setup@v1
|
||||
uses: notaryproject/notation-action/setup@b6fee73110795d6793253c673bd723f12bcf9bbb # v1.2.2
|
||||
with:
|
||||
version: "1.1.0"
|
||||
- name: Setup Notation signing keys
|
||||
@@ -36,28 +35,28 @@ jobs:
|
||||
env:
|
||||
NOTATION_KEY: ${{ secrets.NOTATION_SIGNING_KEY }}
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
with:
|
||||
go-version: 1.25.x
|
||||
go-version: 1.26.x
|
||||
- name: Setup Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
|
||||
with:
|
||||
version: v3.17.3
|
||||
version: v4.1.1
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
with:
|
||||
platforms: all
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
@@ -73,7 +72,7 @@ jobs:
|
||||
echo "REVISION=${GITHUB_SHA}" >> $GITHUB_OUTPUT
|
||||
- name: Generate images meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
with:
|
||||
images: |
|
||||
docker.io/stefanprodan/podinfo
|
||||
@@ -82,7 +81,7 @@ jobs:
|
||||
type=raw,value=${{ steps.prep.outputs.VERSION }}
|
||||
type=raw,value=latest
|
||||
- name: Publish multi-arch image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
sbom: true
|
||||
provenance: true
|
||||
@@ -125,7 +124,7 @@ jobs:
|
||||
cosign sign ghcr.io/stefanprodan/charts/podinfo:${{ steps.prep.outputs.VERSION }} --yes
|
||||
cosign sign ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }} --yes
|
||||
- name: Publish base image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
with:
|
||||
push: true
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
@@ -134,7 +133,7 @@ jobs:
|
||||
file: ./Dockerfile.base
|
||||
tags: docker.io/stefanprodan/podinfo-base:latest
|
||||
- name: Publish helm chart
|
||||
uses: stefanprodan/helm-gh-pages@master
|
||||
uses: stefanprodan/helm-gh-pages@0ad2bb377311d61ac04ad9eb6f252fb68e207260 # v1.7.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Publish config artifact
|
||||
@@ -160,9 +159,13 @@ jobs:
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo-deploy:latest
|
||||
- name: Publish release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --skip=validate
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Attest release
|
||||
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
|
||||
with:
|
||||
subject-checksums: ./dist/podinfo_${{ steps.prep.outputs.VERSION }}_checksums.txt
|
||||
|
||||
18
.github/workflows/test.yml
vendored
18
.github/workflows/test.yml
vendored
@@ -10,36 +10,36 @@ permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
KUBERNETES_VERSION: 1.31.0
|
||||
HELM_VERSION: 3.17.3
|
||||
KUBERNETES_VERSION: 1.35.0
|
||||
HELM_VERSION: 4.1.1
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: ./.github/actions/runner-cleanup
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
with:
|
||||
go-version: 1.25.x
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Setup kubectl
|
||||
uses: azure/setup-kubectl@v4
|
||||
uses: azure/setup-kubectl@15650b3ad78fff148532a140b8a4c821796b2d7b # v5.0.0
|
||||
with:
|
||||
version: v${{ env.KUBERNETES_VERSION }}
|
||||
- name: Setup kubeconform
|
||||
uses: ./.github/actions/kubeconform
|
||||
- name: Setup Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
|
||||
with:
|
||||
version: v${{ env.HELM_VERSION }}
|
||||
- name: Setup CUE
|
||||
uses: cue-lang/setup-cue@v1.0.1
|
||||
uses: cue-lang/setup-cue@a93fa358375740cd8b0078f76355512b9208acb1 # v1.0.1
|
||||
- name: Setup Timoni
|
||||
uses: stefanprodan/timoni/actions/setup@v0.25.2
|
||||
uses: stefanprodan/timoni/actions/setup@c68e33a34f17c7ca93c7fc6717d61a14819276dc # v0.26.0
|
||||
- name: Run unit tests
|
||||
run: make test
|
||||
- name: Validate Helm chart
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25-alpine AS builder
|
||||
FROM golang:1.26-alpine AS builder
|
||||
|
||||
ARG REVISION
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25
|
||||
FROM golang:1.26
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG GO_VERSION=1.25
|
||||
ARG GO_VERSION=1.26
|
||||
ARG XX_VERSION=1.9.0
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
2
Makefile
2
Makefile
@@ -24,7 +24,7 @@ build:
|
||||
GIT_COMMIT=$$(git rev-list -1 HEAD) && CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/stefanprodan/podinfo/pkg/version.REVISION=$(GIT_COMMIT)" -a -o ./bin/podcli ./cmd/podcli/*
|
||||
|
||||
tidy:
|
||||
rm -f go.sum; go mod tidy -compat=1.25
|
||||
rm -f go.sum; go mod tidy -compat=1.26
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
version: 6.10.0
|
||||
appVersion: 6.10.0
|
||||
version: 6.11.2
|
||||
appVersion: 6.11.2
|
||||
name: podinfo
|
||||
engine: gotpl
|
||||
description: Podinfo Helm chart for Kubernetes
|
||||
|
||||
@@ -52,79 +52,84 @@ 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.
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------------------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------|
|
||||
| `replicaCount` | `1` | Desired number of pods |
|
||||
| `logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
||||
| `backend` | `None` | Echo backend URL |
|
||||
| `backends` | `[]` | Array of echo backend URLs |
|
||||
| `cache` | `None` | Redis address in the format `tcp://<host>:<port>` |
|
||||
| `redis.enabled` | `false` | Create Redis deployment for caching purposes |
|
||||
| `redis.repository` | `docker.io/redis` | Redis image repository |
|
||||
| `redis.tag` | `<VERSION>` | Redis image tag |
|
||||
| `redis.imagePullSecrets` | `[]` | Redis image pull secrets |
|
||||
| `ui.color` | `#34577c` | UI color |
|
||||
| `ui.message` | `None` | UI greetings message |
|
||||
| `ui.logo` | `None` | UI logo |
|
||||
| `faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds |
|
||||
| `faults.error` | `false` | 1/3 chances of a random HTTP response error |
|
||||
| `faults.unhealthy` | `false` | When set, the healthy state is never reached |
|
||||
| `faults.unready` | `false` | When set, the ready state is never reached |
|
||||
| `faults.testFail` | `false` | When set, a helm test is included which always fails |
|
||||
| `faults.testTimeout` | `false` | When set, a helm test is included which always times out |
|
||||
| `image.repository` | `ghcr.io/stefanprodan/podinfo` | Image repository |
|
||||
| `image.tag` | `<VERSION>` | Image tag |
|
||||
| `image.pullPolicy` | `IfNotPresent` | Image pull policy |
|
||||
| `image.pullSecrets` | `[]` | Image pull secrets |
|
||||
| `service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app) |
|
||||
| `service.type` | `ClusterIP` | Type of the Kubernetes Service |
|
||||
| `service.metricsPort` | `9797` | Prometheus metrics endpoint port |
|
||||
| `service.httpPort` | `9898` | Container HTTP port |
|
||||
| `service.externalPort` | `9898` | ClusterIP HTTP port |
|
||||
| `service.grpcPort` | `9999` | ClusterIP gPRC port |
|
||||
| `service.grpcService` | `podinfo` | gPRC service name |
|
||||
| `service.nodePort` | `31198` | NodePort for the HTTP endpoint |
|
||||
| `service.trafficDistribution` | `""` | Traffic distribution strategy |
|
||||
| `service.additionalLabels` | `{}` | Additional labels to add to the service |
|
||||
| `service.externalTrafficPolicy` | `None` | External traffic policy for LoadBalance service |
|
||||
| `h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2) |
|
||||
| `extraArgs` | `[]` | Additional command line arguments to pass to podinfo container |
|
||||
| `extraEnvs` | `[]` | Extra environment variables for the podinfo container |
|
||||
| `config.path` | `""` | config file path |
|
||||
| `config.name` | `""` | config file name |
|
||||
| `hpa.enabled` | `false` | Enables the Kubernetes HPA |
|
||||
| `hpa.maxReplicas` | `10` | Maximum amount of pods |
|
||||
| `hpa.cpu` | `None` | Target CPU usage per pod |
|
||||
| `hpa.memory` | `None` | Target memory usage per pod |
|
||||
| `hpa.requests` | `None` | Target HTTP requests per second per pod |
|
||||
| `serviceAccount.enabled` | `false` | Whether a service account should be created |
|
||||
| `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 |
|
||||
| `serviceAccount.imagePullSecrets` | `[]` | List of image pull secrets if pulling from private registries. |
|
||||
| `securityContext` | `{}` | The security context to be set on the podinfo container |
|
||||
| `podSecurityContext` | `{}` | The security context to be set on the pod |
|
||||
| `podAnnotations` | `{}` | Pod annotations |
|
||||
| `serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created |
|
||||
| `serviceMonitor.interval` | `15s` | Prometheus scraping interval |
|
||||
| `serviceMonitor.additionalLabels` | `{}` | Add additional labels to the service monitor |
|
||||
| `ingress.enabled` | `false` | Enables Ingress |
|
||||
| `ingress.className` | `""` | Use ingressClassName |
|
||||
| `ingress.additionalLabels` | `{}` | Add additional labels to the ingress |
|
||||
| `ingress.annotations` | `{}` | Ingress annotations |
|
||||
| `ingress.hosts` | `[]` | Ingress accepted hosts |
|
||||
| `ingress.tls` | `[]` | Ingress TLS configuration |
|
||||
| `httpRoute.enabled` | `false` | Enables Gateway API HTTPRoute |
|
||||
| `httpRoute.additionalLabels` | `{}` | Add additional labels to the HTTPRoute |
|
||||
| `httpRoute.annotations` | `{}` | HTTPRoute annotations |
|
||||
| `httpRoute.parentRefs` | `[]` | Gateways that this route is attached to |
|
||||
| `httpRoute.hostnames` | `["podinfo.local"]` | Hostnames matching HTTP header |
|
||||
| `httpRoute.rules` | `[]` | List of rules and filters applied |
|
||||
| `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 |
|
||||
| Parameter | Default | Description |
|
||||
|--------------------------------------------------|--------------------------------|---------------------------------------------------------------------------------------------------|
|
||||
| `replicaCount` | `1` | Desired number of pods |
|
||||
| `logLevel` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
||||
| `backend` | `None` | Echo backend URL |
|
||||
| `backends` | `[]` | Array of echo backend URLs |
|
||||
| `cache` | `None` | Redis address in the format `tcp://<host>:<port>` |
|
||||
| `redis.enabled` | `false` | Create Redis deployment for caching purposes |
|
||||
| `redis.repository` | `docker.io/redis` | Redis image repository |
|
||||
| `redis.tag` | `<VERSION>` | Redis image tag |
|
||||
| `redis.imagePullSecrets` | `[]` | Redis image pull secrets |
|
||||
| `ui.color` | `#34577c` | UI color |
|
||||
| `ui.message` | `None` | UI greetings message |
|
||||
| `ui.logo` | `None` | UI logo |
|
||||
| `faults.delay` | `false` | Random HTTP response delays between 0 and 5 seconds |
|
||||
| `faults.error` | `false` | 1/3 chances of a random HTTP response error |
|
||||
| `faults.unhealthy` | `false` | When set, the healthy state is never reached |
|
||||
| `faults.unready` | `false` | When set, the ready state is never reached |
|
||||
| `faults.testFail` | `false` | When set, a helm test is included which always fails |
|
||||
| `faults.testTimeout` | `false` | When set, a helm test is included which always times out |
|
||||
| `image.repository` | `ghcr.io/stefanprodan/podinfo` | Image repository |
|
||||
| `image.tag` | `<VERSION>` | Image tag |
|
||||
| `image.pullPolicy` | `IfNotPresent` | Image pull policy |
|
||||
| `image.pullSecrets` | `[]` | Image pull secrets |
|
||||
| `service.enabled` | `true` | Create a Kubernetes Service, should be disabled when using [Flagger](https://flagger.app) |
|
||||
| `service.type` | `ClusterIP` | Type of the Kubernetes Service |
|
||||
| `service.metricsPort` | `9797` | Prometheus metrics endpoint port |
|
||||
| `service.httpPort` | `9898` | Container HTTP port |
|
||||
| `service.externalPort` | `9898` | ClusterIP HTTP port |
|
||||
| `service.grpcPort` | `9999` | ClusterIP gPRC port |
|
||||
| `service.grpcService` | `podinfo` | gPRC service name |
|
||||
| `service.nodePort` | `31198` | NodePort for the HTTP endpoint |
|
||||
| `service.trafficDistribution` | `""` | Traffic distribution strategy |
|
||||
| `service.additionalLabels` | `{}` | Additional labels to add to the service |
|
||||
| `service.externalTrafficPolicy` | `None` | External traffic policy for LoadBalance service |
|
||||
| `h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2) |
|
||||
| `extraArgs` | `[]` | Additional command line arguments to pass to podinfo container |
|
||||
| `extraEnvs` | `[]` | Extra environment variables for the podinfo container |
|
||||
| `config.path` | `""` | config file path |
|
||||
| `config.name` | `""` | config file name |
|
||||
| `hpa.enabled` | `false` | Enables the Kubernetes HPA |
|
||||
| `hpa.maxReplicas` | `10` | Maximum amount of pods |
|
||||
| `hpa.cpu` | `None` | Target CPU usage per pod |
|
||||
| `hpa.memory` | `None` | Target memory usage per pod |
|
||||
| `hpa.requests` | `None` | Target HTTP requests per second per pod |
|
||||
| `serviceAccount.enabled` | `false` | Whether a service account should be created |
|
||||
| `serviceAccount.name` | `None` | The name of the service account to use, if not set a name is generated using the fullname template|
|
||||
| `serviceAccount.imagePullSecrets` | `[]` | List of image pull secrets if pulling from private registries |
|
||||
| `securityContext` | `{}` | The security context to be set on the podinfo container |
|
||||
| `podSecurityContext` | `{}` | The security context to be set on the pod |
|
||||
| `podAnnotations` | `{}` | Pod annotations |
|
||||
| `serviceMonitor.enabled` | `false` | Whether a Prometheus Operator service monitor should be created |
|
||||
| `serviceMonitor.interval` | `15s` | Prometheus scraping interval |
|
||||
| `serviceMonitor.additionalLabels` | `{}` | Add additional labels to the service monitor |
|
||||
| `ingress.enabled` | `false` | Enables Ingress |
|
||||
| `ingress.className` | `""` | Use ingressClassName |
|
||||
| `ingress.additionalLabels` | `{}` | Add additional labels to the ingress |
|
||||
| `ingress.annotations` | `{}` | Ingress annotations |
|
||||
| `ingress.hosts` | `[]` | Ingress accepted hosts |
|
||||
| `ingress.tls` | `[]` | Ingress TLS configuration |
|
||||
| `httpRoute.enabled` | `false` | Enables Gateway API HTTPRoute |
|
||||
| `httpRoute.additionalLabels` | `{}` | Add additional labels to the HTTPRoute |
|
||||
| `httpRoute.annotations` | `{}` | HTTPRoute annotations |
|
||||
| `httpRoute.parentRefs` | `[]` | Gateways that this route is attached to |
|
||||
| `httpRoute.hostnames` | `["podinfo.local"]` | Hostnames matching HTTP header |
|
||||
| `httpRoute.rules` | `[]` | List of rules and filters applied |
|
||||
| `hooks.<hookType>.job.enabled` | `false` | Create a Helm hook job for testing (hookType: see values.yaml for available hooks) |
|
||||
| `hooks.<hookType>.job.hookDeletePolicy` | `hook-succeeded,hook-failed` | Helm hook delete policy |
|
||||
| `hooks.<hookType>.job.ttlSecondsAfterFinished` | `None` | Job TTL after finished |
|
||||
| `hooks.<hookType>.job.sleepSeconds` | `None` | Sleep duration before job exits |
|
||||
| `hooks.<hookType>.job.exitCode` | `0` | Job exit code |
|
||||
| `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:
|
||||
|
||||
|
||||
42
charts/podinfo/templates/grpcroute.yaml
Normal file
42
charts/podinfo/templates/grpcroute.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
{{- if .Values.grpcRoute.enabled -}}
|
||||
{{- $fullName := include "podinfo.fullname" . -}}
|
||||
{{- $grpcPort := .Values.service.grpcPort -}}
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: GRPCRoute
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ include "podinfo.namespace" . }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" . | nindent 4 }}
|
||||
{{- with .Values.grpcRoute.additionalLabels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.grpcRoute.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
parentRefs:
|
||||
{{- with .Values.grpcRoute.parentRefs }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.grpcRoute.hostnames }}
|
||||
hostnames:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.grpcRoute.rules }}
|
||||
- backendRefs:
|
||||
- name: {{ $fullName }}
|
||||
port: {{ $grpcPort }}
|
||||
weight: 1
|
||||
{{- with .matches }}
|
||||
matches:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .filters }}
|
||||
filters:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
37
charts/podinfo/templates/hooks/job.yaml
Normal file
37
charts/podinfo/templates/hooks/job.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
{{- $hooks := dict "preInstall" "pre-install" "postInstall" "post-install" "preDelete" "pre-delete" "postDelete" "post-delete" "preUpgrade" "pre-upgrade" "postUpgrade" "post-upgrade" "preRollback" "pre-rollback" "postRollback" "post-rollback" }}
|
||||
{{- range $hookName, $hookType := $hooks }}
|
||||
{{- $hookConfig := index $.Values.hooks $hookName }}
|
||||
{{- if and $hookConfig $hookConfig.job $hookConfig.job.enabled }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ template "podinfo.fullname" $ }}-{{ $hookType }}
|
||||
namespace: {{ include "podinfo.namespace" $ }}
|
||||
labels:
|
||||
{{- include "podinfo.labels" $ | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": {{ $hookType }}
|
||||
"helm.sh/hook-delete-policy": {{ $hookConfig.job.hookDeletePolicy }}
|
||||
spec:
|
||||
{{- if kindIs "float64" $hookConfig.job.ttlSecondsAfterFinished }}
|
||||
ttlSecondsAfterFinished: {{ $hookConfig.job.ttlSecondsAfterFinished | int }}
|
||||
{{- end }}
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: job
|
||||
image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag }}"
|
||||
imagePullPolicy: {{ $.Values.image.pullPolicy }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
{{- if kindIs "float64" $hookConfig.job.sleepSeconds }}
|
||||
sleep {{ $hookConfig.job.sleepSeconds | int }}
|
||||
{{- end }}
|
||||
exit {{ $hookConfig.job.exitCode | default 0 }}
|
||||
restartPolicy: Never
|
||||
backoffLimit: 1
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -8,7 +8,7 @@ backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.10.0
|
||||
tag: 6.11.2
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
ui:
|
||||
@@ -96,7 +96,7 @@ cache: ""
|
||||
redis:
|
||||
enabled: true
|
||||
repository: redis
|
||||
tag: 8.4.0
|
||||
tag: 8.6.1
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
|
||||
@@ -8,7 +8,7 @@ backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.10.0
|
||||
tag: 6.11.2
|
||||
pullPolicy: IfNotPresent
|
||||
pullSecrets: []
|
||||
|
||||
@@ -93,6 +93,65 @@ certificate:
|
||||
dnsNames:
|
||||
- podinfo
|
||||
|
||||
# Helm hooks (for testing purposes)
|
||||
hooks:
|
||||
preInstall:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
postInstall:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
preDelete:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
postDelete:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
preUpgrade:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
postUpgrade:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
preRollback:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
postRollback:
|
||||
job:
|
||||
enabled: false
|
||||
hookDeletePolicy: hook-succeeded,hook-failed
|
||||
ttlSecondsAfterFinished:
|
||||
sleepSeconds:
|
||||
exitCode: 0
|
||||
|
||||
# metrics-server add-on required
|
||||
hpa:
|
||||
enabled: false
|
||||
@@ -110,7 +169,7 @@ cache: ""
|
||||
redis:
|
||||
enabled: false
|
||||
repository: docker.io/redis
|
||||
tag: 8.4.0
|
||||
tag: 8.6.1
|
||||
imagePullSecrets: []
|
||||
|
||||
serviceAccount:
|
||||
@@ -173,6 +232,28 @@ httpRoute:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
|
||||
# -- Expose the gRPC service via Gateway GRPCRoute
|
||||
# Requires a Gateway controller with GRPCRoute support
|
||||
# Docs https://gateway-api.sigs.k8s.io/guides/grpc-routing/
|
||||
grpcRoute:
|
||||
# GRPCRoute enabled.
|
||||
enabled: false
|
||||
# Add additional labels to the GRPCRoute.
|
||||
additionalLabels: {}
|
||||
# GRPCRoute annotations.
|
||||
annotations: {}
|
||||
# Which Gateways this Route is attached to.
|
||||
parentRefs:
|
||||
- name: gateway
|
||||
sectionName: http
|
||||
# namespace: default
|
||||
# Hostnames matching HTTP header.
|
||||
hostnames:
|
||||
- podinfo.local
|
||||
# List of rules applied.
|
||||
rules:
|
||||
- {}
|
||||
|
||||
# create Prometheus Operator monitor
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
steps:
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args: ['build','-f' , 'Dockerfile', '-t', 'gcr.io/$PROJECT_ID/podinfo:$BRANCH_NAME-$SHORT_SHA', '.']
|
||||
images: ['gcr.io/$PROJECT_ID/podinfo:$BRANCH_NAME-$SHORT_SHA']
|
||||
@@ -12,10 +12,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -27,6 +30,7 @@ var (
|
||||
body string
|
||||
timeout time.Duration
|
||||
grpcServiceName string
|
||||
grpcTLS bool
|
||||
)
|
||||
|
||||
var checkCmd = &cobra.Command{
|
||||
@@ -63,6 +67,13 @@ var checkgRPCCmd = &cobra.Command{
|
||||
RunE: runCheckgPRC,
|
||||
}
|
||||
|
||||
var checkWsCmd = &cobra.Command{
|
||||
Use: `ws [address]`,
|
||||
Short: "WebSocket round-trip health check",
|
||||
Example: ` check ws ws://localhost:9898/ws/echo --retry=1 --delay=2s --timeout=5s`,
|
||||
RunE: runCheckWs,
|
||||
}
|
||||
|
||||
func init() {
|
||||
checkUrlCmd.Flags().StringVar(&method, "method", "GET", "HTTP method")
|
||||
checkUrlCmd.Flags().StringVar(&body, "body", "", "HTTP POST/PUT content")
|
||||
@@ -80,10 +91,16 @@ func init() {
|
||||
checkgRPCCmd.Flags().DurationVar(&retryDelay, "delay", 1*time.Second, "wait duration between retries")
|
||||
checkgRPCCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
|
||||
checkgRPCCmd.Flags().StringVar(&grpcServiceName, "service", "", "gRPC service name")
|
||||
checkgRPCCmd.Flags().BoolVar(&grpcTLS, "tls", false, "use TLS for gRPC connection")
|
||||
checkCmd.AddCommand(checkgRPCCmd)
|
||||
|
||||
checkCmd.AddCommand(checkCertCmd)
|
||||
|
||||
checkWsCmd.Flags().IntVar(&retryCount, "retry", 0, "times to retry the WebSocket check")
|
||||
checkWsCmd.Flags().DurationVar(&retryDelay, "delay", 1*time.Second, "wait duration between retries")
|
||||
checkWsCmd.Flags().DurationVar(&timeout, "timeout", 5*time.Second, "timeout")
|
||||
checkCmd.AddCommand(checkWsCmd)
|
||||
|
||||
rootCmd.AddCommand(checkCmd)
|
||||
}
|
||||
|
||||
@@ -262,6 +279,72 @@ func fmtContentLength(b int64) string {
|
||||
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
|
||||
}
|
||||
|
||||
func runCheckWs(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 ws wss://localhost:9898/ws/echo")
|
||||
}
|
||||
|
||||
address := args[0]
|
||||
if !strings.HasPrefix(address, "ws://") && !strings.HasPrefix(address, "wss://") {
|
||||
return fmt.Errorf("address must start with ws:// or wss://")
|
||||
}
|
||||
|
||||
for n := 0; n <= retryCount; n++ {
|
||||
if n != 0 {
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
|
||||
dialer := websocket.Dialer{
|
||||
HandshakeTimeout: timeout,
|
||||
}
|
||||
|
||||
conn, _, err := dialer.Dial(address, nil)
|
||||
if err != nil {
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
msg := "podinfo-check"
|
||||
start := time.Now()
|
||||
|
||||
conn.SetWriteDeadline(start.Add(timeout))
|
||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||
conn.Close()
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
_, resp, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
rtt := time.Since(start)
|
||||
conn.Close()
|
||||
|
||||
logger.Info("check succeed",
|
||||
zap.String("address", address),
|
||||
zap.Duration("round-trip", rtt),
|
||||
zap.Int("response size", len(resp)))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCheckgPRC(cmd *cobra.Command, args []string) error {
|
||||
if retryCount < 0 {
|
||||
return fmt.Errorf("--retry is required")
|
||||
@@ -271,12 +354,19 @@ func runCheckgPRC(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
address := args[0]
|
||||
|
||||
var creds grpc.DialOption
|
||||
if grpcTLS {
|
||||
creds = grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))
|
||||
} else {
|
||||
creds = grpc.WithTransportCredentials(insecure.NewCredentials())
|
||||
}
|
||||
|
||||
for n := 0; n <= retryCount; n++ {
|
||||
if n != 1 {
|
||||
if n != 0 {
|
||||
time.Sleep(retryDelay)
|
||||
}
|
||||
|
||||
conn, err := grpc.Dial(address, grpc.WithInsecure())
|
||||
conn, err := grpc.NewClient(address, creds)
|
||||
if err != nil {
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
@@ -291,13 +381,14 @@ func runCheckgPRC(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if err != nil {
|
||||
if stat, ok := status.FromError(err); ok && stat.Code() == codes.Unimplemented {
|
||||
logger.Info("gPRC health protocol not implemented")
|
||||
logger.Info("gRPC health protocol not implemented")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
logger.Info("check failed",
|
||||
zap.String("address", address),
|
||||
zap.Error(err))
|
||||
}
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -305,7 +396,6 @@ func runCheckgPRC(cmd *cobra.Command, args []string) error {
|
||||
logger.Info("check succeed",
|
||||
zap.String("status", resp.GetStatus().String()))
|
||||
os.Exit(0)
|
||||
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -10,6 +11,11 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"go.opentelemetry.io/contrib/bridges/otelzap"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
|
||||
sdklog "go.opentelemetry.io/otel/sdk/log"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
@@ -53,7 +59,7 @@ func main() {
|
||||
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.String("cache-server", "", "Redis address in the format 'tcp://<host>:<port>'")
|
||||
fs.String("otel-service-name", "", "service name for reporting to open telemetry address, when not set tracing is disabled")
|
||||
fs.String("otel-service-name", "", "service name for OpenTelemetry, when not set tracing and log export are disabled")
|
||||
|
||||
versionFlag := fs.BoolP("version", "v", false, "get version number")
|
||||
|
||||
@@ -93,8 +99,18 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// initialize OTel log provider if service name is set
|
||||
var loggerProvider *sdklog.LoggerProvider
|
||||
if otelServiceName := viper.GetString("otel-service-name"); otelServiceName != "" {
|
||||
var err error
|
||||
loggerProvider, err = initLoggerProvider(context.Background(), otelServiceName)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error initializing OTel log provider: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// configure logging
|
||||
logger, _ := initZap(viper.GetString("level"))
|
||||
logger, _ := initZap(viper.GetString("level"), loggerProvider)
|
||||
defer logger.Sync()
|
||||
stdLog := zap.RedirectStdLog(logger)
|
||||
defer stdLog()
|
||||
@@ -163,10 +179,29 @@ func main() {
|
||||
// graceful shutdown
|
||||
stopCh := signals.SetupSignalHandler()
|
||||
sd, _ := signals.NewShutdown(srvCfg.ServerShutdownTimeout, logger)
|
||||
sd.SetLoggerProvider(loggerProvider)
|
||||
sd.Graceful(stopCh, httpServer, httpsServer, grpcServer, healthy, ready)
|
||||
}
|
||||
|
||||
func initZap(logLevel string) (*zap.Logger, error) {
|
||||
func initLoggerProvider(ctx context.Context, serviceName string) (*sdklog.LoggerProvider, error) {
|
||||
exporter, err := otlploggrpc.New(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating OTLP log exporter: %w", err)
|
||||
}
|
||||
|
||||
provider := sdklog.NewLoggerProvider(
|
||||
sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)),
|
||||
sdklog.WithResource(resource.NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.ServiceNameKey.String(serviceName),
|
||||
semconv.ServiceVersionKey.String(version.VERSION),
|
||||
)),
|
||||
)
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
func initZap(logLevel string, loggerProvider *sdklog.LoggerProvider) (*zap.Logger, error) {
|
||||
level := zap.NewAtomicLevelAt(zapcore.InfoLevel)
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
@@ -210,7 +245,21 @@ func initZap(logLevel string) (*zap.Logger, error) {
|
||||
ErrorOutputPaths: []string{"stderr"},
|
||||
}
|
||||
|
||||
return zapConfig.Build()
|
||||
logger, err := zapConfig.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if loggerProvider != nil {
|
||||
otelCore := otelzap.NewCore("github.com/stefanprodan/podinfo",
|
||||
otelzap.WithLoggerProvider(loggerProvider),
|
||||
)
|
||||
logger = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
|
||||
return zapcore.NewTee(core, otelCore)
|
||||
}))
|
||||
}
|
||||
|
||||
return logger, nil
|
||||
}
|
||||
|
||||
var stressMemoryPayload []byte
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
2
deploy/bases/cache/deployment.yaml
vendored
2
deploy/bases/cache/deployment.yaml
vendored
@@ -13,7 +13,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: docker.io/redis:8.4.0
|
||||
image: docker.io/redis:8.6.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: backup
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: healthcheck
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: healthcheck
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /bin/sh
|
||||
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
serviceAccountName: database
|
||||
containers:
|
||||
- name: database
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: db
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
serviceAccountName: database
|
||||
containers:
|
||||
- name: database
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: db
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
serviceAccountName: webapp
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
serviceAccountName: webapp
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
50
go.mod
50
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/stefanprodan/podinfo
|
||||
|
||||
go 1.25
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/chzyer/readline v1.5.1
|
||||
@@ -16,21 +16,24 @@ require (
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/swaggo/http-swagger v1.3.4
|
||||
github.com/swaggo/swag v1.16.6
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.64.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.64.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.39.0
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.39.0
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.39.0
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.39.0
|
||||
go.opentelemetry.io/otel v1.39.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0
|
||||
go.opentelemetry.io/otel/sdk v1.39.0
|
||||
go.opentelemetry.io/otel/trace v1.39.0
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.15.0
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.65.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.65.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.40.0
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.40.0
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.40.0
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.40.0
|
||||
go.opentelemetry.io/otel v1.40.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0
|
||||
go.opentelemetry.io/otel/sdk v1.40.0
|
||||
go.opentelemetry.io/otel/sdk/log v0.16.0
|
||||
go.opentelemetry.io/otel/trace v1.40.0
|
||||
go.uber.org/zap v1.27.1
|
||||
golang.org/x/net v0.49.0
|
||||
google.golang.org/grpc v1.78.0
|
||||
golang.org/x/net v0.51.0
|
||||
google.golang.org/grpc v1.79.3
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
@@ -48,7 +51,7 @@ require (
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
@@ -66,17 +69,18 @@ require (
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/swaggo/files v1.0.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.16.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/tools v0.41.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
108
go.sum
108
go.sum
@@ -52,8 +52,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@@ -117,36 +117,48 @@ github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.64.0 h1:vwZaYp+EEiPUQD1rYKPT0vLfGD7XMv2WypO/59ySpwM=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.64.0/go.mod h1:D96L6/izMrfhIlFm1sFiyEC8zVyMcDzC8dwqUoTmGT8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.64.0 h1:OXSUzgmIFkcC4An+mv+lqqZSndTffXpjAyoR+1f8k/A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.64.0/go.mod h1:1A4GVLFIm54HFqVdOpWmukap7rgb0frrE3zWXohLPdM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ=
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.39.0 h1:IvNR8pAVGpkK1CHMjU/YE6B6TlnAPGFvogkMWRWU6wo=
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.39.0/go.mod h1:TUsFCERuGM4IGhJG9w+9l0nzmHUKHuaDYYNF6mtNgjY=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.39.0 h1:PI7pt9pkSnimWcp5sQhUA9OzLbc3Ba4sL+VEUTNsxrk=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.39.0/go.mod h1:5gV/EzPnfYIwjzj+6y8tbGW2PKWhcsz5e/7twptRVQY=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.39.0 h1:Gz3yKzfMSEFzF0Vy5eIpu9ndpo4DhXMCxsLMF0OOApo=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.39.0/go.mod h1:2D/cxxCqTlrday0rZrPujjg5aoAdqk1NaNyoXn8FJn8=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.39.0 h1:vKTve1W/WKPVp1fzJamhCDDECt+5upJJ65bPyWoddGg=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.39.0/go.mod h1:FH5VB2N19duNzh1Q8ks6CsZFyu3LFhNLiA9lPxyEkvU=
|
||||
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0/go.mod h1:Rp0EXBm5tfnv0WL+ARyO/PHBEaEAT8UUHQ6AGJcSq6c=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0/go.mod h1:MZ1T/+51uIVKlRzGw1Fo46KEWThjlCBZKl2LzY5nv4g=
|
||||
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
|
||||
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
|
||||
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
|
||||
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
|
||||
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.15.0 h1:x4qzjKkTl2hXmLl+IviSXvzaTyCJSYvpFZL5SRVLBxs=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.15.0/go.mod h1:h7dZHJgqkzUiKFXCTJBrPWH0LEZaZXBFzKWstjWBRxw=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.65.0 h1:LIMn2KWRS0jRDDHYyIEYgKWsMwufA9GXusJiwik0u64=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.65.0/go.mod h1:JwJa4o3Wq+4Yz2BjlYFGWyx2h0Fw1lnoj5kpsaTI97o=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.65.0 h1:ab5U7DpTjjN8pNgwqlA/s0Csb+N2Raqo9eTSDhfg4Z8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.65.0/go.mod h1:nwFJC46Dxhqz5R9k7IV8To/Z46JPvW+GNKhTxQQlUzg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.40.0 h1:4VIrh75jW4RTimUNx1DSk+6H9/nDr1FvmKoOVDh3K04=
|
||||
go.opentelemetry.io/contrib/propagators/aws v1.40.0/go.mod h1:B0dCov9KNQGlut3T8wZZjDnLXEXdBroM7bFsHh/gRos=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.40.0 h1:xariChe8OOVF3rNlfzGFgQc61npQmXhzZj/i82mxMfg=
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.40.0/go.mod h1:72WvbdxbOfXaELEQfonFfOL6osvcVjI7uJEE8C2nkrs=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.40.0 h1:aXl9uobjJs5vquMLt9ZkI/3zIuz8XQ3TqOKSWx0/xdU=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.40.0/go.mod h1:ioMePqe6k6c/ovXSkmkMr1mbN5qRBGJxNTVop7/2XO0=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.40.0 h1:Lon8J5SPmWaL1Ko2TIlCNHJ42/J1b5XbJlgJaE/9m7I=
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.40.0/go.mod h1:dKWtJTlp1Yj+8Cneye5idO46eRPIbi23qVuJYKjNnvY=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0 h1:ZVg+kCXxd9LtAaQNKBxAvJ5NpMf7LpvEr4MIZqb0TMQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.16.0/go.mod h1:hh0tMeZ75CCXrHd9OXRYxTlCAdxcXioWHFIpYw2rZu8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 h1:MzfofMZN8ulNqobCmCAVbqVL5syHw+eB2qPRkCMA/fQ=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0/go.mod h1:E73G9UFtKRXrxhBsHtG00TB5WxX57lpsQzogDkqBTz8=
|
||||
go.opentelemetry.io/otel/log v0.16.0 h1:DeuBPqCi6pQwtCK0pO4fvMB5eBq6sNxEnuTs88pjsN4=
|
||||
go.opentelemetry.io/otel/log v0.16.0/go.mod h1:rWsmqNVTLIA8UnwYVOItjyEZDbKIkMxdQunsIhpUMes=
|
||||
go.opentelemetry.io/otel/log/logtest v0.16.0 h1:jr1CG3Z6FD9pwUaL/D0s0X4lY2ZVm1jP3JfCtzGxUmE=
|
||||
go.opentelemetry.io/otel/log/logtest v0.16.0/go.mod h1:qeeZw+cI/rAtCzZ03Kq1ozq6C4z/PCa+K+bb0eJfKNs=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/log v0.16.0 h1:e/b4bdlQwC5fnGtG3dlXUrNOnP7c8YLVSpSfEBIkTnI=
|
||||
go.opentelemetry.io/otel/sdk/log v0.16.0/go.mod h1:JKfP3T6ycy7QEuv3Hj8oKDy7KItrEkus8XJE6EoSzw4=
|
||||
go.opentelemetry.io/otel/sdk/log/logtest v0.16.0 h1:/XVkpZ41rVRTP4DfMgYv1nEtNmf65XPPyAdqV90TMy4=
|
||||
go.opentelemetry.io/otel/sdk/log/logtest v0.16.0/go.mod h1:iOOPgQr5MY9oac/F5W86mXdeyWZGleIx3uXO98X2R6Y=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -162,14 +174,14 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
@@ -182,8 +194,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -191,22 +203,22 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: ghcr.io/stefanprodan/podinfo:6.10.0
|
||||
image: ghcr.io/stefanprodan/podinfo:6.11.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -1,27 +1,34 @@
|
||||
# Tracing Demo
|
||||
# Tracing & Logging Demo
|
||||
|
||||
The directory contains sample [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector)
|
||||
and [Jaeger](https://www.jaegertracing.io) configurations for a tracing demo.
|
||||
and [Jaeger](https://www.jaegertracing.io) / [Loki](https://grafana.com/oss/loki/) configurations for a tracing and logging demo.
|
||||
|
||||
## Configuration
|
||||
|
||||
The provided [docker-compose.yaml](docker-compose.yaml) sets up 4 Containers
|
||||
The provided [docker-compose.yaml](docker-compose.yaml) sets up 6 containers:
|
||||
|
||||
1. PodInfo Frontend on port 9898
|
||||
2. PodInfo Backend on port 9899
|
||||
3. OpenTelemetry Collector listening on port 4317 for GRPC
|
||||
4. Jaeger all-in-one listening on multiple ports
|
||||
4. Jaeger all-in-one with UI on port 16686
|
||||
5. Loki on port 3100
|
||||
6. Grafana on port 3000
|
||||
|
||||
## How does it work?
|
||||
|
||||
The frontend pods are configured to call onto the backend pods. Both the podinfo
|
||||
pods are configured to send traces over to the collector at port 4317 using GRPC.
|
||||
The collector forwards all received spans to Jaeger over port 14250 and Jaeger
|
||||
exposes a UI over port `16686`.
|
||||
The frontend pod is configured to call the backend pod. Both podinfo pods send traces
|
||||
and logs to the collector at port 4317 using OTLP gRPC.
|
||||
|
||||
The collector forwards:
|
||||
- **Traces** to Jaeger via OTLP gRPC on port 4317
|
||||
- **Logs** to Loki via OTLP HTTP on port 3100
|
||||
|
||||
Jaeger exposes its UI on port `16686`. Grafana exposes its UI on port `3000` and is
|
||||
pre-configured with both Jaeger and Loki as datasources.
|
||||
|
||||
## Running it locally
|
||||
|
||||
1. Start all the Containers
|
||||
1. Start all the containers
|
||||
```shell
|
||||
make run
|
||||
```
|
||||
@@ -30,8 +37,9 @@ make run
|
||||
curl -v http://localhost:9898/status/200
|
||||
curl -X POST -v http://localhost:9898/api/echo
|
||||
```
|
||||
3. Visit `http://localhost:16686/` to see the spans
|
||||
4. Stop all the containers
|
||||
3. Visit `http://localhost:16686/` to see traces in Jaeger
|
||||
4. Visit `http://localhost:3000/` to explore logs in Grafana (Explore → Loki) and traces (Explore → Jaeger)
|
||||
5. Stop all the containers
|
||||
```shell
|
||||
make stop
|
||||
```
|
||||
|
||||
@@ -5,31 +5,38 @@ services:
|
||||
build: ..
|
||||
command: ./podinfo --backend-url http://podinfo_backend:9899/status/200 --otel-service-name=podinfo_frontend
|
||||
environment:
|
||||
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://otel:4317
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel:4317
|
||||
ports:
|
||||
- "9898:9898"
|
||||
podinfo_backend:
|
||||
build: ..
|
||||
command: ./podinfo --port 9899 --otel-service-name=podinfo_backend
|
||||
environment:
|
||||
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://otel:4317
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel:4317
|
||||
ports:
|
||||
- "9899:9899"
|
||||
otel:
|
||||
command: --config otel-config.yaml
|
||||
image: otel/opentelemetry-collector:0.41.0
|
||||
image: otel/opentelemetry-collector-contrib:0.116.1
|
||||
ports:
|
||||
- "4317:4317"
|
||||
volumes:
|
||||
- ${PWD}/otel-config.yaml:/otel-config.yaml
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.29.0
|
||||
loki:
|
||||
image: grafana/loki:3.0.0
|
||||
ports:
|
||||
- "3100:3100"
|
||||
command: -config.file=/etc/loki/local-config.yaml
|
||||
grafana:
|
||||
image: grafana/grafana:10.4.0
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||
volumes:
|
||||
- ${PWD}/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.57.0
|
||||
ports:
|
||||
- "5775:5775/udp"
|
||||
- "6831:6831/udp"
|
||||
- "6832:6832/udp"
|
||||
- "5778:5778"
|
||||
- "16686:16686"
|
||||
- "14268:14268"
|
||||
- "14250:14250"
|
||||
- "9411:9411"
|
||||
|
||||
10
otel/grafana-datasources.yaml
Normal file
10
otel/grafana-datasources.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Loki
|
||||
type: loki
|
||||
url: http://loki:3100
|
||||
isDefault: true
|
||||
- name: Jaeger
|
||||
type: jaeger
|
||||
url: http://jaeger:16686
|
||||
@@ -2,15 +2,18 @@ receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
|
||||
processors:
|
||||
|
||||
exporters:
|
||||
jaeger:
|
||||
endpoint: jaeger:14250
|
||||
otlp/jaeger:
|
||||
endpoint: jaeger:4317
|
||||
tls:
|
||||
insecure: true
|
||||
otlphttp/loki:
|
||||
endpoint: http://loki:3100/otlp
|
||||
|
||||
extensions:
|
||||
health_check:
|
||||
@@ -23,4 +26,8 @@ service:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: []
|
||||
exporters: [jaeger]
|
||||
exporters: [otlp/jaeger]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: []
|
||||
exporters: [otlphttp/loki]
|
||||
|
||||
@@ -7,11 +7,14 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var validHash = regexp.MustCompile(`^[a-f0-9]{40}$`)
|
||||
|
||||
// Store godoc
|
||||
// @Summary Upload file
|
||||
// @Description writes the posted content to disk at /data/hash and returns the SHA1 hash of the content
|
||||
@@ -54,12 +57,19 @@ func (s *Server) storeReadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defer span.End()
|
||||
|
||||
hash := mux.Vars(r)["hash"]
|
||||
if !validHash.MatchString(hash) {
|
||||
s.ErrorResponse(w, r, span, "invalid hash", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
content, err := os.ReadFile(path.Join(s.config.DataPath, hash))
|
||||
if err != nil {
|
||||
s.logger.Warn("reading file failed", zap.Error(err), zap.String("file", path.Join(s.config.DataPath, hash)))
|
||||
s.ErrorResponse(w, r, span, "reading file failed", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'none'")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
w.Write([]byte(content))
|
||||
}
|
||||
|
||||
82
pkg/api/http/store_test.go
Normal file
82
pkg/api/http/store_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func TestStoreReadHandler_ContentType(t *testing.T) {
|
||||
dataDir := t.TempDir()
|
||||
srv := NewMockServer()
|
||||
srv.config.DataPath = dataDir
|
||||
|
||||
// Write an HTML payload to the store.
|
||||
writeReq, err := http.NewRequest("POST", "/store", strings.NewReader("<html><script>alert(1)</script></html>"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
writeRR := httptest.NewRecorder()
|
||||
http.HandlerFunc(srv.storeWriteHandler).ServeHTTP(writeRR, writeReq)
|
||||
|
||||
if writeRR.Code != http.StatusAccepted {
|
||||
t.Fatalf("store write returned status %d, want %d", writeRR.Code, http.StatusAccepted)
|
||||
}
|
||||
|
||||
// Read it back and verify Content-Type is application/octet-stream, not text/html.
|
||||
hash := hash("<html><script>alert(1)</script></html>")
|
||||
readReq, err := http.NewRequest("GET", "/store/"+hash, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
readReq = mux.SetURLVars(readReq, map[string]string{"hash": hash})
|
||||
|
||||
readRR := httptest.NewRecorder()
|
||||
http.HandlerFunc(srv.storeReadHandler).ServeHTTP(readRR, readReq)
|
||||
|
||||
if readRR.Code != http.StatusAccepted {
|
||||
t.Fatalf("store read returned status %d, want %d", readRR.Code, http.StatusAccepted)
|
||||
}
|
||||
|
||||
expectedHeaders := map[string]string{
|
||||
"Content-Type": "application/octet-stream",
|
||||
"X-Content-Type-Options": "nosniff",
|
||||
"Content-Security-Policy": "default-src 'none'",
|
||||
}
|
||||
for header, want := range expectedHeaders {
|
||||
if got := readRR.Header().Get(header); got != want {
|
||||
t.Errorf("%s = %q, want %q", header, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreReadHandler_PathTraversal(t *testing.T) {
|
||||
srv := NewMockServer()
|
||||
srv.config.DataPath = t.TempDir()
|
||||
|
||||
traversalPaths := []string{
|
||||
"../../../../etc/passwd",
|
||||
"../../../etc/shadow",
|
||||
"..%2f..%2f..%2fetc%2fpasswd",
|
||||
"abc123",
|
||||
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzg", // 40 chars but not hex
|
||||
}
|
||||
|
||||
for _, tp := range traversalPaths {
|
||||
req, err := http.NewRequest("GET", "/store/"+tp, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req = mux.SetURLVars(req, map[string]string{"hash": tp})
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
http.HandlerFunc(srv.storeReadHandler).ServeHTTP(rr, req)
|
||||
|
||||
if !strings.Contains(rr.Body.String(), "invalid hash") {
|
||||
t.Errorf("path %q: expected 'invalid hash' error, got %q", tp, rr.Body.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/spf13/viper"
|
||||
sdklog "go.opentelemetry.io/otel/sdk/log"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
@@ -17,9 +18,14 @@ type Shutdown struct {
|
||||
logger *zap.Logger
|
||||
pool *redis.Pool
|
||||
tracerProvider *sdktrace.TracerProvider
|
||||
loggerProvider *sdklog.LoggerProvider
|
||||
serverShutdownTimeout time.Duration
|
||||
}
|
||||
|
||||
func (s *Shutdown) SetLoggerProvider(lp *sdklog.LoggerProvider) {
|
||||
s.loggerProvider = lp
|
||||
}
|
||||
|
||||
func NewShutdown(serverShutdownTimeout time.Duration, logger *zap.Logger) (*Shutdown, error) {
|
||||
srv := &Shutdown{
|
||||
logger: logger,
|
||||
@@ -62,6 +68,13 @@ func (s *Shutdown) Graceful(stopCh <-chan struct{}, httpServer *http.Server, htt
|
||||
}
|
||||
}
|
||||
|
||||
// stop OpenTelemetry logger provider
|
||||
if s.loggerProvider != nil {
|
||||
if err := s.loggerProvider.Shutdown(ctx); err != nil {
|
||||
s.logger.Warn("stopping logger provider", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// determine if the GRPC was started
|
||||
if grpcServer != nil {
|
||||
s.logger.Info("Shutting down GRPC server", zap.Duration("timeout", s.serverShutdownTimeout))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
var VERSION = "6.10.0"
|
||||
var VERSION = "6.11.2"
|
||||
var REVISION = "unknown"
|
||||
|
||||
@@ -26,4 +26,5 @@ helm upgrade --install podinfo ./charts/podinfo \
|
||||
--set certificate.create=true \
|
||||
--set hpa.enabled=true \
|
||||
--set hpa.cpu=95 \
|
||||
--set hooks.postInstall.job.enabled=true \
|
||||
--namespace=default
|
||||
|
||||
@@ -9,7 +9,7 @@ package main
|
||||
values: {
|
||||
image: {
|
||||
repository: "ghcr.io/stefanprodan/podinfo"
|
||||
tag: "6.10.0"
|
||||
tag: "6.11.2"
|
||||
digest: ""
|
||||
}
|
||||
test: image: {
|
||||
|
||||
Reference in New Issue
Block a user