Compare commits

...

65 Commits

Author SHA1 Message Date
renovate[bot]
c353aaa3a3 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
3e62c74d4e 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
f6330d0c30 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
c941e73afd 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
881fd55bc7 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
090611cb39 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
49d14e1e75 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
4e0ccc8195 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
55bdff7cf8 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
5a886c1de4 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Naveen Thangaraj
b7a14f98cb 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
9ee2fc4084 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
ca46793c0d 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Yanwei Li
ff73434d34 fix: add providerId to serve mode (#1260)
Signed-off-by: yanweili <yanweili@ibm.com>
Co-authored-by: yanweili <yanweili@ibm.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
b1528c77a0 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Guangya Liu
8e4f56ae28 fix: rename watsonxai to ibmwatsonxai (#1234)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
github-actions[bot]
461f715fb8 chore(main): release 0.3.41 (#1217)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Alex Jones
1dea6dc749 feat: adding a query mode for the schednex scheduler (#1257)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
ce5ade86b8 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Alex Jones
9e75f4aed5 Update README.md (#1253)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
69b92680d9 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
b1424e1bf0 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
awsyshah
91fafeb1f2 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
a7e1aedba9 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Aris Boutselis
fc2ea26f2e fix: typo (#1244)
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
911ef1b8cb 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
ac68e457cb 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Dominik Augustin
a0b2884f13 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
e6e1bbaf3f 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
michael12312
7110931ce5 fix: issue-1168, remove duplicate CVE (#1230)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Guangya Liu
e3e2ba6e50 fix: disable adding multiple openai provider (#1191)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Matthis <matthish29@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Guangya Liu
2fa925bded 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
3f070e4ed0 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
3c4cd623d9 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Alex Jones
803806e747 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
92ecb4dcf1 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Xuetao Song
7919d35880 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
8678ced9fa 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Matthis
f50440fb9f 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Bo Wong
fd08097761 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
R0CKSTAR
bdb0f2c26b fix: set logger for controller-runtime (#1211)
Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
renovate[bot]
c2592e3efe 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
Kay Yan
e8ee090977 fix: segmentation violation during serve (#1215)
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
github-actions[bot]
e0a7af321d chore(main): release 0.3.40 (#1202)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:34 +01:00
AlexsJones
278473bd9d chore: merge
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:30:30 +01:00
renovate[bot]
acd77c1b9a 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
cddc7402dc 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Yanwei Li
7e3d452cdb fix: add default maxToken value of watsonxai backend (#1209)
Signed-off-by: yanweili <yanweili@ibm.com>
Co-authored-by: yanweili <yanweili@ibm.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Naveen Thangaraj
91fb2126bc 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
d67ec85081 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Matthis
cc9c05dcb0 feat: custom analysis paralelism (#1203)
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Guangya Liu
b455119286 fix: auth update throw out exception (#1193)
Signed-off-by: Guangya Liu <gyliu@ibm.com>
Co-authored-by: Matthis <matthish29@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
github-actions[bot]
c67097b372 chore(main): release 0.3.39 (#1181)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
JuHyung Son
58a76a94d8 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Ronald Petty
6ef0e7dd8e 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>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
0e330a4248 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
5cfa2bc0ab 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
185a07d30a 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Alex Jones
096f43356d feat: fix the custom-analysis printing (#1195)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
Kay Yan
4e125f1692 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
0dffc5be1e 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
5a03e253fd 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
renovate[bot]
5d83d0d402 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: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
jiajia
aebe9680da fix:config nil pointer
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
jiajia
84a548a304 fix:config nil point
Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
2024-10-24 07:27:47 +01:00
78 changed files with 3280 additions and 1671 deletions

View File

@@ -33,7 +33,7 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Extract branch name
id: extract_branch
@@ -70,7 +70,7 @@ jobs:
RELEASE_REGISTRY: "localhost:5000/k8sgpt"
steps:
- name: Check out code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up Docker Buildx
id: buildx
@@ -96,7 +96,7 @@ jobs:
outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}-image.tar
- name: Upload image as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
with:
name: ${{ env.IMAGE_NAME }}-image.tar
path: /tmp/${{ env.IMAGE_NAME }}-image.tar
@@ -115,10 +115,10 @@ jobs:
contents: read # Needed for checking out the repository
steps:
- name: Check out code
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: golangci-lint
uses: reviewdog/action-golangci-lint@7708105983c614f7a2725e2172908b7709d1c3e4 # v2

View File

@@ -23,7 +23,7 @@ jobs:
# Release-please creates a PR that tracks all changes
steps:
- name: Checkout
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1
id: release
@@ -41,7 +41,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0
- name: Set up Go
@@ -49,9 +49,9 @@ jobs:
with:
go-version: '1.22'
- name: Download Syft
uses: anchore/sbom-action/download-syft@95b086ac308035dc0850b3853be5b7ab108236a8 # v0.16.1
uses: anchore/sbom-action/download-syft@8d0a6505bf28ced3e85154d13dc6af83299e13f1 # v0.17.4
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6 # v5
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
@@ -76,7 +76,7 @@ jobs:
IMAGE_NAME: k8sgpt
steps:
- name: Checkout
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
submodules: recursive
@@ -85,7 +85,7 @@ jobs:
uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3
- name: Login to GitHub Container Registry
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}
@@ -106,7 +106,7 @@ jobs:
cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }}
- name: Generate SBOM
uses: anchore/sbom-action@95b086ac308035dc0850b3853be5b7ab108236a8 # v0.16.1
uses: anchore/sbom-action@8d0a6505bf28ced3e85154d13dc6af83299e13f1 # v0.17.4
with:
image: ${{ env.IMAGE_TAG }}
artifact-name: sbom-${{ env.IMAGE_NAME }}

View File

@@ -15,7 +15,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5

View File

@@ -1 +1 @@
{".":"0.3.38"}
{".":"0.3.41"}

View File

@@ -1,5 +1,96 @@
# Changelog
## [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)

203
README.md
View File

@@ -21,13 +21,13 @@ It has SRE experience codified into its analyzers and helps to pull out the most
_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://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>
<img src="images/demo4.gif" width=650px; />
# CLI Installation
### Linux/Mac via brew
```sh
@@ -44,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.38/k8sgpt_386.rpm
sudo rpm -ivh k8sgpt_386.rpm
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/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.38/k8sgpt_amd64.rpm
sudo rpm -ivh -i k8sgpt_amd64.rpm
sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/k8sgpt_amd64.rpm
```
<!---x-release-please-end-->
</details>
@@ -65,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.38/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.38/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/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.41/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
<!---x-release-please-end-->
</details>
@@ -86,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.38/k8sgpt_386.apk
apk add k8sgpt_386.apk
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/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.38/k8sgpt_amd64.apk
apk add k8sgpt_amd64.apk
wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.41/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
@@ -131,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
@@ -193,6 +202,7 @@ k8sgpt analyze --explain --filter=Service
```
_Filter by namespace_
```
k8sgpt analyze --explain --filter=Pod --namespace=default
```
@@ -297,7 +307,10 @@ k8sgpt serve
_Analysis with serve mode_
```
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain": false}' localhost:8080 schema.v1.ServerService/Analyze
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServerAnalyzerService/Analyze
{
"status": "OK"
}
```
_Analysis with custom headers_
@@ -305,6 +318,7 @@ _Analysis with custom headers_
```
k8sgpt analyze --explain --custom-headers CustomHeaderKey:CustomHeaderValue
```
</details>
## LLM AI Backends
@@ -329,7 +343,7 @@ Unused:
> huggingface
> noopai
> googlevertexai
> watsonxai
> ibmwatsonxai
```
For detailed documentation on how to configure and use each provider see [here](https://docs.k8sgpt.ai/reference/providers/backend/).
@@ -350,21 +364,25 @@ With this option, the data is anonymized before being sent to the AI Backend. Du
<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.
```
@@ -375,7 +393,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**:-
@@ -395,11 +413,12 @@ Note: **Anonymization does not currently apply to events.**
- PersistentVolumeClaim
- Pod
- Log
- **_*Events_**
- **_\*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**:-
@@ -407,18 +426,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>
@@ -428,11 +447,12 @@ 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>
@@ -444,38 +464,42 @@ In these scenarios K8sGPT supports AWS S3 or Azure Blob storage Integration.
_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> ```
* 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
- 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>
@@ -485,6 +509,7 @@ There may be scenarios where you wish to write your own analyzer in a language o
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
```
@@ -504,23 +529,39 @@ This now gives the ability to pass through hostOS information ( from this analyz
_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

@@ -24,7 +24,7 @@ spec:
{{- if .Values.deployment.securityContext }}
securityContext:
{{- toYaml .Values.deployment.securityContext | nindent 8 }}
{{ end -}}
{{- end }}
serviceAccountName: {{ template "k8sgpt.fullname" . }}
containers:
- name: k8sgpt-container

View File

@@ -33,6 +33,7 @@ var (
language string
nocache bool
namespace string
labelSelector string
anonymize bool
maxConcurrency int
withDoc bool
@@ -55,6 +56,7 @@ var AnalyzeCmd = &cobra.Command{
language,
filters,
namespace,
labelSelector,
nocache,
explain,
maxConcurrency,
@@ -142,4 +144,6 @@ func init() {
AnalyzeCmd.Flags().BoolVarP(&customAnalysis, "custom-analysis", "z", false, "Enable custom analyzers")
// add custom headers flag
AnalyzeCmd.Flags().StringSliceVarP(&customHeaders, "custom-headers", "r", []string{}, "Custom Headers, <key>:<value> (e.g CustomHeaderKey:CustomHeaderValue AnotherHeader:AnotherValue)")
// label selector flag
AnalyzeCmd.Flags().StringVarP(&labelSelector, "selector", "L", "", "Label selector (label query) to filter on, supports '=', '==', and '!='. (e.g. -L key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
}

View File

@@ -48,25 +48,12 @@ var addCmd = &cobra.Command{
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 {
@@ -87,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
@@ -143,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.")
}
},
}
@@ -173,8 +179,8 @@ func init() {
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 (only for amazonbedrock, googlevertexai backend)")
//add flag for vertexAI Project ID
addCmd.Flags().StringVarP(&providerId, "providerId", "i", "", "Provider specific ID for e.g. project (only for googlevertexai backend)")
//add flag for 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

View File

@@ -28,6 +28,7 @@ var updateCmd = &cobra.Command{
Long: "The command to update an AI backend provider",
// 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")

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

View File

@@ -22,6 +22,7 @@ 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/filters"
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
"github.com/k8sgpt-ai/k8sgpt/cmd/integration"
@@ -74,6 +75,7 @@ func init() {
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"
@@ -108,6 +109,7 @@ var ServeCmd = &cobra.Command{
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 != ""
@@ -119,6 +121,7 @@ var ServeCmd = &cobra.Command{
BaseURL: baseURL,
Engine: engine,
ProxyEndpoint: proxyEndpoint,
ProviderId: providerId,
Temperature: temperature(),
TopP: topP(),
TopK: topK(),
@@ -149,7 +152,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)
}

View File

@@ -9,7 +9,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM golang:1.22-alpine3.19 AS builder
FROM golang:1.23-alpine3.19 AS builder
ENV CGO_ENABLED=0
ARG VERSION

213
go.mod
View File

@@ -1,51 +1,53 @@
module github.com/k8sgpt-ai/k8sgpt
go 1.22.0
go 1.22.3
toolchain go1.22.4
toolchain go1.23.2
require (
github.com/aquasecurity/trivy-operator v0.17.1
github.com/aquasecurity/trivy-operator v0.22.0
github.com/fatih/color v1.17.0
github.com/kedacore/keda/v2 v2.11.2
github.com/magiconair/properties v1.8.7
github.com/mittwald/go-helm-client v0.12.10
github.com/mittwald/go-helm-client v0.12.13
github.com/ollama/ollama v0.1.48
github.com/sashabaranov/go-openai v1.23.0
github.com/schollz/progressbar/v3 v3.14.2
github.com/schollz/progressbar/v3 v3.15.0
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.18.2
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
golang.org/x/term v0.21.0
helm.sh/helm/v3 v3.15.2
k8s.io/api v0.30.2
k8s.io/apimachinery v0.30.2
k8s.io/client-go v0.30.2
k8s.io/kubectl v0.30.2 // indirect
golang.org/x/term v0.24.0
helm.sh/helm/v3 v3.15.4
k8s.io/api v0.30.3
k8s.io/apimachinery v0.30.3
k8s.io/client-go v0.30.3
k8s.io/kubectl v0.30.3 // indirect
)
require github.com/adrg/xdg v0.4.0
require github.com/adrg/xdg v0.5.0
require (
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240406062209-1cc152efbf5c.1
cloud.google.com/go/storage v1.40.0
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.22.0-20240920204244-7a91c8620515.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.5.1-20240920204244-7a91c8620515.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.35.1-20240920204244-7a91c8620515.1
cloud.google.com/go/storage v1.44.0
cloud.google.com/go/vertexai v0.7.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
github.com/IBM/watsonx-go v1.0.0
github.com/aws/aws-sdk-go v1.53.21
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1
github.com/IBM/watsonx-go v1.0.1
github.com/aws/aws-sdk-go v1.55.5
github.com/cohere-ai/cohere-go/v2 v2.7.3
github.com/go-logr/zapr v1.3.0
github.com/google/generative-ai-go v0.11.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0
github.com/hupe1980/go-huggingface v0.0.15
github.com/kyverno/policy-reporter-kyverno-plugin v1.6.3
github.com/olekukonko/tablewriter v0.0.5
github.com/oracle/oci-go-sdk/v65 v65.65.1
github.com/prometheus/prometheus v0.49.1
github.com/prometheus/prometheus v0.53.1
github.com/pterm/pterm v0.12.79
google.golang.org/api v0.172.0
google.golang.org/api v0.197.0
gopkg.in/yaml.v2 v2.4.0
sigs.k8s.io/controller-runtime v0.18.4
sigs.k8s.io/gateway-api v1.0.0
@@ -55,78 +57,153 @@ require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
cloud.google.com/go v0.112.1 // indirect
cel.dev/expr v0.16.1 // indirect
cloud.google.com/go v0.115.1 // indirect
cloud.google.com/go/ai v0.3.5-0.20240409161017-ce55ad694f21 // indirect
cloud.google.com/go/aiplatform v1.60.0 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.7 // indirect
cloud.google.com/go/longrunning v0.5.6 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
cloud.google.com/go/aiplatform v1.68.0 // indirect
cloud.google.com/go/auth v0.9.3 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.1 // indirect
cloud.google.com/go/iam v1.2.1 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
cloud.google.com/go/monitoring v1.21.0 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.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.2 // 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-20231202071711-9a357b53e9c9 // indirect
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // 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/service/s3 v1.55.1 // indirect
github.com/aws/smithy-go v1.20.2 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/containerd/console v1.0.3 // 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.1.0 // indirect
github.com/containerd/log v0.1.0 // 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/felixge/httpsnoop v1.0.4 // 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/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/gofrs/flock v0.8.1 // 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.3 // 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.13.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/websocket v1.5.2 // indirect
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // 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/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/moby/sys/userns v0.1.0 // 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.4.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/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
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
go.opentelemetry.io/otel/metric v1.27.0 // 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.54.0 // indirect
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/tools v0.24.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // 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
gopkg.in/yaml.v3 v3.0.1 // indirect
knative.dev/pkg v0.0.0-20230616134650-eb63a40adfb0 // 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-20230124172434-306776ec8161 // indirect
github.com/BurntSushi/toml v1.4.0 // 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/squirrel v1.5.4 // indirect
github.com/aquasecurity/defsec v0.93.1 // indirect
github.com/aquasecurity/go-dep-parser v0.0.0-20231030050624-4548cca9a5c9 // indirect
github.com/aquasecurity/table v1.8.0 // indirect
github.com/aquasecurity/tml v0.6.1 // indirect
github.com/aquasecurity/trivy v0.47.0 // 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
@@ -137,7 +214,7 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v26.1.4+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v27.0.0+incompatible // indirect
github.com/docker/docker v27.1.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
@@ -158,7 +235,7 @@ require (
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.17.0 // 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.6.0 // indirect
@@ -210,10 +287,9 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/rubenv/sql-migrate v1.6.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/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.3 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
@@ -222,31 +298,31 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/otel v1.27.0 // indirect
go.opentelemetry.io/otel/trace v1.27.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.starlark.net v0.0.0-20240520160348-046347dcd104 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect
golang.org/x/net v0.26.0
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/net v0.29.0
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.6.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.34.2 // indirect
google.golang.org/grpc v1.66.2
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
k8s.io/apiextensions-apiserver v0.30.2
k8s.io/apiserver v0.30.2 // indirect
k8s.io/cli-runtime v0.30.2 // indirect
k8s.io/component-base v0.30.2 // indirect
k8s.io/apiextensions-apiserver v0.30.3
k8s.io/apiserver v0.30.3 // indirect
k8s.io/cli-runtime v0.30.3 // indirect
k8s.io/component-base v0.30.3 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.17.2 // indirect
@@ -258,3 +334,4 @@ require (
// 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 github.com/docker/docker => github.com/docker/docker v27.3.1+incompatible

1817
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -20,12 +20,8 @@ type AmazonBedRockClient struct {
client *bedrockruntime.BedrockRuntime
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,14 +48,22 @@ const (
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{
ModelAnthropicClaudeV2,
ModelAnthropicClaudeV1,
ModelAnthropicClaudeInstantV1,
ModelA21J2UltraV1,
ModelA21J2JumboInstruct,
ModelAmazonTitanExpressV1,
}
//const TOPP = 0.9 moved to config
// GetModelOrDefault check config model
func GetModelOrDefault(model string) string {
@@ -109,6 +113,8 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
a.client = bedrockruntime.New(sess)
a.model = GetModelOrDefault(config.GetModel())
a.temperature = config.GetTemperature()
a.topP = config.GetTopP()
a.maxTokens = config.GetMaxTokens()
return nil
}
@@ -116,14 +122,37 @@ func (a *AmazonBedRockClient) Configure(config IAIConfig) error {
// GetCompletion sends a request to the model for generating completion based on the provided prompt.
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 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:
return "", fmt.Errorf("model %s not supported", a.model)
}
body, err := json.Marshal(request)
if err != nil {
return "", err
@@ -142,15 +171,56 @@ 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
// Response type changes as per model
switch a.model {
case 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
}
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)
}
}
// GetName returns the name of the AmazonBedRockClient.
func (a *AmazonBedRockClient) GetName() string {
return amazonbedrockAIClientName

View File

@@ -32,7 +32,7 @@ var (
&HuggingfaceClient{},
&GoogleVertexAIClient{},
&OCIGenAIClient{},
&WatsonxAIClient{},
&IBMWatsonxAIClient{},
}
Backends = []string{
openAIClientName,
@@ -47,7 +47,7 @@ var (
huggingfaceAIClientName,
googleVertexAIClientName,
ociClientName,
watsonxAIClientName,
ibmWatsonxAIClientName,
}
)
@@ -181,7 +181,7 @@ func (p *AIProvider) GetCustomHeaders() []http.Header {
return p.CustomHeaders
}
var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci", "watsonxai"}
var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci"}
func NeedPassword(backend string) bool {
for _, b := range passwordlessProviders {

View File

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

View File

@@ -1,56 +1,59 @@
package ai
import (
"os"
"fmt"
"context"
"errors"
"fmt"
wx "github.com/IBM/watsonx-go/pkg/models"
)
const watsonxAIClientName = "watsonxai"
const ibmWatsonxAIClientName = "ibmwatsonxai"
type WatsonxAIClient struct {
type IBMWatsonxAIClient struct {
nopCloser
client *wx.Client
model string
temperature float32
topP float32
topK int32
maxNewTokens int
client *wx.Client
model string
temperature float32
topP float32
topK int32
maxNewTokens int
}
const (
modelMetallama = "ibm/granite-13b-chat-v2"
maxTokens = 2048
)
func (c *WatsonxAIClient) Configure(config IAIConfig) error {
if(config.GetModel() == "") {
c.model = config.GetModel()
} else {
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()
c.maxNewTokens = config.GetMaxTokens()
// WatsonxAPIKeyEnvVarName = "WATSONX_API_KEY"
// WatsonxProjectIDEnvVarName = "WATSONX_PROJECT_ID"
apiKey, projectID := os.Getenv(wx.WatsonxAPIKeyEnvVarName), os.Getenv(wx.WatsonxProjectIDEnvVarName)
apiKey := config.GetPassword()
if apiKey == "" {
return errors.New("No watsonx API key provided")
}
if projectID == "" {
projectId := config.GetProviderId()
if projectId == "" {
return errors.New("No watsonx project ID provided")
}
client, err := wx.NewClient(
wx.WithWatsonxAPIKey(apiKey),
wx.WithWatsonxProjectID(projectID),
wx.WithWatsonxProjectID(projectId),
)
if err != nil {
return fmt.Errorf("Failed to create client for testing. Error: %v", err)
@@ -60,7 +63,7 @@ func (c *WatsonxAIClient) Configure(config IAIConfig) error {
return nil
}
func (c *WatsonxAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
func (c *IBMWatsonxAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
result, err := c.client.GenerateText(
c.model,
prompt,
@@ -75,10 +78,9 @@ func (c *WatsonxAIClient) GetCompletion(ctx context.Context, prompt string) (str
if result.Text == "" {
return "", errors.New("Expected a result, but got an empty string")
}
return result.Text, nil
}
func (c *WatsonxAIClient) GetName() string {
return watsonxAIClientName
func (c *IBMWatsonxAIClient) GetName() string {
return ibmWatsonxAIClientName
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -118,3 +118,56 @@ func TestLogAnalyzer(t *testing.T) {
}
}
}
func TestLogAnalyzerLabelSelectorFiltering(t *testing.T) {
oldPattern := errorPattern
errorPattern = regexp.MustCompile(`(fake logs)`)
t.Cleanup(func() {
errorPattern = oldPattern
})
config := common.Analyzer{
Client: &kubernetes.Client{
Client: fake.NewSimpleClientset(
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod1",
Namespace: "default",
Labels: map[string]string{
"app": "log",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container1",
},
},
},
},
&v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "Pod2",
Namespace: "default",
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test-container2",
},
},
},
},
),
},
Context: context.Background(),
Namespace: "default",
LabelSelector: "app=log",
}
logAnalyzer := LogAnalyzer{}
results, err := logAnalyzer.Analyze(config)
require.NoError(t, err)
require.Equal(t, 1, len(results))
require.Equal(t, "default/Pod1/test-container1", results[0].Name)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
}

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ import (
type Client struct {
c *grpc.ClientConn
analyzerClient rpc.AnalyzerServiceClient
analyzerClient rpc.CustomAnalyzerServiceClient
}
func NewClient(c Connection) (*Client, error) {
@@ -22,7 +22,7 @@ func NewClient(c Connection) (*Client, error) {
if err != nil {
return nil, err
}
client := rpc.NewAnalyzerServiceClient(conn)
client := rpc.NewCustomAnalyzerServiceClient(conn)
return &Client{
c: conn,
analyzerClient: client,
@@ -31,7 +31,7 @@ func NewClient(c Connection) (*Client, error) {
func (cli *Client) Run() (common.Result, error) {
var result common.Result
req := &schemav1.AnalyzerRunRequest{}
req := &schemav1.RunRequest{}
res, err := cli.analyzerClient.Run(context.Background(), req)
if err != nil {
return result, err

View File

@@ -0,0 +1,46 @@
package custom_analyzer
import (
"fmt"
"reflect"
"regexp"
)
type CustomAnalyzerConfiguration struct {
Name string `mapstructure:"name"`
Connection Connection `mapstructure:"connection"`
}
type Connection struct {
Url string `mapstructure:"url"`
Port int `mapstructure:"port"`
}
type CustomAnalyzer struct{}
func NewCustomAnalyzer() *CustomAnalyzer {
return &CustomAnalyzer{}
}
func (*CustomAnalyzer) Check(actualConfig []CustomAnalyzerConfiguration, name, url string, port int) error {
validNameRegex := `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
validName := regexp.MustCompile(validNameRegex)
if !validName.MatchString(name) {
return fmt.Errorf("invalid name format. Must match %s", validNameRegex)
}
for _, analyzer := range actualConfig {
if analyzer.Name == name {
return fmt.Errorf("custom analyzer with the name '%s' already exists. Please use a different name", name)
}
if reflect.DeepEqual(analyzer.Connection, Connection{
Url: url,
Port: port,
}) {
return fmt.Errorf("custom analyzer with the same connection configuration (URL: '%s', Port: %d) already exists. Please use a different URL or port", url, port)
}
}
return nil
}

View File

@@ -18,6 +18,7 @@ import (
"fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/aws"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/kyverno"
"github.com/k8sgpt-ai/k8sgpt/pkg/common"
"github.com/k8sgpt-ai/k8sgpt/pkg/integration/keda"
@@ -52,6 +53,7 @@ var integrations = map[string]IIntegration{
"prometheus": prometheus.NewPrometheus(),
"aws": aws.NewAWS(),
"keda": keda.NewKeda(),
"kyverno": kyverno.NewKyverno(),
}
func NewIntegration() *Integration {

View File

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

View File

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

View File

@@ -49,16 +49,21 @@ func (TrivyAnalyzer) analyzeVulnerabilityReports(a common.Analyzer) ([]common.Re
// For each pod there may be multiple vulnerabilities
var failures []common.Failure
distinctFailures := make(map[string]common.Failure)
for _, vuln := range report.Report.Vulnerabilities {
if vuln.Severity == "CRITICAL" {
// get the vulnerability ID
// get the vulnerability description
failures = append(failures, common.Failure{
Text: fmt.Sprintf("critical Vulnerability found ID: %s (learn more at: %s)", vuln.VulnerabilityID, vuln.PrimaryLink),
text := fmt.Sprintf("critical Vulnerability found ID: %s (learn more at: %s)", vuln.VulnerabilityID, vuln.PrimaryLink)
distinctFailures[text] = common.Failure{
Text: text,
Sensitive: []common.Sensitive{},
})
}
}
}
for _, v := range distinctFailures {
failures = append(failures, v)
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", report.Namespace,
report.Name)] = common.PreAnalysis{

View File

@@ -7,16 +7,16 @@ The grpc interface that is served is hosted on [buf](https://buf.build/k8sgpt-ai
## grpcurl
A fantastic tool for local debugging and development is `grpcurl`
A fantastic tool for local debugging and development is `grpcurl`
It allows you to form curl like requests that are http2
e.g.
e.g.
```
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServerService/Analyze
grpcurl -plaintext -d '{"namespace": "k8sgpt", "explain" : "true"}' localhost:8080 schema.v1.ServiceAnalyzeService/Analyze
```
```
grpcurl -plaintext localhost:8080 schema.v1.ServerService/ListIntegrations
grpcurl -plaintext localhost:8080 schema.v1.ServiceConfigService/ListIntegrations
{
"integrations": [
"trivy"
@@ -26,5 +26,5 @@ grpcurl -plaintext localhost:8080 schema.v1.ServerService/ListIntegrations
```
```
grpcurl -plaintext -d '{"integrations":{"trivy":{"enabled":"true","namespace":"default","skipInstall":"false"}}}' localhost:8080 schema.v1.ServerService/AddConfig
grpcurl -plaintext -d '{"integrations":{"trivy":{"enabled":"true","namespace":"default","skipInstall":"false"}}}' localhost:8080 schema.v1.ServiceConfigService/AddConfig
```

View File

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

View File

@@ -0,0 +1,7 @@
package analyze
import rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc"
type Handler struct {
rpc.UnimplementedServerAnalyzerServiceServer
}

View File

@@ -1,10 +1,12 @@
package server
package config
import (
"context"
`log`
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/custom"
"github.com/spf13/viper"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -19,14 +21,49 @@ const (
notUsedInsecure = false
)
func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (*schemav1.AddConfigResponse, error,
func (h *Handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (*schemav1.AddConfigResponse, error,
) {
if i == nil {
log.Println("Error: AddConfigRequest is nil")
return nil, status.Error(codes.InvalidArgument, "AddConfigRequest is nil")
}
resp, err := h.syncIntegration(ctx, i)
if err != nil {
return resp, err
}
if i.CustomAnalyzers != nil {
// We need to add the custom analyzers to the viper config and save them
var customAnalyzers = make([]custom.CustomAnalyzer, 0)
if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil {
return resp, err
} else {
// If there are analyzers are already in the config we will append the ones with new names
for _, ca := range i.CustomAnalyzers {
exists := false
for _, c := range customAnalyzers {
if c.Name == ca.Name {
exists = true
break
}
}
if !exists {
customAnalyzers = append(customAnalyzers, custom.CustomAnalyzer{
Name: ca.Name,
Connection: custom.Connection{
Url: ca.Connection.Url,
Port: ca.Connection.Port,
},
})
}
}
// save the config
viper.Set("custom_analyzers", customAnalyzers)
if err := viper.WriteConfig(); err != nil {
return resp, err
}
}
}
if i.Cache != nil {
var err error
var remoteCache cache.CacheProvider
@@ -54,7 +91,7 @@ func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) (
return resp, nil
}
func (h *handler) RemoveConfig(ctx context.Context, i *schemav1.RemoveConfigRequest) (*schemav1.RemoveConfigResponse, error,
func (h *Handler) RemoveConfig(ctx context.Context, i *schemav1.RemoveConfigRequest) (*schemav1.RemoveConfigResponse, error,
) {
err := cache.RemoveRemoteCache()
if err != nil {

View File

@@ -0,0 +1,16 @@
package config
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"
)
type Handler struct {
rpc.UnimplementedServerConfigServiceServer
}
func (h *Handler) Shutdown(ctx context.Context, request *schemav1.ShutdownRequest) (*schemav1.ShutdownResponse, error) {
//TODO implement me
panic("implement me")
}

View File

@@ -1,4 +1,4 @@
package server
package config
import (
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
@@ -18,7 +18,7 @@ const (
// syncIntegration is aware of the following events
// A new integration added
// An integration removed from the Integration block
func (h *handler) syncIntegration(ctx context.Context,
func (h *Handler) syncIntegration(ctx context.Context,
i *schemav1.AddConfigRequest) (*schemav1.AddConfigResponse, error,
) {
response := &schemav1.AddConfigResponse{}
@@ -90,7 +90,7 @@ func (h *handler) syncIntegration(ctx context.Context,
return response, err
}
func (*handler) ListIntegrations(ctx context.Context, req *schemav1.ListIntegrationsRequest) (*schemav1.ListIntegrationsResponse, error) {
func (*Handler) ListIntegrations(ctx context.Context, req *schemav1.ListIntegrationsRequest) (*schemav1.ListIntegrationsResponse, error) {
integrationProvider := integration.NewIntegration()
// Update the requester with the status of Trivy
@@ -122,7 +122,7 @@ func (*handler) ListIntegrations(ctx context.Context, req *schemav1.ListIntegrat
return resp, nil
}
func (*handler) deactivateAllIntegrations(integrationProvider *integration.Integration) error {
func (*Handler) deactivateAllIntegrations(integrationProvider *integration.Integration) error {
integrations := integrationProvider.List()
for _, i := range integrations {
b, _ := integrationProvider.IsActivate(i)

View File

@@ -1,9 +0,0 @@
package server
import (
rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc"
)
type handler struct {
rpc.UnimplementedServerServiceServer
}

View File

@@ -11,7 +11,7 @@ import (
"google.golang.org/grpc/status"
)
func logInterceptor(logger *zap.Logger) grpc.UnaryServerInterceptor {
func LogInterceptor(logger *zap.Logger) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
start := time.Now()

View File

@@ -0,0 +1,7 @@
package query
import rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc"
type Handler struct {
rpc.UnimplementedServerQueryServiceServer
}

27
pkg/server/query/query.go Normal file
View File

@@ -0,0 +1,27 @@
package query
import (
schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1"
"context"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
)
func (h *Handler) Query(ctx context.Context, i *schemav1.QueryRequest) (
*schemav1.QueryResponse,
error,
) {
aiClient := ai.NewClient(i.Backend)
defer aiClient.Close()
resp, err := aiClient.GetCompletion(ctx, i.Query)
var errMessage string = ""
if err != nil {
errMessage = err.Error()
}
return &schemav1.QueryResponse{
Response: resp,
Error: &schemav1.QueryError{
Message: errMessage,
},
}, nil
}

View File

@@ -17,19 +17,25 @@ import (
"context"
"errors"
"fmt"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/k8sgpt-ai/k8sgpt/pkg/server/analyze"
"github.com/k8sgpt-ai/k8sgpt/pkg/server/config"
"github.com/k8sgpt-ai/k8sgpt/pkg/server/query"
"log"
"net"
"net/http"
"strings"
"time"
gw "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2/schema/v1/server-service/schemav1gateway"
gw2 "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2/schema/v1/server_analyzer_service/schemav1gateway"
gw "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2/schema/v1/server_config_service/schemav1gateway"
rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/go-logr/zapr"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.uber.org/zap"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
ctrl "sigs.k8s.io/controller-runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@@ -37,17 +43,19 @@ import (
)
type Config struct {
Port string
MetricsPort string
Backend string
Key string
Token string
Output string
Handler *handler
Logger *zap.Logger
metricsServer *http.Server
listener net.Listener
EnableHttp bool
Port string
MetricsPort string
Backend string
Key string
Token string
Output string
ConfigHandler *config.Handler
AnalyzeHandler *analyze.Handler
QueryHandler *query.Handler
Logger *zap.Logger
metricsServer *http.Server
listener net.Listener
EnableHttp bool
}
type Health struct {
@@ -80,6 +88,8 @@ func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Ha
}
func (s *Config) Serve() error {
ctrl.SetLogger(zapr.NewLogger(s.Logger))
var lis net.Listener
var err error
address := fmt.Sprintf(":%s", s.Port)
@@ -88,17 +98,27 @@ func (s *Config) Serve() error {
return err
}
s.ConfigHandler = &config.Handler{}
s.AnalyzeHandler = &analyze.Handler{}
s.QueryHandler = &query.Handler{}
s.listener = lis
s.Logger.Info(fmt.Sprintf("binding api to %s", s.Port))
grpcServerUnaryInterceptor := grpc.UnaryInterceptor(logInterceptor(s.Logger))
grpcServerUnaryInterceptor := grpc.UnaryInterceptor(LogInterceptor(s.Logger))
grpcServer := grpc.NewServer(grpcServerUnaryInterceptor)
reflection.Register(grpcServer)
rpc.RegisterServerServiceServer(grpcServer, s.Handler)
rpc.RegisterServerConfigServiceServer(grpcServer, s.ConfigHandler)
rpc.RegisterServerAnalyzerServiceServer(grpcServer, s.AnalyzeHandler)
rpc.RegisterServerQueryServiceServer(grpcServer, s.QueryHandler)
if s.EnableHttp {
s.Logger.Info("enabling rest/http api")
gwmux := runtime.NewServeMux()
err = gw.RegisterServerServiceHandlerFromEndpoint(context.Background(), gwmux, fmt.Sprintf("localhost:%s", s.Port), []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
err = gw.RegisterServerConfigServiceHandlerFromEndpoint(context.Background(), gwmux, fmt.Sprintf("localhost:%s", s.Port),
[]grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
err = gw2.RegisterServerAnalyzerServiceHandlerFromEndpoint(context.Background(), gwmux, fmt.Sprintf("localhost:%s", s.Port),
[]grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}

View File

@@ -26,6 +26,8 @@ import (
"regexp"
"strings"
"k8s.io/apimachinery/pkg/labels"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -295,3 +297,17 @@ func NewHeaders(customHeaders []string) []http.Header {
return result
}
func LabelStrToSelector(labelStr string) labels.Selector {
if labelStr == "" {
return nil
}
labelSelectorMap := make(map[string]string)
for _, s := range strings.Split(labelStr, ",") {
parts := strings.SplitN(s, "=", 2)
if len(parts) == 2 {
labelSelectorMap[parts[0]] = parts[1]
}
}
return labels.SelectorFromSet(labels.Set(labelSelectorMap))
}