Compare commits

..

32 Commits

Author SHA1 Message Date
Thomas Schuetz
8e1920e0aa fix: ignore old client go packages in renovate
Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
2023-04-28 17:44:19 +02:00
Thomas Schuetz
8e8f77d01d docs: remove issue templates to use org wide ones
Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
2023-04-27 16:25:10 +02:00
github-actions[bot]
80dddc35a4 chore(main): release 0.2.8 (#335)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-27 14:48:55 +02:00
Matthis
dee423519e fix: use a cache file name with a fixed size. (#350)
Signed-off-by: Matthis Holleville <matthish29@gmail.com>
2023-04-27 11:59:30 +02:00
Thomas Schuetz
3af366788f chore: add settings (#351)
Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
2023-04-27 10:43:23 +02:00
Anais Urlichs
cf16769a36 merging main (#347) 2023-04-26 17:26:44 +02:00
Patrick Pichler
ee85d13d59 fix: take KUBECONFIG env variable into consideration (#340)
Before, the default value set for the `--kubeconfig` flag prevented the
`KUBECONFIG` env variable to be ever taken into consideration. This
behavior has now been fixed.

If `--kubeconfig` flag is set, it takes precedence over the `KUBECONFIG` env
variable.

fixes #331

Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
Co-authored-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-26 12:12:56 +00:00
Harshit Mehta
f8fa35cf9d docs: fix README (#345)
Signed-off-by: Harshit Mehta <hdm23061993@gmail.com>
Co-authored-by: Matthis <99146727+matthisholleville@users.noreply.github.com>
2023-04-26 10:29:22 +02:00
Alex Jones
14a3537ce9 chore: update README.md (#346)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-04-26 09:36:44 +02:00
Alex Jones
0995e008fe chore: updated banner (#343)
Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-04-26 08:15:20 +02:00
renovate[bot]
125341bdaa chore(deps): pin dependencies (#336)
Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Thomas Schuetz <38893055+thschue@users.noreply.github.com>
2023-04-26 08:09:40 +02:00
Brad McCoy
aca58064c3 chore: update Apache2 license (#342)
Signed-off-by: Brad McCoy <bradmccoydev@gmail.com>
2023-04-26 07:54:42 +02:00
Matthis
10f49e6146 Merge pull request #334 from patrickpichler/fix/various-linter-reported-issues
fix: various linter reported issues
2023-04-25 23:19:29 +02:00
Patrick Pichler
c29860d418 fix: remove dead code
Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 22:31:24 +02:00
Patrick Pichler
947e94f353 fix: use correct result slice for cronjob analyzer
Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 22:31:24 +02:00
Patrick Pichler
8adde6bf87 fix: report failure if network policy doesn't match any pods
Before, there was no failure reported by the netpol analyzer, if the
matcher on the policy doesn't match any pods.

Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 22:31:24 +02:00
Alex Jones
d4dcc7a399 chore: logo update (#339)
* chore: updated logo

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

* chore: updated logo

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

* chore: updated logo

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

* chore: updated logo

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

* chore: updated logo again

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

* chore: updated logo

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

* chore: updated logo

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

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
2023-04-25 22:26:40 +02:00
Aris Boutselis
78ee280e73 Merge pull request #337 from arbreezy/feat/localai-passw
feat: don't ask for password if backend is localai
2023-04-25 21:04:22 +03:00
Aris Boutselis
74d9a750ca feat: don't ask for password if backend is localai
Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>
2023-04-25 20:45:04 +03:00
Aris Boutselis
c365c53332 Merge pull request #269 from mudler/local_models
feat: running local models
2023-04-25 20:27:17 +03:00
Matthis
9f092f3928 Merge branch 'main' into local_models 2023-04-25 19:22:46 +02:00
Patrick Pichler
252c734310 feat: introduce linter to run on PR builds (#333)
In order to catch a variaty of small and quick to happen mistakes, there
is now an additional action in place which runs a linter on the PR
content.

fixes #330

Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
Co-authored-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 14:02:47 +02:00
github-actions[bot]
db4a88e409 chore(main): release 0.2.7 (#329)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-25 11:10:53 +02:00
Patrick Pichler
2616220935 fix: remove pointer to loop variable when searching the latest event to analyze (#328)
Having a pointer to a range variable will always yield the latest value
the loop sees. This leads to subtle bugs. To prevent this from
happening, the range variable was assigned to a temp variable, which is
then referenced as a pointer.

Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
Co-authored-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 11:06:45 +02:00
Ettore Di Giacinto
30de25166d Merge branch 'main' into local_models 2023-04-25 10:55:29 +02:00
github-actions[bot]
3d11e12963 chore(main): release 0.2.6 (#327)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-25 10:44:08 +02:00
Patrick Pichler
692cd06c38 fix: explicitly pass in filter to async analysis go routine (#326)
Before the filter inside the func literal was capturing the value from
the outer loop. This is a subtle mistake, since in combination with
running the function literal as go routine, the value of filter could
have already changed at invocation time.

To fix this, the filter is now passed in as an argument to the func
literal.

Signed-off-by: Patrick Pichler <git@patrickpichler.dev>
Co-authored-by: Patrick Pichler <git@patrickpichler.dev>
2023-04-25 10:35:39 +02:00
Ettore Di Giacinto
a1aaa0a2d1 Merge branch 'main' into local_models 2023-04-25 09:56:04 +02:00
Ettore Di Giacinto
2a27344e9c Merge branch 'main' into local_models 2023-04-25 00:08:58 +02:00
mudler
3f769bf0e0 docs: simplify, link to an e2e example
Signed-off-by: mudler <mudler@mocaccino.org>
2023-04-24 23:48:42 +02:00
mudler
9b914fbc0b feat: add LocalAI backend
Signed-off-by: mudler <mudler@mocaccino.org>
2023-04-24 10:09:30 +02:00
mudler
110cb54a8a docs: add instructions to run local models
Signed-off-by: mudler <mudler@mocaccino.org>
2023-04-24 10:09:27 +02:00
33 changed files with 335 additions and 196 deletions

1
.github/CODEOWNERS vendored
View File

@@ -9,4 +9,5 @@
# Unless a later match takes precedence, these owners will be requested for
# review when someone opens a pull request.
/.github/settings.yml @k8sgpt-ai/maintainers
* @k8sgpt-ai/maintainers @k8sgpt-ai/k8sgpt-maintainers @k8sgpt-ai/k8sgpt-approvers

View File

@@ -1,35 +0,0 @@
---
name: Feature Request
about: Suggest an idea for this project
title: 'feature: '
labels: 'type:question'
assignees: '@k8sgpt-ai/maintainers'
---
<!--
Thank you for initiating this feature request 🤗
To ensure conciseness, kindly try to adhere to the following format.
-->
Checklist:
* [ ] I've searched for similar issues and couldn't find anything matching
* [ ] I've discussed this feature in the #k8sgpt slack channel
## Is this feature request related to a problem?
* [ ] Yes
* [ ] No
<!-- If yes, please provide a clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
## Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
## Benefits for the project and its users
<!-- Describe the benefits this feature will bring to the project and its users. -->
## Potential drawbacks
<!-- Describe any potential drawbacks this feature might bring to the project and its users. -->
## Additional context
<!-- Add any other context about your feature request here. If applicable, add drawings to help explain. -->

View File

@@ -1,50 +0,0 @@
---
name: Question / Bug Report
about: Create a report to help us improve
title: 'question: '
labels: 'type:question'
assignees: ''
---
<!--
Thank you for initiating this issue request 🤗
To ensure conciseness, kindly try to adhere to the following format.
-->
Checklist:
* [ ] I've searched for similar issues and couldn't find anything matching
* [ ] I've included steps to reproduce the bug.
* [ ] I've included the version of Kubernetes and k8sgpt.
### Subject of the issue
<!-- Describe your issue here. -->
### Your environment
<!-- Describe your environment here. -->
* Version of Kubernetes
<!-- kubectl version -->
* Host OS and its version / If windows, is it WSL?
* Version of k8sgpt
<!-- k8sgpt version -->
### Steps to reproduce
<!-- Tell us how to reproduce this issue. -->
* Step 1
* Step 2
### Expected behaviour
<!-- Tell us what should happen -->
### Actual behaviour
<!-- Tell us what happens instead -->
### Additional context / screenshots
<!-- Add any other context about the problem here. If applicable, add screenshots to help explain. -->

47
.github/settings.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
repository:
name: "k8sgpt"
description: "Giving Kubernetes SRE superpowers to everyone"
homepage_url: "https://k8sgpt.ai"
topics: kubernetes, devops, tooling, openai, sre
default_branch: main
allow_squash_merge: true
allow_merge_commit: true
allow_rebase_merge: true
has_wiki: false
teams:
- name: "maintainers"
permission: "admin"
- name: "k8sgpt-maintainers"
permission: "maintain"
- name: "k8sgpt-approvers"
permission: "push"
- name: "contributors"
permission: "push"
branches:
- name: main
protection:
required_pull_request_reviews:
required_approving_review_count: 1
dismiss_stale_reviews: true
require_code_owner_reviews: true
dismissal_restrictions: {}
code_owner_approval: true
required_conversation_resolution: true
required_status_checks:
strict: true
contexts:
- "DCO"
enforce_admins: true
required_linear_history: true
restrictions:
users: []
apps: []
teams: []

18
.github/workflows/golangci_lint.yaml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Run golangci-lint
on:
pull_request:
branches: [ main ]
jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- name: golangci-lint
uses: reviewdog/action-golangci-lint@53f8eabb87b40b1a2c63ec75b0d418bd0f4aa919 # v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-check

3
.gitignore vendored
View File

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

View File

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

View File

@@ -1,5 +1,51 @@
# Changelog
## [0.2.8](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.7...v0.2.8) (2023-04-27)
### Features
* don't ask for password if backend is localai ([74d9a75](https://github.com/k8sgpt-ai/k8sgpt/commit/74d9a750ca01361eb81fdcc91eb5886ecff1d17c))
* introduce linter to run on PR builds ([#333](https://github.com/k8sgpt-ai/k8sgpt/issues/333)) ([252c734](https://github.com/k8sgpt-ai/k8sgpt/commit/252c7343106bf64c86861a9452e8618efc72881c)), closes [#330](https://github.com/k8sgpt-ai/k8sgpt/issues/330)
### Bug Fixes
* remove dead code ([c29860d](https://github.com/k8sgpt-ai/k8sgpt/commit/c29860d418faa316bc167721e443f7b64eafd970))
* report failure if network policy doesn't match any pods ([8adde6b](https://github.com/k8sgpt-ai/k8sgpt/commit/8adde6bf873b46f365146bc14fc4c8f46d82f8dc))
* take `KUBECONFIG` env variable into consideration ([#340](https://github.com/k8sgpt-ai/k8sgpt/issues/340)) ([ee85d13](https://github.com/k8sgpt-ai/k8sgpt/commit/ee85d13d59e045519b087adaf55520acc2c205db)), closes [#331](https://github.com/k8sgpt-ai/k8sgpt/issues/331)
* use a cache file name with a fixed size. ([#350](https://github.com/k8sgpt-ai/k8sgpt/issues/350)) ([dee4235](https://github.com/k8sgpt-ai/k8sgpt/commit/dee423519eb35f11c3e3a6dd64981e781899fe22))
* use correct result slice for cronjob analyzer ([947e94f](https://github.com/k8sgpt-ai/k8sgpt/commit/947e94f35379712a2fb1e2a2c90636606e0e44b6))
### Docs
* fix README ([#345](https://github.com/k8sgpt-ai/k8sgpt/issues/345)) ([f8fa35c](https://github.com/k8sgpt-ai/k8sgpt/commit/f8fa35cf9d591691679d6881fcc203e3411d99aa))
### Other
* add settings ([#351](https://github.com/k8sgpt-ai/k8sgpt/issues/351)) ([3af3667](https://github.com/k8sgpt-ai/k8sgpt/commit/3af366788fb47ff87be0142446c027f5a90491e7))
* **deps:** pin dependencies ([#336](https://github.com/k8sgpt-ai/k8sgpt/issues/336)) ([125341b](https://github.com/k8sgpt-ai/k8sgpt/commit/125341bdaacbc8bedbb333e498dabfb5c72a24c0))
* logo update ([#339](https://github.com/k8sgpt-ai/k8sgpt/issues/339)) ([d4dcc7a](https://github.com/k8sgpt-ai/k8sgpt/commit/d4dcc7a3991a861923c8115c0c82759b9e83bcfa))
* update Apache2 license ([#342](https://github.com/k8sgpt-ai/k8sgpt/issues/342)) ([aca5806](https://github.com/k8sgpt-ai/k8sgpt/commit/aca58064c36b3bc13699e055a7cca8a493320078))
* update README.md ([#346](https://github.com/k8sgpt-ai/k8sgpt/issues/346)) ([14a3537](https://github.com/k8sgpt-ai/k8sgpt/commit/14a3537ce9bc9d581b78329be899a66bc14db648))
* updated banner ([#343](https://github.com/k8sgpt-ai/k8sgpt/issues/343)) ([0995e00](https://github.com/k8sgpt-ai/k8sgpt/commit/0995e008fe64f5978c3a0cc9fb4c525470f00dfa))
## [0.2.7](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.6...v0.2.7) (2023-04-25)
### Bug Fixes
* remove pointer to loop variable when searching the latest event to analyze ([#328](https://github.com/k8sgpt-ai/k8sgpt/issues/328)) ([2616220](https://github.com/k8sgpt-ai/k8sgpt/commit/2616220935d450030c8a9f2f2741c3607aa4b663))
## [0.2.6](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.5...v0.2.6) (2023-04-25)
### Bug Fixes
* explicitly pass in filter to async analysis go routine ([#326](https://github.com/k8sgpt-ai/k8sgpt/issues/326)) ([692cd06](https://github.com/k8sgpt-ai/k8sgpt/commit/692cd06c385c1c6f458994f6e975a9fce2bc1c57))
## [0.2.5](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.2.4...v0.2.5) (2023-04-25)

View File

@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -1,12 +1,10 @@
<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/>
<img src="./images/banner-white.png" width="600px;" />
![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)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/k8sgpt-ai/k8sgpt)
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7272/badge)](https://bestpractices.coreinfrastructure.org/projects/7272)
[![Link to documentation](https://img.shields.io/static/v1?label=%F0%9F%93%96&message=Documentation&color=blue)](https://docs.k8sgpt.ai/)
`k8sgpt` is a tool for scanning your Kubernetes clusters, diagnosing, and triaging issues in simple English.
@@ -30,7 +28,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.5/k8sgpt_386.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_386.rpm
sudo rpm -ivh k8sgpt_386.rpm
```
<!---x-release-please-end-->
@@ -39,7 +37,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.5/k8sgpt_amd64.rpm
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.rpm
sudo rpm -ivh -i k8sgpt_amd64.rpm
```
<!---x-release-please-end-->
@@ -51,7 +49,7 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.5/k8sgpt_386.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_386.deb
sudo dpkg -i k8sgpt_386.deb
```
<!---x-release-please-end-->
@@ -59,7 +57,7 @@ brew install k8sgpt
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.5/k8sgpt_amd64.deb
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.deb
sudo dpkg -i k8sgpt_amd64.deb
```
<!---x-release-please-end-->
@@ -72,14 +70,14 @@ brew install k8sgpt
**32 bit:**
<!---x-release-please-start-version-->
```
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.5/k8sgpt_386.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/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.5/k8sgpt_amd64.apk
curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.8/k8sgpt_amd64.apk
apk add k8sgpt_amd64.apk
```
<!---x-release-please-end-->x
@@ -313,6 +311,37 @@ _Analysis with serve mode_
```
curl -X GET "http://localhost:8080/analyze?namespace=k8sgpt&explain=false"
```
</details>
## 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.
<details>
To run local inference, you need to download the models first, for instance you can find `ggml` compatible models in [huggingface.com](https://huggingface.co/models?search=ggml) (for example vicuna, alpaca and koala).
### Start the API server
To start the API server, follow the instruction in [LocalAI](https://github.com/go-skynet/LocalAI#example-use-gpt4all-j-model).
### Run k8sgpt
To run k8sgpt, run `k8sgpt auth` 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>
## Configuration

View File

@@ -71,7 +71,7 @@ var AuthCmd = &cobra.Command{
os.Exit(1)
}
if password == "" {
if ai.NeedPassword(backend) && password == "" {
fmt.Printf("Enter %s Key: ", backend)
bytePassword, err := term.ReadPassword(int(syscall.Stdin))
if err != nil {

View File

@@ -17,18 +17,18 @@ import (
"fmt"
"os"
"path/filepath"
"github.com/adrg/xdg"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/cmd/serve"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/k8sgpt-ai/k8sgpt/cmd/analyze"
"github.com/k8sgpt-ai/k8sgpt/cmd/auth"
"github.com/k8sgpt-ai/k8sgpt/cmd/filters"
"github.com/k8sgpt-ai/k8sgpt/cmd/generate"
"github.com/k8sgpt-ai/k8sgpt/cmd/integration"
"github.com/k8sgpt-ai/k8sgpt/cmd/serve"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/client-go/util/homedir"
)
var (
@@ -63,10 +63,6 @@ func init() {
cobra.OnInitialize(initConfig)
var kubeconfigPath string
if home := homedir.HomeDir(); home != "" {
kubeconfigPath = filepath.Join(home, ".kube", "config")
}
rootCmd.AddCommand(auth.AuthCmd)
rootCmd.AddCommand(analyze.AnalyzeCmd)
rootCmd.AddCommand(filters.FiltersCmd)
@@ -75,7 +71,7 @@ func init() {
rootCmd.AddCommand(serve.ServeCmd)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.k8sgpt.yaml)")
rootCmd.PersistentFlags().StringVar(&kubecontext, "kubecontext", "", "Kubernetes context to use. Only required if out-of-cluster.")
rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", kubeconfigPath, "Path to a kubeconfig. Only required if out-of-cluster.")
rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
}
// initConfig reads in config file and ENV variables if set.

View File

@@ -26,7 +26,6 @@ import (
var (
port string
backend string
token string
)
var ServeCmd = &cobra.Command{
@@ -76,7 +75,11 @@ var ServeCmd = &cobra.Command{
if aiProvider == nil {
for _, provider := range configAI.Providers {
if backend == provider.Name {
aiProvider = &provider
// 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
aiProvider = &p
break
}
}

View File

@@ -19,7 +19,7 @@ spec:
containers:
- name: k8sgpt-container
imagePullPolicy: Always
image: ghcr.io/k8sgpt-ai/k8sgpt:v0.2.5 #x-release-please-version
image: ghcr.io/k8sgpt-ai/k8sgpt:v0.2.8 #x-release-please-version
ports:
- containerPort: 8080
args: ["serve"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 235 KiB

70
images/banner-white.svg Normal file
View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="svg_document" data-name="svg document" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 788 355">
<defs>
<style>
.cls-1 {
font-size: 125.36269px;
}
.cls-1, .cls-2, .cls-3 {
isolation: isolate;
}
.cls-1, .cls-3 {
font-family: Antonio-Regular, Antonio;
font-variation-settings: 'wght' 400;
}
.cls-4 {
fill: #3dc7f4;
stroke-width: 7px;
}
.cls-4, .cls-5, .cls-6, .cls-7, .cls-8 {
stroke: #000;
}
.cls-5 {
fill: #bd3026;
stroke-width: 15px;
}
.cls-6 {
fill: #70ccda;
}
.cls-6, .cls-7 {
stroke-width: 6px;
}
.cls-7 {
fill: #4db748;
}
.cls-3 {
font-size: 83.57513px;
}
.cls-8 {
fill: #fff;
stroke-width: 9px;
}
</style>
</defs>
<circle id="circle1" class="cls-5" cx="174" cy="178" r="136"/>
<ellipse id="circle4" class="cls-7" cx="162.26111" cy="182.3952" rx="116" ry="114.90282"/>
<ellipse id="circle4-2" data-name="circle4" class="cls-6" cx="142.12273" cy="185.51733" rx="90.62273" ry="94.37787"/>
<g id="main_group" data-name="main group">
<g id="sample_text_element" data-name="sample text element" class="cls-2" text-rendering="geometricPrecision">
<text class="cls-1" transform="translate(322.37061 148.54785) scale(1.04842 1)"><tspan x="0" y="0">K8SGPT</tspan></text>
</g>
<g id="text1" class="cls-2" text-rendering="geometricPrecision">
<text class="cls-3" transform="translate(325.03955 235.46582) scale(1.04842 1)"><tspan x="0" y="0">KUBERNETES</tspan></text>
</g>
<g id="text2" class="cls-2" text-rendering="geometricPrecision">
<text class="cls-3" transform="translate(324.16309 314.8623) scale(1.04842 1)"><tspan x="0" y="0">SUPERPOWERS</tspan></text>
</g>
</g>
<circle id="circle3" class="cls-4" cx="116.5" cy="182.3952" r="65"/>
<ellipse id="circle5" class="cls-8" cx="84" cy="182.3952" rx="32.5" ry="33.25"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

View File

@@ -36,6 +36,8 @@ func NewClient(provider string) IAI {
switch provider {
case "openai":
return &OpenAIClient{}
case "localai":
return &LocalAIClient{}
case "noopai":
return &NoOpAIClient{}
default:
@@ -51,7 +53,7 @@ type AIProvider struct {
Name string `mapstructure:"name"`
Model string `mapstructure:"model"`
Password string `mapstructure:"password"`
BaseURL string `mapstructure:"base_url"`
BaseURL string `mapstructure:"baseurl"`
}
func (p *AIProvider) GetBaseURL() string {
@@ -65,3 +67,7 @@ func (p *AIProvider) GetPassword() string {
func (p *AIProvider) GetModel() string {
return p.Model
}
func NeedPassword(backend string) bool {
return backend != "localai"
}

9
pkg/ai/localai.go Normal file
View File

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

View File

@@ -73,27 +73,22 @@ func (c *OpenAIClient) GetCompletion(ctx context.Context, prompt string) (string
func (a *OpenAIClient) Parse(ctx context.Context, prompt []string, cache cache.ICache) (string, error) {
inputKey := strings.Join(prompt, " ")
// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
cacheKey := util.GetCacheKey(a.GetName(), a.language, sEnc)
// find in viper cache
if cache.Exists(cacheKey) {
// retrieve data from cache
response, err := cache.Load(cacheKey)
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 == "" {
color.Red("error retrieving cached data")
return "", nil
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
}
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)

View File

@@ -2,7 +2,4 @@ package ai
const (
default_prompt = "Simplify the following Kubernetes error message and provide a solution in %s: %s"
prompt_a = "Read the following input %s and provide possible scenarios for remediation in %s"
prompt_b = "Considering the following input from the Kubernetes resource %s and the error message %s, provide possible scenarios for remediation in %s"
prompt_c = "Reading the following %s error message and it's accompanying log message %s, how would you simplify this message?"
)

View File

@@ -34,14 +34,14 @@ import (
)
type Analysis struct {
Context context.Context
Filters []string
Client *kubernetes.Client
AIClient ai.IAI
Results []common.Result
Namespace string
Cache cache.ICache
Explain bool
Context context.Context
Filters []string
Client *kubernetes.Client
AIClient ai.IAI
Results []common.Result
Namespace string
Cache cache.ICache
Explain bool
MaxConcurrency int
}
@@ -102,13 +102,13 @@ func NewAnalysis(backend string, language string, filters []string, namespace st
}
return &Analysis{
Context: ctx,
Filters: filters,
Client: client,
AIClient: aiClient,
Namespace: namespace,
Cache: cache.New(noCache),
Explain: explain,
Context: ctx,
Filters: filters,
Client: client,
AIClient: aiClient,
Namespace: namespace,
Cache: cache.New(noCache),
Explain: explain,
MaxConcurrency: maxConcurrency,
}, nil
}
@@ -161,7 +161,7 @@ func (a *Analysis) RunAnalysis() []error {
if analyzer, ok := analyzerMap[filter]; ok {
semaphore <- struct{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer) {
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
@@ -173,7 +173,7 @@ func (a *Analysis) RunAnalysis() []error {
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer)
}(analyzer, filter)
} else {
errorList = append(errorList, fmt.Errorf(fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter)))
}
@@ -190,7 +190,7 @@ func (a *Analysis) RunAnalysis() []error {
if analyzer, ok := analyzerMap[filter]; ok {
semaphore <- struct{}{}
wg.Add(1)
go func(analyzer common.IAnalyzer) {
go func(analyzer common.IAnalyzer, filter string) {
defer wg.Done()
results, err := analyzer.Analyze(analyzerConfig)
if err != nil {
@@ -202,7 +202,7 @@ func (a *Analysis) RunAnalysis() []error {
a.Results = append(a.Results, results...)
mutex.Unlock()
<-semaphore
}(analyzer)
}(analyzer, filter)
}
}
wg.Wait()

View File

@@ -33,11 +33,9 @@ func (analyzer CronJobAnalyzer) Analyze(a common.Analyzer) ([]common.Result, err
"analyzer_name": kind,
})
var results []common.Result
cronJobList, err := a.Client.GetClient().BatchV1().CronJobs(a.Namespace).List(a.Context, v1.ListOptions{})
if err != nil {
return results, err
return nil, err
}
var preAnalysis = map[string]common.PreAnalysis{}
@@ -114,7 +112,7 @@ func (analyzer CronJobAnalyzer) Analyze(a common.Analyzer) ([]common.Result, err
Name: key,
Error: value.FailureDetails,
}
a.Results = append(results, currentAnalysis)
a.Results = append(a.Results, currentAnalysis)
}
}

View File

@@ -36,10 +36,14 @@ func FetchLatestEvent(ctx context.Context, kubernetesClient *kubernetes.Client,
var latestEvent *v1.Event
for _, event := range events.Items {
if latestEvent == nil {
latestEvent = &event
// this is required, as a pointer to a loop variable would always yield the latest value in the range
e := event
latestEvent = &e
}
if event.LastTimestamp.After(latestEvent.LastTimestamp.Time) {
latestEvent = &event
// this is required, as a pointer to a loop variable would always yield the latest value in the range
e := event
latestEvent = &e
}
}
return latestEvent, nil

View File

@@ -54,23 +54,23 @@ func (NetworkPolicyAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
},
},
})
continue
}
// Check if policy is not applied to any pods
podList, err := util.GetPodListByLabels(a.Client.GetClient(), a.Namespace, policy.Spec.PodSelector.MatchLabels)
if err != nil {
return nil, err
}
if len(podList.Items) == 0 {
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Network policy is not applied to any pods: %s", policy.Name),
Sensitive: []common.Sensitive{
{
Unmasked: policy.Name,
Masked: util.MaskString(policy.Name),
} else {
// Check if policy is not applied to any pods
podList, err := util.GetPodListByLabels(a.Client.GetClient(), a.Namespace, policy.Spec.PodSelector.MatchLabels)
if err != nil {
return nil, err
}
if len(podList.Items) == 0 {
failures = append(failures, common.Failure{
Text: fmt.Sprintf("Network policy is not applied to any pods: %s", policy.Name),
Sensitive: []common.Sensitive{
{
Unmasked: policy.Name,
Masked: util.MaskString(policy.Name),
},
},
},
})
})
}
}
if len(failures) > 0 {

7
pkg/cache/cache.go vendored
View File

@@ -4,12 +4,11 @@ type ICache interface {
Store(key string, data string) error
Load(key string) (string, error)
Exists(key string) bool
IsCacheDisabled() bool
}
func New(noCache bool) ICache {
if noCache {
return &NoopCache{}
return &FileBasedCache{
noCache: noCache,
}
return &FileBasedCache{}
}

View File

@@ -11,7 +11,13 @@ import (
var _ (ICache) = (*FileBasedCache)(nil)
type FileBasedCache struct{}
type FileBasedCache struct {
noCache bool
}
func (f *FileBasedCache) IsCacheDisabled() bool {
return f.noCache
}
func (*FileBasedCache) Exists(key string) bool {
path, err := xdg.CacheFile(filepath.Join("k8sgpt", key))

17
pkg/cache/noop.go vendored
View File

@@ -1,17 +0,0 @@
package cache
var _ (ICache) = (*NoopCache)(nil)
type NoopCache struct{}
func (c *NoopCache) Store(key string, data string) error {
return nil
}
func (c *NoopCache) Load(key string) (string, error) {
return "", nil
}
func (c *NoopCache) Exists(key string) bool {
return false
}

View File

@@ -44,8 +44,14 @@ func NewClient(kubecontext string, kubeconfig string) (*Client, error) {
var config *rest.Config
config, err := rest.InClusterConfig()
if err != nil {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
if kubeconfig != "" {
loadingRules.ExplicitPath = kubeconfig
}
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig},
loadingRules,
&clientcmd.ConfigOverrides{
CurrentContext: kubecontext,
})

View File

@@ -15,7 +15,9 @@ package util
import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"math/rand"
@@ -148,7 +150,11 @@ func ReplaceIfMatch(text string, pattern string, replacement string) string {
}
func GetCacheKey(provider string, language string, sEnc string) string {
return fmt.Sprintf("%s-%s-%s", provider, language, sEnc)
data := fmt.Sprintf("%s-%s-%s", provider, language, sEnc)
hash := sha256.Sum256([]byte(data))
return hex.EncodeToString(hash[:])
}
func GetPodListByLabels(client k.Interface,

View File

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