diff --git a/README.md b/README.md
index af08021..f8d8f60 100644
--- a/README.md
+++ b/README.md
@@ -277,6 +277,38 @@ curl -X GET "http://localhost:8080/analyze?namespace=k8sgpt&explain=false"
## Additional AI providers
+### Setting a new default AI provider
+
+
+
+There may be scenarios where you wish to have K8sGPT plugged into several default AI providers. In this case you may wish to use one as a new default, other than OpenAI which is the project default.
+
+_To view available providers_
+
+```
+k8sgpt auth list
+Default:
+> openai
+Active:
+> openai
+> azureopenai
+Unused:
+> localai
+> noopai
+
+```
+
+_To set a new default provider_
+
+```
+k8sgpt auth default -p azureopenai
+Default provider set to azureopenai
+```
+
+
+
+
+
### Azure OpenAI
Prerequisites: 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.
@@ -286,7 +318,7 @@ To authenticate with k8sgpt, you will need the Azure OpenAI endpoint of your ten
### Run k8sgpt
To run k8sgpt, run `k8sgpt auth` with the `azureopenai` backend:
```
-k8sgpt auth --backend azureopenai --baseurl https:// --engine --model
+k8sgpt auth new --backend azureopenai --baseurl https:// --engine --model
```
Lastly, enter your Azure API key, after the prompt.
diff --git a/cmd/auth/auth.go b/cmd/auth/auth.go
index 914139a..45727de 100644
--- a/cmd/auth/auth.go
+++ b/cmd/auth/auth.go
@@ -48,4 +48,6 @@ func init() {
AuthCmd.AddCommand(newCmd)
// add subcommand to remove new backend provider
AuthCmd.AddCommand(removeCmd)
+ // add subcommand to set default backend provider
+ AuthCmd.AddCommand(defaultCmd)
}
diff --git a/cmd/auth/default.go b/cmd/auth/default.go
new file mode 100644
index 0000000..8b58293
--- /dev/null
+++ b/cmd/auth/default.go
@@ -0,0 +1,79 @@
+/*
+Copyright 2023 The K8sGPT Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package auth
+
+import (
+ "os"
+ "strings"
+
+ "github.com/fatih/color"
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+)
+
+var (
+ providerName string
+)
+
+var defaultCmd = &cobra.Command{
+ Use: "default",
+ Short: "Set your default AI backend provider",
+ Long: "The command to set your new default AI backend provider (default is openai)",
+ Run: func(cmd *cobra.Command, args []string) {
+ err := viper.UnmarshalKey("ai", &configAI)
+ if err != nil {
+ color.Red("Error: %v", err)
+ os.Exit(1)
+ }
+ if providerName == "" {
+ if configAI.DefaultProvider != "" {
+ color.Yellow("Your default provider is %s", configAI.DefaultProvider)
+ } else {
+ color.Yellow("Your default provider is openai")
+ }
+ os.Exit(0)
+ }
+ // lowercase the provider name
+ providerName = strings.ToLower(providerName)
+
+ // Check if the provider is in the provider list
+ providerExists := false
+ for _, provider := range configAI.Providers {
+ if provider.Name == providerName {
+ providerExists = true
+ }
+ }
+ if !providerExists {
+ color.Red("Error: Provider %s does not exist", providerName)
+ os.Exit(1)
+ }
+ // Set the default provider
+ configAI.DefaultProvider = providerName
+
+ viper.Set("ai", configAI)
+ // Viper write config
+ err = viper.WriteConfig()
+ if err != nil {
+ color.Red("Error: %v", err)
+ os.Exit(1)
+ }
+ // Print acknowledgement
+ color.Green("Default provider set to %s", providerName)
+ },
+}
+
+func init() {
+ // provider name flag
+ defaultCmd.Flags().StringVarP(&providerName, "provider", "p", "", "The name of the provider to set as default")
+}
diff --git a/cmd/auth/list.go b/cmd/auth/list.go
index 41b7ecd..09a75e3 100644
--- a/cmd/auth/list.go
+++ b/cmd/auth/list.go
@@ -18,6 +18,7 @@ import (
"os"
"github.com/fatih/color"
+ "github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -35,12 +36,37 @@ var listCmd = &cobra.Command{
os.Exit(1)
}
- // iterate over the provider list and prints each provider name
- for _, provider := range configAI.Providers {
- if len(configAI.Providers) == 0 {
- color.Red("Provider list is currently empty.")
- } else {
- fmt.Printf("> %s\n", provider.Name)
+ // Print the default if it is set
+ fmt.Print(color.YellowString("Default: \n"))
+ if configAI.DefaultProvider != "" {
+ fmt.Printf("> %s\n", color.BlueString(configAI.DefaultProvider))
+ } else {
+ fmt.Printf("> %s\n", color.BlueString("openai"))
+ }
+
+ // Get list of all AI Backends and only print htem if they are not in the provider list
+ fmt.Print(color.YellowString("Active: \n"))
+ for _, aiBackend := range ai.Backends {
+ providerExists := false
+ for _, provider := range configAI.Providers {
+ if provider.Name == aiBackend {
+ providerExists = true
+ }
+ }
+ if providerExists {
+ fmt.Printf("> %s\n", color.GreenString(aiBackend))
+ }
+ }
+ fmt.Print(color.YellowString("Unused: \n"))
+ for _, aiBackend := range ai.Backends {
+ providerExists := false
+ for _, provider := range configAI.Providers {
+ if provider.Name == aiBackend {
+ providerExists = true
+ }
+ }
+ if !providerExists {
+ fmt.Printf("> %s\n", color.RedString(aiBackend))
}
}
},
diff --git a/pkg/ai/iai.go b/pkg/ai/iai.go
index 767e1e5..bd4dd06 100644
--- a/pkg/ai/iai.go
+++ b/pkg/ai/iai.go
@@ -59,7 +59,8 @@ func NewClient(provider string) IAI {
}
type AIConfiguration struct {
- Providers []AIProvider `mapstructure:"providers"`
+ Providers []AIProvider `mapstructure:"providers"`
+ DefaultProvider string `mapstructure:"defaultprovider"`
}
type AIProvider struct {
diff --git a/pkg/analysis/analysis.go b/pkg/analysis/analysis.go
index b9f8ca5..1d82f1d 100644
--- a/pkg/analysis/analysis.go
+++ b/pkg/analysis/analysis.go
@@ -34,16 +34,17 @@ import (
)
type Analysis struct {
- Context context.Context
- Filters []string
- Client *kubernetes.Client
- AIClient ai.IAI
- Results []common.Result
- Errors []string
- Namespace string
- Cache cache.ICache
- Explain bool
- MaxConcurrency int
+ Context context.Context
+ Filters []string
+ Client *kubernetes.Client
+ AIClient ai.IAI
+ Results []common.Result
+ Errors []string
+ Namespace string
+ Cache cache.ICache
+ Explain bool
+ MaxConcurrency int
+ AnalysisAIProvider string // The name of the AI Provider used for this analysis
}
type AnalysisStatus string
@@ -55,6 +56,7 @@ const (
)
type JsonOutput struct {
+ Provider string `json:"provider"`
Errors AnalysisErrors `json:"errors"`
Status AnalysisStatus `json:"status"`
Problems int `json:"problems"`
@@ -74,6 +76,12 @@ func NewAnalysis(backend string, language string, filters []string, namespace st
os.Exit(1)
}
+ // Backend string will have high priority than a default provider
+ // Backend as "openai" represents the default CLI argument passed through
+ if configAI.DefaultProvider != "" && backend == "openai" {
+ backend = configAI.DefaultProvider
+ }
+
var aiProvider ai.AIProvider
for _, provider := range configAI.Providers {
if backend == provider.Name {
@@ -105,14 +113,15 @@ 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,
- MaxConcurrency: maxConcurrency,
+ Context: ctx,
+ Filters: filters,
+ Client: client,
+ AIClient: aiClient,
+ Namespace: namespace,
+ Cache: cache.New(noCache),
+ Explain: explain,
+ MaxConcurrency: maxConcurrency,
+ AnalysisAIProvider: backend,
}, nil
}
diff --git a/pkg/analysis/output.go b/pkg/analysis/output.go
index e445966..bfbc663 100644
--- a/pkg/analysis/output.go
+++ b/pkg/analysis/output.go
@@ -42,6 +42,7 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
}
result := JsonOutput{
+ Provider: a.AnalysisAIProvider,
Problems: problems,
Results: a.Results,
Errors: a.Errors,
@@ -56,6 +57,10 @@ func (a *Analysis) jsonOutput() ([]byte, error) {
func (a *Analysis) textOutput() ([]byte, error) {
var output strings.Builder
+
+ // Print the AI provider used for this analysis
+ output.WriteString(fmt.Sprintf("AI Provider: %s\n", color.YellowString(a.AnalysisAIProvider)))
+
if len(a.Errors) != 0 {
output.WriteString("\n")
output.WriteString(color.YellowString("Warnings : \n"))