Compare commits

..

17 Commits

Author SHA1 Message Date
github-actions[bot]
fbc9a3b6e1 chore(main): release 0.2.9 (#355)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-03 15:57:09 +01:00
renovate[bot]
9faa69422d chore(deps): update golang docker tag to v1.20.4 (#370)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2023-05-03 14:30:33 +00:00
renovate[bot]
8b82d59bd7 fix(deps): update module github.com/sashabaranov/go-openai to v1.9.2 (#375)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
2023-05-03 15:30:10 +01:00
renovate[bot]
799869bcef fix(deps): update module github.com/prometheus/client_golang to v1.15.1 (#374)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-03 15:29:22 +01:00
Matthis
8b49f708f3 feat: rework output format (#368)
* feat: remove warning output

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

* feat: improves the error output to respect the format

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

* feat: rework errorsList

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

* Revert "feat: rework errorsList"

This reverts commit 1a3cfa88ae.

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

---------

Signed-off-by: Matthis Holleville <matthish29@gmail.com>
2023-05-03 14:23:30 +01:00
Xav Paice
e0200e7fa0 fix: update CONTRIBUTING.md Slack URL (#373)
Signed-off-by: Xav Paice <xav@replicated.com>
2023-05-03 09:58:19 +01:00
Aris Boutselis
d8357ceb94 feat: add azure openai provider (#309)
* feat: add azure openai provider

Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>

* feat: validate backend name

Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>

* fix: remove BaseURL from the mandatory env variables

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

* fix: conflicts

Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>

* chore: updated logo (#365)

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

* chore: added changing banners (#367)

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

* feat: add additionalLabels to Service Monitor (#366)

* feat: add additionalLabels to Service Monitor

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>

* feat: update additionalLabels

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>

---------

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>

* fix: update README file's ai provider section.

Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>

---------

Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>
Signed-off-by: Aris Boutselis <arisboutselis08@gmail.com>
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>
Co-authored-by: Aris Boutselis <arisboutselis08@gmail.com>
Co-authored-by: Alex Jones <alexsimonjones@gmail.com>
Co-authored-by: Brad McCoy <bradmccoydev@gmail.com>
2023-05-02 21:28:15 +01:00
Brad McCoy
a89a5cfa2e feat: add additionalLabels to Service Monitor (#366)
* feat: add additionalLabels to Service Monitor

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>

* feat: update additionalLabels

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>

---------

Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>
2023-05-02 07:58:39 +00:00
Alex Jones
4f6e833d34 chore: added changing banners (#367)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-05-02 08:37:29 +01:00
Alex Jones
6431be7771 chore: updated logo (#365)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-05-01 21:32:44 +02:00
renovate[bot]
766a15b25a fix(deps): update module github.com/sashabaranov/go-openai to v1.9.1 (#363)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 06:43:26 +02:00
Ikko Eltociear Ashimine
4e146fb152 docs: update README.md (#356)
Signed-off-by: Ikko Eltociear Ashimine <eltociear@gmail.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2023-04-29 16:45:19 +02:00
renovate[bot]
b8a5f3bab8 chore(deps): update reviewdog/action-golangci-lint digest to f5d8591 (#362)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-29 16:44:22 +02:00
Thomas Schuetz
3051b1ca34 docs: remove issue templates to use org wide ones (#352)
Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
2023-04-28 09:44:35 +02:00
Alex Jones
7471b76794 feat: improving readme
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-04-28 07:29:35 +02:00
Tyler Gillson
5af8178802 feat: add helm chart (#318)
* feat: add helm chart

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* Address PR feedback (#1)

* remove K8SGPT_BASEURL

* add default model

* add user-specified Deployment annotations

* remove Values.secret.enabled

---------

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* update chart.appVersion, default labels

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* default image tag to Chart.appVersion

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* release-please annotation for k8sgpt image

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* revert improperly relocated Dockerfile

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* revert changes to docker-build target and actually re-locate Dockerfile

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* Update charts/k8sgpt/Chart.yaml

Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

* Update charts/k8sgpt/templates/deployment.yaml

Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>

---------

Signed-off-by: Tyler Gillson <tyler.gillson@gmail.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2023-04-27 20:47:08 +02:00
renovate[bot]
363294c310 fix(deps): update module github.com/aquasecurity/trivy-operator to v0.13.2 (#353)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-27 17:11:40 +02:00
38 changed files with 549 additions and 341 deletions

View File

@@ -12,7 +12,7 @@ jobs:
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- name: golangci-lint
uses: reviewdog/action-golangci-lint@53f8eabb87b40b1a2c63ec75b0d418bd0f4aa919 # v2
uses: reviewdog/action-golangci-lint@f5d85915708b6e687c44764987a6912d390b17f6 # v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-check

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.DS_Store
k8sgpt*
!charts/k8sgpt
*.vscode
dist/

View File

@@ -1 +1 @@
{".":"0.2.8"}
{".":"0.2.9"}

View File

@@ -1,5 +1,39 @@
# Changelog
## [0.2.9](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.8...v0.2.9) (2023-05-03)
### Features
* add additionalLabels to Service Monitor ([#366](https://github.com/k8sgpt-ai/k8sgpt/issues/366)) ([a89a5cf](https://github.com/k8sgpt-ai/k8sgpt/commit/a89a5cfa2efd365cfc1c501c7055a315949c5f97))
* add azure openai provider ([#309](https://github.com/k8sgpt-ai/k8sgpt/issues/309)) ([d8357ce](https://github.com/k8sgpt-ai/k8sgpt/commit/d8357ceb949e04d9dd21276a1d1dfcb60010c37a))
* add helm chart ([#318](https://github.com/k8sgpt-ai/k8sgpt/issues/318)) ([5af8178](https://github.com/k8sgpt-ai/k8sgpt/commit/5af817880278771cf0b25d0936b90a45c089218c))
* improving readme ([7471b76](https://github.com/k8sgpt-ai/k8sgpt/commit/7471b7679469bc7416ee35061a13e8442bfc532c))
* rework output format ([#368](https://github.com/k8sgpt-ai/k8sgpt/issues/368)) ([8b49f70](https://github.com/k8sgpt-ai/k8sgpt/commit/8b49f708f364569994801757cf72982291c0de82))
### Bug Fixes
* **deps:** update module github.com/aquasecurity/trivy-operator to v0.13.2 ([#353](https://github.com/k8sgpt-ai/k8sgpt/issues/353)) ([363294c](https://github.com/k8sgpt-ai/k8sgpt/commit/363294c310ca1a6666d4d2dcba7e232387f0d41f))
* **deps:** update module github.com/prometheus/client_golang to v1.15.1 ([#374](https://github.com/k8sgpt-ai/k8sgpt/issues/374)) ([799869b](https://github.com/k8sgpt-ai/k8sgpt/commit/799869bcef76be0d5b2169646de106bd3b441c50))
* **deps:** update module github.com/sashabaranov/go-openai to v1.9.1 ([#363](https://github.com/k8sgpt-ai/k8sgpt/issues/363)) ([766a15b](https://github.com/k8sgpt-ai/k8sgpt/commit/766a15b25a2669b101c717013dae0ea4f5d0daa3))
* **deps:** update module github.com/sashabaranov/go-openai to v1.9.2 ([#375](https://github.com/k8sgpt-ai/k8sgpt/issues/375)) ([8b82d59](https://github.com/k8sgpt-ai/k8sgpt/commit/8b82d59bd7a6837a543467f9d76c66e70f267b85))
* update CONTRIBUTING.md Slack URL ([#373](https://github.com/k8sgpt-ai/k8sgpt/issues/373)) ([e0200e7](https://github.com/k8sgpt-ai/k8sgpt/commit/e0200e7fa05597b52c9f25fc2e9b744aea764b9a))
### Docs
* remove issue templates to use org wide ones ([#352](https://github.com/k8sgpt-ai/k8sgpt/issues/352)) ([3051b1c](https://github.com/k8sgpt-ai/k8sgpt/commit/3051b1ca343d739e48ff05c96468040adefc929a))
* update README.md ([#356](https://github.com/k8sgpt-ai/k8sgpt/issues/356)) ([4e146fb](https://github.com/k8sgpt-ai/k8sgpt/commit/4e146fb152b79a43f3163a94389022b4325126d4))
### Other
* added changing banners ([#367](https://github.com/k8sgpt-ai/k8sgpt/issues/367)) ([4f6e833](https://github.com/k8sgpt-ai/k8sgpt/commit/4f6e833d3427adf82438186f52eee40293c50cd0))
* **deps:** update golang docker tag to v1.20.4 ([#370](https://github.com/k8sgpt-ai/k8sgpt/issues/370)) ([9faa694](https://github.com/k8sgpt-ai/k8sgpt/commit/9faa69422dab812ec062c10a8fffb73160a3cd21))
* **deps:** update reviewdog/action-golangci-lint digest to f5d8591 ([#362](https://github.com/k8sgpt-ai/k8sgpt/issues/362)) ([b8a5f3b](https://github.com/k8sgpt-ai/k8sgpt/commit/b8a5f3bab85e28f83259739958fe22ca0ada211a))
* updated logo ([#365](https://github.com/k8sgpt-ai/k8sgpt/issues/365)) ([6431be7](https://github.com/k8sgpt-ai/k8sgpt/commit/6431be7771bd7c34d6beac14470bc6918b1793c4))
## [0.2.8](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.7...v0.2.8) (2023-04-27)

View File

@@ -17,7 +17,7 @@ We're happy that you want to contribute to this project. Please read the section
- We are also happy to help you find something to work on. Just reach out to us.
**Getting in touch with the community**
* Join our [#k8sgpt slack channel](https://slack.cloud-native.io/channels/k8sgpt)
* Join our [#k8sgpt slack channel](https://join.slack.com/t/k8sgpt/shared_invite/zt-1rwe5fpzq-VNtJK8DmYbbm~iWL1H34nw)
* Introduce yourself on the slack channel or open an issue to let us know that you are interested in contributing
**Discuss issues**

View File

@@ -10,6 +10,8 @@ ROOT_PACKAGE=github.com/k8sgpt-ai/k8sgpt
SHELL := /bin/bash
DIRS=$(shell ls)
GO=go
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
.DEFAULT_GOAL := help
@@ -61,17 +63,21 @@ tidy:
## deploy: Deploy k8sgpt
.PHONY: deploy
deploy:
deploy: helm
@echo "===========> Deploying k8sgpt"
@$(call funcsecret)
$(HELM) install k8sgpt charts/k8sgpt -n k8sgpt --create-namespace
## update: Update k8sgpt
.PHONY: update
update: helm
@echo "===========> Updating k8sgpt"
$(HELM) upgrade k8sgpt charts/k8sgpt -n k8sgpt
## undeploy: Undeploy k8sgpt
.PHONY: undeploy
undeploy:
undeploy: helm
@echo "===========> Undeploying k8sgpt"
kubectl delete secret ai-backend-secret --namespace=k8sgpt
kubectl delete -f container/manifests
kubectl delete ns k8sgpt
$(HELM) uninstall k8sgpt -n k8sgpt
## docker-build: Build docker image
.PHONY: docker-build
@@ -79,7 +85,6 @@ docker-build:
@echo "===========> Building docker image"
docker buildx build --build-arg=VERSION="$$(git describe --tags --abbrev=0)" --build-arg=COMMIT="$$(git rev-parse --short HEAD)" --build-arg DATE="$$(date +%FT%TZ)" --platform="linux/amd64,linux/arm64" -t ${IMG} -f container/Dockerfile . --push
## fmt: Run go fmt against code.
.PHONY: fmt
fmt:
@@ -137,11 +142,16 @@ copyright.add: tools.verify.addlicense
# @addlicense -y $(shell date +"%Y") -v -c "K8sgpt AI." -f $(LICENSE_TEMPLATE) $(CODE_DIRS)
@echo "===========> End the copyright is added..."
define funcsecret
ifndef SECRET
$(error SECRET environment variable is not set)
endif
kubectl create ns k8sgpt || true
kubectl create secret generic ai-backend-secret --from-literal=secret-key=$(SECRET) --namespace=k8sgpt || true
kubectl apply -f container/manifests
endef
# =====
# Tools
HELM_VERSION ?= v3.11.3
helm:
if ! test -f $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); then \
curl -L https://get.helm.sh/helm-$(HELM_VERSION)-$(GOOS)-$(GOARCH).tar.gz | tar xz; \
mv $(GOOS)-$(GOARCH)/helm $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); \
chmod +x $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); \
rm -rf ./$(GOOS)-$(GOARCH)/; \
fi
HELM=$(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH)

187
README.md
View File

@@ -1,4 +1,8 @@
<img src="./images/banner-white.png" width="600px;" />
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./images/banner-white.png" width="600px;">
<img alt="Text changing depending on mode. Light: 'So light!' Dark: 'So dark!'" src="./images/banner-black.png" width="600px;">
</picture>
<br/>
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/k8sgpt-ai/k8sgpt)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/k8sgpt-ai/k8sgpt/release.yaml)
@@ -12,10 +16,10 @@ It has SRE experience codified into its analyzers and helps to pull out the most
<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>
# Installation
# CLI Installation
## Linux/Mac via brew
### Linux/Mac via brew
```
brew tap k8sgpt-ai/k8sgpt
@@ -28,7 +32,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_386.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_386.rpm
sudo rpm -ivh k8sgpt_386.rpm
```
<!---x-release-please-end-->
@@ -37,7 +41,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_amd64.rpm
sudo rpm -ivh -i k8sgpt_amd64.rpm
```
<!---x-release-please-end-->
@@ -49,7 +53,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_386.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
<!---x-release-please-end-->
@@ -57,7 +61,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
<!---x-release-please-end-->
@@ -70,14 +74,14 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_386.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_386.apk
apk add k8sgpt_386.apk
```
<!---x-release-please-end-->
**64 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.9/k8sgpt_amd64.apk
apk add k8sgpt_amd64.apk
```
<!---x-release-please-end-->x
@@ -100,18 +104,18 @@ If you install gcc as suggested, the problem will persist. Therefore, you need t
</details>
## Windows
### Windows
* 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
## Operator Installation
## Verify installation
To install within a Kubernetes cluster please use our `k8sgpt-operator` with installation instructions available [here](https://github.com/k8sgpt-ai/k8sgpt-operator)
* Run `k8sgpt version`
_This mode of operation is ideal for continuous monitoring of your cluster and can integrate with your existing monitoring such as Prometheus and Alertmanager._
<hr>
## Quick Start
@@ -151,63 +155,7 @@ you will be able to write your own analyzers.
- [x] pdbAnalyzer
- [x] networkPolicyAnalyzer
## Usage
```
Kubernetes debugging powered by AI
Usage:
k8sgpt [command]
Available Commands:
analyze This command will find problems within your Kubernetes cluster
auth Authenticate with your chosen backend
completion Generate the autocompletion script for the specified shell
filters Manage filters for analyzing Kubernetes resources
generate Generate Key for your chosen backend (opens browser)
help Help about any command
integration Intergrate another tool into K8sGPT
serve Runs k8sgpt as a server
version Print the version number of k8sgpt
Flags:
--config string config file (default is $HOME/.k8sgpt.yaml)
-h, --help help for k8sgpt
--kubeconfig string Path to a kubeconfig. Only required if out-of-cluster. (default "$HOME/.kube/config")
--kubecontext string Kubernetes context to use. Only required if out-of-cluster.
Use "k8sgpt [command] --help" for more information about a command.
```
_Manage filters_
_List filters_
```
k8sgpt filters list
```
_Add default filters_
```
k8sgpt filters add [filter(s)]
```
### Examples :
- Simple filter : `k8sgpt filters add Service`
- Multiple filters : `k8sgpt filters add Ingress,Pod`
_Add default filters_
```
k8sgpt filters remove [filter(s)]
```
### Examples :
- Simple filter : `k8sgpt filters remove Service`
- Multiple filters : `k8sgpt filters remove Ingress,Pod`
## Examples
_Run a scan with the default analyzers_
@@ -240,41 +188,44 @@ _Anonymize during explain_
k8sgpt analyze --explain --filter=Service --output=json --anonymize
```
### How does anonymization work?
With this option, the data is anonymized before being sent to the AI Backend. During the analysis execution, `k8sgpt` retrieves sensitive data (Kubernetes object names, labels, etc.). This data is masked when sent to the AI backend and replaced by a key that can be used to de-anonymize the data when the solution is returned to the user.
### Using filters
<details>
1. Error reported during analysis:
```bash
Error: HorizontalPodAutoscaler uses StatefulSet/fake-deployment as ScaleTargetRef which does not exist.
_List filters_
```
k8sgpt filters list
```
2. Payload sent to the AI backend:
```bash
Error: HorizontalPodAutoscaler uses StatefulSet/tGLcCRcHa1Ce5Rs as ScaleTargetRef which does not exist.
_Add default filters_
```
k8sgpt filters add [filter(s)]
```
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.
### Examples :
- Simple filter : `k8sgpt filters add Service`
- Multiple filters : `k8sgpt filters add Ingress,Pod`
_Add default filters_
```
k8sgpt filters remove [filter(s)]
```
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.
```
### Examples :
**Anonymization does not currently apply to events.**
- Simple filter : `k8sgpt filters remove Service`
- Multiple filters : `k8sgpt filters remove Ingress,Pod`
</details>
### Additional commands
<details>
_Manage integrations_
_List integrations_
@@ -311,10 +262,31 @@ _Analysis with serve mode_
```
curl -X GET "http://localhost:8080/analyze?namespace=k8sgpt&explain=false"
```
</details>
## Additional AI providers
### Azure OpenAI
<em>Prerequisites:</em> an Azure OpenAI deployment is needed, please visit MS official [documentation](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource) to create your own.
To authenticate with k8sgpt, you will need the Azure OpenAI endpoint of your tenant `"https://your Azure OpenAI Endpoint"`, the api key to access your deployment, the deployment name of your model and the model name itself.
<details>
### Run k8sgpt
To run k8sgpt, run `k8sgpt auth` with the `azureopenai` backend:
```
k8sgpt auth --backend azureopenai --baseurl https://<your Azure OpenAI endpoint> --engine <deployment_name> --model <model_name>
```
Lastly, enter your Azure API key, after the prompt.
Now you are ready to analyze with the azure openai backend:
```
k8sgpt analyze --explain --backend azureopenai
```
</details>
## Running local models
### Running local models
To run local models, it is possible to use OpenAI compatible APIs, for instance [LocalAI](https://github.com/go-skynet/LocalAI) which uses [llama.cpp](https://github.com/ggerganov/llama.cpp) and [ggml](https://github.com/ggerganov/ggml) to run inference on consumer-grade hardware. Models supported by LocalAI for instance are Vicuna, Alpaca, LLaMA, Cerebras, GPT4ALL, GPT4ALL-J and koala.
@@ -334,18 +306,47 @@ To run k8sgpt, run `k8sgpt auth` with the `localai` backend:
k8sgpt auth --backend localai --model <model_name> --baseurl http://localhost:8080/v1
```
When being asked for an API key, just press enter.
Now you can analyze with the `localai` backend:
```
k8sgpt analyze --explain --backend localai
```
</details>
## How does anonymization work?
With this option, the data is anonymized before being sent to the AI Backend. During the analysis execution, `k8sgpt` retrieves sensitive data (Kubernetes object names, labels, etc.). This data is masked when sent to the AI backend and replaced by a key that can be used to de-anonymize the data when the solution is returned to the user.
<details>
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.
```
**Anonymization does not currently apply to events.**
</details>
## Configuration
<details>
`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:
@@ -354,7 +355,7 @@ Config file locations:
| MacOS | ~/Library/Application Support/k8sgpt/k8sgpt.yaml |
| Linux | ~/.config/k8sgpt/k8sgpt.yaml |
| Windows | %LOCALAPPDATA%/k8sgpt/k8sgpt.yaml |
</details>
## Contributing

6
charts/k8sgpt/Chart.yaml Normal file
View File

@@ -0,0 +1,6 @@
apiVersion: v2
appVersion: v0.2.4 #x-release-please-version
description: A Helm chart for K8SGPT
name: k8sgpt
type: application
version: 1.0.0

View File

@@ -0,0 +1,44 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "k8sgpt.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "k8sgpt.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "k8sgpt.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "k8sgpt.labels" -}}
helm.sh/chart: {{ include "k8sgpt.chart" . }}
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
{{- if .Values.deployment.annotations }}
annotations:
{{- toYaml .Values.deployment.annotations | nindent 4 }}
{{- end }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
serviceAccountName: k8sgpt
containers:
- name: k8sgpt-container
imagePullPolicy: {{ .Values.deployment.imagePullPolicy }}
image: {{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag | default .Chart.AppVersion }}
ports:
- containerPort: 8080
args: ["serve"]
{{- if .Values.deployment.resources }}
resources:
{{- toYaml .Values.deployment.resources | nindent 10 }}
{{- end }}
env:
- name: K8SGPT_MODEL
value: {{ .Values.deployment.env.model }}
- name: K8SGPT_BACKEND
value: {{ .Values.deployment.env.backend }}
{{- if .Values.secret.secretKey }}
- name: K8SGPT_PASSWORD
valueFrom:
secretKeyRef:
name: ai-backend-secret
key: secret-key
{{- end }}

View File

@@ -1,7 +1,10 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8sgpt-cluster-role-all
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}
rules:
- apiGroups:
- '*'

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
roleRef:
kind: ClusterRole
name: k8sgpt-cluster-role-all
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}

View File

@@ -0,0 +1,10 @@
{{- if .Values.secret.secretKey }}
apiVersion: v1
data:
secret-key: {{ .Values.secret.secretKey }}
kind: Secret
metadata:
name: ai-backend-secret
namespace: {{ .Release.Namespace | quote }}
type: Opaque
{{- end}}

View File

@@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}
{{- if .Values.service.annotations }}
annotations:
{{- toYaml .Values.service.annotations | nindent 4 }}
{{- end }}
spec:
selector:
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
ports:
- name: http
port: 8080
targetPort: 8080
type: {{ .Values.service.type }}

View File

@@ -0,0 +1,21 @@
{{- if .Values.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ template "k8sgpt.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "k8sgpt.labels" . | nindent 4 }}
{{- if .Values.serviceMonitor.additionalLabels }}
{{- toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }}
{{- end }}
spec:
endpoints:
- honorLabels: true
path: /metrics
port: http
selector:
matchLabels:
app.kubernetes.io/name: {{ include "k8sgpt.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

27
charts/k8sgpt/values.yaml Normal file
View File

@@ -0,0 +1,27 @@
deployment:
image:
repository: ghcr.io/k8sgpt-ai/k8sgpt
tag: "" # defaults to Chart.appVersion if unspecified
imagePullPolicy: Always
annotations: {}
env:
model: "gpt-3.5-turbo"
backend: "openai" # one of: [ openai | llama ]
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "156Mi"
secret:
secretKey: "" # base64 encoded OpenAI token
service:
type: ClusterIP
annotations: {}
serviceMonitor:
enabled: false
additionalLabels: {}

View File

@@ -51,12 +51,7 @@ var AnalyzeCmd = &cobra.Command{
os.Exit(1)
}
analysisErrors := config.RunAnalysis()
if len(analysisErrors) != 0 {
for _, err := range analysisErrors {
color.Red("Error: %s", err)
}
}
config.RunAnalysis()
if explain {
err := config.GetAIResults(output, anonymize)

View File

@@ -31,6 +31,7 @@ var (
password string
baseURL string
model string
engine string
)
// authCmd represents the auth command
@@ -38,6 +39,13 @@ var AuthCmd = &cobra.Command{
Use: "auth",
Short: "Authenticate with your chosen backend",
Long: `Provide the necessary credentials to authenticate with your chosen backend.`,
PreRun: func(cmd *cobra.Command, args []string) {
backend, _ := cmd.Flags().GetString("backend")
if strings.ToLower(backend) == "azureopenai" {
cmd.MarkFlagRequired("engine")
cmd.MarkFlagRequired("baseurl")
}
},
Run: func(cmd *cobra.Command, args []string) {
// get ai configuration
@@ -57,9 +65,18 @@ var AuthCmd = &cobra.Command{
}
}
// check if backend is not empty
if backend == "" {
color.Red("Error: Backend AI cannot be empty.")
validBackend := func(validBackends []string, backend string) bool {
for _, b := range validBackends {
if b == backend {
return true
}
}
return false
}
// check if backend is not empty and a valid value
if backend == "" || !validBackend(ai.Backends, backend) {
color.Red("Error: Backend AI cannot be empty and accepted values are '%v'", strings.Join(ai.Backends, ", "))
os.Exit(1)
}
@@ -88,6 +105,7 @@ var AuthCmd = &cobra.Command{
Model: model,
Password: password,
BaseURL: baseURL,
Engine: engine,
}
if providerIndex == -1 {
@@ -117,4 +135,6 @@ func init() {
AuthCmd.Flags().StringVarP(&password, "password", "p", "", "Backend AI password")
// add flag for url
AuthCmd.Flags().StringVarP(&baseURL, "baseurl", "u", "", "URL AI provider, (e.g `http://localhost:8080/v1`)")
// add flag for azure open ai engine/deployment name
AuthCmd.Flags().StringVarP(&engine, "engine", "e", "", "Azure AI deployment name")
}

View File

@@ -14,12 +14,10 @@ limitations under the License.
package cmd
import (
"fmt"
"os"
"path/filepath"
"github.com/adrg/xdg"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/cmd/analyze"
"github.com/k8sgpt-ai/k8sgpt/cmd/auth"
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
@@ -116,14 +114,7 @@ func performConfigMigrationIfNeeded() {
err = util.EnsureDirExists(configDir)
cobra.CheckErr(err)
if oldConfigExists && newConfigExists {
fmt.Fprintln(os.Stderr, color.RedString("Warning: Legacy config file at `%s` detected! This file will be ignored!", oldConfig))
return
}
if oldConfigExists && !newConfigExists {
fmt.Fprintln(os.Stderr, color.RedString("Performing config file migration from `%s` to `%s`", oldConfig, newConfig))
err = os.Rename(oldConfig, newConfig)
cobra.CheckErr(err)
}

View File

@@ -47,17 +47,17 @@ var ServeCmd = &cobra.Command{
password := os.Getenv("K8SGPT_PASSWORD")
model := os.Getenv("K8SGPT_MODEL")
baseURL := os.Getenv("K8SGPT_BASEURL")
engine := os.Getenv("K8SGPT_ENGINE")
// If the envs are set, allocate in place to the aiProvider
// else exit with error
envIsSet := backend != "" || password != "" || model != "" || baseURL != ""
envIsSet := backend != "" || password != "" || model != ""
if envIsSet {
aiProvider = &ai.AIProvider{
Name: backend,
Password: password,
Model: model,
BaseURL: baseURL,
Engine: engine,
}
configAI.Providers = append(configAI.Providers, *aiProvider)
@@ -75,10 +75,10 @@ var ServeCmd = &cobra.Command{
if aiProvider == nil {
for _, provider := range configAI.Providers {
if backend == provider.Name {
// he pointer to the range variable is not really an issue here, as there
// is a break right after, but to prevent potential future issues, a temp
// variable is assigned
p := provider
// the pointer to the range variable is not really an issue here, as there
// is a break right after, but to prevent potential future issues, a temp
// variable is assigned
p := provider
aiProvider = &p
break
}

View File

@@ -9,7 +9,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM golang:1.20.3-alpine3.16 AS builder
FROM golang:1.20.4-alpine3.16 AS builder
ENV CGO_ENABLED=0

View File

@@ -1,42 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8sgpt-deployment
namespace: k8sgpt
labels:
app: k8sgpt
spec:
replicas: 1
selector:
matchLabels:
app: k8sgpt
template:
metadata:
labels:
app: k8sgpt
spec:
serviceAccountName: k8sgpt
containers:
- name: k8sgpt-container
imagePullPolicy: Always
image: ghcr.io/k8sgpt-ai/k8sgpt:v0.2.8 #x-release-please-version
ports:
- containerPort: 8080
args: ["serve"]
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "156Mi"
env:
- name: K8SGPT_MODEL
value: "gpt-3.5-turbo"
- name: K8SGPT_BACKEND
value: "openai"
- name: K8SGPT_PASSWORD
valueFrom:
secretKeyRef:
name: ai-backend-secret
key: secret-key

View File

@@ -1,13 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8sgpt-rolebinding
namespace: k8sgpt
subjects:
- kind: ServiceAccount
name: k8sgpt
namespace: k8sgpt
roleRef:
kind: ClusterRole
name: k8sgpt-cluster-role-all
apiGroup: rbac.authorization.k8s.io

View File

@@ -1,5 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8sgpt
namespace: k8sgpt

View File

@@ -1,15 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: k8sgpt-service
namespace: k8sgpt
labels:
app: k8sgpt
spec:
selector:
app: k8sgpt
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP

View File

@@ -1,15 +0,0 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app: k8sgpt
name: k8sgpt-service-monitor
namespace: k8sgpt
spec:
endpoints:
- honorLabels: true
path: /metrics
port: http
selector:
matchLabels:
app: k8sgpt

6
go.mod
View File

@@ -3,11 +3,11 @@ module github.com/k8sgpt-ai/k8sgpt
go 1.20
require (
github.com/aquasecurity/trivy-operator v0.13.1
github.com/aquasecurity/trivy-operator v0.13.2
github.com/fatih/color v1.15.0
github.com/magiconair/properties v1.8.7
github.com/mittwald/go-helm-client v0.12.1
github.com/sashabaranov/go-openai v1.9.0
github.com/sashabaranov/go-openai v1.9.2
github.com/schollz/progressbar/v3 v3.13.1
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.15.0
@@ -115,7 +115,7 @@ require (
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.15.0
github.com/prometheus/client_golang v1.15.1
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect

12
go.sum
View File

@@ -89,8 +89,8 @@ github.com/aquasecurity/trivy v0.40.0 h1:zT+ZwofGfMqsg3ccFUMPDyiyhBPdDap1TcKWxrq
github.com/aquasecurity/trivy v0.40.0/go.mod h1:NXuad2fPoIWB97hU6igQsBI1YbMfYD7aAz09SfdZuq4=
github.com/aquasecurity/trivy-db v0.0.0-20230411140759-3c2ee2168575 h1:8Y/qLPXGFYGGetDo0uhMRnqF8696tWBVis5scJ42q3w=
github.com/aquasecurity/trivy-db v0.0.0-20230411140759-3c2ee2168575/go.mod h1:zn8GepvD5wBkCmmtBDwh0BWfiMUxS6xfGRcTPmXRVXo=
github.com/aquasecurity/trivy-operator v0.13.1 h1:zQBAdzaxfjRGFNKN0V0y+ibp8ZiPBdomYyGphuJIm/Y=
github.com/aquasecurity/trivy-operator v0.13.1/go.mod h1:DZaazIkMJNYeacKJ1Hiv+iGY3pW4icEc+gzFNm48lw8=
github.com/aquasecurity/trivy-operator v0.13.2 h1:JyDV5aX5g0RhNyqAR87VRk3Ou2hTu8g1cXo0Ky2DrRQ=
github.com/aquasecurity/trivy-operator v0.13.2/go.mod h1:DZaazIkMJNYeacKJ1Hiv+iGY3pW4icEc+gzFNm48lw8=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -561,8 +561,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -601,8 +601,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw=
github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA=
github.com/sashabaranov/go-openai v1.9.0 h1:NoiO++IISxxJ1pRc0n7uZvMGMake0G+FJ1XPwXtprsA=
github.com/sashabaranov/go-openai v1.9.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sashabaranov/go-openai v1.9.2 h1:7//Glm9EiMBjelgmBb00yYzKYqm1jckHWWTDLahfeuQ=
github.com/sashabaranov/go-openai v1.9.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE=
github.com/schollz/progressbar/v3 v3.13.1/go.mod h1:xvrbki8kfT1fzWzBT/UZd9L6GA+jdL7HAgq2RFnO6fQ=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=

BIN
images/banner-black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 KiB

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 22 KiB

94
pkg/ai/azureopenai.go Normal file
View File

@@ -0,0 +1,94 @@
package ai
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strings"
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/fatih/color"
"github.com/sashabaranov/go-openai"
)
type AzureAIClient struct {
client *openai.Client
language string
model string
}
func (c *AzureAIClient) Configure(config IAIConfig, lang string) error {
token := config.GetPassword()
baseURL := config.GetBaseURL()
engine := config.GetEngine()
defaultConfig := openai.DefaultAzureConfig(token, baseURL, engine)
client := openai.NewClientWithConfig(defaultConfig)
if client == nil {
return errors.New("error creating Azure OpenAI client")
}
c.language = lang
c.client = client
c.model = config.GetModel()
return nil
}
func (c *AzureAIClient) GetCompletion(ctx context.Context, prompt string) (string, error) {
// Create a completion request
resp, err := c.client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: c.model,
Messages: []openai.ChatCompletionMessage{
{
Role: "user",
Content: fmt.Sprintf(default_prompt, c.language, prompt),
},
},
})
if err != nil {
return "", err
}
return resp.Choices[0].Message.Content, nil
}
func (a *AzureAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
cacheKey := util.GetCacheKey(a.GetName(), a.language, inputKey)
if !cache.IsCacheDisabled() && cache.Exists(cacheKey) {
response, err := cache.Load(cacheKey)
if err != nil {
return "", err
}
if response != "" {
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
return "", nil
}
return string(output), nil
}
}
response, err := a.GetCompletion(ctx, inputKey)
if err != nil {
return "", err
}
err = cache.Store(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err != nil {
color.Red("error storing value to cache: %v", err)
return "", nil
}
return response, nil
}
func (a *AzureAIClient) GetName() string {
return "azureopenai"
}

View File

@@ -19,6 +19,21 @@ import (
"github.com/k8sgpt-ai/k8sgpt/pkg/cache"
)
var (
clients = []IAI{
&OpenAIClient{},
&AzureAIClient{},
&LocalAIClient{},
&NoOpAIClient{},
}
Backends = []string{
"openai",
"localai",
"azureopenai",
"noopai",
}
)
type IAI interface {
Configure(config IAIConfig, language string) error
GetCompletion(ctx context.Context, prompt string) (string, error)
@@ -30,19 +45,17 @@ type IAIConfig interface {
GetPassword() string
GetModel() string
GetBaseURL() string
GetEngine() string
}
func NewClient(provider string) IAI {
switch provider {
case "openai":
return &OpenAIClient{}
case "localai":
return &LocalAIClient{}
case "noopai":
return &NoOpAIClient{}
default:
return &OpenAIClient{}
for _, c := range clients {
if provider == c.GetName() {
return c
}
}
// default client
return &OpenAIClient{}
}
type AIConfiguration struct {
@@ -52,8 +65,9 @@ type AIConfiguration struct {
type AIProvider struct {
Name string `mapstructure:"name"`
Model string `mapstructure:"model"`
Password string `mapstructure:"password"`
BaseURL string `mapstructure:"baseurl"`
Password string `mapstructure:"password" yaml:"password,omitempty"`
BaseURL string `mapstructure:"baseurl" yaml:"baseurl,omitempty"`
Engine string `mapstructure:"engine" yaml:"engine,omitempty"`
}
func (p *AIProvider) GetBaseURL() string {
@@ -68,6 +82,10 @@ func (p *AIProvider) GetModel() string {
return p.Model
}
func (p *AIProvider) GetEngine() string {
return p.Engine
}
func NeedPassword(backend string) bool {
return backend != "localai"
}

View File

@@ -39,6 +39,7 @@ type Analysis struct {
Client *kubernetes.Client
AIClient ai.IAI
Results []common.Result
Errors []string
Namespace string
Cache cache.ICache
Explain bool
@@ -46,6 +47,7 @@ type Analysis struct {
}
type AnalysisStatus string
type AnalysisErrors []string
const (
StateOK AnalysisStatus = "OK"
@@ -53,6 +55,7 @@ const (
)
type JsonOutput struct {
Errors AnalysisErrors `json:"errors"`
Status AnalysisStatus `json:"status"`
Problems int `json:"problems"`
Results []common.Result `json:"results"`
@@ -113,7 +116,7 @@ func NewAnalysis(backend string, language string, filters []string, namespace st
}, nil
}
func (a *Analysis) RunAnalysis() []error {
func (a *Analysis) RunAnalysis() {
activeFilters := viper.GetStringSlice("active_filters")
analyzerMap := analyzer.GetAnalyzerMap()
@@ -125,7 +128,6 @@ func (a *Analysis) RunAnalysis() []error {
AIClient: a.AIClient,
}
var errorList []error
semaphore := make(chan struct{}, a.MaxConcurrency)
// if there are no filters selected and no active_filters then run all of them
if len(a.Filters) == 0 && len(activeFilters) == 0 {
@@ -139,7 +141,7 @@ func (a *Analysis) RunAnalysis() []error {
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
errorList = append(errorList, fmt.Errorf(fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err)))
a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err)))
mutex.Unlock()
}
mutex.Lock()
@@ -150,7 +152,6 @@ func (a *Analysis) RunAnalysis() []error {
}
wg.Wait()
return errorList
}
semaphore = make(chan struct{}, a.MaxConcurrency)
// if the filters flag is specified
@@ -166,7 +167,7 @@ func (a *Analysis) RunAnalysis() []error {
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
errorList = append(errorList, fmt.Errorf(fmt.Sprintf("[%s] %s", filter, err)))
a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("[%s] %s", filter, err)))
mutex.Unlock()
}
mutex.Lock()
@@ -175,11 +176,10 @@ func (a *Analysis) RunAnalysis() []error {
<-semaphore
}(analyzer, filter)
} else {
errorList = append(errorList, fmt.Errorf(fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter)))
a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter)))
}
}
wg.Wait()
return errorList
}
var wg sync.WaitGroup
@@ -195,7 +195,7 @@ func (a *Analysis) RunAnalysis() []error {
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
mutex.Lock()
errorList = append(errorList, fmt.Errorf("[%s] %s", filter, err))
a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err))
mutex.Unlock()
}
mutex.Lock()
@@ -206,7 +206,6 @@ func (a *Analysis) RunAnalysis() []error {
}
}
wg.Wait()
return errorList
}
func (a *Analysis) GetAIResults(output string, anonymize bool) error {

View File

@@ -44,6 +44,7 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
result := JsonOutput{
Problems: problems,
Results: a.Results,
Errors: a.Errors,
Status: status,
}
output, err := json.MarshalIndent(result, "", " ")
@@ -55,6 +56,13 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
func (a *Analysis) textOutput() ([]byte, error) {
var output strings.Builder
if len(a.Errors) != 0 {
output.WriteString("\n")
output.WriteString(color.YellowString("Warnings : \n"))
for _, aerror := range a.Errors {
output.WriteString(fmt.Sprintf("- %s\n", color.YellowString(aerror)))
}
}
output.WriteString("\n")
if len(a.Results) == 0 {
output.WriteString(color.GreenString("No problems detected\n"))

View File

@@ -75,15 +75,7 @@ func (s *Config) analyzeHandler(w http.ResponseWriter, r *http.Request) {
return
}
analysisErrors := config.RunAnalysis()
if analysisErrors != nil {
var errorMessage string
for _, err := range analysisErrors {
errorMessage += err.Error() + "\n"
}
http.Error(w, errorMessage, http.StatusInternalServerError)
health.Failure++
}
config.RunAnalysis()
if explain {
err := config.GetAIResults(s.Output, anonymize)

View File

@@ -12,10 +12,6 @@
"gomodMassage"
],
"packageRules": [
{
"matchPackageNames": ["k8s.io/client-go"],
"allowedVersions": "!/1\\.(4\\.0|5\\.0|5\\.1|5\\.2)$/"
},
{
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
@@ -48,4 +44,4 @@
]
}
]
}
}