feat: unified cmd and api

Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
This commit is contained in:
Thomas Schuetz
2023-04-13 08:11:56 +02:00
parent adae2ef71d
commit 9157d4dd13
7 changed files with 76 additions and 117 deletions

View File

@@ -1,16 +1,12 @@
package analyze package analyze
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis" "github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var ( var (
@@ -33,58 +29,11 @@ var AnalyzeCmd = &cobra.Command{
provide you with a list of issues that need to be resolved`, provide you with a list of issues that need to be resolved`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// get ai configuration
var configAI ai.AIConfiguration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
if len(configAI.Providers) == 0 {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
}
var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if backend == provider.Name {
aiProvider = provider
break
}
}
if aiProvider.Name == "" {
color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", backend)
os.Exit(1)
}
aiClient := ai.NewClient(aiProvider.Name)
if err := aiClient.Configure(aiProvider.Password, aiProvider.Model, language); err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
ctx := context.Background()
// Get kubernetes client from viper
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error initialising kubernetes client: %v", err)
os.Exit(1)
}
// AnalysisResult configuration // AnalysisResult configuration
config := &analysis.Analysis{ config, err := analysis.NewAnalysis(backend, language, filters, namespace, nocache, explain)
Namespace: namespace, if err != nil {
NoCache: nocache, color.Red("Error: %v", err)
Filters: filters, os.Exit(1)
Explain: explain,
AIClient: aiClient,
Client: client,
Context: ctx,
} }
err = config.RunAnalysis() err = config.RunAnalysis()

View File

@@ -44,8 +44,6 @@ var ServeCmd = &cobra.Command{
Token: token, Token: token,
} }
fmt.Println(server)
err := server.Serve() err := server.Serve()
if err != nil { if err != nil {
color.Red("Error: %v", err) color.Red("Error: %v", err)

View File

@@ -5,6 +5,7 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"github.com/spf13/viper" "github.com/spf13/viper"
"strings" "strings"
) )
@@ -33,6 +34,7 @@ func (a *NoOpAIClient) Parse(ctx context.Context, prompt []string, nocache bool)
inputKey := strings.Join(prompt, " ") inputKey := strings.Join(prompt, " ")
// Check for cached data // Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey)) sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
cacheKey := util.GetCacheKey(a.GetName(), sEnc)
response, err := a.GetCompletion(ctx, inputKey) response, err := a.GetCompletion(ctx, inputKey)
if err != nil { if err != nil {
@@ -40,8 +42,8 @@ func (a *NoOpAIClient) Parse(ctx context.Context, prompt []string, nocache bool)
return "", err return "", err
} }
if !viper.IsSet(sEnc) { if !viper.IsSet(cacheKey) {
viper.Set(sEnc, base64.StdEncoding.EncodeToString([]byte(response))) viper.Set(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err := viper.WriteConfig(); err != nil { if err := viper.WriteConfig(); err != nil {
color.Red("error writing config: %v", err) color.Red("error writing config: %v", err)
return "", nil return "", nil

View File

@@ -5,6 +5,7 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"github.com/k8sgpt-ai/k8sgpt/pkg/util"
"strings" "strings"
"github.com/fatih/color" "github.com/fatih/color"
@@ -58,10 +59,11 @@ func (a *OpenAIClient) Parse(ctx context.Context, prompt []string, nocache bool)
inputKey := strings.Join(prompt, " ") inputKey := strings.Join(prompt, " ")
// Check for cached data // Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey)) sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
cacheKey := util.GetCacheKey(a.GetName(), sEnc)
// find in viper cache // find in viper cache
if viper.IsSet(sEnc) && !nocache { if viper.IsSet(cacheKey) && !nocache {
// retrieve data from cache // retrieve data from cache
response := viper.GetString(sEnc) response := viper.GetString(cacheKey)
if response == "" { if response == "" {
color.Red("error retrieving cached data") color.Red("error retrieving cached data")
return "", nil return "", nil
@@ -79,8 +81,8 @@ func (a *OpenAIClient) Parse(ctx context.Context, prompt []string, nocache bool)
return "", err return "", err
} }
if !viper.IsSet(sEnc) { if !viper.IsSet(cacheKey) || nocache {
viper.Set(sEnc, base64.StdEncoding.EncodeToString([]byte(response))) viper.Set(cacheKey, base64.StdEncoding.EncodeToString([]byte(response)))
if err := viper.WriteConfig(); err != nil { if err := viper.WriteConfig(); err != nil {
color.Red("error writing config: %v", err) color.Red("error writing config: %v", err)
return "", nil return "", nil

View File

@@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"os"
"strings" "strings"
"github.com/fatih/color" "github.com/fatih/color"
@@ -41,8 +42,61 @@ type JsonOutput struct {
Results []common.Result `json:"results"` Results []common.Result `json:"results"`
} }
func (a *Analysis) RunAnalysis() error { func NewAnalysis(backend string, language string, filters []string, namespace string, noCache bool, explain bool) (*Analysis, error) {
var configAI ai.AIConfiguration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
if len(configAI.Providers) == 0 {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
}
var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if backend == provider.Name {
aiProvider = provider
break
}
}
if aiProvider.Name == "" {
color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", backend)
return nil, errors.New("AI provider not specified in configuration")
}
aiClient := ai.NewClient(aiProvider.Name)
if err := aiClient.Configure(aiProvider.Password, aiProvider.Model, language); err != nil {
color.Red("Error: %v", err)
return nil, err
}
ctx := context.Background()
// Get kubernetes client from viper
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error initialising kubernetes client: %v", err)
return nil, err
}
return &Analysis{
Context: ctx,
Filters: filters,
Client: client,
AIClient: aiClient,
Namespace: namespace,
NoCache: noCache,
Explain: explain,
}, nil
}
func (a *Analysis) RunAnalysis() error {
activeFilters := viper.GetStringSlice("active_filters") activeFilters := viper.GetStringSlice("active_filters")
analyzerMap := analyzer.GetAnalyzerMap() analyzerMap := analyzer.GetAnalyzerMap()

View File

@@ -1,13 +1,9 @@
package server package server
import ( import (
"context"
"fmt" "fmt"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/analysis" "github.com/k8sgpt-ai/k8sgpt/pkg/analysis"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
"net/http" "net/http"
"os" "os"
) )
@@ -31,56 +27,9 @@ func (s *K8sGPTServer) analyzeHandler(w http.ResponseWriter, r *http.Request) {
nocache := getBoolParam(r.URL.Query().Get("nocache")) nocache := getBoolParam(r.URL.Query().Get("nocache"))
language := r.URL.Query().Get("language") language := r.URL.Query().Get("language")
// get ai configuration config, err := analysis.NewAnalysis(s.Backend, language, []string{}, namespace, nocache, explain)
var configAI ai.AIConfiguration
err := viper.UnmarshalKey("ai", &configAI)
if err != nil { if err != nil {
color.Red("Error: %v", err) fmt.Fprintf(w, err.Error())
os.Exit(1)
}
if len(configAI.Providers) == 0 {
color.Red("Error: AI provider not specified in configuration. Please run k8sgpt auth")
os.Exit(1)
}
var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if s.Backend == provider.Name {
aiProvider = provider
break
}
}
if aiProvider.Name == "" {
color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", s.Backend)
os.Exit(1)
}
aiClient := ai.NewClient(aiProvider.Name)
if err := aiClient.Configure(aiProvider.Password, aiProvider.Model, language); err != nil {
color.Red("Error: %v", err)
os.Exit(1)
}
ctx := context.Background()
// Get kubernetes client from viper
kubecontext := viper.GetString("kubecontext")
kubeconfig := viper.GetString("kubeconfig")
client, err := kubernetes.NewClient(kubecontext, kubeconfig)
if err != nil {
color.Red("Error initialising kubernetes client: %v", err)
os.Exit(1)
}
config := &analysis.Analysis{
Namespace: namespace,
Explain: explain,
AIClient: aiClient,
Client: client,
Context: ctx,
NoCache: nocache,
} }
err = config.RunAnalysis() err = config.RunAnalysis()
@@ -108,6 +57,7 @@ func (s *K8sGPTServer) analyzeHandler(w http.ResponseWriter, r *http.Request) {
func (s *K8sGPTServer) Serve() error { func (s *K8sGPTServer) Serve() error {
http.HandleFunc("/analyze", s.analyzeHandler) http.HandleFunc("/analyze", s.analyzeHandler)
color.Green("Starting server on port " + s.Port)
err := http.ListenAndServe(":"+s.Port, nil) err := http.ListenAndServe(":"+s.Port, nil)
if err != nil { if err != nil {
fmt.Printf("error starting server: %s\n", err) fmt.Printf("error starting server: %s\n", err)

View File

@@ -129,3 +129,7 @@ func ReplaceIfMatch(text string, pattern string, replacement string) string {
} }
return text return text
} }
func GetCacheKey(provider string, sEnc string) string {
return fmt.Sprintf("%s-%s", provider, sEnc)
}