Compare commits

...

236 Commits
6.1.0 ... 6.6.0

Author SHA1 Message Date
Stefan Prodan
357009a863 Sign only GHCR artifacts with Notation
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-02-26 14:00:22 +02:00
Stefan Prodan
0f98770296 Split signature actions
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-02-26 13:27:46 +02:00
Stefan Prodan
f9032836a6 Merge pull request #343 from stefanprodan/release-6.6.0
Release v6.6.0
2024-02-26 12:17:54 +02:00
Stefan Prodan
5368c3fe10 Release v6.6.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-02-26 12:15:05 +02:00
Stefan Prodan
b1207aa9b1 Merge pull request #341 from JasonTheDeveloper/feat/notation
feat(notation): sign artifacts using notation
2024-02-26 11:58:49 +02:00
Jason
c7f9b521fa ci(notation): install 1.1.0
Signed-off-by: Jason <jagoodse@microsoft.com>
2024-02-26 20:40:03 +11:00
Stefan Prodan
24405a5a5d Setup notation signing keys
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-02-25 12:12:22 +02:00
Stefan Prodan
5195b158fc Merge pull request #334 from michaelkebe/patch-1
Fixes /store endpoint with the kustomize deployment
2024-02-25 11:31:44 +02:00
Stefan Prodan
532db405f8 Merge pull request #322 from JayKaku/feature/grpc-version-echo-apis
Implement gRPC for `echo` and `version` APIs
2024-02-25 11:30:59 +02:00
JayKaku
2251bee699 Fixed parsing logger in echo_test.go service registeration 2024-02-24 23:44:12 +05:30
JayKaku
8535efccb7 Implemented zap logger in place of log | gprc echo 2024-02-24 23:44:12 +05:30
JayKaku
e008d1f261 Added config, logger for grpc echo api 2024-02-24 23:44:12 +05:30
Jay Kaku
22097353d2 Feature grpc version echo api (#3)
added grpc verion and echo apis

---------

Co-authored-by: Prashant Dwivedi <prashantdwivedi194@gmail.com>
2024-02-24 23:44:12 +05:30
JayKaku
c305843105 restructured api to api/http, api/grpc, pkg http 2024-02-24 23:44:12 +05:30
Jason
0d2c428859 refactor(trustpolicy): jasonthedeveloper -> stefanprodan 2024-02-09 10:59:44 +11:00
Jason
ecaa7cf4d3 ci(release): trigger on tag push 2024-02-09 10:47:11 +11:00
Jason
8447b6985b ci(notation): remove release workflow 2024-02-09 10:42:51 +11:00
Jason
9371d6d153 ci(release): sign artefacts using notation 2024-02-09 10:41:19 +11:00
Jason
20b8c1043c Merge branch 'master' into feat/notation 2024-02-09 10:14:38 +11:00
Michael Kebe
2d80c7a22d added /data to kustomize deployment
Added an emptyDir to the kustomzie deployment, otherwise the /store endpoint does not work for storing files.
2024-01-10 09:44:12 +01:00
Stefan Prodan
dc830d02a6 Enable GitHub Sponsors 2023-12-30 22:18:54 +02:00
Stefan Prodan
badf3271a1 Merge pull request #332 from arunsathiya/master
ci: Use `GITHUB_OUTPUT` instead of set-output
2023-12-29 00:11:06 +02:00
Arun
9f9c2f3245 Use GITHUB_OUTPUT envvar instead of set-output command as the latter is deprecated 2023-12-28 13:21:55 -08:00
Stefan Prodan
33dac1ba40 Merge pull request #329 from stefanprodan/release-6.5.4
Release 6.5.4
2023-12-17 16:44:12 +02:00
Stefan Prodan
1cf8b8aeef Release 6.5.4
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-12-17 16:36:33 +02:00
Stefan Prodan
22fb1c3d34 Merge pull request #328 from stefanprodan/timoni-schemas-update
Update Timoni CUE schemas
2023-12-17 16:34:38 +02:00
Stefan Prodan
adf8157da6 Update Timoni CUE schemas
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-12-17 15:53:22 +02:00
Stefan Prodan
03f8ad0251 Merge pull request #327 from stefanprodan/up-deps
Update Go dependencies
2023-12-17 15:18:23 +02:00
Stefan Prodan
101e371e96 Update Go dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-12-17 15:14:43 +02:00
Stefan Prodan
53c9f3ad9b Merge pull request #326 from stefanprodan/alpine-3.19
Update Alpine to 3.19
2023-12-17 15:10:30 +02:00
Stefan Prodan
a69f0282fd Update Alpine to 3.19
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-12-17 15:07:34 +02:00
Jason
174d183056 refactor(rename): policy.json -> trustpolicy.json 2023-12-14 16:16:12 +11:00
Jason
7bb64e7567 fix(trustpolicy): small typo in registryScopes 2023-12-08 17:30:47 +11:00
Jason
49a4b31d53 feat(notation): update registry scopes 2023-12-07 18:06:52 +11:00
Jason
c29e013a33 feat(notation): add trust store policy 2023-12-07 16:57:04 +11:00
Jason
45ecda63bb ci(release): don't trigger on tag push 2023-12-07 16:26:01 +11:00
Jason
4868f430c7 ci(release): trigger on tag 2023-12-07 16:15:17 +11:00
Jason
ca9c6bb4f8 ci(release): sign artefacts using notaiton 2023-12-07 16:06:40 +11:00
Jason
86f3b1a57c ci(release): create notation config folder 2023-12-07 15:52:29 +11:00
Jason
b22dd96a54 feat(notation): add signingkey.json config 2023-12-07 15:51:22 +11:00
Jason
5aaf95849e ci(release): setup signing keys for notation 2023-12-07 15:50:30 +11:00
Jason
e197eca420 ci(release): add notation release workflow 2023-12-07 15:46:22 +11:00
Stefan Prodan
73fcdbe4a6 Merge pull request #320 from duxinxiao/patch-1
Add comment on sleep during graceful shutdown
2023-11-15 13:32:44 +02:00
du
074d0f9ff2 add comment on sleep during graceful shutdown 2023-11-15 18:47:52 +08:00
Stefan Prodan
d9bc6301e9 Merge pull request #316 from stefanprodan/release-6.5.3
Release 6.5.3
2023-10-30 14:38:28 +02:00
Stefan Prodan
a0e323e331 Release 6.5.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 14:27:41 +02:00
Stefan Prodan
1ee349fa17 Merge pull request #315 from stefanprodan/timoni-tests
timoni: Add connectivity test to module
2023-10-30 14:25:12 +02:00
Stefan Prodan
0f526c3cd4 timoni: Run module tests in CI
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 14:11:41 +02:00
Stefan Prodan
021c55fed9 timoni: Add connectivity test to module
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 14:10:25 +02:00
Stefan Prodan
bb2408d17d Merge pull request #314 from stefanprodan/timoni-vet-module
timoni: Add debug values and vet module in CI
2023-10-30 12:56:48 +02:00
Stefan Prodan
5eb3cafd6a timoni: Vet module in CI
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 12:51:28 +02:00
Stefan Prodan
df0f8ba885 timoni: Add debug values
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 12:51:03 +02:00
Stefan Prodan
19a59d96f1 timoni: Update module schemas
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 12:41:21 +02:00
Stefan Prodan
401461595a Merge pull request #313 from stefanprodan/docs-cosign-verify
docs: Verify podinfo release assets with cosign
2023-10-30 12:32:21 +02:00
Stefan Prodan
bd77584ade docs: Verify podinfo release assets with cosign
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-30 12:28:21 +02:00
Stefan Prodan
87e0dbaa7e Merge pull request #312 from stefanprodan/dependabot/go_modules/google.golang.org/grpc-1.58.3
Bump google.golang.org/grpc from 1.58.2 to 1.58.3
2023-10-26 00:38:00 +03:00
dependabot[bot]
c5494104a1 Bump google.golang.org/grpc from 1.58.2 to 1.58.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.58.2 to 1.58.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.58.2...v1.58.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 21:27:33 +00:00
Stefan Prodan
74c60a927c Merge pull request #310 from stefanprodan/release-6.5.2
Release 6.5.2
2023-10-12 12:18:47 +03:00
Stefan Prodan
ecdf07c4d5 Release 6.5.2
Fix for CVE-2023-39325 and CVE-2023-38545

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-12 12:11:37 +03:00
Stefan Prodan
ff29c549ff Merge pull request #309 from stefanprodan/dependabot/go_modules/golang.org/x/net-0.17.0
Bump golang.org/x/net from 0.15.0 to 0.17.0
2023-10-12 09:24:03 +03:00
dependabot[bot]
fa75fc0520 Bump golang.org/x/net from 0.15.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.15.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.15.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 23:14:03 +00:00
Stefan Prodan
0bc496456d Merge pull request #307 from stefanprodan/release-6.5.1
Release 6.5.1
2023-10-02 21:04:32 +03:00
Stefan Prodan
398c543171 Release 6.5.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-02 20:58:27 +03:00
Stefan Prodan
a54dc2a9c7 Merge pull request #306 from stefanprodan/update-otel-deps
Update Go dependencies
2023-10-02 20:57:13 +03:00
Stefan Prodan
bfa42afa1f Bump Go to 1.21
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-02 20:46:06 +03:00
Stefan Prodan
590987704e Update open telemetry packages
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-02 20:45:20 +03:00
Stefan Prodan
d561182076 Merge pull request #305 from stefanprodan/timoni-v0.14
Update module to Timoni v0.14 APIs
2023-10-02 20:41:06 +03:00
Stefan Prodan
72bd6faf35 Update module to Timoni v0.14 APIs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-10-02 20:36:58 +03:00
Stefan Prodan
2cbe0fcdff Merge pull request #304 from stefanprodan/release-6.5.0
Release v6.5.0
2023-09-23 12:35:00 +03:00
Stefan Prodan
87e594b109 Release 6.5.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 12:29:59 +03:00
Stefan Prodan
7ec9e6c84a Merge pull request #303 from stefanprodan/publish-timoni-module
Publish signed Timoni module to GHCR
2023-09-23 12:22:06 +03:00
Stefan Prodan
8183d0d5fc Publish signed Timoni module to GHCR
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 12:16:48 +03:00
Stefan Prodan
aa27416651 Merge pull request #302 from stefanprodan/module-imps
Timoni module improvements
2023-09-23 11:35:47 +03:00
Stefan Prodan
b0594a85b9 Add e2e tests for Timoni module
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 11:29:47 +03:00
Stefan Prodan
e816d1b5bc Add UI configuration
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 10:04:56 +03:00
Stefan Prodan
6316e213d1 Improve monitoring config
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 09:25:25 +03:00
Stefan Prodan
a1b112f4e1 Mark vendored code
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 00:43:20 +03:00
Stefan Prodan
1495fd888e Merge pull request #301 from stefanprodan/timoni-module
Add Timoni module
2023-09-23 00:37:48 +03:00
Stefan Prodan
dfc4a6d37e Add Timoni module
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-23 00:33:36 +03:00
Stefan Prodan
aaa47e535f Merge pull request #300 from stefanprodan/up-deps
Update dependencies
2023-09-22 23:29:36 +03:00
Stefan Prodan
0278e11a05 Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-09-22 23:24:32 +03:00
Stefan Prodan
12ceae475f Merge pull request #284 from johankok/add-additional-labels-to-ingress
Added additionalLabels option for ingress in helm chart
2023-09-22 23:13:11 +03:00
Stefan Prodan
4892983fd1 Merge pull request #290 from stefanprodan/release-6.4.1
Release v6.4.1
2023-08-10 15:25:19 +03:00
Stefan Prodan
bcf492e92b Release v6.4.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-08-10 15:10:01 +03:00
Stefan Prodan
a54550e439 Merge pull request #289 from stefanprodan/go-1.21
Build with Go 1.21
2023-08-10 15:08:37 +03:00
Stefan Prodan
29dd482f49 Build with Go 1.21
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-08-10 15:04:03 +03:00
Stefan Prodan
3a7d4d1544 Merge pull request #285 from stefanprodan/up-deps
Update dependencies
2023-08-10 14:59:18 +03:00
Stefan Prodan
c14b116dea Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-08-07 16:20:42 +03:00
Johan Kok
12c078938d Added additionalLabels option for ingress 2023-07-17 17:50:42 +02:00
Stefan Prodan
dd3869b1a1 Merge pull request #274 from stefanprodan/alpine-3.18
Update base image to Alpine 3.18
2023-06-26 13:02:18 +03:00
Stefan Prodan
45cfe3abc2 Update base image to Alpine 3.18
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-06-26 12:57:54 +03:00
Stefan Prodan
fcf573111b Merge pull request #273 from stefanprodan/release-6.4.0
Release 6.4.0
2023-06-26 12:55:42 +03:00
Stefan Prodan
cadabcc6a5 Release 6.4.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-06-26 12:50:40 +03:00
Stefan Prodan
9dfb676083 Sign release tags with OpenPGP
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-06-26 12:49:33 +03:00
Stefan Prodan
e06a5517da Merge pull request #272 from stefanprodan/deps-up
Update dependencies
2023-06-22 18:51:41 +03:00
Stefan Prodan
fedab0de38 Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-06-22 18:36:47 +03:00
Stefan Prodan
7d13025a35 Merge pull request #271 from jjchambl/feature/add_dynamic_paths
feat(echo): add dynamic path support for echo endpoint
2023-06-22 18:30:00 +03:00
Jacob Chambliss
7280e43cbf chore: add pathprefix to enable dynamic paths for echo 2023-06-08 10:14:21 -05:00
Jacob Chambliss
3ef0b4cd09 feat: add dynamic path support for echo endpoint 2023-06-07 16:55:25 -05:00
Stefan Prodan
073f1ec5af Merge pull request #265 from stefanprodan/release-6.3.6
Release 6.3.6
2023-05-03 17:26:29 +03:00
Stefan Prodan
1e0307c759 Release 6.3.6
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-05-03 17:22:28 +03:00
Stefan Prodan
d4d75c2fbf Merge pull request #264 from stefanprodan/update-otel
Update dependencies
2023-05-03 17:10:32 +03:00
Stefan Prodan
2a6533c68a Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-05-03 17:00:48 +03:00
Stefan Prodan
0647aea75b Merge pull request #263 from mstiri/feature/add-startup-probe
chart: Add optional startupProbe values
2023-04-22 14:37:35 +02:00
Mossaab Stiri
8c258bb1d8 Add startupProbe for deployment and use a flag to enable/disable it 2023-04-18 13:20:47 +02:00
Stefan Prodan
58726f0bd2 Merge pull request #262 from stefanprodan/update-deps
Update dependencies
2023-04-06 11:21:52 +03:00
Stefan Prodan
bc08542ed3 Generate CUE go.mod in CI
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-04-06 11:18:03 +03:00
Stefan Prodan
bbce3f3f67 Update dependencies
- github.com/spf13/cobra v1.7.0
- github.com/swaggo/http-swagger v1.3.4
- github.com/swaggo/swag v1.8.12
- google.golang.org/grpc v1.54.0

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-04-06 10:35:43 +03:00
Stefan Prodan
67e2c98a60 Merge pull request #260 from stefanprodan/cosign-update
Update sigstore/cosign-installer to v3
2023-03-09 11:07:16 +02:00
Stefan Prodan
938b00be6d Update sigstore/cosign-installer to v3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-03-09 11:01:32 +02:00
Stefan Prodan
e6c7657155 Merge pull request #259 from stefanprodan/release-6.3.5
Release 6.3.5
2023-03-09 10:47:40 +02:00
Stefan Prodan
d75e8d7838 Release 6.3.5
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-03-09 10:42:52 +02:00
Stefan Prodan
74d6532429 Merge pull request #258 from stefanprodan/otel-updates
Update open telemetry dependencies
2023-03-09 10:41:49 +02:00
Stefan Prodan
8187f79475 Update open telemetry dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-03-09 10:37:39 +02:00
Stefan Prodan
2b6f4f0a7d Merge pull request #257 from hiddeco/update-autoscaling-apis
Update `autoscaling/v2beta2` to `autoscaling/v2`
2023-03-09 10:30:04 +02:00
Hidde Beydals
3a4a99697b Update autoscaling/v2beta2 to autoscaling/v2
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
2023-03-09 09:23:00 +01:00
Stefan Prodan
1abc44f0d8 Merge pull request #254 from stefanprodan/release-6.3.4
Release v6.3.4
2023-02-21 10:49:33 +02:00
Stefan Prodan
3d798af827 Release v6.3.4
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-21 10:44:37 +02:00
Stefan Prodan
f8f8073946 Merge pull request #253 from stefanprodan/update-deps-xnet
Update dependencies
2023-02-21 10:41:42 +02:00
Stefan Prodan
c8c7a6d1bb Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-21 10:37:19 +02:00
Stefan Prodan
eac008b339 Merge pull request #249 from exfly/be-fix-stress-typo
Fix beginStressTest memory log typo
2023-02-05 13:45:00 +02:00
exfly
d2227a4204 Fix beginStressTest memory log typo 2023-02-05 13:03:04 +08:00
Stefan Prodan
ae3fe3da98 Merge pull request #247 from stefanprodan/release-6.3.3
Release v6.3.3
2023-02-03 13:08:33 +02:00
Stefan Prodan
42fdaf8e7a Release v6.3.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 13:01:30 +02:00
Stefan Prodan
3e2d907993 Merge pull request #246 from stefanprodan/go-1.20
build: Update Go to 1.20
2023-02-03 12:57:39 +02:00
Stefan Prodan
21136b6405 build: Update Go to 1.20
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 12:45:46 +02:00
Stefan Prodan
e8c388a3fd Merge pull request #245 from stefanprodan/release-6.3.2
Release v6.3.3
2023-02-03 12:28:34 +02:00
Stefan Prodan
abc38e1bff Release v6.3.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 12:25:11 +02:00
Stefan Prodan
bf4a3140fe Merge pull request #244 from stefanprodan/slsa-sbom
build: Enable SBOM and SLSA Provenance
2023-02-03 12:23:00 +02:00
Stefan Prodan
de2dd687cb build: Enable SBOM and SLSA Provenance
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 12:19:26 +02:00
Stefan Prodan
f7a9563986 Merge pull request #243 from stefanprodan/release-6.3.1
Release v6.3.1
2023-02-03 11:52:05 +02:00
Stefan Prodan
a699fffe7b Release v6.3.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 11:47:55 +02:00
Stefan Prodan
24e5de8934 Merge pull request #242 from stefanprodan/golang-jwt
Update dependencies
2023-02-03 11:46:53 +02:00
Stefan Prodan
298c1ae941 Update dependencies
- Replace `dgrijalva/jwt-go` with `golang-jwt/jwt`
- Replace `ioutil` with `io` and `os`

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2023-02-03 11:42:17 +02:00
Stefan Prodan
fdd0a0b7da Merge pull request #240 from stefanprodan/kubeconform
Validate manifests with kubeconform
2022-12-23 13:28:18 +02:00
Stefan Prodan
8bab17843c Validate manifests with kubeconform
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-23 13:23:24 +02:00
Stefan Prodan
34c5ab57b6 Merge pull request #239 from stefanprodan/cue-hpa-v2
Update HPA to v2 in CUE definitions
2022-12-23 12:30:23 +02:00
Stefan Prodan
0f9c989b68 Update HPA to v2 in CUE definitions
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-23 12:18:50 +02:00
Stefan Prodan
e2e85a9604 Merge pull request #238 from stefanprodan/release-v6.3.0
Release v6.3.0
2022-12-21 12:58:20 +02:00
Stefan Prodan
b687d3c76f Update Alpine to v3.17
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 12:53:43 +02:00
Stefan Prodan
dbbb415194 Release v6.3.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 12:50:25 +02:00
Stefan Prodan
1a89d81ebb Merge pull request #237 from stefanprodan/hpa-v2
Update HPA to autoscaling/v2
2022-12-21 12:43:55 +02:00
Stefan Prodan
b39526ebe8 Set Kubernetes 1.23.0 as the minimum required version
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 12:33:47 +02:00
Stefan Prodan
607303dca9 Update HPA to autoscaling/v2
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 12:07:31 +02:00
Stefan Prodan
3053e634f9 Merge pull request #236 from stefanprodan/update-workflows
Update GitHub workflows
2022-12-21 12:00:59 +02:00
Stefan Prodan
4f1e56ae83 Update GitHub workflows
- replace `engineerd/setup-kind` with `helm/kind-action`
- use  `azure/setup-helm` to install the Helm CLI

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 11:55:36 +02:00
Stefan Prodan
f0590a03e0 Merge pull request #235 from stefanprodan/update-x/net
Update dependencies
2022-12-21 11:23:32 +02:00
Stefan Prodan
aa815625d9 Update dependencies
Fix for golang.org/x/net CVEs

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-12-21 11:18:30 +02:00
Stefan Prodan
8615cb75d9 Merge pull request #233 from stefanprodan/release-6.2.3
Release v6.2.3
2022-11-09 13:17:16 +02:00
Stefan Prodan
b23ebb15cb Release v6.2.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-11-09 13:12:30 +02:00
Stefan Prodan
dcb5b13023 Merge pull request #232 from stefanprodan/deps-update
Update dependencies
2022-11-09 13:10:23 +02:00
Stefan Prodan
71869089fa Update dependencies
- github.com/prometheus/client_golang v1.14.0
- github.com/spf13/cobra v1.6.1
- github.com/spf13/viper v1.14.0
- go.opentelemetry.io/contrib/propagators/ot v1.11.1
- golang.org/x/net v0.2.0

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-11-09 12:59:22 +02:00
Stefan Prodan
1cf228c67b Merge pull request #228 from stefanprodan/release-6.2.2
Release 6.2.2
2022-10-20 12:25:15 +03:00
Stefan Prodan
b6e81a931b Release 6.2.2
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-10-20 12:12:44 +03:00
Stefan Prodan
744597a481 Merge pull request #227 from stefanprodan/deps-up
Update dependencies
2022-10-20 12:05:40 +03:00
Stefan Prodan
389c86ee93 Update dependencies
Fix CVE-2022-32149 of `golang.org/x/text`

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-10-20 12:00:33 +03:00
Stefan Prodan
34db5fa463 Merge pull request #226 from cv65kr/feat/graceful-shutdown
Enable graceful shutdown for gRPC server
2022-10-20 11:48:43 +03:00
Kajetan
0d62402ae9 Graceful shutdown 2022-10-18 17:31:51 +02:00
Stefan Prodan
e40d32ba87 Merge pull request #224 from jkremser/helm-probes
Add a way to customize liveness and readiness probes in helm chart
2022-10-06 15:17:54 +02:00
Jirka Kremser
3879b59f43 Add a way to customize liveness and readiness probes in helm chart
Signed-off-by: Jirka Kremser <jiri.kremser@gmail.com>
2022-10-03 17:36:14 +02:00
Stefan Prodan
44157ecd84 Merge pull request #222 from stefanprodan/release-6.2.1
Release 6.2.1
2022-09-29 12:54:45 +03:00
Stefan Prodan
bfa8d8032f Release 6.2.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-09-29 12:49:43 +03:00
Stefan Prodan
b1251214f6 Merge pull request #221 from stefanprodan/update-golang.org/x/net
Update dependencies
2022-09-29 12:41:38 +03:00
Stefan Prodan
f1168c4946 Update dependencies
Fix for golang.org/x/net CVE-2022-27664

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-09-29 12:36:35 +03:00
Stefan Prodan
013343a232 Merge pull request #220 from stefanprodan/go1.19
Build with Go 1.19
2022-09-29 12:31:39 +03:00
Stefan Prodan
d460863f3b Merge pull request #217 from Boojapho/imagepullsecret
feat(helm): added imagepullsecrets
2022-09-29 12:31:26 +03:00
Stefan Prodan
25a1e26159 Build with Go 1.19
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-09-29 12:24:20 +03:00
Stefan Prodan
b39afea117 Merge pull request #219 from stefanprodan/build-revision
ci: Add revision to Docker build args
2022-09-29 12:23:27 +03:00
Stefan Prodan
6d11ef9baf ci: Add revision to Docker build args
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-09-29 12:18:53 +03:00
Michael McLeroy
baf128d856 feat(helm): added imagepullsecrets 2022-09-13 15:55:16 -04:00
Stefan Prodan
79f8138328 Merge pull request #215 from stefanprodan/fix-flux-oci
Fix Flux tagging action
2022-08-15 15:48:06 +03:00
Stefan Prodan
ceed4e7870 Fix Flux tagging action
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-08-15 15:43:33 +03:00
Stefan Prodan
bfce2199e8 Merge pull request #214 from stefanprodan/release-6.2.0
Release 6.2.0
2022-08-15 15:36:39 +03:00
Stefan Prodan
d55bb8eabd Release 6.2.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-08-15 15:29:44 +03:00
Stefan Prodan
5fb056ebcb Merge pull request #213 from stefanprodan/update-actions
Update GitHub Actions workflows
2022-08-15 15:28:53 +03:00
Stefan Prodan
35b9c9f946 Update GitHub Actions workflows
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-08-15 15:22:02 +03:00
Stefan Prodan
74e0aeeff7 Merge pull request #212 from stefanprodan/update-deps
Update dependencies
2022-08-15 15:10:54 +03:00
Stefan Prodan
bbb081b0e1 Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-08-15 15:06:41 +03:00
Stefan Prodan
c16318bb85 Merge pull request #211 from stefanprodan/flux-oci
Publish OCI artifacts on release with Flux
2022-08-15 15:01:51 +03:00
Stefan Prodan
86d5fe86e4 Publish OCI artifacts on release with Flux
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-08-15 14:56:50 +03:00
Stefan Prodan
b3b00fe354 Merge pull request #209 from stefanprodan/release-6.1.8
Release 6.1.8
2022-07-28 13:13:30 +03:00
Stefan Prodan
a7bcfaf9b3 Release 6.1.8
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-07-28 13:06:55 +03:00
Stefan Prodan
1d4c534728 Merge pull request #208 from stefanprodan/update-go-yaml
Update gopkg.in/yaml.v3 to v3.0.1
2022-07-28 13:05:52 +03:00
Stefan Prodan
f2e0aa154d Update gopkg.in/yaml.v3 to v3.0.1
Fix CVE-2022-28948

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-07-28 12:59:12 +03:00
Stefan Prodan
6d5b3d254a Merge pull request #207 from stefanprodan/release-6.1.7
Release 6.1.7
2022-07-27 19:19:21 +03:00
Stefan Prodan
9b9f11da95 Release 6.1.7
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-07-27 19:11:48 +03:00
Stefan Prodan
1a55e30bcf Merge pull request #206 from stefanprodan/update-swagger
Update Swagger packages and definition
2022-07-27 19:10:11 +03:00
Stefan Prodan
394c40e3ff Update Swagger packages and definition
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-07-27 18:59:22 +03:00
Stefan Prodan
b76b1a38c9 Merge pull request #204 from FlomoN/master
Add path based params to OpenAPI spec
2022-06-22 11:11:40 +03:00
FlomoN
2eb17d80c8 add some more params to other api routes with path based params 2022-06-20 18:37:13 +02:00
FlomoN
678a42ce34 recreate docs 2022-06-20 18:26:34 +02:00
FlomoN
2da59980fe switch to for installing swag 2022-06-20 18:05:53 +02:00
FlomoN
8697f091f3 Add params to godoc for cache 2022-06-20 14:20:34 +02:00
Stefan Prodan
4d2cf65260 Merge pull request #202 from TaylorMonacelli/patch-1
Fix test error "Error: release: not found"
2022-06-14 11:58:54 +03:00
Taylor Monacelli
116a378991 Fix test error "Error: release: not found" 2022-06-12 12:05:41 -07:00
Stefan Prodan
450796ddb2 Merge pull request #200 from stefanprodan/release-6.1.6
Release v6.1.6
2022-05-31 13:11:27 +03:00
Stefan Prodan
cb8c1fcec1 Release v6.1.6
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-05-31 13:04:28 +03:00
Stefan Prodan
37da8d1c74 Merge pull request #199 from stefanprodan/update-deps
Update dependencies
2022-05-31 13:01:10 +03:00
Stefan Prodan
e55ebd258d Update dependencies
Fix CVE-2022-28948

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-05-31 12:42:25 +03:00
Stefan Prodan
6b869d1a18 Merge pull request #198 from stefanprodan/go-1.18
Update Go to 1.18 and Alpine to 3.16
2022-05-24 13:06:50 +03:00
Stefan Prodan
dea973d614 Release podinfo 6.1.5
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-05-24 12:09:58 +03:00
Stefan Prodan
f4199ab8bc Update Go to 1.18 and Alpine to 3.16
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-05-24 12:09:08 +03:00
Paul Carlton
19603ddfc1 Fix panic triggering via HTTP API (#197)
Fix GET /panic

The GET /panic api call is not working due the the logger.Panic method
failing to call panic. This change replaces the logger.Panic method
call with logger.Info and adds a call to os.Exit(255).
2022-05-24 12:03:54 +03:00
Stefan Prodan
bf09377bfd Merge pull request #194 from stefanprodan/release-v6.1.4
Release v6.1.4
2022-04-18 10:00:06 +03:00
Stefan Prodan
075712dd73 Release v6.1.4
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-18 09:56:02 +03:00
Stefan Prodan
07dd9a3c3e Merge pull request #193 from stefanprodan/deps-up
Update dependencies
2022-04-18 09:54:32 +03:00
Stefan Prodan
63ac69ea69 Update dependencies
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-18 09:49:42 +03:00
Stefan Prodan
3db382d2c9 Merge pull request #192 from stefanprodan/cue-refac
Refactor CUE module
2022-04-18 09:44:21 +03:00
Stefan Prodan
9f88a0e940 Refactor CUE module
- set default labels and annotations
- fix the service monitor selector
- allow setting ingress annotations
- remove embedded cert
- add cert-manager example for ingress
- set CPU scaling as default in HPA
- rename app input to config
- rename app out to objects

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-17 15:43:09 +03:00
Stefan Prodan
c6a2c90497 Merge pull request #191 from stefanprodan/exclude-cue-vendor
Exclude the CUE vendor packages from Git
2022-04-14 19:31:59 +03:00
Stefan Prodan
54908f7d51 Exclude the CUE vendor packages from Git
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-14 19:03:58 +03:00
Stefan Prodan
36bf90b008 Merge pull request #190 from stefanprodan/release-6.1.3
Release v6.1.3
2022-04-13 11:52:28 +03:00
Stefan Prodan
dd9020c8b2 Release v6.1.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-13 11:43:55 +03:00
Stefan Prodan
51009591a5 Merge pull request #189 from stefanprodan/redis-url-fix
Add protocol to Redis URL
2022-04-13 11:42:55 +03:00
Stefan Prodan
2b8c71ba78 Add protocol to Redis URL
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-13 11:37:49 +03:00
Stefan Prodan
203f7e1bf0 Merge pull request #187 from stefanprodan/release-6.1.2
Release 6.1.2
2022-04-11 16:35:21 +03:00
Stefan Prodan
8179263f52 Release 6.1.2
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-11 16:30:15 +03:00
Stefan Prodan
b26a34b5b6 cue: Fix label selectors
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-11 16:29:35 +03:00
Stefan Prodan
cd7a0fb18e Rename cue module
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-04-11 15:45:12 +03:00
Stefan Prodan
c1fd17e50a Merge pull request #185 from phoban01/piarash/cue-module
Add CUE module for generating Kubernetes manifests
2022-04-11 15:38:29 +03:00
Piaras Hoban
f98267009e cue: move cue fmt check above dirty working tree check in test workflow
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 11:56:59 +01:00
Piaras Hoban
7d0203196a cue: add cue format and validation checks to github actions test workflow
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 11:03:22 +01:00
Piaras Hoban
673966bae4 cue: remove linkerd ServiceProfile resource
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 10:44:35 +01:00
Piaras Hoban
9265828c4f cue: patch version in main.cue with makefile version-set rule
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 10:44:01 +01:00
Piaras Hoban
0f68b60870 cue: remove default tag from config.image
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 10:27:14 +01:00
Piaras Hoban
217a27ce02 cue: rename directory from cuelang -> cue
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-11 10:26:00 +01:00
Piaras Hoban
fc172b0e7c add cuelang module for podinfo
Signed-off-by: Piaras Hoban <phoban01@gmail.com>
2022-04-06 17:50:41 +01:00
Stefan Prodan
b891025365 Fix Helm OCI packaging job
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-03-30 11:38:41 +03:00
Stefan Prodan
3c3f2a2e60 Merge pull request #183 from stefanprodan/release-6.1.1
Release v6.1.1
2022-03-30 11:24:21 +03:00
Stefan Prodan
06b5e969db Publish v6.1.1
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-03-30 11:17:38 +03:00
Stefan Prodan
8508550ee6 Merge pull request #182 from stefanprodan/helm-oci
Published signed Helm charts to GHCR
2022-03-30 11:16:19 +03:00
Stefan Prodan
5c1032c578 Published signed Helm charts to GHCR
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-03-30 11:11:45 +03:00
Stefan Prodan
9febc66b98 Merge pull request #180 from mmontes11/redis-basic-auth
Adapted cache to support redis authentication
2022-03-29 10:26:13 +03:00
Stefan Prodan
59dc738b25 Merge pull request #181 from nozaq/fix-typo
Fix a typo
2022-03-29 10:25:56 +03:00
nozaq
8524be7240 Fix a typo 2022-03-27 21:44:09 +09:00
Martín Montes
065a18c258 Adapted cache to support redis authentication 2022-03-23 22:13:14 +01:00
224 changed files with 30477 additions and 1497 deletions

View File

@@ -1,9 +1,10 @@
# Podinfo signed releases
Podinfo deployment manifests are published to GitHub Container Registry as OCI artifacts
and are signed using [cosign](https://github.com/sigstore/cosign).
Podinfo release assets (container image, Helm chart, Flux artifact, Timoni module)
are published to GitHub Container Registry and are signed with
[Cosign v2](https://github.com/sigstore/cosign) keyless & GitHub Actions OIDC.
## Verify the artifacts with cosign
## Verify podinfo with cosign
Install the [cosign](https://github.com/sigstore/cosign) CLI:
@@ -11,29 +12,50 @@ Install the [cosign](https://github.com/sigstore/cosign) CLI:
brew install sigstore/tap/cosign
```
Verify a podinfo release with cosign CLI:
### Container image
Verify the podinfo container image hosted on GHCR:
```sh
cosign verify -key https://raw.githubusercontent.com/stefanprodan/podinfo/master/cosign/cosign.pub \
ghcr.io/stefanprodan/podinfo-deploy:latest
cosign verify ghcr.io/stefanprodan/podinfo:6.5.0 \
--certificate-identity-regexp="^https://github.com/stefanprodan/podinfo.*$" \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
## Download the artifacts with crane
Install the [crane](https://github.com/google/go-containerregistry/tree/main/cmd/crane) CLI:
Verify the podinfo container image hosted on Docker Hub:
```sh
brew install crane
cosign verify docker.io/stefanprodan/podinfo:6.5.0 \
--certificate-identity-regexp="^https://github.com/stefanprodan/podinfo.*$" \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
Download the podinfo deployment manifests with crane CLI:
### Helm chart
```console
$ crane export ghcr.io/stefanprodan/podinfo-deploy:latest -| tar -xf -
Verify the podinfo [Helm](https://helm.sh) chart hosted on GHCR:
$ ls -1
deployment.yaml
hpa.yaml
kustomization.yaml
service.yaml
```sh
cosign verify ghcr.io/stefanprodan/charts/podinfo:6.5.0 \
--certificate-identity-regexp="^https://github.com/stefanprodan/podinfo.*$" \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
### Flux artifact
Verify the podinfo [Flux](https://fluxcd.io) artifact hosted on GHCR:
```sh
cosign verify ghcr.io/stefanprodan/manifests/podinfo:6.5.0 \
--certificate-identity-regexp="^https://github.com/stefanprodan/podinfo.*$" \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
### Timoni module
Verify the podinfo [Timoni](https://timoni.sh) module hosted on GHCR:
```sh
cosign verify ghcr.io/stefanprodan/modules/podinfo:6.5.0 \
--certificate-identity-regexp="^https://github.com/stefanprodan/podinfo.*$" \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
timoni/podinfo/cue.mod/** linguist-vendored

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: stefanprodan

View File

@@ -1,33 +0,0 @@
name: Setup Helm CLI
description: A GitHub Action for running Helm commands
author: Stefan Prodan
branding:
color: blue
icon: command
inputs:
version:
description: "Helm version"
required: true
runs:
using: composite
steps:
- name: "Download helm binary to tmp"
shell: bash
run: |
VERSION=${{ inputs.version }}
BIN_URL="https://get.helm.sh/helm-v${VERSION}-linux-amd64.tar.gz"
curl -sL ${BIN_URL} -o /tmp/helm.tar.gz
mkdir -p /tmp/helm
tar -C /tmp/helm/ -zxvf /tmp/helm.tar.gz
- name: "Add helm binary to /usr/local/bin"
shell: bash
run: |
sudo cp /tmp/helm/linux-amd64/helm /usr/local/bin
- name: "Cleanup tmp"
shell: bash
run: |
rm -rf /tmp/helm/ /tmp/helm.tar.gz
- name: "Verify correct installation of binary"
shell: bash
run: |
helm version

38
.github/actions/kubeconform/action.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Setup kubeconform
description: A GitHub Action for running kubeconform commands
author: Stefan Prodan
branding:
color: blue
icon: command
inputs:
version:
description: "kubeconform version e.g. 0.5.0 (defaults to latest stable release)"
required: false
arch:
description: "arch can be amd64 or arm64"
required: true
default: "amd64"
runs:
using: composite
steps:
- name: "Download binary to the GH runner cache"
shell: bash
run: |
ARCH=${{ inputs.arch }}
VERSION=${{ inputs.version }}
if [ -z $VERSION ]; then
VERSION=$(curl https://api.github.com/repos/yannh/kubeconform/releases/latest -sL | grep tag_name | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
fi
BIN_URL="https://github.com/yannh/kubeconform/releases/download/v${VERSION}/kubeconform-linux-${ARCH}.tar.gz"
BIN_DIR=$RUNNER_TOOL_CACHE/kubeconform/$VERSION/$ARCH
if [[ ! -x "$BIN_DIR/kind" ]]; then
mkdir -p $BIN_DIR
cd $BIN_DIR
curl -sL $BIN_URL | tar xz
chmod +x kubeconform
fi
echo "$BIN_DIR" >> "$GITHUB_PATH"

View File

@@ -1,51 +0,0 @@
package kubernetes
name = input.metadata.name
kind = input.kind
is_service {
input.kind = "Service"
}
is_deployment {
input.kind = "Deployment"
}
is_pod {
input.kind = "Pod"
}
split_image(image) = [image, "latest"] {
not contains(image, ":")
}
split_image(image) = [image_name, tag] {
[image_name, tag] = split(image, ":")
}
pod_containers(pod) = all_containers {
keys = {"containers", "initContainers"}
all_containers = [c | keys[k]; c = pod.spec[k][_]]
}
containers[container] {
pods[pod]
all_containers = pod_containers(pod)
container = all_containers[_]
}
containers[container] {
all_containers = pod_containers(input)
container = all_containers[_]
}
pods[pod] {
is_deployment
pod = input.spec.template
}
pods[pod] {
is_pod
pod = input
}

View File

@@ -1,43 +0,0 @@
package main
import data.kubernetes
name = input.metadata.name
# Deny containers with latest image tag
deny[msg] {
kubernetes.containers[container]
[image_name, "latest"] = kubernetes.split_image(container.image)
msg = sprintf("%s in the %s %s has an image %s, using the latest tag", [container.name, kubernetes.kind, kubernetes.name, image_name])
}
# Deny services without app label selector
service_labels {
input.spec.selector["app"]
}
deny[msg] {
kubernetes.is_service
not service_labels
msg = sprintf("Service %s should set app label selector", [name])
}
# Deny deployments without app label selector
match_labels {
input.spec.selector.matchLabels["app"]
}
deny[msg] {
kubernetes.is_deployment
not match_labels
msg = sprintf("Service %s should set app label selector", [name])
}
# Warn if deployments have no prometheus pod annotations
annotations {
input.spec.template.metadata.annotations["prometheus.io/scrape"]
input.spec.template.metadata.annotations["prometheus.io/port"]
}
warn[msg] {
kubernetes.is_deployment
not annotations
msg = sprintf("Deployment %s should set prometheus.io/scrape and prometheus.io/port pod annotations", [name])
}

View File

@@ -3,20 +3,23 @@ name: cve-scan
on:
push:
branches:
- 'master'
- "master"
permissions:
contents: read
jobs:
trivy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Build image
id: build
run: |
IMAGE=test/podinfo:${GITHUB_SHA}
docker build -t ${IMAGE} .
echo "::set-output name=image::$IMAGE"
echo "image=$IMAGE" >> $GITHUB_OUTPUT
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:

View File

@@ -6,28 +6,28 @@ on:
branches:
- 'master'
permissions:
contents: read
jobs:
kind-helm:
strategy:
matrix:
helm-version:
- 3.6.0
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0
uses: helm/kind-action@v1.8.0
with:
version: v0.11.1
version: v0.20.0
cluster_name: kind
- name: Build container image
run: |
./test/build.sh
kind load docker-image test/podinfo:latest
- name: Setup Helm
uses: ./.github/actions/helm
uses: azure/setup-helm@v3
with:
version: ${{ matrix.helm-version }}
version: v3.12.3
- name: Deploy
run: ./test/deploy.sh
- name: Run integration tests
@@ -36,3 +36,45 @@ jobs:
if: failure()
run: |
kubectl logs -l app=podinfo || true
kind-timoni:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
env:
PODINFO_IMAGE_URL: "test/podinfo"
PODINFO_MODULE_URL: "oci://localhost:5000/podinfo"
PODINFO_VERSION: "0.0.0-devel"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Timoni
uses: stefanprodan/timoni/actions/setup@main
- name: Setup Kubernetes
uses: helm/kind-action@v1.8.0
with:
version: v0.20.0
cluster_name: kind
- name: Build container
run: |
docker build -t ${PODINFO_IMAGE_URL}:${PODINFO_VERSION} --build-arg "REVISION=${GITHUB_SHA}" -f Dockerfile.xx .
kind load docker-image ${PODINFO_IMAGE_URL}:${PODINFO_VERSION}
- name: Vet module
run: |
timoni mod vet ./timoni/podinfo --debug
- name: Build module
run: |
timoni mod push ./timoni/podinfo ${PODINFO_MODULE_URL} -v ${PODINFO_VERSION}
- name: Apply bundle
run: |
timoni bundle apply -f ./timoni/bundles/test.podinfo.cue --runtime-from-env
- name: Verify status
run: |
timoni -n podinfo status backend
timoni -n podinfo status frontend
- name: Debug failure
if: failure()
run: |
kubectl -n podinfo get all || true

View File

@@ -6,32 +6,55 @@ on:
- '*'
permissions:
contents: write # needed to write releases
id-token: write # needed for keyless signing
packages: write # needed for ghcr access
contents: read
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write # needed to write releases
id-token: write # needed for keyless signing
packages: write # needed for ghcr access
steps:
- uses: actions/checkout@v2
- uses: imjasonh/setup-crane@v0.1
- uses: sigstore/cosign-installer@main
- uses: actions/checkout@v4
- uses: sigstore/cosign-installer@v3
- uses: fluxcd/flux2/action@main
- uses: stefanprodan/timoni/actions/setup@main
- name: Setup Notation CLI
uses: notaryproject/notation-action/setup@v1
with:
version: "1.1.0"
- name: Setup Notation signing keys
run: |
mkdir -p ~/.config/notation/localkeys/
cp ./.notation/signingkeys.json ~/.config/notation/
cp ./.notation/notation.crt ~/.config/notation/localkeys/
echo "$NOTATION_KEY" > ~/.config/notation/localkeys/notation.key
env:
NOTATION_KEY: ${{ secrets.NOTATION_SIGNING_KEY }}
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Setup Helm
uses: azure/setup-helm@v3
with:
version: v3.12.3
- name: Setup QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
@@ -42,37 +65,64 @@ jobs:
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF/refs\/tags\//}
fi
echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
echo ::set-output name=VERSION::${VERSION}
- name: Publish multi-arch image
uses: docker/build-push-action@v2
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
echo "REVISION=${GITHUB_SHA}" >> $GITHUB_OUTPUT
- name: Generate images meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
docker.io/stefanprodan/podinfo
ghcr.io/stefanprodan/podinfo
tags: |
type=raw,value=${{ steps.prep.outputs.VERSION }}
type=raw,value=latest
- name: Publish multi-arch image
uses: docker/build-push-action@v5
with:
sbom: true
provenance: true
push: true
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile.xx
build-args: |
REVISION=${{ steps.prep.outputs.REVISION }}
platforms: linux/amd64,linux/arm/v7,linux/arm64
tags: |
docker.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
docker.io/stefanprodan/podinfo:latest
ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
labels: |
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=${{ github.event.repository.description }}
org.opencontainers.image.source=${{ github.event.repository.html_url }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ steps.prep.outputs.VERSION }}
org.opencontainers.image.created=${{ steps.prep.outputs.BUILD_DATE }}
- name: Sign images
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Publish Timoni module to GHCR
run: |
timoni mod push ./timoni/podinfo oci://ghcr.io/stefanprodan/modules/podinfo \
--sign cosign \
--version ${{ steps.prep.outputs.VERSION }} \
-a 'org.opencontainers.image.source=https://github.com/stefanprodan/podinfo' \
-a 'org.opencontainers.image.licenses=Apache-2.0' \
-a 'org.opencontainers.image.description=A timoni.sh module for deploying Podinfo.' \
-a 'org.opencontainers.image.documentation=https://github.com/stefanprodan/podinfo/blob/main/timoni/podinfo/README.md'
- name: Publish Helm chart to GHCR
run: |
helm package charts/podinfo
helm push podinfo-${{ steps.prep.outputs.VERSION }}.tgz oci://ghcr.io/stefanprodan/charts
rm podinfo-${{ steps.prep.outputs.VERSION }}.tgz
- name: Publish Flux OCI artifact to GHCR
run: |
flux push artifact oci://ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }} \
--path="./kustomize" \
--source="${{ github.event.repository.html_url }}" \
--revision="${GITHUB_REF_NAME}/${GITHUB_SHA}"
flux tag artifact oci://ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }} --tag latest
- name: Sign artifacts with Cosign
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign sign docker.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
cosign sign docker.io/stefanprodan/podinfo:latest
cosign sign ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
cosign sign docker.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }} --yes
cosign sign ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }} --yes
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@v2
uses: docker/build-push-action@v5
with:
push: true
builder: ${{ steps.buildx.outputs.name }}
@@ -86,28 +136,35 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Publish config artifact
run: |
cd kustomize
tar -cf config.tar * --numeric-owner --owner=0 --group=0
crane append -f config.tar -t ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
crane tag ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} latest
rm config.tar
- name: Sign config artifact
flux push artifact oci://ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} \
--path="./kustomize" \
--source="${{ github.event.repository.html_url }}" \
--revision="${GITHUB_REF_NAME}/${GITHUB_SHA}"
flux tag artifact oci://ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} --tag latest
- name: Sign config artifact with cso
run: |
echo "$COSIGN_KEY" > /tmp/cosign.key
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:latest
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} --yes
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:latest --yes
env:
COSIGN_PASSWORD: ${{secrets.COSIGN_PASSWORD}}
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
- name: Sign artifacts with Notation
run: |
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
notation sign --signature-format cose ghcr.io/stefanprodan/charts/podinfo:${{ steps.prep.outputs.VERSION }}
notation sign --signature-format cose ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }}
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
- uses: ./.github/actions/release-notes
- name: Generate release notes
run: |
echo 'CHANGELOG' > /tmp/release.txt
github-release-notes -org stefanprodan -repo podinfo -since-latest-release >> /tmp/release.txt
- name: Publish release
uses: goreleaser/goreleaser-action@v1
uses: goreleaser/goreleaser-action@v5
with:
version: latest
args: release --release-notes=/tmp/release.txt
args: release --release-notes=/tmp/release.txt --skip-validate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,42 +6,67 @@ on:
branches:
- 'master'
permissions:
contents: read
env:
KUBERNETES_VERSION: 1.26.0
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Restore Go cache
uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: 1.17.x
go-version: 1.21.x
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: v${{ env.KUBERNETES_VERSION }}
- name: Setup kubeconform
uses: ./.github/actions/kubeconform
- name: Setup Helm
uses: azure/setup-helm@v3
with:
version: v3.10.3
- name: Setup CUE
uses: cue-lang/setup-cue@v1.0.0
- name: Setup Timoni
uses: stefanprodan/timoni/actions/setup@main
- name: Run unit tests
run: make test
- name: Validate Helm chart
run: |
helm lint ./charts/podinfo/
helm template ./charts/podinfo/ | kubeconform -strict -summary -kubernetes-version ${{ env.KUBERNETES_VERSION }}
- name: Validate Kustomize overlay
run: |
kubectl kustomize ./kustomize/ | kubeconform -strict -summary -kubernetes-version ${{ env.KUBERNETES_VERSION }}
- name: Verify CUE formatting
working-directory: ./timoni/podinfo
run: |
cue fmt ./..
status=$(git status . --porcelain)
[[ -z "$status" ]] || {
echo "CUE files are not correctly formatted"
echo "$status"
git diff
exit 1
}
- name: Validate Timoni module
working-directory: ./timoni/podinfo
run: |
timoni mod lint .
timoni build podinfo . -f test_values.cue | kubeconform -strict -summary -skip=ServiceMonitor -kubernetes-version ${{ env.KUBERNETES_VERSION }}
- name: Check if working tree is dirty
run: |
if [[ $(git diff --stat) != '' ]]; then
echo 'run make test and commit changes'
exit 1
fi
- name: Validate Helm chart
uses: stefanprodan/kube-tools@v1
with:
kubectl: 1.19.11
helm: 2.17.0
helmv3: 3.6.0
command: |
helmv3 template ./charts/podinfo | kubeval --strict --kubernetes-version 1.19.11 --schema-location https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master
- name: Validate kustomization
uses: stefanprodan/kube-tools@v1
with:
kubectl: 1.19.11
command: |
kustomize build ./kustomize | kubeval --strict --kubernetes-version 1.19.11 --schema-location https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master
kustomize build ./kustomize | conftest test -p .github/policy -

8
.gitignore vendored
View File

@@ -19,4 +19,10 @@ release/
build/
gcloud/
dist/
bin/
bin/
cue/cue.mod/gen/
cue/go.mod
cue/go.sum
.notation/podinfo.csr
.notation/podinfo.key

15
.notation/README.md Normal file
View File

@@ -0,0 +1,15 @@
# Podinfo signed releases
Podinfo release assets such as the Helm chart and the Flux artifact
are published to GitHub Container Registry and are signed with
[Notation](https://github.com/notaryproject/notation).
## Generate signing keys
Generate a new signing key pair:
```sh
openssl genrsa -out podinfo.key 2048
openssl req -new -key podinfo.key -out podinfo.csr -config codesign.cnf
openssl x509 -req -days 1826 -in podinfo.csr -signkey podinfo.key -out notation.crt -extensions v3_req -extfile codesign.cnf
```

18
.notation/codesign.cnf Normal file
View File

@@ -0,0 +1,18 @@
[ req ]
default_bits = 2048
default_keyfile = privatekey.pem
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
C = RO
ST = BU
L = Bucharest
O = Notary
CN = stefanprodan.com
[ v3_req ]
keyUsage = critical,digitalSignature
extendedKeyUsage = critical,codeSigning
#subjectKeyIdentifier = hash

21
.notation/notation.crt Normal file
View File

@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDbDCCAlSgAwIBAgIUP7zhmTw5XTWLcgBGkBEsErMOkz4wDQYJKoZIhvcNAQEL
BQAwWjELMAkGA1UEBhMCUk8xCzAJBgNVBAgMAkJVMRIwEAYDVQQHDAlCdWNoYXJl
c3QxDzANBgNVBAoMBk5vdGFyeTEZMBcGA1UEAwwQc3RlZmFucHJvZGFuLmNvbTAe
Fw0yNDAyMjUxMDAyMzZaFw0yOTAyMjQxMDAyMzZaMFoxCzAJBgNVBAYTAlJPMQsw
CQYDVQQIDAJCVTESMBAGA1UEBwwJQnVjaGFyZXN0MQ8wDQYDVQQKDAZOb3Rhcnkx
GTAXBgNVBAMMEHN0ZWZhbnByb2Rhbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDtH4oPi3SyX/DGv6NdjIvmApvD9eeSgsmHdwpAly8T9D2me+fx
Z+wRNJmq4aq/A1anX+Sg28iwHzV+1WKpsHnjYzDAJSEYP2S8A5H1nGRKUoibdijw
C3QBh5C75rjF/tmZVSX/Vgbf3HJJEsF4WUxWabLxoV2QLo7UlEsQd9+bSeKNMncx
1+E6FdbRCrYo90iobvZJ8K/S2zCWq/JTeHfTnmSEDhx6nMJcaSjvMPn3zyauWcQw
dDpkcaGiJ64fEJRT2OFxXv9u+vDmIMKzo/Wjbd+IzFj6YY4VisK88aU7tmDelnk5
gQB9eu62PFoaVsYJp4VOhblFKvGJpQwbWB9BAgMBAAGjKjAoMA4GA1UdDwEB/wQE
AwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEA
6x+C6hAIbLwMvkNx4K5p7Qe/pLQR0VwQFAw10yr/5KSN+YKFpon6pQ0TebL7qll+
uBGZvtQhN6v+DlnVqB7lvJKd+89isgirkkews5KwuXg7Gv5UPIugH0dXISZU8DMJ
7J4oKREv5HzdFmfsUfNlQcfyVTjKL6UINXfKGdqNNxXxR9b4a1TY2JcmEhzBTHaq
ZqX6HK784a0dB7aHgeFrFwPCCP4M684Hs7CFbk3jo2Ef4ljnB5AyWpe8pwCLMdRt
UjSjL5xJWVQvRU+STQsPr6SvpokPCG4rLQyjgeYYk4CCj5piSxbSUZFavq8v1y7Y
m91USVqfeUX7ZzjDxPHE2A==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,10 @@
{
"default": "stefanprodan.com",
"keys": [
{
"name": "stefanprodan.com",
"keyPath": "/home/runner/.config/notation/localkeys/notation.key",
"certPath": "/home/runner/.config/notation/localkeys/notation.crt"
}
]
}

View File

@@ -0,0 +1,19 @@
{
"version": "1.0",
"trustPolicies": [
{
"name": "stefanprodan.com",
"registryScopes": [
"ghcr.io/stefanprodan/podinfo-deploy",
"ghcr.io/stefanprodan/charts/podinfo"
],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:stefanprodan.com" ],
"trustedIdentities": [
"x509.subject: C=RO, ST=BU, L=Bucharest, O=Notary, CN=stefanprodan.com"
]
}
]
}

View File

@@ -1,4 +1,4 @@
FROM golang:1.17-alpine as builder
FROM golang:1.21-alpine as builder
ARG REVISION
@@ -18,7 +18,7 @@ RUN CGO_ENABLED=0 go build -ldflags "-s -w \
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
-a -o bin/podcli cmd/podcli/*
FROM alpine:3.15
FROM alpine:3.19
ARG BUILD_DATE
ARG VERSION

View File

@@ -1,4 +1,4 @@
FROM golang:1.17
FROM golang:1.21
WORKDIR /workspace

View File

@@ -1,5 +1,5 @@
ARG GO_VERSION=1.17
ARG XX_VERSION=1.1.0
ARG GO_VERSION=1.21
ARG XX_VERSION=1.3.0
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@@ -28,7 +28,7 @@ RUN xx-go build -ldflags "-s -w \
-X github.com/stefanprodan/podinfo/pkg/version.REVISION=${REVISION}" \
-a -o bin/podcli cmd/podcli/*
FROM alpine:3.15
FROM alpine:3.19
ARG BUILD_DATE
ARG VERSION

View File

@@ -24,7 +24,10 @@ 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.17
rm -f go.sum; go mod tidy -compat=1.21
vet:
go vet ./...
fmt:
gofmt -l -s -w ./
@@ -79,12 +82,19 @@ version-set:
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/webapp/backend/deployment.yaml && \
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/frontend/deployment.yaml && \
/usr/bin/sed -i '' "s/podinfo:$$current/podinfo:$$next/g" deploy/bases/backend/deployment.yaml && \
echo "Version $$next set in code, deployment, chart and kustomize"
/usr/bin/sed -i '' "s/$$current/$$next/g" timoni/podinfo/values.cue && \
echo "Version $$next set in code, deployment, module, chart and kustomize"
release:
git tag $(VERSION)
git tag -s -m $(VERSION) $(VERSION)
git push origin $(VERSION)
swagger:
go get github.com/swaggo/swag/cmd/swag
go install github.com/swaggo/swag/cmd/swag@latest
go get github.com/swaggo/swag/gen@latest
go get github.com/swaggo/swag/cmd/swag@latest
cd pkg/api && $$(go env GOPATH)/bin/swag init -g server.go
.PHONY: timoni-build
timoni-build:
@timoni build podinfo ./timoni/podinfo -f ./timoni/podinfo/debug_values.cue

View File

@@ -20,11 +20,11 @@ Specifications:
* 12-factor app with viper
* Fault injection (random errors and latency)
* Swagger docs
* Helm and Kustomize installers
* Timoni, Helm and Kustomize installers
* End-to-End testing with Kubernetes Kind and Helm
* Kustomize testing with GitHub Actions and Open Policy Agent
* Multi-arch container image with Docker buildx and Github Actions
* Container image signing with Sigstore cosign
* SBOMs and SLSA Provenance embedded in the container image
* CVE scanning with Trivy
Web API:
@@ -57,6 +57,8 @@ Web API:
gRPC API:
* `/grpc.health.v1.Health/Check` health checking
* `/grpc.EchoService/Echo` echos the received content
* `/grpc.VersionService/Version` returns podinfo version and Git commit hash
Web UI:
@@ -66,17 +68,26 @@ To access the Swagger UI open `<podinfo-host>/swagger/index.html` in a browser.
### Guides
* [GitOps Progressive Deliver with Flagger, Helm v3 and Linkerd](https://helm.workshop.flagger.dev/intro/)
* [GitOps Progressive Deliver on EKS with Flagger and AppMesh](https://eks.handson.flagger.dev/prerequisites/)
* [Automated canary deployments with Flagger and Istio](https://medium.com/google-cloud/automated-canary-deployments-with-flagger-and-istio-ac747827f9d1)
* [Kubernetes autoscaling with Istio metrics](https://medium.com/google-cloud/kubernetes-autoscaling-with-istio-metrics-76442253a45a)
* [Autoscaling EKS on Fargate with custom metrics](https://aws.amazon.com/blogs/containers/autoscaling-eks-on-fargate-with-custom-metrics/)
* [Managing Helm releases the GitOps way](https://medium.com/google-cloud/managing-helm-releases-the-gitops-way-207a6ac6ff0e)
* [Securing EKS Ingress With Contour And Lets Encrypt The GitOps Way](https://aws.amazon.com/blogs/containers/securing-eks-ingress-contour-lets-encrypt-gitops/)
* [Getting started with Timoni](https://timoni.sh/quickstart/)
* [Getting started with Flux](https://fluxcd.io/flux/get-started/)
* [Progressive Deliver with Flagger and Linkerd](https://docs.flagger.app/tutorials/linkerd-progressive-delivery)
* [Automated canary deployments with Kubernetes Gateway API](https://docs.flagger.app/tutorials/gatewayapi-progressive-delivery)
### Install
Helm:
To install Podinfo on Kubernetes the minimum required version is **Kubernetes v1.23**.
#### Timoni
Install with [Timoni](https://timoni.sh):
```bash
timoni -n default apply podinfo oci://ghcr.io/stefanprodan/modules/podinfo
```
#### Helm
Install from github.io:
```bash
helm repo add podinfo https://stefanprodan.github.io/podinfo
@@ -87,7 +98,7 @@ helm upgrade --install --wait frontend \
--set backend=http://backend-podinfo:9898/echo \
podinfo/podinfo
helm test frontend
helm test frontend --namespace test
helm upgrade --install --wait backend \
--namespace test \
@@ -95,13 +106,20 @@ helm upgrade --install --wait backend \
podinfo/podinfo
```
Kustomize:
Install from ghcr.io:
```bash
helm upgrade --install --wait podinfo --namespace default \
oci://ghcr.io/stefanprodan/charts/podinfo
```
#### Kustomize
```bash
kubectl apply -k github.com/stefanprodan/podinfo//kustomize
```
Docker:
#### Docker
```bash
docker run -dp 9898:9898 stefanprodan/podinfo

View File

@@ -1,6 +1,6 @@
apiVersion: v1
version: 6.1.0
appVersion: 6.1.0
version: 6.6.0
appVersion: 6.6.0
name: podinfo
engine: gotpl
description: Podinfo Helm chart for Kubernetes
@@ -10,4 +10,4 @@ maintainers:
name: stefanprodan
sources:
- https://github.com/stefanprodan/podinfo
kubeVersion: ">=1.19.0-0"
kubeVersion: ">=1.23.0-0"

View File

@@ -9,7 +9,23 @@ for end-to-end testing and workshops.
## Installing the Chart
To install the chart with the release name `my-release`:
The Podinfo charts are published to
[GitHub Container Registry](https://github.com/stefanprodan/podinfo/pkgs/container/charts%2Fpodinfo)
and signed with [Cosign](https://github.com/sigstore/cosign) & GitHub Actions OIDC.
To install the chart with the release name `my-release` from GHCR:
```console
$ helm upgrade -i my-release oci://ghcr.io/stefanprodan/charts/podinfo
```
To verify a chart with Cosign:
```console
$ cosign verify ghcr.io/stefanprodan/charts/podinfo:<VERSION>
```
Alternatively, you can install the chart from GitHub pages:
```console
$ helm repo add podinfo https://stefanprodan.github.io/podinfo
@@ -34,60 +50,62 @@ 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 `<host>:<port>`
`redis.enabled` | `false` | Create Redis deployment for caching purposes
`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` | `stefanprodan/podinfo` | Image repository
`image.tag` | `<VERSION>` | Image tag
`image.pullPolicy` | `IfNotPresent` | Image pull policy
`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
`h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2)
`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
`securityContext` | `{}` | The security context to be set on the podinfo container
`linkerd.profile.enabled` | `false` | Create Linkerd service profile
`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.annotations` | `{}` | Ingress annotations
`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
`podAnnotations` | `{}` | Pod annotations
| 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 |
| `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` | `stefanprodan/podinfo` | Image repository |
| `image.tag` | `<VERSION>` | Image tag |
| `image.pullPolicy` | `IfNotPresent` | Image pull policy |
| `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 |
| `h2c.enabled` | `false` | Allow upgrading to h2c (non-TLS version of HTTP/2) |
| `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 |
| `linkerd.profile.enabled` | `false` | Create Linkerd service profile |
| `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 |
| `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 |
| `podAnnotations` | `{}` | Pod annotations |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
@@ -110,14 +128,3 @@ $ helm install my-release podinfo/podinfo -f values.yaml
```
> **Tip**: You can use the default [values.yaml](values.yaml)
## Upgrading the chart
### To =< 5.0.0
Version 5.0.0 is a major update.
* The chart now follows the new Kubernetes label recommendations:
<https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/>
The simplest way to update is to do a force upgrade, which recreates the resources by doing a delete and an install.

View File

@@ -73,7 +73,7 @@ spec:
{{- if .Values.cache }}
- --cache-server={{ .Values.cache }}
{{- else if .Values.redis.enabled }}
- --cache-server={{ template "podinfo.fullname" . }}-redis:6379
- --cache-server=tcp://{{ template "podinfo.fullname" . }}-redis:6379
{{- end }}
- --level={{ .Values.logLevel }}
- --random-delay={{ .Values.faults.delay }}
@@ -129,6 +129,22 @@ spec:
containerPort: {{ .Values.service.grpcPort }}
protocol: TCP
{{- end }}
{{- if .Values.probes.startup.enable }}
startupProbe:
exec:
command:
- podcli
- check
- http
- localhost:{{ .Values.service.httpPort | default 9898 }}/healthz
{{- with .Values.probes.startup }}
initialDelaySeconds: {{ .initialDelaySeconds | default 1 }}
timeoutSeconds: {{ .timeoutSeconds | default 5 }}
failureThreshold: {{ .failureThreshold | default 3 }}
successThreshold: {{ .successThreshold | default 1 }}
periodSeconds: {{ .periodSeconds | default 10 }}
{{- end }}
{{- end }}
livenessProbe:
exec:
command:
@@ -136,8 +152,13 @@ spec:
- check
- http
- localhost:{{ .Values.service.httpPort | default 9898 }}/healthz
initialDelaySeconds: 1
timeoutSeconds: 5
{{- with .Values.probes.liveness }}
initialDelaySeconds: {{ .initialDelaySeconds | default 1 }}
timeoutSeconds: {{ .timeoutSeconds | default 5 }}
failureThreshold: {{ .failureThreshold | default 3 }}
successThreshold: {{ .successThreshold | default 1 }}
periodSeconds: {{ .periodSeconds | default 10 }}
{{- end }}
readinessProbe:
exec:
command:
@@ -145,8 +166,13 @@ spec:
- check
- http
- localhost:{{ .Values.service.httpPort | default 9898 }}/readyz
initialDelaySeconds: 1
timeoutSeconds: 5
{{- with .Values.probes.readiness }}
initialDelaySeconds: {{ .initialDelaySeconds | default 1 }}
timeoutSeconds: {{ .timeoutSeconds | default 5 }}
failureThreshold: {{ .failureThreshold | default 3 }}
successThreshold: {{ .successThreshold | default 1 }}
periodSeconds: {{ .periodSeconds | default 10 }}
{{- end }}
volumeMounts:
- name: data
mountPath: /data

View File

@@ -1,5 +1,5 @@
{{- if .Values.hpa.enabled -}}
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ template "podinfo.fullname" . }}

View File

@@ -7,6 +7,9 @@ metadata:
name: {{ $fullName }}
labels:
{{- include "podinfo.labels" . | nindent 4 }}
{{- with .Values.ingress.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}

View File

@@ -5,4 +5,8 @@ metadata:
name: {{ template "podinfo.serviceAccountName" . }}
labels:
{{- include "podinfo.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 2 }}
{{- end -}}
{{- end -}}

View File

@@ -8,7 +8,7 @@ backends: []
image:
repository: ghcr.io/stefanprodan/podinfo
tag: 6.1.0
tag: 6.6.0
pullPolicy: IfNotPresent
ui:
@@ -77,13 +77,13 @@ hpa:
# average http requests per second per pod (k8s-prometheus-adapter)
requests:
# Redis address in the format <host>:<port>
# Redis address in the format tcp://<host>:<port>
cache: ""
# Redis deployment
redis:
enabled: true
repository: redis
tag: 6.0.8
tag: 7.0.7
serviceAccount:
# Specifies whether a service account should be created
@@ -91,6 +91,8 @@ serviceAccount:
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
# List of image pull secrets if pulling from private registries
imagePullSecrets: []
# set container security context
securityContext: {}
@@ -98,6 +100,7 @@ securityContext: {}
ingress:
enabled: false
className: ""
additionalLabels: {}
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"

View File

@@ -8,7 +8,7 @@ backends: []
image:
repository: ghcr.io/stefanprodan/podinfo
tag: 6.1.0
tag: 6.6.0
pullPolicy: IfNotPresent
ui:
@@ -81,13 +81,13 @@ hpa:
# average http requests per second per pod (k8s-prometheus-adapter)
requests:
# Redis address in the format <host>:<port>
# Redis address in the format tcp://<host>:<port>
cache: ""
# Redis deployment
redis:
enabled: false
repository: redis
tag: 6.0.8
tag: 7.0.7
serviceAccount:
# Specifies whether a service account should be created
@@ -95,6 +95,8 @@ serviceAccount:
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name:
# List of image pull secrets if pulling from private registries
imagePullSecrets: []
# set container security context
securityContext: {}
@@ -102,6 +104,7 @@ securityContext: {}
ingress:
enabled: false
className: ""
additionalLabels: {}
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
@@ -138,3 +141,25 @@ tolerations: []
affinity: {}
podAnnotations: {}
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
probes:
readiness:
initialDelaySeconds: 1
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
periodSeconds: 10
liveness:
initialDelaySeconds: 1
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
periodSeconds: 10
startup:
enable: false
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 20
successThreshold: 1
periodSeconds: 10

View File

@@ -2,7 +2,6 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -14,10 +13,11 @@ import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/stefanprodan/podinfo/pkg/api"
"github.com/stefanprodan/podinfo/pkg/grpc"
"github.com/stefanprodan/podinfo/pkg/api/grpc"
"github.com/stefanprodan/podinfo/pkg/api/http"
"github.com/stefanprodan/podinfo/pkg/signals"
"github.com/stefanprodan/podinfo/pkg/version"
go_grpc "google.golang.org/grpc"
)
func main() {
@@ -29,11 +29,11 @@ func main() {
fs.Int("port-metrics", 0, "metrics port")
fs.Int("grpc-port", 0, "gRPC port")
fs.String("grpc-service-name", "podinfo", "gPRC service name")
fs.String("level", "info", "log level debug, info, warn, error, flat or panic")
fs.String("level", "info", "log level debug, info, warn, error, fatal or panic")
fs.StringSlice("backend-url", []string{}, "backend service URL")
fs.Duration("http-client-timeout", 2*time.Minute, "client timeout duration")
fs.Duration("http-server-timeout", 30*time.Second, "server read and write timeout duration")
fs.Duration("http-server-shutdown-timeout", 5*time.Second, "server graceful shutdown timeout duration")
fs.Duration("server-shutdown-timeout", 5*time.Second, "server graceful shutdown timeout duration")
fs.String("data-path", "/data", "data local path")
fs.String("config-path", "", "config dir path")
fs.String("cert-path", "/data/cert", "certificate path for HTTPS port")
@@ -52,7 +52,7 @@ func main() {
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-memory", 0, "MB of data to load into memory")
fs.String("cache-server", "", "Redis address in the format <host>:<port>")
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")
versionFlag := fs.BoolP("version", "v", false, "get version number")
@@ -135,13 +135,16 @@ func main() {
}
// start gRPC server
var grpcServer *go_grpc.Server
if grpcCfg.Port > 0 {
grpcSrv, _ := grpc.NewServer(&grpcCfg, logger)
go grpcSrv.ListenAndServe()
//grpcinfoSrv, _ := grpc.NewInfoServer(&grpcCfg)
grpcServer = grpcSrv.ListenAndServe()
}
// load HTTP server config
var srvCfg api.Config
var srvCfg http.Config
if err := viper.Unmarshal(&srvCfg); err != nil {
logger.Panic("config unmarshal failed", zap.Error(err))
}
@@ -154,9 +157,13 @@ func main() {
)
// start HTTP server
srv, _ := api.NewServer(&srvCfg, logger)
srv, _ := http.NewServer(&srvCfg, logger)
httpServer, httpsServer, healthy, ready := srv.ListenAndServe()
// graceful shutdown
stopCh := signals.SetupSignalHandler()
srv.ListenAndServe(stopCh)
sd, _ := signals.NewShutdown(srvCfg.ServerShutdownTimeout, logger)
sd.Graceful(stopCh, httpServer, httpsServer, grpcServer, healthy, ready)
}
func initZap(logLevel string) (*zap.Logger, error) {
@@ -238,12 +245,12 @@ func beginStressTest(cpus int, mem int, logger *zap.Logger) {
logger.Error("memory stress failed", zap.Error(err))
}
stressMemoryPayload, err = ioutil.ReadFile(path)
stressMemoryPayload, err = os.ReadFile(path)
f.Close()
os.Remove(path)
if err != nil {
logger.Error("memory stress failed", zap.Error(err))
}
logger.Info("starting CPU stress", zap.Int("memory", len(stressMemoryPayload)))
logger.Info("starting MEMORY stress", zap.Int("memory", len(stressMemoryPayload)))
}
}

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: backend
image: ghcr.io/stefanprodan/podinfo:6.1.0
image: ghcr.io/stefanprodan/podinfo:6.6.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend

View File

@@ -13,7 +13,7 @@ spec:
spec:
containers:
- name: redis
image: redis:6.0.1
image: redis:7.0.7
imagePullPolicy: IfNotPresent
command:
- redis-server

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: frontend
image: ghcr.io/stefanprodan/podinfo:6.1.0
image: ghcr.io/stefanprodan/podinfo:6.6.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend

View File

@@ -25,7 +25,7 @@ spec:
serviceAccountName: webapp
containers:
- name: backend
image: ghcr.io/stefanprodan/podinfo:6.1.0
image: ghcr.io/stefanprodan/podinfo:6.6.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend

View File

@@ -25,7 +25,7 @@ spec:
serviceAccountName: webapp
containers:
- name: frontend
image: ghcr.io/stefanprodan/podinfo:6.1.0
image: ghcr.io/stefanprodan/podinfo:6.6.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: frontend

141
go.mod
View File

@@ -1,84 +1,89 @@
module github.com/stefanprodan/podinfo
go 1.17
go 1.21
require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1
github.com/fatih/color v1.9.0
github.com/fsnotify/fsnotify v1.4.9
github.com/gomodule/redigo v1.8.4
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2
github.com/prometheus/client_golang v1.11.0
github.com/spf13/cobra v1.2.1
github.com/chzyer/readline v1.5.1
github.com/fatih/color v1.16.0
github.com/fsnotify/fsnotify v1.7.0
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/gomodule/redigo v1.8.9
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.1
github.com/prometheus/client_golang v1.17.0
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.8.1
github.com/swaggo/http-swagger v1.0.0
github.com/swaggo/swag v1.7.6
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.28.0
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.28.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.28.0
go.opentelemetry.io/contrib/propagators/aws v1.3.0
go.opentelemetry.io/contrib/propagators/b3 v1.3.0
go.opentelemetry.io/contrib/propagators/jaeger v1.3.0
go.opentelemetry.io/contrib/propagators/ot v1.3.0
go.opentelemetry.io/otel v1.3.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0
go.opentelemetry.io/otel/sdk v1.3.0
go.opentelemetry.io/otel/trace v1.3.0
go.uber.org/zap v1.19.1
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
google.golang.org/grpc v1.43.0
github.com/spf13/viper v1.18.1
github.com/swaggo/http-swagger v1.3.4
github.com/swaggo/swag v1.16.2
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.46.1
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1
go.opentelemetry.io/contrib/propagators/aws v1.21.1
go.opentelemetry.io/contrib/propagators/b3 v1.21.1
go.opentelemetry.io/contrib/propagators/jaeger v1.21.1
go.opentelemetry.io/contrib/propagators/ot v1.21.1
go.opentelemetry.io/otel v1.21.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0
go.opentelemetry.io/otel/sdk v1.21.0
go.opentelemetry.io/otel/trace v1.21.0
go.uber.org/zap v1.26.0
golang.org/x/net v0.19.0
google.golang.org/grpc v1.60.0
)
// Fix CVE-2022-32149
replace golang.org/x/text => golang.org/x/text v0.14.0
// Fix CVE-2022-28948
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/go-logr/logr v1.2.1 // indirect
github.com/go-logr/stdr v1.2.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/spec v0.20.3 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect
go.opentelemetry.io/otel/internal/metric v0.26.0 // indirect
go.opentelemetry.io/otel/metric v0.26.0 // indirect
go.opentelemetry.io/proto/otlp v0.11.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.1.5 // indirect
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect
go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

953
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@ spec:
spec:
containers:
- name: podinfod
image: ghcr.io/stefanprodan/podinfo:6.1.0
image: ghcr.io/stefanprodan/podinfo:6.6.0
imagePullPolicy: IfNotPresent
ports:
- name: http
@@ -72,3 +72,9 @@ spec:
requests:
cpu: 100m
memory: 64Mi
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}

View File

@@ -1,4 +1,4 @@
apiVersion: autoscaling/v2beta2
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: podinfo

View File

@@ -1,34 +0,0 @@
package api
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestEchoHandler(t *testing.T) {
expected := `{"test": true}`
req, err := http.NewRequest("POST", "/api/echo", strings.NewReader(expected))
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
srv := NewMockServer()
handler := http.HandlerFunc(srv.echoHandler)
handler.ServeHTTP(rr, req)
// Check the status code is what we expect.
if status := rr.Code; status != http.StatusAccepted {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusAccepted)
}
// Check the response body is what we expect.
if rr.Body.String() != expected {
t.Fatalf("handler returned unexpected body:\ngot \n%v \nwant \n%s",
rr.Body.String(), expected)
}
}

20
pkg/api/grpc/echo.go Normal file
View File

@@ -0,0 +1,20 @@
package grpc
import (
"context"
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
"go.uber.org/zap"
)
type echoServer struct {
echo.UnimplementedEchoServiceServer
config *Config
logger *zap.Logger
}
func (s *echoServer) Echo (ctx context.Context, message *echo.Message) (*echo.Message, error){
s.logger.Info("Received message body from client:", zap.String("input body", message.Body))
return &echo.Message {Body: message.Body}, nil
}

View File

@@ -0,0 +1,146 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v4.24.3
// source: echo/echo.proto
package echo
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Message struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Body string `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
}
func (x *Message) Reset() {
*x = Message{}
if protoimpl.UnsafeEnabled {
mi := &file_echo_echo_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Message) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Message) ProtoMessage() {}
func (x *Message) ProtoReflect() protoreflect.Message {
mi := &file_echo_echo_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
func (*Message) Descriptor() ([]byte, []int) {
return file_echo_echo_proto_rawDescGZIP(), []int{0}
}
func (x *Message) GetBody() string {
if x != nil {
return x.Body
}
return ""
}
var File_echo_echo_proto protoreflect.FileDescriptor
var file_echo_echo_proto_rawDesc = []byte{
0x0a, 0x0f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x04, 0x65, 0x63, 0x68, 0x6f, 0x22, 0x1d, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x32, 0x35, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x0d, 0x2e,
0x65, 0x63, 0x68, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0d, 0x2e, 0x65,
0x63, 0x68, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a,
0x06, 0x2e, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_echo_echo_proto_rawDescOnce sync.Once
file_echo_echo_proto_rawDescData = file_echo_echo_proto_rawDesc
)
func file_echo_echo_proto_rawDescGZIP() []byte {
file_echo_echo_proto_rawDescOnce.Do(func() {
file_echo_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_echo_echo_proto_rawDescData)
})
return file_echo_echo_proto_rawDescData
}
var file_echo_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_echo_echo_proto_goTypes = []interface{}{
(*Message)(nil), // 0: echo.Message
}
var file_echo_echo_proto_depIdxs = []int32{
0, // 0: echo.EchoService.Echo:input_type -> echo.Message
0, // 1: echo.EchoService.Echo:output_type -> echo.Message
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_echo_echo_proto_init() }
func file_echo_echo_proto_init() {
if File_echo_echo_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_echo_echo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Message); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_echo_echo_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_echo_echo_proto_goTypes,
DependencyIndexes: file_echo_echo_proto_depIdxs,
MessageInfos: file_echo_echo_proto_msgTypes,
}.Build()
File_echo_echo_proto = out.File
file_echo_echo_proto_rawDesc = nil
file_echo_echo_proto_goTypes = nil
file_echo_echo_proto_depIdxs = nil
}

View File

@@ -0,0 +1,14 @@
syntax = "proto3";
option go_package = "./echo";
package echo;
message Message {
string body = 1;
}
service EchoService {
rpc Echo(Message) returns (Message) {}
}

View File

@@ -0,0 +1,109 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.3
// source: echo/echo.proto
package echo
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
EchoService_Echo_FullMethodName = "/echo.EchoService/Echo"
)
// EchoServiceClient is the client API for EchoService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type EchoServiceClient interface {
Echo(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error)
}
type echoServiceClient struct {
cc grpc.ClientConnInterface
}
func NewEchoServiceClient(cc grpc.ClientConnInterface) EchoServiceClient {
return &echoServiceClient{cc}
}
func (c *echoServiceClient) Echo(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) {
out := new(Message)
err := c.cc.Invoke(ctx, EchoService_Echo_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// EchoServiceServer is the server API for EchoService service.
// All implementations must embed UnimplementedEchoServiceServer
// for forward compatibility
type EchoServiceServer interface {
Echo(context.Context, *Message) (*Message, error)
mustEmbedUnimplementedEchoServiceServer()
}
// UnimplementedEchoServiceServer must be embedded to have forward compatible implementations.
type UnimplementedEchoServiceServer struct {
}
func (UnimplementedEchoServiceServer) Echo(context.Context, *Message) (*Message, error) {
return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented")
}
func (UnimplementedEchoServiceServer) mustEmbedUnimplementedEchoServiceServer() {}
// UnsafeEchoServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EchoServiceServer will
// result in compilation errors.
type UnsafeEchoServiceServer interface {
mustEmbedUnimplementedEchoServiceServer()
}
func RegisterEchoServiceServer(s grpc.ServiceRegistrar, srv EchoServiceServer) {
s.RegisterService(&EchoService_ServiceDesc, srv)
}
func _EchoService_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Message)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EchoServiceServer).Echo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EchoService_Echo_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EchoServiceServer).Echo(ctx, req.(*Message))
}
return interceptor(ctx, in, info, handler)
}
// EchoService_ServiceDesc is the grpc.ServiceDesc for EchoService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var EchoService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "echo.EchoService",
HandlerType: (*EchoServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Echo",
Handler: _EchoService_Echo_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "echo/echo.proto",
}

70
pkg/api/grpc/echo_test.go Normal file
View File

@@ -0,0 +1,70 @@
package grpc
import (
"context"
"log"
"net"
"regexp"
"testing"
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
"google.golang.org/grpc/test/bufconn"
)
func TestGrpcEcho(t *testing.T) {
// Server initialization
// bufconn => uses in-memory connection instead of system network I/O
lis := bufconn.Listen(1024*1024)
t.Cleanup(func() {
lis.Close()
})
s := NewMockGrpcServer()
srv := grpc.NewServer()
t.Cleanup(func() {
srv.Stop()
})
echo.RegisterEchoServiceServer(srv, &echoServer{config: s.config, logger: s.logger})
go func(){
if err := srv.Serve(lis); err != nil {
log.Fatalf("srv.Serve %v", err)
}
}()
// - Test
dialer := func(context.Context, string) (net.Conn, error){
return lis.Dial()
}
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(dialer), grpc.WithInsecure())
t.Cleanup(func() {
conn.Close()
})
if err != nil {
t.Fatalf("grpc.DialContext %v", err)
}
client := echo.NewEchoServiceClient(conn)
res , err := client.Echo(context.Background(), &echo.Message{Body:"test123-test"})
// Check the status code is what we expect.
if _, ok := status.FromError(err); !ok {
t.Errorf("Echo returned type %T, want %T", err, status.Error)
}
// Check the response body is what we expect.
expected := ".*body.*test123-test.*"
r := regexp.MustCompile(expected)
if !r.MatchString(res.String()) {
t.Fatalf("Returned unexpected body:\ngot \n%v \nwant \n%s",
res, expected)
}
}

31
pkg/api/grpc/mock_grpc.go Normal file
View File

@@ -0,0 +1,31 @@
package grpc
import (
"go.uber.org/zap"
)
func NewMockGrpcServer() *Server {
config := &Config{
Port: 9999,
// ServerShutdownTimeout: 5 * time.Second,
// HttpServerTimeout: 30 * time.Second,
BackendURL: []string{},
ConfigPath: "/config",
DataPath: "/data",
// HttpClientTimeout: 30 * time.Second,
UIColor: "blue",
UIPath: ".ui",
UIMessage: "Greetings",
Hostname: "localhost",
}
logger, _ := zap.NewDevelopment()
return &Server{
//router: mux.NewRouter(),
logger: logger,
config: config,
//tracer: trace.NewNoopTracerProvider().Tracer("mock"),
}
}

24
pkg/api/grpc/panic.go Normal file
View File

@@ -0,0 +1,24 @@
package grpc
import (
"context"
// "log"
"os"
pb "github.com/stefanprodan/podinfo/pkg/api/grpc/panic"
"go.uber.org/zap"
)
type PanicServer struct {
pb.UnimplementedPanicServiceServer
config *Config
logger *zap.Logger
}
func (s *PanicServer) Panic(ctx context.Context, req *pb.PanicRequest) (*pb.PanicResponse, error) {
s.logger.Info("Panic command received")
os.Exit(225)
return &pb.PanicResponse{}, nil
}

View File

@@ -0,0 +1,189 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.6.1
// source: panic.proto
package panic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type PanicRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *PanicRequest) Reset() {
*x = PanicRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_panic_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PanicRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PanicRequest) ProtoMessage() {}
func (x *PanicRequest) ProtoReflect() protoreflect.Message {
mi := &file_panic_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PanicRequest.ProtoReflect.Descriptor instead.
func (*PanicRequest) Descriptor() ([]byte, []int) {
return file_panic_proto_rawDescGZIP(), []int{0}
}
type PanicResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *PanicResponse) Reset() {
*x = PanicResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_panic_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PanicResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PanicResponse) ProtoMessage() {}
func (x *PanicResponse) ProtoReflect() protoreflect.Message {
mi := &file_panic_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PanicResponse.ProtoReflect.Descriptor instead.
func (*PanicResponse) Descriptor() ([]byte, []int) {
return file_panic_proto_rawDescGZIP(), []int{1}
}
var File_panic_proto protoreflect.FileDescriptor
var file_panic_proto_rawDesc = []byte{
0x0a, 0x0b, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70,
0x61, 0x6e, 0x69, 0x63, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x44, 0x0a, 0x0c, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x12, 0x13,
0x2e, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x50, 0x61, 0x6e, 0x69,
0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2e,
0x2f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_panic_proto_rawDescOnce sync.Once
file_panic_proto_rawDescData = file_panic_proto_rawDesc
)
func file_panic_proto_rawDescGZIP() []byte {
file_panic_proto_rawDescOnce.Do(func() {
file_panic_proto_rawDescData = protoimpl.X.CompressGZIP(file_panic_proto_rawDescData)
})
return file_panic_proto_rawDescData
}
var file_panic_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_panic_proto_goTypes = []interface{}{
(*PanicRequest)(nil), // 0: panic.PanicRequest
(*PanicResponse)(nil), // 1: panic.PanicResponse
}
var file_panic_proto_depIdxs = []int32{
0, // 0: panic.PanicService.Panic:input_type -> panic.PanicRequest
1, // 1: panic.PanicService.Panic:output_type -> panic.PanicResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_panic_proto_init() }
func file_panic_proto_init() {
if File_panic_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_panic_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PanicRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_panic_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PanicResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_panic_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_panic_proto_goTypes,
DependencyIndexes: file_panic_proto_depIdxs,
MessageInfos: file_panic_proto_msgTypes,
}.Build()
File_panic_proto = out.File
file_panic_proto_rawDesc = nil
file_panic_proto_goTypes = nil
file_panic_proto_depIdxs = nil
}

View File

@@ -0,0 +1,17 @@
syntax = "proto3";
option go_package = "./panic";
package panic;
// The greeting service definition.
service PanicService {
rpc Panic (PanicRequest) returns (PanicResponse) {}
}
message PanicRequest {
}
message PanicResponse {
}

View File

@@ -0,0 +1,105 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.6.1
// source: panic.proto
package panic
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// PanicServiceClient is the client API for PanicService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PanicServiceClient interface {
Panic(ctx context.Context, in *PanicRequest, opts ...grpc.CallOption) (*PanicResponse, error)
}
type panicServiceClient struct {
cc grpc.ClientConnInterface
}
func NewPanicServiceClient(cc grpc.ClientConnInterface) PanicServiceClient {
return &panicServiceClient{cc}
}
func (c *panicServiceClient) Panic(ctx context.Context, in *PanicRequest, opts ...grpc.CallOption) (*PanicResponse, error) {
out := new(PanicResponse)
err := c.cc.Invoke(ctx, "/panic.PanicService/Panic", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// PanicServiceServer is the server API for PanicService service.
// All implementations must embed UnimplementedPanicServiceServer
// for forward compatibility
type PanicServiceServer interface {
Panic(context.Context, *PanicRequest) (*PanicResponse, error)
mustEmbedUnimplementedPanicServiceServer()
}
// UnimplementedPanicServiceServer must be embedded to have forward compatible implementations.
type UnimplementedPanicServiceServer struct {
}
func (UnimplementedPanicServiceServer) Panic(context.Context, *PanicRequest) (*PanicResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Panic not implemented")
}
func (UnimplementedPanicServiceServer) mustEmbedUnimplementedPanicServiceServer() {}
// UnsafePanicServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PanicServiceServer will
// result in compilation errors.
type UnsafePanicServiceServer interface {
mustEmbedUnimplementedPanicServiceServer()
}
func RegisterPanicServiceServer(s grpc.ServiceRegistrar, srv PanicServiceServer) {
s.RegisterService(&PanicService_ServiceDesc, srv)
}
func _PanicService_Panic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PanicRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PanicServiceServer).Panic(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/panic.PanicService/Panic",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PanicServiceServer).Panic(ctx, req.(*PanicRequest))
}
return interceptor(ctx, in, info, handler)
}
// PanicService_ServiceDesc is the grpc.ServiceDesc for PanicService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PanicService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "panic.PanicService",
HandlerType: (*PanicServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Panic",
Handler: _PanicService_Panic_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "panic.proto",
}

93
pkg/api/grpc/server.go Normal file
View File

@@ -0,0 +1,93 @@
package grpc
import (
"fmt"
"net"
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
"github.com/stefanprodan/podinfo/pkg/api/grpc/panic"
"github.com/stefanprodan/podinfo/pkg/api/grpc/version"
)
type Server struct {
logger *zap.Logger
config *Config
}
type Config struct {
Port int `mapstructure:"grpc-port"`
ServiceName string `mapstructure:"grpc-service-name"`
BackendURL []string `mapstructure:"backend-url"`
UILogo string `mapstructure:"ui-logo"`
UIMessage string `mapstructure:"ui-message"`
UIColor string `mapstructure:"ui-color"`
UIPath string `mapstructure:"ui-path"`
DataPath string `mapstructure:"data-path"`
ConfigPath string `mapstructure:"config-path"`
CertPath string `mapstructure:"cert-path"`
Host string `mapstructure:"host"`
//Port string `mapstructure:"port"`
SecurePort string `mapstructure:"secure-port"`
PortMetrics int `mapstructure:"port-metrics"`
Hostname string `mapstructure:"hostname"`
H2C bool `mapstructure:"h2c"`
RandomDelay bool `mapstructure:"random-delay"`
RandomDelayUnit string `mapstructure:"random-delay-unit"`
RandomDelayMin int `mapstructure:"random-delay-min"`
RandomDelayMax int `mapstructure:"random-delay-max"`
RandomError bool `mapstructure:"random-error"`
Unhealthy bool `mapstructure:"unhealthy"`
Unready bool `mapstructure:"unready"`
JWTSecret string `mapstructure:"jwt-secret"`
CacheServer string `mapstructure:"cache-server"`
}
func NewServer(config *Config, logger *zap.Logger) (*Server, error) {
srv := &Server{
logger: logger,
config: config,
}
return srv, nil
}
func (s *Server) ListenAndServe() *grpc.Server {
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", s.config.Port))
if err != nil {
s.logger.Fatal("failed to listen", zap.Int("port", s.config.Port))
}
srv := grpc.NewServer()
server := health.NewServer()
// Register grpc apis for refection
echo.RegisterEchoServiceServer(srv, &echoServer{config: s.config, logger: s.logger})
version.RegisterVersionServiceServer(srv, &VersionServer{config: s.config, logger: s.logger})
panic.RegisterPanicServiceServer(srv, &PanicServer{config: s.config, logger: s.logger})
reflection.Register(srv)
grpc_health_v1.RegisterHealthServer(srv, server)
server.SetServingStatus(s.config.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
go func() {
if err := srv.Serve(listener); err != nil {
s.logger.Fatal("failed to serve", zap.Error(err))
}
}()
return srv
}

21
pkg/api/grpc/version.go Normal file
View File

@@ -0,0 +1,21 @@
package grpc
import (
"context"
pb "github.com/stefanprodan/podinfo/pkg/api/grpc/version"
"github.com/stefanprodan/podinfo/pkg/version"
"go.uber.org/zap"
)
type VersionServer struct {
pb.UnimplementedVersionServiceServer
config *Config
logger *zap.Logger
}
func (s *VersionServer) Version(ctx context.Context, req *pb.VersionRequest) (*pb.VersionResponse, error) {
return &pb.VersionResponse{Version: version.VERSION, Commit: version.REVISION}, nil
}

View File

@@ -0,0 +1,211 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.6.1
// source: version.proto
package version
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type VersionRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *VersionRequest) Reset() {
*x = VersionRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_version_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *VersionRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*VersionRequest) ProtoMessage() {}
func (x *VersionRequest) ProtoReflect() protoreflect.Message {
mi := &file_version_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use VersionRequest.ProtoReflect.Descriptor instead.
func (*VersionRequest) Descriptor() ([]byte, []int) {
return file_version_proto_rawDescGZIP(), []int{0}
}
type VersionResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
Commit string `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"`
}
func (x *VersionResponse) Reset() {
*x = VersionResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_version_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *VersionResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*VersionResponse) ProtoMessage() {}
func (x *VersionResponse) ProtoReflect() protoreflect.Message {
mi := &file_version_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use VersionResponse.ProtoReflect.Descriptor instead.
func (*VersionResponse) Descriptor() ([]byte, []int) {
return file_version_proto_rawDescGZIP(), []int{1}
}
func (x *VersionResponse) GetVersion() string {
if x != nil {
return x.Version
}
return ""
}
func (x *VersionResponse) GetCommit() string {
if x != nil {
return x.Commit
}
return ""
}
var File_version_proto protoreflect.FileDescriptor
var file_version_proto_rawDesc = []byte{
0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x10, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x43, 0x0a, 0x0f, 0x56, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x32,
0x50, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x2e, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_version_proto_rawDescOnce sync.Once
file_version_proto_rawDescData = file_version_proto_rawDesc
)
func file_version_proto_rawDescGZIP() []byte {
file_version_proto_rawDescOnce.Do(func() {
file_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_version_proto_rawDescData)
})
return file_version_proto_rawDescData
}
var file_version_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_version_proto_goTypes = []interface{}{
(*VersionRequest)(nil), // 0: version.VersionRequest
(*VersionResponse)(nil), // 1: version.VersionResponse
}
var file_version_proto_depIdxs = []int32{
0, // 0: version.VersionService.Version:input_type -> version.VersionRequest
1, // 1: version.VersionService.Version:output_type -> version.VersionResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_version_proto_init() }
func file_version_proto_init() {
if File_version_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*VersionRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_version_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*VersionResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_version_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_version_proto_goTypes,
DependencyIndexes: file_version_proto_depIdxs,
MessageInfos: file_version_proto_msgTypes,
}.Build()
File_version_proto = out.File
file_version_proto_rawDesc = nil
file_version_proto_goTypes = nil
file_version_proto_depIdxs = nil
}

View File

@@ -0,0 +1,18 @@
syntax = "proto3";
option go_package = "./version";
package version;
service VersionService {
rpc Version (VersionRequest) returns (VersionResponse) {}
}
message VersionRequest {}
message VersionResponse {
string version = 1;
string commit = 2;
}

View File

@@ -0,0 +1,105 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.6.1
// source: version.proto
package version
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// VersionServiceClient is the client API for VersionService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type VersionServiceClient interface {
Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error)
}
type versionServiceClient struct {
cc grpc.ClientConnInterface
}
func NewVersionServiceClient(cc grpc.ClientConnInterface) VersionServiceClient {
return &versionServiceClient{cc}
}
func (c *versionServiceClient) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) {
out := new(VersionResponse)
err := c.cc.Invoke(ctx, "/version.VersionService/Version", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// VersionServiceServer is the server API for VersionService service.
// All implementations must embed UnimplementedVersionServiceServer
// for forward compatibility
type VersionServiceServer interface {
Version(context.Context, *VersionRequest) (*VersionResponse, error)
mustEmbedUnimplementedVersionServiceServer()
}
// UnimplementedVersionServiceServer must be embedded to have forward compatible implementations.
type UnimplementedVersionServiceServer struct {
}
func (UnimplementedVersionServiceServer) Version(context.Context, *VersionRequest) (*VersionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
}
func (UnimplementedVersionServiceServer) mustEmbedUnimplementedVersionServiceServer() {}
// UnsafeVersionServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to VersionServiceServer will
// result in compilation errors.
type UnsafeVersionServiceServer interface {
mustEmbedUnimplementedVersionServiceServer()
}
func RegisterVersionServiceServer(s grpc.ServiceRegistrar, srv VersionServiceServer) {
s.RegisterService(&VersionService_ServiceDesc, srv)
}
func _VersionService_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(VersionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VersionServiceServer).Version(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/version.VersionService/Version",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VersionServiceServer).Version(ctx, req.(*VersionRequest))
}
return interceptor(ctx, in, info, handler)
}
// VersionService_ServiceDesc is the grpc.ServiceDesc for VersionService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var VersionService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "version.VersionService",
HandlerType: (*VersionServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Version",
Handler: _VersionService_Version_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "version.proto",
}

View File

@@ -0,0 +1,72 @@
package grpc
import (
"context"
"fmt"
"log"
"net"
"regexp"
"testing"
"github.com/stefanprodan/podinfo/pkg/api/grpc/version"
v "github.com/stefanprodan/podinfo/pkg/version"
"google.golang.org/grpc"
"google.golang.org/grpc/status"
"google.golang.org/grpc/test/bufconn"
)
func TestGrpcVersion(t *testing.T) {
// Server initialization
// bufconn => uses in-memory connection instead of system network I/O
lis := bufconn.Listen(1024*1024)
t.Cleanup(func() {
lis.Close()
})
srv := grpc.NewServer()
t.Cleanup(func() {
srv.Stop()
})
version.RegisterVersionServiceServer(srv, &VersionServer{})
go func(){
if err := srv.Serve(lis); err != nil {
log.Fatalf("srv.Serve %v", err)
}
}()
// - Test
dialer := func(context.Context, string) (net.Conn, error){
return lis.Dial()
}
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(dialer), grpc.WithInsecure())
t.Cleanup(func() {
conn.Close()
})
if err != nil {
t.Fatalf("grpc.DialContext %v", err)
}
client := version.NewVersionServiceClient(conn)
res , err := client.Version(context.Background(), &version.VersionRequest{})
// Check the status code is what we expect.
if _, ok := status.FromError(err); !ok {
t.Errorf("Version returned type %T, want %T", err, status.Error)
}
// Check the response body is what we expect.
expected := fmt.Sprintf(".*%s.*", v.VERSION)
r := regexp.MustCompile(expected)
if !r.MatchString(res.String()) {
t.Fatalf("Returned unexpected body:\ngot \n%v \nwant \n%s",
res, expected)
}
}

View File

@@ -1,8 +1,10 @@
package api
package http
import (
"io/ioutil"
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/gomodule/redigo/redis"
@@ -18,6 +20,7 @@ import (
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param key path string true "Key to save to"
// @Router /cache/{key} [post]
// @Success 202
func (s *Server) cacheWriteHandler(w http.ResponseWriter, r *http.Request) {
@@ -30,7 +33,7 @@ func (s *Server) cacheWriteHandler(w http.ResponseWriter, r *http.Request) {
}
key := mux.Vars(r)["key"]
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
s.ErrorResponse(w, r, span, "reading the request body failed", http.StatusBadRequest)
return
@@ -54,6 +57,7 @@ func (s *Server) cacheWriteHandler(w http.ResponseWriter, r *http.Request) {
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param key path string true "Key to delete"
// @Router /cache/{key} [delete]
// @Success 202
func (s *Server) cacheDeleteHandler(w http.ResponseWriter, r *http.Request) {
@@ -85,6 +89,7 @@ func (s *Server) cacheDeleteHandler(w http.ResponseWriter, r *http.Request) {
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param key path string true "Key to load from cache"
// @Router /cache/{key} [get]
// @Success 200 {string} string value
func (s *Server) cacheReadHandler(w http.ResponseWriter, r *http.Request) {
@@ -119,16 +124,31 @@ func (s *Server) cacheReadHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(data))
}
func (s *Server) startCachePool(ticker *time.Ticker, stopCh <-chan struct{}) {
func (s *Server) getCacheConn() (redis.Conn, error) {
redisUrl, err := url.Parse(s.config.CacheServer)
if err != nil {
return nil, fmt.Errorf("failed to parse redis url: %v", err)
}
var opts []redis.DialOption
if user := redisUrl.User; user != nil {
opts = append(opts, redis.DialUsername(user.Username()))
if password, ok := user.Password(); ok {
opts = append(opts, redis.DialPassword(password))
}
}
return redis.Dial("tcp", redisUrl.Host, opts...)
}
func (s *Server) startCachePool(ticker *time.Ticker) {
if s.config.CacheServer == "" {
return
}
s.pool = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", s.config.CacheServer)
},
Dial: s.getCacheConn,
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
@@ -149,8 +169,6 @@ func (s *Server) startCachePool(ticker *time.Ticker, stopCh <-chan struct{}) {
setVersion()
for {
select {
case <-stopCh:
return
case <-ticker.C:
setVersion()
}

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"math/rand"
@@ -15,6 +15,7 @@ import (
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param seconds path int true "seconds to wait for"
// @Router /chunked/{seconds} [get]
// @Success 200 {object} api.MapResponse
func (s *Server) chunkedHandler(w http.ResponseWriter, r *http.Request) {

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import "net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"math/rand"
@@ -49,6 +49,7 @@ func (m *RandomDelayMiddleware) Handler(next http.Handler) http.Handler {
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param seconds path int true "seconds to wait for"
// @Router /delay/{seconds} [get]
// @Success 200 {object} api.MapResponse
func (s *Server) delayHandler(w http.ResponseWriter, r *http.Request) {

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,22 +1,13 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs
import (
"bytes"
"encoding/json"
"strings"
import "github.com/swaggo/swag"
"github.com/alecthomas/template"
"github.com/swaggo/swag"
)
var doc = `{
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{.Description}}",
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"contact": {
"name": "Source Code",
@@ -110,6 +101,15 @@ var doc = `{
"HTTP API"
],
"summary": "Get payload from cache",
"parameters": [
{
"type": "string",
"description": "Key to load from cache",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -131,9 +131,18 @@ var doc = `{
"HTTP API"
],
"summary": "Save payload in cache",
"parameters": [
{
"type": "string",
"description": "Key to save to",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": ""
"description": "Accepted"
}
}
},
@@ -149,9 +158,18 @@ var doc = `{
"HTTP API"
],
"summary": "Delete payload from cache",
"parameters": [
{
"type": "string",
"description": "Key to delete",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": ""
"description": "Accepted"
}
}
}
@@ -169,6 +187,15 @@ var doc = `{
"HTTP API"
],
"summary": "Chunked transfer encoding",
"parameters": [
{
"type": "integer",
"description": "seconds to wait for",
"name": "seconds",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -192,6 +219,15 @@ var doc = `{
"HTTP API"
],
"summary": "Delay",
"parameters": [
{
"type": "integer",
"description": "seconds to wait for",
"name": "seconds",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -303,7 +339,8 @@ var doc = `{
"tags": [
"HTTP API"
],
"summary": "Panic"
"summary": "Panic",
"responses": {}
}
},
"/readyz": {
@@ -388,6 +425,15 @@ var doc = `{
"HTTP API"
],
"summary": "Status code",
"parameters": [
{
"type": "integer",
"description": "status code to return",
"name": "code",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -434,6 +480,15 @@ var doc = `{
"HTTP API"
],
"summary": "Download file",
"parameters": [
{
"type": "string",
"description": "hash value",
"name": "hash",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "file",
@@ -610,49 +665,20 @@ var doc = `{
}
}`
type swaggerInfo struct {
Version string
Host string
BasePath string
Schemes []string
Title string
Description string
}
// SwaggerInfo holds exported Swagger Info so clients can modify it
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{}
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{
"marshal": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
}).Parse(doc)
if err != nil {
return doc
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, sInfo); err != nil {
return doc
}
return tpl.String()
var SwaggerInfo = &swag.Spec{
Version: "2.0",
Host: "localhost:9898",
BasePath: "/",
Schemes: []string{"http", "https"},
Title: "Podinfo API",
Description: "Go microservice template for Kubernetes.",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
swag.Register(swag.Name, &s{})
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}

View File

@@ -99,6 +99,15 @@
"HTTP API"
],
"summary": "Get payload from cache",
"parameters": [
{
"type": "string",
"description": "Key to load from cache",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -120,9 +129,18 @@
"HTTP API"
],
"summary": "Save payload in cache",
"parameters": [
{
"type": "string",
"description": "Key to save to",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": ""
"description": "Accepted"
}
}
},
@@ -138,9 +156,18 @@
"HTTP API"
],
"summary": "Delete payload from cache",
"parameters": [
{
"type": "string",
"description": "Key to delete",
"name": "key",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": ""
"description": "Accepted"
}
}
}
@@ -158,6 +185,15 @@
"HTTP API"
],
"summary": "Chunked transfer encoding",
"parameters": [
{
"type": "integer",
"description": "seconds to wait for",
"name": "seconds",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -181,6 +217,15 @@
"HTTP API"
],
"summary": "Delay",
"parameters": [
{
"type": "integer",
"description": "seconds to wait for",
"name": "seconds",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -292,7 +337,8 @@
"tags": [
"HTTP API"
],
"summary": "Panic"
"summary": "Panic",
"responses": {}
}
},
"/readyz": {
@@ -377,6 +423,15 @@
"HTTP API"
],
"summary": "Status code",
"parameters": [
{
"type": "integer",
"description": "status code to return",
"name": "code",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
@@ -423,6 +478,15 @@
"HTTP API"
],
"summary": "Download file",
"parameters": [
{
"type": "string",
"description": "hash value",
"name": "hash",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "file",

View File

@@ -103,11 +103,17 @@ paths:
consumes:
- application/json
description: deletes the key and its value from cache
parameters:
- description: Key to delete
in: path
name: key
required: true
type: string
produces:
- application/json
responses:
"202":
description: ""
description: Accepted
summary: Delete payload from cache
tags:
- HTTP API
@@ -115,6 +121,12 @@ paths:
consumes:
- application/json
description: returns the content from cache if key exists
parameters:
- description: Key to load from cache
in: path
name: key
required: true
type: string
produces:
- application/json
responses:
@@ -129,11 +141,17 @@ paths:
consumes:
- application/json
description: writes the posted content in cache
parameters:
- description: Key to save to
in: path
name: key
required: true
type: string
produces:
- application/json
responses:
"202":
description: ""
description: Accepted
summary: Save payload in cache
tags:
- HTTP API
@@ -143,6 +161,12 @@ paths:
- application/json
description: uses transfer-encoding type chunked to give a partial response
and then waits for the specified period
parameters:
- description: seconds to wait for
in: path
name: seconds
required: true
type: integer
produces:
- application/json
responses:
@@ -158,6 +182,12 @@ paths:
consumes:
- application/json
description: waits for the specified period
parameters:
- description: seconds to wait for
in: path
name: seconds
required: true
type: integer
produces:
- application/json
responses:
@@ -233,6 +263,7 @@ paths:
/panic:
get:
description: crashes the process with exit code 255
responses: {}
summary: Panic
tags:
- HTTP API
@@ -287,6 +318,12 @@ paths:
consumes:
- application/json
description: sets the response status code to the specified code
parameters:
- description: status code to return
in: path
name: code
required: true
type: integer
produces:
- application/json
responses:
@@ -318,6 +355,12 @@ paths:
consumes:
- application/json
description: returns the content of the file /data/hash if exists
parameters:
- description: hash value
in: path
name: hash
required: true
type: string
produces:
- text/plain
responses:

View File

@@ -1,10 +1,10 @@
package api
package http
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/httptrace"
"sync"
@@ -27,7 +27,7 @@ func (s *Server) echoHandler(w http.ResponseWriter, r *http.Request) {
ctx, span := s.tracer.Start(r.Context(), "echoHandler")
defer span.End()
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
s.logger.Error("reading the request body failed", zap.Error(err))
s.ErrorResponse(w, r, span, "invalid request body", http.StatusBadRequest)
@@ -78,7 +78,7 @@ func (s *Server) echoHandler(w http.ResponseWriter, r *http.Request) {
}
// forward the received body
rbody, err := ioutil.ReadAll(resp.Body)
rbody, err := io.ReadAll(resp.Body)
if err != nil {
s.logger.Error(
"reading the backend request body failed",

48
pkg/api/http/echo_test.go Normal file
View File

@@ -0,0 +1,48 @@
package http
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestEchoHandler(t *testing.T) {
cases := []struct {
url string
method string
expected string
}{
{url: "/api/echo", method: "POST", expected: `{"test": true}`},
{url: "/api/echo", method: "PUT", expected: `{"test": true}`},
{url: "/echo", method: "PUT", expected: `{"test": true}`},
{url: "/echo/", method: "POST", expected: `{"test": true}`},
{url: "/echo/test", method: "POST", expected: `{"test": true}`},
{url: "/echo/test/", method: "POST", expected: `{"test": true}`},
{url: "/echo/test/test123-test", method: "POST", expected: `{"test": true}`},
}
srv := NewMockServer()
handler := http.HandlerFunc(srv.echoHandler)
for _, c := range cases {
req, err := http.NewRequest(c.method, c.url, strings.NewReader(c.expected))
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
// Check the status code is what we expect.
if status := rr.Code; status != http.StatusAccepted {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusAccepted)
}
// Check the response body is what we expect.
if rr.Body.String() != c.expected {
t.Fatalf("handler returned unexpected body:\ngot \n%v \nwant \n%s",
rr.Body.String(), c.expected)
}
}
}

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"bytes"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"html/template"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"bufio"

35
pkg/api/http/mock.go Normal file
View File

@@ -0,0 +1,35 @@
package http
import (
"time"
"go.opentelemetry.io/otel/trace"
"github.com/gorilla/mux"
"go.uber.org/zap"
)
func NewMockServer() *Server {
config := &Config{
Port: "9898",
ServerShutdownTimeout: 5 * time.Second,
HttpServerTimeout: 30 * time.Second,
BackendURL: []string{},
ConfigPath: "/config",
DataPath: "/data",
HttpClientTimeout: 30 * time.Second,
UIColor: "blue",
UIPath: ".ui",
UIMessage: "Greetings",
Hostname: "localhost",
}
logger, _ := zap.NewDevelopment()
return &Server{
router: mux.NewRouter(),
logger: logger,
config: config,
tracer: trace.NewNoopTracerProvider().Tracer("mock"),
}
}

View File

@@ -1,7 +1,8 @@
package api
package http
import (
"net/http"
"os"
)
// Panic godoc
@@ -10,5 +11,6 @@ import (
// @Tags HTTP API
// @Router /panic [get]
func (s *Server) panicHandler(w http.ResponseWriter, r *http.Request) {
s.logger.Panic("Panic command received")
s.logger.Info("Panic command received")
os.Exit(255)
}

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"context"
@@ -14,8 +14,7 @@ import (
"github.com/gomodule/redigo/redis"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/viper"
_ "github.com/stefanprodan/podinfo/pkg/api/docs"
_ "github.com/stefanprodan/podinfo/pkg/api/http/docs"
"github.com/stefanprodan/podinfo/pkg/fscache"
httpSwagger "github.com/swaggo/http-swagger"
"github.com/swaggo/swag"
@@ -47,32 +46,32 @@ var (
)
type Config struct {
HttpClientTimeout time.Duration `mapstructure:"http-client-timeout"`
HttpServerTimeout time.Duration `mapstructure:"http-server-timeout"`
HttpServerShutdownTimeout time.Duration `mapstructure:"http-server-shutdown-timeout"`
BackendURL []string `mapstructure:"backend-url"`
UILogo string `mapstructure:"ui-logo"`
UIMessage string `mapstructure:"ui-message"`
UIColor string `mapstructure:"ui-color"`
UIPath string `mapstructure:"ui-path"`
DataPath string `mapstructure:"data-path"`
ConfigPath string `mapstructure:"config-path"`
CertPath string `mapstructure:"cert-path"`
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
SecurePort string `mapstructure:"secure-port"`
PortMetrics int `mapstructure:"port-metrics"`
Hostname string `mapstructure:"hostname"`
H2C bool `mapstructure:"h2c"`
RandomDelay bool `mapstructure:"random-delay"`
RandomDelayUnit string `mapstructure:"random-delay-unit"`
RandomDelayMin int `mapstructure:"random-delay-min"`
RandomDelayMax int `mapstructure:"random-delay-max"`
RandomError bool `mapstructure:"random-error"`
Unhealthy bool `mapstructure:"unhealthy"`
Unready bool `mapstructure:"unready"`
JWTSecret string `mapstructure:"jwt-secret"`
CacheServer string `mapstructure:"cache-server"`
HttpClientTimeout time.Duration `mapstructure:"http-client-timeout"`
HttpServerTimeout time.Duration `mapstructure:"http-server-timeout"`
ServerShutdownTimeout time.Duration `mapstructure:"server-shutdown-timeout"`
BackendURL []string `mapstructure:"backend-url"`
UILogo string `mapstructure:"ui-logo"`
UIMessage string `mapstructure:"ui-message"`
UIColor string `mapstructure:"ui-color"`
UIPath string `mapstructure:"ui-path"`
DataPath string `mapstructure:"data-path"`
ConfigPath string `mapstructure:"config-path"`
CertPath string `mapstructure:"cert-path"`
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
SecurePort string `mapstructure:"secure-port"`
PortMetrics int `mapstructure:"port-metrics"`
Hostname string `mapstructure:"hostname"`
H2C bool `mapstructure:"h2c"`
RandomDelay bool `mapstructure:"random-delay"`
RandomDelayUnit string `mapstructure:"random-delay-unit"`
RandomDelayMin int `mapstructure:"random-delay-min"`
RandomDelayMax int `mapstructure:"random-delay-max"`
RandomError bool `mapstructure:"random-error"`
Unhealthy bool `mapstructure:"unhealthy"`
Unready bool `mapstructure:"unready"`
JWTSecret string `mapstructure:"jwt-secret"`
CacheServer string `mapstructure:"cache-server"`
}
type Server struct {
@@ -101,7 +100,8 @@ func (s *Server) registerHandlers() {
s.router.HandleFunc("/", s.indexHandler).HeadersRegexp("User-Agent", "^Mozilla.*").Methods("GET")
s.router.HandleFunc("/", s.infoHandler).Methods("GET")
s.router.HandleFunc("/version", s.versionHandler).Methods("GET")
s.router.HandleFunc("/echo", s.echoHandler).Methods("POST")
s.router.HandleFunc("/echo", s.echoHandler)
s.router.PathPrefix("/echo/").HandlerFunc(s.echoHandler)
s.router.HandleFunc("/env", s.envHandler).Methods("GET", "POST")
s.router.HandleFunc("/headers", s.echoHeadersHandler).Methods("GET", "POST")
s.router.HandleFunc("/delay/{wait:[0-9]+}", s.delayHandler).Methods("GET").Name("delay")
@@ -120,7 +120,8 @@ func (s *Server) registerHandlers() {
s.router.HandleFunc("/token", s.tokenGenerateHandler).Methods("POST")
s.router.HandleFunc("/token/validate", s.tokenValidateHandler).Methods("GET")
s.router.HandleFunc("/api/info", s.infoHandler).Methods("GET")
s.router.HandleFunc("/api/echo", s.echoHandler).Methods("POST")
s.router.HandleFunc("/api/echo", s.echoHandler)
s.router.PathPrefix("/api/echo/").HandlerFunc(s.echoHandler)
s.router.HandleFunc("/ws/echo", s.echoWsHandler)
s.router.HandleFunc("/chunked", s.chunkedHandler)
s.router.HandleFunc("/chunked/{wait:[0-9]+}", s.chunkedHandler)
@@ -153,7 +154,7 @@ func (s *Server) registerMiddlewares() {
}
}
func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
func (s *Server) ListenAndServe() (*http.Server, *http.Server, *int32, *int32) {
ctx := context.Background()
go s.startMetricsServer()
@@ -183,7 +184,7 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
// start redis connection pool
ticker := time.NewTicker(30 * time.Second)
s.startCachePool(ticker, stopCh)
s.startCachePool(ticker)
// create the http server
srv := s.startServer()
@@ -199,48 +200,7 @@ func (s *Server) ListenAndServe(stopCh <-chan struct{}) {
atomic.StoreInt32(&ready, 1)
}
// wait for SIGTERM or SIGINT
<-stopCh
ctx, cancel := context.WithTimeout(ctx, s.config.HttpServerShutdownTimeout)
defer cancel()
// all calls to /healthz and /readyz will fail from now on
atomic.StoreInt32(&healthy, 0)
atomic.StoreInt32(&ready, 0)
// close cache pool
if s.pool != nil {
_ = s.pool.Close()
}
s.logger.Info("Shutting down HTTP/HTTPS server", zap.Duration("timeout", s.config.HttpServerShutdownTimeout))
// wait for Kubernetes readiness probe to remove this instance from the load balancer
// the readiness check interval must be lower than the timeout
if viper.GetString("level") != "debug" {
time.Sleep(3 * time.Second)
}
// stop OpenTelemetry tracer provider
if s.tracerProvider != nil {
if err := s.tracerProvider.Shutdown(ctx); err != nil {
s.logger.Warn("stopping tracer provider", zap.Error(err))
}
}
// determine if the http server was started
if srv != nil {
if err := srv.Shutdown(ctx); err != nil {
s.logger.Warn("HTTP server graceful shutdown failed", zap.Error(err))
}
}
// determine if the secure server was started
if secureSrv != nil {
if err := secureSrv.Shutdown(ctx); err != nil {
s.logger.Warn("HTTPS server graceful shutdown failed", zap.Error(err))
}
}
return srv, secureSrv, &healthy, &ready
}
func (s *Server) startServer() *http.Server {

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"
@@ -14,6 +14,7 @@ import (
// @Tags HTTP API
// @Accept json
// @Produce json
// @Param code path int true "status code to return"
// @Router /status/{code} [get]
// @Success 200 {object} api.MapResponse
func (s *Server) statusHandler(w http.ResponseWriter, r *http.Request) {

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,10 +1,11 @@
package api
package http
import (
"crypto/sha1"
"encoding/hex"
"io/ioutil"
"io"
"net/http"
"os"
"path"
"github.com/gorilla/mux"
@@ -23,14 +24,14 @@ func (s *Server) storeWriteHandler(w http.ResponseWriter, r *http.Request) {
_, span := s.tracer.Start(r.Context(), "storeWriteHandler")
defer span.End()
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
s.ErrorResponse(w, r, span, "reading the request body failed", http.StatusBadRequest)
return
}
hash := hash(string(body))
err = ioutil.WriteFile(path.Join(s.config.DataPath, hash), body, 0644)
err = os.WriteFile(path.Join(s.config.DataPath, hash), body, 0644)
if err != nil {
s.logger.Warn("writing file failed", zap.Error(err), zap.String("file", path.Join(s.config.DataPath, hash)))
s.ErrorResponse(w, r, span, "writing file failed", http.StatusInternalServerError)
@@ -45,6 +46,7 @@ func (s *Server) storeWriteHandler(w http.ResponseWriter, r *http.Request) {
// @Tags HTTP API
// @Accept json
// @Produce plain
// @Param hash path string true "hash value"
// @Router /store/{hash} [get]
// @Success 200 {string} string "file"
func (s *Server) storeReadHandler(w http.ResponseWriter, r *http.Request) {
@@ -52,7 +54,7 @@ func (s *Server) storeReadHandler(w http.ResponseWriter, r *http.Request) {
defer span.End()
hash := mux.Vars(r)["hash"]
content, err := ioutil.ReadFile(path.Join(s.config.DataPath, hash))
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)

View File

@@ -1,14 +1,13 @@
package api
package http
import (
"fmt"
"io"
"net/http"
"strings"
"time"
"io/ioutil"
"github.com/dgrijalva/jwt-go/v4"
"github.com/golang-jwt/jwt/v4"
"go.uber.org/zap"
)
@@ -29,7 +28,7 @@ func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
_, span := s.tracer.Start(r.Context(), "tokenGenerateHandler")
defer span.End()
body, err := ioutil.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
s.logger.Error("reading the request body failed", zap.Error(err))
s.ErrorResponse(w, r, span, "invalid request body", http.StatusBadRequest)
@@ -47,7 +46,7 @@ func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
user,
jwt.StandardClaims{
Issuer: "podinfo",
ExpiresAt: jwt.At(expiresAt),
ExpiresAt: expiresAt.Unix(),
},
}
@@ -60,7 +59,7 @@ func (s *Server) tokenGenerateHandler(w http.ResponseWriter, r *http.Request) {
var result = TokenResponse{
Token: t,
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt.Unix(), 0),
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt, 0),
}
s.JSONResponse(w, r, result)
@@ -110,7 +109,7 @@ func (s *Server) tokenValidateHandler(w http.ResponseWriter, r *http.Request) {
} else {
var result = TokenValidationResponse{
TokenName: claims.Name,
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt.Unix(), 0),
ExpiresAt: time.Unix(claims.StandardClaims.ExpiresAt, 0),
}
s.JSONResponse(w, r, result)
}

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"encoding/json"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"context"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"net/http"

View File

@@ -1,4 +1,4 @@
package api
package http
import (
"fmt"

View File

@@ -1,35 +0,0 @@
package api
import (
"time"
"go.opentelemetry.io/otel/trace"
"github.com/gorilla/mux"
"go.uber.org/zap"
)
func NewMockServer() *Server {
config := &Config{
Port: "9898",
HttpServerShutdownTimeout: 5 * time.Second,
HttpServerTimeout: 30 * time.Second,
BackendURL: []string{},
ConfigPath: "/config",
DataPath: "/data",
HttpClientTimeout: 30 * time.Second,
UIColor: "blue",
UIPath: ".ui",
UIMessage: "Greetings",
Hostname: "localhost",
}
logger, _ := zap.NewDevelopment()
return &Server{
router: mux.NewRouter(),
logger: logger,
config: config,
tracer: trace.NewNoopTracerProvider().Tracer("mock"),
}
}

View File

@@ -2,8 +2,8 @@ package fscache
import (
"errors"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"sync"
@@ -77,7 +77,7 @@ func (w *Watcher) Watch() {
// updateCache reads files content and loads them into the cache
func (w *Watcher) updateCache() error {
fileMap := make(map[string]string)
files, err := ioutil.ReadDir(w.dir)
files, err := os.ReadDir(w.dir)
if err != nil {
return err
}
@@ -86,7 +86,7 @@ func (w *Watcher) updateCache() error {
for _, file := range files {
name := filepath.Base(file.Name())
if !file.IsDir() && !strings.Contains(name, "..") {
b, err := ioutil.ReadFile(filepath.Join(w.dir, file.Name()))
b, err := os.ReadFile(filepath.Join(w.dir, file.Name()))
if err != nil {
return err
}

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