Compare commits

...

372 Commits

Author SHA1 Message Date
AlexsJones
2d5c08c615 feat: adding entire AWS model catalog
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2025-02-05 10:02:33 +00:00
Daniel Clark
83672fa768 fix: prevent npe by handling checking error in NewAnalysis call (#1365)
If there is an issue in creating the Analysis config when calling
analysis.NewAnalysis, then we want to check before assigning the context to a
potentially nil pointer.

Signed-off-by: Danny Clark <danielclark@google.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2025-01-31 14:26:35 +00:00
renovate[bot]
990d723909 chore(deps): update codecov/codecov-action digest to 13ce06b (#1342)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-25 17:06:09 +00:00
renovate[bot]
c506a4b441 chore(deps): update actions/upload-artifact digest to 65c4c4a (#1350)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 20:48:55 +00:00
renovate[bot]
2918556793 chore(deps): update docker/setup-buildx-action digest to 6524bf6 (#1349)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 20:21:46 +00:00
renovate[bot]
19abbef9a3 fix(deps): update module gopkg.in/yaml.v2 to v3 (#1336)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 07:35:23 +00:00
renovate[bot]
939e0672aa chore(deps): update actions/setup-go digest to 3041bf5 (#1347)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-12 17:24:09 +00:00
renovate[bot]
8cd3b2985e fix(deps): update all non-major dependencies (#1335)
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-12-10 09:41:16 +00:00
github-actions[bot]
1827c43696 chore(main): release 0.3.48 (#1341)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-04 14:07:11 +00:00
Alex Jones
1363219b1b feat: fixed missing cache params (#1340)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-12-04 10:30:57 +00:00
github-actions[bot]
c3f448693d chore(main): release 0.3.47 (#1320)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-02 16:45:20 +00:00
renovate[bot]
5514ebb53b fix(deps): update module gopkg.in/yaml.v2 to v3 (#1326)
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-12-02 13:45:39 +00:00
renovate[bot]
c21ba86237 chore(deps): update docker/build-push-action digest to 48aba3b (#1333)
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-12-02 13:08:07 +00:00
Alex Jones
d6d80ee860 feat: adds interplex as a caching provider (#1328)
* feat: adds interplex as a caching provider

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

* chore: refactored cache input to lower

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

* chore: refactored cache input to lower

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-12-02 12:58:08 +00:00
renovate[bot]
a841568a9c chore(deps): update all non-major dependencies (#1327)
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-12-02 12:08:02 +00:00
renovate[bot]
4d7eb0f622 chore(deps): update codecov/codecov-action digest to 015f24e (#1325)
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-11-26 13:56:01 +00:00
ju187
a12aa07b1a feat: add new AWS Bedrock model ids (#1330)
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-11-25 07:37:39 +00:00
100daysofdevops
ec5e42b8f4 fix: update OpenAI API key generation URL to reflect new platform link (#1331)
Updated the outdated URL 'https://beta.openai.com/account/api-keys' to the current OpenAI API key generation page 'https://platform.openai.com/account/api-keys'.

This resolves the issue where users were directed to an incorrect URL when generating an OpenAI API key.

Signed-off-by: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com>
2024-11-25 07:32:11 +00:00
renovate[bot]
69c67bd1d9 fix(deps): update module gopkg.in/yaml.v2 to v3 (#1321)
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-11-17 19:59:22 +00:00
renovate[bot]
b3f60b2d20 fix(deps): update all non-major dependencies (#1323)
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-11-17 16:41:15 +00:00
renovate[bot]
cb1e1ffede chore(deps): update codecov/codecov-action action to v5 (#1324)
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-11-15 12:24:26 +00:00
renovate[bot]
f37d923918 chore(deps): update docker/build-push-action action to v6 (#1294)
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-11-12 20:36:32 +00:00
Samir Tahir
a50375c960 fix: add maxTokens to serve mode (#1280)
Signed-off-by: samir-tahir <samirtahir91@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-11-12 20:16:29 +00:00
Alex Jones
da266b3c82 feat: dump (#1322)
* feat: reverting the cncf runners

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

* feat: creating a dump file for debugging

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

* chore: ran the linter

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

* chore: updated

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

* chore: updated

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

* chore: improved the function readme

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

* feat: added k8sgpt version info

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

* feat: added k8sgpt version info

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

* chore: added additional command

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-12 12:04:01 +00:00
renovate[bot]
896a53be83 chore(deps): update rajatjindal/krew-release-bot action to v0.0.47 (#1317)
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-11-12 07:13:06 +00:00
renovate[bot]
2da057360b fix(deps): update module gopkg.in/yaml.v2 to v3 (#1303)
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-11-11 06:09:39 +00:00
github-actions[bot]
69fd7c7696 chore(main): release 0.3.46 (#1316)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-10 21:00:49 +00:00
Alex Jones
ad86e7aa39 feat: reverting the cncf runners (#1319)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-10 20:54:16 +00:00
Alex Jones
1ae70e806e feat: updated runners to enterprise (#1318)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-10 20:26:43 +00:00
renovate[bot]
2ce8450e03 chore(deps): update actions/setup-go digest to 41dfa10 (#1284)
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-11-10 17:13:38 +00:00
renovate[bot]
b6b3d0c856 chore(deps): update softprops/action-gh-release action to v2 (#1295)
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-11-10 16:29:01 +00:00
Alex Jones
5f7d9de46a feat: switching to higher spec runners (#1312)
* feat: switching to higher spec runners

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

* chore: switched to runner groups

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

* chore: switched to runner groups

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

* chore: switched to runner groups

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-10 16:06:06 +00:00
Alex Jones
7dcdfc83d2 feat: testupdate (#1315)
* feat: updated server test function

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

* chore: fixed server test

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

* chore: updated go.sum

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

* feat: added free disk space to release job

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-10 15:33:50 +00:00
github-actions[bot]
44f4f7437f chore(main): release 0.3.45 (#1314)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-10 09:25:48 +00:00
Alex Jones
783cd1cfc6 feat: free disk (#1313)
* chore: updated go.sum

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

* feat: added free disk space to release job

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

* feat: added free disk space to release job

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-10 09:11:54 +00:00
github-actions[bot]
62ba6d84a4 chore(main): release 0.3.44 (#1311)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-09 17:55:26 +00:00
Alex Jones
cc9b3ea657 feat: test revert runner on release job (#1310)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-11-09 17:44:56 +00:00
github-actions[bot]
8ad288152f chore(main): release 0.3.43 (#1301)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-11-09 16:05:58 +00:00
renovate[bot]
004d9efc55 fix(deps): update all non-major dependencies (#1307)
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-11-09 15:10:05 +00:00
renovate[bot]
2f62c7b3e0 fix(deps): update k8s.io/utils digest to 6fe5fd8 (#1302)
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-11-07 17:24:45 +00:00
renovate[bot]
a6b19a81b0 fix(deps): update all non-major dependencies (#1306)
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-11-06 14:54:35 +00:00
renovate[bot]
32e8bc3253 chore(deps): update all non-major dependencies (#1304)
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-11-05 19:56:29 +00:00
Alex Jones
5f01cc685f chore: updated to use CNCF runners (#1305)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-11-05 16:48:01 +00:00
renovate[bot]
c67add30c6 chore(deps): update dependency ubuntu to v24 (#1293)
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-11-05 07:07:28 +00:00
renovate[bot]
2f759865b6 fix(deps): update module gopkg.in/yaml.v2 to v3 (#1296)
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-11-04 12:52:27 +00:00
github-actions[bot]
9d68c47040 chore(main): release 0.3.42 (#1258)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-04 07:38:22 +00:00
renovate[bot]
14e0f19b12 fix(deps): update all non-major dependencies (#1291)
* fix(deps): update all non-major dependencies

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore: fixed the topk type

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

---------

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AlexsJones <alexsimonjones@gmail.com>
2024-11-04 07:12:57 +00:00
renovate[bot]
c1a38c2b35 chore(deps): update codecov/codecov-action action to v4 (#1292)
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-10-31 18:42:55 +00:00
Alex Jones
458fcfe8d3 chore: renovate.json (#1290)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-10-31 16:56:49 +00:00
renovate[bot]
173e4dc5ac chore(deps): update anchore/sbom-action action to v0.17.6 (#1285)
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-10-31 16:14:53 +00:00
renovate[bot]
7a3fb3cf67 fix(deps): update module github.com/cohere-ai/cohere-go/v2 to v2.12.0 (#1276)
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-10-31 15:16:05 +00:00
renovate[bot]
0cfecbdd87 chore(deps): update actions/checkout digest to 11bd719 (#1283)
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-10-31 09:05:10 +00:00
renovate[bot]
161bc11294 chore(deps): update docker/setup-buildx-action digest to c47758b (#1213)
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-10-31 08:42:10 +00:00
renovate[bot]
ad349ae263 fix(deps): update module github.com/google/generative-ai-go to v0.18.0 (#1278)
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-10-31 08:34:03 +00:00
renovate[bot]
911d578bf0 chore(deps): update actions/upload-artifact digest to b4b15b8 (#1272)
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-10-31 07:42:42 +00:00
Matthis
3eec9bbb05 feat: add stats option to analyze command for performance insights (#1237)
* feat: add stats option to analyze command for performance insights

Introduced a new feature to the analyze command that enables users to print detailed performance statistics of each analyzer. This enhancement aids in debugging and understanding the time taken by various components during analysis, providing valuable insights for performance optimization.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: enhance analysis command with statistics option

Refactored the analysis command to support an enhanced statistics option, enabling users to opt-in for detailed performance metrics of the analysis process. This change introduces a more flexible approach to handling statistics, allowing for a clearer separation between the analysis output and performance metrics, thereby improving the usability and insights provided to the user.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

---------

Signed-off-by: Matthis Holleville <matthish29@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-10-30 13:58:18 +00:00
Milap Jhumkhawala
87565a0bcc fix: [Bug] Make lint command is not working (#1282)
* fix: [Bug] Make lint command is not working

Signed-off-by: Milap Jhumkhawala <milap.jhumkhawala@gmail.com>

* forgot to sign commit

Signed-off-by: Milap Jhumkhawala <milap.jhumkhawala@gmail.com>

---------

Signed-off-by: Milap Jhumkhawala <milap.jhumkhawala@gmail.com>
2024-10-30 10:49:44 +00:00
renovate[bot]
c128bf7942 chore(deps): update anchore/sbom-action action to v0.17.4 (#1273)
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-10-16 15:41:54 +01:00
renovate[bot]
c9b11b6eee fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.4.1 (#1275)
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-10-15 07:07:41 +01:00
renovate[bot]
9f39abf89e fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go to v1.35.1-20240920204244-7a91c8620515.1 (#1274)
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-10-14 12:55:19 +01:00
renovate[bot]
98237b6408 fix(deps): update module github.com/adrg/xdg to v0.5.0 (#1262)
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-10-14 07:58:02 +01:00
renovate[bot]
4143e9fd52 fix(deps): update module cloud.google.com/go/storage to v1.44.0 (#1265)
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-10-14 06:48:07 +01:00
renovate[bot]
72eb8159fb chore(deps): update actions/checkout digest to eef6144 (#1270)
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-10-14 06:38:32 +01:00
renovate[bot]
36135857ac fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.8.0 (#1264)
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-10-11 08:02:01 +01:00
renovate[bot]
9c1927b497 chore(deps): update module github.com/docker/docker to v27.3.1+incompatible (#1225)
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-10-04 07:54:27 +01:00
renovate[bot]
0148a5b354 fix(deps): update module github.com/aws/aws-sdk-go to v1.55.5 (#1263)
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-10-03 19:19:28 +01:00
renovate[bot]
037e745c6f fix(deps): update module github.com/aquasecurity/trivy-operator to v0.22.0 (#1034)
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-10-03 19:05:04 +01:00
Naveen Thangaraj
d8fad956f4 feat: error from events for STS analyzer (#1256)
* error from events for sts analyzer

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

* Signedoff this commit

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

---------

Signed-off-by: naveenthangaraj03 <tnaveen3402@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-10-03 18:33:50 +01:00
renovate[bot]
7785dd12a0 fix(deps): update k8s.io/utils digest to 49e7df5 (#1259)
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-09-29 20:55:29 +01:00
renovate[bot]
04582d8516 chore(deps): update anchore/sbom-action action to v0.17.2 (#1248)
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-09-27 07:45:54 +01:00
Yanwei Li
da0764d951 fix: add providerId to serve mode (#1260)
Signed-off-by: yanweili <yanweili@ibm.com>
Co-authored-by: yanweili <yanweili@ibm.com>
2024-09-27 07:32:58 +01:00
renovate[bot]
b62b7dbe3c chore(deps): update golang docker tag to v1.23 (#1254)
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-09-25 09:13:45 +01:00
Guangya Liu
5ff6dc9be5 fix: rename watsonxai to ibmwatsonxai (#1234)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-09-24 21:58:01 +01:00
github-actions[bot]
f071b32aa8 chore(main): release 0.3.41 (#1217)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-23 06:33:03 +01:00
Alex Jones
53465d5c83 feat: adding a query mode for the schednex scheduler (#1257)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-09-22 19:29:29 +01:00
renovate[bot]
1dfd139731 fix(deps): update module github.com/mittwald/go-helm-client to v0.12.13 (#1251)
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-09-19 12:08:13 +01:00
Alex Jones
d9c81494b7 Update README.md (#1253)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-09-19 09:04:52 +01:00
renovate[bot]
e0e86ea60f chore(deps): update actions/upload-artifact digest to 5076954 (#1239)
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-09-19 08:41:46 +01:00
renovate[bot]
8405778cb2 fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.22.0-20240807134501-ea98c104104d.1 (#1186)
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-09-18 20:18:03 +01:00
awsyshah
4f3ecf0083 feat: added support for A21 and Amazon Titan models via bedrock api (#1101)
* feat: added support for A21 and Amazon Titan models via bedrock api

Signed-off-by: Yomesh Shah <yomesh@gmail.com>

* fix: response type for diffrent models and use of constant for top_P

Signed-off-by: Yomesh Shah <yomesh@gmail.com>

* fix: constant for top_P as int vs string

Signed-off-by: Yomesh Shah <yomesh@gmail.com>

* feat: moved topP and maxTokens to config rather than being constants in the code

Signed-off-by: Yomesh Shah <yomesh@gmail.com>

---------

Signed-off-by: Yomesh Shah <yomesh@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-09-17 16:24:21 +01:00
renovate[bot]
d30563d8cd fix(deps): update k8s.io/utils digest to 702e33f (#1246)
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-09-17 15:01:52 +01:00
Aris Boutselis
e02c0ddd2d fix: typo (#1244)
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-09-17 08:39:39 +01:00
renovate[bot]
025a069ff1 fix(deps): update module github.com/schollz/progressbar/v3 to v3.15.0 (#1227)
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-09-16 11:43:11 +01:00
renovate[bot]
453d5c37dd chore(deps): update dependency go to v1.23.1 (#1176)
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-09-16 07:09:27 +01:00
Dominik Augustin
be4ca86af0 fix: helm chart security context rendering if empty (#1235)
Signed-off-by: Dominik Augustin <botchk@users.noreply.github.com>
Co-authored-by: Dominik Augustin <botchk@users.noreply.github.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-09-09 07:58:05 +01:00
renovate[bot]
477ef155d3 chore(deps): update docker/login-action digest to 9780b0c (#1212)
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-09-02 07:43:20 +01:00
michael12312
8edb053b3e fix: issue-1168, remove duplicate CVE (#1230) 2024-08-27 07:21:38 +02:00
Guangya Liu
644581f495 fix: disable adding multiple openai provider (#1191)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Matthis <matthish29@gmail.com>
2024-08-20 15:52:44 +02:00
Guangya Liu
d702209941 fix: enabled auth add support watsonx backend (#1190)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Matthis <matthish29@gmail.com>
2024-08-20 09:35:45 +02:00
renovate[bot]
7019d0b62f fix(deps): update module github.com/mittwald/go-helm-client to v0.12.12 (#1226)
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-15 18:38:16 +01:00
renovate[bot]
f57381961f chore(deps): update anchore/sbom-action action to v0.17.1 (#1224)
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-15 18:22:11 +01:00
Alex Jones
02fa109429 feat: refactoring to the new schema (#1219)
* feat: refactoring to the new schema

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

* chore: updated readme with grpc commands

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

* chore: updated deps

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

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
Co-authored-by: Matthis <matthish29@gmail.com>
2024-08-15 14:42:55 +01:00
renovate[bot]
3148b5c61d fix(deps): update module github.com/docker/docker to v27.1.1+incompatible [security] (#1220)
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-13 13:17:40 +01:00
Xuetao Song
a4e44d59e3 feat: add event failure handling in service analyzer (#1132)
Signed-off-by: magicsong <songxuetao@bytedance.com>

Co-authored-by: magicsong <songxuetao@bytedance.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-08-13 06:36:15 +01:00
renovate[bot]
24ebeaf3a7 chore(deps): update actions/checkout digest to 692973e (#1129)
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-13 06:34:46 +01:00
Matthis
db26d24ac6 feat: add custom-analyzer cmd (#1207)
* feat: add custom analyzer management capability

Introduced the ability to manage custom analyzers in the K8sGPT application, enabling users to add, deploy, and configure custom analyzers from various sources. This enhancement supports extending the application's analytical capabilities by integrating external analysis tools, thus offering more flexibility and customization options to meet specific user needs.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: enhance custom analyzer management with removal functionality

Introduced the ability to remove custom analyzers, streamlining the management process and ensuring flexibility in custom analyzer configuration. This enhancement addresses the need for dynamic customization and maintenance of analyzer setups, facilitating easier updates and modifications to the analysis environment.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: add list command to customAnalyzer for displaying configured analyzers

Implemented a new list command within the customAnalyzer module to enable users to view all configured custom analyzers. This enhancement aims to improve usability by providing a straightforward method for users to inspect their custom analyzer configurations directly from the command line.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: add support for listing, adding, and removing custom analyzers

This update introduces commands to manage custom analyzers in the k8sgpt tool, enhancing flexibility and control over analyzer configurations without the need for direct installation or docker dependency.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: support private docker image authentication for custom analyzers

Added authentication support for pulling private Docker images when adding custom analyzers, enhancing security and access control.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: remove Docker custom analyzer installation

Removed the installation and deployment functionality for custom analyzers, streamlining the process of adding analyzers. This change focuses on simplifying the configuration by eliminating the need for specifying installation types, package URLs, and authentication details for Docker images. The goal is to enhance user experience by making the addition of custom analyzers more straightforward and less error-prone.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* fix: remove unused packageUrl

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: update add command description to reflect broader functionality

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: Add name validation for custom analyzer creation

To ensure the integrity and consistency of analyzer names, we introduced a validation step that checks the format of the name against a predefined regex pattern. This change aims to prevent the creation of analyzers with invalid names, enhancing the system's reliability and usability.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

* feat: refactor customAnalyzer package for consistent naming

Refactored the customAnalyzer package and its references to use consistent snake_case naming for improved code readability and alignment with Go naming conventions.

Signed-off-by: Matthis Holleville <matthish29@gmail.com>

---------

Signed-off-by: Matthis Holleville <matthish29@gmail.com>
2024-08-10 22:05:11 +01:00
Bo Wong
b2b86826e5 docs: update "CLI Installation" section in README.md (#1126) (#1127)
Signed-off-by: Bo Wang <wangbob@uniontech.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-08-08 10:34:22 +01:00
R0CKSTAR
8e37369e5c fix: set logger for controller-runtime (#1211)
Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>
2024-08-08 07:10:49 +01:00
renovate[bot]
2a8a9b4867 chore(deps): update actions/upload-artifact digest to 834a144 (#1214)
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-07 09:49:06 +01:00
Kay Yan
b7e5394caa fix: segmentation violation during serve (#1215)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
2024-08-07 09:47:09 +01:00
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
github-actions[bot]
6279f358ca chore(main): release 0.3.30 (#1027)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-26 10:17:15 +01:00
Peter Pan
b2ab94375e fix: invalid ParentObj in output (#1068)
* Fix invalid ParentObj in output

Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>

* fix UT as well for ParentObj changes

Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>

* remove meta.Name in false output

Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>

* fix UT as well

Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>

---------

Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-04-26 07:26:06 +01:00
DragonAlex98
9a73d1923f feat: add keda integration (#1058)
* refactor: move FetchLatestEvent inside util package

Signed-off-by: DragonAlex98 <a.antinori@reply.it>

* feat: add Keda integration and ScaledObject analyzer

Signed-off-by: DragonAlex98 <a.antinori@reply.it>

---------

Signed-off-by: DragonAlex98 <a.antinori@reply.it>
2024-04-25 11:41:01 +01:00
Christoph Enne
85a76a3be0 chore: update license file path to avoid conflicting installations (#878) (#1073)
Signed-off-by: christoph <christoph.enne@glasskube.eu>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-04-20 21:12:49 +01:00
Peter Pan
aa276a5379 feat: add Resource Kind in output (#1069)
Signed-off-by: Peter Pan <Peter.Pan@daocloud.io>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-04-20 21:11:02 +01:00
Miguel Varela Ramos
eb7687a089 chore(deps): update cohere client implementation to v2 (#1062)
* chore(deps): update cohere client implementation to v2 and to use chat endpoint

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>

* chore: remove renovate rule for cohere-go

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>

* style: remove unused attribute

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>

* fix: go mod

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>

---------

Signed-off-by: Miguel Varela Ramos <miguel@cohere.ai>
Signed-off-by: Miguel Varela Ramos <miguelvramos92@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-04-20 21:10:17 +01:00
Guido Muscioni
c162cc22ee fix: set topP from config (#1053)
* fix: set topP from config

Signed-off-by: “Guido <muscionig@gmail.com>

* style: correct format of openai ai provider

Signed-off-by: “Guido <muscionig@gmail.com>

* feat: set topP from the environment

Signed-off-by: “Guido <muscionig@gmail.com>

---------

Signed-off-by: “Guido <muscionig@gmail.com>
2024-04-19 16:38:52 +01:00
izturn
1ae4e75196 refactor: replace util.SliceContainsString with slices.Contains & make fmt (#1041)
* use std package's func instead

Signed-off-by: gang.liu <gang.liu@daocloud.io>

* refactor: replace util.SliceContainsString with slices.Contains  & make fmt

Signed-off-by: gang.liu <gang.liu@daocloud.io>

---------

Signed-off-by: gang.liu <gang.liu@daocloud.io>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-04-19 13:15:50 +01:00
renovate[bot]
693b23f1fc fix(deps): update module golang.org/x/net to v0.23.0 [security] (#1071)
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-19 12:04:55 +01:00
Aris Boutselis
e6085d4191 feat: add minio support (#1048)
* feat: add minio support

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

* feat: add TLS skip for custom https minio endpoint

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

* feat: update cache with the new proto schema

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

---------

Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-04-19 11:58:41 +01:00
renovate[bot]
3eaf776249 chore(deps): update docker/setup-buildx-action digest to d70bba7 (#1066)
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-17 13:55:03 +01:00
renovate[bot]
ccb692c1fd fix(deps): update module github.com/aws/aws-sdk-go to v1.51.21 (#1056)
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-16 07:55:03 +01:00
Kay Yan
9e0263778f fix: remove show password in auth list (#1061)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-04-16 07:20:20 +01:00
Vaibhav Malik
9dfcce842e test: added missing tests for the Pod analyzer (#1021)
- Fixed a small bug where failures were being appended multiple times
  for CrashLoopBackOff and ContainerCreating container status reasons.

- Added missing test cases to ensure proper testing of the Pod analyzer.
  The addition of these missing test cases has increased the code
  coverage of this analyzer to 98%.

- Added checks for init containers in a pod.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-04-13 21:08:33 +01:00
renovate[bot]
6df0169491 fix(deps): update module cloud.google.com/go/storage to v1.40.0 (#1054)
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-05 11:34:51 +01:00
renovate[bot]
007b4bb8ec fix(deps): update module github.com/aws/aws-sdk-go to v1.51.14 (#1051)
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-04 11:23:42 +01:00
renovate[bot]
6b38a56afb fix(deps): update module github.com/google/generative-ai-go to v0.10.0 (#1047)
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-03 14:40:40 +01:00
renovate[bot]
19ae31b5dd fix(deps): update module github.com/aws/aws-sdk-go to v1.51.8 (#1046)
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-03-27 10:01:58 +00:00
renovate[bot]
6a46a26789 fix(deps): update module github.com/sashabaranov/go-openai to v1.20.4 (#1039)
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-03-27 09:48:52 +00:00
renovate[bot]
e05a902d90 chore(deps): update anchore/sbom-action action to v0.15.10 (#1044)
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-03-27 09:34:52 +00:00
renovate[bot]
a3896f4518 fix(deps): update module cloud.google.com/go/storage to v1.39.1 (#1029)
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-03-26 20:26:15 +00:00
Vaibhav Malik
4262c9292c test: removed pkg/kubernetes/testdata (#1018)
The `testdata` was no longer being used. Hence, removed it.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-26 13:48:28 +00:00
renovate[bot]
94cdce44b4 fix(deps): update k8s.io/utils digest to 4693a02 (#1037)
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-03-25 13:16:40 +00:00
renovate[bot]
10c00ba9fe chore(deps): update docker/setup-buildx-action digest to 2b51285 (#1036)
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-03-25 13:09:40 +00:00
renovate[bot]
c872e495ad chore(deps): update docker/login-action digest to e92390c (#1033)
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-03-25 13:04:55 +00:00
Aris Boutselis
bd2e06bae7 chore: update renovate config and bundle deps in groups (#1026)
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-03-24 20:57:43 +00:00
github-actions[bot]
5db4bc28a7 chore(main): release 0.3.29 (#1024)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 10:26:55 +00:00
Alex Jones
8f8f5c6df7 chore: allows an environmental override of the default AWS region and… (#1025)
* chore: allows an environmental override of the default AWS region and using it for bedrock

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

* chore: missing provider region

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-22 10:19:11 +00:00
Vaibhav Malik
3c1c055ac7 test: added missing tests for the CronJob analyzer (#1019)
* test: added missing tests for the CronJob analyzer

- Fixed a small bug where pre-analysis was incorrectly appended to the
  results every time at the end of the for loop. This caused the result
  for a single cronjob failure to be appended multiple times in the
  final results.

- Added missing test cases to ensure proper testing of the CronJob
  analyzer. The addition of these missing test cases has increased the
  code coverage of this analyzer to over 96%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>

* test: removed failure strings matching from tests

It is possible that the error or failure strings might change in the
future, causing the tests to fail. This commit addresses that issue by
removing the matching of failure text from various analyzer tests.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>

---------

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-21 18:13:32 +00:00
Vaibhav Malik
ebfbba98ca test: added missing test case for events.go (#1017)
With the addition of the latest changes, the missing test case when an
event happens after the currently set latest event has been covered.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-21 11:42:12 +00:00
Vaibhav Malik
47463d4412 test: added missing tests for the Ingress analyzer (#1020)
- Added missing test cases to ensure proper testing of the Ingress
  analyzer. The addition of these missing test cases has increased the
  code coverage of this analyzer to over 97%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-21 11:02:19 +00:00
Alex Jones
fe81d16f75 feat: codecov (#1023)
* chore: missing schedule on auto merge

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

* feat: adding codecoverage back in

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-20 11:07:33 +00:00
Vaibhav Malik
a1d0d0a180 test: added tests for the Node analyzer (#1014)
* Added new tests for the `Node` analyzer defined in the `pkg/analyzer`
  package.

* The addition of these new tests has increased the code coverage of the
  node.go file to over 96%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-20 09:32:23 +00:00
Vaibhav Malik
f60467cd4d test: added missing tests for the Netpool analyzer (#1016)
- Added a network policy allowing traffic to all pods. Resulting in
  additional failures in the results.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-03-15 18:45:36 +00:00
Vaibhav Malik
20892b48d0 test: removed useless tests from pkg/kubernetes (#1015)
- This commit removes unnecessary tests defined in the pkg/kubernetes
package.

- The removed tests were found to be flaky and were causing a
  significant increase in CI time without adding much value to
  the codebase.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-14 21:51:15 +00:00
github-actions[bot]
ea7f0a5b4e chore(main): release 0.3.28 (#964)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-14 10:15:49 +00:00
Vaibhav Malik
531f0bc46d test: added tests for the Service analyzer (#1011)
* Added new tests for the `Service` analyzer defined in the
  `pkg/analyzer` package.

* The addition of these new tests has increased the code coverage of the
  service.go file to over 97%.

* Additionally addressed some flaky tests related to the `ReplicaSet`and
  `PersisentVolumeClaim` analyzers.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-03-14 09:42:16 +00:00
Vaibhav Malik
28e19a9d4e test: added tests for the pkg/kubernetes package (#896)
Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-12 21:34:12 +00:00
Vaibhav Malik
3475e2de0c test: fixed various flaky tests (#1009)
- Removed test cases which required access to `/root` from the
  `pkg/util` package.

- Fixed flaky `PodDisruptionBudget` test.

- Fixed a typo in `PersistentVolumeClaim` test.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-12 07:25:03 +00:00
Aris Boutselis
adf4f17085 chore: attempt to group renovate deps (#1007) 2024-03-11 17:48:18 +00:00
Mario
55ac0b2129 feat: add Google Vertex AI as provider to utilize gemini via GCP (#984)
* feat: add Google Vertex AI as provider to utilize gemini via GCP

Signed-off-by: Mario Fahlandt <mfahlandt@pixel-haufen.de>

* fix: adjust providerId description

Signed-off-by: Mario Fahlandt <mfahlandt@pixel-haufen.de>

---------

Signed-off-by: Mario Fahlandt <mfahlandt@pixel-haufen.de>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
2024-03-11 07:33:29 +00:00
Vaibhav Malik
a0225d4f70 test: added tests for the PVC analyzer (#1000)
This commit introduces comprehensive tests for the
`PersistentVolumeClaim` analyzer defined in the `pkg/analyzer` package.

Adding these tests increases the code coverage of the `pvc.go` file to
>95%.

I also made minor modifications to the ReplicaSet test to ensure all
expectations were met.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-08 19:26:19 +00:00
renovate[bot]
b05b6a38ed chore(deps): update anchore/sbom-action action to v0.15.9 (#1004)
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-03-08 11:21:34 +00:00
Vaibhav Malik
1340ead860 test: added tests for the PDB analyzer (#1001)
This commit introduces comprehensive tests for the `PodDisruptionBudget`
analyzer defined in the `pkg/analyzer` package.

Adding these tests increases the code coverage of the `pdb.go` file to
>96%.

Additionally, a potential crash in case of empty or nil PDB status
conditions has been addressed.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-08 11:09:14 +00:00
renovate[bot]
b58b7191af chore(deps): update docker/build-push-action digest to af5a7ed (#1003)
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-03-08 11:08:46 +00:00
renovate[bot]
1491e67567 fix(deps): update module github.com/stretchr/testify to v1.9.0 (#999)
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-03-08 09:37:23 +00:00
renovate[bot]
4ec143ab77 chore(deps): update reviewdog/action-golangci-lint digest to 00311c2 (#1002)
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-03-08 09:36:58 +00:00
Vaibhav Malik
5199dadb2a test: added tests for mutating webhook analyzer (#995)
This commit introduces comprehensive tests for the mutating webhook
analyzer defined in the `pkg/analyzer` package.

Adding these tests increases the code coverage of the
`mutating_webhook.go` file to almost 95%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-08 08:18:20 +00:00
renovate[bot]
425f33bb2d fix(deps): update module github.com/aws/aws-sdk-go to v1.50.34 (#974)
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-03-08 08:12:15 +00:00
Vaibhav Malik
f5c3f18d87 test: added tests for the ReplicaSet analyzer (#997)
This commit introduces comprehensive tests for the ReplicaSet analyzer
defined in the `pkg/analyzer` package.

Adding these tests increases the code coverage of the `rs.go` file to
>95%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-05 19:39:31 +00:00
renovate[bot]
d2754d320f fix(deps): update module github.com/sashabaranov/go-openai to v1.20.2 (#991)
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-03-05 14:04:04 +00:00
renovate[bot]
85f18dde1f fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.1 (#992)
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-03-05 13:57:29 +00:00
Vaibhav Malik
16a4aaab81 test: added tests for validating webhook analyzer (#996)
This commit introduces comprehensive tests for the validating webhook
analyzer defined in the `pkg/analyzer` package.

Adding these tests increases the code coverage of the
`validating_webhook.go` file to almost 95%.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-03-05 13:36:55 +00:00
renovate[bot]
4065faef13 fix(deps): update module github.com/prometheus/client_golang to v1.19.0 (#989)
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-02-28 16:52:50 +00:00
renovate[bot]
f24bcd88b6 chore(deps): update docker/setup-buildx-action digest to 0d103c3 (#988)
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-02-28 16:40:38 +00:00
Tanuj Dwivedi
307710eddc feat: add proxysettings for azureopenai and openai (#987)
Signed-off-by: tanujd11 <dwiveditanuj41@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-28 16:10:42 +00:00
Vaibhav Malik
aab8d77feb fix: analyze command default backend bug (#966)
Now, the default value of the `backend` flag for the analyze command
will be an empty string. And the `NewAnalysis` function has been
modified to use the default backend set by the user if the backend flag
is not provided and the `defaultprovider` is set in the config file.
Otherwise, backend will be set to "openai".

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: JuHyung Son <sonju0427@gmail.com>
2024-02-28 16:09:30 +00:00
renovate[bot]
334a86aaf4 fix(deps): update module gopkg.in/yaml.v2 to v3 (#980)
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-02-27 19:50:30 +00:00
renovate[bot]
88a7907db4 fix(deps): update module github.com/sashabaranov/go-openai to v1.20.1 (#986)
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-02-27 19:39:10 +00:00
renovate[bot]
af3732ad06 fix(deps): update module github.com/schollz/progressbar/v3 to v3.14.2 (#983)
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-02-26 18:47:52 +00:00
Alex Jones
a81377f72d feat: aws integration (#967)
* chore: updated deps

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

* chore: adding aws types

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

* chore: first cut

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

* chore: first pass at aws integration with EKS

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

* chore: fixed linting

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

* chore: updated wording based on PR

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

* chore: improved the kubeconfig

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-26 10:16:32 +00:00
renovate[bot]
6103c96c41 fix(deps): update module google.golang.org/api to v0.167.0 (#973)
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-02-25 17:34:36 +00:00
renovate[bot]
35f5185914 fix(deps): update module gopkg.in/yaml.v2 to v3 (#979)
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-02-23 11:00:30 +00:00
renovate[bot]
97446aae07 fix(deps): update module google.golang.org/grpc to v1.62.0 (#975)
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-02-23 08:28:25 +00:00
renovate[bot]
e07822c10b fix(deps): update module github.com/sashabaranov/go-openai to v1.20.0 (#977)
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-02-23 08:05:22 +00:00
renovate[bot]
f929e7feea fix(deps): update module gopkg.in/yaml.v2 to v3 (#957)
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-02-22 17:48:25 +00:00
Vaibhav Malik
6e640e6921 test: added unit tests for the pkg/util package (#894)
This commit adds new unit tests for the `pkg/util` package bumping the
code coverage to 84%

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-22 16:21:33 +00:00
lili-wan
98286a965e fix: log analyzer failed with multiple containers in the pod (#920)
* Log analyzer failed with multiple containers in the pod #884

Signed-off-by: lwan3 <lili_wan@intuit.com>

* Merge conflicts from main

Signed-off-by: lwan3 <lili_wan@intuit.com>

---------

Signed-off-by: lwan3 <lili_wan@intuit.com>
Co-authored-by: lwan3 <lili_wan@intuit.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-21 12:33:44 +00:00
renovate[bot]
6ac815c10f fix(deps): update module github.com/aws/aws-sdk-go to v1.50.22 (#971)
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-02-21 12:27:49 +00:00
renovate[bot]
8f00218090 fix(deps): update module go.uber.org/zap to v1.27.0 (#972)
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-02-21 08:51:54 +00:00
renovate[bot]
00c91f05a6 fix(deps): update module github.com/aws/aws-sdk-go to v1.50.21 (#970)
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-02-20 20:48:13 +00:00
renovate[bot]
6207c70c51 fix(deps): update module cloud.google.com/go/storage to v1.38.0 (#950)
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-02-19 21:14:38 +00:00
renovate[bot]
8b0b61e596 fix(deps): update module github.com/sashabaranov/go-openai to v1.19.4 (#963)
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-02-19 11:45:37 +00:00
renovate[bot]
248260e081 fix(deps): update module github.com/google/generative-ai-go to v0.8.0 (#965)
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-02-19 08:10:12 +00:00
Vaibhav Malik
f55f8370eb fix: shorthand for the http flag in serve command (#969)
Removed the shorthand for the `http` flag in the serve command because
it was contradicting with the shorthand of the `help` command which is
automatically added on execution if the `help` flag is not already
defined.

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

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
2024-02-19 07:48:16 +00:00
Johannes Kleinlercher
a3cd7e6385 fix: set result name and namespace to trivy vulnreport and configaudi… (#869)
* fix: set result name and namespace to trivy vulnreport and configauditreport

Signed-off-by: Johannes Kleinlercher <johannes.kleinlercher@suxess-it.com>

* fix: increase linter timeout

Signed-off-by: Johannes Kleinlercher <johannes@kleinlercher.at>

---------

Signed-off-by: Johannes Kleinlercher <johannes.kleinlercher@suxess-it.com>
Signed-off-by: Johannes Kleinlercher <johannes@kleinlercher.at>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-18 15:47:19 +00:00
Sahil Badla
f2138c7101 feat: enable Rest api using grpc-gateway (#834)
* grpc-gateway changes

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: grpc-gateway impl

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: enable REST/http api support

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: enable rest/http support

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: enable rest/http support

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: enable rest/http support

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* chore: resolved mod

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

* feat: fix grpc-gateway codegen path

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: merge from master

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

* feat: flag to enable rest api

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>

---------

Signed-off-by: Sahil Badla <sahil_badla@intuit.com>
Signed-off-by: Sahil Badla <146279034+sbadla1@users.noreply.github.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Sahil Badla <sahil_badla@intuit.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-17 15:38:15 +00:00
renovate[bot]
3f0356be66 fix(deps): update module github.com/aws/aws-sdk-go to v1.50.20 (#930)
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-02-17 08:43:26 +00:00
renovate[bot]
cc99bd51f0 fix(deps): update module google.golang.org/api to v0.165.0 (#959)
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-02-16 14:07:23 +00:00
github-actions[bot]
729d14db4d chore(main): release 0.3.27 (#870)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-02-16 12:53:55 +00:00
renovate[bot]
fea2ed1fff fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.0 (#952)
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-02-15 12:48:17 +00:00
Alex Jones
c8c9dbfadc feat: enables remote custom analyzers (#906)
* feat: enables remote custom analyzers

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

* chore: fixed test that was broken

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

* chore: hiding custom analysis behind a flag

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

* chore: resolved govet issue

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

* chore: updated

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

* chore: updated

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

* chore: updated deps

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

* chore: updated deps

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-15 07:28:00 +00:00
renovate[bot]
070aa7fdd0 chore(deps): update actions/upload-artifact digest to 5d5d22a (#925)
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-02-14 19:35:47 +00:00
renovate[bot]
ce7c9551bc fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.5.1 (#939)
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-02-14 12:33:02 +00:00
renovate[bot]
d9fe7446af fix(deps): update module gopkg.in/yaml.v2 to v3 (#956)
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-02-14 11:01:22 +00:00
renovate[bot]
9c1f1b8804 fix(deps): update module google.golang.org/grpc to v1.61.1 (#954)
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-02-14 10:48:40 +00:00
renovate[bot]
37228d88e3 chore(deps): update golang docker tag to v1.22 (#931)
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-02-14 10:22:39 +00:00
renovate[bot]
29b482f597 fix(deps): update module google.golang.org/api to v0.164.0 (#953)
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-02-14 08:26:35 +00:00
Alex Jones
015bccfc2e chore: updated deps (#951)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-13 20:45:33 +00:00
Amit Amrutiya
3f0964ad38 fix: unused variable failure warning in webhooks file (#916)
Signed-off-by: amitamrutiya2210 <amitamrutiya2210@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-13 20:28:11 +00:00
renovate[bot]
3c8d9d42e5 fix(deps): update module github.com/google/generative-ai-go to v0.7.0 (#940)
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-02-13 19:59:37 +00:00
renovate[bot]
bfbb5c7e03 fix(deps): update module github.com/pterm/pterm to v0.12.79 (#943)
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-02-13 15:19:27 +00:00
renovate[bot]
28c4c57e45 fix(deps): update k8s.io/utils digest to e7106e6 (#897)
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-02-13 15:09:48 +00:00
renovate[bot]
4e57088a01 fix(deps): update module golang.org/x/term to v0.17.0 (#941)
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-02-09 22:10:45 +00:00
renovate[bot]
f2eb1ef533 fix(deps): update module github.com/sashabaranov/go-openai to v1.19.3 (#937)
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-02-09 12:41:58 +00:00
Alex Jones
bbf61f53d4 chore: grpc update (#938)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-02-09 09:42:00 +00:00
renovate[bot]
3d2554b9cd fix(deps): update module cloud.google.com/go/storage to v1.37.0 (#934)
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-02-09 09:25:55 +00:00
renovate[bot]
f61c3e228c chore(deps): update anchore/sbom-action action to v0.15.8 (#926)
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-02-08 09:35:32 +01:00
renovate[bot]
c6019728ae fix(deps): update module github.com/sashabaranov/go-openai to v1.19.2 (#886)
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-02-08 08:25:47 +00:00
renovate[bot]
e3eee6d956 fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.3.0-20240128172516-6bf6a55ff115.2 (#899)
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-02-07 18:43:30 +00:00
renovate[bot]
599be33f38 chore(deps): update reviewdog/action-golangci-lint digest to 8e1117c (#915)
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-02-07 15:44:45 +00:00
Amit Amrutiya
3415031006 fix: lint errors (#923)
Signed-off-by: amitamrutiya2210 <amitamrutiya2210@gmail.com>
2024-02-07 11:30:45 +00:00
simone ragonesi
d97dea2896 chore: improve codebase and doc quality (#922)
* chore(prometheus integration): fix mispelling

Signed-off-by: r3drun3 <simone.ragonesi@sighup.io>

* docs(readme): add badges to improve doc quality

Signed-off-by: r3drun3 <simone.ragonesi@sighup.io>

---------

Signed-off-by: r3drun3 <simone.ragonesi@sighup.io>
2024-02-07 09:12:41 +00:00
renovate[bot]
f9c1b90338 fix(deps): update module github.com/pterm/pterm to v0.12.78 (#890)
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-02-05 07:38:34 +00:00
lili-wan
78126b2328 feat: added FailedMount event reason to get the failure (#883)
Signed-off-by: lwan3 <lili_wan@intuit.com>
Co-authored-by: lwan3 <lili_wan@intuit.com>
2024-02-01 18:57:20 +00:00
renovate[bot]
60853fe4eb chore(deps): update anchore/sbom-action action to v0.15.5 (#885)
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-01-29 12:18:39 +00:00
renovate[bot]
a253af23b6 fix(deps): update module github.com/prometheus/prometheus to v2 (#863)
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-01-29 11:21:22 +00:00
JuHyung Son
2fd476e126 feat: add huggingface provider (#893)
* feat: add huggingface ai provider

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

* chore: update readme

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

* fix: set huggingface maxtokens default to 500, use ptr instead of pointer

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

---------

Signed-off-by: JuHyung-Son <sonju0427@gmail.com>
2024-01-28 15:41:49 +00:00
renovate[bot]
483a9dad10 chore(deps): update actions/upload-artifact digest to 26f96df (#888)
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-01-24 14:09:03 +00:00
renovate[bot]
817d9cf754 fix(deps): update module github.com/aws/aws-sdk-go to v1.50.2 (#887)
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-01-24 10:55:01 +00:00
renovate[bot]
72e08efff1 fix(deps): update module google.golang.org/api to v0.157.0 (#860)
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-01-23 13:12:44 +00:00
renovate[bot]
e7d690afd1 fix(deps): update module github.com/pterm/pterm to v0.12.75 (#881)
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-01-23 08:06:44 +00:00
renovate[bot]
3cf18e783e chore(deps): update actions/upload-artifact digest to 694cdab (#880)
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-01-23 08:02:18 +00:00
souleb
cdbeb146a2 fix: typo in httproute files name (#877)
Signed-off-by: Soule BA <bah.soule@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2024-01-23 07:51:57 +00:00
Alex Jones
2effbb345a chore: linting improvements and catching false positives (#882)
* chore: linting improvements and catching false positives

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

* chore: linting improvements and catching false positives

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

* chore: linting improvements and catching false positives

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

* chore: increase linter time out

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-01-23 07:46:01 +00:00
renovate[bot]
335616c20f chore(deps): update reviewdog/action-golangci-lint digest to f016e79 (#714)
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-01-22 07:36:28 +00:00
renovate[bot]
d213399161 chore(deps): update anchore/sbom-action action to v0.15.4 (#879)
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-01-22 07:35:27 +00:00
renovate[bot]
1f371e2807 fix(deps): update module gopkg.in/yaml.v2 to v3 (#875)
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-01-18 16:52:31 +00:00
renovate[bot]
4de1bbd6f7 fix(deps): update module github.com/sashabaranov/go-openai to v1.18.2 (#874)
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-01-16 12:43:49 +00:00
renovate[bot]
81d660447d fix(deps): update module gopkg.in/yaml.v2 to v3 (#866)
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-01-16 09:56:21 +00:00
Philip Miglinci
a34f5dea69 ci: replace deprecated brew config (#873)
tap got replaces by repository and is now deprecated.

This deprecation warning can also be seen in the goreleaser logs:

>     • DEPRECATED: brews.tap should not be used anymore, check https://goreleaser.com/deprecations#brewstap for more info


https://github.com/k8sgpt-ai/k8sgpt/actions/runs/7521548656/job/20472514099

Signed-off-by: Philip Miglinci <pmig@glasskube.eu>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2024-01-16 10:35:36 +01:00
renovate[bot]
6c62c1a0fc fix(deps): update module github.com/sashabaranov/go-openai to v1.18.1 (#871)
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-01-16 09:30:32 +00:00
Philip Miglinci
42be51bc8f chore: set correct license during package build (#872)
Signed-off-by: Philip Miglinci <pmig@glasskube.eu>
2024-01-16 08:23:49 +00:00
renovate[bot]
88002e7e8c fix(deps): update module github.com/aws/aws-sdk-go to v1.49.21 (#868)
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-01-15 19:21:58 +00:00
github-actions[bot]
6d3a3933cd chore(main): release 0.3.26 (#846)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-14 20:28:11 +00:00
Alex Jones
9da75e02bc feat: interactive mode (#854)
* chore: wip interactive mode

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

* chore: tidied up a bit

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

* chore: updated go mod

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

* chore: const prompt

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

* chore: updated based on comments feedback

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

* chore: updated enum

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

* chore: updated enum

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-01-14 20:22:00 +00:00
renovate[bot]
4ce56f38b4 chore(deps): update actions/upload-artifact digest to 1eb3cb2 (#867)
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-01-14 20:08:49 +00:00
renovate[bot]
40b5b7e185 fix(deps): update module github.com/sashabaranov/go-openai to v1.17.11 (#861)
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-01-12 16:41:19 +00:00
renovate[bot]
c55025d04e fix(deps): update module gopkg.in/yaml.v2 to v3 (#865)
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-01-12 14:39:52 +00:00
renovate[bot]
36ba6c5147 fix(deps): update module gopkg.in/yaml.v2 to v3 (#864)
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-01-12 14:27:06 +00:00
renovate[bot]
6a2f315b2f fix(deps): update module github.com/aws/aws-sdk-go to v1.49.19 (#859)
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-01-12 12:56:45 +00:00
Daniel Clark
45fa827c04 feat: initial Prometheus analyzers (#855)
* feat: initial Prometheus analyzers

Added a prometheus integration with two analyzers:
1. PrometheusConfigValidate
2. PrometheusConfigRelabelReport

The integration does not deploy any Prometheus stack in the cluster.
Instead, it searches the provided --namespace for a Prometheus
configuration, stored in a ConfigMap or Secret. If it finds one, it
unmarshals it into memory and runs the analyzers on it.

PrometheusConfigValidate checks if the actual Prometheus configuration is valid or has
any errors.

PrometheusConfigRelabelReport tries to distill the scrape config
relabeling rules to give a concise label set per job that targets need
to have to be scraped. This analyzer is unconventional, in that it does
not necessarily mean there are issues with the config. It merely tries
to give a human-readable explanation of the relabel rules it discovers,
leaning on the LLM and prompt.

Tested on both kube-prometheus and Google Managed Prometheus
stacks.

Signed-off-by: Daniel Clark <danielclark@google.com>

* review: feedback cycle 1

Simplify ConfigValidate prompt and add comments.

Signed-off-by: Daniel Clark <danielclark@google.com>

* review: feedback cycle 2

Add Prometheus configuration discovery to integration activate command.

Also improve logging to make this more clear to users.

Signed-off-by: Daniel Clark <danielclark@google.com>

---------

Signed-off-by: Daniel Clark <danielclark@google.com>
2024-01-12 09:58:09 +00:00
renovate[bot]
4106d39c32 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.18 (#856)
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-01-11 08:44:46 +00:00
renovate[bot]
1979c86d0f fix(deps): update module github.com/sashabaranov/go-openai to v1.17.11 (#853)
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-01-09 21:03:14 +01:00
renovate[bot]
12f764d584 chore(deps): update anchore/sbom-action action to v0.15.3 (#850)
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-01-09 09:21:21 +00:00
renovate[bot]
85ebd12c30 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.17 (#852)
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-01-09 08:44:58 +00:00
Matthis
5c17c24055 feat: unify aiClientName const for all providers (#848) 2024-01-07 13:01:15 +01:00
renovate[bot]
ce4910bc5d fix(deps): update module github.com/aws/aws-sdk-go to v1.49.16 (#847)
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-01-05 22:49:23 +01:00
Anais Urlichs
d8d0beef65 make cli more intuitive when adding openai default backend (#838)
Signed-off-by: AnaisUrlichs <urlichsanais@gmail.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2024-01-05 22:43:08 +01:00
Bartlomiej Plotka
745e960f49 docs: adjusted README information about providers (#844)
Mentioned the basics and referred to website for more details to keep ~one source of truth.

Signed-off-by: bwplotka <bwplotka@gmail.com>
2024-01-05 22:30:34 +01:00
github-actions[bot]
6d29fcf294 chore(main): release 0.3.25 (#812)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-05 07:35:44 +00:00
Bartlomiej Plotka
e7d41496dd feat: added Google GenAI client; simplified IAI/clients API surface. (#829)
* refactor: Simplified IAI; made caching and processing consisent.


Signed-off-by: bwplotka <bwplotka@gmail.com>

* feat: Added Google AI API e.g. for Gemini models.

Signed-off-by: bwplotka <bwplotka@gmail.com>

---------

Signed-off-by: bwplotka <bwplotka@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2024-01-05 06:53:36 +01:00
renovate[bot]
e78ff05419 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.15 (#835)
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-01-05 06:25:05 +01:00
renovate[bot]
105a239d94 fix(deps): update module google.golang.org/api to v0.155.0 (#836)
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-01-05 06:16:07 +01:00
renovate[bot]
4de989c803 fix(deps): update module golang.org/x/term to v0.16.0 (#831)
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-01-04 19:56:11 +01:00
Alex Jones
a7e9b486ba chore: lint fixes (#833)
* chore: added basic server startup test

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

* chore: refactored wg.add move

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-01-04 17:03:32 +00:00
Alex Jones
a77426593d chore: remove code cov (#832)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2024-01-04 16:47:39 +00:00
renovate[bot]
526e22f88b fix(deps): update module github.com/aws/aws-sdk-go to v1.49.14 (#822)
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-01-04 08:48:08 +00:00
renovate[bot]
4314804ca7 fix(deps): update module github.com/sashabaranov/go-openai to v1.17.10 (#824)
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-01-04 06:48:12 +01:00
Bartlomiej Plotka
035348d8a0 fix: no explain case, improved readability. (#825)
Signed-off-by: bwplotka <bwplotka@gmail.com>
2024-01-03 17:59:28 +01:00
renovate[bot]
70c68929d8 chore(deps): update anchore/sbom-action action to v0.15.2 (#823)
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-01-03 13:10:43 +00:00
Debasish Biswas
b17fd7c986 deps: go module bump to fix CVE: GHSA-45x7-px36-x8w8 & GHSA-7ww5-4wqc-m92c (#810)
Signed-off-by: debasishbsws <debasishbsws.dev@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-29 14:36:11 +00:00
renovate[bot]
2f0f2dfa8a chore(deps): pin codecov/codecov-action action to eaaf4be (#820)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-29 14:20:29 +00:00
Alex Jones
3e7cea7bd3 chore: added basic server startup test (#817)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-29 14:15:32 +00:00
Alex Jones
fcd29a547d feat: code_cov badge (#821)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-29 14:08:06 +00:00
Alex Jones
3d0ba3e78c feat: coverage reports (#819)
* Update test.yaml

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

* Update test.yaml

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-29 14:05:27 +00:00
renovate[bot]
91613baa5c fix(deps): update module github.com/aws/aws-sdk-go to v1.49.12 (#813)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-29 08:48:36 +00:00
renovate[bot]
6eb8f6793e fix(deps): update module github.com/prometheus/client_golang to v1.18.0 (#814)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-29 08:24:31 +00:00
renovate[bot]
e5cc4a28cb fix(deps): update module github.com/aws/aws-sdk-go to v1.49.10 (#811)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-27 10:32:16 +01:00
github-actions[bot]
eac9f07abf chore(main): release 0.3.24 (#781)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-24 07:39:44 +00:00
renovate[bot]
130e4c2efd fix(deps): update module github.com/aws/aws-sdk-go to v1.49.9 (#808)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-23 08:15:53 +00:00
renovate[bot]
93b5ca1985 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.8 (#807)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-22 12:57:46 +00:00
renovate[bot]
aa057565b5 fix(deps): update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.2.1 (#801)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-22 07:59:01 +00:00
renovate[bot]
13d64a5875 fix(deps): update module github.com/sashabaranov/go-openai to v1.17.9 (#772)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 17:00:38 +00:00
Akhil Rane
03b63befa2 fix: lowercase logs before running regex matching in LogAnalyzer (#794)
Signed-off-by: Akhil Rane <akhil131192@gmail.com>
2023-12-21 16:59:13 +00:00
renovate[bot]
3c6c7597e0 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.7 (#804)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 16:08:02 +00:00
renovate[bot]
71f36bdb0b fix(deps): update module github.com/aquasecurity/trivy-operator to v0.17.1 (#780)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 16:04:07 +00:00
renovate[bot]
d6fb648e23 chore(deps): update actions/upload-artifact action to v4 (#806)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 12:15:52 +00:00
fossabot
343aec8f04 feat: Add license scan report and status (#796)
Signed off by: fossabot <badges@fossa.com>

Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2023-12-21 13:11:44 +01:00
renovate[bot]
78f7f2ba85 fix(deps): update module google.golang.org/api to v0.154.0 (#779)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 12:06:30 +00:00
renovate[bot]
a8e1932122 fix(deps): update module helm.sh/helm/v3 to v3.13.3 (#803)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 13:04:37 +01:00
renovate[bot]
390f309088 fix(deps): update module cloud.google.com/go/storage to v1.36.0 (#805)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 10:37:14 +00:00
renovate[bot]
5d54c3f840 fix(deps): update module google.golang.org/grpc to v1.60.1 (#790)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 10:12:32 +00:00
renovate[bot]
4a7bad313b fix(deps): update module github.com/mittwald/go-helm-client to v0.12.5 (#802)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 10:00:54 +00:00
renovate[bot]
be4b0bb3c2 chore(deps): update google-github-actions/release-please-action action to v4.0.2 (#800)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 17:14:55 +01:00
renovate[bot]
1b386f64f2 fix(deps): update module github.com/aws/aws-sdk-go to v1.49.6 (#783)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 16:08:33 +00:00
renovate[bot]
8dea6170a2 fix(deps): update module github.com/spf13/viper to v1.18.2 (#787)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 16:04:32 +00:00
Swastik Gour
928b39a728 fix: added the ability to set the trivy variables by the user (#797)
Signed-off-by: swastik959 <Sswastik959@gmail.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-20 15:57:28 +00:00
Alex Jones
c23f24de2e feat: version upgrade to 1.21 (#798)
* feat: version upgrade to 1.21

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

* feat: updated dockerfile

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

* feat: updated dockerfile

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-12-20 15:51:27 +00:00
Akhil Rane
ff4aaf7c32 feat: add last termination state when pod is in CrashloopBackoff (#792)
Signed-off-by: Akhil Rane <akhil131192@gmail.com>
Co-authored-by: Akhil Rane <akhil_rane@intuit.com>
2023-12-20 12:57:17 +00:00
renovate[bot]
2c28c555cf chore(deps): update google-github-actions/release-please-action action to v4 (#782)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-08 08:55:55 +00:00
renovate[bot]
d00ed33678 chore(deps): update actions/setup-go action to v5 (#788)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-07 12:46:57 +00:00
renovate[bot]
6473a2b532 chore(deps): update anchore/sbom-action action to v0.15.1 (#784)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 09:24:38 +00:00
Xiangkun Yin
1d196286b7 refactor: replace rest client with controller-runtime clientset for Trivy analyzers (#776)
* refactor: replace rest client with controller-runtime clientset for Trivy analyzers

Signed-off-by: ptyin <peteryin1604@gmail.com>

* refactor: remove rest client

Signed-off-by: ptyin <peteryin1604@gmail.com>

---------

Signed-off-by: ptyin <peteryin1604@gmail.com>
2023-11-29 15:13:38 +00:00
Matthis
71ae5a7301 doc: use grpcurl instead curl (#773)
Signed-off-by: Matthis Holleville <matthish29@gmail.com>
2023-11-25 16:42:49 +00:00
134 changed files with 10960 additions and 2356 deletions

View File

@@ -13,7 +13,7 @@ on:
- "**.md"
env:
GO_VERSION: "~1.20"
GO_VERSION: "~1.22"
IMAGE_NAME: "k8sgpt"
defaults:
run:
@@ -22,7 +22,7 @@ defaults:
jobs:
prepare_ci_run:
name: Prepare CI Run
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
outputs:
GIT_SHA: ${{ steps.extract_branch.outputs.GIT_SHA }}
BRANCH: ${{ steps.extract_branch.outputs.BRANCH }}
@@ -33,7 +33,7 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Extract branch name
id: extract_branch
@@ -61,7 +61,7 @@ jobs:
build_image:
name: Build Container Image
needs: prepare_ci_run
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
env:
BRANCH: ${{ needs.prepare_ci_run.outputs.BRANCH }}
DATETIME: ${{ needs.prepare_ci_run.outputs.DATETIME }}
@@ -70,14 +70,14 @@ jobs:
RELEASE_REGISTRY: "localhost:5000/k8sgpt"
steps:
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
- name: Build Docker Image
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
with:
name: ${{ env.IMAGE_NAME }}-image.tar
path: /tmp/${{ env.IMAGE_NAME }}-image.tar
@@ -105,7 +105,7 @@ jobs:
name: Upload images to ghcr registry
needs: [ prepare_ci_run, build_image ]
if: github.event_name == 'push' && needs.prepare_ci_run.outputs.NON_FORKED_AND_NON_ROBOT_RUN == 'true' # only run on push to main/maintenance branches
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
env:
DATETIME: ${{ needs.prepare_ci_run.outputs.DATETIME }}
BUILD_TIME: ${{ needs.prepare_ci_run.outputs.BUILD_TIME }}
@@ -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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # 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@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
- name: Build Docker Image
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
with:
context: .
file: ./container/Dockerfile

View File

@@ -2,17 +2,19 @@ name: Run golangci-lint
on:
pull_request:
branches: [ main ]
branches: [main]
jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: golangci-lint
uses: reviewdog/action-golangci-lint@24d4af2fc93f5b2b296229e8b0c0f658d25707af # v2
uses: reviewdog/action-golangci-lint@7708105983c614f7a2725e2172908b7709d1c3e4 # v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-check
golangci_lint_flags: "--timeout=240s"
level: warning

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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: google-github-actions/release-please-action@db8f2c60ee802b3748b512940dde88eabd7b7e01 # v3.7.13
- uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1
id: release
with:
command: manifest
@@ -40,18 +40,32 @@ jobs:
- release-please
runs-on: ubuntu-latest
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
# all of these default to true, but feel free to set to
# "false" if necessary for your workflow
android: false
dotnet: false
haskell: false
large-packages: true
docker-images: true
swap-storage: true
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5
with:
go-version: '1.20'
go-version: '1.22'
- name: Download Syft
uses: anchore/sbom-action/download-syft@fd74a6fb98a204a1ad35bbfae0122c1a302ff88b # v0.15.0
uses: anchore/sbom-action/download-syft@55dc4ee22412511ee8c3142cbea40418e6cec693 # v0.17.8
- 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,12 +73,14 @@ jobs:
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.K8SGPT_BOT_SECRET }}
- name: Update new version in krew-index
uses: rajatjindal/krew-release-bot@3d9faef30a82761d610544f62afddca00993eef9 # v0.0.47
build-container:
if: needs.release-please.outputs.releases_created == 'true'
needs:
- release-please
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
@@ -74,23 +90,23 @@ jobs:
IMAGE_NAME: k8sgpt
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
submodules: recursive
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
- name: Login to GitHub Container Registry
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker Image
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
with:
context: .
file: ./container/Dockerfile
@@ -104,14 +120,14 @@ jobs:
cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }}
- name: Generate SBOM
uses: anchore/sbom-action@fd74a6fb98a204a1ad35bbfae0122c1a302ff88b # v0.15.0
uses: anchore/sbom-action@55dc4ee22412511ee8c3142cbea40418e6cec693 # v0.17.8
with:
image: ${{ env.IMAGE_TAG }}
artifact-name: sbom-${{ env.IMAGE_NAME }}
output-file: ./sbom-${{ env.IMAGE_NAME }}.spdx.json
- name: Attach SBOM to release
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2
with:
tag_name: ${{ needs.release-please.outputs.tag_name }}
files: ./sbom-${{ env.IMAGE_NAME }}.spdx.json

View File

@@ -10,13 +10,13 @@ defaults:
shell: bash
jobs:
validate:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
permissions:
contents: read # Needed for checking out the repository
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,23 +9,22 @@ on:
- main
env:
GO_VERSION: "~1.20"
GO_VERSION: "~1.22"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Unit Test
run: make test
# - name: Fmt Test
# run: fmtFiles=$(make fmt); if [ "$fmtFiles" != "" ];then exit 1; fi
- name: Run test
run: go test ./... -coverprofile=coverage.txt
- name: Upload coverage to Codecov
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5
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,16 +15,18 @@ 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.
license: "MIT"
license: "Apache-2.0"
formats:
- deb
- rpm
@@ -32,7 +35,7 @@ nfpms:
section: utils
contents:
- src: ./LICENSE
dst: /usr/share/doc/nfpm/copyright
dst: /usr/share/doc/k8sgpt/copyright
file_info:
mode: 0644
@@ -51,25 +54,23 @@ archives:
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
- goos: windows
format: zip
brews:
- name: k8sgpt
homepage: https://k8sgpt.ai
tap:
repository:
owner: k8sgpt-ai
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.23"}
{".":"0.3.48"}

View File

@@ -1,5 +1,616 @@
# Changelog
## [0.3.48](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.47...v0.3.48) (2024-12-04)
### Features
* fixed missing cache params ([#1340](https://github.com/k8sgpt-ai/k8sgpt/issues/1340)) ([1363219](https://github.com/k8sgpt-ai/k8sgpt/commit/1363219b1b94e157ef03c53eba8838b7cef559b4))
## [0.3.47](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.46...v0.3.47) (2024-12-02)
### Features
* add new AWS Bedrock model ids ([#1330](https://github.com/k8sgpt-ai/k8sgpt/issues/1330)) ([a12aa07](https://github.com/k8sgpt-ai/k8sgpt/commit/a12aa07b1a2e34c5106b7b930b29b0c97b172dc4))
* adds interplex as a caching provider ([#1328](https://github.com/k8sgpt-ai/k8sgpt/issues/1328)) ([d6d80ee](https://github.com/k8sgpt-ai/k8sgpt/commit/d6d80ee86083643d9b91457791bfc77ef475e82e))
* dump ([#1322](https://github.com/k8sgpt-ai/k8sgpt/issues/1322)) ([da266b3](https://github.com/k8sgpt-ai/k8sgpt/commit/da266b3c82ca8b3e96461be688a9f30e408568fe))
### Bug Fixes
* add maxTokens to serve mode ([#1280](https://github.com/k8sgpt-ai/k8sgpt/issues/1280)) ([a50375c](https://github.com/k8sgpt-ai/k8sgpt/commit/a50375c9605a87546a0fcbcacabe5482fdfa1c2c))
* **deps:** update all non-major dependencies ([#1323](https://github.com/k8sgpt-ai/k8sgpt/issues/1323)) ([b3f60b2](https://github.com/k8sgpt-ai/k8sgpt/commit/b3f60b2d2018d4bede3918adcb3547ef2acf6688))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1303](https://github.com/k8sgpt-ai/k8sgpt/issues/1303)) ([2da0573](https://github.com/k8sgpt-ai/k8sgpt/commit/2da057360b378d34126e1480ade0686f104e3ace))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1321](https://github.com/k8sgpt-ai/k8sgpt/issues/1321)) ([69c67bd](https://github.com/k8sgpt-ai/k8sgpt/commit/69c67bd1d9d4404816a8b7a00c98499729f2185f))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1326](https://github.com/k8sgpt-ai/k8sgpt/issues/1326)) ([5514ebb](https://github.com/k8sgpt-ai/k8sgpt/commit/5514ebb53b79b5bac0fc861ffdebc9399fe87b62))
* update OpenAI API key generation URL to reflect new platform link ([#1331](https://github.com/k8sgpt-ai/k8sgpt/issues/1331)) ([ec5e42b](https://github.com/k8sgpt-ai/k8sgpt/commit/ec5e42b8f43e90632bb62dd89cc6aa3665e0f60d))
### Other
* **deps:** update all non-major dependencies ([#1327](https://github.com/k8sgpt-ai/k8sgpt/issues/1327)) ([a841568](https://github.com/k8sgpt-ai/k8sgpt/commit/a841568a9c4c0012291cf8f4248250192b72a383))
* **deps:** update codecov/codecov-action action to v5 ([#1324](https://github.com/k8sgpt-ai/k8sgpt/issues/1324)) ([cb1e1ff](https://github.com/k8sgpt-ai/k8sgpt/commit/cb1e1ffede1d3086d54157142c6803341e560ca8))
* **deps:** update codecov/codecov-action digest to 015f24e ([#1325](https://github.com/k8sgpt-ai/k8sgpt/issues/1325)) ([4d7eb0f](https://github.com/k8sgpt-ai/k8sgpt/commit/4d7eb0f6226fc50f58b5c2fff7534dd16e2ca378))
* **deps:** update docker/build-push-action action to v6 ([#1294](https://github.com/k8sgpt-ai/k8sgpt/issues/1294)) ([f37d923](https://github.com/k8sgpt-ai/k8sgpt/commit/f37d92391877819c6d26a993ab58bc0c49fb3b66))
* **deps:** update docker/build-push-action digest to 48aba3b ([#1333](https://github.com/k8sgpt-ai/k8sgpt/issues/1333)) ([c21ba86](https://github.com/k8sgpt-ai/k8sgpt/commit/c21ba86237db651086c0a37abc3454db513e505b))
* **deps:** update rajatjindal/krew-release-bot action to v0.0.47 ([#1317](https://github.com/k8sgpt-ai/k8sgpt/issues/1317)) ([896a53b](https://github.com/k8sgpt-ai/k8sgpt/commit/896a53be8394c490e2d34f151de44c3663dddf5b))
## [0.3.46](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.45...v0.3.46) (2024-11-10)
### Features
* reverting the cncf runners ([#1319](https://github.com/k8sgpt-ai/k8sgpt/issues/1319)) ([ad86e7a](https://github.com/k8sgpt-ai/k8sgpt/commit/ad86e7aa39995c492437627dbd9f89f152f11f2c))
* switching to higher spec runners ([#1312](https://github.com/k8sgpt-ai/k8sgpt/issues/1312)) ([5f7d9de](https://github.com/k8sgpt-ai/k8sgpt/commit/5f7d9de46a521463cedc901b729fe27f8d86f381))
* testupdate ([#1315](https://github.com/k8sgpt-ai/k8sgpt/issues/1315)) ([7dcdfc8](https://github.com/k8sgpt-ai/k8sgpt/commit/7dcdfc83d2461e4342ded5fa80493936b70f64a1))
* updated runners to enterprise ([#1318](https://github.com/k8sgpt-ai/k8sgpt/issues/1318)) ([1ae70e8](https://github.com/k8sgpt-ai/k8sgpt/commit/1ae70e806e2609c8fb964f0a577304d07b365cae))
### Other
* **deps:** update actions/setup-go digest to 41dfa10 ([#1284](https://github.com/k8sgpt-ai/k8sgpt/issues/1284)) ([2ce8450](https://github.com/k8sgpt-ai/k8sgpt/commit/2ce8450e03986904a7ffe7afac4b5ba777c67c57))
* **deps:** update softprops/action-gh-release action to v2 ([#1295](https://github.com/k8sgpt-ai/k8sgpt/issues/1295)) ([b6b3d0c](https://github.com/k8sgpt-ai/k8sgpt/commit/b6b3d0c8566b0dbd9cb0e5f59c8493e4343e0106))
## [0.3.45](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.44...v0.3.45) (2024-11-10)
### Features
* free disk ([#1313](https://github.com/k8sgpt-ai/k8sgpt/issues/1313)) ([783cd1c](https://github.com/k8sgpt-ai/k8sgpt/commit/783cd1cfc66f8e4489e5006529745d8caf38cfd4))
## [0.3.44](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.43...v0.3.44) (2024-11-09)
### Features
* test revert runner on release job ([#1310](https://github.com/k8sgpt-ai/k8sgpt/issues/1310)) ([cc9b3ea](https://github.com/k8sgpt-ai/k8sgpt/commit/cc9b3ea6579c6190629e0fac48e37e0eba650158))
## [0.3.43](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.42...v0.3.43) (2024-11-05)
### Bug Fixes
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#1296](https://github.com/k8sgpt-ai/k8sgpt/issues/1296)) ([2f75986](https://github.com/k8sgpt-ai/k8sgpt/commit/2f759865b6fc5ae143c8f5e89a306abc89d4de27))
### Other
* **deps:** update dependency ubuntu to v24 ([#1293](https://github.com/k8sgpt-ai/k8sgpt/issues/1293)) ([c67add3](https://github.com/k8sgpt-ai/k8sgpt/commit/c67add30c64257ac6258dec93193e3201ba8c4ab))
## [0.3.42](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.41...v0.3.42) (2024-11-04)
### Features
* add stats option to analyze command for performance insights ([#1237](https://github.com/k8sgpt-ai/k8sgpt/issues/1237)) ([3eec9bb](https://github.com/k8sgpt-ai/k8sgpt/commit/3eec9bbb05b2f0717437cc4a2ec786594ece1cc3))
* error from events for STS analyzer ([#1256](https://github.com/k8sgpt-ai/k8sgpt/issues/1256)) ([d8fad95](https://github.com/k8sgpt-ai/k8sgpt/commit/d8fad956f45a4dd668647379bb0295e169faeac6))
### Bug Fixes
* [Bug] Make lint command is not working ([#1282](https://github.com/k8sgpt-ai/k8sgpt/issues/1282)) ([87565a0](https://github.com/k8sgpt-ai/k8sgpt/commit/87565a0bcce7087114798c3a32877894c8a9dcee))
* add providerId to serve mode ([#1260](https://github.com/k8sgpt-ai/k8sgpt/issues/1260)) ([da0764d](https://github.com/k8sgpt-ai/k8sgpt/commit/da0764d951ca76cb7007c412f8efa794619c20ba))
* **deps:** update all non-major dependencies ([#1291](https://github.com/k8sgpt-ai/k8sgpt/issues/1291)) ([14e0f19](https://github.com/k8sgpt-ai/k8sgpt/commit/14e0f19b12189052b03d551e409b407fd0b6bd30))
* **deps:** update k8s.io/utils digest to 49e7df5 ([#1259](https://github.com/k8sgpt-ai/k8sgpt/issues/1259)) ([7785dd1](https://github.com/k8sgpt-ai/k8sgpt/commit/7785dd12a0245a33af25dedd2fbb5f4178b5cda9))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go to v1.35.1-20240920204244-7a91c8620515.1 ([#1274](https://github.com/k8sgpt-ai/k8sgpt/issues/1274)) ([9f39abf](https://github.com/k8sgpt-ai/k8sgpt/commit/9f39abf89e4e92009f5e138d9b01d11c60ac135c))
* **deps:** update module cloud.google.com/go/storage to v1.44.0 ([#1265](https://github.com/k8sgpt-ai/k8sgpt/issues/1265)) ([4143e9f](https://github.com/k8sgpt-ai/k8sgpt/commit/4143e9fd524bed3179524d949b7b0f92c02ecd11))
* **deps:** update module github.com/adrg/xdg to v0.5.0 ([#1262](https://github.com/k8sgpt-ai/k8sgpt/issues/1262)) ([98237b6](https://github.com/k8sgpt-ai/k8sgpt/commit/98237b6408521ee7afc05fcaed2f78ba79e77144))
* **deps:** update module github.com/aquasecurity/trivy-operator to v0.22.0 ([#1034](https://github.com/k8sgpt-ai/k8sgpt/issues/1034)) ([037e745](https://github.com/k8sgpt-ai/k8sgpt/commit/037e745c6f667830f0e1d531ce4bbd07083ef972))
* **deps:** update module github.com/aws/aws-sdk-go to v1.55.5 ([#1263](https://github.com/k8sgpt-ai/k8sgpt/issues/1263)) ([0148a5b](https://github.com/k8sgpt-ai/k8sgpt/commit/0148a5b3549cbdb6c6e5832dc01aab044b90ddc9))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.8.0 ([#1264](https://github.com/k8sgpt-ai/k8sgpt/issues/1264)) ([3613585](https://github.com/k8sgpt-ai/k8sgpt/commit/36135857ac55e126b3a6c4533a000cb0b7f32c6b))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.4.1 ([#1275](https://github.com/k8sgpt-ai/k8sgpt/issues/1275)) ([c9b11b6](https://github.com/k8sgpt-ai/k8sgpt/commit/c9b11b6eee00d0269a4d48ad2e4be5458436b51d))
* **deps:** update module github.com/cohere-ai/cohere-go/v2 to v2.12.0 ([#1276](https://github.com/k8sgpt-ai/k8sgpt/issues/1276)) ([7a3fb3c](https://github.com/k8sgpt-ai/k8sgpt/commit/7a3fb3cf6777d5b0babf00455c3833a47bb1bfdb))
* **deps:** update module github.com/google/generative-ai-go to v0.18.0 ([#1278](https://github.com/k8sgpt-ai/k8sgpt/issues/1278)) ([ad349ae](https://github.com/k8sgpt-ai/k8sgpt/commit/ad349ae263f226e300f60dd092729c5a3bf61dbe))
* rename watsonxai to ibmwatsonxai ([#1234](https://github.com/k8sgpt-ai/k8sgpt/issues/1234)) ([5ff6dc9](https://github.com/k8sgpt-ai/k8sgpt/commit/5ff6dc9be5218e47839c4ac5e8f3458b40eb9c88))
### Other
* **deps:** update actions/checkout digest to 11bd719 ([#1283](https://github.com/k8sgpt-ai/k8sgpt/issues/1283)) ([0cfecbd](https://github.com/k8sgpt-ai/k8sgpt/commit/0cfecbdd87586fd138cc63c4e7a26d54e7ed83a8))
* **deps:** update actions/checkout digest to eef6144 ([#1270](https://github.com/k8sgpt-ai/k8sgpt/issues/1270)) ([72eb815](https://github.com/k8sgpt-ai/k8sgpt/commit/72eb8159fb4a2284cf43eb6a5f3de7bed10c6224))
* **deps:** update actions/upload-artifact digest to b4b15b8 ([#1272](https://github.com/k8sgpt-ai/k8sgpt/issues/1272)) ([911d578](https://github.com/k8sgpt-ai/k8sgpt/commit/911d578bf006253d10fe21d96888ddf34a8b4691))
* **deps:** update anchore/sbom-action action to v0.17.2 ([#1248](https://github.com/k8sgpt-ai/k8sgpt/issues/1248)) ([04582d8](https://github.com/k8sgpt-ai/k8sgpt/commit/04582d85160055da30e4e00fd3c6ca69d1decd1a))
* **deps:** update anchore/sbom-action action to v0.17.4 ([#1273](https://github.com/k8sgpt-ai/k8sgpt/issues/1273)) ([c128bf7](https://github.com/k8sgpt-ai/k8sgpt/commit/c128bf7942e380fcab5e9771f405471198e388fe))
* **deps:** update anchore/sbom-action action to v0.17.6 ([#1285](https://github.com/k8sgpt-ai/k8sgpt/issues/1285)) ([173e4dc](https://github.com/k8sgpt-ai/k8sgpt/commit/173e4dc5ac6265af4a3538556220d3a43ab721f7))
* **deps:** update codecov/codecov-action action to v4 ([#1292](https://github.com/k8sgpt-ai/k8sgpt/issues/1292)) ([c1a38c2](https://github.com/k8sgpt-ai/k8sgpt/commit/c1a38c2b35a0bfa772b88f15843c9354b0345284))
* **deps:** update docker/setup-buildx-action digest to c47758b ([#1213](https://github.com/k8sgpt-ai/k8sgpt/issues/1213)) ([161bc11](https://github.com/k8sgpt-ai/k8sgpt/commit/161bc11294d5094533068cf7af9880795a61536e))
* **deps:** update golang docker tag to v1.23 ([#1254](https://github.com/k8sgpt-ai/k8sgpt/issues/1254)) ([b62b7db](https://github.com/k8sgpt-ai/k8sgpt/commit/b62b7dbe3c9cd02b81f6a0111bca939034c5cc9f))
* **deps:** update module github.com/docker/docker to v27.3.1+incompatible ([#1225](https://github.com/k8sgpt-ai/k8sgpt/issues/1225)) ([9c1927b](https://github.com/k8sgpt-ai/k8sgpt/commit/9c1927b4975fa8132fbc24dd96a5737819855544))
* renovate.json ([#1290](https://github.com/k8sgpt-ai/k8sgpt/issues/1290)) ([458fcfe](https://github.com/k8sgpt-ai/k8sgpt/commit/458fcfe8d330523781d32af680febc2a0c0525a2))
## [0.3.41](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.40...v0.3.41) (2024-09-22)
### Features
* add custom-analyzer cmd ([#1207](https://github.com/k8sgpt-ai/k8sgpt/issues/1207)) ([db26d24](https://github.com/k8sgpt-ai/k8sgpt/commit/db26d24ac607534ce78c1c82f3e1d4e5dde17578))
* add event failure handling in service analyzer ([#1132](https://github.com/k8sgpt-ai/k8sgpt/issues/1132)) ([a4e44d5](https://github.com/k8sgpt-ai/k8sgpt/commit/a4e44d59e3ee63714cfd144228299e4f24ac3691))
* added support for A21 and Amazon Titan models via bedrock api ([#1101](https://github.com/k8sgpt-ai/k8sgpt/issues/1101)) ([4f3ecf0](https://github.com/k8sgpt-ai/k8sgpt/commit/4f3ecf008351075068738e930ff3a657f597654a))
* adding a query mode for the schednex scheduler ([#1257](https://github.com/k8sgpt-ai/k8sgpt/issues/1257)) ([53465d5](https://github.com/k8sgpt-ai/k8sgpt/commit/53465d5c832ac490403a2698b80122ca06372df7))
* refactoring to the new schema ([#1219](https://github.com/k8sgpt-ai/k8sgpt/issues/1219)) ([02fa109](https://github.com/k8sgpt-ai/k8sgpt/commit/02fa109429d3c684079f5d488e7f517806fc1a09))
### Bug Fixes
* **deps:** update k8s.io/utils digest to 702e33f ([#1246](https://github.com/k8sgpt-ai/k8sgpt/issues/1246)) ([d30563d](https://github.com/k8sgpt-ai/k8sgpt/commit/d30563d8cdedb5bbf48735e49ebcb44440a5f0f5))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 to v2.22.0-20240807134501-ea98c104104d.1 ([#1186](https://github.com/k8sgpt-ai/k8sgpt/issues/1186)) ([8405778](https://github.com/k8sgpt-ai/k8sgpt/commit/8405778cb25429d2b42d7a3b50ec88b45961a57f))
* **deps:** update module github.com/docker/docker to v27.1.1+incompatible [security] ([#1220](https://github.com/k8sgpt-ai/k8sgpt/issues/1220)) ([3148b5c](https://github.com/k8sgpt-ai/k8sgpt/commit/3148b5c61d2ff57d67d966d6e915994d4aa8a844))
* **deps:** update module github.com/mittwald/go-helm-client to v0.12.12 ([#1226](https://github.com/k8sgpt-ai/k8sgpt/issues/1226)) ([7019d0b](https://github.com/k8sgpt-ai/k8sgpt/commit/7019d0b62f1bebbd4c2a251c98a2beb4975bf2fe))
* **deps:** update module github.com/mittwald/go-helm-client to v0.12.13 ([#1251](https://github.com/k8sgpt-ai/k8sgpt/issues/1251)) ([1dfd139](https://github.com/k8sgpt-ai/k8sgpt/commit/1dfd13973165bd2820aa8ca079e1ec656a5033f0))
* **deps:** update module github.com/schollz/progressbar/v3 to v3.15.0 ([#1227](https://github.com/k8sgpt-ai/k8sgpt/issues/1227)) ([025a069](https://github.com/k8sgpt-ai/k8sgpt/commit/025a069ff1582131cede63420aa535a3b550b7b7))
* disable adding multiple openai provider ([#1191](https://github.com/k8sgpt-ai/k8sgpt/issues/1191)) ([644581f](https://github.com/k8sgpt-ai/k8sgpt/commit/644581f4958f470cfb088a69a478db0ab91c1540))
* enabled auth add support watsonx backend ([#1190](https://github.com/k8sgpt-ai/k8sgpt/issues/1190)) ([d702209](https://github.com/k8sgpt-ai/k8sgpt/commit/d702209941480dce62b9622ea30fdb4a9e5ef083))
* helm chart security context rendering if empty ([#1235](https://github.com/k8sgpt-ai/k8sgpt/issues/1235)) ([be4ca86](https://github.com/k8sgpt-ai/k8sgpt/commit/be4ca86af07e832eb7832f7e5f83df8676bafd29))
* issue-1168, remove duplicate CVE ([#1230](https://github.com/k8sgpt-ai/k8sgpt/issues/1230)) ([8edb053](https://github.com/k8sgpt-ai/k8sgpt/commit/8edb053b3e88027880a75999eab19bed2176747f))
* segmentation violation during serve ([#1215](https://github.com/k8sgpt-ai/k8sgpt/issues/1215)) ([b7e5394](https://github.com/k8sgpt-ai/k8sgpt/commit/b7e5394caaabb43e01161618f7a6e9f4aa8f7408))
* set logger for controller-runtime ([#1211](https://github.com/k8sgpt-ai/k8sgpt/issues/1211)) ([8e37369](https://github.com/k8sgpt-ai/k8sgpt/commit/8e37369e5c6c96096b66179f22a27b2c0018c43a))
* typo ([#1244](https://github.com/k8sgpt-ai/k8sgpt/issues/1244)) ([e02c0dd](https://github.com/k8sgpt-ai/k8sgpt/commit/e02c0ddd2d9f9a6fae8a57514468f26fe72b567a))
### Other
* **deps:** update actions/checkout digest to 692973e ([#1129](https://github.com/k8sgpt-ai/k8sgpt/issues/1129)) ([24ebeaf](https://github.com/k8sgpt-ai/k8sgpt/commit/24ebeaf3a748f2bf40c18ddcecaf8655b457048b))
* **deps:** update actions/upload-artifact digest to 5076954 ([#1239](https://github.com/k8sgpt-ai/k8sgpt/issues/1239)) ([e0e86ea](https://github.com/k8sgpt-ai/k8sgpt/commit/e0e86ea60f3811e8ee22fd9c28e91817c56104a2))
* **deps:** update actions/upload-artifact digest to 834a144 ([#1214](https://github.com/k8sgpt-ai/k8sgpt/issues/1214)) ([2a8a9b4](https://github.com/k8sgpt-ai/k8sgpt/commit/2a8a9b486714d780c0df3ecae8757534249731dc))
* **deps:** update anchore/sbom-action action to v0.17.1 ([#1224](https://github.com/k8sgpt-ai/k8sgpt/issues/1224)) ([f573819](https://github.com/k8sgpt-ai/k8sgpt/commit/f57381961fbc63305d9e9aa63e85a90a100ee553))
* **deps:** update dependency go to v1.23.1 ([#1176](https://github.com/k8sgpt-ai/k8sgpt/issues/1176)) ([453d5c3](https://github.com/k8sgpt-ai/k8sgpt/commit/453d5c37ddafd93c6fa194b5b4fc0794154eb8c1))
* **deps:** update docker/login-action digest to 9780b0c ([#1212](https://github.com/k8sgpt-ai/k8sgpt/issues/1212)) ([477ef15](https://github.com/k8sgpt-ai/k8sgpt/commit/477ef155d32f4d81ca3bee612644f51fc1098cdc))
### Docs
* update "CLI Installation" section in README.md ([#1126](https://github.com/k8sgpt-ai/k8sgpt/issues/1126)) ([#1127](https://github.com/k8sgpt-ai/k8sgpt/issues/1127)) ([b2b8682](https://github.com/k8sgpt-ai/k8sgpt/commit/b2b86826e55984c2b6aed6554869d7ce66a5f854))
## [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)
### Features
* add keda integration ([#1058](https://github.com/k8sgpt-ai/k8sgpt/issues/1058)) ([9a73d19](https://github.com/k8sgpt-ai/k8sgpt/commit/9a73d1923f146aa1343465d89225e64bcb8e0112))
* add minio support ([#1048](https://github.com/k8sgpt-ai/k8sgpt/issues/1048)) ([e6085d4](https://github.com/k8sgpt-ai/k8sgpt/commit/e6085d4191a1695e295f4f6a2ac7219b67a37225))
* add Resource Kind in output ([#1069](https://github.com/k8sgpt-ai/k8sgpt/issues/1069)) ([aa276a5](https://github.com/k8sgpt-ai/k8sgpt/commit/aa276a5379b3d24a8e7a1f8b1193832df5a46220))
### Bug Fixes
* **deps:** update k8s.io/utils digest to 4693a02 ([#1037](https://github.com/k8sgpt-ai/k8sgpt/issues/1037)) ([94cdce4](https://github.com/k8sgpt-ai/k8sgpt/commit/94cdce44b49e0bb85e8b541688b2206e7c1dc33d))
* **deps:** update module cloud.google.com/go/storage to v1.39.1 ([#1029](https://github.com/k8sgpt-ai/k8sgpt/issues/1029)) ([a3896f4](https://github.com/k8sgpt-ai/k8sgpt/commit/a3896f4518ec6666a43de22a24a18f2b93c58073))
* **deps:** update module cloud.google.com/go/storage to v1.40.0 ([#1054](https://github.com/k8sgpt-ai/k8sgpt/issues/1054)) ([6df0169](https://github.com/k8sgpt-ai/k8sgpt/commit/6df01694916504cc4af3795361a4285098e2de85))
* **deps:** update module github.com/aws/aws-sdk-go to v1.51.14 ([#1051](https://github.com/k8sgpt-ai/k8sgpt/issues/1051)) ([007b4bb](https://github.com/k8sgpt-ai/k8sgpt/commit/007b4bb8ec4b36705f76fd2f5d96464c75915573))
* **deps:** update module github.com/aws/aws-sdk-go to v1.51.21 ([#1056](https://github.com/k8sgpt-ai/k8sgpt/issues/1056)) ([ccb692c](https://github.com/k8sgpt-ai/k8sgpt/commit/ccb692c1fdc5496d9d5810dfe41dbf1bdeb68d00))
* **deps:** update module github.com/aws/aws-sdk-go to v1.51.8 ([#1046](https://github.com/k8sgpt-ai/k8sgpt/issues/1046)) ([19ae31b](https://github.com/k8sgpt-ai/k8sgpt/commit/19ae31b5dd5c54413025cee8081d112223e38400))
* **deps:** update module github.com/google/generative-ai-go to v0.10.0 ([#1047](https://github.com/k8sgpt-ai/k8sgpt/issues/1047)) ([6b38a56](https://github.com/k8sgpt-ai/k8sgpt/commit/6b38a56afbdaa8e0d8f025088a52d3022673ef9d))
* **deps:** update module github.com/sashabaranov/go-openai to v1.20.4 ([#1039](https://github.com/k8sgpt-ai/k8sgpt/issues/1039)) ([6a46a26](https://github.com/k8sgpt-ai/k8sgpt/commit/6a46a26789f730d298cf49a706421f36bc8523b1))
* **deps:** update module golang.org/x/net to v0.23.0 [security] ([#1071](https://github.com/k8sgpt-ai/k8sgpt/issues/1071)) ([693b23f](https://github.com/k8sgpt-ai/k8sgpt/commit/693b23f1fc33659a3c4f52fc4d9c23348b22bfb1))
* invalid ParentObj in output ([#1068](https://github.com/k8sgpt-ai/k8sgpt/issues/1068)) ([b2ab943](https://github.com/k8sgpt-ai/k8sgpt/commit/b2ab94375e4233cdfa9762877995445c313bb962))
* remove show password in auth list ([#1061](https://github.com/k8sgpt-ai/k8sgpt/issues/1061)) ([9e02637](https://github.com/k8sgpt-ai/k8sgpt/commit/9e0263778f6dbc179184fa9d86f07d808283d63e))
* set topP from config ([#1053](https://github.com/k8sgpt-ai/k8sgpt/issues/1053)) ([c162cc2](https://github.com/k8sgpt-ai/k8sgpt/commit/c162cc22ee468070e0602d3fd684b022fa585c4f))
### Other
* **deps:** update anchore/sbom-action action to v0.15.10 ([#1044](https://github.com/k8sgpt-ai/k8sgpt/issues/1044)) ([e05a902](https://github.com/k8sgpt-ai/k8sgpt/commit/e05a902d904fc0b63998ae290f15e79d330317fb))
* **deps:** update cohere client implementation to v2 ([#1062](https://github.com/k8sgpt-ai/k8sgpt/issues/1062)) ([eb7687a](https://github.com/k8sgpt-ai/k8sgpt/commit/eb7687a08917ad4048c6f00c17bb45591a935a3a))
* **deps:** update docker/login-action digest to e92390c ([#1033](https://github.com/k8sgpt-ai/k8sgpt/issues/1033)) ([c872e49](https://github.com/k8sgpt-ai/k8sgpt/commit/c872e495ad6f787cf566a5b2f295deb3f08aba15))
* **deps:** update docker/setup-buildx-action digest to 2b51285 ([#1036](https://github.com/k8sgpt-ai/k8sgpt/issues/1036)) ([10c00ba](https://github.com/k8sgpt-ai/k8sgpt/commit/10c00ba9fe61a3ee1dc90d87dd7997da276905b4))
* **deps:** update docker/setup-buildx-action digest to d70bba7 ([#1066](https://github.com/k8sgpt-ai/k8sgpt/issues/1066)) ([3eaf776](https://github.com/k8sgpt-ai/k8sgpt/commit/3eaf776249719a0a13909d24e6b48deb6bf818b6))
* update license file path to avoid conflicting installations ([#878](https://github.com/k8sgpt-ai/k8sgpt/issues/878)) ([#1073](https://github.com/k8sgpt-ai/k8sgpt/issues/1073)) ([85a76a3](https://github.com/k8sgpt-ai/k8sgpt/commit/85a76a3be06df0ff713192d1f08fd01d1e8f219b))
* update renovate config and bundle deps in groups ([#1026](https://github.com/k8sgpt-ai/k8sgpt/issues/1026)) ([bd2e06b](https://github.com/k8sgpt-ai/k8sgpt/commit/bd2e06bae72528c5af1b4f44674d624d474d40dc))
### Refactoring
* replace util.SliceContainsString with slices.Contains & make fmt ([#1041](https://github.com/k8sgpt-ai/k8sgpt/issues/1041)) ([1ae4e75](https://github.com/k8sgpt-ai/k8sgpt/commit/1ae4e751967850e8146f8f3fa04c0dd302ef15bf))
## [0.3.29](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.28...v0.3.29) (2024-03-22)
### Features
* codecov ([#1023](https://github.com/k8sgpt-ai/k8sgpt/issues/1023)) ([fe81d16](https://github.com/k8sgpt-ai/k8sgpt/commit/fe81d16f756e5ea9db909e42e6caf1e17e040f86))
### Other
* allows an environmental override of the default AWS region and… ([#1025](https://github.com/k8sgpt-ai/k8sgpt/issues/1025)) ([8f8f5c6](https://github.com/k8sgpt-ai/k8sgpt/commit/8f8f5c6df7fbcd08ee48d91a4f2e011a3e69e4ac))
## [0.3.28](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.27...v0.3.28) (2024-03-14)
### Features
* add Google Vertex AI as provider to utilize gemini via GCP ([#984](https://github.com/k8sgpt-ai/k8sgpt/issues/984)) ([55ac0b2](https://github.com/k8sgpt-ai/k8sgpt/commit/55ac0b2129a438661a0253251f546db6b59f2b92))
* add proxysettings for azureopenai and openai ([#987](https://github.com/k8sgpt-ai/k8sgpt/issues/987)) ([307710e](https://github.com/k8sgpt-ai/k8sgpt/commit/307710eddc1c3f96f40a674f7dda786510e9c4cc))
* aws integration ([#967](https://github.com/k8sgpt-ai/k8sgpt/issues/967)) ([a81377f](https://github.com/k8sgpt-ai/k8sgpt/commit/a81377f72db7f322e0afbb6d613c2bfffecf8080))
* enable Rest api using grpc-gateway ([#834](https://github.com/k8sgpt-ai/k8sgpt/issues/834)) ([f2138c7](https://github.com/k8sgpt-ai/k8sgpt/commit/f2138c71017b391625eebdfb4c5708c824824f69))
### Bug Fixes
* analyze command default backend bug ([#966](https://github.com/k8sgpt-ai/k8sgpt/issues/966)) ([aab8d77](https://github.com/k8sgpt-ai/k8sgpt/commit/aab8d77febdd4b42ff74aafbb2ada27745c04ae1))
* **deps:** update module cloud.google.com/go/storage to v1.38.0 ([#950](https://github.com/k8sgpt-ai/k8sgpt/issues/950)) ([6207c70](https://github.com/k8sgpt-ai/k8sgpt/commit/6207c70c51d2885c4590c255c8f78e7ee2009034))
* **deps:** update module github.com/aws/aws-sdk-go to v1.50.20 ([#930](https://github.com/k8sgpt-ai/k8sgpt/issues/930)) ([3f0356b](https://github.com/k8sgpt-ai/k8sgpt/commit/3f0356be662c32d82ce4f3db05f859477823717d))
* **deps:** update module github.com/aws/aws-sdk-go to v1.50.21 ([#970](https://github.com/k8sgpt-ai/k8sgpt/issues/970)) ([00c91f0](https://github.com/k8sgpt-ai/k8sgpt/commit/00c91f05a62b2c8b2d756b58b95279195ff38d3d))
* **deps:** update module github.com/aws/aws-sdk-go to v1.50.22 ([#971](https://github.com/k8sgpt-ai/k8sgpt/issues/971)) ([6ac815c](https://github.com/k8sgpt-ai/k8sgpt/commit/6ac815c10fb073f4251e338ab22e247625f21406))
* **deps:** update module github.com/aws/aws-sdk-go to v1.50.34 ([#974](https://github.com/k8sgpt-ai/k8sgpt/issues/974)) ([425f33b](https://github.com/k8sgpt-ai/k8sgpt/commit/425f33bb2ddf8cdaff079b097d6956f675c89b0e))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.1 ([#992](https://github.com/k8sgpt-ai/k8sgpt/issues/992)) ([85f18dd](https://github.com/k8sgpt-ai/k8sgpt/commit/85f18dde1f820fe2413cc6b3109e67b7a010142c))
* **deps:** update module github.com/google/generative-ai-go to v0.8.0 ([#965](https://github.com/k8sgpt-ai/k8sgpt/issues/965)) ([248260e](https://github.com/k8sgpt-ai/k8sgpt/commit/248260e081327de9f9d1d2c851efab2b4a3e7ede))
* **deps:** update module github.com/prometheus/client_golang to v1.19.0 ([#989](https://github.com/k8sgpt-ai/k8sgpt/issues/989)) ([4065fae](https://github.com/k8sgpt-ai/k8sgpt/commit/4065faef13691f9cf1f50696c62d3b30b0933b4b))
* **deps:** update module github.com/sashabaranov/go-openai to v1.19.4 ([#963](https://github.com/k8sgpt-ai/k8sgpt/issues/963)) ([8b0b61e](https://github.com/k8sgpt-ai/k8sgpt/commit/8b0b61e596f790b9558a5e3d1f634a5ee1c6cb0c))
* **deps:** update module github.com/sashabaranov/go-openai to v1.20.0 ([#977](https://github.com/k8sgpt-ai/k8sgpt/issues/977)) ([e07822c](https://github.com/k8sgpt-ai/k8sgpt/commit/e07822c10bff5dbd91f4da592914c25538353d6b))
* **deps:** update module github.com/sashabaranov/go-openai to v1.20.1 ([#986](https://github.com/k8sgpt-ai/k8sgpt/issues/986)) ([88a7907](https://github.com/k8sgpt-ai/k8sgpt/commit/88a7907db4700c241e9aa109bc3d8604a8186f87))
* **deps:** update module github.com/sashabaranov/go-openai to v1.20.2 ([#991](https://github.com/k8sgpt-ai/k8sgpt/issues/991)) ([d2754d3](https://github.com/k8sgpt-ai/k8sgpt/commit/d2754d320fb1f285f93fdced2b8469280bd47fd2))
* **deps:** update module github.com/schollz/progressbar/v3 to v3.14.2 ([#983](https://github.com/k8sgpt-ai/k8sgpt/issues/983)) ([af3732a](https://github.com/k8sgpt-ai/k8sgpt/commit/af3732ad067b809c54c5f08f6cf5a7a519b452d7))
* **deps:** update module github.com/stretchr/testify to v1.9.0 ([#999](https://github.com/k8sgpt-ai/k8sgpt/issues/999)) ([1491e67](https://github.com/k8sgpt-ai/k8sgpt/commit/1491e675673dcc13ccf6ac1778113762542e8cbc))
* **deps:** update module go.uber.org/zap to v1.27.0 ([#972](https://github.com/k8sgpt-ai/k8sgpt/issues/972)) ([8f00218](https://github.com/k8sgpt-ai/k8sgpt/commit/8f002180901c8bf7e6b1a5451dd97ef566260b0f))
* **deps:** update module google.golang.org/api to v0.165.0 ([#959](https://github.com/k8sgpt-ai/k8sgpt/issues/959)) ([cc99bd5](https://github.com/k8sgpt-ai/k8sgpt/commit/cc99bd51f05db4e87f806ac58ee1cb7a83b25e4d))
* **deps:** update module google.golang.org/api to v0.167.0 ([#973](https://github.com/k8sgpt-ai/k8sgpt/issues/973)) ([6103c96](https://github.com/k8sgpt-ai/k8sgpt/commit/6103c96c41e10e2fe13d285ff15a36bf2fbeb5c2))
* **deps:** update module google.golang.org/grpc to v1.62.0 ([#975](https://github.com/k8sgpt-ai/k8sgpt/issues/975)) ([97446aa](https://github.com/k8sgpt-ai/k8sgpt/commit/97446aae079824d6556416314c0a27514088a667))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#957](https://github.com/k8sgpt-ai/k8sgpt/issues/957)) ([f929e7f](https://github.com/k8sgpt-ai/k8sgpt/commit/f929e7feea5931ddec77af49dd08937aca85fd49))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#979](https://github.com/k8sgpt-ai/k8sgpt/issues/979)) ([35f5185](https://github.com/k8sgpt-ai/k8sgpt/commit/35f51859140c78ce953443afcc27f77230287809))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#980](https://github.com/k8sgpt-ai/k8sgpt/issues/980)) ([334a86a](https://github.com/k8sgpt-ai/k8sgpt/commit/334a86aaf40e5421929cf380191841db064d9bf7))
* log analyzer failed with multiple containers in the pod ([#920](https://github.com/k8sgpt-ai/k8sgpt/issues/920)) ([98286a9](https://github.com/k8sgpt-ai/k8sgpt/commit/98286a965e4c4c680deeb43d3397b51089968366))
* set result name and namespace to trivy vulnreport and configaudi… ([#869](https://github.com/k8sgpt-ai/k8sgpt/issues/869)) ([a3cd7e6](https://github.com/k8sgpt-ai/k8sgpt/commit/a3cd7e6385365a1d190a9e8439311cb9d5eeda56))
* shorthand for the http flag in serve command ([#969](https://github.com/k8sgpt-ai/k8sgpt/issues/969)) ([f55f837](https://github.com/k8sgpt-ai/k8sgpt/commit/f55f8370ebf0db6db629641337cd78ad7f120865))
### Other
* attempt to group renovate deps ([#1007](https://github.com/k8sgpt-ai/k8sgpt/issues/1007)) ([adf4f17](https://github.com/k8sgpt-ai/k8sgpt/commit/adf4f17085672fd5ae78dad4f8ac1d887029836d))
* **deps:** update anchore/sbom-action action to v0.15.9 ([#1004](https://github.com/k8sgpt-ai/k8sgpt/issues/1004)) ([b05b6a3](https://github.com/k8sgpt-ai/k8sgpt/commit/b05b6a38ed4a9fc017f9dcb52cff8a332c11056d))
* **deps:** update docker/build-push-action digest to af5a7ed ([#1003](https://github.com/k8sgpt-ai/k8sgpt/issues/1003)) ([b58b719](https://github.com/k8sgpt-ai/k8sgpt/commit/b58b7191af2fe082d94d46ef6a2784c1ea322340))
* **deps:** update docker/setup-buildx-action digest to 0d103c3 ([#988](https://github.com/k8sgpt-ai/k8sgpt/issues/988)) ([f24bcd8](https://github.com/k8sgpt-ai/k8sgpt/commit/f24bcd88b6a915798897b49a562b86265a9b524c))
* **deps:** update reviewdog/action-golangci-lint digest to 00311c2 ([#1002](https://github.com/k8sgpt-ai/k8sgpt/issues/1002)) ([4ec143a](https://github.com/k8sgpt-ai/k8sgpt/commit/4ec143ab772ca4dc3072c248e95da8f7c0a2974b))
## [0.3.27](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.26...v0.3.27) (2024-02-15)
### Features
* add huggingface provider ([#893](https://github.com/k8sgpt-ai/k8sgpt/issues/893)) ([2fd476e](https://github.com/k8sgpt-ai/k8sgpt/commit/2fd476e12624e30570c0819594f2668f720381d6))
* added FailedMount event reason to get the failure ([#883](https://github.com/k8sgpt-ai/k8sgpt/issues/883)) ([78126b2](https://github.com/k8sgpt-ai/k8sgpt/commit/78126b2328c1b3f81a269d203e86128104050010))
* enables remote custom analyzers ([#906](https://github.com/k8sgpt-ai/k8sgpt/issues/906)) ([c8c9dbf](https://github.com/k8sgpt-ai/k8sgpt/commit/c8c9dbfadc72a193ab9f3431d02d50ac5ab5d071))
### Bug Fixes
* **deps:** update k8s.io/utils digest to e7106e6 ([#897](https://github.com/k8sgpt-ai/k8sgpt/issues/897)) ([28c4c57](https://github.com/k8sgpt-ai/k8sgpt/commit/28c4c57e4566b9b888a5633090ccb70875d30106))
* **deps:** update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.3.0-20240128172516-6bf6a55ff115.2 ([#899](https://github.com/k8sgpt-ai/k8sgpt/issues/899)) ([e3eee6d](https://github.com/k8sgpt-ai/k8sgpt/commit/e3eee6d9566a59fd62e6bb804257b1383f75e3ef))
* **deps:** update module cloud.google.com/go/storage to v1.37.0 ([#934](https://github.com/k8sgpt-ai/k8sgpt/issues/934)) ([3d2554b](https://github.com/k8sgpt-ai/k8sgpt/commit/3d2554b9cd8817b24cf8858a107420d6d8424aa4))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.21 ([#868](https://github.com/k8sgpt-ai/k8sgpt/issues/868)) ([88002e7](https://github.com/k8sgpt-ai/k8sgpt/commit/88002e7e8c3e9c71365c44e136a6f1a8d35e1744))
* **deps:** update module github.com/aws/aws-sdk-go to v1.50.2 ([#887](https://github.com/k8sgpt-ai/k8sgpt/issues/887)) ([817d9cf](https://github.com/k8sgpt-ai/k8sgpt/commit/817d9cf754d307d374befc0d57919eb7a0183aaf))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/azidentity to v1.5.1 ([#939](https://github.com/k8sgpt-ai/k8sgpt/issues/939)) ([ce7c955](https://github.com/k8sgpt-ai/k8sgpt/commit/ce7c9551bcb1a8b24922a1eb062605bbfeec7929))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.3.0 ([#952](https://github.com/k8sgpt-ai/k8sgpt/issues/952)) ([fea2ed1](https://github.com/k8sgpt-ai/k8sgpt/commit/fea2ed1fff5fb5a46d6abc2feb72e1e1adf3b69b))
* **deps:** update module github.com/google/generative-ai-go to v0.7.0 ([#940](https://github.com/k8sgpt-ai/k8sgpt/issues/940)) ([3c8d9d4](https://github.com/k8sgpt-ai/k8sgpt/commit/3c8d9d42e573f27185a1572d1bc06f8af87f3a0b))
* **deps:** update module github.com/prometheus/prometheus to v2 ([#863](https://github.com/k8sgpt-ai/k8sgpt/issues/863)) ([a253af2](https://github.com/k8sgpt-ai/k8sgpt/commit/a253af23b601b23179be5019fbb832a41423cdae))
* **deps:** update module github.com/pterm/pterm to v0.12.75 ([#881](https://github.com/k8sgpt-ai/k8sgpt/issues/881)) ([e7d690a](https://github.com/k8sgpt-ai/k8sgpt/commit/e7d690afd12cb71d7b344ba92bf059ae18a993c8))
* **deps:** update module github.com/pterm/pterm to v0.12.78 ([#890](https://github.com/k8sgpt-ai/k8sgpt/issues/890)) ([f9c1b90](https://github.com/k8sgpt-ai/k8sgpt/commit/f9c1b903385978be56f9c4bc87089bd1c761bbea))
* **deps:** update module github.com/pterm/pterm to v0.12.79 ([#943](https://github.com/k8sgpt-ai/k8sgpt/issues/943)) ([bfbb5c7](https://github.com/k8sgpt-ai/k8sgpt/commit/bfbb5c7e03cad144f6037c7233ffc0817fd403e4))
* **deps:** update module github.com/sashabaranov/go-openai to v1.18.1 ([#871](https://github.com/k8sgpt-ai/k8sgpt/issues/871)) ([6c62c1a](https://github.com/k8sgpt-ai/k8sgpt/commit/6c62c1a0fcd38cf9de8a99cda6f37b221740b9c8))
* **deps:** update module github.com/sashabaranov/go-openai to v1.18.2 ([#874](https://github.com/k8sgpt-ai/k8sgpt/issues/874)) ([4de1bbd](https://github.com/k8sgpt-ai/k8sgpt/commit/4de1bbd6f72ca83d46ce5955bac50dffc99af03d))
* **deps:** update module github.com/sashabaranov/go-openai to v1.19.2 ([#886](https://github.com/k8sgpt-ai/k8sgpt/issues/886)) ([c601972](https://github.com/k8sgpt-ai/k8sgpt/commit/c6019728aea837884620e0b4894568802a948a6e))
* **deps:** update module github.com/sashabaranov/go-openai to v1.19.3 ([#937](https://github.com/k8sgpt-ai/k8sgpt/issues/937)) ([f2eb1ef](https://github.com/k8sgpt-ai/k8sgpt/commit/f2eb1ef5334877fd3a26dda8c92023f831ea857e))
* **deps:** update module golang.org/x/term to v0.17.0 ([#941](https://github.com/k8sgpt-ai/k8sgpt/issues/941)) ([4e57088](https://github.com/k8sgpt-ai/k8sgpt/commit/4e57088a0137767a42c778a59ff07fff04c04289))
* **deps:** update module google.golang.org/api to v0.157.0 ([#860](https://github.com/k8sgpt-ai/k8sgpt/issues/860)) ([72e08ef](https://github.com/k8sgpt-ai/k8sgpt/commit/72e08efff1fc501dfcba791c9d940e575f3e2395))
* **deps:** update module google.golang.org/api to v0.164.0 ([#953](https://github.com/k8sgpt-ai/k8sgpt/issues/953)) ([29b482f](https://github.com/k8sgpt-ai/k8sgpt/commit/29b482f5978795fa8db729030bd75803e2e61f95))
* **deps:** update module google.golang.org/grpc to v1.61.1 ([#954](https://github.com/k8sgpt-ai/k8sgpt/issues/954)) ([9c1f1b8](https://github.com/k8sgpt-ai/k8sgpt/commit/9c1f1b8804a26f549379efe637d0bedb8e2cb890))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#866](https://github.com/k8sgpt-ai/k8sgpt/issues/866)) ([81d6604](https://github.com/k8sgpt-ai/k8sgpt/commit/81d660447d236cd03b75866871bb69f2c77c5c66))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#875](https://github.com/k8sgpt-ai/k8sgpt/issues/875)) ([1f371e2](https://github.com/k8sgpt-ai/k8sgpt/commit/1f371e2807c47dbb4613bf873ec67a77e8e6c80c))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#956](https://github.com/k8sgpt-ai/k8sgpt/issues/956)) ([d9fe744](https://github.com/k8sgpt-ai/k8sgpt/commit/d9fe7446af428209610adc83ec17cf50491a5a47))
* lint errors ([#923](https://github.com/k8sgpt-ai/k8sgpt/issues/923)) ([3415031](https://github.com/k8sgpt-ai/k8sgpt/commit/3415031006bb5899019e68d33ac6083d03ef864b))
* typo in httproute files name ([#877](https://github.com/k8sgpt-ai/k8sgpt/issues/877)) ([cdbeb14](https://github.com/k8sgpt-ai/k8sgpt/commit/cdbeb146a28ebc21ac2c4d27e977b1771f9290b4))
* unused variable failure warning in webhooks file ([#916](https://github.com/k8sgpt-ai/k8sgpt/issues/916)) ([3f0964a](https://github.com/k8sgpt-ai/k8sgpt/commit/3f0964ad385390f53516904219fbfc47b989d31f))
### Other
* **deps:** update actions/upload-artifact digest to 26f96df ([#888](https://github.com/k8sgpt-ai/k8sgpt/issues/888)) ([483a9da](https://github.com/k8sgpt-ai/k8sgpt/commit/483a9dad103ad1af82491dc1d5e0a39bb4865a1b))
* **deps:** update actions/upload-artifact digest to 5d5d22a ([#925](https://github.com/k8sgpt-ai/k8sgpt/issues/925)) ([070aa7f](https://github.com/k8sgpt-ai/k8sgpt/commit/070aa7fdd0982c0c7f02a1da9e6797d5efaa5586))
* **deps:** update actions/upload-artifact digest to 694cdab ([#880](https://github.com/k8sgpt-ai/k8sgpt/issues/880)) ([3cf18e7](https://github.com/k8sgpt-ai/k8sgpt/commit/3cf18e783edb341b7bdd6aa20dbcce11971fa241))
* **deps:** update anchore/sbom-action action to v0.15.4 ([#879](https://github.com/k8sgpt-ai/k8sgpt/issues/879)) ([d213399](https://github.com/k8sgpt-ai/k8sgpt/commit/d2133991617697b13b8846f2acb3a3bb6cebb160))
* **deps:** update anchore/sbom-action action to v0.15.5 ([#885](https://github.com/k8sgpt-ai/k8sgpt/issues/885)) ([60853fe](https://github.com/k8sgpt-ai/k8sgpt/commit/60853fe4eb8de7a1fdbaea388c3d2d6205e273a6))
* **deps:** update anchore/sbom-action action to v0.15.8 ([#926](https://github.com/k8sgpt-ai/k8sgpt/issues/926)) ([f61c3e2](https://github.com/k8sgpt-ai/k8sgpt/commit/f61c3e228c69fa160735ddb2c1347720112b738f))
* **deps:** update golang docker tag to v1.22 ([#931](https://github.com/k8sgpt-ai/k8sgpt/issues/931)) ([37228d8](https://github.com/k8sgpt-ai/k8sgpt/commit/37228d88e357c66c5574559ae27a52fdf28418b8))
* **deps:** update reviewdog/action-golangci-lint digest to 8e1117c ([#915](https://github.com/k8sgpt-ai/k8sgpt/issues/915)) ([599be33](https://github.com/k8sgpt-ai/k8sgpt/commit/599be33f38ad1fd688b8e7824102a7944d516435))
* **deps:** update reviewdog/action-golangci-lint digest to f016e79 ([#714](https://github.com/k8sgpt-ai/k8sgpt/issues/714)) ([335616c](https://github.com/k8sgpt-ai/k8sgpt/commit/335616c20f7f8d9fefab4976d986a8d3b4867111))
* grpc update ([#938](https://github.com/k8sgpt-ai/k8sgpt/issues/938)) ([bbf61f5](https://github.com/k8sgpt-ai/k8sgpt/commit/bbf61f53d4fb9244b5a79ae953370296ca9fd44b))
* improve codebase and doc quality ([#922](https://github.com/k8sgpt-ai/k8sgpt/issues/922)) ([d97dea2](https://github.com/k8sgpt-ai/k8sgpt/commit/d97dea289681cd061ca0796208c50720bdb08914))
* linting improvements and catching false positives ([#882](https://github.com/k8sgpt-ai/k8sgpt/issues/882)) ([2effbb3](https://github.com/k8sgpt-ai/k8sgpt/commit/2effbb345ad1c2771ec798e06ccde68d3253b4bc))
* set correct license during package build ([#872](https://github.com/k8sgpt-ai/k8sgpt/issues/872)) ([42be51b](https://github.com/k8sgpt-ai/k8sgpt/commit/42be51bc8f625a35b1435c461d9a32c3c4905f1c))
* updated deps ([#951](https://github.com/k8sgpt-ai/k8sgpt/issues/951)) ([015bccf](https://github.com/k8sgpt-ai/k8sgpt/commit/015bccfc2eae587e0ade371211404f5af4c37d27))
## [0.3.26](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.25...v0.3.26) (2024-01-14)
### Features
* initial Prometheus analyzers ([#855](https://github.com/k8sgpt-ai/k8sgpt/issues/855)) ([45fa827](https://github.com/k8sgpt-ai/k8sgpt/commit/45fa827c046b91d901a08bec1a892d9c0917f350))
* interactive mode ([#854](https://github.com/k8sgpt-ai/k8sgpt/issues/854)) ([9da75e0](https://github.com/k8sgpt-ai/k8sgpt/commit/9da75e02bc17146898377e4f90b7f59c5a8e0eee))
* unify aiClientName const for all providers ([#848](https://github.com/k8sgpt-ai/k8sgpt/issues/848)) ([5c17c24](https://github.com/k8sgpt-ai/k8sgpt/commit/5c17c240550609d9fb7771fe67fe1ab19660b4da))
### Bug Fixes
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.16 ([#847](https://github.com/k8sgpt-ai/k8sgpt/issues/847)) ([ce4910b](https://github.com/k8sgpt-ai/k8sgpt/commit/ce4910bc5d064f80076877d7a096fff903308b63))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.17 ([#852](https://github.com/k8sgpt-ai/k8sgpt/issues/852)) ([85ebd12](https://github.com/k8sgpt-ai/k8sgpt/commit/85ebd12c30d369c5ef9a42b5a834d091523a7b6e))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.18 ([#856](https://github.com/k8sgpt-ai/k8sgpt/issues/856)) ([4106d39](https://github.com/k8sgpt-ai/k8sgpt/commit/4106d39c322940413ebfd9ac0bf6f5bd31830e93))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.19 ([#859](https://github.com/k8sgpt-ai/k8sgpt/issues/859)) ([6a2f315](https://github.com/k8sgpt-ai/k8sgpt/commit/6a2f315b2f4344f2924b7915e8a1393f9732a1e9))
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.11 ([#853](https://github.com/k8sgpt-ai/k8sgpt/issues/853)) ([1979c86](https://github.com/k8sgpt-ai/k8sgpt/commit/1979c86d0f59921d55cd4229a37d604a6f1dc578))
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.11 ([#861](https://github.com/k8sgpt-ai/k8sgpt/issues/861)) ([40b5b7e](https://github.com/k8sgpt-ai/k8sgpt/commit/40b5b7e185c8d335bdefb131988b9900ad26bac3))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#864](https://github.com/k8sgpt-ai/k8sgpt/issues/864)) ([36ba6c5](https://github.com/k8sgpt-ai/k8sgpt/commit/36ba6c5147a9ed75c14dbba4bc06cae903e651a4))
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#865](https://github.com/k8sgpt-ai/k8sgpt/issues/865)) ([c55025d](https://github.com/k8sgpt-ai/k8sgpt/commit/c55025d04ebf9da0f6092aabb0b043ccef05164c))
### Other
* **deps:** update actions/upload-artifact digest to 1eb3cb2 ([#867](https://github.com/k8sgpt-ai/k8sgpt/issues/867)) ([4ce56f3](https://github.com/k8sgpt-ai/k8sgpt/commit/4ce56f38b4338a6a2fe69f588b0f17e0b54d0ae6))
* **deps:** update anchore/sbom-action action to v0.15.3 ([#850](https://github.com/k8sgpt-ai/k8sgpt/issues/850)) ([12f764d](https://github.com/k8sgpt-ai/k8sgpt/commit/12f764d5846accbd987d40f69a153dceb9954f39))
### Docs
* adjusted README information about providers ([#844](https://github.com/k8sgpt-ai/k8sgpt/issues/844)) ([745e960](https://github.com/k8sgpt-ai/k8sgpt/commit/745e960f492e6dd0e50aa4a1ce7239c677025024))
## [0.3.25](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.24...v0.3.25) (2024-01-05)
### Features
* added Google GenAI client; simplified IAI/clients API surface. ([#829](https://github.com/k8sgpt-ai/k8sgpt/issues/829)) ([e7d4149](https://github.com/k8sgpt-ai/k8sgpt/commit/e7d41496ddaa145c70079852da8b2ce3b3b7289f))
* code_cov badge ([#821](https://github.com/k8sgpt-ai/k8sgpt/issues/821)) ([fcd29a5](https://github.com/k8sgpt-ai/k8sgpt/commit/fcd29a547d73ba48935762e2f568f5755f5c6ed3))
* coverage reports ([#819](https://github.com/k8sgpt-ai/k8sgpt/issues/819)) ([3d0ba3e](https://github.com/k8sgpt-ai/k8sgpt/commit/3d0ba3e78cabaf5f1262c5b5b16ebabad974fa87))
### Bug Fixes
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.10 ([#811](https://github.com/k8sgpt-ai/k8sgpt/issues/811)) ([e5cc4a2](https://github.com/k8sgpt-ai/k8sgpt/commit/e5cc4a28cb3682e7094e6ceddf91b65da991ddb6))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.12 ([#813](https://github.com/k8sgpt-ai/k8sgpt/issues/813)) ([91613ba](https://github.com/k8sgpt-ai/k8sgpt/commit/91613baa5cc5244c93deb344abcdd905802eef30))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.14 ([#822](https://github.com/k8sgpt-ai/k8sgpt/issues/822)) ([526e22f](https://github.com/k8sgpt-ai/k8sgpt/commit/526e22f88b8de15eceb10965b045ef0366ff2d6c))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.15 ([#835](https://github.com/k8sgpt-ai/k8sgpt/issues/835)) ([e78ff05](https://github.com/k8sgpt-ai/k8sgpt/commit/e78ff054190cd54cabe17d77ac69443e517f1e55))
* **deps:** update module github.com/prometheus/client_golang to v1.18.0 ([#814](https://github.com/k8sgpt-ai/k8sgpt/issues/814)) ([6eb8f67](https://github.com/k8sgpt-ai/k8sgpt/commit/6eb8f6793ed989ba3ac7ed00336345f68b09bf45))
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.10 ([#824](https://github.com/k8sgpt-ai/k8sgpt/issues/824)) ([4314804](https://github.com/k8sgpt-ai/k8sgpt/commit/4314804ca7e782f5149dc2078ba9c859edc4688a))
* **deps:** update module golang.org/x/term to v0.16.0 ([#831](https://github.com/k8sgpt-ai/k8sgpt/issues/831)) ([4de989c](https://github.com/k8sgpt-ai/k8sgpt/commit/4de989c803ee43a02d75112d1b3a54daee3dd9af))
* **deps:** update module google.golang.org/api to v0.155.0 ([#836](https://github.com/k8sgpt-ai/k8sgpt/issues/836)) ([105a239](https://github.com/k8sgpt-ai/k8sgpt/commit/105a239d94384f4096c01d9978564040773ab56e))
* no explain case, improved readability. ([#825](https://github.com/k8sgpt-ai/k8sgpt/issues/825)) ([035348d](https://github.com/k8sgpt-ai/k8sgpt/commit/035348d8a0d290ac26b42425945eaafe038cedc5))
### Other
* added basic server startup test ([#817](https://github.com/k8sgpt-ai/k8sgpt/issues/817)) ([3e7cea7](https://github.com/k8sgpt-ai/k8sgpt/commit/3e7cea7bd39253718bc3d2f8b10ac5fc9b98cbc2))
* **deps:** pin codecov/codecov-action action to eaaf4be ([#820](https://github.com/k8sgpt-ai/k8sgpt/issues/820)) ([2f0f2df](https://github.com/k8sgpt-ai/k8sgpt/commit/2f0f2dfa8a5957cb8b10864c14d7883158723a6a))
* **deps:** update anchore/sbom-action action to v0.15.2 ([#823](https://github.com/k8sgpt-ai/k8sgpt/issues/823)) ([70c6892](https://github.com/k8sgpt-ai/k8sgpt/commit/70c68929d8d963c0bd17390c76e366d4339f56b9))
* lint fixes ([#833](https://github.com/k8sgpt-ai/k8sgpt/issues/833)) ([a7e9b48](https://github.com/k8sgpt-ai/k8sgpt/commit/a7e9b486bad7c2d62878e470a755d1fef3803680))
* remove code cov ([#832](https://github.com/k8sgpt-ai/k8sgpt/issues/832)) ([a774265](https://github.com/k8sgpt-ai/k8sgpt/commit/a77426593d7f3a8cfa810336ff08a2266db7fb4f))
### Dependency Updates
* go module bump to fix CVE: GHSA-45x7-px36-x8w8 & GHSA-7ww5-4wqc-m92c ([#810](https://github.com/k8sgpt-ai/k8sgpt/issues/810)) ([b17fd7c](https://github.com/k8sgpt-ai/k8sgpt/commit/b17fd7c98644afa70d414fcb32e49e61e1c831ad))
## [0.3.24](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.23...v0.3.24) (2023-12-23)
### Features
* add last termination state when pod is in CrashloopBackoff ([#792](https://github.com/k8sgpt-ai/k8sgpt/issues/792)) ([ff4aaf7](https://github.com/k8sgpt-ai/k8sgpt/commit/ff4aaf7c328a58fcad8e4fb0f93ea543725eedd5))
* Add license scan report and status ([#796](https://github.com/k8sgpt-ai/k8sgpt/issues/796)) ([343aec8](https://github.com/k8sgpt-ai/k8sgpt/commit/343aec8f0455c9461eb8d495ca5bd446b4bad667))
* version upgrade to 1.21 ([#798](https://github.com/k8sgpt-ai/k8sgpt/issues/798)) ([c23f24d](https://github.com/k8sgpt-ai/k8sgpt/commit/c23f24de2e79347e4f5465e28af34e138cc13231))
### Bug Fixes
* added the ability to set the trivy variables by the user ([#797](https://github.com/k8sgpt-ai/k8sgpt/issues/797)) ([928b39a](https://github.com/k8sgpt-ai/k8sgpt/commit/928b39a7283ee274dd517e727624eceb3795594d))
* **deps:** update module cloud.google.com/go/storage to v1.36.0 ([#805](https://github.com/k8sgpt-ai/k8sgpt/issues/805)) ([390f309](https://github.com/k8sgpt-ai/k8sgpt/commit/390f30908800dfe21e2c1660139b0bd9d36b34d6))
* **deps:** update module github.com/aquasecurity/trivy-operator to v0.17.1 ([#780](https://github.com/k8sgpt-ai/k8sgpt/issues/780)) ([71f36bd](https://github.com/k8sgpt-ai/k8sgpt/commit/71f36bdb0b3729c4357299b7d03829dd5b6a69ec))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.6 ([#783](https://github.com/k8sgpt-ai/k8sgpt/issues/783)) ([1b386f6](https://github.com/k8sgpt-ai/k8sgpt/commit/1b386f64f2863d8a49f423ad571cba009807bc55))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.7 ([#804](https://github.com/k8sgpt-ai/k8sgpt/issues/804)) ([3c6c759](https://github.com/k8sgpt-ai/k8sgpt/commit/3c6c7597e014bfd68794b1764c3a8902e8a798ea))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.8 ([#807](https://github.com/k8sgpt-ai/k8sgpt/issues/807)) ([93b5ca1](https://github.com/k8sgpt-ai/k8sgpt/commit/93b5ca1985c3730592388ba6fc32ecca9b806888))
* **deps:** update module github.com/aws/aws-sdk-go to v1.49.9 ([#808](https://github.com/k8sgpt-ai/k8sgpt/issues/808)) ([130e4c2](https://github.com/k8sgpt-ai/k8sgpt/commit/130e4c2efd0e5b34cdc84c357c6c1f3987cf7c35))
* **deps:** update module github.com/azure/azure-sdk-for-go/sdk/storage/azblob to v1.2.1 ([#801](https://github.com/k8sgpt-ai/k8sgpt/issues/801)) ([aa05756](https://github.com/k8sgpt-ai/k8sgpt/commit/aa057565b5c971c493443f3ede4aed8f8a6399f7))
* **deps:** update module github.com/mittwald/go-helm-client to v0.12.5 ([#802](https://github.com/k8sgpt-ai/k8sgpt/issues/802)) ([4a7bad3](https://github.com/k8sgpt-ai/k8sgpt/commit/4a7bad313b66750bd830413b7fef005580ad843c))
* **deps:** update module github.com/sashabaranov/go-openai to v1.17.9 ([#772](https://github.com/k8sgpt-ai/k8sgpt/issues/772)) ([13d64a5](https://github.com/k8sgpt-ai/k8sgpt/commit/13d64a58750c7262c07042b557fbf2c4a511b777))
* **deps:** update module github.com/spf13/viper to v1.18.2 ([#787](https://github.com/k8sgpt-ai/k8sgpt/issues/787)) ([8dea617](https://github.com/k8sgpt-ai/k8sgpt/commit/8dea6170a2c00c03f08f25e4f0a232be617536f1))
* **deps:** update module google.golang.org/api to v0.154.0 ([#779](https://github.com/k8sgpt-ai/k8sgpt/issues/779)) ([78f7f2b](https://github.com/k8sgpt-ai/k8sgpt/commit/78f7f2ba85fd357cab13ccc15e9e767e8611773a))
* **deps:** update module google.golang.org/grpc to v1.60.1 ([#790](https://github.com/k8sgpt-ai/k8sgpt/issues/790)) ([5d54c3f](https://github.com/k8sgpt-ai/k8sgpt/commit/5d54c3f840a9ce002606b6601187e69fb62f8a28))
* **deps:** update module helm.sh/helm/v3 to v3.13.3 ([#803](https://github.com/k8sgpt-ai/k8sgpt/issues/803)) ([a8e1932](https://github.com/k8sgpt-ai/k8sgpt/commit/a8e193212222811f3a278df6056dd2165c4323bd))
* lowercase logs before running regex matching in LogAnalyzer ([#794](https://github.com/k8sgpt-ai/k8sgpt/issues/794)) ([03b63be](https://github.com/k8sgpt-ai/k8sgpt/commit/03b63befa247ac84b795a0ec8d5280196b8d570d))
### Other
* **deps:** update actions/setup-go action to v5 ([#788](https://github.com/k8sgpt-ai/k8sgpt/issues/788)) ([d00ed33](https://github.com/k8sgpt-ai/k8sgpt/commit/d00ed33678b1560a3996f1d735d84ca0ca05c0b0))
* **deps:** update actions/upload-artifact action to v4 ([#806](https://github.com/k8sgpt-ai/k8sgpt/issues/806)) ([d6fb648](https://github.com/k8sgpt-ai/k8sgpt/commit/d6fb648e23c1ed1e4680fc4b7b4e96501f50ad48))
* **deps:** update anchore/sbom-action action to v0.15.1 ([#784](https://github.com/k8sgpt-ai/k8sgpt/issues/784)) ([6473a2b](https://github.com/k8sgpt-ai/k8sgpt/commit/6473a2b532491b707b3af922fc2198e626ebf219))
* **deps:** update google-github-actions/release-please-action action to v4 ([#782](https://github.com/k8sgpt-ai/k8sgpt/issues/782)) ([2c28c55](https://github.com/k8sgpt-ai/k8sgpt/commit/2c28c555cf4e891b90ebd9e9eae1cd8724e9886f))
* **deps:** update google-github-actions/release-please-action action to v4.0.2 ([#800](https://github.com/k8sgpt-ai/k8sgpt/issues/800)) ([be4b0bb](https://github.com/k8sgpt-ai/k8sgpt/commit/be4b0bb3c24e04d35f40d16fd8e94ddbc8457ca6))
### Refactoring
* replace rest client with controller-runtime clientset for Trivy analyzers ([#776](https://github.com/k8sgpt-ai/k8sgpt/issues/776)) ([1d19628](https://github.com/k8sgpt-ai/k8sgpt/commit/1d196286b75f0ea6c068e8bdb01455fb36c52432))
## [0.3.23](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.22...v0.3.23) (2023-11-24)

View File

@@ -98,7 +98,7 @@ vet:
## lint: Run go lint against code.
.PHONY: lint
lint:
@golangci-lint run -v ./...
@golangci-lint run -v --timeout=5m ./...
## style: Code style -> fmt,vet,lint
.PHONY: style

465
README.md
View File

@@ -9,23 +9,34 @@
![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/)
[![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)
`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.
_Out of the box integration with OpenAI, Azure, Cohere, Amazon Bedrock and local models._
_Out of the box integration with OpenAI, Azure, Cohere, Amazon Bedrock, Google Gemini and local models._
<a href="https://www.producthunt.com/posts/k8sgpt?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-k8sgpt" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=389489&theme=light" alt="K8sGPT - K8sGPT&#0032;gives&#0032;Kubernetes&#0032;Superpowers&#0032;to&#0032;everyone | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a> <a href="https://hellogithub.com/repository/9dfe44c18dfb4d6fa0181baf8b2cf2e1" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=9dfe44c18dfb4d6fa0181baf8b2cf2e1&claim_uid=gqG4wmzkMrP0eFy" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<a href="https://www.producthunt.com/posts/k8sgpt?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-k8sgpt" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=389489&theme=light" alt="K8sGPT - K8sGPT&#0032;gives&#0032;Kubernetes&#0032;Superpowers&#0032;to&#0032;everyone | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<img src="images/demo4.gif" width=650px; />
# CLI Installation
### Linux/Mac via brew
```sh
$ brew install k8sgpt
```
or
```sh
brew tap k8sgpt-ai/k8sgpt
brew install k8sgpt
```
@@ -33,20 +44,20 @@ brew install k8sgpt
<details>
<summary>RPM-based installation (RedHat/CentOS/Fedora)</summary>
**32 bit:**
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.rpm
sudo rpm -ivh k8sgpt_386.rpm
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_386.rpm
```
<!---x-release-please-end-->
**64 bit:**
**64 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.rpm
sudo rpm -ivh -i k8sgpt_amd64.rpm
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_amd64.rpm
```
<!---x-release-please-end-->
</details>
@@ -54,20 +65,26 @@ brew install k8sgpt
<details>
<summary>DEB-based installation (Ubuntu/Debian)</summary>
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
<!---x-release-please-end-->
**64 bit:**
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
<!---x-release-please-end-->
**64 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
<!---x-release-please-end-->
</details>
@@ -75,44 +92,48 @@ brew install k8sgpt
<summary>APK-based installation (Alpine)</summary>
**32 bit:**
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_386.apk
apk add k8sgpt_386.apk
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_386.apk
apk add --allow-untrusted k8sgpt_386.apk
```
<!---x-release-please-end-->
**64 bit:**
**64 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.23/k8sgpt_amd64.apk
apk add k8sgpt_amd64.apk
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.48/k8sgpt_amd64.apk
apk add --allow-untrusted k8sgpt_amd64.apk
```
<!---x-release-please-end-->x
<!---x-release-please-end-->
</details>
<details>
<summary>Failing Installation on WSL or Linux (missing gcc)</summary>
When installing Homebrew on WSL or Linux, you may encounter the following error:
```
==> Installing k8sgpt from k8sgpt-ai/k8sgpt Error: The following formula cannot be installed from a bottle and must be
built from the source. k8sgpt Install Clang or run brew install gcc.
```
```
==> Installing k8sgpt from k8sgpt-ai/k8sgpt Error: The following formula cannot be installed from a bottle and must be
built from the source. k8sgpt Install Clang or run brew install gcc.
```
If you install gcc as suggested, the problem will persist. Therefore, you need to install the build-essential package.
```
sudo apt-get update
sudo apt-get install build-essential
```
</details>
```
sudo apt-get update
sudo apt-get install build-essential
```
</details>
### Windows
* Download the latest Windows binaries of **k8sgpt** from the [Release](https://github.com/k8sgpt-ai/k8sgpt/releases)
- Download the latest Windows binaries of **k8sgpt** from the [Release](https://github.com/k8sgpt-ai/k8sgpt/releases)
tab based on your system architecture.
* Extract the downloaded package to your desired location. Configure the system *path* variable with the binary location
- Extract the downloaded package to your desired location. Configure the system _path_ variable with the binary location
## Operator Installation
@@ -120,17 +141,16 @@ To install within a Kubernetes cluster please use our `k8sgpt-operator` with ins
_This mode of operation is ideal for continuous monitoring of your cluster and can integrate with your existing monitoring such as Prometheus and Alertmanager._
## Quick Start
* Currently the default AI provider is OpenAI, you will need to generate an API key from [OpenAI](https://openai.com)
* You can do this by running `k8sgpt generate` to open a browser link to generate it
* Run `k8sgpt auth add` to set it in k8sgpt.
* You can provide the password directly using the `--password` flag.
* Run `k8sgpt filters` to manage the active filters used by the analyzer. By default, all filters are executed during analysis.
* Run `k8sgpt analyze` to run a scan.
* And use `k8sgpt analyze --explain` to get a more detailed explanation of the issues.
* You also run `k8sgpt analyze --with-doc` (with or without the explain flag) to get the official documentation from kubernetes.
- Currently, the default AI provider is OpenAI, you will need to generate an API key from [OpenAI](https://openai.com)
- You can do this by running `k8sgpt generate` to open a browser link to generate it
- Run `k8sgpt auth add` to set it in k8sgpt.
- You can provide the password directly using the `--password` flag.
- Run `k8sgpt filters` to manage the active filters used by the analyzer. By default, all filters are executed during analysis.
- Run `k8sgpt analyze` to run a scan.
- And use `k8sgpt analyze --explain` to get a more detailed explanation of the issues.
- You also run `k8sgpt analyze --with-doc` (with or without the explain flag) to get the official documentation from Kubernetes.
## Analyzers
@@ -162,6 +182,7 @@ you will be able to write your own analyzers.
- [x] gatewayClass
- [x] gateway
- [x] httproute
- [x] logAnalyzer
## Examples
@@ -181,6 +202,7 @@ k8sgpt analyze --explain --filter=Service
```
_Filter by namespace_
```
k8sgpt analyze --explain --filter=Pod --namespace=default
```
@@ -285,204 +307,69 @@ k8sgpt serve
_Analysis with serve mode_
```
curl -X GET "http://localhost:8080/analyze?namespace=k8sgpt&explain=false"
```
</details>
## Key Features
<details>
<summary> LocalAI provider </summary>
To run local models, it is possible to use OpenAI compatible APIs, for instance [LocalAI](https://github.com/go-skynet/LocalAI) which uses [llama.cpp](https://github.com/ggerganov/llama.cpp) and [ggml](https://github.com/ggerganov/ggml) to run inference on consumer-grade hardware. Models supported by LocalAI for instance are Vicuna, Alpaca, LLaMA, Cerebras, GPT4ALL, GPT4ALL-J and koala.
To run local inference, you need to download the models first, for instance you can find `ggml` compatible models in [huggingface.com](https://huggingface.co/models?search=ggml) (for example vicuna, alpaca and koala).
### Start the API server
To start the API server, follow the instruction in [LocalAI](https://github.com/go-skynet/LocalAI#example-use-gpt4all-j-model).
### Run k8sgpt
To run k8sgpt, run `k8sgpt auth add` with the `localai` backend:
```
k8sgpt auth add --backend localai --model <model_name> --baseurl http://localhost:8080/v1 --temperature 0.7
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServerAnalyzerService/Analyze
{
"status": "OK"
}
```
Now you can analyze with the `localai` backend:
_Analysis with custom headers_
```
k8sgpt analyze --explain --backend localai
k8sgpt analyze --explain --custom-headers CustomHeaderKey:CustomHeaderValue
```
_Print analysis stats_
```
k8sgpt analyze -s
The stats mode allows for debugging and understanding the time taken by an analysis by displaying the statistics of each analyzer.
- Analyzer Ingress took 47.125583ms
- Analyzer PersistentVolumeClaim took 53.009167ms
- Analyzer CronJob took 57.517792ms
- Analyzer Deployment took 156.6205ms
- Analyzer Node took 160.109833ms
- Analyzer ReplicaSet took 245.938333ms
- Analyzer StatefulSet took 448.0455ms
- Analyzer Pod took 5.662594708s
- Analyzer Service took 38.583359166s
```
_Diagnostic information_
To collect diagnostic information use the following command to create a `dump_<timestamp>_json` in your local directory.
```
k8sgpt dump
```
</details>
<details>
<summary> AzureOpenAI provider </summary>
## LLM AI Backends
<em>Prerequisites:</em> an Azure OpenAI deployment is needed, please visit MS official [documentation](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource) to create your own.
K8sGPT uses the chosen LLM, generative AI provider when you want to explain the analysis results using --explain flag e.g. `k8sgpt analyze --explain`. You can use `--backend` flag to specify a configured provider (it's `openai` by default).
To authenticate with k8sgpt, you will need the Azure OpenAI endpoint of your tenant `"https://your Azure OpenAI Endpoint"`, the api key to access your deployment, the deployment name of your model and the model name itself.
To run k8sgpt, run `k8sgpt auth` with the `azureopenai` backend:
```
k8sgpt auth add --backend azureopenai --baseurl https://<your Azure OpenAI endpoint> --engine <deployment_name> --model <model_name>
```
Lastly, enter your Azure API key, after the prompt.
Now you are ready to analyze with the azure openai backend:
```
k8sgpt analyze --explain --backend azureopenai
```
</details>
<details>
<summary>Cohere provider</summary>
<em>Prerequisites:</em> a Cohere API key is needed, please visit the [Cohere dashboard](https://dashboard.cohere.ai/api-keys) to create one.
To run k8sgpt, run `k8sgpt auth` with the `cohere` backend:
You can list available providers using `k8sgpt auth list`:
```
k8sgpt auth add --backend cohere --model command-nightly
```
Lastly, enter your Cohere API key, after the prompt.
Now you are ready to analyze with the Cohere backend:
```
k8sgpt analyze --explain --backend cohere
```
</details>
<details>
<summary>Amazon Bedrock provider</summary>
<em>Prerequisites</em>
Bedrock API access is needed.
<img src="images/bedrock.png" width="500px;" />
As illustrated below, you will need to enable this in the [AWS Console](https://eu-central-1.console.aws.amazon.com/bedrock/home?region=eu-central-1#/modelaccess)
In addition to this you will need to set the follow local environmental variables:
```
- AWS_ACCESS_KEY
- AWS_SECRET_ACCESS_KEY
- AWS_DEFAULT_REGION
```
```
k8sgpt auth add --backend amazonbedrock --model anthropic.claude-v2
```
#### Usage
```
k8sgpt analyze -e -b amazonbedrock
0 argocd/argocd-application-controller(argocd-application-controller)
- Error: StatefulSet uses the service argocd/argocd-application-controller which does not exist.
You're right, I don't have enough context to determine if a StatefulSet is correctly configured to use a non-existent service. A StatefulSet manages Pods with persistent storage, and the Pods are created from the same spec. The service name referenced in the StatefulSet configuration would need to match an existing Kubernetes service for the Pods to connect to. Without more details on the specific StatefulSet and environment, I can't confirm whether the configuration is valid or not.
```
</details>
<details>
<summary>Amazon SageMaker Provider</summary>
#### Prerequisites
1. **AWS CLI Configuration**: Make sure you have the AWS Command Line Interface (CLI) configured on your machine. If you haven't already configured the AWS CLI, you can follow the official AWS documentation for instructions on how to do it: [AWS CLI Configuration Guide](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html).
2. **SageMaker Instance**: You need to have an Amazon SageMaker instance set up. If you don't have one already, you can follow the step-by-step instructions provided in this repository for creating a SageMaker instance: [llm-sagemaker-jumpstart-cdk](https://github.com/zaremb/llm-sagemaker-jumpstart-cdk).
#### Backend Configuration
To add amazonsagemaker backend two parameters are required:
* `--endpointname` Amazon SageMaker endpoint name.
* `--providerRegion` AWS region where SageMaker instance is created. `k8sgpt` uses this region to connect to SageMaker (not the one defined with AWS CLI or environment variables )
To add amazonsagemaker as a backend run:
```bash
k8sgpt auth add --backend amazonsagemaker --providerRegion eu-west-1 --endpointname endpoint-xxxxxxxxxx
```
#### Optional params
Optionally, when adding the backend and later by changing the configuration file, you can set the following parameters:
`-l, --maxtokens int` Specify a maximum output length. Adjust (1-...) to control text length. Higher values produce longer output, lower values limit length (default 2048)
`-t, --temperature float32` The sampling temperature, value ranges between 0 ( output be more deterministic) and 1 (more random) (default 0.7)
`-c, --topp float32` Probability Cutoff: Set a threshold (0.0-1.0) to limit word choices. Higher values add randomness, lower values increase predictability. (default 0.5)
To make amazonsagemaker as a default backend run:
```bash
k8sgpt auth default -p amazonsagemaker
```
#### AmazonSageMaker Usage
```bash
./k8sgpt analyze -e -b amazonsagemaker
100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (1/1, 14 it/min)
AI Provider: amazonsagemaker
0 default/nginx(nginx)
- Error: Back-off pulling image "nginxx"
Error: Back-off pulling image "nginxx"
Solution:
1. Check if the image exists in the registry by running `docker image ls nginxx`.
2. If the image is not found, try pulling it by running `docker pull nginxx`.
3. If the image is still not available, check if there are any network issues by running `docker network inspect` and `docker network list`.
4. If the issue persists, try restarting the Docker daemon by running `sudo service docker restart`.
```
</details>
<details>
<summary>Setting a new default AI provider</summary>
There may be scenarios where you wish to have K8sGPT plugged into several default AI providers. In this case you may wish to use one as a new default, other than OpenAI which is the project default.
_To view available providers_
```
k8sgpt auth list
Default:
> openai
Active:
> openai
> azureopenai
Unused:
> openai
> localai
> noopai
> amazonbedrock
> ollama
> azureopenai
> cohere
> amazonbedrock
> amazonsagemaker
> google
> huggingface
> noopai
> googlevertexai
> ibmwatsonxai
```
For detailed documentation on how to configure and use each provider see [here](https://docs.k8sgpt.ai/reference/providers/backend/).
_To set a new default provider_
@@ -491,33 +378,34 @@ k8sgpt auth default -p azureopenai
Default provider set to azureopenai
```
</details>
## Key Features
<details>
With this option, the data is anonymized before being sent to the AI Backend. During the analysis execution, `k8sgpt` retrieves sensitive data (Kubernetes object names, labels, etc.). This data is masked when sent to the AI backend and replaced by a key that can be used to de-anonymize the data when the solution is returned to the user.
<summary> Anonymization </summary>
1. Error reported during analysis:
```bash
Error: HorizontalPodAutoscaler uses StatefulSet/fake-deployment as ScaleTargetRef which does not exist.
```
2. Payload sent to the AI backend:
```bash
Error: HorizontalPodAutoscaler uses StatefulSet/tGLcCRcHa1Ce5Rs as ScaleTargetRef which does not exist.
```
3. Payload returned by the AI:
```bash
The Kubernetes system is trying to scale a StatefulSet named tGLcCRcHa1Ce5Rs using the HorizontalPodAutoscaler, but it cannot find the StatefulSet. The solution is to verify that the StatefulSet name is spelled correctly and exists in the same namespace as the HorizontalPodAutoscaler.
```
4. Payload returned to the user:
```bash
The Kubernetes system is trying to scale a StatefulSet named fake-deployment using the HorizontalPodAutoscaler, but it cannot find the StatefulSet. The solution is to verify that the StatefulSet name is spelled correctly and exists in the same namespace as the HorizontalPodAutoscaler.
```
@@ -528,7 +416,7 @@ Note: **Anonymization does not currently apply to events.**
**Anonymization does not currently apply to events.**
*In a few analysers like Pod, we feed to the AI backend the event messages which are not known beforehand thus we are not masking them for the **time being**.*
_In a few analysers like Pod, we feed to the AI backend the event messages which are not known beforehand thus we are not masking them for the **time being**._
- The following is the list of analysers in which data is **being masked**:-
@@ -547,11 +435,13 @@ Note: **Anonymization does not currently apply to events.**
- RepicaSet
- PersistentVolumeClaim
- Pod
- **_*Events_**
- Log
- **_\*Events_**
***Note**:
- k8gpt will not mask the above analysers because they do not send any identifying information except **Events** analyser.
- Masking for **Events** analyzer is scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560). _Further research has to be made to understand the patterns and be able to mask the sensitive parts of an event like pod name, namespace etc._
**\*Note**:
- k8gpt will not mask the above analysers because they do not send any identifying information except **Events** analyser.
- Masking for **Events** analyzer is scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560). _Further research has to be made to understand the patterns and be able to mask the sensitive parts of an event like pod name, namespace etc._
- The following is the list of fields which are not **being masked**:-
@@ -559,18 +449,18 @@ Note: **Anonymization does not currently apply to events.**
- ObjectStatus
- Replicas
- ContainerStatus
- **_*Event Message_**
- **_\*Event Message_**
- ReplicaStatus
- Count (Pod)
***Note**:
- It is quite possible the payload of the event message might have something like "super-secret-project-pod-X crashed" which we don't currently redact _(scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560))_.
**\*Note**:
- It is quite possible the payload of the event message might have something like "super-secret-project-pod-X crashed" which we don't currently redact _(scheduled in the near future as seen in this [issue](https://github.com/k8sgpt-ai/k8sgpt/issues/560))_.
### Proceed with care
- The K8gpt team recommends using an entirely different backend **(a local model) in critical production environments**. By using a local model, you can rest assured that everything stays within your DMZ, and nothing is leaked.
- If there is any uncertainty about the possibility of sending data to a public LLM (open AI, Azure AI) and it poses a risk to business-critical operations, then, in such cases, the use of public LLM should be avoided based on personal assessment and the jurisdiction of risks involved.
- The K8gpt team recommends using an entirely different backend **(a local model) in critical production environments**. By using a local model, you can rest assured that everything stays within your DMZ, and nothing is leaked.
- If there is any uncertainty about the possibility of sending data to a public LLM (open AI, Azure AI) and it poses a risk to business-critical operations, then, in such cases, the use of public LLM should be avoided based on personal assessment and the jurisdiction of risks involved.
</details>
@@ -580,66 +470,121 @@ Note: **Anonymization does not currently apply to events.**
`k8sgpt` stores config data in the `$XDG_CONFIG_HOME/k8sgpt/k8sgpt.yaml` file. The data is stored in plain text, including your OpenAI key.
Config file locations:
| OS | Path |
| OS | Path |
| ------- | ------------------------------------------------ |
| MacOS | ~/Library/Application Support/k8sgpt/k8sgpt.yaml |
| Linux | ~/.config/k8sgpt/k8sgpt.yaml |
| Windows | %LOCALAPPDATA%/k8sgpt/k8sgpt.yaml |
| MacOS | ~/Library/Application Support/k8sgpt/k8sgpt.yaml |
| Linux | ~/.config/k8sgpt/k8sgpt.yaml |
| Windows | %LOCALAPPDATA%/k8sgpt/k8sgpt.yaml |
</details>
<details>
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_
* AWS S3
* _As a prerequisite `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are required as environmental variables._
* Configuration, ``` k8sgpt cache add s3 --region <aws region> --bucket <name> ```
* K8sGPT will create the bucket if it does not exist
* Azure Storage
* 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)
* 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
- AWS S3
- _As a prerequisite `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are required as environmental variables._
- Configuration, `k8sgpt cache add s3 --region <aws region> --bucket <name>`
- Minio Configuration with HTTP endpoint ` k8sgpt cache add s3 --bucket <name> --endpoint <http://localhost:9000>`
- Minio Configuration with HTTPs endpoint, skipping TLS verification ` k8sgpt cache add s3 --bucket <name> --endpoint <https://localhost:9000> --insecure`
- K8sGPT will create the bucket if it does not exist
- Azure Storage
- 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)
- 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
_Listing cache items_
```
k8sgpt cache list
```
_Purging an object from the cache_
Note: purging an object using this command will delete upstream files, so it requires appropriate permissions.
```
k8sgpt cache purge $OBJECT_NAME
```
_Removing the remote cache_
Note: this will not delete the upstream S3 bucket or Azure storage container
```
k8sgpt cache remove
```
</details>
<details>
<summary> Custom Analyzers</summary>
There may be scenarios where you wish to write your own analyzer in a language of your choice.
K8sGPT now supports the ability to do so by abiding by the [schema](https://github.com/k8sgpt-ai/schemas/blob/main/protobuf/schema/v1/analyzer.proto) and serving the analyzer for consumption.
To do so, define the analyzer within the K8sGPT configuration and it will add it into the scanning process.
In addition to this you will need to enable the following flag on analysis:
```
k8sgpt analyze --custom-analysis
```
Here is an example local host analyzer in [Rust](https://github.com/k8sgpt-ai/host-analyzer)
When this is run on `localhost:8080` the K8sGPT config can pick it up with the following additions:
```
custom_analyzers:
- name: host-analyzer
connection:
url: localhost
port: 8080
```
This now gives the ability to pass through hostOS information ( from this analyzer example ) to K8sGPT to use as context with normal analysis.
_See the docs on how to write a custom analyzer_
_Listing custom analyzers configured_
```
k8sgpt custom-analyzer list
```
_Adding custom analyzer without install_
```
k8sgpt custom-analyzer add --name my-custom-analyzer --port 8085
```
_Removing custom analyzer_
```
k8sgpt custom-analyzer remove --names "my-custom-analyzer,my-custom-analyzer-2"
```
</details>
## Documentation
Find our official documentation available [here](https://docs.k8sgpt.ai)
## Contributing
Please read our [contributing guide](./CONTRIBUTING.md).
## Community
Find us on [Slack](https://join.slack.com/t/k8sgpt/shared_invite/zt-276pa9uyq-pxAUr4TCVHubFxEvLZuT1Q)
<a href="https://github.com/k8sgpt-ai/k8sgpt/graphs/contributors">
<img src="https://contrib.rocks/image?repo=k8sgpt-ai/k8sgpt" />
</a>
## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fk8sgpt-ai%2Fk8sgpt.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fk8sgpt-ai%2Fk8sgpt?ref=badge_large)

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

@@ -16,23 +16,31 @@ package analyze
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai/interactive"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
"github.com/spf13/cobra"
)
var (
explain bool
backend string
output string
filters []string
language string
nocache bool
namespace string
anonymize bool
maxConcurrency int
withDoc bool
explain bool
backend string
output string
filters []string
language string
nocache bool
namespace string
labelSelector string
anonymize bool
maxConcurrency int
withDoc bool
interactiveMode bool
customAnalysis bool
customHeaders []string
withStats bool
)
// AnalyzeCmd represents the problems command
@@ -43,37 +51,81 @@ var AnalyzeCmd = &cobra.Command{
Long: `This command will find problems within your Kubernetes cluster and
provide you with a list of issues that need to be resolved`,
Run: func(cmd *cobra.Command, args []string) {
// Create analysis configuration first.
config, err := analysis.NewAnalysis(
backend,
language,
filters,
namespace,
labelSelector,
nocache,
explain,
maxConcurrency,
withDoc,
interactiveMode,
customHeaders,
withStats,
)
// AnalysisResult configuration
config, err := analysis.NewAnalysis(backend,
language, filters, namespace, nocache, explain, maxConcurrency, withDoc)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
defer config.Close()
if customAnalysis {
config.RunCustomAnalysis()
}
config.RunAnalysis()
if explain {
err := config.GetAIResults(output, anonymize)
if err != nil {
if err := config.GetAIResults(output, anonymize); err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
}
// print results
output, err := config.PrintOutput(output)
output_data, err := config.PrintOutput(output)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
fmt.Println(string(output))
if withStats {
statsData := config.PrintStats()
fmt.Println(string(statsData))
}
fmt.Println(string(output_data))
if interactiveMode && explain {
if output == "json" {
color.Yellow("Caution: interactive mode using --json enabled may use additional tokens.")
}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
interactiveClient := interactive.NewInteractionRunner(config, output_data)
go interactiveClient.StartInteraction()
for {
select {
case res := <-sigs:
switch res {
default:
os.Exit(0)
}
case res := <-interactiveClient.State:
switch res {
case interactive.E_EXITED:
os.Exit(0)
}
}
}
}
},
}
func init() {
// namespace flag
AnalyzeCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Namespace to analyze")
// no cache flag
@@ -85,7 +137,7 @@ func init() {
// explain flag
AnalyzeCmd.Flags().BoolVarP(&explain, "explain", "e", false, "Explain the problem to me")
// add flag for backend
AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "openai", "Backend AI provider")
AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "", "Backend AI provider")
// output as json
AnalyzeCmd.Flags().StringVarP(&output, "output", "o", "text", "Output format (text, json)")
// add language options for output
@@ -94,4 +146,14 @@ func init() {
AnalyzeCmd.Flags().IntVarP(&maxConcurrency, "max-concurrency", "m", 10, "Maximum number of concurrent requests to the Kubernetes API server")
// kubernetes doc flag
AnalyzeCmd.Flags().BoolVarP(&withDoc, "with-doc", "d", false, "Give me the official documentation of the involved field")
// interactive mode flag
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.")
// print stats
AnalyzeCmd.Flags().BoolVarP(&withStats, "with-stat", "s", false, "Print analysis stats. This option disables errors display.")
}

View File

@@ -45,25 +45,15 @@ var addCmd = &cobra.Command{
_ = cmd.MarkFlagRequired("endpointname")
_ = cmd.MarkFlagRequired("providerRegion")
}
if strings.ToLower(backend) == "amazonbedrock" {
_ = cmd.MarkFlagRequired("providerRegion")
}
if strings.ToLower(backend) == "ibmwatsonxai" {
_ = cmd.MarkFlagRequired("providerId")
}
},
Run: func(cmd *cobra.Command, args []string) {
// get ai configuration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
// search for provider with same name
providerIndex := -1
for i, provider := range configAI.Providers {
if backend == provider.Name {
providerIndex = i
break
}
}
validBackend := func(validBackends []string, backend string) bool {
for _, b := range validBackends {
if b == backend {
@@ -84,6 +74,28 @@ var addCmd = &cobra.Command{
}
}
// get ai configuration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
// search for provider with same name
providerIndex := -1
for i, provider := range configAI.Providers {
if backend == provider.Name {
providerIndex = i
break
}
}
if providerIndex != -1 {
// provider with same name exists, update provider info
color.Yellow("Provider with same name already exists.")
os.Exit(1)
}
// check if model is not empty
if model == "" {
model = defaultModel
@@ -97,6 +109,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)
@@ -119,8 +135,12 @@ var addCmd = &cobra.Command{
Engine: engine,
Temperature: temperature,
ProviderRegion: providerRegion,
ProviderId: providerId,
CompartmentId: compartmentId,
TopP: topP,
TopK: topK,
MaxTokens: maxTokens,
OrganizationId: organizationId,
}
if providerIndex == -1 {
@@ -132,9 +152,6 @@ var addCmd = &cobra.Command{
os.Exit(1)
}
color.Green("%s added to the AI backend provider list", backend)
} else {
// provider with same name exists, update provider info
color.Yellow("Provider with same name already exists.")
}
},
}
@@ -149,15 +166,23 @@ func init() {
// add flag for url
addCmd.Flags().StringVarP(&baseURL, "baseurl", "u", "", "URL AI provider, (e.g `http://localhost:8080/v1`)")
// add flag for endpointName
addCmd.Flags().StringVarP(&endpointName, "endpointname", "n", "", "Endpoint Name, (e.g `endpoint-xxxxxxxxxxxx`)")
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
addCmd.Flags().Float32VarP(&temperature, "temperature", "t", 0.7, "The sampling temperature, value ranges between 0 ( output be more deterministic) and 1 (more random)")
// add flag for azure open ai engine/deployment name
addCmd.Flags().StringVarP(&engine, "engine", "e", "", "Azure AI deployment name")
addCmd.Flags().StringVarP(&engine, "engine", "e", "", "Azure AI deployment name (only for azureopenai backend)")
//add flag for amazonbedrock region name
addCmd.Flags().StringVarP(&providerRegion, "providerRegion", "r", "", "Provider Region name")
addCmd.Flags().StringVarP(&providerRegion, "providerRegion", "r", "", "Provider Region name (only for amazonbedrock, googlevertexai backend)")
//add flag for vertexAI/WatsonxAI Project ID
addCmd.Flags().StringVarP(&providerId, "providerId", "i", "", "Provider specific ID for e.g. project (only for googlevertexai/ibmwatsonxai 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

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

View File

@@ -24,7 +24,6 @@ import (
)
var details bool
var userInput string
var listCmd = &cobra.Command{
Use: "list",
@@ -39,11 +38,6 @@ var listCmd = &cobra.Command{
os.Exit(1)
}
if details {
fmt.Println("Show password ? (y/n)")
fmt.Scan(&userInput)
}
// Print the default if it is set
fmt.Print(color.YellowString("Default: \n"))
if configAI.DefaultProvider != "" {
@@ -66,7 +60,7 @@ var listCmd = &cobra.Command{
if details {
for _, provider := range configAI.Providers {
if provider.Name == aiBackend {
printDetails(provider, userInput)
printDetails(provider)
}
}
}
@@ -91,7 +85,7 @@ func init() {
listCmd.Flags().BoolVar(&details, "details", false, "Print active provider configuration details")
}
func printDetails(provider ai.AIProvider, userInput string) {
func printDetails(provider ai.AIProvider) {
if provider.Model != "" {
fmt.Printf(" - Model: %s\n", provider.Model)
}

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")
}

22
cmd/cache/add.go vendored
View File

@@ -17,6 +17,7 @@ package cache
import (
"fmt"
"os"
"strings"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
@@ -24,11 +25,14 @@ import (
)
var (
region string
region string
//nolint:unused
bucketName string
storageAccount string
containerName string
projectId string
endpoint string
insecure bool
)
// addCmd represents the add command
@@ -37,9 +41,10 @@ var addCmd = &cobra.Command{
Short: "Add a remote cache",
Long: `This command allows you to add a remote cache to store the results of an analysis.
The supported cache types are:
- Azure Blob storage
- Google Cloud storage
- S3`,
- Azure Blob storage (e.g., k8sgpt cache add azure)
- Google Cloud storage (e.g., k8sgpt cache add gcs)
- S3 (e.g., k8sgpt cache add s3)
- Interplex (e.g., k8sgpt cache add interplex)`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
color.Red("Error: Please provide a value for cache types. Run k8sgpt cache add --help")
@@ -47,7 +52,7 @@ var addCmd = &cobra.Command{
}
fmt.Println(color.YellowString("Adding remote based cache"))
cacheType := args[0]
remoteCache, err := cache.NewCacheProvider(cacheType, bucketname, region, storageAccount, containerName, projectId)
remoteCache, err := cache.NewCacheProvider(strings.ToLower(cacheType), bucketName, region, endpoint, storageAccount, containerName, projectId, insecure)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
@@ -62,9 +67,10 @@ var addCmd = &cobra.Command{
func init() {
CacheCmd.AddCommand(addCmd)
addCmd.Flags().StringVarP(&region, "region", "r", "", "The region to use for the AWS S3 or GCS cache")
addCmd.Flags().StringVarP(&bucketname, "bucket", "b", "", "The name of the AWS S3 bucket to use for the cache")
addCmd.MarkFlagsRequiredTogether("region", "bucket")
addCmd.Flags().StringVarP(&region, "region", "r", "us-east-1", "The region to use for the AWS S3 or GCS cache")
addCmd.Flags().StringVarP(&endpoint, "endpoint", "e", "", "The S3 or minio endpoint")
addCmd.Flags().BoolVarP(&insecure, "insecure", "i", false, "Skip TLS verification for S3/Minio custom endpoint")
addCmd.Flags().StringVarP(&bucketName, "bucket", "b", "", "The name of the AWS S3 bucket to use for the cache")
addCmd.Flags().StringVarP(&projectId, "projectid", "p", "", "The GCP project ID")
addCmd.Flags().StringVarP(&storageAccount, "storageacc", "s", "", "The Azure storage account name of the container")
addCmd.Flags().StringVarP(&containerName, "container", "c", "", "The Azure container name to use for the cache")

9
cmd/cache/cache.go vendored
View File

@@ -18,17 +18,16 @@ import (
"github.com/spf13/cobra"
)
var (
bucketname string
)
// cacheCmd represents the cache command
var CacheCmd = &cobra.Command{
Use: "cache",
Short: "For working with the cache the results of an analysis",
Long: `Cache commands allow you to add a remote cache, list the contents of the cache, and remove items from the cache.`,
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
err := cmd.Help()
if err != nil {
panic(err)
}
},
}

45
cmd/cache/get.go vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
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 cache
import (
"fmt"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/spf13/cobra"
"os"
)
// listCmd represents the list command
var getCmd = &cobra.Command{
Use: "get",
Short: "Get the current cache",
Long: `Returns the current remote cache being used`,
Run: func(cmd *cobra.Command, args []string) {
// load remote cache if it is configured
c, err := cache.GetCacheConfiguration()
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
fmt.Printf("Current remote cache is: %s", c.GetName())
},
}
func init() {
CacheCmd.AddCommand(getCmd)
}

73
cmd/customAnalyzer/add.go Normal file
View File

@@ -0,0 +1,73 @@
/*
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 customanalyzer
import (
"os"
"github.com/fatih/color"
customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
name string
url string
port int
)
var addCmd = &cobra.Command{
Use: "add",
Aliases: []string{"add"},
Short: "This command will add a custom analyzer from source",
Long: "This command allows you to add/remote/list an existing custom analyzer.",
Run: func(cmd *cobra.Command, args []string) {
err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
analyzer := customAnalyzer.NewCustomAnalyzer()
// Check if configuration is valid
err = analyzer.Check(configCustomAnalyzer, name, url, port)
if err != nil {
color.Red("Error adding custom analyzer: %s", err.Error())
os.Exit(1)
}
configCustomAnalyzer = append(configCustomAnalyzer, customAnalyzer.CustomAnalyzerConfiguration{
Name: name,
Connection: customAnalyzer.Connection{
Url: url,
Port: port,
},
})
viper.Set("custom_analyzers", configCustomAnalyzer)
if err := viper.WriteConfig(); err != nil {
color.Red("Error writing config file: %s", err.Error())
os.Exit(1)
}
color.Green("%s added to the custom analyzers config list", name)
},
}
func init() {
addCmd.Flags().StringVarP(&name, "name", "n", "my-custom-analyzer", "Name of the custom analyzer.")
addCmd.Flags().StringVarP(&url, "url", "u", "localhost", "URL for the custom analyzer connection.")
addCmd.Flags().IntVarP(&port, "port", "r", 8085, "Port for the custom analyzer connection.")
}

View File

@@ -0,0 +1,43 @@
/*
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 customanalyzer
import (
customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer"
"github.com/spf13/cobra"
)
var configCustomAnalyzer []customAnalyzer.CustomAnalyzerConfiguration
// authCmd represents the auth command
var CustomAnalyzerCmd = &cobra.Command{
Use: "custom-analyzer",
Short: "Manage a custom analyzer",
Long: `This command allows you to manage custom analyzers, including adding, removing, and listing them.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
_ = cmd.Help()
return
}
},
}
func init() {
// add subcommand to add custom analyzer
CustomAnalyzerCmd.AddCommand(addCmd)
// remove subcomment to remove custom analyzer
CustomAnalyzerCmd.AddCommand(removeCmd)
// list subcomment to list custom analyzer
CustomAnalyzerCmd.AddCommand(listCmd)
}

View File

@@ -0,0 +1,60 @@
/*
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 customanalyzer
import (
"fmt"
"os"
"github.com/fatih/color"
customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var details bool
var listCmd = &cobra.Command{
Use: "list",
Short: "List configured custom analyzers",
Long: "The list command displays a list of configured custom analyzers",
Run: func(cmd *cobra.Command, args []string) {
// get custom_analyzers configuration
err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
// Get list of all Custom Analyers configured
fmt.Print(color.YellowString("Active: \n"))
for _, analyzer := range configCustomAnalyzer {
fmt.Printf("> %s\n", color.GreenString(analyzer.Name))
if details {
printDetails(analyzer)
}
}
},
}
func init() {
listCmd.Flags().BoolVar(&details, "details", false, "Print custom analyzers configuration details")
}
func printDetails(analyzer customAnalyzer.CustomAnalyzerConfiguration) {
fmt.Printf(" - Url: %s\n", analyzer.Connection.Url)
fmt.Printf(" - Port: %d\n", analyzer.Connection.Port)
}

View File

@@ -0,0 +1,90 @@
/*
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 customanalyzer
import (
"os"
"strings"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
names string
)
var removeCmd = &cobra.Command{
Use: "remove",
Short: "Remove custom analyzer(s)",
Long: "The command to remove custom analyzer(s)",
PreRun: func(cmd *cobra.Command, args []string) {
// Ensure that the "names" flag is provided before running the command
_ = cmd.MarkFlagRequired("names")
},
Run: func(cmd *cobra.Command, args []string) {
if names == "" {
// Display an error message and show command help if "names" is not set
color.Red("Error: names must be set.")
_ = cmd.Help()
return
}
// Split the provided names by comma
inputCustomAnalyzers := strings.Split(names, ",")
// Load the custom analyzers from the configuration file
err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer)
if err != nil {
// Display an error message if the configuration cannot be loaded
color.Red("Error: %v", err)
os.Exit(1)
}
// Iterate over each input analyzer name
for _, inputAnalyzer := range inputCustomAnalyzers {
foundAnalyzer := false
// Search for the analyzer in the current configuration
for i, analyzer := range configCustomAnalyzer {
if analyzer.Name == inputAnalyzer {
foundAnalyzer = true
// Remove the analyzer from the configuration list
configCustomAnalyzer = append(configCustomAnalyzer[:i], configCustomAnalyzer[i+1:]...)
color.Green("%s deleted from the custom analyzer list", analyzer.Name)
break
}
}
if !foundAnalyzer {
// Display an error if the analyzer is not found in the configuration
color.Red("Error: %s does not exist in configuration file. Please use k8sgpt custom-analyzer add.", inputAnalyzer)
os.Exit(1)
}
}
// Save the updated configuration back to the file
viper.Set("custom_analyzers", configCustomAnalyzer)
if err := viper.WriteConfig(); err != nil {
// Display an error if the configuration cannot be written
color.Red("Error writing config file: %s", err.Error())
os.Exit(1)
}
},
}
func init() {
// add flag for names
removeCmd.Flags().StringVarP(&names, "names", "n", "", "Custom analyzers to remove (separated by a comma)")
}

113
cmd/dump/dump.go Normal file
View File

@@ -0,0 +1,113 @@
/*
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 dump
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/apimachinery/pkg/version"
)
type K8sGPTInfo struct {
Version string
Commit string
Date string
}
type DumpOut struct {
AIConfiguration ai.AIConfiguration
ActiveFilters []string
KubenetesServerVersion *version.Info
K8sGPTInfo K8sGPTInfo
}
var DumpCmd = &cobra.Command{
Use: "dump",
Short: "Creates a dumpfile for debugging issues with K8sGPT",
Long: `The dump command will create a dump.*.json which will contain K8sGPT non-sensitive configuration information.`,
Run: func(cmd *cobra.Command, args []string) {
// Fetch the configuration object(s)
// get ai configuration
var configAI ai.AIConfiguration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
var newProvider []ai.AIProvider
for _, config := range configAI.Providers {
// we blank out the custom headers for data protection reasons
config.CustomHeaders = make([]http.Header, 0)
// blank out the password
if len(config.Password) > 4 {
config.Password = config.Password[:4] + "***"
} else {
// If the password is shorter than 4 characters
config.Password = "***"
}
newProvider = append(newProvider, config)
}
configAI.Providers = newProvider
activeFilters := viper.GetStringSlice("active_filters")
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
v, err := client.Client.Discovery().ServerVersion()
if err != nil {
color.Yellow("Could not find kubernetes server version")
}
var dumpOut DumpOut = DumpOut{
AIConfiguration: configAI,
ActiveFilters: activeFilters,
KubenetesServerVersion: v,
K8sGPTInfo: K8sGPTInfo{
Version: viper.GetString("Version"),
Commit: viper.GetString("Commit"),
Date: viper.GetString("Date"),
},
}
// Serialize dumpOut to JSON
jsonData, err := json.MarshalIndent(dumpOut, "", " ")
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
// Write JSON data to file
f := fmt.Sprintf("dump_%s.json", time.Now().Format("20060102150405"))
err = os.WriteFile(f, jsonData, 0644)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
color.Green("Dump created successfully: %s", f)
},
}
func init() {
}

View File

@@ -15,6 +15,7 @@ package filters
import (
"fmt"
"slices"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
@@ -40,10 +41,9 @@ var listCmd = &cobra.Command{
inactiveFilters := util.SliceDiff(availableFilters, activeFilters)
fmt.Print(color.YellowString("Active: \n"))
for _, filter := range activeFilters {
// if the filter is an integration, mark this differently
// but if the integration is inactive, remove
if util.SliceContainsString(integrationFilters, filter) {
if slices.Contains(integrationFilters, filter) {
fmt.Printf("> %s\n", color.BlueString("%s (integration)", filter))
} else {
// This strange bit of logic will loop through every integration via
@@ -60,13 +60,12 @@ var listCmd = &cobra.Command{
fmt.Print(color.YellowString("Unused: \n"))
for _, filter := range inactiveFilters {
// if the filter is an integration, mark this differently
if util.SliceContainsString(integrationFilters, filter) {
if slices.Contains(integrationFilters, filter) {
fmt.Printf("> %s\n", color.BlueString("%s (integration)", filter))
} else {
fmt.Printf("> %s\n", color.RedString(filter))
}
}
}
},
}

View File

@@ -15,15 +15,17 @@ package generate
import (
"fmt"
"os/exec"
"runtime"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"os/exec"
"runtime"
)
var (
backend string
backend string
backendType string
)
// generateCmd represents the auth command
@@ -33,7 +35,7 @@ var GenerateCmd = &cobra.Command{
Long: `Opens your browser to generate a key for your chosen backend.`,
Run: func(cmd *cobra.Command, args []string) {
backendType := viper.GetString("backend_type")
backendType = viper.GetString("backend_type")
if backendType == "" {
// Set the default backend
backend = "openai"
@@ -43,7 +45,7 @@ var GenerateCmd = &cobra.Command{
backendType = backend
}
fmt.Println("")
openbrowser("https://beta.openai.com/account/api-keys")
openbrowser("https://platform.openai.com/api-keys")
},
}
@@ -79,12 +81,12 @@ func openbrowser(url string) {
func printInstructions(isGui bool, backendType string) {
fmt.Println("")
if isGui {
color.Green("Opening: https://beta.openai.com/account/api-keys to generate a key for %s", backendType)
color.Green("Opening: https://platform.openai.com/api-keys to generate a key for %s", backendType)
fmt.Println("")
} else {
color.Green("Please open: https://beta.openai.com/account/api-keys to generate a key for %s", backendType)
color.Green("Please open: https://platform.openai.com/api-keys to generate a key for %s", backendType)
fmt.Println("")
}
color.Green("Please copy the generated key and run `k8sgpt auth` to add it to your config file")
color.Green("Please copy the generated key and run `k8sgpt auth add` to add it to your config file")
fmt.Println("")
}

View File

@@ -21,9 +21,7 @@ import (
"github.com/spf13/viper"
)
var (
skipInstall bool
)
var skipInstall bool
// activateCmd represents the activate command
var activateCmd = &cobra.Command{
@@ -56,5 +54,4 @@ var activateCmd = &cobra.Command{
func init() {
IntegrationCmd.AddCommand(activateCmd)
activateCmd.Flags().BoolVarP(&skipInstall, "no-install", "s", false, "Only activate the integration filter without installing the filter (for example, if that filter plugin is already deployed in cluster, we do not need to re-install it again)")
}

View File

@@ -22,6 +22,8 @@ import (
"github.com/k8sgpt-ai/k8sgpt/cmd/analyze"
"github.com/k8sgpt-ai/k8sgpt/cmd/auth"
"github.com/k8sgpt-ai/k8sgpt/cmd/cache"
customanalyzer "github.com/k8sgpt-ai/k8sgpt/cmd/customAnalyzer"
"github.com/k8sgpt-ai/k8sgpt/cmd/dump"
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
"github.com/k8sgpt-ai/k8sgpt/cmd/integration"
@@ -56,6 +58,9 @@ func Execute(v string, c string, d string) {
Version = v
Commit = c
Date = d
viper.Set("Version", Version)
viper.Set("Commit", Commit)
viper.Set("Date", Date)
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
@@ -69,11 +74,13 @@ func init() {
rootCmd.AddCommand(auth.AuthCmd)
rootCmd.AddCommand(analyze.AnalyzeCmd)
rootCmd.AddCommand(dump.DumpCmd)
rootCmd.AddCommand(filters.FiltersCmd)
rootCmd.AddCommand(generate.GenerateCmd)
rootCmd.AddCommand(integration.IntegrationCmd)
rootCmd.AddCommand(serve.ServeCmd)
rootCmd.AddCommand(cache.CacheCmd)
rootCmd.AddCommand(customanalyzer.CustomAnalyzerCmd)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", fmt.Sprintf("Default config file (%s/k8sgpt/k8sgpt.yaml)", xdg.ConfigHome))
rootCmd.PersistentFlags().StringVar(&kubecontext, "kubecontext", "", "Kubernetes context to use. Only required if out-of-cluster.")
rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")

View File

@@ -17,9 +17,10 @@ import (
"os"
"strconv"
k8sgptserver "github.com/k8sgpt-ai/k8sgpt/pkg/server"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
k8sgptserver "github.com/k8sgpt-ai/k8sgpt/pkg/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"
@@ -27,12 +28,16 @@ import (
const (
defaultTemperature float32 = 0.7
defaultTopP float32 = 1.0
defaultTopK int32 = 50
defaultMaxTokens int = 2048
)
var (
port string
metricsPort string
backend string
enableHttp bool
)
var ServeCmd = &cobra.Command{
@@ -66,23 +71,74 @@ var ServeCmd = &cobra.Command{
}
return float32(temperature)
}
topP := func() float32 {
env := os.Getenv("K8SGPT_TOP_P")
if env == "" {
return defaultTopP
}
topP, err := strconv.ParseFloat(env, 32)
if err != nil {
color.Red("Unable to convert topP value: %v", err)
os.Exit(1)
}
if topP > 1.0 || topP < 0.0 {
color.Red("Error: topP ranges from 0 to 1.")
os.Exit(1)
}
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)
}
maxTokens := func() int {
env := os.Getenv("K8SGPT_MAX_TOKENS")
if env == "" {
return defaultMaxTokens
}
maxTokens, err := strconv.ParseInt(env, 10, 32)
if err != nil {
color.Red("Unable to convert maxTokens value: %v", err)
os.Exit(1)
}
return int(maxTokens)
}
// Check for env injection
backend = os.Getenv("K8SGPT_BACKEND")
password := os.Getenv("K8SGPT_PASSWORD")
model := os.Getenv("K8SGPT_MODEL")
baseURL := os.Getenv("K8SGPT_BASEURL")
engine := os.Getenv("K8SGPT_ENGINE")
proxyEndpoint := os.Getenv("K8SGPT_PROXY_ENDPOINT")
providerId := os.Getenv("K8SGPT_PROVIDER_ID")
// If the envs are set, allocate in place to the aiProvider
// else exit with error
envIsSet := backend != "" || password != "" || model != ""
if envIsSet {
aiProvider = &ai.AIProvider{
Name: backend,
Password: password,
Model: model,
BaseURL: baseURL,
Engine: engine,
Temperature: temperature(),
Name: backend,
Password: password,
Model: model,
BaseURL: baseURL,
Engine: engine,
ProxyEndpoint: proxyEndpoint,
ProviderId: providerId,
Temperature: temperature(),
TopP: topP(),
TopK: topK(),
MaxTokens: maxTokens(),
}
configAI.Providers = append(configAI.Providers, *aiProvider)
@@ -110,7 +166,7 @@ var ServeCmd = &cobra.Command{
}
}
if aiProvider.Name == "" {
if aiProvider == nil || aiProvider.Name == "" {
color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", backend)
os.Exit(1)
}
@@ -120,12 +176,18 @@ var ServeCmd = &cobra.Command{
color.Red("failed to create logger: %v", err)
os.Exit(1)
}
defer logger.Sync()
defer func() {
if err := logger.Sync(); err != nil {
color.Red("failed to sync logger: %v", err)
os.Exit(1)
}
}()
server := k8sgptserver.Config{
Backend: aiProvider.Name,
Port: port,
MetricsPort: metricsPort,
EnableHttp: enableHttp,
Token: aiProvider.Password,
Logger: logger,
}
@@ -153,4 +215,5 @@ func init() {
ServeCmd.Flags().StringVarP(&port, "port", "p", "8080", "Port to run the server on")
ServeCmd.Flags().StringVarP(&metricsPort, "metrics-port", "", "8081", "Port to run the metrics-server on")
ServeCmd.Flags().StringVarP(&backend, "backend", "b", "openai", "Backend AI provider")
ServeCmd.Flags().BoolVarP(&enableHttp, "http", "", false, "Enable REST/http using gppc-gateway")
}

View File

@@ -9,7 +9,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM golang:1.20.4-alpine3.16 AS builder
FROM golang:1.23-alpine3.19 AS builder
ENV CGO_ENABLED=0
ARG VERSION
@@ -36,4 +36,4 @@ WORKDIR /
COPY --from=builder /workspace/k8sgpt .
USER 65532:65532
ENTRYPOINT ["/k8sgpt"]
ENTRYPOINT ["/k8sgpt"]

371
go.mod
View File

@@ -1,137 +1,259 @@
module github.com/k8sgpt-ai/k8sgpt
go 1.20
go 1.23.3
require (
github.com/aquasecurity/trivy-operator v0.16.4
github.com/fatih/color v1.16.0
github.com/magiconair/properties v1.8.7
github.com/mittwald/go-helm-client v0.12.4
github.com/sashabaranov/go-openai v1.17.8
github.com/schollz/progressbar/v3 v3.14.1
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.17.0
github.com/stretchr/testify v1.8.4
golang.org/x/term v0.14.0
helm.sh/helm/v3 v3.13.2
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
github.com/aquasecurity/trivy-operator v0.22.0
github.com/fatih/color v1.18.0
github.com/kedacore/keda/v2 v2.16.0
github.com/magiconair/properties v1.8.9
github.com/mittwald/go-helm-client v0.12.14
github.com/ollama/ollama v0.5.1
github.com/sashabaranov/go-openai v1.36.0
github.com/schollz/progressbar/v3 v3.17.1
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
golang.org/x/term v0.27.0
helm.sh/helm/v3 v3.16.3
k8s.io/api v0.31.3
k8s.io/apimachinery v0.31.3
k8s.io/client-go v0.31.3
k8s.io/kubectl v0.31.1 // indirect
)
require github.com/adrg/xdg v0.4.0
require github.com/adrg/xdg v0.5.3
require (
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20231116211251-9f5041346631.2
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20231116211251-9f5041346631.4
cloud.google.com/go/storage v1.35.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
github.com/aws/aws-sdk-go v1.48.3
github.com/cohere-ai/cohere-go v0.2.0
buf.build/gen/go/interplex-ai/schemas/grpc/go v1.5.1-20241117203254-a91193b62179.1
buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go v1.35.2-20241117203254-a91193b62179.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.24.0-20241118152629-1379a5a1889d.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.5.1-20241118152629-1379a5a1889d.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.35.2-20241118152629-1379a5a1889d.1
cloud.google.com/go/storage v1.48.0
cloud.google.com/go/vertexai v0.13.2
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0
github.com/IBM/watsonx-go v1.0.1
github.com/aws/aws-sdk-go v1.55.6
github.com/cohere-ai/cohere-go/v2 v2.12.2
github.com/go-logr/zapr v1.3.0
github.com/google/generative-ai-go v0.19.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0
github.com/hupe1980/go-huggingface v0.0.15
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.4
github.com/olekukonko/tablewriter v0.0.5
sigs.k8s.io/controller-runtime v0.16.3
sigs.k8s.io/gateway-api v1.0.0
google.golang.org/api v0.151.0
github.com/oracle/oci-go-sdk/v65 v65.79.0
github.com/prometheus/prometheus v0.300.1
github.com/pterm/pterm v0.12.80
google.golang.org/api v0.210.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
sigs.k8s.io/controller-runtime v0.19.3
sigs.k8s.io/gateway-api v1.2.1
)
require (
cloud.google.com/go v0.110.8 // indirect
cloud.google.com/go/compute v1.23.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
github.com/Microsoft/hcsshim v0.11.0 // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/cohere-ai/tokenizer v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
cel.dev/expr v0.16.1 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/ai v0.8.0 // indirect
cloud.google.com/go/aiplatform v1.69.0 // indirect
cloud.google.com/go/auth v0.11.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
cloud.google.com/go/iam v1.2.2 // indirect
cloud.google.com/go/longrunning v0.6.2 // indirect
cloud.google.com/go/monitoring v1.21.2 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.3 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.4 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d // indirect
github.com/aquasecurity/trivy-checks v0.13.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 // indirect
github.com/aws/smithy-go v1.22.0 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/errdefs v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane v0.13.0 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/expr-lang/expr v1.16.9 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-git/go-git/v5 v5.12.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/gofrs/flock v0.12.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.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.7.5 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl/v2 v2.20.1 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/liamg/iamgo v0.0.9 // indirect
github.com/liamg/jfather v0.0.7 // indirect
github.com/liamg/memoryfs v1.6.0 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac // indirect
github.com/masahiro331/go-ext4-filesystem v0.0.0-20231208112839-4339555a0cd4 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/moby/buildkit v0.13.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // 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/open-policy-agent/opa v0.65.0 // indirect
github.com/owenrumney/squealer v1.2.2 // indirect
github.com/package-url/packageurl-go v0.1.3 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
github.com/zclconf/go-cty-yaml v1.0.3 // indirect
go.opencensus.io v0.24.0 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/tools v0.26.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
knative.dev/pkg v0.0.0-20241026180704-25f6002b00f3 // indirect
mvdan.cc/sh/v3 v3.8.0 // indirect
)
require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // 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
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/aquasecurity/defsec v0.93.1 // indirect
github.com/aquasecurity/go-dep-parser v0.0.0-20230830122616-841bc0f812c7 // indirect
github.com/aquasecurity/table v1.8.0 // indirect
github.com/aquasecurity/tml v0.6.1 // indirect
github.com/aquasecurity/trivy v0.45.1 // indirect
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 // indirect
github.com/aquasecurity/trivy v0.53.0 // indirect
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.6 // 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.23 // indirect
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v24.0.6+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/cli v26.1.4+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v27.3.1+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.4.2 // 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.2.4 // 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.3 // 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.19.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/google/uuid v1.6.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.0 // indirect
github.com/klauspost/compress v1.17.10 // 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
@@ -140,82 +262,77 @@ require (
github.com/masahiro331/go-xfs-filesystem v0.0.0-20230608043311-a335f4599b70 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/spdystream v0.4.0 // indirect
github.com/moby/term v0.5.0 // indirect
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.3 // 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.17.0
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/prometheus/client_golang v1.20.5
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.60.1 // 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.7.0 // 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/samber/lo v1.39.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spdx/tools-golang v0.5.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
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.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
go.opentelemetry.io/otel v1.31.0 // indirect
go.opentelemetry.io/otel/trace v1.31.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0 // indirect
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
golang.org/x/net v0.32.0
golang.org/x/oauth2 v0.24.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/grpc v1.68.1
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.28.3 // indirect
k8s.io/apiserver v0.28.3 // indirect
k8s.io/cli-runtime v0.28.4 // indirect
k8s.io/component-base v0.28.4 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
oras.land/oras-go v1.2.4 // indirect
k8s.io/apiextensions-apiserver v0.31.3
k8s.io/apiserver v0.31.3 // indirect
k8s.io/cli-runtime v0.31.1 // indirect
k8s.io/component-base v0.31.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241009091222-67ed5848f094 // indirect
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
sigs.k8s.io/kustomize/api v0.18.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.18.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.4.0+incompatible

1176
go.sum

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -2,33 +2,26 @@ package ai
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/bedrockruntime"
)
const amazonbedrockAIClientName = "amazonbedrock"
// AmazonBedRockClient represents the client for interacting with the Amazon Bedrock service.
type AmazonBedRockClient struct {
nopCloser
client *bedrockruntime.BedrockRuntime
language string
model string
temperature float32
}
// InvokeModelResponseBody represents the response body structure from the model invocation.
type InvokeModelResponseBody struct {
Completion string `json:"completion"`
Stop_reason string `json:"stop_reason"`
topP float32
maxTokens int
}
// Amazon BedRock support region list US East (N. Virginia),US West (Oregon),Asia Pacific (Singapore),Asia Pacific (Tokyo),Europe (Frankfurt)
@@ -52,17 +45,130 @@ var BEDROCKER_SUPPORTED_REGION = []string{
}
const (
ModelAnthropicClaudeV2 = "anthropic.claude-v2"
ModelAnthropicClaudeV1 = "anthropic.claude-v1"
ModelAnthropicClaudeInstantV1 = "anthropic.claude-instant-v1"
ModelAI21Jamba15Large = "ai21.jamba-1-5-large-v1:0"
ModelAI21Jamba15Mini = "ai21.jamba-1-5-mini-v1:0"
ModelAI21JambaInstruct = "ai21.jamba-instruct-v1:0"
ModelAmazonNovaCanvas = "amazon.nova-canvas-v1:0"
ModelAmazonNovaLite = "amazon.nova-lite-v1:0"
ModelAmazonNovaMicro = "amazon.nova-micro-v1:0"
ModelAmazonNovaPro = "amazon.nova-pro-v1:0"
ModelAmazonNovaReel = "amazon.nova-reel-v1:0"
ModelAmazonRerank10 = "amazon.rerank-v1:0"
ModelAmazonTitanEmbedTextV1 = "amazon.titan-embed-text-v1"
ModelAmazonTitanImageGenV2 = "amazon.titan-image-generator-v2:0"
ModelAmazonTitanImageGenV1 = "amazon.titan-image-generator-v1"
ModelAmazonTitanMultimodal = "amazon.titan-embed-image-v1"
ModelAmazonTitanEmbedTextV2 = "amazon.titan-embed-text-v2:0"
ModelAmazonTitanTextExpress = "amazon.titan-text-express-v1"
ModelAmazonTitanTextLite = "amazon.titan-text-lite-v1"
ModelAmazonTitanTextPremier = "amazon.titan-text-premier-v1:0"
ModelAnthropicClaude3Haiku = "anthropic.claude-3-haiku-20240307-v1:0"
ModelAnthropicClaude3Opus = "anthropic.claude-3-opus-20240229-v1:0"
ModelAnthropicClaude3Sonnet = "anthropic.claude-3-sonnet-20240229-v1:0"
ModelAnthropicClaude35Haiku = "anthropic.claude-3-5-haiku-20241022-v1:0"
ModelAnthropicClaudeSonnetV3_5_V2 = "anthropic.claude-3-5-sonnet-20241022-v2:0"
ModelAnthropicClaude35Sonnet = "anthropic.claude-3-5-sonnet-20240620-v1:0"
ModelCohereCommandLight = "cohere.command-light-text-v14"
ModelCohereCommandRPlus = "cohere.command-r-plus-v1:0"
ModelCohereCommandR = "cohere.command-r-v1:0"
ModelCohereCommand = "cohere.command-text-v14"
ModelCohereEmbedEnglish = "cohere.embed-english-v3"
ModelCohereEmbedMultilingual = "cohere.embed-multilingual-v3"
ModelCohereRerank35 = "cohere.rerank-v3-5:0"
ModelLumaAIRayV2 = "luma.ray-v2:0"
ModelMetaLlama38BInstruct = "meta.llama3-8b-instruct-v1:0"
ModelMetaLlama370BInstruct = "meta.llama3-70b-instruct-v1:0"
ModelMetaLlama318BInstruct = "meta.llama3-1-8b-instruct-v1:0"
ModelMetaLlama3170BInstruct = "meta.llama3-1-70b-instruct-v1:0"
ModelMetaLlama31405BInstruct = "meta.llama3-1-405b-instruct-v1:0"
ModelMetaLlama321BInstruct = "meta.llama3-2-1b-instruct-v1:0"
ModelMetaLlama323BInstruct = "meta.llama3-2-3b-instruct-v1:0"
ModelMetaLlama3211BInstruct = "meta.llama3-2-11b-instruct-v1:0"
ModelMetaLlama3290BInstruct = "meta.llama3-2-90b-instruct-v1:0"
ModelMetaLlama3370BInstruct = "meta.llama3-3-70b-instruct-v1:0"
ModelMistral7BInstruct = "mistral.mistral-7b-instruct-v0:2"
ModelMistralLarge2402 = "mistral.mistral-large-2402-v1:0"
ModelMistralLarge2407 = "mistral.mistral-large-2407-v1:0"
ModelMistralSmall2402 = "mistral.mistral-small-2402-v1:0"
ModelMistralMixtral8x7B = "mistral.mixtral-8x7b-instruct-v0:1"
ModelStabilitySD3Large = "stability.sd3-large-v1:0"
ModelStabilitySD35Large = "stability.sd3-5-large-v1:0"
ModelStabilityImageCore10 = "stability.stable-image-core-v1:0"
ModelStabilityImageCore11 = "stability.stable-image-core-v1:1"
ModelStabilityImageUltra10 = "stability.stable-image-ultra-v1:0"
ModelStabilityImageUltra11 = "stability.stable-image-ultra-v1:1"
ModelAnthropicClaudeSonnetV3_5 = "anthropic.claude-3-5-sonnet-20240620-v1:0"
ModelAnthropicClaudeV2 = "anthropic.claude-v2"
ModelAnthropicClaudeV1 = "anthropic.claude-v1"
ModelAnthropicClaudeInstantV1 = "anthropic.claude-instant-v1"
ModelA21J2UltraV1 = "ai21.j2-ultra-v1"
ModelA21J2JumboInstruct = "ai21.j2-jumbo-instruct"
ModelAmazonTitanExpressV1 = "amazon.titan-text-express-v1"
)
var BEDROCK_MODELS = []string{
ModelAI21Jamba15Large,
ModelAI21Jamba15Mini,
ModelAI21JambaInstruct,
ModelAmazonNovaCanvas,
ModelAmazonNovaLite,
ModelAmazonNovaMicro,
ModelAmazonNovaPro,
ModelAmazonNovaReel,
ModelAmazonRerank10,
ModelAmazonTitanEmbedTextV1,
ModelAmazonTitanImageGenV2,
ModelAmazonTitanImageGenV1,
ModelAmazonTitanMultimodal,
ModelAmazonTitanEmbedTextV2,
ModelAmazonTitanTextExpress,
ModelAmazonTitanTextLite,
ModelAmazonTitanTextPremier,
ModelAnthropicClaude3Haiku,
ModelAnthropicClaude3Opus,
ModelAnthropicClaude3Sonnet,
ModelAnthropicClaude35Haiku,
ModelAnthropicClaudeSonnetV3_5_V2, // Already in your example
ModelAnthropicClaude35Sonnet,
ModelCohereCommandLight,
ModelCohereCommandRPlus,
ModelCohereCommandR,
ModelCohereCommand,
ModelCohereEmbedEnglish,
ModelCohereEmbedMultilingual,
ModelCohereRerank35,
ModelLumaAIRayV2,
ModelMetaLlama38BInstruct,
ModelMetaLlama370BInstruct,
ModelMetaLlama318BInstruct,
ModelMetaLlama3170BInstruct,
ModelMetaLlama31405BInstruct,
ModelMetaLlama321BInstruct,
ModelMetaLlama323BInstruct,
ModelMetaLlama3211BInstruct,
ModelMetaLlama3290BInstruct,
ModelMetaLlama3370BInstruct,
ModelMistral7BInstruct,
ModelMistralLarge2402,
ModelMistralLarge2407,
ModelMistralSmall2402,
ModelMistralMixtral8x7B,
ModelStabilitySD3Large,
ModelStabilitySD35Large,
ModelStabilityImageCore10,
ModelStabilityImageCore11,
ModelStabilityImageUltra10,
ModelStabilityImageUltra11,
ModelAnthropicClaudeV2,
ModelAnthropicClaudeV1,
ModelAnthropicClaudeInstantV1,
ModelA21J2UltraV1,
ModelA21J2JumboInstruct,
ModelAmazonTitanExpressV1,
}
//const TOPP = 0.9 moved to config
// GetModelOrDefault check config model
func GetModelOrDefault(model string) string {
@@ -80,6 +186,9 @@ func GetModelOrDefault(model string) string {
// GetModelOrDefault check config region
func GetRegionOrDefault(region string) string {
if os.Getenv("AWS_DEFAULT_REGION") != "" {
region = os.Getenv("AWS_DEFAULT_REGION")
}
// Check if the provided model is in the list
for _, m := range BEDROCKER_SUPPORTED_REGION {
if m == region {
@@ -91,8 +200,8 @@ func GetRegionOrDefault(region string) string {
return BEDROCK_DEFAULT_REGION
}
// Configure configures the AmazonBedRockClient with the provided configuration and language.
func (a *AmazonBedRockClient) Configure(config IAIConfig, language string) error {
// Configure configures the AmazonBedRockClient with the provided configuration.
func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
// Create a new AWS session
providerRegion := GetRegionOrDefault(config.GetProviderRegion())
@@ -107,22 +216,50 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig, language string) error
// Create a new BedrockRuntime client
a.client = bedrockruntime.New(sess)
a.language = language
a.model = GetModelOrDefault(config.GetModel())
a.temperature = config.GetTemperature()
a.topP = config.GetTopP()
a.maxTokens = config.GetMaxTokens()
return nil
}
// GetCompletion sends a request to the model for generating completion based on the provided prompt.
func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error) {
func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Prepare the input data for the model invocation
request := map[string]interface{}{
"prompt": fmt.Sprintf("\n\nHuman: %s \n\nAssistant:", prompt),
"max_tokens_to_sample": 1024,
"temperature": a.temperature,
"top_p": 0.9,
// Prepare the input data for the model invocation based on the model & the Response Body per model as well.
var request map[string]interface{}
switch a.model {
case ModelAnthropicClaudeSonnetV3_5, ModelAnthropicClaudeSonnetV3_5_V2, ModelAnthropicClaudeV2, ModelAnthropicClaudeV1, ModelAnthropicClaudeInstantV1:
request = map[string]interface{}{
"prompt": fmt.Sprintf("\n\nHuman: %s \n\nAssistant:", prompt),
"max_tokens_to_sample": a.maxTokens,
"temperature": a.temperature,
"top_p": a.topP,
}
case ModelA21J2UltraV1, ModelA21J2JumboInstruct:
request = map[string]interface{}{
"prompt": prompt,
"maxTokens": a.maxTokens,
"temperature": a.temperature,
"topP": a.topP,
}
case ModelAmazonTitanExpressV1:
request = map[string]interface{}{
"inputText": fmt.Sprintf("\n\nUser: %s", prompt),
"textGenerationConfig": map[string]interface{}{
"maxTokenCount": a.maxTokens,
"temperature": a.temperature,
"topP": a.topP,
},
}
default:
request = map[string]interface{}{
"prompt": prompt,
"maxTokens": a.maxTokens,
"temperature": a.temperature,
"topP": a.topP,
}
}
body, err := json.Marshal(request)
@@ -143,54 +280,58 @@ func (a *AmazonBedRockClient) GetCompletion(ctx context.Context, prompt string,
if err != nil {
return "", err
}
// Parse the response body
output := &InvokeModelResponseBody{}
err = json.Unmarshal(resp.Body, output)
if err != nil {
return "", err
}
return output.Completion, nil
}
// Parse generates a completion for the provided prompt using the Amazon Bedrock model.
func (a *AmazonBedRockClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
cacheKey := util.GetCacheKey(a.GetName(), a.language, inputKey)
if !cache.IsCacheDisabled() && cache.Exists(cacheKey) {
response, err := cache.Load(cacheKey)
// Response type changes as per model
switch a.model {
case ModelAnthropicClaudeSonnetV3_5, ModelAnthropicClaudeSonnetV3_5_V2, ModelAnthropicClaudeV2, ModelAnthropicClaudeV1, ModelAnthropicClaudeInstantV1:
type InvokeModelResponseBody struct {
Completion string `json:"completion"`
Stop_reason string `json:"stop_reason"`
}
output := &InvokeModelResponseBody{}
err = json.Unmarshal(resp.Body, output)
if err != nil {
return "", err
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
return "", nil
}
return string(output), nil
return output.Completion, nil
case ModelA21J2UltraV1, ModelA21J2JumboInstruct:
type Data struct {
Text string `json:"text"`
}
type Completion struct {
Data Data `json:"data"`
}
type InvokeModelResponseBody struct {
Completions []Completion `json:"completions"`
}
output := &InvokeModelResponseBody{}
err = json.Unmarshal(resp.Body, output)
if err != nil {
return "", err
}
return output.Completions[0].Data.Text, nil
case ModelAmazonTitanExpressV1:
type Result struct {
TokenCount int `json:"tokenCount"`
OutputText string `json:"outputText"`
CompletionReason string `json:"completionReason"`
}
type InvokeModelResponseBody struct {
InputTextTokenCount int `json:"inputTextTokenCount"`
Results []Result `json:"results"`
}
output := &InvokeModelResponseBody{}
err = json.Unmarshal(resp.Body, output)
if err != nil {
return "", err
}
return output.Results[0].OutputText, nil
default:
return "", fmt.Errorf("model %s not supported", a.model)
}
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
// GetName returns the name of the AmazonBedRockClient.
func (a *AmazonBedRockClient) GetName() string {
return "amazonbedrock"
return amazonbedrockAIClientName
}

View File

@@ -15,28 +15,25 @@ package ai
import (
"context"
"encoding/base64"
"fmt"
"strings"
"encoding/json"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sagemakerruntime"
)
const amazonsagemakerAIClientName = "amazonsagemaker"
type SageMakerAIClient struct {
nopCloser
client *sagemakerruntime.SageMakerRuntime
language string
model string
temperature float32
endpoint string
topP float32
topK int32
maxTokens int
}
@@ -60,10 +57,11 @@ 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"`
}
func (c *SageMakerAIClient) Configure(config IAIConfig, language string) error {
func (c *SageMakerAIClient) Configure(config IAIConfig) error {
// Create a new AWS session
sess := session.Must(session.NewSessionWithOptions(session.Options{
@@ -71,7 +69,6 @@ func (c *SageMakerAIClient) Configure(config IAIConfig, language string) error {
SharedConfigState: session.SharedConfigEnable,
}))
c.language = language
// Create a new SageMaker runtime client
c.client = sagemakerruntime.New(sess)
c.model = config.GetModel()
@@ -79,27 +76,24 @@ func (c *SageMakerAIClient) Configure(config IAIConfig, language string) error {
c.temperature = config.GetTemperature()
c.maxTokens = config.GetMaxTokens()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
return nil
}
func (c *SageMakerAIClient) GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error) {
func (c *SageMakerAIClient) GetCompletion(_ context.Context, prompt string) (string, error) {
// Create a completion request
if len(promptTmpl) == 0 {
promptTmpl = PromptMap["default"]
}
request := Request{
Inputs: [][]Message{
{
{Role: "system", Content: "DEFAULT_PROMPT"},
{Role: "user", Content: fmt.Sprintf(promptTmpl, c.language, prompt)},
{Role: "user", Content: prompt},
},
},
Parameters: Parameters{
MaxNewTokens: int(c.maxTokens),
TopP: float64(c.topP),
TopK: float64(c.topK),
Temperature: float64(c.temperature),
},
}
@@ -142,29 +136,6 @@ func (c *SageMakerAIClient) GetCompletion(ctx context.Context, prompt string, pr
return content, nil
}
func (a *SageMakerAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
// parse the text with the AI backend
inputKey := strings.Join(prompt, " ")
// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
cacheKey := util.GetCacheKey(a.GetName(), a.language, sEnc)
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
color.Red("error getting completion: %v", err)
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", err
}
return response, nil
}
func (a *SageMakerAIClient) GetName() string {
return "amazonsagemaker"
func (c *SageMakerAIClient) GetName() string {
return amazonsagemakerAIClientName
}

View File

@@ -2,31 +2,31 @@ package ai
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strings"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/fatih/color"
"net/http"
"net/url"
"github.com/sashabaranov/go-openai"
)
const azureAIClientName = "azureopenai"
type AzureAIClient struct {
nopCloser
client *openai.Client
language string
model string
temperature float32
// organizationId string
}
func (c *AzureAIClient) Configure(config IAIConfig, lang string) error {
func (c *AzureAIClient) Configure(config IAIConfig) error {
token := config.GetPassword()
baseURL := config.GetBaseURL()
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
@@ -36,25 +36,42 @@ func (c *AzureAIClient) Configure(config IAIConfig, lang string) error {
return azureModelMapping[model]
}
if proxyEndpoint != "" {
proxyUrl, err := url.Parse(proxyEndpoint)
if err != nil {
return err
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
}
defaultConfig.HTTPClient = &http.Client{
Transport: transport,
}
}
if orgId != "" {
defaultConfig.OrgID = orgId
}
client := openai.NewClientWithConfig(defaultConfig)
if client == nil {
return errors.New("error creating Azure OpenAI client")
}
c.language = lang
c.client = client
c.model = config.GetModel()
c.temperature = config.GetTemperature()
return nil
}
func (c *AzureAIClient) GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error) {
func (c *AzureAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Create a completion request
resp, err := c.client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: c.model,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: fmt.Sprintf(default_prompt, c.language, prompt),
Content: prompt,
},
},
Temperature: c.temperature,
@@ -65,42 +82,6 @@ func (c *AzureAIClient) GetCompletion(ctx context.Context, prompt string, prompt
return resp.Choices[0].Message.Content, nil
}
func (a *AzureAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
cacheKey := util.GetCacheKey(a.GetName(), a.language, inputKey)
if !cache.IsCacheDisabled() && cache.Exists(cacheKey) {
response, err := cache.Load(cacheKey)
if err != nil {
return "", err
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
return "", nil
}
return string(output), nil
}
}
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
func (a *AzureAIClient) GetName() string {
return "azureopenai"
func (c *AzureAIClient) GetName() string {
return azureAIClientName
}

View File

@@ -15,104 +15,66 @@ package ai
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strings"
"github.com/cohere-ai/cohere-go"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
api "github.com/cohere-ai/cohere-go/v2"
cohere "github.com/cohere-ai/cohere-go/v2/client"
"github.com/cohere-ai/cohere-go/v2/option"
)
const cohereAIClientName = "cohere"
type CohereClient struct {
nopCloser
client *cohere.Client
language string
model string
temperature float32
maxTokens int
}
func (c *CohereClient) Configure(config IAIConfig, language string) error {
func (c *CohereClient) Configure(config IAIConfig) error {
token := config.GetPassword()
client, err := cohere.CreateClient(token)
if err != nil {
return err
opts := []option.RequestOption{
cohere.WithToken(token),
}
baseURL := config.GetBaseURL()
if baseURL != "" {
client.BaseURL = baseURL
opts = append(opts, cohere.WithBaseURL(baseURL))
}
client := cohere.NewClient(opts...)
if client == nil {
return errors.New("error creating Cohere client")
}
c.language = language
c.client = client
c.model = config.GetModel()
c.temperature = config.GetTemperature()
c.maxTokens = config.GetMaxTokens()
return nil
}
func (c *CohereClient) GetCompletion(ctx context.Context, prompt, promptTmpl string) (string, error) {
func (c *CohereClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Create a completion request
if len(promptTmpl) == 0 {
promptTmpl = PromptMap["default"]
}
resp, err := c.client.Generate(cohere.GenerateOptions{
Model: c.model,
Prompt: fmt.Sprintf(strings.TrimSpace(promptTmpl), c.language, prompt),
MaxTokens: cohere.Uint(2048),
Temperature: cohere.Float64(float64(c.temperature)),
K: cohere.Int(0),
StopSequences: []string{},
ReturnLikelihoods: "NONE",
response, err := c.client.Chat(ctx, &api.ChatRequest{
Message: prompt,
Model: &c.model,
K: api.Int(0),
Preamble: api.String(""),
Temperature: api.Float64(float64(c.temperature)),
RawPrompting: api.Bool(false),
MaxTokens: api.Int(c.maxTokens),
})
if err != nil {
return "", err
}
return resp.Generations[0].Text, nil
return response.Text, nil
}
func (a *CohereClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
cacheKey := util.GetCacheKey(a.GetName(), a.language, inputKey)
if !cache.IsCacheDisabled() && cache.Exists(cacheKey) {
response, err := cache.Load(cacheKey)
if err != nil {
return "", err
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
return "", nil
}
return string(output), nil
}
}
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
func (a *CohereClient) GetName() string {
return "cohere"
func (c *CohereClient) GetName() string {
return cohereAIClientName
}

122
pkg/ai/googlegenai.go Normal file
View File

@@ -0,0 +1,122 @@
/*
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"
"fmt"
"github.com/fatih/color"
"github.com/google/generative-ai-go/genai"
"google.golang.org/api/option"
)
const googleAIClientName = "google"
type GoogleGenAIClient struct {
client *genai.Client
model string
temperature float32
topP float32
topK int32
maxTokens int
}
func (c *GoogleGenAIClient) Configure(config IAIConfig) error {
ctx := context.Background()
// Access your API key as an environment variable (see "Set up your API key" above)
token := config.GetPassword()
authOption := option.WithAPIKey(token)
if token[0] == '{' {
authOption = option.WithCredentialsJSON([]byte(token))
}
client, err := genai.NewClient(ctx, authOption)
if err != nil {
return fmt.Errorf("creating genai Google SDK client: %w", err)
}
c.client = client
c.model = config.GetModel()
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
c.topK = config.GetTopK()
c.maxTokens = config.GetMaxTokens()
return nil
}
func (c *GoogleGenAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Available models are at https://ai.google.dev/models e.g.gemini-pro.
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.
// Similarly, we could stream the response. For now k8sgpt does not support streaming.
resp, err := model.GenerateContent(ctx, genai.Text(prompt))
if err != nil {
return "", err
}
if len(resp.Candidates) == 0 {
if resp.PromptFeedback.BlockReason == genai.BlockReasonSafety {
for _, r := range resp.PromptFeedback.SafetyRatings {
if !r.Blocked {
continue
}
return "", fmt.Errorf("complection blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
}
}
return "", errors.New("no complection returned; unknown reason")
}
// Format output.
// TODO(bwplotka): Provider richer output in certain cases e.g. suddenly finished
// completion based on finish reasons or safety rankings.
got := resp.Candidates[0]
var output string
for _, part := range got.Content.Parts {
switch o := part.(type) {
case genai.Text:
output += string(o)
output += "\n"
default:
color.Yellow("found unsupported AI response part of type %T; ignoring", part)
}
}
if got.CitationMetadata != nil && len(got.CitationMetadata.CitationSources) > 0 {
output += "Citations:\n"
for _, source := range got.CitationMetadata.CitationSources {
// TODO(bwplotka): Give details around what exactly words could be attributed to the citation.
output += fmt.Sprintf("* %s, %s\n", *source.URI, source.License)
}
}
return output, nil
}
func (c *GoogleGenAIClient) GetName() string {
return googleAIClientName
}
func (c *GoogleGenAIClient) Close() {
if err := c.client.Close(); err != nil {
color.Red("googleai client close error: %v", err)
}
}

181
pkg/ai/googlevertexai.go Normal file
View File

@@ -0,0 +1,181 @@
/*
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"
"fmt"
"cloud.google.com/go/vertexai/genai"
"github.com/fatih/color"
)
const googleVertexAIClientName = "googlevertexai"
type GoogleVertexAIClient struct {
client *genai.Client
model string
temperature float32
topP float32
topK int32
maxTokens int
}
// Vertex AI Gemini supported Regions
// https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini
const VERTEXAI_DEFAULT_REGION = "us-central1" // default use us-east-1 region
const (
US_Central_1 = "us-central1"
US_West_4 = "us-west4"
North_America_Northeast1 = "northamerica-northeast1"
US_East_4 = "us-east4"
US_West_1 = "us-west1"
Asia_Northeast_3 = "asia-northeast3"
Asia_Southeast_1 = "asia-southeast1"
Asia_Northeast_1 = "asia-northeast1"
)
var VERTEXAI_SUPPORTED_REGION = []string{
US_Central_1,
US_West_4,
North_America_Northeast1,
US_East_4,
US_West_1,
Asia_Northeast_3,
Asia_Southeast_1,
Asia_Northeast_1,
}
const (
ModelGeminiProV1 = "gemini-1.0-pro-001"
)
var VERTEXAI_MODELS = []string{
ModelGeminiProV1,
}
// GetModelOrDefault check config model
func GetVertexAIModelOrDefault(model string) string {
// Check if the provided model is in the list
for _, m := range VERTEXAI_MODELS {
if m == model {
return model // Return the provided model
}
}
// Return the default model if the provided model is not in the list
return VERTEXAI_MODELS[0]
}
// GetModelOrDefault check config region
func GetVertexAIRegionOrDefault(region string) string {
// Check if the provided model is in the list
for _, m := range VERTEXAI_SUPPORTED_REGION {
if m == region {
return region // Return the provided model
}
}
// Return the default model if the provided model is not in the list
return VERTEXAI_DEFAULT_REGION
}
func (g *GoogleVertexAIClient) Configure(config IAIConfig) error {
ctx := context.Background()
// Currently you can access VertexAI either by being authenticated via OAuth or Bearer token so we need to consider both
projectId := config.GetProviderId()
region := GetVertexAIRegionOrDefault(config.GetProviderRegion())
client, err := genai.NewClient(ctx, projectId, region)
if err != nil {
return fmt.Errorf("creating genai Google SDK client: %w", err)
}
g.client = client
g.model = GetVertexAIModelOrDefault(config.GetModel())
g.temperature = config.GetTemperature()
g.topP = config.GetTopP()
g.topK = config.GetTopK()
g.maxTokens = config.GetMaxTokens()
return nil
}
func (g *GoogleVertexAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
model := g.client.GenerativeModel(g.model)
model.SetTemperature(g.temperature)
model.SetTopP(g.topP)
model.SetTopK(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.
// Similarly, we could stream the response. For now k8sgpt does not support streaming.
resp, err := model.GenerateContent(ctx, genai.Text(prompt))
if err != nil {
return "", err
}
if len(resp.Candidates) == 0 {
if resp.PromptFeedback.BlockReason > 0 {
for _, r := range resp.PromptFeedback.SafetyRatings {
if !r.Blocked {
continue
}
return "", fmt.Errorf("complection blocked due to %v with probability %v", r.Category.String(), r.Probability.String())
}
}
return "", errors.New("no complection returned; unknown reason")
}
// Format output.
// TODO(bwplotka): Provider richer output in certain cases e.g. suddenly finished
// completion based on finish reasons or safety rankings.
got := resp.Candidates[0]
var output string
for _, part := range got.Content.Parts {
switch o := part.(type) {
case genai.Text:
output += string(o)
output += "\n"
default:
color.Yellow("found unsupported AI response part of type %T; ignoring", part)
}
}
if got.CitationMetadata != nil && len(got.CitationMetadata.Citations) > 0 {
output += "Citations:\n"
for _, source := range got.CitationMetadata.Citations {
// TODO(bwplotka): Give details around what exactly words could be attributed to the citation.
output += fmt.Sprintf("* %s, %s\n", source.URI, source.License)
}
}
return output, nil
}
func (g *GoogleVertexAIClient) GetName() string {
return googleVertexAIClientName
}
func (g *GoogleVertexAIClient) Close() {
if err := g.client.Close(); err != nil {
color.Red("googleai client close error: %v", err)
}
}

63
pkg/ai/huggingface.go Normal file
View File

@@ -0,0 +1,63 @@
package ai
import (
"context"
"github.com/hupe1980/go-huggingface"
"k8s.io/utils/ptr"
)
const huggingfaceAIClientName = "huggingface"
type HuggingfaceClient struct {
nopCloser
client *huggingface.InferenceClient
model string
topP float32
topK int32
temperature float32
maxTokens int
}
func (c *HuggingfaceClient) Configure(config IAIConfig) error {
token := config.GetPassword()
client := huggingface.NewInferenceClient(token)
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
} else {
c.maxTokens = config.GetMaxTokens()
}
return nil
}
func (c *HuggingfaceClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
resp, err := c.client.Conversational(ctx, &huggingface.ConversationalRequest{
Inputs: huggingface.ConverstationalInputs{
Text: prompt,
},
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,
},
Options: huggingface.Options{
WaitForModel: ptr.To[bool](true),
},
})
if err != nil {
return "", err
}
return resp.GeneratedText, nil
}
func (c *HuggingfaceClient) GetName() string { return huggingfaceAIClientName }

View File

@@ -15,8 +15,7 @@ package ai
import (
"context"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"net/http"
)
var (
@@ -24,39 +23,68 @@ var (
&OpenAIClient{},
&AzureAIClient{},
&LocalAIClient{},
&OllamaClient{},
&NoOpAIClient{},
&CohereClient{},
&AmazonBedRockClient{},
&SageMakerAIClient{},
&GoogleGenAIClient{},
&HuggingfaceClient{},
&GoogleVertexAIClient{},
&OCIGenAIClient{},
&IBMWatsonxAIClient{},
}
Backends = []string{
"openai",
"localai",
"azureopenai",
"noopai",
"cohere",
"amazonbedrock",
"amazonsagemaker",
openAIClientName,
localAIClientName,
ollamaClientName,
azureAIClientName,
cohereAIClientName,
amazonbedrockAIClientName,
amazonsagemakerAIClientName,
googleAIClientName,
noopAIClientName,
huggingfaceAIClientName,
googleVertexAIClientName,
ociClientName,
ibmWatsonxAIClientName,
}
)
// IAI is an interface all clients (representing backends) share.
type IAI interface {
Configure(config IAIConfig, language string) error
GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error)
Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error)
// Configure sets up client for given configuration. This is expected to be
// executed once per client life-time (e.g. analysis CLI command invocation).
Configure(config IAIConfig) error
// GetCompletion generates text based on prompt.
GetCompletion(ctx context.Context, prompt string) (string, error)
// GetName returns name of the backend/client.
GetName() string
// Close cleans all the resources. No other methods should be used on the
// objects after this method is invoked.
Close()
}
type nopCloser struct{}
func (nopCloser) Close() {}
type IAIConfig interface {
GetPassword() string
GetModel() string
GetBaseURL() string
GetProxyEndpoint() string
GetEndpointName() string
GetEngine() string
GetTemperature() float32
GetProviderRegion() string
GetTopP() float32
GetTopK() int32
GetMaxTokens() int
GetProviderId() string
GetCompartmentId() string
GetOrganizationId() string
GetCustomHeaders() []http.Header
}
func NewClient(provider string) IAI {
@@ -75,22 +103,33 @@ 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"`
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"`
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 {
return p.BaseURL
}
func (p *AIProvider) GetProxyEndpoint() string {
return p.ProxyEndpoint
}
func (p *AIProvider) GetEndpointName() string {
return p.EndpointName
}
@@ -99,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
}
@@ -122,7 +165,23 @@ func (p *AIProvider) GetProviderRegion() string {
return p.ProviderRegion
}
var passwordlessProviders = []string{"localai", "amazonsagemaker", "amazonbedrock"}
func (p *AIProvider) GetProviderId() string {
return p.ProviderId
}
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"}
func NeedPassword(backend string) bool {
for _, b := range passwordlessProviders {

View File

@@ -0,0 +1,67 @@
package interactive
import (
"fmt"
"strings"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
"github.com/pterm/pterm"
)
type INTERACTIVE_STATE int
const (
prompt = "Given the following context: "
)
const (
E_RUNNING INTERACTIVE_STATE = iota
E_EXITED = iota
)
type InteractionRunner struct {
config *analysis.Analysis
State chan INTERACTIVE_STATE
contextWindow []byte
}
func NewInteractionRunner(config *analysis.Analysis, contextWindow []byte) *InteractionRunner {
return &InteractionRunner{
config: config,
contextWindow: contextWindow,
State: make(chan INTERACTIVE_STATE),
}
}
func (a *InteractionRunner) StartInteraction() {
a.State <- E_RUNNING
pterm.Println("Interactive mode enabled [type exit to close.]")
for {
query := pterm.DefaultInteractiveTextInput.WithMultiLine(false)
queryString, err := query.Show()
if err != nil {
fmt.Println(err)
}
if queryString == "" {
continue
}
if strings.Contains(queryString, "exit") {
a.State <- E_EXITED
continue
}
pterm.Println()
contextWindow := fmt.Sprintf("%s %s %s", prompt, string(a.contextWindow),
queryString)
response, err := a.config.AIClient.GetCompletion(a.config.Context,
contextWindow)
if err != nil {
color.Red("Error: %v", err)
a.State <- E_EXITED
continue
}
pterm.Println(response)
}
}

View File

@@ -1,9 +1,11 @@
package ai
const localAIClientName = "localai"
type LocalAIClient struct {
OpenAIClient
}
func (a *LocalAIClient) GetName() string {
return "localai"
return localAIClientName
}

View File

@@ -15,58 +15,23 @@ package ai
import (
"context"
"encoding/base64"
"fmt"
"strings"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
)
const noopAIClientName = "noopai"
type NoOpAIClient struct {
client string
language string
model string
nopCloser
}
func (c *NoOpAIClient) Configure(config IAIConfig, language string) error {
token := config.GetPassword()
c.language = language
c.client = fmt.Sprintf("I am a noop client with the token %s ", token)
c.model = config.GetModel()
func (c *NoOpAIClient) Configure(_ IAIConfig) error {
return nil
}
func (c *NoOpAIClient) GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error) {
// Create a completion request
func (c *NoOpAIClient) GetCompletion(_ context.Context, prompt string) (string, error) {
response := "I am a noop response to the prompt " + prompt
return response, nil
}
func (a *NoOpAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
// parse the text with the AI backend
inputKey := strings.Join(prompt, " ")
// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
cacheKey := util.GetCacheKey(a.GetName(), a.language, sEnc)
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
color.Red("error getting completion: %v", err)
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
func (a *NoOpAIClient) GetName() string {
return "noopai"
func (c *NoOpAIClient) GetName() string {
return noopAIClientName
}

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

@@ -15,24 +15,23 @@ package ai
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strings"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"net/http"
"net/url"
"github.com/sashabaranov/go-openai"
"github.com/fatih/color"
)
const openAIClientName = "openai"
type OpenAIClient struct {
nopCloser
client *openai.Client
language string
model string
temperature float32
topP float32
// organizationId string
}
const (
@@ -40,47 +39,66 @@ const (
maxToken = 2048
presencePenalty = 0.0
frequencyPenalty = 0.0
topP = 1.0
)
func (c *OpenAIClient) Configure(config IAIConfig, language string) error {
func (c *OpenAIClient) Configure(config IAIConfig) error {
token := config.GetPassword()
defaultConfig := openai.DefaultConfig(token)
orgId := config.GetOrganizationId()
proxyEndpoint := config.GetProxyEndpoint()
baseURL := config.GetBaseURL()
if baseURL != "" {
defaultConfig.BaseURL = baseURL
}
transport := &http.Transport{}
if proxyEndpoint != "" {
proxyUrl, err := url.Parse(proxyEndpoint)
if err != nil {
return err
}
transport.Proxy = http.ProxyURL(proxyUrl)
}
if orgId != "" {
defaultConfig.OrgID = orgId
}
customHeaders := config.GetCustomHeaders()
defaultConfig.HTTPClient = &http.Client{
Transport: &OpenAIHeaderTransport{
Origin: transport,
Headers: customHeaders,
},
}
client := openai.NewClientWithConfig(defaultConfig)
if client == nil {
return errors.New("error creating OpenAI client")
}
c.language = language
c.client = client
c.model = config.GetModel()
c.temperature = config.GetTemperature()
c.topP = config.GetTopP()
return nil
}
func (c *OpenAIClient) GetCompletion(ctx context.Context, prompt string, promptTmpl string) (string, error) {
func (c *OpenAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Create a completion request
if len(promptTmpl) == 0 {
promptTmpl = PromptMap["default"]
}
resp, err := c.client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: c.model,
Messages: []openai.ChatCompletionMessage{
{
Role: "user",
Content: fmt.Sprintf(promptTmpl, c.language, prompt),
Content: prompt,
},
},
Temperature: c.temperature,
MaxTokens: maxToken,
PresencePenalty: presencePenalty,
FrequencyPenalty: frequencyPenalty,
TopP: topP,
TopP: c.topP,
})
if err != nil {
return "", err
@@ -88,42 +106,28 @@ func (c *OpenAIClient) GetCompletion(ctx context.Context, prompt string, promptT
return resp.Choices[0].Message.Content, nil
}
func (a *OpenAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache, promptTmpl string) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
cacheKey := util.GetCacheKey(a.GetName(), a.language, inputKey)
func (c *OpenAIClient) GetName() string {
return openAIClientName
}
if !cache.IsCacheDisabled() && cache.Exists(cacheKey) {
response, err := cache.Load(cacheKey)
if err != nil {
return "", err
}
// OpenAIHeaderTransport is an http.RoundTripper that adds the given headers to each request.
type OpenAIHeaderTransport struct {
Origin http.RoundTripper
Headers []http.Header
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
return "", nil
// 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 string(output), nil
}
}
response, err := a.GetCompletion(ctx, inputKey, promptTmpl)
if err != nil {
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
func (a *OpenAIClient) GetName() string {
return "openai"
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

@@ -8,10 +8,64 @@ const (
`
trivy_vuln_prompt = "Explain the following trivy scan result and the detail risk or root cause of the CVE ID, then provide a solution. Response in %s: %s"
trivy_conf_prompt = "Explain the following trivy scan result and the detail risk or root cause of the security check, then provide a solution."
prom_conf_prompt = `Simplify the following Prometheus error message delimited by triple dashes written in --- %s --- language; --- %s ---.
This error came when validating the Prometheus configuration file.
Provide step by step instructions to fix, with suggestions, referencing Prometheus documentation if relevant.
Write the output in the following format in no more than 300 characters:
Error: {Explain error here}
Solution: {Step by step solution here}
`
prom_relabel_prompt = `
Return your prompt in this language: %s, beginning with
The following is a list of the form:
job_name:
{Prometheus job_name}
relabel_configs:
{Prometheus relabel_configs}
kubernetes_sd_configs:
{Prometheus service discovery config}
---
%s
---
For each job_name, describe the Kubernetes service and pod labels,
namespaces, ports, and containers they match.
Return the message:
Discovered and parsed Prometheus scrape configurations.
For targets to be scraped by Prometheus, ensure they are running with
at least one of the following label sets:
Then for each job, write this format:
- Job: {job_name}
- Service Labels:
- {list of service labels}
- Pod Labels:
- {list of pod labels}
- Namespaces:
- {list of namespaces}
- Ports:
- {list of ports}
- 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{
"default": default_prompt,
"VulnerabilityReport": trivy_vuln_prompt, // for Trivy integration, the key should match `Result.Kind` in pkg/common/types.go
"ConfigAuditReport": trivy_conf_prompt,
"default": default_prompt,
"VulnerabilityReport": trivy_vuln_prompt, // for Trivy integration, the key should match `Result.Kind` in pkg/common/types.go
"ConfigAuditReport": trivy_conf_prompt,
"PrometheusConfigValidate": prom_conf_prompt,
"PrometheusConfigRelabelReport": prom_relabel_prompt,
"PolicyReport": kyverno_prompt,
"ClusterPolicyReport": kyverno_prompt,
}

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

@@ -0,0 +1,86 @@
package ai
import (
"context"
"errors"
"fmt"
wx "github.com/IBM/watsonx-go/pkg/models"
)
const ibmWatsonxAIClientName = "ibmwatsonxai"
type IBMWatsonxAIClient 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 *IBMWatsonxAIClient) 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()
apiKey := config.GetPassword()
if apiKey == "" {
return errors.New("No watsonx API key provided")
}
projectId := config.GetProviderId()
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 *IBMWatsonxAIClient) 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 *IBMWatsonxAIClient) GetName() string {
return ibmWatsonxAIClientName
}

View File

@@ -15,12 +15,12 @@ package analysis
import (
"context"
"encoding/base64"
"errors"
"fmt"
"os"
"reflect"
"strings"
"sync"
"time"
"github.com/fatih/color"
openapi_v2 "github.com/google/gnostic/openapiv2"
@@ -28,6 +28,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/analyzer"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/custom"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/schollz/progressbar/v3"
@@ -38,19 +39,25 @@ type Analysis struct {
Context context.Context
Filters []string
Client *kubernetes.Client
Language string
AIClient ai.IAI
Results []common.Result
Errors []string
Namespace string
LabelSelector string
Cache cache.ICache
Explain bool
MaxConcurrency int
AnalysisAIProvider string // The name of the AI Provider used for this analysis
WithDoc bool
WithStats bool
Stats []common.AnalysisStats
}
type AnalysisStatus string
type AnalysisErrors []string
type (
AnalysisStatus string
AnalysisErrors []string
)
const (
StateOK AnalysisStatus = "OK"
@@ -65,25 +72,75 @@ type JsonOutput struct {
Results []common.Result `json:"results"`
}
func NewAnalysis(backend string, language string, filters []string, namespace string, noCache bool, explain bool, maxConcurrency int, withDoc bool) (*Analysis, error) {
var configAI ai.AIConfiguration
err := viper.UnmarshalKey("ai", &configAI)
func NewAnalysis(
backend string,
language string,
filters []string,
namespace string,
labelSelector string,
noCache bool,
explain bool,
maxConcurrency int,
withDoc bool,
interactiveMode bool,
httpHeaders []string,
withStats bool,
) (*Analysis, error) {
// Get kubernetes client from viper.
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
return nil, fmt.Errorf("initialising kubernetes client: %w", err)
}
if len(configAI.Providers) == 0 && explain {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
// Load remote cache if it is configured.
cache, err := cache.GetCacheConfiguration()
if err != nil {
return nil, err
}
if noCache {
cache.DisableCache()
}
a := &Analysis{
Context: context.Background(),
Filters: filters,
Client: client,
Language: language,
Namespace: namespace,
LabelSelector: labelSelector,
Cache: cache,
Explain: explain,
MaxConcurrency: maxConcurrency,
WithDoc: withDoc,
WithStats: withStats,
}
if !explain {
// Return early if AI use was not requested.
return a, nil
}
var configAI ai.AIConfiguration
if err := viper.UnmarshalKey("ai", &configAI); err != nil {
return nil, err
}
if len(configAI.Providers) == 0 {
return nil, errors.New("AI provider not specified in configuration. Please run k8sgpt auth")
}
// Backend string will have high priority than a default provider
// Backend as "openai" represents the default CLI argument passed through
if configAI.DefaultProvider != "" && backend == "openai" {
// Hence, use the default provider only if the backend is not specified by the user.
if configAI.DefaultProvider != "" && backend == "" {
backend = configAI.DefaultProvider
}
if backend == "" {
backend = "openai"
}
var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if backend == provider.Name {
@@ -93,49 +150,71 @@ func NewAnalysis(backend string, language string, filters []string, namespace st
}
if aiProvider.Name == "" {
color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", backend)
return nil, errors.New("AI provider not specified in configuration")
return nil, fmt.Errorf("AI provider %s not specified in configuration. Please run k8sgpt auth", backend)
}
aiClient := ai.NewClient(aiProvider.Name)
if err := aiClient.Configure(&aiProvider, language); err != nil {
color.Red("Error: %v", err)
customHeaders := util.NewHeaders(httpHeaders)
aiProvider.CustomHeaders = customHeaders
if err := aiClient.Configure(&aiProvider); err != nil {
return nil, err
}
a.AIClient = aiClient
a.AnalysisAIProvider = aiProvider.Name
return a, nil
}
ctx := context.Background()
// Get kubernetes client from viper
func (a *Analysis) CustomAnalyzersAreAvailable() bool {
var customAnalyzers []custom.CustomAnalyzer
if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil {
return false
}
return len(customAnalyzers) > 0
}
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error initialising kubernetes client: %v", err)
return nil, err
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
}
// load remote cache if it is configured
cache, err := cache.GetCacheConfiguration()
if err != nil {
return nil, err
}
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
}
if noCache {
cache.DisableCache()
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)
}
return &Analysis{
Context: ctx,
Filters: filters,
Client: client,
AIClient: aiClient,
Namespace: namespace,
Cache: cache,
Explain: explain,
MaxConcurrency: maxConcurrency,
AnalysisAIProvider: backend,
WithDoc: withDoc,
}, nil
wg.Wait()
}
func (a *Analysis) RunAnalysis() {
@@ -158,58 +237,32 @@ 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 {
for name, analyzer := range coreAnalyzerMap {
wg.Add(1)
semaphore <- struct{}{}
go func(analyzer common.IAnalyzer, wg *sync.WaitGroup, semaphore chan struct{}) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, &wg, semaphore)
go a.executeAnalyzer(analyzer, name, analyzerConfig, semaphore, &wg, &mutex)
}
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{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, filter)
go a.executeAnalyzer(analyzer, filter, analyzerConfig, semaphore, &wg, &mutex)
} else {
a.Errors = append(a.Errors, fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter))
}
@@ -218,32 +271,57 @@ 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 {
semaphore <- struct{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
mutex.Unlock()
}
mutex.Lock()
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer, filter)
go a.executeAnalyzer(analyzer, filter, analyzerConfig, semaphore, &wg, &mutex)
}
}
wg.Wait()
}
func (a *Analysis) executeAnalyzer(analyzer common.IAnalyzer, filter string, analyzerConfig common.Analyzer, semaphore chan struct{}, wg *sync.WaitGroup, mutex *sync.Mutex) {
defer wg.Done()
var startTime time.Time
var elapsedTime time.Duration
// Start the timer
if a.WithStats {
startTime = time.Now()
}
// Run the analyzer
results, err := analyzer.Analyze(analyzerConfig)
// Measure the time taken
if a.WithStats {
elapsedTime = time.Since(startTime)
}
stat := common.AnalysisStats{
Analyzer: filter,
DurationTime: elapsedTime,
}
mutex.Lock()
defer mutex.Unlock()
if err != nil {
if a.WithStats {
a.Stats = append(a.Stats, stat)
}
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
} else {
if a.WithStats {
a.Stats = append(a.Stats, stat)
}
a.Results = append(a.Results, results...)
}
<-semaphore
}
func (a *Analysis) GetAIResults(output string, anonymize bool) error {
if len(a.Results) == 0 {
return nil
@@ -265,14 +343,14 @@ func (a *Analysis) GetAIResults(output string, anonymize bool) error {
}
texts = append(texts, failure.Text)
}
// If the resource `Kind` comes from a "integration plugin", maybe a customized prompt template will be involved.
var promptTemplate string
promptTemplate := ai.PromptMap["default"]
// If the resource `Kind` comes from an "integration plugin",
// maybe a customized prompt template will be involved.
if prompt, ok := ai.PromptMap[analysis.Kind]; ok {
promptTemplate = prompt
} else {
promptTemplate = ai.PromptMap["default"]
}
parsedText, err := a.AIClient.Parse(a.Context, texts, a.Cache, promptTemplate)
result, err := a.getAIResultForSanitizedFailures(texts, promptTemplate)
if err != nil {
// FIXME: can we avoid checking if output is json multiple times?
// maybe implement the progress bar better?
@@ -280,23 +358,22 @@ func (a *Analysis) GetAIResults(output string, anonymize bool) error {
_ = bar.Exit()
}
// Check for exhaustion
// Check for exhaustion.
if strings.Contains(err.Error(), "status code: 429") {
return fmt.Errorf("exhausted API quota for AI provider %s: %v", a.AIClient.GetName(), err)
} else {
return fmt.Errorf("failed while calling AI provider %s: %v", a.AIClient.GetName(), err)
}
return fmt.Errorf("failed while calling AI provider %s: %v", a.AIClient.GetName(), err)
}
if anonymize {
for _, failure := range analysis.Error {
for _, s := range failure.Sensitive {
parsedText = strings.ReplaceAll(parsedText, s.Masked, s.Unmasked)
result = strings.ReplaceAll(result, s.Masked, s.Unmasked)
}
}
}
analysis.Details = parsedText
analysis.Details = result
if output != "json" {
_ = bar.Add(1)
}
@@ -304,3 +381,44 @@ func (a *Analysis) GetAIResults(output string, anonymize bool) error {
}
return nil
}
func (a *Analysis) getAIResultForSanitizedFailures(texts []string, promptTmpl string) (string, error) {
inputKey := strings.Join(texts, " ")
// Check for cached data.
// TODO(bwplotka): This might depend on model too (or even other client configuration pieces), fix it in later PRs.
cacheKey := util.GetCacheKey(a.AIClient.GetName(), a.Language, inputKey)
if !a.Cache.IsCacheDisabled() && a.Cache.Exists(cacheKey) {
response, err := a.Cache.Load(cacheKey)
if err != nil {
return "", err
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err == nil {
return string(output), nil
}
color.Red("error decoding cached data; ignoring cache item: %v", err)
}
}
// Process template.
prompt := fmt.Sprintf(strings.TrimSpace(promptTmpl), a.Language, inputKey)
response, err := a.AIClient.GetCompletion(a.Context, prompt)
if err != nil {
return "", err
}
if err = a.Cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response))); err != nil {
color.Red("error storing value to cache; value won't be cached: %v", err)
}
return response, nil
}
func (a *Analysis) Close() {
if a.AIClient == nil {
return
}
a.AIClient.Close()
}

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

@@ -55,11 +55,27 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
return output, nil
}
func (a *Analysis) PrintStats() []byte {
var output strings.Builder
output.WriteString(color.YellowString("The stats mode allows for debugging and understanding the time taken by an analysis by displaying the statistics of each analyzer.\n"))
for _, stat := range a.Stats {
output.WriteString(fmt.Sprintf("- Analyzer %s took %s \n", color.YellowString(stat.Analyzer), stat.DurationTime))
}
return []byte(output.String())
}
func (a *Analysis) textOutput() ([]byte, error) {
var output strings.Builder
// Print the AI provider used for this analysis
output.WriteString(fmt.Sprintf("AI Provider: %s\n", color.YellowString(a.AnalysisAIProvider)))
// Print the AI provider used for this analysis (if explain was enabled).
if a.Explain {
output.WriteString(fmt.Sprintf("AI Provider: %s\n", color.YellowString(a.AnalysisAIProvider)))
} else {
output.WriteString(fmt.Sprintf("AI Provider: %s\n", color.YellowString("AI not used; --explain not set")))
}
if len(a.Errors) != 0 {
output.WriteString("\n")
@@ -74,8 +90,10 @@ func (a *Analysis) textOutput() ([]byte, error) {
return []byte(output.String()), nil
}
for n, result := range a.Results {
output.WriteString(fmt.Sprintf("%s %s(%s)\n", color.CyanString("%d", n),
color.YellowString(result.Name), color.CyanString(result.ParentObject)))
output.WriteString(fmt.Sprintf("%s: %s %s(%s)\n", color.CyanString("%d", n),
color.HiYellowString(result.Kind),
color.YellowString(result.Name),
color.CyanString(result.ParentObject)))
for _, err := range result.Error {
output.WriteString(fmt.Sprintf("- %s %s\n", color.RedString("Error:"), color.RedString(err.Text)))
if err.KubernetesDoc != "" {

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
}
@@ -123,15 +123,15 @@ func (analyzer CronJobAnalyzer) Analyze(a common.Analyzer) ([]common.Result, err
AnalyzerErrorsMetric.WithLabelValues(kind, cronJob.Name, cronJob.Namespace).Set(float64(len(failures)))
}
}
for key, value := range preAnalysis {
currentAnalysis := common.Result{
Kind: kind,
Name: key,
Error: value.FailureDetails,
}
a.Results = append(a.Results, currentAnalysis)
for key, value := range preAnalysis {
currentAnalysis := common.Result{
Kind: kind,
Name: key,
Error: value.FailureDetails,
}
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil

View File

@@ -15,219 +15,186 @@ package analyzer
import (
"context"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
"github.com/stretchr/testify/require"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestCronJobSuccess(t *testing.T) {
clientset := fake.NewSimpleClientset(&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "example-cronjob",
Namespace: "default",
Annotations: map[string]string{
"analysisDate": "2022-04-01",
},
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.CronJobSpec{
Schedule: "*/1 * * * *",
ConcurrencyPolicy: "Allow",
JobTemplate: batchv1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "example-container",
Image: "nginx",
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
},
},
},
},
},
})
func TestCronJobAnalyzer(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: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analyzer := CronJobAnalyzer{}
analysisResults, err := analyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 0)
}
func TestCronJobBroken(t *testing.T) {
clientset := fake.NewSimpleClientset(&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "example-cronjob",
Namespace: "default",
Annotations: map[string]string{
"analysisDate": "2022-04-01",
},
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.CronJobSpec{
Schedule: "*** * * * *",
ConcurrencyPolicy: "Allow",
JobTemplate: batchv1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "example-container",
Image: "nginx",
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
},
},
},
},
},
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analyzer := CronJobAnalyzer{}
analysisResults, err := analyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
assert.Equal(t, analysisResults[0].Name, "default/example-cronjob")
assert.Equal(t, analysisResults[0].Kind, "CronJob")
}
func TestCronJobBrokenMultipleNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "example-cronjob",
Namespace: "default",
Annotations: map[string]string{
"analysisDate": "2022-04-01",
},
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.CronJobSpec{
Schedule: "*** * * * *",
ConcurrencyPolicy: "Allow",
JobTemplate: batchv1.JobTemplateSpec{
Client: fake.NewSimpleClientset(
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ1",
// This CronJob won't be list because of namespace filtering.
Namespace: "test",
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ2",
Namespace: "default",
},
// A suspended CronJob will contribute to failures.
Spec: batchv1.CronJobSpec{
Suspend: suspend,
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ3",
Namespace: "default",
},
Spec: batchv1.CronJobSpec{
// Valid schedule
Schedule: "*/1 * * * *",
// Negative starting deadline
StartingDeadlineSeconds: invalidStartingDeadline,
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ4",
Namespace: "default",
},
Spec: batchv1.CronJobSpec{
// Invalid schedule
Schedule: "*** * * * *",
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "CJ5",
Namespace: "default",
},
Spec: batchv1.CronJobSpec{
// Valid schedule
Schedule: "*/1 * * * *",
// Positive starting deadline shouldn't be any problem.
StartingDeadlineSeconds: validStartingDeadline,
},
},
&batchv1.CronJob{
// This cronjob shouldn't contribute to any failures.
ObjectMeta: metav1.ObjectMeta{
Name: "successful-cronjob",
Namespace: "default",
Annotations: map[string]string{
"analysisDate": "2022-04-01",
},
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "example-container",
Image: "nginx",
Spec: batchv1.CronJobSpec{
Schedule: "*/1 * * * *",
ConcurrencyPolicy: "Allow",
JobTemplate: batchv1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "example-container",
Image: "nginx",
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
},
},
},
},
},
},
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "example-cronjob",
Namespace: "other-namespace",
Annotations: map[string]string{
"analysisDate": "2022-04-01",
},
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.CronJobSpec{
Schedule: "*** * * * *",
ConcurrencyPolicy: "Allow",
JobTemplate: batchv1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "example-app",
},
},
Spec: batchv1.JobSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "example-container",
Image: "nginx",
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
},
},
},
},
},
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
),
},
Context: context.Background(),
Namespace: "default",
}
analyzer := CronJobAnalyzer{}
analysisResults, err := analyzer.Analyze(config)
if err != nil {
t.Error(err)
cjAnalyzer := CronJobAnalyzer{}
results, err := cjAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
expectations := []string{
"default/CJ2",
"default/CJ3",
"default/CJ4",
}
assert.Equal(t, len(analysisResults), 1)
assert.Equal(t, analysisResults[0].Name, "default/example-cronjob")
assert.Equal(t, analysisResults[0].Kind, "CronJob")
require.Equal(t, len(expectations), len(results))
for i, result := range results {
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

@@ -1,50 +0,0 @@
/*
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"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func FetchLatestEvent(ctx context.Context, kubernetesClient *kubernetes.Client, namespace string, name string) (*v1.Event, error) {
// get the list of events
events, err := kubernetesClient.GetClient().CoreV1().Events(namespace).List(ctx,
metav1.ListOptions{
FieldSelector: "involvedObject.name=" + name,
})
if err != nil {
return nil, err
}
// find most recent event
var latestEvent *v1.Event
for _, event := range events.Items {
if latestEvent == nil {
// this is required, as a pointer to a loop variable would always yield the latest value in the range
e := event
latestEvent = &e
}
if event.LastTimestamp.After(latestEvent.LastTimestamp.Time) {
// this is required, as a pointer to a loop variable would always yield the latest value in the range
e := event
latestEvent = &e
}
}
return latestEvent, nil
}

View File

@@ -37,8 +37,13 @@ func (GatewayAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
gtwList := &gtwapi.GatewayList{}
gc := &gtwapi.GatewayClass{}
client := a.Client.CtrlClient
gtwapi.AddToScheme(client.Scheme())
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{}); err != nil {
err := gtwapi.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
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,11 +56,18 @@ 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
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(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,
&GatewayClass,
@@ -84,12 +94,18 @@ 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
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(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,
}
@@ -117,12 +133,18 @@ 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
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(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,
&GatewayClass,
@@ -159,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

@@ -35,8 +35,13 @@ func (GatewayClassAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
gcList := &gtwapi.GatewayClassList{}
client := a.Client.CtrlClient
gtwapi.AddToScheme(client.Scheme())
if err := client.List(a.Context, gcList, &ctrl.ListOptions{}); err != nil {
err := gtwapi.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
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

@@ -29,8 +29,14 @@ func TestGatewayClassAnalyzer(t *testing.T) {
GatewayClass.Status.Conditions = []metav1.Condition{BadCondition}
// Create a GatewayClassAnalyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(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).Build()
@@ -49,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,17 @@ 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
@@ -140,8 +151,10 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.HorizontalPodAutoscalers.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.HorizontalPodAutoscalers.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

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,207 @@ 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

@@ -38,14 +38,18 @@ func (HTTPRouteAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
gtw := &gtwapi.Gateway{}
service := &corev1.Service{}
client := a.Client.CtrlClient
gtwapi.AddToScheme(client.Scheme())
if err := client.List(a.Context, routeList, &ctrl.ListOptions{}); err != nil {
err := gtwapi.AddToScheme(client.Scheme())
if err != nil {
return nil, err
}
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{}
// Find all unhealthy gateway Classes
for _, route := range routeList.Items {
var failures []common.Failure

View File

@@ -104,8 +104,14 @@ func TestGWMissiningHTTRouteAnalyzer(t *testing.T) {
HTTPRoute := BuildHTTPRoute(backendName, gtwName, gtwNamespace, &svcPort, httpRouteNamespace)
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(scheme)
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&HTTPRoute,
}
@@ -156,8 +162,14 @@ func TestGWConfigSameHTTRouteAnalyzer(t *testing.T) {
Gateway := BuildRouteGateway("differentnamespace", "gatewayname", "Same")
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(scheme)
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&HTTPRoute,
&Gateway,
@@ -207,8 +219,14 @@ func TestGWConfigSelectorHTTRouteAnalyzer(t *testing.T) {
Gateway := BuildRouteGateway("default", "gatewayname", "Selector")
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(scheme)
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&HTTPRoute,
&Gateway,
@@ -259,8 +277,14 @@ func TestSvcMissingHTTRouteAnalyzer(t *testing.T) {
Gateway := BuildRouteGateway("default", "gatewayname", "Same")
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(scheme)
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&HTTPRoute,
&Gateway,
@@ -332,8 +356,14 @@ func TestSvcDifferentPortHTTRouteAnalyzer(t *testing.T) {
Gateway := BuildRouteGateway("default", "gatewayname", "Same")
// Create a Gateway Analyzer instance with the fake client
scheme := scheme.Scheme
gtwapi.Install(scheme)
apiextensionsv1.AddToScheme(scheme)
err := gtwapi.Install(scheme)
if err != nil {
t.Error(err)
}
err = apiextensionsv1.AddToScheme(scheme)
if err != nil {
t.Error(err)
}
objects := []runtime.Object{
&HTTPRoute,
&Gateway,

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
}
@@ -163,8 +163,10 @@ func (IngressAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.Ingress.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.Ingress.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

View File

@@ -15,146 +15,226 @@ package analyzer
import (
"context"
"strings"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestIngressAnalyzer(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
validIgClassName := new(string)
*validIgClassName = "valid-ingress-class"
var igRule networkingv1.IngressRule
httpRule := networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
Path: "/",
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
// This service exists.
Name: "Service1",
},
},
},
})
ingressAnalyzer := IngressAnalyzer{}
{
Path: "/test1",
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
// This service is in the test namespace
// Hence, it won't be discovered.
Name: "Service2",
},
},
},
{
Path: "/test2",
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
// This service doesn't exist.
Name: "Service3",
},
},
},
},
}
igRule.IngressRuleValue.HTTP = &httpRule
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := ingressAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
Client: fake.NewSimpleClientset(
&networkingv1.Ingress{
// Doesn't specify an ingress class.
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress1",
Namespace: "default",
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress2",
Namespace: "default",
// Specify an invalid ingress class name using annotations.
Annotations: map[string]string{
"kubernetes.io/ingress.class": "invalid-class",
},
},
},
&networkingv1.Ingress{
// Namespace filtering.
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress3",
Namespace: "test",
},
},
&networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: *validIgClassName,
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress4",
Namespace: "default",
// Specify valid ingress class name using annotations.
Annotations: map[string]string{
"kubernetes.io/ingress.class": *validIgClassName,
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "Service1",
Namespace: "default",
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
// Namespace filtering.
Name: "Service2",
Namespace: "test",
},
},
&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "Secret1",
Namespace: "default",
},
},
&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "Secret2",
Namespace: "test",
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "Ingress5",
Namespace: "default",
},
func TestIngressAnalyzerWithMultipleIngresses(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example-2",
Namespace: "default",
Annotations: map[string]string{},
},
},
)
ingressAnalyzer := IngressAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
// Specify valid ingress class name in spec.
Spec: networkingv1.IngressSpec{
IngressClassName: validIgClassName,
Rules: []networkingv1.IngressRule{
igRule,
},
TLS: []networkingv1.IngressTLS{
{
// This won't contribute to any failures.
SecretName: "Secret1",
},
{
// This secret won't be discovered because of namespace filtering.
SecretName: "Secret2",
},
{
// This secret doesn't exist.
SecretName: "Secret3",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := ingressAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
igAnalyzer := IngressAnalyzer{}
results, err := igAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
expectations := []struct {
name string
failuresCount int
}{
{
name: "default/Ingress1",
failuresCount: 1,
},
{
name: "default/Ingress2",
failuresCount: 1,
},
{
name: "default/Ingress5",
failuresCount: 4,
},
}
require.Equal(t, len(expectations), len(results))
for i, result := range results {
require.Equal(t, expectations[i].name, result.Name)
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
assert.Equal(t, len(analysisResults), 2)
}
func TestIngressAnalyzerWithoutIngressClassAnnotation(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
})
ingressAnalyzer := IngressAnalyzer{}
func TestIngressAnalyzerLabelSelectorFiltering(t *testing.T) {
validIgClassName := new(string)
*validIgClassName = "valid-ingress-class"
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
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",
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=ingress",
}
analysisResults, err := ingressAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
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)
var errorFound bool
for _, analysis := range analysisResults {
for _, err := range analysis.Error {
if strings.Contains(err.Text, "does not specify an Ingress class") {
errorFound = true
break
}
}
if errorFound {
break
}
}
if !errorFound {
t.Error("expected error 'does not specify an Ingress class' not found in analysis results")
}
}
func TestIngressAnalyzerNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "other-namespace",
Annotations: map[string]string{},
},
})
ingressAnalyzer := IngressAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := ingressAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}

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
}
@@ -49,29 +49,17 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
// Iterate through each pod
for _, pod := range list.Items {
var failures []common.Failure
podName := pod.Name
podLogOptions := v1.PodLogOptions{
TailLines: &tailLines,
}
podLogs, err := a.Client.Client.CoreV1().Pods(pod.Namespace).GetLogs(podName, &podLogOptions).DoRaw(a.Context)
if err != nil {
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Error %s from Pod %s", err.Error(), pod.Name),
Sensitive: []common.Sensitive{
{
Unmasked: pod.Name,
Masked: util.MaskString(pod.Name),
},
},
})
} else {
rawlogs := string(podLogs)
if errorPattern.MatchString(rawlogs) {
for _, c := range pod.Spec.Containers {
var failures []common.Failure
podLogOptions := v1.PodLogOptions{
TailLines: &tailLines,
Container: c.Name,
}
podLogs, err := a.Client.Client.CoreV1().Pods(pod.Namespace).GetLogs(podName, &podLogOptions).DoRaw(a.Context)
if err != nil {
failures = append(failures, common.Failure{
Text: printErrorLines(pod.Name, pod.Namespace, rawlogs, errorPattern),
Text: fmt.Sprintf("Error %s from Pod %s", err.Error(), pod.Name),
Sensitive: []common.Sensitive{
{
Unmasked: pod.Name,
@@ -79,14 +67,27 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
},
},
})
} else {
rawlogs := string(podLogs)
if errorPattern.MatchString(strings.ToLower(rawlogs)) {
failures = append(failures, common.Failure{
Text: printErrorLines(rawlogs, errorPattern),
Sensitive: []common.Sensitive{
{
Unmasked: pod.Name,
Masked: util.MaskString(pod.Name),
},
},
})
}
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = common.PreAnalysis{
FailureDetails: failures,
Pod: pod,
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s/%s", pod.Namespace, pod.Name, c.Name)] = common.PreAnalysis{
FailureDetails: failures,
Pod: pod,
}
AnalyzerErrorsMetric.WithLabelValues(kind, pod.Name, pod.Namespace).Set(float64(len(failures)))
}
AnalyzerErrorsMetric.WithLabelValues(kind, pod.Name, pod.Namespace).Set(float64(len(failures)))
}
}
for key, value := range preAnalysis {
@@ -95,20 +96,22 @@ func (LogAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Name: key,
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.Pod.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.Pod.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}
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")
// Check each line for errors and print the lines containing errors
for _, line := range logLines {
if errorPattern.MatchString(line) {
if errorPattern.MatchString(strings.ToLower(line)) {
return line
}
}

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
}
@@ -75,6 +75,11 @@ func (MutatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, erro
},
},
})
preAnalysis[fmt.Sprintf("%s/%s", webhookConfig.Namespace, webhook.Name)] = common.PreAnalysis{
MutatingWebhook: webhookConfig,
FailureDetails: failures,
}
AnalyzerErrorsMetric.WithLabelValues(kind, webhook.Name, webhookConfig.Namespace).Set(float64(len(failures)))
continue
}
@@ -146,8 +151,10 @@ func (MutatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, erro
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.MutatingWebhook.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.MutatingWebhook.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

View File

@@ -0,0 +1,215 @@
/*
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 analyzer
import (
"context"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestMutatingWebhookAnalyzer(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{
"pod": "Pod1",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service1",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"pod": "Pod1",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service2",
Namespace: "test",
},
Spec: v1.ServiceSpec{
// No such pod exists in the test namespace
Selector: map[string]string{
"pod": "Pod2",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service3",
Namespace: "test",
},
Spec: v1.ServiceSpec{
// len(service.Spec.Selector) == 0
Selector: map[string]string{},
},
},
&admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-mutating-webhook-config",
Namespace: "test",
},
Webhooks: []admissionregistrationv1.MutatingWebhook{
{
// Failure: Pointing to an inactive receiver pod
Name: "webhook1",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
{
// Failure: No active pods found in the test namespace
Name: "webhook2",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service2",
Namespace: "test",
},
},
},
{
Name: "webhook3",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service3",
Namespace: "test",
},
},
},
{
// Failure: Service doesn't exist.
Name: "webhook4",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service4-doesn't-exist",
Namespace: "test",
},
},
},
{
// Service is nil.
Name: "webhook5",
ClientConfig: admissionregistrationv1.WebhookClientConfig{},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
}
mwAnalyzer := MutatingWebhookAnalyzer{}
results, err := mwAnalyzer.Analyze(config)
require.NoError(t, err)
// The results should contain: webhook1, webhook2, and webhook4
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

@@ -136,6 +136,19 @@ func TestNetpolWithPod(t *testing.T) {
func TestNetpolNoPodsNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "policy-without-podselector-match-labels",
Namespace: "default",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{
// len(MatchLabels) == 0 should trigger a failure.
// Allowing traffic to all pods.
MatchLabels: map[string]string{},
},
},
},
&networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
@@ -203,7 +216,50 @@ func TestNetpolNoPodsNamespaceFiltering(t *testing.T) {
t.Error(err)
}
assert.Equal(t, len(results), 1)
assert.Equal(t, len(results), 2)
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)
@@ -74,8 +77,10 @@ func (NodeAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.Node.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.Node.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

View File

@@ -15,110 +15,203 @@ package analyzer
import (
"context"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
"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 TestNodeAnalyzerNodeReady(t *testing.T) {
clientset := fake.NewSimpleClientset(&v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionTrue,
Reason: "KubeletReady",
Message: "kubelet is posting ready status",
},
},
},
})
func TestNodeAnalyzer(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
}
nodeAnalyzer := NodeAnalyzer{}
var analysisResults []common.Result
analysisResults, err := nodeAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 0)
}
func TestNodeAnalyzerNodeDiskPressure(t *testing.T) {
clientset := fake.NewSimpleClientset(&v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeDiskPressure,
Status: v1.ConditionTrue,
Reason: "KubeletHasDiskPressure",
Message: "kubelet has disk pressure",
Client: fake.NewSimpleClientset(
&v1.Node{
// A node without Status Conditions shouldn't contribute to failures.
ObjectMeta: metav1.ObjectMeta{
Name: "Node1",
Namespace: "test",
},
},
},
&v1.Node{
// Nodes are not filtered using namespace.
ObjectMeta: metav1.ObjectMeta{
Name: "Node2",
Namespace: "default",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
// Won't contribute to failures.
Type: v1.NodeReady,
Status: v1.ConditionTrue,
},
{
// Will contribute to failures.
Type: v1.NodeReady,
Status: v1.ConditionFalse,
},
{
// Will contribute to failures.
Type: v1.NodeReady,
Status: v1.ConditionUnknown,
},
// Non-false statuses for the default cases contribute to failures.
{
Type: v1.NodeMemoryPressure,
Status: v1.ConditionTrue,
},
{
Type: v1.NodeDiskPressure,
Status: v1.ConditionTrue,
},
{
Type: v1.NodePIDPressure,
Status: v1.ConditionTrue,
},
{
Type: v1.NodeNetworkUnavailable,
Status: v1.ConditionTrue,
},
{
Type: v1.NodeMemoryPressure,
Status: v1.ConditionUnknown,
},
{
Type: v1.NodeDiskPressure,
Status: v1.ConditionUnknown,
},
{
Type: v1.NodePIDPressure,
Status: v1.ConditionUnknown,
},
{
Type: v1.NodeNetworkUnavailable,
Status: v1.ConditionUnknown,
},
// A cloud provider may set their own condition and/or a new status
// might be introduced. In such cases a failure is assumed and
// the code shouldn't break, although it might be a false positive.
{
Type: "UnknownNodeConditionType",
Status: "CompletelyUnknown",
},
// These won't contribute to failures.
{
Type: v1.NodeMemoryPressure,
Status: v1.ConditionFalse,
},
{
Type: v1.NodeDiskPressure,
Status: v1.ConditionFalse,
},
{
Type: v1.NodePIDPressure,
Status: v1.ConditionFalse,
},
{
Type: v1.NodeNetworkUnavailable,
Status: v1.ConditionFalse,
},
},
},
},
&v1.Node{
// A node without any failures shouldn't be present in the results.
ObjectMeta: metav1.ObjectMeta{
Name: "Node3",
Namespace: "test",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
// Won't contribute to failures.
Type: v1.NodeReady,
Status: v1.ConditionTrue,
},
},
},
},
),
},
Context: context.Background(),
Namespace: "test",
}
nAnalyzer := NodeAnalyzer{}
results, err := nAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
expectations := []struct {
name string
failuresCount int
}{
{
name: "Node2",
failuresCount: 11,
},
Context: context.Background(),
}
nodeAnalyzer := NodeAnalyzer{}
var analysisResults []common.Result
analysisResults, err := nodeAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
require.Equal(t, len(expectations), len(results))
for i, result := range results {
require.Equal(t, expectations[i].name, result.Name)
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
assert.Equal(t, len(analysisResults), 1)
}
// A cloud provider may set their own condition and/or a new status might be introduced
// In such cases a failure is assumed and the code shouldn't break, although it might be a false positive
func TestNodeAnalyzerNodeUnknownType(t *testing.T) {
clientset := fake.NewSimpleClientset(&v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: "UnknownNodeConditionType",
Status: "CompletelyUnknown",
Reason: "KubeletHasTheUnknown",
Message: "kubelet has the unknown",
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",
}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
}
nodeAnalyzer := NodeAnalyzer{}
var analysisResults []common.Result
analysisResults, err := nodeAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
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
}
@@ -50,6 +50,11 @@ func (PdbAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
for _, pdb := range list.Items {
var failures []common.Failure
// Before accessing the Conditions, check if they exist or not.
if len(pdb.Status.Conditions) == 0 {
continue
}
if pdb.Status.Conditions[0].Type == "DisruptionAllowed" && pdb.Status.Conditions[0].Status == "False" {
var doc string
if pdb.Spec.MaxUnavailable != nil {
@@ -94,8 +99,10 @@ func (PdbAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.PodDisruptionBudget.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.PodDisruptionBudget.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

208
pkg/analyzer/pdb_test.go Normal file
View File

@@ -0,0 +1,208 @@
/*
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 analyzer
import (
"context"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
policyv1 "k8s.io/api/policy/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes/fake"
)
func TestPodDisruptionBudgetAnalyzer(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "PDB1",
Namespace: "test",
},
// Status conditions are nil.
Status: policyv1.PodDisruptionBudgetStatus{
Conditions: nil,
},
},
&policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "PDB2",
Namespace: "test",
},
// Status conditions are empty.
Status: policyv1.PodDisruptionBudgetStatus{
Conditions: []metav1.Condition{},
},
},
&policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "PDB3",
Namespace: "test",
},
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: "PDB4",
Namespace: "test",
},
Status: policyv1.PodDisruptionBudgetStatus{
Conditions: []metav1.Condition{
{
Type: "DisruptionAllowed",
Status: "False",
Reason: "test reason",
},
},
},
// Match Labels Empty.
Spec: policyv1.PodDisruptionBudgetSpec{
Selector: &metav1.LabelSelector{},
},
},
),
},
Context: context.Background(),
Namespace: "test",
}
pdbAnalyzer := PdbAnalyzer{}
results, err := pdbAnalyzer.Analyze(config)
require.NoError(t, err)
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

@@ -18,6 +18,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -33,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
}
@@ -41,12 +44,12 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
for _, pod := range list.Items {
var failures []common.Failure
// Check for pending pods
if pod.Status.Phase == "Pending" {
// Check through container status to check for crashes
for _, containerStatus := range pod.Status.Conditions {
if containerStatus.Type == "PodScheduled" && containerStatus.Reason == "Unschedulable" {
if containerStatus.Type == v1.PodScheduled && containerStatus.Reason == "Unschedulable" {
if containerStatus.Message != "" {
failures = append(failures, common.Failure{
Text: containerStatus.Message,
@@ -57,52 +60,12 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
}
}
// Check through container status to check for crashes or unready
for _, containerStatus := range pod.Status.ContainerStatuses {
// Check for errors in the init containers.
failures = append(failures, analyzeContainerStatusFailures(a, pod.Status.InitContainerStatuses, pod.Name, pod.Namespace, string(pod.Status.Phase))...)
if containerStatus.State.Waiting != nil {
// Check for errors in containers.
failures = append(failures, analyzeContainerStatusFailures(a, pod.Status.ContainerStatuses, pod.Name, pod.Namespace, string(pod.Status.Phase))...)
if isErrorReason(containerStatus.State.Waiting.Reason) && containerStatus.State.Waiting.Message != "" {
failures = append(failures, common.Failure{
Text: containerStatus.State.Waiting.Message,
Sensitive: []common.Sensitive{},
})
}
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
if containerStatus.State.Waiting.Reason == "ContainerCreating" && pod.Status.Phase == "Pending" {
// parse the event log and append details
evt, err := FetchLatestEvent(a.Context, a.Client, pod.Namespace, pod.Name)
if err != nil || evt == nil {
continue
}
if evt.Reason == "FailedCreatePodSandBox" && evt.Message != "" {
failures = append(failures, common.Failure{
Text: evt.Message,
Sensitive: []common.Sensitive{},
})
}
}
} else {
// when pod is Running but its ReadinessProbe fails
if !containerStatus.Ready && pod.Status.Phase == "Running" {
// parse the event log and append details
evt, err := FetchLatestEvent(a.Context, a.Client, pod.Namespace, pod.Name)
if err != nil || evt == nil {
continue
}
if evt.Reason == "Unhealthy" && evt.Message != "" {
failures = append(failures, common.Failure{
Text: evt.Message,
Sensitive: []common.Sensitive{},
})
}
}
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = common.PreAnalysis{
Pod: pod,
@@ -119,17 +82,85 @@ func (PodAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.Pod.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.Pod.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil
}
func analyzeContainerStatusFailures(a common.Analyzer, statuses []v1.ContainerStatus, name string, namespace string, statusPhase string) []common.Failure {
var failures []common.Failure
// Check through container status to check for crashes or unready
for _, containerStatus := range statuses {
if containerStatus.State.Waiting != nil {
if containerStatus.State.Waiting.Reason == "ContainerCreating" && statusPhase == "Pending" {
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
// parse the event log and append details
evt, err := util.FetchLatestEvent(a.Context, a.Client, namespace, name)
if err != nil || evt == nil {
continue
}
if isEvtErrorReason(evt.Reason) && evt.Message != "" {
failures = append(failures, common.Failure{
Text: evt.Message,
Sensitive: []common.Sensitive{},
})
}
} else if containerStatus.State.Waiting.Reason == "CrashLoopBackOff" && containerStatus.LastTerminationState.Terminated != nil {
// This represents container that is in CrashLoopBackOff state due to conditions such as OOMKilled
failures = append(failures, common.Failure{
Text: fmt.Sprintf("the last termination reason is %s container=%s pod=%s", containerStatus.LastTerminationState.Terminated.Reason, containerStatus.Name, name),
Sensitive: []common.Sensitive{},
})
} else if isErrorReason(containerStatus.State.Waiting.Reason) && containerStatus.State.Waiting.Message != "" {
failures = append(failures, common.Failure{
Text: containerStatus.State.Waiting.Message,
Sensitive: []common.Sensitive{},
})
}
} else {
// when pod is Running but its ReadinessProbe fails
if !containerStatus.Ready && statusPhase == "Running" {
// parse the event log and append details
evt, err := util.FetchLatestEvent(a.Context, a.Client, namespace, name)
if err != nil || evt == nil {
continue
}
if evt.Reason == "Unhealthy" && evt.Message != "" {
failures = append(failures, common.Failure{
Text: evt.Message,
Sensitive: []common.Sensitive{},
})
}
}
}
}
return failures
}
func isErrorReason(reason string) bool {
failureReasons := []string{
"CrashLoopBackOff", "ImagePullBackOff", "CreateContainerConfigError", "PreCreateHookError", "CreateContainerError", "PreStartHookError", "RunContainerError", "ImageInspectError", "ErrImagePull", "ErrImageNeverPull", "InvalidImageName",
"CrashLoopBackOff", "ImagePullBackOff", "CreateContainerConfigError", "PreCreateHookError", "CreateContainerError",
"PreStartHookError", "RunContainerError", "ImageInspectError", "ErrImagePull", "ErrImageNeverPull", "InvalidImageName",
}
for _, r := range failureReasons {
if r == reason {
return true
}
}
return false
}
func isEvtErrorReason(reason string) bool {
failureReasons := []string{
"FailedCreatePodSandBox", "FailedMount",
}
for _, r := range failureReasons {

View File

@@ -15,144 +15,357 @@ package analyzer
import (
"context"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
"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 TestPodAnalyzer(t *testing.T) {
clientset := fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Status: v1.PodStatus{
Phase: v1.PodPending,
Conditions: []v1.PodCondition{
{
Type: v1.PodScheduled,
Reason: "Unschedulable",
Message: "0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.",
},
tests := []struct {
name string
config common.Analyzer
expectations []struct {
name string
failuresCount int
}
}{
{
name: "Pending pods, namespace filtering and readiness probe failure",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
Conditions: []v1.PodCondition{
{
// This condition will contribute to failures.
Type: v1.PodScheduled,
Reason: "Unschedulable",
Message: "0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.",
},
{
// This condition won't contribute to failures.
Type: v1.PodScheduled,
Reason: "Unexpected failure",
},
},
},
},
&v1.Pod{
// This pod won't be selected because of namespace filtering.
ObjectMeta: metav1.ObjectMeta{
Name: "Pod2",
Namespace: "test",
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod3",
Namespace: "default",
},
Status: v1.PodStatus{
// When pod is Running but its ReadinessProbe fails
Phase: v1.PodRunning,
ContainerStatuses: []v1.ContainerStatus{
{
Ready: false,
},
},
},
},
&v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
InvolvedObject: v1.ObjectReference{
Kind: "Pod",
Name: "Pod3",
Namespace: "default",
},
Reason: "Unhealthy",
Message: "readiness probe failed: the detail reason here ...",
Source: v1.EventSource{Component: "eventTest"},
Count: 1,
Type: v1.EventTypeWarning,
},
),
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "example2",
Context: context.Background(),
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
ContainerStatuses: []v1.ContainerStatus{
{
Name: "example2",
Ready: false,
},
expectations: []struct {
name string
failuresCount int
}{
{
name: "default/Pod1",
failuresCount: 1,
},
Conditions: []v1.PodCondition{
{
Type: v1.ContainersReady,
Reason: "ContainersNotReady",
Message: "containers with unready status: [example2]",
},
{
name: "default/Pod3",
failuresCount: 1,
},
},
},
// simulate event: 30s Warning Unhealthy pod/my-nginx-7fb4dbcf47-4ch4w Readiness probe failed: bash: xxxx: command not found
&v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
{
name: "readiness probe failure without any event",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
},
Status: v1.PodStatus{
// When pod is Running but its ReadinessProbe fails
// It won't contribute to any failures because
// there's no event present.
Phase: v1.PodRunning,
ContainerStatuses: []v1.ContainerStatus{
{
Ready: false,
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
InvolvedObject: v1.ObjectReference{
Kind: "Pod",
Name: "example2",
Namespace: "default",
UID: "differentUid",
APIVersion: "v1",
},
Reason: "Unhealthy",
Message: "readiness probe failed: the detail reason here ...",
Source: v1.EventSource{Component: "eventTest"},
Count: 1,
Type: v1.EventTypeWarning,
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
podAnalyzer := PodAnalyzer{}
var analysisResults []common.Result
analysisResults, err := podAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 2)
}
func TestPodAnalyzerNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
{
name: "Init container status state waiting",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
InitContainerStatuses: []v1.ContainerStatus{
{
Ready: true,
State: v1.ContainerState{
Running: &v1.ContainerStateRunning{
StartedAt: metav1.Now(),
},
},
},
{
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
Reason: "ContainerCreating",
},
},
},
},
},
},
&v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
InvolvedObject: v1.ObjectReference{
Kind: "Pod",
Name: "Pod1",
Namespace: "default",
},
Reason: "FailedCreatePodSandBox",
Message: "failed to create the pod sandbox ...",
Type: v1.EventTypeWarning,
},
),
},
Context: context.Background(),
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
Conditions: []v1.PodCondition{
{
Type: v1.PodScheduled,
Reason: "Unschedulable",
Message: "0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.",
},
expectations: []struct {
name string
failuresCount int
}{
{
name: "default/Pod1",
failuresCount: 1,
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "other-namespace",
Annotations: map[string]string{},
{
name: "Container status state waiting but no event reported",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
ContainerStatuses: []v1.ContainerStatus{
{
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
Reason: "ContainerCreating",
},
},
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
Conditions: []v1.PodCondition{
{
Type: v1.PodScheduled,
Reason: "Unschedulable",
Message: "0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.",
},
},
{
name: "Container status state waiting",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
},
Status: v1.PodStatus{
Phase: v1.PodPending,
ContainerStatuses: []v1.ContainerStatus{
{
Name: "Container1",
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
Reason: "ContainerCreating",
},
},
},
{
Name: "Container2",
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// This represents container that is in CrashLoopBackOff state due to conditions such as OOMKilled
Reason: "CrashLoopBackOff",
},
},
LastTerminationState: v1.ContainerState{
Terminated: &v1.ContainerStateTerminated{
Reason: "test reason",
},
},
},
{
Name: "Container3",
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// This won't contribute to failures.
Reason: "RandomReason",
Message: "This container won't be present in the failures",
},
},
},
{
Name: "Container4",
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// Valid error reason.
Reason: "PreStartHookError",
Message: "Container4 encountered PreStartHookError",
},
},
},
{
Name: "Container5",
Ready: false,
State: v1.ContainerState{
Waiting: &v1.ContainerStateWaiting{
// Valid error reason.
Reason: "CrashLoopBackOff",
Message: "Container4 encountered CrashLoopBackOff",
},
},
},
},
},
},
&v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
InvolvedObject: v1.ObjectReference{
Kind: "Pod",
Name: "Pod1",
Namespace: "default",
},
// This reason won't contribute to failures.
Reason: "RandomEvent",
Type: v1.EventTypeWarning,
},
),
},
Context: context.Background(),
Namespace: "default",
},
expectations: []struct {
name string
failuresCount int
}{
{
name: "default/Pod1",
failuresCount: 3,
},
},
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
podAnalyzer := PodAnalyzer{}
var analysisResults []common.Result
analysisResults, err := podAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
results, err := podAnalyzer.Analyze(tt.config)
require.NoError(t, err)
if tt.expectations == nil {
require.Equal(t, 0, len(results))
} else {
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
require.Equal(t, len(tt.expectations), len(results))
for i, result := range results {
require.Equal(t, tt.expectations[i].name, result.Name)
require.Equal(t, tt.expectations[i].failuresCount, len(result.Error))
}
}
})
}
assert.Equal(t, len(analysisResults), 1)
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
appsv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -32,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
}
@@ -43,10 +44,10 @@ func (PvcAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
var failures []common.Failure
// Check for empty rs
if pvc.Status.Phase == "Pending" {
if pvc.Status.Phase == appsv1.ClaimPending {
// parse the event log and append details
evt, err := FetchLatestEvent(a.Context, a.Client, pvc.Namespace, pvc.Name)
evt, err := util.FetchLatestEvent(a.Context, a.Client, pvc.Namespace, pvc.Name)
if err != nil || evt == nil {
continue
}
@@ -73,8 +74,10 @@ func (PvcAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.PersistentVolumeClaim.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.PersistentVolumeClaim.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

280
pkg/analyzer/pvc_test.go Normal file
View File

@@ -0,0 +1,280 @@
/*
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 analyzer
import (
"context"
"sort"
"testing"
"time"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestPersistentVolumeClaimAnalyzer(t *testing.T) {
tests := []struct {
name string
config common.Analyzer
expectations []string
}{
{
name: "PV1 and PVC5 report failures",
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.Event{
ObjectMeta: metav1.ObjectMeta{
// This event won't get selected.
Name: "Event2",
Namespace: "test",
},
},
&appsv1.Event{
// This is the latest event.
ObjectMeta: metav1.ObjectMeta{
Name: "Event3",
Namespace: "default",
},
LastTimestamp: metav1.Time{
Time: time.Date(2024, 4, 15, 10, 0, 0, 0, time.UTC),
},
Reason: "ProvisioningFailed",
Message: "PVC Event3 provisioning failed",
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC1",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC2",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
// Won't contribute to failures.
Phase: appsv1.ClaimBound,
},
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC3",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
// Won't contribute to failures.
Phase: appsv1.ClaimLost,
},
},
&appsv1.PersistentVolumeClaim{
// PVCs in namespace other than "default" won't be discovered.
ObjectMeta: metav1.ObjectMeta{
Name: "PVC4",
Namespace: "test",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimLost,
},
},
&appsv1.PersistentVolumeClaim{
// PVCs in namespace other than "default" won't be discovered.
ObjectMeta: metav1.ObjectMeta{
Name: "PVC5",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
expectations: []string{
"default/PVC1",
"default/PVC5",
},
},
{
name: "no event",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC1",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
},
{
name: "event other than provision failure",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
// Any reason other than ProvisioningFailed won't result in failure.
Reason: "UnknownReason",
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC1",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
},
{
name: "event without error message",
config: common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: "Event1",
Namespace: "default",
},
// Event without any error message won't result in failure.
Reason: "ProvisioningFailed",
},
&appsv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "PVC1",
Namespace: "default",
},
Status: appsv1.PersistentVolumeClaimStatus{
Phase: appsv1.ClaimPending,
},
},
),
},
Context: context.Background(),
Namespace: "default",
},
},
}
pvcAnalyzer := PvcAnalyzer{}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
results, err := pvcAnalyzer.Analyze(tt.config)
require.NoError(t, err)
if tt.expectations == nil {
require.Equal(t, 0, len(results))
} else {
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
require.Equal(t, len(tt.expectations), len(results))
for i, expectation := range tt.expectations {
require.Equal(t, expectation, results[i].Name)
}
}
})
}
}
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
}
@@ -72,8 +72,10 @@ func (ReplicaSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.ReplicaSet.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.ReplicaSet.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil

201
pkg/analyzer/rs_test.go Normal file
View File

@@ -0,0 +1,201 @@
/*
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 analyzer
import (
"context"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestReplicaSetAnalyzer(t *testing.T) {
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet1",
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",
},
},
},
},
&appsv1.ReplicaSet{
// This replicaset won't be discovered as it is not in the
// default namespace.
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet2",
Namespace: "test",
},
},
&appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet3",
Namespace: "default",
},
Status: appsv1.ReplicaSetStatus{
Replicas: 0,
Conditions: []appsv1.ReplicaSetCondition{
{
Type: appsv1.ReplicaSetReplicaFailure,
// Should not be included in the failures.
Reason: "RandomError",
},
},
},
},
&appsv1.ReplicaSet{
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet4",
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 4 condition 1",
},
{
// Should not contribute to failures.
Type: appsv1.ReplicaSetReplicaFailure,
Reason: "Unknown",
},
{
// Should not contribute to failures.
Type: appsv1.ReplicaSetReplicaFailure,
Reason: "FailedCreate",
Message: "failed to create test replica set 4 condition 3",
},
},
},
},
&appsv1.ReplicaSet{
// Replicaset without any failures.
ObjectMeta: metav1.ObjectMeta{
Name: "ReplicaSet5",
Namespace: "default",
},
Status: appsv1.ReplicaSetStatus{
Replicas: 3,
},
},
),
},
Context: context.Background(),
Namespace: "default",
}
rsAnalyzer := ReplicaSetAnalyzer{}
results, err := rsAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
expectations := []struct {
name string
failuresCount int
}{
{
name: "default/ReplicaSet1",
failuresCount: 1,
},
{
name: "default/ReplicaSet4",
failuresCount: 2,
},
}
require.Equal(t, len(expectations), len(results))
for i, result := range results {
require.Equal(t, expectations[i].name, result.Name)
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
}
@@ -98,18 +98,35 @@ func (ServiceAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
count++
pods = append(pods, addresses.TargetRef.Kind+"/"+addresses.TargetRef.Name)
}
doc := apiDoc.GetApiDocV2("subsets.notReadyAddresses")
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Service has not ready endpoints, pods: %s, expected %d", pods, count),
KubernetesDoc: doc,
Sensitive: []common.Sensitive{},
})
}
}
}
if count > 0 {
doc := apiDoc.GetApiDocV2("subsets.notReadyAddresses")
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Service has not ready endpoints, pods: %s, expected %d", pods, count),
KubernetesDoc: doc,
Sensitive: []common.Sensitive{},
})
}
}
// fetch event
events, err := a.Client.GetClient().CoreV1().Events(a.Namespace).List(a.Context,
metav1.ListOptions{
FieldSelector: "involvedObject.name=" + ep.Name,
})
if err != nil {
return nil, err
}
for _, event := range events.Items {
if event.Type != "Normal" {
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Service %s/%s has event %s", ep.Namespace, ep.Name, event.Message),
})
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", ep.Namespace, ep.Name)] = common.PreAnalysis{
Endpoint: ep,
@@ -126,8 +143,10 @@ func (ServiceAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.Endpoint.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.Endpoint.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}
return a.Results, nil

View File

@@ -15,108 +15,256 @@ package analyzer
import (
"context"
"sort"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
"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"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)
func TestServiceAnalyzer(t *testing.T) {
clientset := fake.NewSimpleClientset(&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "example",
},
}})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
Client: fake.NewSimpleClientset(
&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "Endpoint1",
Namespace: "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.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "Endpoint2",
Namespace: "test",
Annotations: map[string]string{
// Leader election record annotation key defined.
resourcelock.LeaderElectionRecordAnnotationKey: "this is okay",
},
},
// Endpoint with zero subsets.
},
&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
// This won't contribute to any failures.
Name: "non-existent-service",
Namespace: "test",
Annotations: map[string]string{},
},
// Endpoint with zero subsets.
},
&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "Service1",
Namespace: "test",
Annotations: map[string]string{},
},
// Endpoint with zero subsets.
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "Service1",
Namespace: "test",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app1": "test-app1",
"app2": "test-app2",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
// This service won't be discovered.
Name: "Service2",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app1": "test-app1",
"app2": "test-app2",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "Service3",
Namespace: "test",
},
Spec: v1.ServiceSpec{
// No Spec Selector
},
},
),
},
Context: context.Background(),
Namespace: "default",
Namespace: "test",
}
serviceAnalyzer := ServiceAnalyzer{}
analysisResults, err := serviceAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
sAnalyzer := ServiceAnalyzer{}
results, err := sAnalyzer.Analyze(config)
require.NoError(t, err)
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
expectations := []struct {
name string
failuresCount int
}{
{
name: "test/Endpoint1",
failuresCount: 1,
},
{
name: "test/Service1",
failuresCount: 2,
},
}
require.Equal(t, len(expectations), len(results))
for i, result := range results {
require.Equal(t, expectations[i].name, result.Name)
require.Equal(t, expectations[i].failuresCount, len(result.Error))
}
assert.Equal(t, len(analysisResults), 1)
}
func TestServiceAnalyzerNamespaceFiltering(t *testing.T) {
clientset := fake.NewSimpleClientset(
&v1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
Annotations: map[string]string{},
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "example",
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.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "other-namespace",
Annotations: map[string]string{},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "other-namespace",
Annotations: map[string]string{},
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"app": "example",
&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,
Client: clientSet,
},
Context: context.Background(),
Namespace: "default",
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=service",
}
serviceAnalyzer := ServiceAnalyzer{}
analysisResults, err := serviceAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
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",
}
assert.Equal(t, len(analysisResults), 1)
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

@@ -19,6 +19,7 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
@@ -41,7 +42,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
}
@@ -93,6 +94,41 @@ func (StatefulSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
}
}
}
if sts.Spec.Replicas != nil && *(sts.Spec.Replicas) != sts.Status.AvailableReplicas {
for i := int32(0); i < *(sts.Spec.Replicas); i++ {
podName := sts.Name + "-" + fmt.Sprint(i)
pod, err := a.Client.GetClient().CoreV1().Pods(sts.Namespace).Get(a.Context, podName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) && i == 0 {
evt, err := util.FetchLatestEvent(a.Context, a.Client, sts.Namespace, sts.Name)
if err != nil || evt == nil || evt.Type == "Normal" {
break
}
failures = append(failures, common.Failure{
Text: evt.Message,
Sensitive: []common.Sensitive{},
})
}
break
}
if pod.Status.Phase != "Running" {
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Statefulset pod %s in the namespace %s is not in running state.", pod.Name, pod.Namespace),
Sensitive: []common.Sensitive{
{
Unmasked: sts.Namespace,
Masked: util.MaskString(pod.Name),
},
{
Unmasked: serviceName,
Masked: util.MaskString(pod.Namespace),
},
},
})
break
}
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", sts.Namespace, sts.Name)] = common.PreAnalysis{
StatefulSet: sts,
@@ -109,8 +145,10 @@ func (StatefulSetAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.StatefulSet.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.StatefulSet.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

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,217 @@ 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)
}
func TestStatefulSetAnalyzerReplica(t *testing.T) {
replicas := int32(3)
pods := []*corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-0",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-1",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-2",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
}
clientset := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
},
Status: appsv1.StatefulSetStatus{
AvailableReplicas: 3,
},
},
pods[0], pods[1], pods[2],
)
statefulSetAnalyzer := StatefulSetAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestStatefulSetAnalyzerUnavailableReplicas(t *testing.T) {
replicas := int32(3)
clientset := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
},
Status: appsv1.StatefulSetStatus{
AvailableReplicas: 0,
},
})
statefulSetAnalyzer := StatefulSetAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}
func TestStatefulSetAnalyzerUnavailableReplicaWithPodInitialized(t *testing.T) {
replicas := int32(3)
pods := []*corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-0",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "example-1",
Namespace: "default",
},
Status: corev1.PodStatus{
Phase: corev1.PodPending,
},
},
}
clientset := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
},
Status: appsv1.StatefulSetStatus{
AvailableReplicas: 1,
},
},
pods[0], pods[1],
)
statefulSetAnalyzer := StatefulSetAnalyzer{}
config := common.Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
var errorFound bool
want := "Statefulset pod example-1 in the namespace default is not in running state."
for _, analysis := range analysisResults {
for _, got := range analysis.Error {
if want == got.Text {
errorFound = true
}
}
if errorFound {
break
}
}
if !errorFound {
t.Errorf("Error expected: '%v', not found in StatefulSet's analysis results", want)
}
}

View File

@@ -28,7 +28,7 @@ type ValidatingWebhookAnalyzer struct{}
func (ValidatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
kind := "ValidatingWebhookConfgiguration"
kind := "ValidatingWebhookConfiguration"
apiDoc := kubernetes.K8sApiReference{
Kind: kind,
ApiVersion: schema.GroupVersion{
@@ -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
}
@@ -73,6 +73,11 @@ func (ValidatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, er
},
},
})
preAnalysis[fmt.Sprintf("%s/%s", webhookConfig.Namespace, webhook.Name)] = common.PreAnalysis{
ValidatingWebhook: webhookConfig,
FailureDetails: failures,
}
AnalyzerErrorsMetric.WithLabelValues(kind, webhook.Name, webhookConfig.Namespace).Set(float64(len(failures)))
continue
}
@@ -144,8 +149,10 @@ func (ValidatingWebhookAnalyzer) Analyze(a common.Analyzer) ([]common.Result, er
Error: value.FailureDetails,
}
parent, _ := util.GetParent(a.Client, value.ValidatingWebhook.ObjectMeta)
currentAnalysis.ParentObject = parent
parent, found := util.GetParent(a.Client, value.ValidatingWebhook.ObjectMeta)
if found {
currentAnalysis.ParentObject = parent
}
a.Results = append(a.Results, currentAnalysis)
}

View File

@@ -0,0 +1,217 @@
/*
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 analyzer
import (
"context"
"testing"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/stretchr/testify/require"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestValidatingWebhookAnalyzer(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{
"pod": "Pod1",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service1",
Namespace: "default",
},
Spec: v1.ServiceSpec{
Selector: map[string]string{
"pod": "Pod1",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service2",
Namespace: "test",
},
Spec: v1.ServiceSpec{
// No such pod exists in the test namespace
Selector: map[string]string{
"pod": "Pod2",
},
},
},
&v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service3",
Namespace: "test",
},
Spec: v1.ServiceSpec{
// len(service.Spec.Selector) == 0
Selector: map[string]string{},
},
},
&admissionregistrationv1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "test-validating-webhook-config",
Namespace: "test",
},
Webhooks: []admissionregistrationv1.ValidatingWebhook{
{
// Failure: Pointing to an inactive receiver pod
Name: "webhook1",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service1",
Namespace: "default",
},
},
},
{
// Failure: No active pods found in the test namespace
Name: "webhook2",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service2",
Namespace: "test",
},
},
},
{
Name: "webhook3",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service3",
Namespace: "test",
},
},
},
{
// Failure: Service doesn't exist.
Name: "webhook4",
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "test-service4-doesn't-exist",
Namespace: "test",
},
},
},
{
// Service is nil.
Name: "webhook5",
ClientConfig: admissionregistrationv1.WebhookClientConfig{},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
}
vwAnalyzer := ValidatingWebhookAnalyzer{}
results, err := vwAnalyzer.Analyze(config)
require.NoError(t, err)
// The results should contain: webhook1, webhook2, and webhook4
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))
}

26
pkg/cache/cache.go vendored
View File

@@ -14,6 +14,7 @@ var (
&FileBasedCache{},
&GCSCache{},
&S3Cache{},
&InterplexCache{},
}
)
@@ -47,20 +48,28 @@ func ParseCacheConfiguration() (CacheProvider, error) {
return cacheInfo, nil
}
func NewCacheProvider(cacheType, bucketname, region, storageAccount, containerName, projectId string) (CacheProvider, error) {
func NewCacheProvider(cacheType, bucketname, region, endpoint, storageAccount, containerName, projectId string, insecure bool) (CacheProvider, error) {
cProvider := CacheProvider{}
switch {
case cacheType == "azure":
cProvider.Azure.ContainerName = containerName
cProvider.Azure.StorageAccount = storageAccount
cProvider.CurrentCacheType = "azure"
case cacheType == "gcs":
cProvider.GCS.BucketName = bucketname
cProvider.GCS.ProjectId = projectId
cProvider.GCS.Region = region
cProvider.CurrentCacheType = "gcs"
case cacheType == "s3":
cProvider.S3.BucketName = bucketname
cProvider.S3.Region = region
cProvider.S3.Endpoint = endpoint
cProvider.S3.InsecureSkipVerify = insecure
cProvider.CurrentCacheType = "s3"
case cacheType == "interplex":
cProvider.Interplex.ConnectionString = endpoint
cProvider.CurrentCacheType = "interplex"
default:
return CacheProvider{}, status.Error(codes.Internal, fmt.Sprintf("%s is not a valid option", cacheType))
}
@@ -81,21 +90,20 @@ func GetCacheConfiguration() (ICache, error) {
}
var cache ICache
switch {
case cacheInfo.GCS != GCSCacheConfiguration{}:
case cacheInfo.CurrentCacheType == "gcs":
cache = &GCSCache{}
case cacheInfo.Azure != AzureCacheConfiguration{}:
case cacheInfo.CurrentCacheType == "azure":
cache = &AzureCache{}
case cacheInfo.S3 != S3CacheConfiguration{}:
case cacheInfo.CurrentCacheType == "s3":
cache = &S3Cache{}
case cacheInfo.CurrentCacheType == "interplex":
cache = &InterplexCache{}
default:
cache = &FileBasedCache{}
}
cache.Configure(cacheInfo)
return cache, nil
err_config := cache.Configure(cacheInfo)
return cache, err_config
}
func AddRemoteCache(cacheInfo CacheProvider) error {

108
pkg/cache/interplex_based.go vendored Normal file
View File

@@ -0,0 +1,108 @@
package cache
import (
rpc "buf.build/gen/go/interplex-ai/schemas/grpc/go/protobuf/schema/v1/schemav1grpc"
schemav1 "buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go/protobuf/schema/v1"
"context"
"errors"
"google.golang.org/grpc"
"os"
)
var _ ICache = (*InterplexCache)(nil)
type InterplexCache struct {
configuration InterplexCacheConfiguration
client InterplexClient
cacheServiceClient rpc.CacheServiceClient
noCache bool
}
type InterplexCacheConfiguration struct {
ConnectionString string `mapstructure:"connectionString" yaml:"connectionString,omitempty"`
}
type InterplexClient struct {
}
func (c *InterplexCache) Configure(cacheInfo CacheProvider) error {
if cacheInfo.Interplex.ConnectionString == "" {
return errors.New("connection string is required")
}
c.configuration.ConnectionString = cacheInfo.Interplex.ConnectionString
return nil
}
func (c *InterplexCache) Store(key string, data string) error {
if os.Getenv("INTERPLEX_LOCAL_MODE") != "" {
c.configuration.ConnectionString = "localhost:8084"
}
conn, err := grpc.NewClient(c.configuration.ConnectionString, grpc.WithInsecure(), grpc.WithBlock())
defer conn.Close()
if err != nil {
return err
}
serviceClient := rpc.NewCacheServiceClient(conn)
c.cacheServiceClient = serviceClient
req := schemav1.SetRequest{
Key: key,
Value: data,
}
_, err = c.cacheServiceClient.Set(context.Background(), &req)
if err != nil {
return err
}
return nil
}
func (c *InterplexCache) Load(key string) (string, error) {
conn, err := grpc.NewClient(c.configuration.ConnectionString, grpc.WithInsecure(), grpc.WithBlock())
defer conn.Close()
if err != nil {
return "", err
}
serviceClient := rpc.NewCacheServiceClient(conn)
c.cacheServiceClient = serviceClient
req := schemav1.GetRequest{
Key: key,
}
resp, err := c.cacheServiceClient.Get(context.Background(), &req)
// check if response is cache error not found
if err != nil {
return "", err
}
return resp.Value, nil
}
func (InterplexCache) List() ([]CacheObjectDetails, error) {
//TODO implement me
return nil, errors.New("not implemented")
}
func (InterplexCache) Remove(key string) error {
return errors.New("not implemented")
}
func (c *InterplexCache) Exists(key string) bool {
if _, err := c.Load(key); err != nil {
return false
}
return true
}
func (c *InterplexCache) IsCacheDisabled() bool {
return c.noCache
}
func (InterplexCache) GetName() string {
//TODO implement me
return "interplex"
}
func (c *InterplexCache) DisableCache() {
c.noCache = true
}

77
pkg/cache/interplex_based_test.go vendored Normal file
View File

@@ -0,0 +1,77 @@
package cache
import (
rpc "buf.build/gen/go/interplex-ai/schemas/grpc/go/protobuf/schema/v1/schemav1grpc"
schemav1 "buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go/protobuf/schema/v1"
"context"
"errors"
"google.golang.org/grpc"
"net"
"testing"
)
func TestInterplexCache(t *testing.T) {
cache := &InterplexCache{
configuration: InterplexCacheConfiguration{
ConnectionString: "localhost:50051",
},
}
// Mock GRPC server setup
go func() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
t.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
rpc.RegisterCacheServiceServer(s, &mockCacheService{})
if err := s.Serve(lis); err != nil {
t.Fatalf("failed to serve: %v", err)
}
}()
t.Run("TestStore", func(t *testing.T) {
err := cache.Store("key1", "value1")
if err != nil {
t.Errorf("Error storing value: %v", err)
}
})
t.Run("TestLoad", func(t *testing.T) {
value, err := cache.Load("key1")
if err != nil {
t.Errorf("Error loading value: %v", err)
}
if value != "value1" {
t.Errorf("Expected value1, got %v", value)
}
})
t.Run("TestExists", func(t *testing.T) {
exists := cache.Exists("key1")
if !exists {
t.Errorf("Expected key1 to exist")
}
})
}
type mockCacheService struct {
rpc.UnimplementedCacheServiceServer
data map[string]string
}
func (m *mockCacheService) Set(ctx context.Context, req *schemav1.SetRequest) (*schemav1.SetResponse, error) {
if m.data == nil {
m.data = make(map[string]string)
}
m.data[req.Key] = req.Value
return &schemav1.SetResponse{}, nil
}
func (m *mockCacheService) Get(ctx context.Context, req *schemav1.GetRequest) (*schemav1.GetResponse, error) {
value, exists := m.data[req.Key]
if !exists {
return nil, errors.New("key not found")
}
return &schemav1.GetResponse{Value: value}, nil
}

24
pkg/cache/s3_based.go vendored
View File

@@ -2,7 +2,9 @@ package cache
import (
"bytes"
"crypto/tls"
"log"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
@@ -17,17 +19,16 @@ type S3Cache struct {
}
type S3CacheConfiguration struct {
Region string `mapstructure:"region" yaml:"region,omitempty"`
BucketName string `mapstructure:"bucketname" yaml:"bucketname,omitempty"`
Region string `mapstructure:"region" yaml:"region,omitempty"`
BucketName string `mapstructure:"bucketname" yaml:"bucketname,omitempty"`
Endpoint string `mapstructure:"endpoint" yaml:"endpoint,omitempty"`
InsecureSkipVerify bool `mapstructure:"insecure" yaml:"insecure,omitempty"`
}
func (s *S3Cache) Configure(cacheInfo CacheProvider) error {
if cacheInfo.S3.BucketName == "" {
log.Fatal("Bucket name not configured")
}
if cacheInfo.S3.Region == "" {
log.Fatal("Region not configured")
}
s.bucketName = cacheInfo.S3.BucketName
sess := session.Must(session.NewSessionWithOptions(session.Options{
@@ -36,6 +37,15 @@ func (s *S3Cache) Configure(cacheInfo CacheProvider) error {
Region: aws.String(cacheInfo.S3.Region),
},
}))
if cacheInfo.S3.Endpoint != "" {
sess.Config.Endpoint = &cacheInfo.S3.Endpoint
sess.Config.S3ForcePathStyle = aws.Bool(true)
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: cacheInfo.S3.InsecureSkipVerify},
}
customClient := &http.Client{Transport: transport}
sess.Config.HTTPClient = customClient
}
s3Client := s3.New(sess)
@@ -90,9 +100,9 @@ func (s *S3Cache) Load(key string) (string, error) {
}
buf := new(bytes.Buffer)
buf.ReadFrom(result.Body)
_, err_read := buf.ReadFrom(result.Body)
result.Body.Close()
return buf.String(), nil
return buf.String(), err_read
}
func (s *S3Cache) List() ([]CacheObjectDetails, error) {

8
pkg/cache/types.go vendored
View File

@@ -3,9 +3,11 @@ package cache
import "time"
type CacheProvider struct {
GCS GCSCacheConfiguration `mapstructucre:"gcs" yaml:"gcs,omitempty"`
Azure AzureCacheConfiguration `mapstructucre:"azure" yaml:"azure,omitempty"`
S3 S3CacheConfiguration `mapstructucre:"s3" yaml:"s3,omitempty"`
CurrentCacheType string `mapstructure:"currentCacheType" yaml:"currentCacheType"`
GCS GCSCacheConfiguration `mapstructure:"gcs" yaml:"gcs,omitempty"`
Azure AzureCacheConfiguration `mapstructure:"azure" yaml:"azure,omitempty"`
S3 S3CacheConfiguration `mapstructure:"s3" yaml:"s3,omitempty"`
Interplex InterplexCacheConfiguration `mapstructure:"interplex" yaml:"interplex,omitempty"`
}
type CacheObjectDetails struct {

View File

@@ -15,14 +15,17 @@ package common
import (
"context"
"time"
trivy "github.com/aquasecurity/trivy-operator/pkg/apis/aquasecurity/v1alpha1"
openapi_v2 "github.com/google/gnostic/openapiv2"
"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"
@@ -37,6 +40,7 @@ type Analyzer struct {
Client *kubernetes.Client
Context context.Context
Namespace string
LabelSelector string
AIClient ai.IAI
PreAnalysis map[string]PreAnalysis
Results []Result
@@ -51,7 +55,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
@@ -62,8 +66,11 @@ type PreAnalysis struct {
Gateway gtwapi.Gateway
HTTPRoute gtwapi.HTTPRoute
// Integrations
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
ScaledObject keda.ScaledObject
TrivyVulnerabilityReport trivy.VulnerabilityReport
TrivyConfigAuditReport trivy.ConfigAuditReport
KyvernoPolicyReport kyverno.PolicyReport
KyvernoClusterPolicyReport kyverno.ClusterPolicyReport
}
type Result struct {
@@ -74,6 +81,11 @@ type Result struct {
ParentObject string `json:"parentObject"`
}
type AnalysisStats struct {
Analyzer string `json:"analyzer"`
DurationTime time.Duration `json:"durationTime"`
}
type Failure struct {
Text string
KubernetesDoc string

58
pkg/custom/client.go Normal file
View File

@@ -0,0 +1,58 @@
package custom
import (
rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc"
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
"fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type Client struct {
c *grpc.ClientConn
analyzerClient rpc.CustomAnalyzerServiceClient
}
func NewClient(c Connection) (*Client, error) {
//nolint:staticcheck // Ignoring SA1019 for compatibility reasons
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", c.Url, c.Port), grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, err
}
client := rpc.NewCustomAnalyzerServiceClient(conn)
return &Client{
c: conn,
analyzerClient: client,
}, nil
}
func (cli *Client) Run() (common.Result, error) {
var result common.Result
req := &schemav1.RunRequest{}
res, err := cli.analyzerClient.Run(context.Background(), req)
if err != nil {
return result, err
}
if res.Result != nil {
// We should refactor this, because Error and Failure do not map 1:1 from K8sGPT/schema
var errorsFound []common.Failure
for _, e := range res.Result.Error {
errorsFound = append(errorsFound, common.Failure{
Text: e.Text,
// TODO: Support sensitive data
})
}
result.Name = res.Result.Name
result.Kind = res.Result.Kind
result.Details = res.Result.Details
result.ParentObject = res.Result.ParentObject
result.Error = errorsFound
}
return result, nil
}

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