updated copy on readme

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
This commit is contained in:
AlexsJones 2023-03-21 19:58:32 +00:00
parent 59a0507e37
commit a14cde2c1f
9 changed files with 126 additions and 3 deletions

View File

@ -3,6 +3,8 @@
AI Powered Kubernetes debugging for SRE, Platform and DevOps teams.
<img src="images/demo.gif" width=800px; />
## What is k8sgpt?
`k8sgpt` is a tool for scanning your kubernetes clusters, diagnosing and triaging issues in simple english.

View File

@ -4,9 +4,24 @@ Copyright © 2023 NAME HERE <EMAIL ADDRESS>
package find
import (
"context"
"fmt"
"os"
"strings"
"time"
"github.com/briandowns/spinner"
"github.com/cloud-native-skunkworks/k8sgpt/pkg/client"
"github.com/cloud-native-skunkworks/k8sgpt/pkg/openai"
"github.com/fatih/color"
ai "github.com/sashabaranov/go-openai"
"github.com/spf13/cobra"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
var explain bool
// problemsCmd represents the problems command
var problemsCmd = &cobra.Command{
Use: "problems",
@ -15,10 +30,76 @@ var problemsCmd = &cobra.Command{
provide you with a list of issues that need to be resolved`,
Run: func(cmd *cobra.Command, args []string) {
// Initialise the openAI client
openAIClient, err := openai.NewClient()
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
ctx := context.Background()
// Get kubernetes client from viper
client := viper.Get("kubernetesClient").(*client.Client)
// search all namespaces for pods that are not running
list, err := client.GetClient().CoreV1().Pods("").List(ctx, metav1.ListOptions{})
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
var brokenPods = map[string][]string{}
for _, pod := range list.Items {
// Loop through container status to check for crashes
var failureDetails = []string{}
for _, containerStatus := range pod.Status.ContainerStatuses {
if containerStatus.State.Waiting != nil {
if containerStatus.State.Waiting.Reason == "CrashLoopBackOff" || containerStatus.State.Waiting.Reason == "ImagePullBackOff" {
failureDetails = append(failureDetails, containerStatus.State.Waiting.Message)
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = failureDetails
}
}
}
}
// loop through and print map
for key, value := range brokenPods {
y := color.YellowString(key)
v := color.RedString(value[0])
fmt.Printf("%s: %s\n", y, v)
if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()
resp, err := openAIClient.GetClient().CreateChatCompletion(ctx, ai.ChatCompletionRequest{
Model: ai.GPT3Dot5Turbo,
Messages: []ai.ChatCompletionMessage{
{
Role: "user",
Content: "Simplify the following Kubernetes error message and provide a solution: " + strings.Join(value, " "),
},
},
})
s.Stop()
if err != nil {
color.Red("Error: %v", err)
return
}
color.Green(resp.Choices[0].Message.Content)
}
}
},
}
func init() {
problemsCmd.Flags().BoolVarP(&explain, "explain", "e", false, "Explain the problem to me")
FindCmd.AddCommand(problemsCmd)
}

View File

@ -4,7 +4,6 @@ Copyright © 2023 NAME HERE <EMAIL ADDRESS>
package cmd
import (
"fmt"
"os"
"github.com/cloud-native-skunkworks/k8sgpt/cmd/auth"
@ -57,11 +56,12 @@ func init() {
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
//Initialise the kubeconfig
_, err := client.NewClient(masterURL, kubeconfig)
kubernetesClient, err := client.NewClient(masterURL, kubeconfig)
if err != nil {
color.Red("Error initialising kubernetes client: %v", err)
}
viper.Set("kubernetesClient", kubernetesClient)
}
// initConfig reads in config file and ENV variables if set.
@ -86,6 +86,6 @@ func initConfig() {
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
// fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
}
}

2
go.mod
View File

@ -11,6 +11,7 @@ require (
)
require (
github.com/briandowns/spinner v1.23.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
@ -37,6 +38,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/sashabaranov/go-openai v1.5.4 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect

4
go.sum
View File

@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A=
github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@ -206,6 +208,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sashabaranov/go-openai v1.5.4 h1:I2K7JMIx/EC/mwT2fbypBzJ3OtwKNxaFg4jf3KOvXuc=
github.com/sashabaranov/go-openai v1.5.4/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=

BIN
images/demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

BIN
images/demo1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

View File

@ -10,6 +10,10 @@ type Client struct {
client *kubernetes.Clientset
}
func (c *Client) GetClient() *kubernetes.Clientset {
return c.client
}
func NewClient(masterURL string, kubeconfig string) (*Client, error) {
config, err := rest.InClusterConfig()

30
pkg/openai/openai.go Normal file
View File

@ -0,0 +1,30 @@
package openai
import (
"fmt"
"github.com/sashabaranov/go-openai"
"github.com/spf13/viper"
)
type Client struct {
client *openai.Client
}
func (c *Client) GetClient() *openai.Client {
return c.client
}
func NewClient() (*Client, error) {
// get the token with viper
token := viper.GetString("openai_api_key")
// check if nil
if token == "" {
return nil, fmt.Errorf("no OpenAI API Key found")
}
client := openai.NewClient(token)
return &Client{
client: client,
}, nil
}