Compare commits

..

87 Commits

Author SHA1 Message Date
github-actions[bot]
ad117a530f chore(main): release 0.3.40 (#1202)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-04 21:30:21 +01:00
Alex Jones
16d57e5a55 feat: initial custom analysis server mode (#1205)
* chore: initial custom analysis

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: saving the missing stuff

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: removed redundant error handling

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: missing piece of the custom analysis response

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-08-04 21:03:34 +01:00
renovate[bot]
3547c4808a fix(deps): update module github.com/schollz/progressbar/v3 to v3.14.5 (#1145)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-08-02 15:01:47 +01:00
renovate[bot]
407c855e14 chore(deps): update anchore/sbom-action action to v0.17.0 (#1197)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-02 14:42:24 +01:00
Yanwei Li
d43fd878ba fix: add default maxToken value of watsonxai backend (#1209)
Signed-off-by: yanweili <yanweili@ibm.com>
Co-authored-by: yanweili <yanweili@ibm.com>
2024-08-02 05:15:28 -04:00
Naveen Thangaraj
a068310731 feat: getting the error from status field for HPA analyzer (#1164)
* getting the error from status field for hpa analyzer

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Signed-off

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Updated the hpaAnalyzer_test.go

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Updated hpa_test.go

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Updated the hpa

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Updated the Conflicts

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Resolved all the conflicts

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

* Updated the test case

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>

---------

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Matthis <matthish29@gmail.com>
2024-07-22 09:25:38 +02:00
renovate[bot]
8949f5bac3 fix(deps): update module cloud.google.com/go/storage to v1.43.0 (#1198)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-21 18:20:27 +01:00
Matthis
f1b7b37fb8 feat: custom analysis paralelism (#1203) 2024-07-20 07:58:26 +02:00
Guangya Liu
391a3cd5ad fix: auth update throw out exception (#1193)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Matthis <matthish29@gmail.com>
2024-07-18 16:49:51 +01:00
github-actions[bot]
3c08118104 chore(main): release 0.3.39 (#1181)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-18 15:03:49 +01:00
JuHyung Son
eb3b81f176 feat: add label selector (#1201)
* feat: fix the custom-analysis printing (#1195)

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* feat: add label selector

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* feat: add label selector on analyzers

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* chore(deps): pin goreleaser/goreleaser-action action to 286f3b1 (#1171)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.4.0-20240715142657-3785f0a44aae.2 (#1196)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* chore(deps): update actions/upload-artifact digest to 0b2256b (#1175)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* chore: update proto pkg version

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* chore: fix typo

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* feat: add label string to LabelSelector util func

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* feat: add test using 2 label selector

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: JuHyung Son <sonju0427@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-18 14:31:41 +01:00
Ronald Petty
5176759bd0 feat: initial kyverno support (#1200)
* refresh fork

Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* let out, wasn't sure it was needed, but seems it might be in CI pipeline

Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): update docker/setup-buildx-action digest to 4fd8129 (#1173)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.20.0-20240406062209-1cc152efbf5c.1 (#1147)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): update anchore/sbom-action action to v0.16.0 (#1146)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module google.golang.org/grpc to v1.64.1 [security] (#1178)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module github.com/mittwald/go-helm-client to v0.12.10 (#1177)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* feat: add custom http headers to openai related api backends (#1174)

* feat: add custom http headers to openai related api backends

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* ci: add custom headers test

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* add error handling

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* chore(deps): update docker/setup-buildx-action digest to 4fd8129 (#1173)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.20.0-20240406062209-1cc152efbf5c.1 (#1147)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* chore(deps): update anchore/sbom-action action to v0.16.0 (#1146)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* Update README.md

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

---------

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(main): release 0.3.38 (#1165)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): update anchore/sbom-action action to v0.16.1 (#1179)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): update actions/setup-go digest to 0a12ed9 (#1182)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* ci: release to krew index as kubectl-gpt (#1100)

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update k8s.io/utils digest to 18e509b (#1183)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module github.com/prometheus/prometheus to v0.53.1 (#1035)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module github.com/ibm/watsonx-go to v1.0.1 (#1187)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* feat: skip k3s node type EtcdIsVoter (#1167)

Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* feat: fix the custom-analysis printing (#1195)

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): pin goreleaser/goreleaser-action action to 286f3b1 (#1171)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.4.0-20240715142657-3785f0a44aae.2 (#1196)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* chore(deps): update actions/upload-artifact digest to 0b2256b (#1175)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* Update pkg/integration/kyverno/kyverno.go

lgtm

Co-authored-by: Alex Jones <alex@k8sgpt.ai>
Signed-off-by: Ronald Petty <ronald.petty@minimumdistance.com>
Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

* remove unused function

Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>

---------

Signed-off-by: Ronald Petty <ronald.petty@rx-m.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Ronald Petty <ronald.petty@minimumdistance.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Miguel Varela Ramos <miguel@cohere.ai>
Co-authored-by: Kay Yan <kay.yan@daocloud.io>
Co-authored-by: Alex Jones <alex@k8sgpt.ai>
2024-07-18 07:57:11 +01:00
renovate[bot]
4b13727ef5 chore(deps): update actions/upload-artifact digest to 0b2256b (#1175)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-15 19:09:43 +01:00
renovate[bot]
f9edbf34f3 fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.4.0-20240715142657-3785f0a44aae.2 (#1196)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-15 18:50:16 +01:00
renovate[bot]
1a00aafbb2 chore(deps): pin goreleaser/goreleaser-action action to 286f3b1 (#1171)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-15 14:12:06 +01:00
Alex Jones
b6dd2a1181 feat: fix the custom-analysis printing (#1195)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-07-15 12:02:16 +01:00
Kay Yan
4366ad97b8 feat: skip k3s node type EtcdIsVoter (#1167)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-07-12 16:17:45 +01:00
renovate[bot]
34b6de3404 fix(deps): update module github.com/ibm/watsonx-go to v1.0.1 (#1187)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 17:12:43 +01:00
renovate[bot]
de9ef85878 fix(deps): update module github.com/prometheus/prometheus to v0.53.1 (#1035)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 12:33:10 +01:00
renovate[bot]
0b906511d5 fix(deps): update k8s.io/utils digest to 18e509b (#1183)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 11:05:15 +01:00
Miguel Varela Ramos
4d76e9c5ae ci: release to krew index as kubectl-gpt (#1100)
Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-07-11 09:37:46 +01:00
renovate[bot]
593139cffb chore(deps): update actions/setup-go digest to 0a12ed9 (#1182)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 09:12:37 +01:00
renovate[bot]
3e9340925c chore(deps): update anchore/sbom-action action to v0.16.1 (#1179)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-11 06:07:49 +01:00
github-actions[bot]
f6ce47c3a9 chore(main): release 0.3.38 (#1165)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-10 10:15:14 +01:00
Aris Boutselis
02e754ed59 feat: add custom http headers to openai related api backends (#1174)
* feat: add custom http headers to openai related api backends

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* ci: add custom headers test

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* add error handling

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* chore(deps): update docker/setup-buildx-action digest to 4fd8129 (#1173)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.20.0-20240406062209-1cc152efbf5c.1 (#1147)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* chore(deps): update anchore/sbom-action action to v0.16.0 (#1146)

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

* Update README.md

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>

---------

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-07-10 09:59:08 +01:00
renovate[bot]
fef853966f fix(deps): update module github.com/mittwald/go-helm-client to v0.12.10 (#1177)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-10 09:54:48 +01:00
renovate[bot]
dd20dbc982 fix(deps): update module google.golang.org/grpc to v1.64.1 [security] (#1178)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-10 09:48:40 +01:00
renovate[bot]
dd66355797 chore(deps): update anchore/sbom-action action to v0.16.0 (#1146)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-07-08 07:41:28 +01:00
renovate[bot]
314f25ac8b fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.20.0-20240406062209-1cc152efbf5c.1 (#1147)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-08 07:38:28 +01:00
renovate[bot]
d4abb33b3c chore(deps): update docker/setup-buildx-action digest to 4fd8129 (#1173)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-08 07:27:44 +01:00
renovate[bot]
27ac60aed2 chore(deps): update amannn/action-semantic-pull-request action to v5.5.3 (#1172)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-04 11:03:15 +01:00
renovate[bot]
0c0216096e chore(deps): update docker/build-push-action digest to ca052bb (#1140)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-03 21:23:15 +01:00
Kay Yan
b35dbd9b09 feat: add Ollama backend (#1065)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
2024-07-03 21:16:06 +01:00
renovate[bot]
a075792119 fix(deps): update module github.com/spf13/cobra to v1.8.1 (#1161)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 10:31:27 +01:00
Jin Song Wang
ce63821beb feat: add watsonx ai provider (#1163)
Signed-off-by: JINSONG WANG <jswang@ibm.com>
2024-07-01 10:20:44 +01:00
Rui Chen
ab534d184f chore: update brew installation note (#1155)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2024-06-20 17:43:47 +01:00
github-actions[bot]
3f80bbaa1b chore(main): release 0.3.37 (#1159)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-17 20:47:21 +01:00
Alex Jones
9bace02a67 chore: updated the goreleaser action (#1160)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-17 20:40:28 +01:00
renovate[bot]
7b1b63322e chore(deps): update reviewdog/action-golangci-lint digest to 7708105 (#1157)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-17 20:36:35 +01:00
github-actions[bot]
f963e4e0f4 chore(main): release 0.3.36 (#1152)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-17 20:25:59 +01:00
Alex Jones
2382de4c6f chore: fixed the goreleaser file (#1158)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-17 20:09:24 +01:00
renovate[bot]
55ae7c3298 chore(deps): update goreleaser/goreleaser-action digest to 5742e2a (#1153)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-17 19:59:44 +01:00
Rui Chen
aeae2ba765 chore: update goreleaser ldflags (#1154)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2024-06-17 19:59:20 +01:00
renovate[bot]
602d111d85 chore(deps): update docker/login-action digest to 0d4c9c5 (#1141)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-14 10:37:03 +01:00
github-actions[bot]
c3f164eb2b chore(main): release 0.3.35 (#1150)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-14 10:19:09 +01:00
ChristianBieri1995
92dd1bd8b0 feat: add spec.template.spec.securityContext (#1109)
* feat: add spec.template.spec.securityContext 

Signed-off-by: ChristianBieri1995 <122007149+ChristianBieri1995@users.noreply.github.com>

* make securityContext adjustable

Signed-off-by: ChristianBieri1995 <122007149+ChristianBieri1995@users.noreply.github.com>

* adjust values.yaml accordingly to enable adjustable securityContext

Signed-off-by: ChristianBieri1995 <122007149+ChristianBieri1995@users.noreply.github.com>

* Remove default values from securityContext

Signed-off-by: ChristianBieri1995 <122007149+ChristianBieri1995@users.noreply.github.com>

---------

Signed-off-by: ChristianBieri1995 <122007149+ChristianBieri1995@users.noreply.github.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-14 09:05:24 +01:00
JuHyung Son
4867d39c66 feat: support openai organization Id (#1133)
* feat: add organization flag

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

* feat: add orgId on openai backend

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>

---------

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-14 08:39:56 +01:00
Alex Jones
c834c09996 chore: updated goreleaser config (#1149)
Signed-off-by: Alex Jones <axjns@amazon.com>
Co-authored-by: Alex Jones <axjns@amazon.com>
2024-06-14 08:37:46 +01:00
github-actions[bot]
038e52e044 chore(main): release 0.3.34 (#1144)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-14 08:30:27 +01:00
Alex Jones
f9d734ee53 Revert "chore(deps): update goreleaser/goreleaser-action digest to 5742e2a (#…" (#1148)
This reverts commit c101e8a3ea.
2024-06-14 08:27:40 +01:00
renovate[bot]
c101e8a3ea chore(deps): update goreleaser/goreleaser-action digest to 5742e2a (#1142)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 10:33:11 +01:00
renovate[bot]
63b63f7664 chore(deps): update google-github-actions/release-please-action action to v4.1.1 (#1143)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 10:27:24 +01:00
github-actions[bot]
0fe984966a chore(main): release 0.3.33 (#1128)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-13 10:02:26 +01:00
renovate[bot]
3a893184af fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.6.0 [security] (#1138)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 09:44:24 +01:00
Kay Yan
6652fbe7cb feat: bump golang version to 1.22 (#1117)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-13 09:33:19 +01:00
Alex Jones
728555c0ef fix: advisory k8sgpt ghsa 85rg 8m6h 825p (#1139)
* chore: updated helmclient and helmv3

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: fixing tests

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-06-13 09:30:09 +01:00
renovate[bot]
bdd470f9ca fix(deps): update module github.com/aws/aws-sdk-go to v1.53.21 (#1106)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-12 18:52:04 +01:00
Ronald Petty
fad00eac49 fix(deps): typo in prometheus.go (#1137)
fix(deps): typo in prometheus.go

Signed-off-by: Ronald Petty <ronald.petty@gmail.com>
2024-06-12 18:34:38 +01:00
renovate[bot]
3452c0def6 chore(deps): update actions/setup-go digest to cdcb360 (#1096)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-04 12:59:53 +01:00
github-actions[bot]
ffd017fbd7 chore(main): release 0.3.32 (#1119)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-20 09:29:10 +01:00
Rui Chen
e261c09889 fix: remove shorthand flag for topp option in add command (#1115)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2024-05-20 09:06:35 +01:00
github-actions[bot]
cc890dfa46 chore(main): release 0.3.31 (#1077)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-16 16:23:41 +01:00
Anders Swanson
047afd46d6 feat: oci genai (#1102)
Signed-off-by: Anders Swanson <anders.swanson@oracle.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-05-16 15:44:41 +01:00
Vaibhav Malik
eda52312ae feat: implement Top-K sampling for improved user control (#1110)
This commit adds Top-K sampling, a feature that allows users to control
the randomness of the generated text by specifying the number of most
probable next words considered by the model. This enhances user control
and potentially improves the quality of the generated outputs.

Fixes: https://github.com/k8sgpt-ai/k8sgpt/issues/1105

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-05-16 15:41:07 +01:00
JuHyung Son
882c6f5225 feat: support AWS_PROFILE (#1114)
Signed-off-by: JuHyung-Son <sonju0427@gmail.com>
2024-05-16 15:36:33 +01:00
renovate[bot]
fe53907c44 fix(deps): update module golang.org/x/net to v0.25.0 (#1092)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-09 07:49:49 +01:00
Vaibhav Malik
63f7fcfef7 test: added tests for the pkg/integration package (#904)
This commit adds new tests for the `pkg/integration` package. As a
result, the code the code coverage of the package has increased from 0%
to 100%

This also includes a minor adjustment in the error statements of the
`Activate` and `Deactive` functions to ensure better understanding of
the cause of the error.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-05-09 07:18:59 +01:00
Vaibhav Malik
2c7c74472c test: added tests for the log analyzer (#1010)
* Added new tests for `LogAnalyzer` defined in the `pkg/analyzer`
  package. Increased the code coverage of the `log.go` file to >90%

Partially addresses: https://github.com/k8sgpt-ai/k8sgpt/issues/889

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-05-09 07:18:22 +01:00
renovate[bot]
3c4823127c fix(deps): update module github.com/aws/aws-sdk-go to v1.52.3 (#1094)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-07 12:18:15 +01:00
Vaibhav Malik
c3a884f0c4 test: added missing tests for pkg/analysis package (#908)
This commit bumps the code coverage of the `pkg/analysis` package to
60.8%

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: JuHyung Son <sonju0427@gmail.com>
2024-05-05 17:24:26 +01:00
renovate[bot]
e74fc0838f fix(deps): update module github.com/sashabaranov/go-openai to v1.23.0 (#1091)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 19:37:34 +01:00
renovate[bot]
f30c9f5554 fix(deps): update module github.com/google/generative-ai-go to v0.11.0 (#1089)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 14:30:22 +01:00
renovate[bot]
36ccc62846 fix(deps): update module github.com/cohere-ai/cohere-go/v2 to v2.7.3 (#1087)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 14:23:48 +01:00
renovate[bot]
a809a455f5 chore(deps): update amannn/action-semantic-pull-request action to v5.5.2 (#1088)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 14:18:07 +01:00
renovate[bot]
12fa5aef4d chore(deps): update anchore/sbom-action action to v0.15.11 (#1082)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 14:10:59 +01:00
renovate[bot]
75c2addf66 fix(deps): update module github.com/aws/aws-sdk-go to v1.51.32 (#1083)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 14:05:39 +01:00
renovate[bot]
9b797d7e8b chore(deps): update actions/upload-artifact digest to 6546280 (#1079)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 13:59:19 +01:00
renovate[bot]
820cd2e16c fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.3.0-20240406062209-1cc152efbf5c.3 (#1086)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 11:33:41 +01:00
renovate[bot]
43953ffa34 fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.2 (#1085)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-01 09:12:47 +01:00
renovate[bot]
bd695d0987 fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.5.2 (#1084)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 20:14:39 +01:00
renovate[bot]
b12c006c63 chore(deps): update docker/build-push-action digest to 2cdde99 (#1032)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 20:01:10 +01:00
renovate[bot]
e0af76f3c9 chore(deps): pin codecov/codecov-action action to ab904c4 (#1031)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 19:55:39 +01:00
renovate[bot]
e894e778e9 fix(deps): update k8s.io/utils digest to 0849a56 (#1080)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 10:53:52 +01:00
JuHyung Son
5cfe3325cb docs: add logAnalyzer in README.md (#1081)
Signed-off-by: JuHyung Son <sonju0427@gmail.com>
2024-04-28 09:08:43 +01:00
renovate[bot]
ea8183ce84 chore(deps): update actions/checkout digest to 0ad4b8f (#1078)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 17:24:30 +01:00
renovate[bot]
24cff90a0c fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.19.1-20240406062209-1cc152efbf5c.1 (#1070)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 14:44:25 +01:00
renovate[bot]
bf6f642c28 chore(deps): update google-github-actions/release-please-action action to v4.1.0 (#1045)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 10:58:29 +01:00
78 changed files with 3751 additions and 582 deletions

View File

@@ -13,7 +13,7 @@ on:
- "**.md"
env:
GO_VERSION: "~1.21"
GO_VERSION: "~1.22"
IMAGE_NAME: "k8sgpt"
defaults:
run:
@@ -33,7 +33,7 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- name: Extract branch name
id: extract_branch
@@ -70,14 +70,14 @@ jobs:
RELEASE_REGISTRY: "localhost:5000/k8sgpt"
steps:
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3
uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3
- name: Build Docker Image
uses: docker/build-push-action@af5a7ed5ba88268d5278f7203fb52cd833f66d6e # v5
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
platforms: linux/amd64
@@ -96,7 +96,7 @@ jobs:
outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}-image.tar
- name: Upload image as artifact
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
with:
name: ${{ env.IMAGE_NAME }}-image.tar
path: /tmp/${{ env.IMAGE_NAME }}-image.tar
@@ -115,10 +115,10 @@ jobs:
contents: read # Needed for checking out the repository
steps:
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}
@@ -126,10 +126,10 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3
uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3
- name: Build Docker Image
uses: docker/build-push-action@af5a7ed5ba88268d5278f7203fb52cd833f66d6e # v5
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
file: ./container/Dockerfile

View File

@@ -9,10 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- name: golangci-lint
uses: reviewdog/action-golangci-lint@00311c26a97213f93f2fd3a3524d66762e956ae0 # v2
uses: reviewdog/action-golangci-lint@7708105983c614f7a2725e2172908b7709d1c3e4 # v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-check

View File

@@ -23,9 +23,9 @@ jobs:
# Release-please creates a PR that tracks all changes
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- uses: google-github-actions/release-please-action@cc61a07e2da466bebbc19b3a7dd01d6aecb20d1e # v4.0.2
- uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1
id: release
with:
command: manifest
@@ -41,17 +41,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
with:
go-version: '1.21'
go-version: '1.22'
- name: Download Syft
uses: anchore/sbom-action/download-syft@ab5d7b5f48981941c4c5d6bf33aeb98fe3bae38c # v0.15.10
uses: anchore/sbom-action/download-syft@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
@@ -59,6 +59,8 @@ jobs:
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.K8SGPT_BOT_SECRET }}
- name: Update new version in krew-index
uses: rajatjindal/krew-release-bot@df3eb197549e3568be8b4767eec31c5e8e8e6ad8 # v0.0.46
build-container:
if: needs.release-please.outputs.releases_created == 'true'
@@ -74,23 +76,23 @@ jobs:
IMAGE_NAME: k8sgpt
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
with:
submodules: recursive
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3
uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3
- name: Login to GitHub Container Registry
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker Image
uses: docker/build-push-action@af5a7ed5ba88268d5278f7203fb52cd833f66d6e # v5
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
file: ./container/Dockerfile
@@ -104,7 +106,7 @@ jobs:
cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }}
- name: Generate SBOM
uses: anchore/sbom-action@ab5d7b5f48981941c4c5d6bf33aeb98fe3bae38c # v0.15.10
uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0
with:
image: ${{ env.IMAGE_TAG }}
artifact-name: sbom-${{ env.IMAGE_NAME }}

View File

@@ -16,7 +16,7 @@ jobs:
pull-requests: read # Needed for reading prs
steps:
- name: Validate Pull Request
uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0
uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:

View File

@@ -9,22 +9,22 @@ on:
- main
env:
GO_VERSION: "~1.21"
GO_VERSION: "~1.22"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run test
run: go test ./... -coverprofile=coverage.txt
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -1,3 +1,4 @@
version: 2
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
before:
@@ -14,12 +15,14 @@ builds:
- windows
- darwin
ldflags:
- -s -w -X main.version={{.Version}}
- -s -w -X main.commit={{.ShortCommit}}
- -s -w -X main.Date={{.CommitDate}}
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.ShortCommit}}
- -X main.Date={{.CommitDate}}
nfpms:
- file_name_template: '{{ .ProjectName }}_{{ .Arch }}'
- file_name_template: "{{ .ProjectName }}_{{ .Arch }}"
maintainer: "K8sGPT Maintainers <contact@k8sgpt.ai>"
homepage: https://k8sgpt.ai
description: >-
K8sGPT is a tool for scanning your kubernetes clusters, diagnosing and triaging issues in simple english. It has SRE experience codified into its analyzers and helps to pull out the most relevant information to enrich it with AI.
@@ -51,8 +54,8 @@ archives:
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
- goos: windows
format: zip
brews:
- name: k8sgpt
@@ -62,14 +65,12 @@ brews:
name: homebrew-k8sgpt
checksum:
name_template: 'checksums.txt'
name_template: "checksums.txt"
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
skip: true
# skip: true
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json

110
.krew.yaml Normal file
View File

@@ -0,0 +1,110 @@
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: gpt
spec:
version: {{ .TagName }}
homepage: https://github.com/k8sgpt-ai/k8sgpt
shortDescription: "Giving Kubernetes Superpowers to everyone"
description: |
A tool for scanning your Kubernetes clusters, diagnosing, and triaging issues in simple English.
platforms:
##########
# Darwin #
##########
- selector:
matchLabels:
os: darwin
arch: amd64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Darwin_x86_64.tar.gz" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Darwin_arm64.tar.gz" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
#########
# Linux #
#########
- selector:
matchLabels:
os: linux
arch: amd64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Linux_x86_64.tar.gz" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
- selector:
matchLabels:
os: linux
arch: arm64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Linux_arm64.tar.gz" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
- selector:
matchLabels:
os: linux
arch: "386"
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Linux_i386.tar.gz" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
###########
# Windows #
###########
- selector:
matchLabels:
os: windows
arch: amd64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Windows_x86_64.zip" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
- selector:
matchLabels:
os: windows
arch: arm64
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Windows_arm64.zip" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt
- selector:
matchLabels:
os: windows
arch: "386"
{{addURIAndSha "https://github.com/k8sgpt-ai/k8sgpt/releases/download/{{ .TagName }}/k8sgpt_Windows_i386.zip" .TagName | indent 6 }}
files:
- from: "k8sgpt"
to: "kubectl-gpt"
- from: "LICENSE"
to: "."
bin: kubectl-gpt

View File

@@ -1 +1 @@
{".":"0.3.30"}
{".":"0.3.40"}

View File

@@ -1,5 +1,186 @@
# Changelog
## [0.3.40](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.39...v0.3.40) (2024-08-04)
### Features
* custom analysis paralelism ([#1203](https://github.com/k8sgpt-ai/k8sgpt/issues/1203)) ([f1b7b37](https://github.com/k8sgpt-ai/k8sgpt/commit/f1b7b37fb83937d5fad90d7b6b52f4a38823da9e))
* getting the error from status field for HPA analyzer ([#1164](https://github.com/k8sgpt-ai/k8sgpt/issues/1164)) ([a068310](https://github.com/k8sgpt-ai/k8sgpt/commit/a068310731d775beecede03a1709e541ffd68142))
* initial custom analysis server mode ([#1205](https://github.com/k8sgpt-ai/k8sgpt/issues/1205)) ([16d57e5](https://github.com/k8sgpt-ai/k8sgpt/commit/16d57e5a55c2084bf1580377ae52e2961cc84922))
### Bug Fixes
* add default maxToken value of watsonxai backend ([#1209](https://github.com/k8sgpt-ai/k8sgpt/issues/1209)) ([d43fd87](https://github.com/k8sgpt-ai/k8sgpt/commit/d43fd878ba04fec8ac8afe4a1c15272b7f21c951))
* auth update throw out exception ([#1193](https://github.com/k8sgpt-ai/k8sgpt/issues/1193)) ([391a3cd](https://github.com/k8sgpt-ai/k8sgpt/commit/391a3cd5adcbd90f37922332b4fad5ba5d813e5f))
* **deps:** update module cloud.google.com/go/storage to v1.43.0 ([#1198](https://github.com/k8sgpt-ai/k8sgpt/issues/1198)) ([8949f5b](https://github.com/k8sgpt-ai/k8sgpt/commit/8949f5bac3c69130e30103511fdb5ece66e1619f))
* **deps:** update module github.com/schollz/progressbar/v3 to v3.14.5 ([#1145](https://github.com/k8sgpt-ai/k8sgpt/issues/1145)) ([3547c48](https://github.com/k8sgpt-ai/k8sgpt/commit/3547c4808a846eb4392996afa20a84bdddf8e24f))
### Other
* **deps:** update anchore/sbom-action action to v0.17.0 ([#1197](https://github.com/k8sgpt-ai/k8sgpt/issues/1197)) ([407c855](https://github.com/k8sgpt-ai/k8sgpt/commit/407c855e147b73739e800310c926826344d36323))
## [0.3.39](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.38...v0.3.39) (2024-07-18)
### Features
* add label selector ([#1201](https://github.com/k8sgpt-ai/k8sgpt/issues/1201)) ([eb3b81f](https://github.com/k8sgpt-ai/k8sgpt/commit/eb3b81f1767c589474864992ae78001ab1b376a1))
* fix the custom-analysis printing ([#1195](https://github.com/k8sgpt-ai/k8sgpt/issues/1195)) ([b6dd2a1](https://github.com/k8sgpt-ai/k8sgpt/commit/b6dd2a1181b478a4fb8543ab7529ce595fa7d4a8))
* initial kyverno support ([#1200](https://github.com/k8sgpt-ai/k8sgpt/issues/1200)) ([5176759](https://github.com/k8sgpt-ai/k8sgpt/commit/5176759bd0fad8671164f9e75b31dec19f02bd54))
* skip k3s node type EtcdIsVoter ([#1167](https://github.com/k8sgpt-ai/k8sgpt/issues/1167)) ([4366ad9](https://github.com/k8sgpt-ai/k8sgpt/commit/4366ad97b80d2df0400e06e4b892fadab3939dc7))
### Bug Fixes
* **deps:** update k8s.io/utils digest to 18e509b ([#1183](https://github.com/k8sgpt-ai/k8sgpt/issues/1183)) ([0b90651](https://github.com/k8sgpt-ai/k8sgpt/commit/0b906511d5a9837c9a67cf819754c610b1becc5c))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.4.0-20240715142657-3785f0a44aae.2 ([#1196](https://github.com/k8sgpt-ai/k8sgpt/issues/1196)) ([f9edbf3](https://github.com/k8sgpt-ai/k8sgpt/commit/f9edbf34f3eb3e90528d04b1c470fd6ef15293ec))
* **deps:** update module github.com/ibm/watsonx-go to v1.0.1 ([#1187](https://github.com/k8sgpt-ai/k8sgpt/issues/1187)) ([34b6de3](https://github.com/k8sgpt-ai/k8sgpt/commit/34b6de34041ce253c1c680a7f5fe535b03a50da5))
* **deps:** update module github.com/prometheus/prometheus to v0.53.1 ([#1035](https://github.com/k8sgpt-ai/k8sgpt/issues/1035)) ([de9ef85](https://github.com/k8sgpt-ai/k8sgpt/commit/de9ef8587822814542661e0039b47ef65d902abb))
### Other
* **deps:** pin goreleaser/goreleaser-action action to 286f3b1 ([#1171](https://github.com/k8sgpt-ai/k8sgpt/issues/1171)) ([1a00aaf](https://github.com/k8sgpt-ai/k8sgpt/commit/1a00aafbb2f6f1482dfb3da7e96954b12ad5a4fd))
* **deps:** update actions/setup-go digest to 0a12ed9 ([#1182](https://github.com/k8sgpt-ai/k8sgpt/issues/1182)) ([593139c](https://github.com/k8sgpt-ai/k8sgpt/commit/593139cffb1982fe45ccc9403acc893f51064271))
* **deps:** update actions/upload-artifact digest to 0b2256b ([#1175](https://github.com/k8sgpt-ai/k8sgpt/issues/1175)) ([4b13727](https://github.com/k8sgpt-ai/k8sgpt/commit/4b13727ef579240adc2777d1126544fafb23b993))
* **deps:** update anchore/sbom-action action to v0.16.1 ([#1179](https://github.com/k8sgpt-ai/k8sgpt/issues/1179)) ([3e93409](https://github.com/k8sgpt-ai/k8sgpt/commit/3e9340925c3d59861b1a95d5c1bc08c19ec26e4a))
## [0.3.38](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.37...v0.3.38) (2024-07-10)
### Features
* add custom http headers to openai related api backends ([#1174](https://github.com/k8sgpt-ai/k8sgpt/issues/1174)) ([02e754e](https://github.com/k8sgpt-ai/k8sgpt/commit/02e754ed591742fccc5ff9a20c3e36e4475f6ec5))
* add Ollama backend ([#1065](https://github.com/k8sgpt-ai/k8sgpt/issues/1065)) ([b35dbd9](https://github.com/k8sgpt-ai/k8sgpt/commit/b35dbd9b09197994f041cda04f1a4e5fb316e468))
* add watsonx ai provider ([#1163](https://github.com/k8sgpt-ai/k8sgpt/issues/1163)) ([ce63821](https://github.com/k8sgpt-ai/k8sgpt/commit/ce63821bebbd87b2e058f5cf58a2cdd474b8fb58))
### Bug Fixes
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.20.0-20240406062209-1cc152efbf5c.1 ([#1147](https://github.com/k8sgpt-ai/k8sgpt/issues/1147)) ([314f25a](https://github.com/k8sgpt-ai/k8sgpt/commit/314f25ac8bf5c3629474ece0eae6a3bda83099aa))
* **deps:** update module github.com/mittwald/go-helm-client to v0.12.10 ([#1177](https://github.com/k8sgpt-ai/k8sgpt/issues/1177)) ([fef8539](https://github.com/k8sgpt-ai/k8sgpt/commit/fef853966fc6e33dae0a9686fa767b36201c0228))
* **deps:** update module github.com/spf13/cobra to v1.8.1 ([#1161](https://github.com/k8sgpt-ai/k8sgpt/issues/1161)) ([a075792](https://github.com/k8sgpt-ai/k8sgpt/commit/a0757921191205398539a6ccc8dbfaa503db595f))
* **deps:** update module google.golang.org/grpc to v1.64.1 [security] ([#1178](https://github.com/k8sgpt-ai/k8sgpt/issues/1178)) ([dd20dbc](https://github.com/k8sgpt-ai/k8sgpt/commit/dd20dbc9829fc50f77ad6a32c3a10dcf221d2750))
### Other
* **deps:** update amannn/action-semantic-pull-request action to v5.5.3 ([#1172](https://github.com/k8sgpt-ai/k8sgpt/issues/1172)) ([27ac60a](https://github.com/k8sgpt-ai/k8sgpt/commit/27ac60aed296c3d9582f34e14c5985a4bccd991e))
* **deps:** update anchore/sbom-action action to v0.16.0 ([#1146](https://github.com/k8sgpt-ai/k8sgpt/issues/1146)) ([dd66355](https://github.com/k8sgpt-ai/k8sgpt/commit/dd6635579789ce65ee86dc1196e7dfde1b7d20e6))
* **deps:** update docker/build-push-action digest to ca052bb ([#1140](https://github.com/k8sgpt-ai/k8sgpt/issues/1140)) ([0c02160](https://github.com/k8sgpt-ai/k8sgpt/commit/0c0216096efde9c2c812ee90522c081f51c52631))
* **deps:** update docker/setup-buildx-action digest to 4fd8129 ([#1173](https://github.com/k8sgpt-ai/k8sgpt/issues/1173)) ([d4abb33](https://github.com/k8sgpt-ai/k8sgpt/commit/d4abb33b3c29d9a2e4dee094ea7be2bc5d1807d1))
* update brew installation note ([#1155](https://github.com/k8sgpt-ai/k8sgpt/issues/1155)) ([ab534d1](https://github.com/k8sgpt-ai/k8sgpt/commit/ab534d184fcd538f2ba10a6b5bf3a74c28d5fee6))
## [0.3.37](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.36...v0.3.37) (2024-06-17)
### Other
* **deps:** update reviewdog/action-golangci-lint digest to 7708105 ([#1157](https://github.com/k8sgpt-ai/k8sgpt/issues/1157)) ([7b1b633](https://github.com/k8sgpt-ai/k8sgpt/commit/7b1b63322ec7b0c0864682bc23be6e70c0ed7ec7))
* updated the goreleaser action ([#1160](https://github.com/k8sgpt-ai/k8sgpt/issues/1160)) ([9bace02](https://github.com/k8sgpt-ai/k8sgpt/commit/9bace02a6702a8af0e6511b51ffc38378e14d3cb))
## [0.3.36](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.35...v0.3.36) (2024-06-17)
### Other
* **deps:** update docker/login-action digest to 0d4c9c5 ([#1141](https://github.com/k8sgpt-ai/k8sgpt/issues/1141)) ([602d111](https://github.com/k8sgpt-ai/k8sgpt/commit/602d111d8568d38cda744d2b179ee2d3eb59ba02))
* **deps:** update goreleaser/goreleaser-action digest to 5742e2a ([#1153](https://github.com/k8sgpt-ai/k8sgpt/issues/1153)) ([55ae7c3](https://github.com/k8sgpt-ai/k8sgpt/commit/55ae7c32986100d4b0bab6dcaf7a52ac7b37aa5f))
* fixed the goreleaser file ([#1158](https://github.com/k8sgpt-ai/k8sgpt/issues/1158)) ([2382de4](https://github.com/k8sgpt-ai/k8sgpt/commit/2382de4c6f82de535b67c2752d7c502d0a8b2b66))
* update goreleaser ldflags ([#1154](https://github.com/k8sgpt-ai/k8sgpt/issues/1154)) ([aeae2ba](https://github.com/k8sgpt-ai/k8sgpt/commit/aeae2ba765c7db6e4953b5a93c54617f1dd85efa))
## [0.3.35](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.34...v0.3.35) (2024-06-14)
### Features
* add spec.template.spec.securityContext ([#1109](https://github.com/k8sgpt-ai/k8sgpt/issues/1109)) ([92dd1bd](https://github.com/k8sgpt-ai/k8sgpt/commit/92dd1bd8b08c5173f72a6c333f626c63aa05a1d3))
* support openai organization Id ([#1133](https://github.com/k8sgpt-ai/k8sgpt/issues/1133)) ([4867d39](https://github.com/k8sgpt-ai/k8sgpt/commit/4867d39c66a6c16906cd769a2055dea9f66f1ccb))
### Other
* updated goreleaser config ([#1149](https://github.com/k8sgpt-ai/k8sgpt/issues/1149)) ([c834c09](https://github.com/k8sgpt-ai/k8sgpt/commit/c834c099969f3e888f49f73fba6794387063a6fc))
## [0.3.34](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.33...v0.3.34) (2024-06-14)
### Other
* **deps:** update google-github-actions/release-please-action action to v4.1.1 ([#1143](https://github.com/k8sgpt-ai/k8sgpt/issues/1143)) ([63b63f7](https://github.com/k8sgpt-ai/k8sgpt/commit/63b63f7664277042188351073f269569bfec65bf))
* **deps:** update goreleaser/goreleaser-action digest to 5742e2a ([#1142](https://github.com/k8sgpt-ai/k8sgpt/issues/1142)) ([c101e8a](https://github.com/k8sgpt-ai/k8sgpt/commit/c101e8a3ea6d911d00ca2a51986edc5425a1042a))
## [0.3.33](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.32...v0.3.33) (2024-06-13)
### Features
* bump golang version to 1.22 ([#1117](https://github.com/k8sgpt-ai/k8sgpt/issues/1117)) ([6652fbe](https://github.com/k8sgpt-ai/k8sgpt/commit/6652fbe7cb6e581497e1d086e13397ff9e5b11be))
### Bug Fixes
* advisory k8sgpt ghsa 85rg 8m6h 825p ([#1139](https://github.com/k8sgpt-ai/k8sgpt/issues/1139)) ([728555c](https://github.com/k8sgpt-ai/k8sgpt/commit/728555c0effbf7a56221d625bcbbf62f74d14359))
* **deps:** typo in prometheus.go ([fad00ea](https://github.com/k8sgpt-ai/k8sgpt/commit/fad00eac4925351c4dc6fd6dd347fe2968f0b7a5))
* **deps:** typo in prometheus.go ([#1137](https://github.com/k8sgpt-ai/k8sgpt/issues/1137)) ([fad00ea](https://github.com/k8sgpt-ai/k8sgpt/commit/fad00eac4925351c4dc6fd6dd347fe2968f0b7a5))
* **deps:** update module github.com/aws/aws-sdk-go to v1.53.21 ([#1106](https://github.com/k8sgpt-ai/k8sgpt/issues/1106)) ([bdd470f](https://github.com/k8sgpt-ai/k8sgpt/commit/bdd470f9cae917f965badd22da7def4a7d64d2ae))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.6.0 [security] ([#1138](https://github.com/k8sgpt-ai/k8sgpt/issues/1138)) ([3a89318](https://github.com/k8sgpt-ai/k8sgpt/commit/3a893184af50f8c822ac06ce0e20818eaec587b1))
### Other
* **deps:** update actions/setup-go digest to cdcb360 ([#1096](https://github.com/k8sgpt-ai/k8sgpt/issues/1096)) ([3452c0d](https://github.com/k8sgpt-ai/k8sgpt/commit/3452c0def68fd5352d2d09201f813f657245bd9f))
## [0.3.32](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.31...v0.3.32) (2024-05-20)
### Bug Fixes
* remove shorthand flag for topp option in add command ([#1115](https://github.com/k8sgpt-ai/k8sgpt/issues/1115)) ([e261c09](https://github.com/k8sgpt-ai/k8sgpt/commit/e261c09889359d5870acb9720ff033440f835f8f))
## [0.3.31](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.30...v0.3.31) (2024-05-16)
### Features
* implement Top-K sampling for improved user control ([#1110](https://github.com/k8sgpt-ai/k8sgpt/issues/1110)) ([eda5231](https://github.com/k8sgpt-ai/k8sgpt/commit/eda52312aef8113debbd770b8354c3a3cb1cc681))
* oci genai ([#1102](https://github.com/k8sgpt-ai/k8sgpt/issues/1102)) ([047afd4](https://github.com/k8sgpt-ai/k8sgpt/commit/047afd46d62d1bd1da1435550cbaf9daaca53aee))
* support AWS_PROFILE ([#1114](https://github.com/k8sgpt-ai/k8sgpt/issues/1114)) ([882c6f5](https://github.com/k8sgpt-ai/k8sgpt/commit/882c6f52252000da436e4fed9fd184b263f5a017))
### Bug Fixes
* **deps:** update k8s.io/utils digest to 0849a56 ([#1080](https://github.com/k8sgpt-ai/k8sgpt/issues/1080)) ([e894e77](https://github.com/k8sgpt-ai/k8sgpt/commit/e894e778e91d070448cd4a3f46dfc98dd588c9ed))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.19.1-20240406062209-1cc152efbf5c.1 ([#1070](https://github.com/k8sgpt-ai/k8sgpt/issues/1070)) ([24cff90](https://github.com/k8sgpt-ai/k8sgpt/commit/24cff90a0ca7488e48c94d13678529617c749aab))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.3.0-20240406062209-1cc152efbf5c.3 ([#1086](https://github.com/k8sgpt-ai/k8sgpt/issues/1086)) ([820cd2e](https://github.com/k8sgpt-ai/k8sgpt/commit/820cd2e16cbca2c89b56a4d2a69f95f3f5cd6c6b))
* **deps:** update module github.com/aws/aws-sdk-go to v1.51.32 ([#1083](https://github.com/k8sgpt-ai/k8sgpt/issues/1083)) ([75c2add](https://github.com/k8sgpt-ai/k8sgpt/commit/75c2addf66a54df57d0c0ac17f0b359f7612e446))
* **deps:** update module github.com/aws/aws-sdk-go to v1.52.3 ([#1094](https://github.com/k8sgpt-ai/k8sgpt/issues/1094)) ([3c48231](https://github.com/k8sgpt-ai/k8sgpt/commit/3c4823127ca04d1d280da6d932e951e6c3f71536))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.5.2 ([#1084](https://github.com/k8sgpt-ai/k8sgpt/issues/1084)) ([bd695d0](https://github.com/k8sgpt-ai/k8sgpt/commit/bd695d0987e8ec12b44512c46bc5f2e5116076bd))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.2 ([#1085](https://github.com/k8sgpt-ai/k8sgpt/issues/1085)) ([43953ff](https://github.com/k8sgpt-ai/k8sgpt/commit/43953ffa3412ae97b6d54ed14b94955d1b73feba))
* **deps:** update module github.com/cohere-ai/cohere-go/v2 to v2.7.3 ([#1087](https://github.com/k8sgpt-ai/k8sgpt/issues/1087)) ([36ccc62](https://github.com/k8sgpt-ai/k8sgpt/commit/36ccc628462ad102712fca115b56f521b2b33b38))
* **deps:** update module github.com/google/generative-ai-go to v0.11.0 ([#1089](https://github.com/k8sgpt-ai/k8sgpt/issues/1089)) ([f30c9f5](https://github.com/k8sgpt-ai/k8sgpt/commit/f30c9f555449bb90bf8242b88b8fae936cb57938))
* **deps:** update module github.com/sashabaranov/go-openai to v1.23.0 ([#1091](https://github.com/k8sgpt-ai/k8sgpt/issues/1091)) ([e74fc08](https://github.com/k8sgpt-ai/k8sgpt/commit/e74fc0838feac5a019a340f7c5ad1c9ae49913fa))
* **deps:** update module golang.org/x/net to v0.25.0 ([#1092](https://github.com/k8sgpt-ai/k8sgpt/issues/1092)) ([fe53907](https://github.com/k8sgpt-ai/k8sgpt/commit/fe53907c44e9cd56b6747f52ae3402bc6ae2bd49))
### Other
* **deps:** pin codecov/codecov-action action to ab904c4 ([#1031](https://github.com/k8sgpt-ai/k8sgpt/issues/1031)) ([e0af76f](https://github.com/k8sgpt-ai/k8sgpt/commit/e0af76f3c9c0120dbc4d9373d69a262e1ec2b7f2))
* **deps:** update actions/checkout digest to 0ad4b8f ([#1078](https://github.com/k8sgpt-ai/k8sgpt/issues/1078)) ([ea8183c](https://github.com/k8sgpt-ai/k8sgpt/commit/ea8183ce848ba58f91cfa68755d6f5b9cf695d36))
* **deps:** update actions/upload-artifact digest to 6546280 ([#1079](https://github.com/k8sgpt-ai/k8sgpt/issues/1079)) ([9b797d7](https://github.com/k8sgpt-ai/k8sgpt/commit/9b797d7e8b4f704dae12acaa7778b6b65e2c36ac))
* **deps:** update amannn/action-semantic-pull-request action to v5.5.2 ([#1088](https://github.com/k8sgpt-ai/k8sgpt/issues/1088)) ([a809a45](https://github.com/k8sgpt-ai/k8sgpt/commit/a809a455f55d1af104ebc0540007aa678581dd21))
* **deps:** update anchore/sbom-action action to v0.15.11 ([#1082](https://github.com/k8sgpt-ai/k8sgpt/issues/1082)) ([12fa5ae](https://github.com/k8sgpt-ai/k8sgpt/commit/12fa5aef4dada597d7059e5717ec7bee3b38c122))
* **deps:** update docker/build-push-action digest to 2cdde99 ([#1032](https://github.com/k8sgpt-ai/k8sgpt/issues/1032)) ([b12c006](https://github.com/k8sgpt-ai/k8sgpt/commit/b12c006c6304165269b90d770048b851e1aa1d1f))
* **deps:** update google-github-actions/release-please-action action to v4.1.0 ([#1045](https://github.com/k8sgpt-ai/k8sgpt/issues/1045)) ([bf6f642](https://github.com/k8sgpt-ai/k8sgpt/commit/bf6f642c280f640f2c9020b325e52670ced2cf50))
### Docs
* add logAnalyzer in README.md ([#1081](https://github.com/k8sgpt-ai/k8sgpt/issues/1081)) ([5cfe332](https://github.com/k8sgpt-ai/k8sgpt/commit/5cfe3325cb556cfb9d0532ae26727441c5177015))
## [0.3.30](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.29...v0.3.30) (2024-04-26)

View File

@@ -8,12 +8,12 @@
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/k8sgpt-ai/k8sgpt/release.yaml)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/k8sgpt-ai/k8sgpt)
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7272/badge)](https://bestpractices.coreinfrastructure.org/projects/7272)
[![Link to documentation](https://img.shields.io/static/v1?label=%F0%9F%93%96&message=Documentation&color=blue)](https://docs.k8sgpt.ai/)
[![Link to documentation](https://img.shields.io/static/v1?label=%F0%9F%93%96&message=Documentation&color=blue)](https://docs.k8sgpt.ai/)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fk8sgpt-ai%2Fk8sgpt.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fk8sgpt-ai%2Fk8sgpt?ref=badge_shield)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Go version](https://img.shields.io/github/go-mod/go-version/k8sgpt-ai/k8sgpt.svg)](https://github.com/k8sgpt-ai/k8sgpt)
[![codecov](https://codecov.io/github/k8sgpt-ai/k8sgpt/graph/badge.svg?token=ZLR7NG8URE)](https://codecov.io/github/k8sgpt-ai/k8sgpt)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/k8sgpt-ai/k8sgpt/main)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/k8sgpt-ai/k8sgpt/main)
`k8sgpt` is a tool for scanning your Kubernetes clusters, diagnosing, and triaging issues in simple English.
@@ -30,7 +30,13 @@ _Out of the box integration with OpenAI, Azure, Cohere, Amazon Bedrock, Google G
### Linux/Mac via brew
```sh
$ brew install k8sgpt
```
or
```sh
brew tap k8sgpt-ai/k8sgpt
brew install k8sgpt
```
@@ -41,7 +47,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_386.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.rpm
sudo rpm -ivh k8sgpt_386.rpm
```
<!---x-release-please-end-->
@@ -50,7 +56,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_amd64.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.rpm
sudo rpm -ivh -i k8sgpt_amd64.rpm
```
<!---x-release-please-end-->
@@ -62,7 +68,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_386.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
<!---x-release-please-end-->
@@ -70,7 +76,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_amd64.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
<!---x-release-please-end-->
@@ -83,14 +89,14 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_386.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.apk
apk add k8sgpt_386.apk
```
<!---x-release-please-end-->
**64 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.30/k8sgpt_amd64.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.apk
apk add k8sgpt_amd64.apk
```
<!---x-release-please-end-->x
@@ -167,6 +173,7 @@ you will be able to write your own analyzers.
- [x] gatewayClass
- [x] gateway
- [x] httproute
- [x] logAnalyzer
## Examples
@@ -292,6 +299,12 @@ _Analysis with serve mode_
```
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain": false}' localhost:8080 schema.v1.ServerService/Analyze
```
_Analysis with custom headers_
```
k8sgpt analyze --explain --custom-headers CustomHeaderKey:CustomHeaderValue
```
</details>
## LLM AI Backends
@@ -301,12 +314,13 @@ K8sGPT uses the chosen LLM, generative AI provider when you want to explain the
You can list available providers using `k8sgpt auth list`:
```
Default:
Default:
> openai
Active:
Unused:
Active:
Unused:
> openai
> localai
> ollama
> azureopenai
> cohere
> amazonbedrock
@@ -315,6 +329,7 @@ Unused:
> huggingface
> noopai
> googlevertexai
> watsonxai
```
For detailed documentation on how to configure and use each provider see [here](https://docs.k8sgpt.ai/reference/providers/backend/).
@@ -379,6 +394,7 @@ Note: **Anonymization does not currently apply to events.**
- RepicaSet
- PersistentVolumeClaim
- Pod
- Log
- **_*Events_**
***Note**:
@@ -423,7 +439,7 @@ Config file locations:
There may be scenarios where caching remotely is preferred.
In these scenarios K8sGPT supports AWS S3 or Azure Blob storage Integration.
<summary> Remote caching </summary>
<summary> Remote caching </summary>
<em>Note: You can only configure and use only one remote cache at a time</em>
_Adding a remote cache_
@@ -438,11 +454,11 @@ _Adding a remote cache_
* We support a number of [techniques](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#2-authenticate-with-azure) to authenticate against Azure
* Configuration, ``` k8sgpt cache add azure --storageacc <storage account name> --container <container name> ```
* K8sGPT assumes that the storage account already exist and it will create the container if it does not exist
* It is the **user** responsibility have to grant specific permissions to their identity in order to be able to upload blob files and create SA containers (e.g Storage Blob Data Contributor)
* It is the **user** responsibility have to grant specific permissions to their identity in order to be able to upload blob files and create SA containers (e.g Storage Blob Data Contributor)
* Google Cloud Storage
* _As a prerequisite `GOOGLE_APPLICATION_CREDENTIALS` are required as environmental variables._
* Configuration, ``` k8sgpt cache add gcs --region <gcp region> --bucket <name> --projectid <project id>```
* K8sGPT will create the bucket if it does not exist
* K8sGPT will create the bucket if it does not exist
_Listing cache items_
```

View File

@@ -21,6 +21,10 @@ spec:
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
{{- if .Values.deployment.securityContext }}
securityContext:
{{- toYaml .Values.deployment.securityContext | nindent 8 }}
{{ end -}}
serviceAccountName: {{ template "k8sgpt.fullname" . }}
containers:
- name: k8sgpt-container

View File

@@ -14,7 +14,10 @@ deployment:
requests:
cpu: "0.2"
memory: "156Mi"
securityContext: {}
# Set securityContext.runAsUser/runAsGroup if necessary. Values below were taken from https://github.com/k8sgpt-ai/k8sgpt/blob/main/container/Dockerfile
# runAsUser: 65532
# runAsGroup: 65532
secret:
secretKey: "" # base64 encoded OpenAI token

View File

@@ -33,11 +33,13 @@ var (
language string
nocache bool
namespace string
labelSelector string
anonymize bool
maxConcurrency int
withDoc bool
interactiveMode bool
customAnalysis bool
customHeaders []string
)
// AnalyzeCmd represents the problems command
@@ -54,11 +56,13 @@ var AnalyzeCmd = &cobra.Command{
language,
filters,
namespace,
labelSelector,
nocache,
explain,
maxConcurrency,
withDoc,
interactiveMode,
customHeaders,
)
if err != nil {
@@ -138,5 +142,8 @@ func init() {
AnalyzeCmd.Flags().BoolVarP(&interactiveMode, "interactive", "i", false, "Enable interactive mode that allows further conversation with LLM about the problem. Works only with --explain flag")
// custom analysis flag
AnalyzeCmd.Flags().BoolVarP(&customAnalysis, "custom-analysis", "z", false, "Enable custom analyzers")
// add custom headers flag
AnalyzeCmd.Flags().StringSliceVarP(&customHeaders, "custom-headers", "r", []string{}, "Custom Headers, <key>:<value> (e.g CustomHeaderKey:CustomHeaderValue AnotherHeader:AnotherValue)")
// label selector flag
AnalyzeCmd.Flags().StringVarP(&labelSelector, "selector", "L", "", "Label selector (label query) to filter on, supports '=', '==', and '!='. (e.g. -L key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
}

View File

@@ -100,6 +100,10 @@ var addCmd = &cobra.Command{
color.Red("Error: topP ranges from 0 to 1.")
os.Exit(1)
}
if topK < 1 || topK > 100 {
color.Red("Error: topK ranges from 1 to 100.")
os.Exit(1)
}
if ai.NeedPassword(backend) && password == "" {
fmt.Printf("Enter %s Key: ", backend)
@@ -123,8 +127,11 @@ var addCmd = &cobra.Command{
Temperature: temperature,
ProviderRegion: providerRegion,
ProviderId: providerId,
CompartmentId: compartmentId,
TopP: topP,
TopK: topK,
MaxTokens: maxTokens,
OrganizationId: organizationId,
}
if providerIndex == -1 {
@@ -155,7 +162,9 @@ func init() {
// add flag for endpointName
addCmd.Flags().StringVarP(&endpointName, "endpointname", "n", "", "Endpoint Name, e.g. `endpoint-xxxxxxxxxxxx` (only for amazonbedrock, amazonsagemaker backends)")
// add flag for topP
addCmd.Flags().Float32VarP(&topP, "topp", "c", 0.5, "Probability Cutoff: Set a threshold (0.0-1.0) to limit word choices. Higher values add randomness, lower values increase predictability.")
addCmd.Flags().Float32VarP(&topP, "topp", "", 0.5, "Probability Cutoff: Set a threshold (0.0-1.0) to limit word choices. Higher values add randomness, lower values increase predictability.")
// add flag for topK
addCmd.Flags().Int32VarP(&topK, "topk", "c", 50, "Sampling Cutoff: Set a threshold (1-100) to restrict the sampling process to the top K most probable words at each step. Higher values lead to greater variability, lower values increases predictability.")
// max tokens
addCmd.Flags().IntVarP(&maxTokens, "maxtokens", "l", 2048, "Specify a maximum output length. Adjust (1-...) to control text length. Higher values produce longer output, lower values limit length")
// add flag for temperature
@@ -166,4 +175,8 @@ func init() {
addCmd.Flags().StringVarP(&providerRegion, "providerRegion", "r", "", "Provider Region name (only for amazonbedrock, googlevertexai backend)")
//add flag for vertexAI Project ID
addCmd.Flags().StringVarP(&providerId, "providerId", "i", "", "Provider specific ID for e.g. project (only for googlevertexai backend)")
//add flag for OCI Compartment ID
addCmd.Flags().StringVarP(&compartmentId, "compartmentId", "k", "", "Compartment ID for generative AI model (only for oci backend)")
// add flag for openai organization
addCmd.Flags().StringVarP(&organizationId, "organizationId", "o", "", "OpenAI or AzureOpenAI Organization ID (only for openai and azureopenai backend)")
}

View File

@@ -28,8 +28,11 @@ var (
temperature float32
providerRegion string
providerId string
compartmentId string
topP float32
topK int32
maxTokens int
organizationId string
)
var configAI ai.AIConfiguration

View File

@@ -26,13 +26,21 @@ var updateCmd = &cobra.Command{
Use: "update",
Short: "Update a backend provider",
Long: "The command to update an AI backend provider",
Args: cobra.ExactArgs(1),
// Args: cobra.ExactArgs(1),
PreRun: func(cmd *cobra.Command, args []string) {
_ = cmd.MarkFlagRequired("backend")
backend, _ := cmd.Flags().GetString("backend")
if strings.ToLower(backend) == "azureopenai" {
_ = cmd.MarkFlagRequired("engine")
_ = cmd.MarkFlagRequired("baseurl")
}
organizationId, _ := cmd.Flags().GetString("organizationId")
if strings.ToLower(backend) != "azureopenai" && strings.ToLower(backend) != "openai" {
if organizationId != "" {
color.Red("Error: organizationId must be empty for backends other than azureopenai or openai.")
os.Exit(1)
}
}
},
Run: func(cmd *cobra.Command, args []string) {
@@ -43,50 +51,47 @@ var updateCmd = &cobra.Command{
os.Exit(1)
}
inputBackends := strings.Split(args[0], ",")
backend, _ := cmd.Flags().GetString("backend")
if len(inputBackends) == 0 {
color.Red("Error: backend must be set.")
os.Exit(1)
}
if temperature > 1.0 || temperature < 0.0 {
color.Red("Error: temperature ranges from 0 to 1.")
os.Exit(1)
}
for _, b := range inputBackends {
foundBackend := false
for i, provider := range configAI.Providers {
if b == provider.Name {
foundBackend = true
if backend != "" {
configAI.Providers[i].Name = backend
color.Blue("Backend name updated successfully")
}
if model != "" {
configAI.Providers[i].Model = model
color.Blue("Model updated successfully")
}
if password != "" {
configAI.Providers[i].Password = password
color.Blue("Password updated successfully")
}
if baseURL != "" {
configAI.Providers[i].BaseURL = baseURL
color.Blue("Base URL updated successfully")
}
if engine != "" {
configAI.Providers[i].Engine = engine
}
configAI.Providers[i].Temperature = temperature
color.Green("%s updated in the AI backend provider list", b)
foundBackend := false
for i, provider := range configAI.Providers {
if backend == provider.Name {
foundBackend = true
if backend != "" {
configAI.Providers[i].Name = backend
color.Blue("Backend name updated successfully")
}
if model != "" {
configAI.Providers[i].Model = model
color.Blue("Model updated successfully")
}
if password != "" {
configAI.Providers[i].Password = password
color.Blue("Password updated successfully")
}
if baseURL != "" {
configAI.Providers[i].BaseURL = baseURL
color.Blue("Base URL updated successfully")
}
if engine != "" {
configAI.Providers[i].Engine = engine
}
if organizationId != "" {
configAI.Providers[i].OrganizationId = organizationId
color.Blue("Organization Id updated successfully")
}
configAI.Providers[i].Temperature = temperature
color.Green("%s updated in the AI backend provider list", backend)
}
if !foundBackend {
color.Red("Error: %s does not exist in configuration file. Please use k8sgpt auth new.", args[0])
os.Exit(1)
}
}
if !foundBackend {
color.Red("Error: %s does not exist in configuration file. Please use k8sgpt auth new.", args[0])
os.Exit(1)
}
viper.Set("ai", configAI)
@@ -110,4 +115,6 @@ func init() {
updateCmd.Flags().Float32VarP(&temperature, "temperature", "t", 0.7, "The sampling temperature, value ranges between 0 ( output be more deterministic) and 1 (more random)")
// update flag for azure open ai engine/deployment name
updateCmd.Flags().StringVarP(&engine, "engine", "e", "", "Update Azure AI deployment name")
// update flag for organizationId
updateCmd.Flags().StringVarP(&organizationId, "organizationId", "o", "", "Update OpenAI or Azure organization Id")
}

View File

@@ -28,6 +28,7 @@ import (
const (
defaultTemperature float32 = 0.7
defaultTopP float32 = 1.0
defaultTopK int32 = 50
)
var (
@@ -84,6 +85,22 @@ var ServeCmd = &cobra.Command{
}
return float32(topP)
}
topK := func() int32 {
env := os.Getenv("K8SGPT_TOP_K")
if env == "" {
return defaultTopK
}
topK, err := strconv.ParseFloat(env, 32)
if err != nil {
color.Red("Unable to convert topK value: %v", err)
os.Exit(1)
}
if topK < 10 || topK > 100 {
color.Red("Error: topK ranges from 1 to 100.")
os.Exit(1)
}
return int32(topK)
}
// Check for env injection
backend = os.Getenv("K8SGPT_BACKEND")
password := os.Getenv("K8SGPT_PASSWORD")
@@ -104,6 +121,7 @@ var ServeCmd = &cobra.Command{
ProxyEndpoint: proxyEndpoint,
Temperature: temperature(),
TopP: topP(),
TopK: topK(),
}
configAI.Providers = append(configAI.Providers, *aiProvider)

216
go.mod
View File

@@ -1,48 +1,54 @@
module github.com/k8sgpt-ai/k8sgpt
go 1.21
go 1.22.0
toolchain go1.22.4
require (
github.com/aquasecurity/trivy-operator v0.17.1
github.com/fatih/color v1.16.0
github.com/fatih/color v1.17.0
github.com/kedacore/keda/v2 v2.11.2
github.com/magiconair/properties v1.8.7
github.com/mittwald/go-helm-client v0.12.5
github.com/sashabaranov/go-openai v1.20.4
github.com/schollz/progressbar/v3 v3.14.2
github.com/spf13/cobra v1.8.0
github.com/mittwald/go-helm-client v0.12.10
github.com/ollama/ollama v0.1.48
github.com/sashabaranov/go-openai v1.23.0
github.com/schollz/progressbar/v3 v3.14.5
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
golang.org/x/term v0.18.0
helm.sh/helm/v3 v3.13.3
k8s.io/api v0.28.4
k8s.io/apimachinery v0.28.4
k8s.io/client-go v0.28.4
k8s.io/kubectl v0.28.4 // indirect
golang.org/x/term v0.22.0
helm.sh/helm/v3 v3.15.2
k8s.io/api v0.30.2
k8s.io/apimachinery v0.30.2
k8s.io/client-go v0.30.2
k8s.io/kubectl v0.30.2 // indirect
)
require github.com/adrg/xdg v0.4.0
require (
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.19.1-20240213144542-6e830f3fdf19.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240213144542-6e830f3fdf19.2
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.33.0-20240406062209-1cc152efbf5c.1
cloud.google.com/go/storage v1.40.0
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240720172138-1b9bcd834f17.2
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240720172138-1b9bcd834f17.2
cloud.google.com/go/storage v1.43.0
cloud.google.com/go/vertexai v0.7.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.1
github.com/aws/aws-sdk-go v1.51.21
github.com/cohere-ai/cohere-go/v2 v2.7.1
github.com/google/generative-ai-go v0.10.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
github.com/IBM/watsonx-go v1.0.1
github.com/aws/aws-sdk-go v1.53.21
github.com/cohere-ai/cohere-go/v2 v2.7.3
github.com/google/generative-ai-go v0.11.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/hupe1980/go-huggingface v0.0.15
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3
github.com/olekukonko/tablewriter v0.0.5
github.com/prometheus/prometheus v0.49.1
github.com/oracle/oci-go-sdk/v65 v65.65.1
github.com/prometheus/prometheus v0.53.1
github.com/pterm/pterm v0.12.79
google.golang.org/api v0.170.0
google.golang.org/api v0.187.0
gopkg.in/yaml.v2 v2.4.0
sigs.k8s.io/controller-runtime v0.16.3
sigs.k8s.io/controller-runtime v0.18.4
sigs.k8s.io/gateway-api v1.0.0
)
@@ -50,54 +56,62 @@ require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
cloud.google.com/go v0.112.1 // indirect
cloud.google.com/go/ai v0.3.0 // indirect
cloud.google.com/go/aiplatform v1.60.0 // indirect
cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.7 // indirect
cloud.google.com/go/longrunning v0.5.5 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
cloud.google.com/go v0.115.0 // indirect
cloud.google.com/go/ai v0.3.5-0.20240409161017-ce55ad694f21 // indirect
cloud.google.com/go/aiplatform v1.68.0 // indirect
cloud.google.com/go/auth v0.6.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.8 // indirect
cloud.google.com/go/longrunning v0.5.7 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/Microsoft/hcsshim v0.12.4 // indirect
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
github.com/gorilla/websocket v1.5.2 // indirect
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
go.opentelemetry.io/otel/metric v1.27.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2 // indirect
gopkg.in/evanphx/json-patch.v5 v5.7.0 // indirect
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
knative.dev/pkg v0.0.0-20230616134650-eb63a40adfb0 // indirect
)
@@ -105,7 +119,7 @@ require (
require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
@@ -119,52 +133,51 @@ require (
github.com/aquasecurity/trivy-db v0.0.0-20231020043206-3770774790ce // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/containerd/containerd v1.7.11 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chai2010/gettext-go v1.0.3 // indirect
github.com/containerd/containerd v1.7.18 // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v24.0.7+incompatible // indirect
github.com/docker/cli v26.1.4+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/docker v27.0.0+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.2 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/gnostic v0.7.0
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-containerregistry v0.16.1 // indirect
github.com/google/go-containerregistry v0.17.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/lib/pq v1.10.9 // indirect
@@ -185,24 +198,23 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.0
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.54.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robfig/cron/v3 v3.0.1
github.com/rubenv/sql-migrate v1.5.2 // indirect
github.com/rubenv/sql-migrate v1.6.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spdx/tools-golang v0.5.3 // indirect
github.com/spf13/afero v1.11.0 // indirect
@@ -213,40 +225,40 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.starlark.net v0.0.0-20231016134836-22325403fcb3 // indirect
go.opentelemetry.io/otel v1.27.0 // indirect
go.opentelemetry.io/otel/trace v1.27.0 // indirect
go.starlark.net v0.0.0-20240520160348-046347dcd104 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
golang.org/x/net v0.23.0
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect
golang.org/x/net v0.26.0
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
k8s.io/apiextensions-apiserver v0.28.4
k8s.io/apiserver v0.28.4 // indirect
k8s.io/cli-runtime v0.28.4 // indirect
k8s.io/component-base v0.28.4 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20240310230437-4693a0247e57
oras.land/oras-go v1.2.4 // indirect
k8s.io/apiextensions-apiserver v0.30.2
k8s.io/apiserver v0.30.2 // indirect
k8s.io/cli-runtime v0.30.2 // indirect
k8s.io/component-base v0.30.2 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.15.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.15.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.0 // indirect
sigs.k8s.io/kustomize/api v0.17.2 // indirect
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
// v1.2.0 is taken from github.com/open-policy-agent/opa v0.42.0
// v1.2.0 incompatible with github.com/docker/docker v23.0.0-rc.1+incompatible
replace oras.land/oras-go => oras.land/oras-go v1.2.4
//replace oras.land/oras-go => oras.land/oras-go v1.2.4
replace github.com/docker/docker => github.com/docker/docker v27.1.1+incompatible

836
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,7 @@ type SageMakerAIClient struct {
temperature float32
endpoint string
topP float32
topK int32
maxTokens int
}
@@ -56,6 +57,7 @@ type Message struct {
type Parameters struct {
MaxNewTokens int `json:"max_new_tokens"`
TopP float64 `json:"top_p"`
TopK float64 `json:"top_k"`
Temperature float64 `json:"temperature"`
}
@@ -74,6 +76,7 @@ func (c *SageMakerAIClient) Configure(config IAIConfig) error {
c.temperature = config.GetTemperature()
c.maxTokens = config.GetMaxTokens()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
return nil
}
@@ -90,6 +93,7 @@ func (c *SageMakerAIClient) GetCompletion(_ context.Context, prompt string) (str
Parameters: Parameters{
MaxNewTokens: int(c.maxTokens),
TopP: float64(c.topP),
TopK: float64(c.topK),
Temperature: float64(c.temperature),
},
}

View File

@@ -14,9 +14,10 @@ const azureAIClientName = "azureopenai"
type AzureAIClient struct {
nopCloser
client *openai.Client
model string
temperature float32
client *openai.Client
model string
temperature float32
organizationId string
}
func (c *AzureAIClient) Configure(config IAIConfig) error {
@@ -25,6 +26,7 @@ func (c *AzureAIClient) Configure(config IAIConfig) error {
engine := config.GetEngine()
proxyEndpoint := config.GetProxyEndpoint()
defaultConfig := openai.DefaultAzureConfig(token, baseURL)
orgId := config.GetOrganizationId()
defaultConfig.AzureModelMapperFunc = func(model string) string {
// If you use a deployment name different from the model name, you can customize the AzureModelMapperFunc function
@@ -48,6 +50,10 @@ func (c *AzureAIClient) Configure(config IAIConfig) error {
Transport: transport,
}
}
if orgId != "" {
defaultConfig.OrgID = orgId
}
client := openai.NewClientWithConfig(defaultConfig)
if client == nil {
return errors.New("error creating Azure OpenAI client")

View File

@@ -31,6 +31,7 @@ type GoogleGenAIClient struct {
model string
temperature float32
topP float32
topK int32
maxTokens int
}
@@ -53,6 +54,7 @@ func (c *GoogleGenAIClient) Configure(config IAIConfig) error {
c.model = config.GetModel()
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
c.maxTokens = config.GetMaxTokens()
return nil
}
@@ -62,6 +64,7 @@ func (c *GoogleGenAIClient) GetCompletion(ctx context.Context, prompt string) (s
model := c.client.GenerativeModel(c.model)
model.SetTemperature(c.temperature)
model.SetTopP(c.topP)
model.SetTopK(c.topK)
model.SetMaxOutputTokens(int32(c.maxTokens))
// Google AI SDK is capable of different inputs than just text, for now set explicit text prompt type.

View File

@@ -30,6 +30,7 @@ type GoogleVertexAIClient struct {
model string
temperature float32
topP float32
topK int32
maxTokens int
}
@@ -111,6 +112,7 @@ func (g *GoogleVertexAIClient) Configure(config IAIConfig) error {
g.model = GetVertexAIModelOrDefault(config.GetModel())
g.temperature = config.GetTemperature()
g.topP = config.GetTopP()
g.topK = config.GetTopK()
g.maxTokens = config.GetMaxTokens()
return nil
@@ -121,6 +123,7 @@ func (g *GoogleVertexAIClient) GetCompletion(ctx context.Context, prompt string)
model := g.client.GenerativeModel(g.model)
model.SetTemperature(g.temperature)
model.SetTopP(g.topP)
model.SetTopK(float32(g.topK))
model.SetMaxOutputTokens(int32(g.maxTokens))
// Google AI SDK is capable of different inputs than just text, for now set explicit text prompt type.

View File

@@ -2,6 +2,7 @@ package ai
import (
"context"
"github.com/hupe1980/go-huggingface"
"k8s.io/utils/ptr"
)
@@ -14,6 +15,7 @@ type HuggingfaceClient struct {
client *huggingface.InferenceClient
model string
topP float32
topK int32
temperature float32
maxTokens int
}
@@ -26,6 +28,7 @@ func (c *HuggingfaceClient) Configure(config IAIConfig) error {
c.client = client
c.model = config.GetModel()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
c.temperature = config.GetTemperature()
if config.GetMaxTokens() > 500 {
c.maxTokens = 500
@@ -43,6 +46,7 @@ func (c *HuggingfaceClient) GetCompletion(ctx context.Context, prompt string) (s
Model: c.model,
Parameters: huggingface.ConversationalParameters{
TopP: ptr.To[float64](float64(c.topP)),
TopK: ptr.To[int](int(c.topK)),
Temperature: ptr.To[float64](float64(c.temperature)),
MaxLength: &c.maxTokens,
},

View File

@@ -15,6 +15,7 @@ package ai
import (
"context"
"net/http"
)
var (
@@ -22,6 +23,7 @@ var (
&OpenAIClient{},
&AzureAIClient{},
&LocalAIClient{},
&OllamaClient{},
&NoOpAIClient{},
&CohereClient{},
&AmazonBedRockClient{},
@@ -29,10 +31,13 @@ var (
&GoogleGenAIClient{},
&HuggingfaceClient{},
&GoogleVertexAIClient{},
&OCIGenAIClient{},
&WatsonxAIClient{},
}
Backends = []string{
openAIClientName,
localAIClientName,
ollamaClientName,
azureAIClientName,
cohereAIClientName,
amazonbedrockAIClientName,
@@ -41,6 +46,8 @@ var (
noopAIClientName,
huggingfaceAIClientName,
googleVertexAIClientName,
ociClientName,
watsonxAIClientName,
}
)
@@ -72,8 +79,12 @@ type IAIConfig interface {
GetTemperature() float32
GetProviderRegion() string
GetTopP() float32
GetTopK() int32
GetMaxTokens() int
GetProviderId() string
GetCompartmentId() string
GetOrganizationId() string
GetCustomHeaders() []http.Header
}
func NewClient(provider string) IAI {
@@ -92,19 +103,23 @@ type AIConfiguration struct {
}
type AIProvider struct {
Name string `mapstructure:"name"`
Model string `mapstructure:"model"`
Password string `mapstructure:"password" yaml:"password,omitempty"`
BaseURL string `mapstructure:"baseurl" yaml:"baseurl,omitempty"`
ProxyEndpoint string `mapstructure:"proxyEndpoint" yaml:"proxyEndpoint,omitempty"`
ProxyPort string `mapstructure:"proxyPort" yaml:"proxyPort,omitempty"`
EndpointName string `mapstructure:"endpointname" yaml:"endpointname,omitempty"`
Engine string `mapstructure:"engine" yaml:"engine,omitempty"`
Temperature float32 `mapstructure:"temperature" yaml:"temperature,omitempty"`
ProviderRegion string `mapstructure:"providerregion" yaml:"providerregion,omitempty"`
ProviderId string `mapstructure:"providerid" yaml:"providerid,omitempty"`
TopP float32 `mapstructure:"topp" yaml:"topp,omitempty"`
MaxTokens int `mapstructure:"maxtokens" yaml:"maxtokens,omitempty"`
Name string `mapstructure:"name"`
Model string `mapstructure:"model"`
Password string `mapstructure:"password" yaml:"password,omitempty"`
BaseURL string `mapstructure:"baseurl" yaml:"baseurl,omitempty"`
ProxyEndpoint string `mapstructure:"proxyEndpoint" yaml:"proxyEndpoint,omitempty"`
ProxyPort string `mapstructure:"proxyPort" yaml:"proxyPort,omitempty"`
EndpointName string `mapstructure:"endpointname" yaml:"endpointname,omitempty"`
Engine string `mapstructure:"engine" yaml:"engine,omitempty"`
Temperature float32 `mapstructure:"temperature" yaml:"temperature,omitempty"`
ProviderRegion string `mapstructure:"providerregion" yaml:"providerregion,omitempty"`
ProviderId string `mapstructure:"providerid" yaml:"providerid,omitempty"`
CompartmentId string `mapstructure:"compartmentid" yaml:"compartmentid,omitempty"`
TopP float32 `mapstructure:"topp" yaml:"topp,omitempty"`
TopK int32 `mapstructure:"topk" yaml:"topk,omitempty"`
MaxTokens int `mapstructure:"maxtokens" yaml:"maxtokens,omitempty"`
OrganizationId string `mapstructure:"organizationid" yaml:"organizationid,omitempty"`
CustomHeaders []http.Header `mapstructure:"customHeaders"`
}
func (p *AIProvider) GetBaseURL() string {
@@ -123,6 +138,10 @@ func (p *AIProvider) GetTopP() float32 {
return p.TopP
}
func (p *AIProvider) GetTopK() int32 {
return p.TopK
}
func (p *AIProvider) GetMaxTokens() int {
return p.MaxTokens
}
@@ -150,7 +169,19 @@ func (p *AIProvider) GetProviderId() string {
return p.ProviderId
}
var passwordlessProviders = []string{"localai", "amazonsagemaker", "amazonbedrock", "googlevertexai"}
func (p *AIProvider) GetCompartmentId() string {
return p.CompartmentId
}
func (p *AIProvider) GetOrganizationId() string {
return p.OrganizationId
}
func (p *AIProvider) GetCustomHeaders() []http.Header {
return p.CustomHeaders
}
var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci", "watsonxai"}
func NeedPassword(backend string) bool {
for _, b := range passwordlessProviders {

97
pkg/ai/ocigenai.go Normal file
View File

@@ -0,0 +1,97 @@
/*
Copyright 2024 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ai
import (
"context"
"errors"
"github.com/oracle/oci-go-sdk/v65/common"
"github.com/oracle/oci-go-sdk/v65/generativeaiinference"
"strings"
)
const ociClientName = "oci"
type OCIGenAIClient struct {
nopCloser
client *generativeaiinference.GenerativeAiInferenceClient
model string
compartmentId string
temperature float32
topP float32
maxTokens int
}
func (c *OCIGenAIClient) GetName() string {
return ociClientName
}
func (c *OCIGenAIClient) Configure(config IAIConfig) error {
config.GetEndpointName()
c.model = config.GetModel()
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
c.maxTokens = config.GetMaxTokens()
c.compartmentId = config.GetCompartmentId()
provider := common.DefaultConfigProvider()
client, err := generativeaiinference.NewGenerativeAiInferenceClientWithConfigurationProvider(provider)
if err != nil {
return err
}
c.client = &client
return nil
}
func (c *OCIGenAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
generateTextRequest := c.newGenerateTextRequest(prompt)
generateTextResponse, err := c.client.GenerateText(ctx, generateTextRequest)
if err != nil {
return "", err
}
return extractGeneratedText(generateTextResponse.InferenceResponse)
}
func (c *OCIGenAIClient) newGenerateTextRequest(prompt string) generativeaiinference.GenerateTextRequest {
temperatureF64 := float64(c.temperature)
topPF64 := float64(c.topP)
return generativeaiinference.GenerateTextRequest{
GenerateTextDetails: generativeaiinference.GenerateTextDetails{
CompartmentId: &c.compartmentId,
ServingMode: generativeaiinference.OnDemandServingMode{
ModelId: &c.model,
},
InferenceRequest: generativeaiinference.CohereLlmInferenceRequest{
Prompt: &prompt,
MaxTokens: &c.maxTokens,
Temperature: &temperatureF64,
TopP: &topPF64,
},
},
}
}
func extractGeneratedText(llmInferenceResponse generativeaiinference.LlmInferenceResponse) (string, error) {
response, ok := llmInferenceResponse.(generativeaiinference.CohereLlmInferenceResponse)
if !ok {
return "", errors.New("failed to extract generated text from backed response")
}
sb := strings.Builder{}
for _, text := range response.GeneratedTexts {
if text.Text != nil {
sb.WriteString(*text.Text)
}
}
return sb.String(), nil
}

102
pkg/ai/ollama.go Normal file
View File

@@ -0,0 +1,102 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ai
import (
"context"
"errors"
"net/http"
"net/url"
ollama "github.com/ollama/ollama/api"
)
const ollamaClientName = "ollama"
type OllamaClient struct {
nopCloser
client *ollama.Client
model string
temperature float32
topP float32
}
const (
defaultBaseURL = "http://localhost:11434"
defaultModel = "llama3"
)
func (c *OllamaClient) Configure(config IAIConfig) error {
baseURL := config.GetBaseURL()
if baseURL == "" {
baseURL = defaultBaseURL
}
baseClientURL, err := url.Parse(baseURL)
if err != nil {
return err
}
proxyEndpoint := config.GetProxyEndpoint()
httpClient := http.DefaultClient
if proxyEndpoint != "" {
proxyUrl, err := url.Parse(proxyEndpoint)
if err != nil {
return err
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
}
httpClient = &http.Client{
Transport: transport,
}
}
c.client = ollama.NewClient(baseClientURL, httpClient)
if c.client == nil {
return errors.New("error creating Ollama client")
}
c.model = config.GetModel()
if c.model == "" {
c.model = defaultModel
}
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
return nil
}
func (c *OllamaClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
req := &ollama.GenerateRequest{
Model: c.model,
Prompt: prompt,
Stream: new(bool),
Options: map[string]interface{}{
"temperature": c.temperature,
"top_p": c.topP,
},
}
completion := ""
respFunc := func(resp ollama.GenerateResponse) error {
completion = resp.Response
return nil
}
err := c.client.Generate(ctx, req, respFunc)
if err != nil {
return "", err
}
return completion, nil
}
func (a *OllamaClient) GetName() string {
return ollamaClientName
}

View File

@@ -27,10 +27,11 @@ const openAIClientName = "openai"
type OpenAIClient struct {
nopCloser
client *openai.Client
model string
temperature float32
topP float32
client *openai.Client
model string
temperature float32
topP float32
organizationId string
}
const (
@@ -43,6 +44,7 @@ const (
func (c *OpenAIClient) Configure(config IAIConfig) error {
token := config.GetPassword()
defaultConfig := openai.DefaultConfig(token)
orgId := config.GetOrganizationId()
proxyEndpoint := config.GetProxyEndpoint()
baseURL := config.GetBaseURL()
@@ -50,18 +52,25 @@ func (c *OpenAIClient) Configure(config IAIConfig) error {
defaultConfig.BaseURL = baseURL
}
transport := &http.Transport{}
if proxyEndpoint != "" {
proxyUrl, err := url.Parse(proxyEndpoint)
if err != nil {
return err
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
}
transport.Proxy = http.ProxyURL(proxyUrl)
}
defaultConfig.HTTPClient = &http.Client{
Transport: transport,
}
if orgId != "" {
defaultConfig.OrgID = orgId
}
customHeaders := config.GetCustomHeaders()
defaultConfig.HTTPClient = &http.Client{
Transport: &OpenAIHeaderTransport{
Origin: transport,
Headers: customHeaders,
},
}
client := openai.NewClientWithConfig(defaultConfig)
@@ -100,3 +109,25 @@ func (c *OpenAIClient) GetCompletion(ctx context.Context, prompt string) (string
func (c *OpenAIClient) GetName() string {
return openAIClientName
}
// OpenAIHeaderTransport is an http.RoundTripper that adds the given headers to each request.
type OpenAIHeaderTransport struct {
Origin http.RoundTripper
Headers []http.Header
}
// RoundTrip implements the http.RoundTripper interface.
func (t *OpenAIHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// Clone the request to avoid modifying the original request
clonedReq := req.Clone(req.Context())
for _, header := range t.Headers {
for key, values := range header {
// Possible values per header: RFC 2616
for _, value := range values {
clonedReq.Header.Add(key, value)
}
}
}
return t.Origin.RoundTrip(clonedReq)
}

View File

@@ -0,0 +1,106 @@
package ai
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
// Mock configuration
type mockConfig struct {
baseURL string
}
func (m *mockConfig) GetPassword() string {
return ""
}
func (m *mockConfig) GetOrganizationId() string {
return ""
}
func (m *mockConfig) GetProxyEndpoint() string {
return ""
}
func (m *mockConfig) GetBaseURL() string {
return m.baseURL
}
func (m *mockConfig) GetCustomHeaders() []http.Header {
return []http.Header{
{"X-Custom-Header-1": []string{"Value1"}},
{"X-Custom-Header-2": []string{"Value2"}},
{"X-Custom-Header-2": []string{"Value3"}}, // Testing multiple values for the same header
}
}
func (m *mockConfig) GetModel() string {
return ""
}
func (m *mockConfig) GetTemperature() float32 {
return 0.0
}
func (m *mockConfig) GetTopP() float32 {
return 0.0
}
func (m *mockConfig) GetCompartmentId() string {
return ""
}
func (m *mockConfig) GetTopK() int32 {
return 0.0
}
func (m *mockConfig) GetMaxTokens() int {
return 0
}
func (m *mockConfig) GetEndpointName() string {
return ""
}
func (m *mockConfig) GetEngine() string {
return ""
}
func (m *mockConfig) GetProviderId() string {
return ""
}
func (m *mockConfig) GetProviderRegion() string {
return ""
}
func TestOpenAIClient_CustomHeaders(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "Value1", r.Header.Get("X-Custom-Header-1"))
assert.ElementsMatch(t, []string{"Value2", "Value3"}, r.Header["X-Custom-Header-2"])
w.WriteHeader(http.StatusOK)
// Mock response for openai completion
mockResponse := `{"choices": [{"message": {"content": "test"}}]}`
n, err := w.Write([]byte(mockResponse))
if err != nil {
t.Fatalf("error writing response: %v", err)
}
if n != len(mockResponse) {
t.Fatalf("expected to write %d bytes but wrote %d bytes", len(mockResponse), n)
}
}))
defer server.Close()
config := &mockConfig{baseURL: server.URL}
client := &OpenAIClient{}
err := client.Configure(config)
assert.NoError(t, err)
// Make a completion request to trigger the headers
ctx := context.Background()
_, err = client.GetCompletion(ctx, "foo prompt")
assert.NoError(t, err)
}

View File

@@ -48,6 +48,16 @@ const (
- Containers:
- {list of container names}
`
kyverno_prompt = `Simplify the following Kyverno warnings message delimited by triple dashes written in --- %s --- language; --- %s ---.
Provide the most probable solution as a kubectl command.
Write the output in the following format, for the solution, only show the kubectl command:
Error: {Explain error here}
Solution: {kubectl command}
`
)
var PromptMap = map[string]string{
@@ -56,4 +66,6 @@ var PromptMap = map[string]string{
"ConfigAuditReport": trivy_conf_prompt,
"PrometheusConfigValidate": prom_conf_prompt,
"PrometheusConfigRelabelReport": prom_relabel_prompt,
"PolicyReport": kyverno_prompt,
"ClusterPolicyReport": kyverno_prompt,
}

88
pkg/ai/watsonxai.go Normal file
View File

@@ -0,0 +1,88 @@
package ai
import (
"context"
"errors"
"fmt"
"os"
wx "github.com/IBM/watsonx-go/pkg/models"
)
const watsonxAIClientName = "watsonxai"
type WatsonxAIClient struct {
nopCloser
client *wx.Client
model string
temperature float32
topP float32
topK int32
maxNewTokens int
}
const (
modelMetallama = "ibm/granite-13b-chat-v2"
maxTokens = 2048
)
func (c *WatsonxAIClient) Configure(config IAIConfig) error {
if config.GetModel() == "" {
c.model = modelMetallama
} else {
c.model = config.GetModel()
}
if config.GetMaxTokens() == 0 {
c.maxNewTokens = maxTokens
} else {
c.maxNewTokens = config.GetMaxTokens()
}
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
// WatsonxAPIKeyEnvVarName = "WATSONX_API_KEY"
// WatsonxProjectIDEnvVarName = "WATSONX_PROJECT_ID"
apiKey, projectID := os.Getenv(wx.WatsonxAPIKeyEnvVarName), os.Getenv(wx.WatsonxProjectIDEnvVarName)
if apiKey == "" {
return errors.New("No watsonx API key provided")
}
if projectID == "" {
return errors.New("No watsonx project ID provided")
}
client, err := wx.NewClient(
wx.WithWatsonxAPIKey(apiKey),
wx.WithWatsonxProjectID(projectID),
)
if err != nil {
return fmt.Errorf("Failed to create client for testing. Error: %v", err)
}
c.client = client
return nil
}
func (c *WatsonxAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
result, err := c.client.GenerateText(
c.model,
prompt,
wx.WithTemperature((float64)(c.temperature)),
wx.WithTopP((float64)(c.topP)),
wx.WithTopK((uint)(c.topK)),
wx.WithMaxNewTokens((uint)(c.maxNewTokens)),
)
if err != nil {
return "", fmt.Errorf("Expected no error, but got an error: %v", err)
}
if result.Text == "" {
return "", errors.New("Expected a result, but got an empty string")
}
return result.Text, nil
}
func (c *WatsonxAIClient) GetName() string {
return watsonxAIClientName
}

View File

@@ -44,6 +44,7 @@ type Analysis struct {
Results []common.Result
Errors []string
Namespace string
LabelSelector string
Cache cache.ICache
Explain bool
MaxConcurrency int
@@ -74,11 +75,13 @@ func NewAnalysis(
language string,
filters []string,
namespace string,
labelSelector string,
noCache bool,
explain bool,
maxConcurrency int,
withDoc bool,
interactiveMode bool,
httpHeaders []string,
) (*Analysis, error) {
// Get kubernetes client from viper.
kubecontext := viper.GetString("kubecontext")
@@ -104,6 +107,7 @@ func NewAnalysis(
Client: client,
Language: language,
Namespace: namespace,
LabelSelector: labelSelector,
Cache: cache,
Explain: explain,
MaxConcurrency: maxConcurrency,
@@ -146,6 +150,8 @@ func NewAnalysis(
}
aiClient := ai.NewClient(aiProvider.Name)
customHeaders := util.NewHeaders(httpHeaders)
aiProvider.CustomHeaders = customHeaders
if err := aiClient.Configure(&aiProvider); err != nil {
return nil, err
}
@@ -154,25 +160,57 @@ func NewAnalysis(
return a, nil
}
func (a *Analysis) CustomAnalyzersAreAvailable() bool {
var customAnalyzers []custom.CustomAnalyzer
if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil {
return false
}
return len(customAnalyzers) > 0
}
func (a *Analysis) RunCustomAnalysis() {
var customAnalyzers []custom.CustomAnalyzer
if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil {
a.Errors = append(a.Errors, err.Error())
return
}
semaphore := make(chan struct{}, a.MaxConcurrency)
var wg sync.WaitGroup
var mutex sync.Mutex
for _, cAnalyzer := range customAnalyzers {
wg.Add(1)
semaphore <- struct{}{}
go func(analyzer custom.CustomAnalyzer, wg *sync.WaitGroup, semaphore chan struct{}) {
defer wg.Done()
canClient, err := custom.NewClient(cAnalyzer.Connection)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("Client creation error for %s analyzer", cAnalyzer.Name))
mutex.Unlock()
return
}
canClient, err := custom.NewClient(cAnalyzer.Connection)
if err != nil {
a.Errors = append(a.Errors, fmt.Sprintf("Client creation error for %s analyzer", cAnalyzer.Name))
continue
}
result, err := canClient.Run()
if err != nil {
a.Results = append(a.Results, result)
}
result, err := canClient.Run()
if result.Kind == "" {
// for custom analyzer name, we must use a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.',
//and must start and end with an alphanumeric character (e.g. 'example.com',
//regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
result.Kind = cAnalyzer.Name
}
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", cAnalyzer.Name, err))
mutex.Unlock()
} else {
mutex.Lock()
a.Results = append(a.Results, result)
mutex.Unlock()
}
<-semaphore
}(cAnalyzer, &wg, semaphore)
}
wg.Wait()
}
func (a *Analysis) RunAnalysis() {
@@ -195,15 +233,16 @@ func (a *Analysis) RunAnalysis() {
Client: a.Client,
Context: a.Context,
Namespace: a.Namespace,
LabelSelector: a.LabelSelector,
AIClient: a.AIClient,
OpenapiSchema: openapiSchema,
}
semaphore := make(chan struct{}, a.MaxConcurrency)
var wg sync.WaitGroup
var mutex sync.Mutex
// if there are no filters selected and no active_filters then run coreAnalyzer
if len(a.Filters) == 0 && len(activeFilters) == 0 {
var wg sync.WaitGroup
var mutex sync.Mutex
for _, analyzer := range coreAnalyzerMap {
wg.Add(1)
semaphore <- struct{}{}
@@ -225,11 +264,8 @@ func (a *Analysis) RunAnalysis() {
wg.Wait()
return
}
semaphore = make(chan struct{}, a.MaxConcurrency)
// if the filters flag is specified
if len(a.Filters) != 0 {
var wg sync.WaitGroup
var mutex sync.Mutex
for _, filter := range a.Filters {
if analyzer, ok := analyzerMap[filter]; ok {
semaphore <- struct{}{}
@@ -255,9 +291,6 @@ func (a *Analysis) RunAnalysis() {
return
}
var wg sync.WaitGroup
var mutex sync.Mutex
semaphore = make(chan struct{}, a.MaxConcurrency)
// use active_filters
for _, filter := range activeFilters {
if analyzer, ok := analyzerMap[filter]; ok {

View File

@@ -17,6 +17,11 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
@@ -26,8 +31,6 @@ import (
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"strings"
"testing"
)
// sub-function
@@ -85,6 +88,7 @@ func analysis_RunAnalysisFilterTester(t *testing.T, filterFlag string) []common.
Client: &kubernetes.Client{
Client: clientset,
},
WithDoc: true,
}
if len(filterFlag) > 0 {
// `--filter` is explicitly given
@@ -133,6 +137,10 @@ func TestAnalysis_RunAnalysisActiveFilter(t *testing.T) {
viper.SetDefault("active_filters", []string{"Ingress", "Service", "Pod"})
results = analysis_RunAnalysisFilterTester(t, "")
assert.Equal(t, len(results), 3)
// Invalid filter
results = analysis_RunAnalysisFilterTester(t, "invalid")
assert.Equal(t, len(results), 0)
}
func TestAnalysis_NoProblemJsonOutput(t *testing.T) {
@@ -279,3 +287,120 @@ func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) {
require.Equal(t, got, expected)
}
func TestNewAnalysis(t *testing.T) {
disabledCache := cache.New("disabled-cache")
disabledCache.DisableCache()
aiClient := &ai.NoOpAIClient{}
results := []common.Result{
{
Kind: "VulnerabilityReport",
Error: []common.Failure{
{
Text: "This is a custom failure",
KubernetesDoc: "test-kubernetes-doc",
Sensitive: []common.Sensitive{
{
Masked: "masked-error",
Unmasked: "unmasked-error",
},
},
},
},
},
}
tests := []struct {
name string
a Analysis
output string
anonymize bool
expectedErr string
}{
{
name: "Empty results",
a: Analysis{},
},
{
name: "cache disabled",
a: Analysis{
AIClient: aiClient,
Cache: disabledCache,
Results: results,
},
},
{
name: "output and anonymize both set",
a: Analysis{
AIClient: aiClient,
Cache: cache.New("test-cache"),
Results: results,
},
output: "test-output",
anonymize: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
err := tt.a.GetAIResults(tt.output, tt.anonymize)
if tt.expectedErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tt.expectedErr)
}
})
}
}
func TestGetAIResultForSanitizedFailures(t *testing.T) {
enabledCache := cache.New("enabled-cache")
disabledCache := cache.New("disabled-cache")
disabledCache.DisableCache()
aiClient := &ai.NoOpAIClient{}
tests := []struct {
name string
a Analysis
texts []string
promptTmpl string
expectedOutput string
expectedErr string
}{
{
name: "Cache enabled",
a: Analysis{
AIClient: aiClient,
Cache: enabledCache,
},
texts: []string{"some-data"},
expectedOutput: "I am a noop response to the prompt %!(EXTRA string=, string=some-data)",
},
{
name: "cache disabled",
a: Analysis{
AIClient: aiClient,
Cache: disabledCache,
Language: "English",
},
texts: []string{"test input"},
promptTmpl: "Response in %s: %s",
expectedOutput: "I am a noop response to the prompt Response in English: test input",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
output, err := tt.a.getAIResultForSanitizedFailures(tt.texts, tt.promptTmpl)
if tt.expectedErr == "" {
require.NoError(t, err)
require.Equal(t, tt.expectedOutput, output)
} else {
require.ErrorContains(t, err, tt.expectedErr)
require.Empty(t, output)
}
})
}
}

View File

@@ -0,0 +1,64 @@
/*
Copyright 2024 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package analysis
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestPrintOutput(t *testing.T) {
require.NotEmpty(t, getOutputFormats())
tests := []struct {
name string
a *Analysis
format string
expectedOutput string
expectedErr string
}{
{
name: "json format",
a: &Analysis{},
format: "json",
expectedOutput: "{\n \"provider\": \"\",\n \"errors\": null,\n \"status\": \"OK\",\n \"problems\": 0,\n \"results\": null\n}",
},
{
name: "text format",
a: &Analysis{},
format: "text",
expectedOutput: "AI Provider: AI not used; --explain not set\n\nNo problems detected\n",
},
{
name: "unsupported format",
a: &Analysis{},
format: "unsupported",
expectedErr: "unsupported output format: unsupported. Available format",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
output, err := tt.a.PrintOutput(tt.format)
if tt.expectedErr == "" {
require.NoError(t, err)
require.Contains(t, string(output), tt.expectedOutput)
} else {
require.ErrorContains(t, err, tt.expectedErr)
require.Nil(t, output)
}
})
}
}

View File

@@ -43,7 +43,7 @@ func (analyzer CronJobAnalyzer) Analyze(a common.Analyzer) ([]common.Result, err
"analyzer_name": kind,
})
cronJobList, err := a.Client.GetClient().BatchV1().CronJobs(a.Namespace).List(a.Context, v1.ListOptions{})
cronJobList, err := a.Client.GetClient().BatchV1().CronJobs(a.Namespace).List(a.Context, v1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -156,3 +156,45 @@ func TestCronJobAnalyzer(t *testing.T) {
require.Equal(t, expectations[i], result.Name)
}
}
func TestCronJobAnalyzerLabelSelectorFiltering(t *testing.T) {
suspend := new(bool)
*suspend = true
invalidStartingDeadline := new(int64)
*invalidStartingDeadline = -7
validStartingDeadline := new(int64)
*validStartingDeadline = 7
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ1",
Namespace: "default",
Labels: map[string]string{
"app": "cronjob",
},
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ2",
Namespace: "default",
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=cronjob",
}
cjAnalyzer := CronJobAnalyzer{}
results, err := cjAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/CJ1", results[0].Name)
}

View File

@@ -46,7 +46,7 @@ func (d DeploymentAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
"analyzer_name": kind,
})
deployments, err := a.Client.GetClient().AppsV1().Deployments(a.Namespace).List(context.Background(), v1.ListOptions{})
deployments, err := a.Client.GetClient().AppsV1().Deployments(a.Namespace).List(context.Background(), v1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -151,3 +151,55 @@ func TestDeploymentAnalyzerNamespaceFiltering(t *testing.T) {
assert.Equal(t, analysisResults[0].Kind, "Deployment")
assert.Equal(t, analysisResults[0].Name, "default/example")
}
func TestDeploymentAnalyzerLabelSelectorFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Labels: map[string]string{
"app": "deployment",
},
},
Spec: appsv1.DeploymentSpec{
Replicas: func() *int32 { i := int32(3); return &i }(),
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{},
},
},
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "example2",
Namespace: "default",
},
Spec: appsv1.DeploymentSpec{
Replicas: func() *int32 { i := int32(3); return &i }(),
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{},
},
},
},
},
)
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=deployment",
}
deploymentAnalyzer := DeploymentAnalyzer{}
analysisResults, err := deploymentAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}

View File

@@ -41,7 +41,9 @@ func (GatewayAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
if err != nil {
return nil, err
}
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{}); err != nil {
labelSelector := util.LabelStrToSelector(a.LabelSelector)
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{LabelSelector: labelSelector}); err != nil {
return nil, err
}

View File

@@ -25,10 +25,13 @@ func BuildGatewayClass(name string) gtwapi.GatewayClass {
return GatewayClass
}
func BuildGateway(className gtwapi.ObjectName, status metav1.ConditionStatus) gtwapi.Gateway {
func BuildGateway(className gtwapi.ObjectName, status metav1.ConditionStatus, labels map[string]string) gtwapi.Gateway {
Gateway := gtwapi.Gateway{}
Gateway.Name = "foobar"
Gateway.Namespace = "default"
if labels != nil {
Gateway.Labels = labels
}
Gateway.Spec.GatewayClassName = className
Gateway.Spec.Listeners = []gtwapi.Listener{
{
@@ -53,7 +56,7 @@ func TestGatewayAnalyzer(t *testing.T) {
AcceptedStatus := metav1.ConditionTrue
GatewayClass := BuildGatewayClass(string(ClassName))
Gateway := BuildGateway(ClassName, AcceptedStatus)
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
@@ -91,7 +94,7 @@ func TestGatewayAnalyzer(t *testing.T) {
func TestMissingClassGatewayAnalyzer(t *testing.T) {
ClassName := gtwapi.ObjectName("non-existed")
AcceptedStatus := metav1.ConditionTrue
Gateway := BuildGateway(ClassName, AcceptedStatus)
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
@@ -130,7 +133,7 @@ func TestStatusGatewayAnalyzer(t *testing.T) {
AcceptedStatus := metav1.ConditionUnknown
GatewayClass := BuildGatewayClass(string(ClassName))
Gateway := BuildGateway(ClassName, AcceptedStatus)
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
@@ -178,3 +181,70 @@ func TestStatusGatewayAnalyzer(t *testing.T) {
t.Errorf("Expected message, <%v> , not found in Gateway's analysis results", want)
}
}
func TestGatewayAnalyzerLabelSelectorFiltering(t *testing.T) {
ClassName := gtwapi.ObjectName("non-existed")
AcceptedStatus := metav1.ConditionTrue
Gateway := BuildGateway(ClassName, AcceptedStatus, map[string]string{"app": "gateway"})
scheme := scheme.Scheme
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&Gateway,
}
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
analyzerInstance := GatewayAnalyzer{}
// without label selector should return 1 result
config := common.Analyzer{
Client: &kubernetes.Client{
CtrlClient: fakeClient,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := analyzerInstance.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
// with label selector should return 1 result
config = common.Analyzer{
Client: &kubernetes.Client{
CtrlClient: fakeClient,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=gateway",
}
analysisResults, err = analyzerInstance.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
// with wrong label selector should return 0 result
config = common.Analyzer{
Client: &kubernetes.Client{
CtrlClient: fakeClient,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=wrong",
}
analysisResults, err = analyzerInstance.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 0)
}

View File

@@ -39,7 +39,9 @@ func (GatewayClassAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
if err != nil {
return nil, err
}
if err := client.List(a.Context, gcList, &ctrl.ListOptions{}); err != nil {
labelSelector := util.LabelStrToSelector(a.LabelSelector)
if err := client.List(a.Context, gcList, &ctrl.ListOptions{LabelSelector: labelSelector}); err != nil {
return nil, err
}
var preAnalysis = map[string]common.PreAnalysis{}

View File

@@ -55,3 +55,51 @@ func TestGatewayClassAnalyzer(t *testing.T) {
assert.Equal(t, len(analysisResults), 1)
}
func TestGatewayClassAnalyzerLabelSelectorFiltering(t *testing.T) {
condition := metav1.Condition{
Type: "Accepted",
Status: "Ready",
Message: "Ready",
Reason: "Ready",
}
// Create two GatewayClasses with different labels
GatewayClass := &gtwapi.GatewayClass{}
GatewayClass.Name = "foobar"
GatewayClass.Spec.ControllerName = "gateway.fooproxy.io/gatewayclass-controller"
GatewayClass.Labels = map[string]string{"app": "gatewayclass"}
GatewayClass.Status.Conditions = []metav1.Condition{condition}
GatewayClass2 := &gtwapi.GatewayClass{}
GatewayClass2.Name = "foobar2"
GatewayClass2.Spec.ControllerName = "gateway.fooproxy.io/gatewayclass-controller"
GatewayClass2.Status.Conditions = []metav1.Condition{condition}
scheme := scheme.Scheme
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(GatewayClass, GatewayClass2).Build()
analyzerInstance := GatewayClassAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
CtrlClient: fakeClient,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=gatewayclass",
}
analysisResults, err := analyzerInstance.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}

View File

@@ -43,7 +43,7 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
"analyzer_name": kind,
})
list, err := a.Client.GetClient().AutoscalingV1().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().AutoscalingV2().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}
@@ -53,6 +53,18 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
for _, hpa := range list.Items {
var failures []common.Failure
//check the error from status field
conditions := hpa.Status.Conditions
for _, condition := range conditions {
if condition.Status != "True" {
failures = append(failures, common.Failure{
Text: condition.Message,
Sensitive: []common.Sensitive{},
})
}
}
// check ScaleTargetRef exist
scaleTargetRef := hpa.Spec.ScaleTargetRef
var podInfo PodInfo

View File

@@ -22,7 +22,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
appsv1 "k8s.io/api/apps/v1"
autoscalingv1 "k8s.io/api/autoscaling/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -31,7 +31,7 @@ import (
func TestHPAAnalyzer(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
@@ -55,14 +55,14 @@ func TestHPAAnalyzer(t *testing.T) {
func TestHPAAnalyzerWithMultipleHPA(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example-2",
Namespace: "default",
@@ -88,14 +88,14 @@ func TestHPAAnalyzerWithMultipleHPA(t *testing.T) {
func TestHPAAnalyzerWithUnsuportedScaleTargetRef(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "unsupported",
},
},
@@ -134,14 +134,14 @@ func TestHPAAnalyzerWithUnsuportedScaleTargetRef(t *testing.T) {
func TestHPAAnalyzerWithNonExistentScaleTargetRef(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "non-existent",
},
@@ -181,14 +181,14 @@ func TestHPAAnalyzerWithNonExistentScaleTargetRef(t *testing.T) {
func TestHPAAnalyzerWithExistingScaleTargetRefAsDeployment(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
@@ -245,14 +245,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsDeployment(t *testing.T) {
func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicationController(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "ReplicationController",
Name: "example",
},
@@ -309,14 +309,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicationController(t *testing
func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicaSet(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "ReplicaSet",
Name: "example",
},
@@ -373,14 +373,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicaSet(t *testing.T) {
func TestHPAAnalyzerWithExistingScaleTargetRefAsStatefulSet(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "StatefulSet",
Name: "example",
},
@@ -437,14 +437,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsStatefulSet(t *testing.T) {
func TestHPAAnalyzerWithExistingScaleTargetRefWithoutSpecifyingResources(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
@@ -503,14 +503,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefWithoutSpecifyingResources(t *test
func TestHPAAnalyzerNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&autoscalingv1.HorizontalPodAutoscaler{
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "other-namespace",
@@ -531,3 +531,212 @@ func TestHPAAnalyzerNamespaceFiltering(t *testing.T) {
}
assert.Equal(t, len(analysisResults), 1)
}
func TestHPAAnalyzerLabelSelectorFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Labels: map[string]string{
"app": "hpa",
},
},
},
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example2",
Namespace: "default",
},
},
)
hpaAnalyzer := HpaAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=hpa",
}
analysisResults, err := hpaAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestHPAAnalyzerStatusFieldAbleToScale(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
},
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
{
Type: "AbleToScale",
Status: "False",
Message: "test reason",
},
},
},
})
hpaAnalyzer := HpaAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := hpaAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestHPAAnalyzerStatusFieldScalingActive(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
},
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
{
Type: autoscalingv2.ScalingActive,
Status: "False",
Message: "test reason",
},
},
},
})
hpaAnalyzer := HpaAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := hpaAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestHPAAnalyzerStatusFieldScalingLimited(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
},
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
{
Type: autoscalingv2.ScalingLimited,
Status: "False",
Message: "test reason",
},
},
},
})
hpaAnalyzer := HpaAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := hpaAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestHPAAnalyzerStatusField(t *testing.T) {
clientset := fake.NewSimpleClientset(
&autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
Name: "example",
},
},
Status: autoscalingv2.HorizontalPodAutoscalerStatus{
Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{
{
Type: autoscalingv2.AbleToScale,
Status: "True",
Message: "recommended size matches current size",
},
{
Type: autoscalingv2.ScalingActive,
Status: "True",
Message: "the HPA was able to successfully calculate a replica count",
},
{
Type: autoscalingv2.ScalingLimited,
Status: "True",
Message: "the desired replica count is less than the minimum replica count",
},
},
},
})
hpaAnalyzer := HpaAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := hpaAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}

View File

@@ -42,7 +42,9 @@ func (HTTPRouteAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
if err != nil {
return nil, err
}
if err := client.List(a.Context, routeList, &ctrl.ListOptions{}); err != nil {
labelSelector := util.LabelStrToSelector(a.LabelSelector)
if err := client.List(a.Context, routeList, &ctrl.ListOptions{LabelSelector: labelSelector}); err != nil {
return nil, err
}
var preAnalysis = map[string]common.PreAnalysis{}

View File

@@ -41,7 +41,7 @@ func (IngressAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
"analyzer_name": kind,
})
list, err := a.Client.GetClient().NetworkingV1().Ingresses(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().NetworkingV1().Ingresses(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -201,3 +201,40 @@ func TestIngressAnalyzer(t *testing.T) {
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
}
func TestIngressAnalyzerLabelSelectorFiltering(t *testing.T) {
validIgClassName := new(string)
*validIgClassName = "valid-ingress-class"
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress1",
Namespace: "default",
Labels: map[string]string{
"app": "ingress",
},
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress2",
Namespace: "default",
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=ingress",
}
igAnalyzer := IngressAnalyzer{}
results, err := igAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/Ingress1", results[0].Name)
}

View File

@@ -41,7 +41,7 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
})
// search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}
@@ -71,7 +71,7 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
rawlogs := string(podLogs)
if errorPattern.MatchString(strings.ToLower(rawlogs)) {
failures = append(failures, common.Failure{
Text: printErrorLines(pod.Name, pod.Namespace, rawlogs, errorPattern),
Text: printErrorLines(rawlogs, errorPattern),
Sensitive: []common.Sensitive{
{
Unmasked: pod.Name,
@@ -105,7 +105,7 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
return a.Results, nil
}
func printErrorLines(podName, namespace, logs string, errorPattern *regexp.Regexp) string {
func printErrorLines(logs string, errorPattern *regexp.Regexp) string {
// Split the logs into lines
logLines := strings.Split(logs, "\n")

173
pkg/analyzer/log_test.go Normal file
View File

@@ -0,0 +1,173 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package analyzer
import (
"context"
"regexp"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestLogAnalyzer(t *testing.T) {
oldPattern := errorPattern
errorPattern = regexp.MustCompile(`(fake logs)`)
t.Cleanup(func() {
errorPattern = oldPattern
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
Labels: map[string]string{
"Name": "Pod1",
"Namespace": "default",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container1",
},
{
Name: "test-container2",
},
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod2",
Namespace: "default",
Labels: map[string]string{
"Name": "Pod1",
"Namespace": "default",
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod3",
Namespace: "test-namespace",
Labels: map[string]string{
"Name": "Pod1",
"Namespace": "test-namespace",
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod4",
Namespace: "default",
Labels: map[string]string{
"Name": "Pod4",
"Namespace": "default",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container3",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
}
logAnalyzer := LogAnalyzer{}
results, err := logAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
expectations := []string{"default/Pod1/test-container1", "default/Pod1/test-container2", "default/Pod4/test-container3"}
for i, expectation := range expectations {
require.Equal(t, expectation, results[i].Name)
for _, failure := range results[i].Error {
require.Equal(t, "fake logs", failure.Text)
}
}
}
func TestLogAnalyzerLabelSelectorFiltering(t *testing.T) {
oldPattern := errorPattern
errorPattern = regexp.MustCompile(`(fake logs)`)
t.Cleanup(func() {
errorPattern = oldPattern
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
Labels: map[string]string{
"app": "log",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container1",
},
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod2",
Namespace: "default",
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container2",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=log",
}
logAnalyzer := LogAnalyzer{}
results, err := logAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/Pod1/test-container1", results[0].Name)
}

View File

@@ -42,7 +42,7 @@ func (MutatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, erro
"analyzer_name": kind,
})
mutatingWebhooks, err := a.Client.GetClient().AdmissionregistrationV1().MutatingWebhookConfigurations().List(context.Background(), v1.ListOptions{})
mutatingWebhooks, err := a.Client.GetClient().AdmissionregistrationV1().MutatingWebhookConfigurations().List(context.Background(), v1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -138,3 +138,78 @@ func TestMutatingWebhookAnalyzer(t *testing.T) {
resultsLen := 3
require.Equal(t, resultsLen, len(results))
}
func TestMutatingWebhookAnalyzerLabelSelectorFiltering(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
Labels: map[string]string{
"app": "mutating-webhook",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service1",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "mutating-webhook",
},
},
},
&admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-mutating-webhook-config",
Namespace: "default",
Labels: map[string]string{
"app": "mutating-webhook",
},
},
Webhooks: []admissionregistrationv1.MutatingWebhook{
{
Name: "webhook1",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
},
},
&admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-mutating-webhook-config2",
Namespace: "default",
},
Webhooks: []admissionregistrationv1.MutatingWebhook{
{
Name: "webhook2",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=mutating-webhook",
}
mwAnalyzer := MutatingWebhookAnalyzer{}
results, err := mwAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/webhook1", results[0].Name)
}

View File

@@ -43,7 +43,7 @@ func (NetworkPolicyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
// get all network policies in the namespace
policies, err := a.Client.GetClient().NetworkingV1().
NetworkPolicies(a.Namespace).List(a.Context, metav1.ListOptions{})
NetworkPolicies(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -220,3 +220,46 @@ func TestNetpolNoPodsNamespaceFiltering(t *testing.T) {
assert.Equal(t, results[0].Kind, "NetworkPolicy")
}
func TestNetpolLabelSelectorFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "example1",
Namespace: "default",
Labels: map[string]string{
"app": "netpol",
},
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "netpol",
},
},
},
},
&networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "example2",
Namespace: "default",
},
},
)
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=netpol",
}
analyzer := NetworkPolicyAnalyzer{}
results, err := analyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(results), 1)
}

View File

@@ -33,7 +33,7 @@ func (NodeAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
"analyzer_name": kind,
})
list, err := a.Client.GetClient().CoreV1().Nodes().List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().CoreV1().Nodes().List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}
@@ -50,6 +50,9 @@ func (NodeAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
break
}
failures = addNodeConditionFailure(failures, node.Name, nodeCondition)
// k3s `EtcdIsVoter`` should not be reported as an error
case v1.NodeConditionType("EtcdIsVoter"):
break
default:
if nodeCondition.Status != v1.ConditionFalse {
failures = addNodeConditionFailure(failures, node.Name, nodeCondition)

View File

@@ -167,3 +167,51 @@ func TestNodeAnalyzer(t *testing.T) {
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
}
func TestNodeAnalyzerLabelSelectorFiltering(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(&v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "Node1",
Namespace: "default",
Labels: map[string]string{
"app": "node",
},
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionFalse,
},
},
},
},
&v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "Node2",
Namespace: "default",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionFalse,
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=node",
}
nAnalyzer := NodeAnalyzer{}
results, err := nAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "Node1", results[0].Name)
}

View File

@@ -41,7 +41,7 @@ func (PdbAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
"analyzer_name": kind,
})
list, err := a.Client.GetClient().PolicyV1().PodDisruptionBudgets(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().PolicyV1().PodDisruptionBudgets(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -115,3 +115,94 @@ func TestPodDisruptionBudgetAnalyzer(t *testing.T) {
require.Equal(t, 1, len(results))
require.Equal(t, "test/PDB3", results[0].Name)
}
func TestPodDisruptionBudgetAnalyzerLabelSelectorFiltering(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "PDB1",
Namespace: "default",
Labels: map[string]string{
"app": "pdb",
},
},
// Status conditions are nil.
Status: policyv1.PodDisruptionBudgetStatus{
Conditions: []metav1.Condition{
{
Type: "DisruptionAllowed",
Status: "False",
Reason: "test reason",
},
},
},
Spec: policyv1.PodDisruptionBudgetSpec{
MaxUnavailable: &intstr.IntOrString{
Type: 0,
IntVal: 17,
StrVal: "17",
},
MinAvailable: &intstr.IntOrString{
Type: 0,
IntVal: 7,
StrVal: "7",
},
// MatchLabels specified.
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
"label2": "test2",
},
},
},
},
&policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "PDB2",
Namespace: "default",
},
// Status conditions are empty.
Status: policyv1.PodDisruptionBudgetStatus{
Conditions: []metav1.Condition{
{
Type: "DisruptionAllowed",
Status: "False",
Reason: "test reason",
},
},
},
Spec: policyv1.PodDisruptionBudgetSpec{
MaxUnavailable: &intstr.IntOrString{
Type: 0,
IntVal: 17,
StrVal: "17",
},
MinAvailable: &intstr.IntOrString{
Type: 0,
IntVal: 7,
StrVal: "7",
},
// MatchLabels specified.
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
"label2": "test2",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=pdb",
}
pdbAnalyzer := PdbAnalyzer{}
results, err := pdbAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/PDB1", results[0].Name)
}

View File

@@ -34,7 +34,9 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
})
// search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().CoreV1().Pods(a.Namespace).List(a.Context, metav1.ListOptions{
LabelSelector: a.LabelSelector,
})
if err != nil {
return nil, err
}

View File

@@ -33,7 +33,7 @@ func (PvcAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
})
// search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().PersistentVolumeClaims(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().CoreV1().PersistentVolumeClaims(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -228,3 +228,53 @@ func TestPersistentVolumeClaimAnalyzer(t *testing.T) {
})
}
}
func TestPvcAnalyzerLabelSelectorFiltering(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
LastTimestamp: metav1.Time{
Time: time.Date(2024, 3, 15, 10, 0, 0, 0, time.UTC),
},
Reason: "ProvisioningFailed",
Message: "PVC Event1 provisioning failed",
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC1",
Namespace: "default",
Labels: map[string]string{
"app": "pvc",
},
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC2",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=pvc",
}
pvcAnalyzer := PvcAnalyzer{}
results, err := pvcAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/PVC1", results[0].Name)
}

View File

@@ -32,7 +32,7 @@ func (ReplicaSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
})
// search all namespaces for pods that are not running
list, err := a.Client.GetClient().AppsV1().ReplicaSets(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().AppsV1().ReplicaSets(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -144,3 +144,58 @@ func TestReplicaSetAnalyzer(t *testing.T) {
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
}
func TestReplicaSetAnalyzerLabelSelectorFiltering(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet1",
Namespace: "default",
Labels: map[string]string{
"app": "replicaset",
},
},
Status: appsv1.ReplicaSetStatus{
Replicas: 0,
Conditions: []appsv1.ReplicaSetCondition{
{
// Should contribute to failures.
Type: appsv1.ReplicaSetReplicaFailure,
Reason: "FailedCreate",
Message: "failed to create test replica set 1",
},
},
},
},
&appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet2",
Namespace: "default",
},
Status: appsv1.ReplicaSetStatus{
Replicas: 0,
Conditions: []appsv1.ReplicaSetCondition{
{
// Should contribute to failures.
Type: appsv1.ReplicaSetReplicaFailure,
Reason: "FailedCreate",
Message: "failed to create test replica set 1",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=replicaset",
}
rsAnalyzer := ReplicaSetAnalyzer{}
results, err := rsAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/ReplicaSet1", results[0].Name)
}

View File

@@ -45,7 +45,7 @@ func (ServiceAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
})
// search all namespaces for pods that are not running
list, err := a.Client.GetClient().CoreV1().Endpoints(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().CoreV1().Endpoints(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -165,3 +165,106 @@ func TestServiceAnalyzer(t *testing.T) {
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
}
func TestServiceAnalyzerLabelSelectorFiltering(t *testing.T) {
clientSet :=
fake.NewSimpleClientset(
&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "Endpoint1",
Namespace: "default",
Labels: map[string]string{
"app": "service",
"part-of": "test",
},
},
// Endpoint with non-zero subsets.
Subsets: []v1.EndpointSubset{
{
// These not ready end points will contribute to failures.
NotReadyAddresses: []v1.EndpointAddress{
{
TargetRef: &v1.ObjectReference{
Kind: "test-reference",
Name: "reference1",
},
},
{
TargetRef: &v1.ObjectReference{
Kind: "test-reference",
Name: "reference2",
},
},
},
},
{
// These not ready end points will contribute to failures.
NotReadyAddresses: []v1.EndpointAddress{
{
TargetRef: &v1.ObjectReference{
Kind: "test-reference",
Name: "reference3",
},
},
},
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "Service1",
Namespace: "default",
Labels: map[string]string{
"app": "service",
},
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app1": "test-app1",
"app2": "test-app2",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "Service2",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app1": "test-app1",
"app2": "test-app2",
},
},
},
)
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=service",
}
sAnalyzer := ServiceAnalyzer{}
results, err := sAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/Endpoint1", results[0].Name)
config = common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=service,part-of=test",
}
sAnalyzer = ServiceAnalyzer{}
results, err = sAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/Endpoint1", results[0].Name)
}

View File

@@ -41,7 +41,7 @@ func (StatefulSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
"analyzer_name": kind,
})
list, err := a.Client.GetClient().AppsV1().StatefulSets(a.Namespace).List(a.Context, metav1.ListOptions{})
list, err := a.Client.GetClient().AppsV1().StatefulSets(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -117,7 +117,7 @@ func TestStatefulSetAnalyzerMissingStorageClass(t *testing.T) {
AccessModes: []corev1.PersistentVolumeAccessMode{
"ReadWriteOnce",
},
Resources: corev1.ResourceRequirements{
Resources: corev1.VolumeResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse("1Gi"),
},
@@ -188,3 +188,55 @@ func TestStatefulSetAnalyzerNamespaceFiltering(t *testing.T) {
}
assert.Equal(t, len(analysisResults), 1)
}
func TestStatefulSetAnalyzerLabelSelectorFiltering(t *testing.T) {
clientSet := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example1",
Namespace: "default",
Labels: map[string]string{
"app": "statefulset",
"part-of": "test",
},
},
},
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example2",
Namespace: "default",
},
},
)
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=statefulset",
}
statefulSetAnalyzer := StatefulSetAnalyzer{}
results, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, 1, len(results))
assert.Equal(t, "default/example1", results[0].Name)
config = common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=statefulset,part-of=test",
}
statefulSetAnalyzer = StatefulSetAnalyzer{}
results, err = statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, 1, len(results))
assert.Equal(t, "default/example1", results[0].Name)
}

View File

@@ -42,7 +42,7 @@ func (ValidatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, er
"analyzer_name": kind,
})
validatingWebhooks, err := a.Client.GetClient().AdmissionregistrationV1().ValidatingWebhookConfigurations().List(context.Background(), v1.ListOptions{})
validatingWebhooks, err := a.Client.GetClient().AdmissionregistrationV1().ValidatingWebhookConfigurations().List(context.Background(), v1.ListOptions{LabelSelector: a.LabelSelector})
if err != nil {
return nil, err
}

View File

@@ -138,3 +138,80 @@ func TestValidatingWebhookAnalyzer(t *testing.T) {
resultsLen := 3
require.Equal(t, resultsLen, len(results))
}
func TestValidatingWebhookAnalyzerLabelSelectorFiltering(t *testing.T) {
clientSet := fake.NewSimpleClientset(
&admissionregistrationv1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-validating-webhook-config1",
Namespace: "default",
Labels: map[string]string{
"app": "validating-webhook",
"part-of": "test",
},
},
Webhooks: []admissionregistrationv1.ValidatingWebhook{
{
// Failure: Pointing to an inactive receiver pod
Name: "webhook1",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
},
},
&admissionregistrationv1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-validating-webhook-config2",
Namespace: "default",
},
Webhooks: []admissionregistrationv1.ValidatingWebhook{
{
// Failure: Pointing to an inactive receiver pod
Name: "webhook1",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
},
},
)
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=validating-webhook",
}
vwAnalyzer := ValidatingWebhookAnalyzer{}
results, err := vwAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
require.Equal(t, 1, len(results))
config = common.Analyzer{
Client: &kubernetes.Client{
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=validating-webhook,part-of=test",
}
vwAnalyzer = ValidatingWebhookAnalyzer{}
results, err = vwAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
require.Equal(t, 1, len(results))
}

View File

@@ -21,9 +21,10 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
keda "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
kyverno "github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
regv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
autov1 "k8s.io/api/autoscaling/v1"
autov2 "k8s.io/api/autoscaling/v2"
v1 "k8s.io/api/core/v1"
networkv1 "k8s.io/api/networking/v1"
policyv1 "k8s.io/api/policy/v1"
@@ -38,6 +39,7 @@ type Analyzer struct {
Client *kubernetes.Client
Context context.Context
Namespace string
LabelSelector string
AIClient ai.IAI
PreAnalysis map[string]PreAnalysis
Results []Result
@@ -52,7 +54,7 @@ type PreAnalysis struct {
PersistentVolumeClaim v1.PersistentVolumeClaim
Endpoint v1.Endpoints
Ingress networkv1.Ingress
HorizontalPodAutoscalers autov1.HorizontalPodAutoscaler
HorizontalPodAutoscalers autov2.HorizontalPodAutoscaler
PodDisruptionBudget policyv1.PodDisruptionBudget
StatefulSet appsv1.StatefulSet
NetworkPolicy networkv1.NetworkPolicy
@@ -63,9 +65,11 @@ type PreAnalysis struct {
Gateway gtwapi.Gateway
HTTPRoute gtwapi.HTTPRoute
// Integrations
ScaledObject keda.ScaledObject
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
ScaledObject keda.ScaledObject
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
KyvernoPolicyReport kyverno.PolicyReport
KyvernoClusterPolicyReport kyverno.ClusterPolicyReport
}
type Result struct {

View File

@@ -1,11 +1,12 @@
package aws
import (
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/spf13/viper"
"os"
)
type AWS struct {
@@ -23,16 +24,28 @@ func (a *AWS) UnDeploy(namespace string) error {
}
func (a *AWS) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {
// Check for AWS credentials in the environment
// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
if os.Getenv("AWS_ACCESS_KEY_ID") == "" || os.Getenv("AWS_SECRET_ACCESS_KEY") == "" {
panic("AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be set in the environment")
// Retrieve AWS credentials from the environment
accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
awsProfile := os.Getenv("AWS_PROFILE")
var sess *session.Session
if accessKeyID != "" && secretAccessKey != "" {
// Use access keys if both are provided
sess = session.Must(session.NewSessionWithOptions(session.Options{
Config: aws.Config{},
}))
} else {
// Use AWS profile, default to "default" if not set
if awsProfile == "" {
awsProfile = "default"
}
sess = session.Must(session.NewSessionWithOptions(session.Options{
Profile: awsProfile,
SharedConfigState: session.SharedConfigEnable,
}))
}
sess := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Config: aws.Config{},
}))
a.sess = sess
(*mergedMap)["EKS"] = &EKSAnalyzer{
session: a.sess,

View File

@@ -18,6 +18,7 @@ import (
"fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/aws"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/kyverno"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/keda"
@@ -52,6 +53,7 @@ var integrations = map[string]IIntegration{
"prometheus": prometheus.NewPrometheus(),
"aws": aws.NewAWS(),
"keda": keda.NewKeda(),
"kyverno": kyverno.NewKyverno(),
}
func NewIntegration() *Integration {
@@ -92,7 +94,7 @@ func (*Integration) Activate(name string, namespace string, activeFilters []stri
if !skipInstall {
if err := integrations[name].Deploy(namespace); err != nil {
return err
return fmt.Errorf("failed to deploy %s integration: %w", name, err)
}
}
mergedFilters := activeFilters
@@ -127,7 +129,7 @@ func (*Integration) Deactivate(name string, namespace string) error {
}
if err := integrations[name].UnDeploy(namespace); err != nil {
return err
return fmt.Errorf("failed to undeploy %s integration: %w", name, err)
}
viper.Set("active_filters", activeFilters)

View File

@@ -0,0 +1,142 @@
/*
Copyright 2024 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package integration
import (
"os"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestAnalyzerByIntegration(t *testing.T) {
integration := NewIntegration()
_, err := integration.Get("invalid-name")
require.ErrorContains(t, err, "integration not found")
tests := []struct {
name string
expectedName string
expectedErr string
}{
{
name: "random",
expectedErr: "analyzerbyintegration: no matches found",
},
{
name: "PrometheusConfigValidate",
expectedName: "prometheus",
},
{
name: "PrometheusConfigRelabelReport",
expectedName: "prometheus",
},
{
name: "VulnerabilityReport",
expectedName: "trivy",
},
{
name: "ConfigAuditReport",
expectedName: "trivy",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
name, err := integration.AnalyzerByIntegration(tt.name)
if tt.expectedErr == "" {
require.NoError(t, err)
require.Equal(t, tt.expectedName, name)
} else {
require.ErrorContains(t, err, tt.expectedErr)
require.Empty(t, name)
}
})
}
}
func TestActivate(t *testing.T) {
integration := NewIntegration()
err := integration.Activate("prometheus", "", []string{}, true)
require.ErrorContains(t, err, "error writing config file:")
err = integration.Deactivate("prometheus", "")
require.ErrorContains(t, err, "error writing config file:")
configFileName := "config.json"
_, err = os.CreateTemp("", configFileName)
require.NoError(t, err)
defer os.Remove(configFileName)
// Set the configuration file in viper
viper.SetConfigType("json")
viper.SetConfigFile(configFileName)
inteNotFoundErr := "integration not found"
tests := []struct {
name string
namespace string
activeFilters []string
skipInstall bool
expectedIsActivate bool
expectedActivationErr string
expectedIsActivateError string
expectedDeactivationErr string
}{
{
name: "invalid integration",
expectedActivationErr: inteNotFoundErr,
expectedIsActivateError: inteNotFoundErr,
expectedDeactivationErr: inteNotFoundErr,
},
{
name: "prometheus",
skipInstall: true,
expectedIsActivate: true,
},
{
name: "trivy",
skipInstall: false,
expectedActivationErr: "failed to deploy trivy integration:",
expectedDeactivationErr: "failed to undeploy trivy integration:",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
err := integration.Activate(tt.name, tt.namespace, tt.activeFilters, tt.skipInstall)
if tt.expectedActivationErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tt.expectedActivationErr)
}
ok, err := integration.IsActivate(tt.name)
if tt.expectedIsActivateError == "" {
require.NoError(t, err)
require.Equal(t, tt.expectedIsActivate, ok)
} else {
require.ErrorContains(t, err, tt.expectedIsActivateError)
}
err = integration.Deactivate(tt.name, tt.namespace)
if tt.expectedDeactivationErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tt.expectedDeactivationErr)
}
})
}
}

View File

@@ -0,0 +1,162 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kyverno
import (
"fmt"
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
)
// "github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2"
type KyvernoAnalyzer struct {
policyReportAnalysis bool
clusterReportAnalysis bool
}
func (KyvernoAnalyzer) analyzePolicyReports(a common.Analyzer) ([]common.Result, error) {
result := &v1alpha2.PolicyReportList{}
client := a.Client.CtrlClient
err := v1alpha2.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
return nil, err
}
// Find criticals and get CVE
var preAnalysis = map[string]common.PreAnalysis{}
for _, report := range result.Items {
// For each pod there may be multiple vulnerabilities
var failures []common.Failure
for _, vuln := range report.Results {
if vuln.Result == "fail" {
// get the vulnerability ID
// get the vulnerability description
failures = append(failures, common.Failure{
Text: fmt.Sprintf("policy failure: %s (message: %s)", vuln.Policy, vuln.Message),
Sensitive: []common.Sensitive{},
})
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
report.Name)] = common.PreAnalysis{
KyvernoPolicyReport: report,
FailureDetails: failures,
}
}
}
for key, value := range preAnalysis {
var currentAnalysis = common.Result{
Kind: "PolicyReport",
Name: key,
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.KyvernoPolicyReport.ObjectMeta)
currentAnalysis.ParentObject = parent
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil
}
func (t KyvernoAnalyzer) analyzeClusterPolicyReports(a common.Analyzer) ([]common.Result, error) {
result := &v1alpha2.ClusterPolicyReportList{}
client := a.Client.CtrlClient
err := v1alpha2.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
if err := client.List(a.Context, result, &ctrl.ListOptions{}); err != nil {
return nil, err
}
// Find criticals and get CVE
var preAnalysis = map[string]common.PreAnalysis{}
for _, report := range result.Items {
// For each pod there may be multiple vulnerabilities
var failures []common.Failure
for _, vuln := range report.Results {
if vuln.Severity == "CRITICAL" {
// get the vulnerability ID
// get the vulnerability description
failures = append(failures, common.Failure{
Text: fmt.Sprintf("critical Vulnerability found ID: %s (learn more at: %s)", vuln.ID, vuln.Source),
Sensitive: []common.Sensitive{},
})
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
report.Name)] = common.PreAnalysis{
KyvernoClusterPolicyReport: report,
FailureDetails: failures,
}
}
}
for key, value := range preAnalysis {
var currentAnalysis = common.Result{
Kind: "ClusterPolicyReport",
Name: key,
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.KyvernoClusterPolicyReport.ObjectMeta)
currentAnalysis.ParentObject = parent
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil
}
func (t KyvernoAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
if t.policyReportAnalysis {
common := make([]common.Result, 0)
vresult, err := t.analyzePolicyReports(a)
if err != nil {
return nil, err
}
common = append(common, vresult...)
return common, nil
}
if t.clusterReportAnalysis {
common := make([]common.Result, 0)
cresult, err := t.analyzeClusterPolicyReports(a)
if err != nil {
return nil, err
}
common = append(common, cresult...)
return common, nil
}
return make([]common.Result, 0), nil
}

View File

@@ -0,0 +1,117 @@
/*
Copyright 2023 The K8sGPT Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kyverno
import (
"os"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
)
type Kyverno struct{}
func NewKyverno() *Kyverno {
return &Kyverno{}
}
func (k *Kyverno) GetAnalyzerName() []string {
return []string{
//from wgpolicyk8s.io/v1alpha2
"PolicyReport",
"ClusterPolicyReport",
}
}
func (k *Kyverno) OwnsAnalyzer(analyzer string) bool {
for _, a := range k.GetAnalyzerName() {
if analyzer == a {
return true
}
}
return false
}
func (k *Kyverno) isDeployed() bool {
// check if wgpolicyk8s apigroup is available as a marker if new policy resource available is installed on the cluster
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
// TODO: better error handling
color.Red("Error initialising kubernetes client: %v", err)
os.Exit(1)
}
groups, _, err := client.Client.Discovery().ServerGroupsAndResources()
if err != nil {
// TODO: better error handling
color.Red("Error initialising discovery client: %v", err)
os.Exit(1)
}
for _, group := range groups {
if group.Name == "kyverno.io" {
return true
}
}
return false
}
func (k *Kyverno) isFilterActive() bool {
activeFilters := viper.GetStringSlice("active_filters")
for _, filter := range k.GetAnalyzerName() {
for _, af := range activeFilters {
if af == filter {
return true
}
}
}
return false
}
func (k *Kyverno) IsActivate() bool {
if k.isFilterActive() && k.isDeployed() {
return true
} else {
return false
}
}
func (k *Kyverno) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {
(*mergedMap)["PolicyReport"] = &KyvernoAnalyzer{
policyReportAnalysis: true,
}
(*mergedMap)["ClusterPolicyReport"] = &KyvernoAnalyzer{
clusterReportAnalysis: true,
}
}
func (k *Kyverno) Deploy(namespace string) error {
return nil
}
func (k *Kyverno) UnDeploy(_ string) error {
return nil
}
func (t *Kyverno) GetNamespace() (string, error) {
return "", nil
}

View File

@@ -53,7 +53,7 @@ func (p *Prometheus) Deploy(namespace string) error {
// manage Prometheus on the behalf of users.
podConfigs, err := findPrometheusPodConfigs(ctx, client.GetClient(), namespace)
if err != nil {
color.Red("Error discovering Prometheus worklads: %v", err)
color.Red("Error discovering Prometheus workloads: %v", err)
os.Exit(1)
}
if len(podConfigs) == 0 {

View File

@@ -1,10 +1,9 @@
package server
import (
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
json "encoding/json"
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
)
@@ -25,11 +24,13 @@ func (h *handler) Analyze(ctx context.Context, i *schemav1.AnalyzeRequest) (
i.Language,
i.Filters,
i.Namespace,
i.LabelSelector,
i.Nocache,
i.Explain,
int(i.MaxConcurrency),
false, // Kubernetes Doc disabled in server mode
false, // Interactive mode disabled in server mode
false, // Kubernetes Doc disabled in server mode
false, // Interactive mode disabled in server mode
[]string{}, //TODO: add custom http headers in server mode
)
config.Context = ctx // Replace context for correct timeouts.
if err != nil {
@@ -37,6 +38,9 @@ func (h *handler) Analyze(ctx context.Context, i *schemav1.AnalyzeRequest) (
}
defer config.Close()
if config.CustomAnalyzersAreAvailable() {
config.RunCustomAnalysis()
}
config.RunAnalysis()
if i.Explain {

View File

@@ -1,10 +1,11 @@
package server
import (
"context"
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/custom"
"github.com/spf13/viper"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -27,6 +28,38 @@ func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (
return resp, err
}
if i.CustomAnalyzers != nil {
// We need to add the custom analyzers to the viper config and save them
var customAnalyzers = make([]custom.CustomAnalyzer, 0)
if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil {
return resp, err
} else {
// If there are analyzers are already in the config we will append the ones with new names
for _, ca := range i.CustomAnalyzers {
exists := false
for _, c := range customAnalyzers {
if c.Name == ca.Name {
exists = true
break
}
}
if !exists {
customAnalyzers = append(customAnalyzers, custom.CustomAnalyzer{
Name: ca.Name,
Connection: custom.Connection{
Url: ca.Connection.Url,
Port: ca.Connection.Port,
},
})
}
}
// save the config
viper.Set("custom_analyzers", customAnalyzers)
if err := viper.WriteConfig(); err != nil {
return resp, err
}
}
}
if i.Cache != nil {
var err error
var remoteCache cache.CacheProvider

View File

@@ -21,10 +21,13 @@ import (
"encoding/hex"
"errors"
"fmt"
"net/http"
"os"
"regexp"
"strings"
"k8s.io/apimachinery/pkg/labels"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -261,3 +264,50 @@ func FetchLatestEvent(ctx context.Context, kubernetesClient *kubernetes.Client,
}
return latestEvent, nil
}
// NewHeaders parses a slice of strings in the format "key:value" into []http.Header
// It handles headers with the same key by appending values
func NewHeaders(customHeaders []string) []http.Header {
headers := make(map[string][]string)
for _, header := range customHeaders {
vals := strings.SplitN(header, ":", 2)
if len(vals) != 2 {
//TODO: Handle error instead of ignoring it
continue
}
key := strings.TrimSpace(vals[0])
value := strings.TrimSpace(vals[1])
if _, ok := headers[key]; !ok {
headers[key] = []string{}
}
headers[key] = append(headers[key], value)
}
// Convert map to []http.Header format
var result []http.Header
for key, values := range headers {
header := make(http.Header)
for _, value := range values {
header.Add(key, value)
}
result = append(result, header)
}
return result
}
func LabelStrToSelector(labelStr string) labels.Selector {
if labelStr == "" {
return nil
}
labelSelectorMap := make(map[string]string)
for _, s := range strings.Split(labelStr, ",") {
parts := strings.SplitN(s, "=", 2)
if len(parts) == 2 {
labelSelectorMap[parts[0]] = parts[1]
}
}
return labels.SelectorFromSet(labels.Set(labelSelectorMap))
}