diff --git a/.github/workflows/build_container.yaml b/.github/workflows/build_container.yaml index f0b73cc2cd..899ecc9f27 100644 --- a/.github/workflows/build_container.yaml +++ b/.github/workflows/build_container.yaml @@ -96,7 +96,7 @@ jobs: outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}-image.tar - name: Upload image as artifact - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4 with: name: ${{ env.IMAGE_NAME }}-image.tar path: /tmp/${{ env.IMAGE_NAME }}-image.tar diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d83e05b6c2..21bdea8795 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -49,7 +49,7 @@ jobs: with: go-version: '1.22' - name: Download Syft - uses: anchore/sbom-action/download-syft@95b086ac308035dc0850b3853be5b7ab108236a8 # v0.16.1 + uses: anchore/sbom-action/download-syft@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0 - name: Run GoReleaser uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6 with: @@ -106,7 +106,7 @@ jobs: cache-to: type=gha,scope=${{ github.ref_name }}-${{ env.IMAGE_TAG }} - name: Generate SBOM - uses: anchore/sbom-action@95b086ac308035dc0850b3853be5b7ab108236a8 # v0.16.1 + uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0 with: image: ${{ env.IMAGE_TAG }} artifact-name: sbom-${{ env.IMAGE_NAME }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9165e2d73c..5afac91d5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.3.39"} \ No newline at end of file +{".":"0.3.40"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b7a0152fa3..6d9f0b89eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [0.3.40](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.39...v0.3.40) (2024-08-04) + + +### Features + +* custom analysis paralelism ([#1203](https://github.com/k8sgpt-ai/k8sgpt/issues/1203)) ([f1b7b37](https://github.com/k8sgpt-ai/k8sgpt/commit/f1b7b37fb83937d5fad90d7b6b52f4a38823da9e)) +* getting the error from status field for HPA analyzer ([#1164](https://github.com/k8sgpt-ai/k8sgpt/issues/1164)) ([a068310](https://github.com/k8sgpt-ai/k8sgpt/commit/a068310731d775beecede03a1709e541ffd68142)) +* initial custom analysis server mode ([#1205](https://github.com/k8sgpt-ai/k8sgpt/issues/1205)) ([16d57e5](https://github.com/k8sgpt-ai/k8sgpt/commit/16d57e5a55c2084bf1580377ae52e2961cc84922)) + + +### Bug Fixes + +* add default maxToken value of watsonxai backend ([#1209](https://github.com/k8sgpt-ai/k8sgpt/issues/1209)) ([d43fd87](https://github.com/k8sgpt-ai/k8sgpt/commit/d43fd878ba04fec8ac8afe4a1c15272b7f21c951)) +* auth update throw out exception ([#1193](https://github.com/k8sgpt-ai/k8sgpt/issues/1193)) ([391a3cd](https://github.com/k8sgpt-ai/k8sgpt/commit/391a3cd5adcbd90f37922332b4fad5ba5d813e5f)) +* **deps:** update module cloud.google.com/go/storage to v1.43.0 ([#1198](https://github.com/k8sgpt-ai/k8sgpt/issues/1198)) ([8949f5b](https://github.com/k8sgpt-ai/k8sgpt/commit/8949f5bac3c69130e30103511fdb5ece66e1619f)) +* **deps:** update module github.com/schollz/progressbar/v3 to v3.14.5 ([#1145](https://github.com/k8sgpt-ai/k8sgpt/issues/1145)) ([3547c48](https://github.com/k8sgpt-ai/k8sgpt/commit/3547c4808a846eb4392996afa20a84bdddf8e24f)) + + +### Other + +* **deps:** update anchore/sbom-action action to v0.17.0 ([#1197](https://github.com/k8sgpt-ai/k8sgpt/issues/1197)) ([407c855](https://github.com/k8sgpt-ai/k8sgpt/commit/407c855e147b73739e800310c926826344d36323)) + ## [0.3.39](https://github.com/k8sgpt-ai/k8sgpt/compare/v0.3.38...v0.3.39) (2024-07-18) diff --git a/README.md b/README.md index d16f7ab0d9..86bd9d736e 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,7 @@ brew install k8sgpt **32 bit:** ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_386.rpm - sudo rpm -ivh k8sgpt_386.rpm + sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.rpm ``` @@ -56,8 +55,7 @@ brew install k8sgpt ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_amd64.rpm - sudo rpm -ivh -i k8sgpt_amd64.rpm + sudo rpm -ivh https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.rpm ``` @@ -68,7 +66,7 @@ brew install k8sgpt **32 bit:** ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_386.deb + curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.deb sudo dpkg -i k8sgpt_386.deb ``` @@ -76,7 +74,7 @@ brew install k8sgpt ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_amd64.deb + curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.deb sudo dpkg -i k8sgpt_amd64.deb ``` @@ -89,17 +87,17 @@ brew install k8sgpt **32 bit:** ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_386.apk - apk add k8sgpt_386.apk + wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_386.apk + apk add --allow-untrusted k8sgpt_386.apk ``` **64 bit:** ``` - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.39/k8sgpt_amd64.apk - apk add k8sgpt_amd64.apk + wget https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.3.40/k8sgpt_amd64.apk + apk add --allow-untrusted k8sgpt_amd64.apk ``` - x +
@@ -504,6 +502,21 @@ This now gives the ability to pass through hostOS information ( from this analyz _See the docs on how to write a custom analyzer_ +_Listing custom analyzers configured_ +``` +k8sgpt custom-analyzer list +``` + +_Adding custom analyzer without install_ +``` +k8sgpt custom-analyzer add --name my-custom-analyzer --port 8085 +``` + +_Removing custom analyzer_ +``` +k8sgpt custom-analyzer remove --names "my-custom-analyzer,my-custom-analyzer-2" +``` +
## Documentation diff --git a/cmd/customAnalyzer/add.go b/cmd/customAnalyzer/add.go new file mode 100644 index 0000000000..91dbdb9896 --- /dev/null +++ b/cmd/customAnalyzer/add.go @@ -0,0 +1,73 @@ +/* +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 customanalyzer + +import ( + "os" + + "github.com/fatih/color" + customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + name string + url string + port int +) + +var addCmd = &cobra.Command{ + Use: "add", + Aliases: []string{"add"}, + Short: "This command will add a custom analyzer from source", + Long: "This command allows you to add/remote/list an existing custom analyzer.", + Run: func(cmd *cobra.Command, args []string) { + err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer) + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + analyzer := customAnalyzer.NewCustomAnalyzer() + + // Check if configuration is valid + err = analyzer.Check(configCustomAnalyzer, name, url, port) + if err != nil { + color.Red("Error adding custom analyzer: %s", err.Error()) + os.Exit(1) + } + + configCustomAnalyzer = append(configCustomAnalyzer, customAnalyzer.CustomAnalyzerConfiguration{ + Name: name, + Connection: customAnalyzer.Connection{ + Url: url, + Port: port, + }, + }) + + viper.Set("custom_analyzers", configCustomAnalyzer) + if err := viper.WriteConfig(); err != nil { + color.Red("Error writing config file: %s", err.Error()) + os.Exit(1) + } + color.Green("%s added to the custom analyzers config list", name) + + }, +} + +func init() { + addCmd.Flags().StringVarP(&name, "name", "n", "my-custom-analyzer", "Name of the custom analyzer.") + addCmd.Flags().StringVarP(&url, "url", "u", "localhost", "URL for the custom analyzer connection.") + addCmd.Flags().IntVarP(&port, "port", "r", 8085, "Port for the custom analyzer connection.") +} diff --git a/cmd/customAnalyzer/customAnalyzer.go b/cmd/customAnalyzer/customAnalyzer.go new file mode 100644 index 0000000000..934ad7d4e2 --- /dev/null +++ b/cmd/customAnalyzer/customAnalyzer.go @@ -0,0 +1,43 @@ +/* +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 customanalyzer + +import ( + customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer" + "github.com/spf13/cobra" +) + +var configCustomAnalyzer []customAnalyzer.CustomAnalyzerConfiguration + +// authCmd represents the auth command +var CustomAnalyzerCmd = &cobra.Command{ + Use: "custom-analyzer", + Short: "Manage a custom analyzer", + Long: `This command allows you to manage custom analyzers, including adding, removing, and listing them.`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + _ = cmd.Help() + return + } + }, +} + +func init() { + // add subcommand to add custom analyzer + CustomAnalyzerCmd.AddCommand(addCmd) + // remove subcomment to remove custom analyzer + CustomAnalyzerCmd.AddCommand(removeCmd) + // list subcomment to list custom analyzer + CustomAnalyzerCmd.AddCommand(listCmd) +} diff --git a/cmd/customAnalyzer/list.go b/cmd/customAnalyzer/list.go new file mode 100644 index 0000000000..d7027aa362 --- /dev/null +++ b/cmd/customAnalyzer/list.go @@ -0,0 +1,60 @@ +/* +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 customanalyzer + +import ( + "fmt" + "os" + + "github.com/fatih/color" + customAnalyzer "github.com/k8sgpt-ai/k8sgpt/pkg/custom_analyzer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var details bool + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List configured custom analyzers", + Long: "The list command displays a list of configured custom analyzers", + Run: func(cmd *cobra.Command, args []string) { + + // get custom_analyzers configuration + err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer) + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + + // Get list of all Custom Analyers configured + fmt.Print(color.YellowString("Active: \n")) + for _, analyzer := range configCustomAnalyzer { + fmt.Printf("> %s\n", color.GreenString(analyzer.Name)) + if details { + printDetails(analyzer) + } + } + }, +} + +func init() { + listCmd.Flags().BoolVar(&details, "details", false, "Print custom analyzers configuration details") +} + +func printDetails(analyzer customAnalyzer.CustomAnalyzerConfiguration) { + fmt.Printf(" - Url: %s\n", analyzer.Connection.Url) + fmt.Printf(" - Port: %d\n", analyzer.Connection.Port) + +} diff --git a/cmd/customAnalyzer/remove.go b/cmd/customAnalyzer/remove.go new file mode 100644 index 0000000000..f9f19471c9 --- /dev/null +++ b/cmd/customAnalyzer/remove.go @@ -0,0 +1,90 @@ +/* +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 customanalyzer + +import ( + "os" + "strings" + + "github.com/fatih/color" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + names string +) + +var removeCmd = &cobra.Command{ + Use: "remove", + Short: "Remove custom analyzer(s)", + Long: "The command to remove custom analyzer(s)", + PreRun: func(cmd *cobra.Command, args []string) { + // Ensure that the "names" flag is provided before running the command + _ = cmd.MarkFlagRequired("names") + }, + Run: func(cmd *cobra.Command, args []string) { + if names == "" { + // Display an error message and show command help if "names" is not set + color.Red("Error: names must be set.") + _ = cmd.Help() + return + } + // Split the provided names by comma + inputCustomAnalyzers := strings.Split(names, ",") + + // Load the custom analyzers from the configuration file + err := viper.UnmarshalKey("custom_analyzers", &configCustomAnalyzer) + if err != nil { + // Display an error message if the configuration cannot be loaded + color.Red("Error: %v", err) + os.Exit(1) + } + + // Iterate over each input analyzer name + for _, inputAnalyzer := range inputCustomAnalyzers { + foundAnalyzer := false + // Search for the analyzer in the current configuration + for i, analyzer := range configCustomAnalyzer { + if analyzer.Name == inputAnalyzer { + foundAnalyzer = true + + // Remove the analyzer from the configuration list + configCustomAnalyzer = append(configCustomAnalyzer[:i], configCustomAnalyzer[i+1:]...) + color.Green("%s deleted from the custom analyzer list", analyzer.Name) + break + } + } + if !foundAnalyzer { + // Display an error if the analyzer is not found in the configuration + color.Red("Error: %s does not exist in configuration file. Please use k8sgpt custom-analyzer add.", inputAnalyzer) + os.Exit(1) + } + } + + // Save the updated configuration back to the file + viper.Set("custom_analyzers", configCustomAnalyzer) + if err := viper.WriteConfig(); err != nil { + // Display an error if the configuration cannot be written + color.Red("Error writing config file: %s", err.Error()) + os.Exit(1) + } + + }, +} + +func init() { + // add flag for names + removeCmd.Flags().StringVarP(&names, "names", "n", "", "Custom analyzers to remove (separated by a comma)") +} diff --git a/cmd/root.go b/cmd/root.go index 13f74dd40c..16e1b2c0d8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -22,6 +22,7 @@ import ( "github.com/k8sgpt-ai/k8sgpt/cmd/analyze" "github.com/k8sgpt-ai/k8sgpt/cmd/auth" "github.com/k8sgpt-ai/k8sgpt/cmd/cache" + customanalyzer "github.com/k8sgpt-ai/k8sgpt/cmd/customAnalyzer" "github.com/k8sgpt-ai/k8sgpt/cmd/filters" "github.com/k8sgpt-ai/k8sgpt/cmd/generate" "github.com/k8sgpt-ai/k8sgpt/cmd/integration" @@ -74,6 +75,7 @@ func init() { rootCmd.AddCommand(integration.IntegrationCmd) rootCmd.AddCommand(serve.ServeCmd) rootCmd.AddCommand(cache.CacheCmd) + rootCmd.AddCommand(customanalyzer.CustomAnalyzerCmd) rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", fmt.Sprintf("Default config file (%s/k8sgpt/k8sgpt.yaml)", xdg.ConfigHome)) rootCmd.PersistentFlags().StringVar(&kubecontext, "kubecontext", "", "Kubernetes context to use. Only required if out-of-cluster.") rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 1984ac9805..be20f8564a 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -149,7 +149,7 @@ var ServeCmd = &cobra.Command{ } } - if aiProvider.Name == "" { + if aiProvider == nil || aiProvider.Name == "" { color.Red("Error: AI provider %s not specified in configuration. Please run k8sgpt auth", backend) os.Exit(1) } diff --git a/go.mod b/go.mod index aa28c20151..2482c17346 100644 --- a/go.mod +++ b/go.mod @@ -12,11 +12,11 @@ require ( github.com/mittwald/go-helm-client v0.12.10 github.com/ollama/ollama v0.1.48 github.com/sashabaranov/go-openai v1.23.0 - github.com/schollz/progressbar/v3 v3.14.2 + github.com/schollz/progressbar/v3 v3.14.5 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 - golang.org/x/term v0.21.0 + golang.org/x/term v0.22.0 helm.sh/helm/v3 v3.15.2 k8s.io/api v0.30.2 k8s.io/apimachinery v0.30.2 @@ -29,15 +29,16 @@ require github.com/adrg/xdg v0.4.0 require ( buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1 - buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3 - buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2 - cloud.google.com/go/storage v1.40.0 + buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240720172138-1b9bcd834f17.2 + buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240720172138-1b9bcd834f17.2 + cloud.google.com/go/storage v1.43.0 cloud.google.com/go/vertexai v0.7.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/IBM/watsonx-go v1.0.1 github.com/aws/aws-sdk-go v1.53.21 github.com/cohere-ai/cohere-go/v2 v2.7.3 + github.com/go-logr/zapr v1.3.0 github.com/google/generative-ai-go v0.11.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hupe1980/go-huggingface v0.0.15 @@ -46,7 +47,7 @@ require ( github.com/oracle/oci-go-sdk/v65 v65.65.1 github.com/prometheus/prometheus v0.53.1 github.com/pterm/pterm v0.12.79 - google.golang.org/api v0.183.0 + google.golang.org/api v0.187.0 gopkg.in/yaml.v2 v2.4.0 sigs.k8s.io/controller-runtime v0.18.4 sigs.k8s.io/gateway-api v1.0.0 @@ -56,10 +57,10 @@ require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect - cloud.google.com/go v0.114.0 // indirect + cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/ai v0.3.5-0.20240409161017-ce55ad694f21 // indirect - cloud.google.com/go/aiplatform v1.67.0 // indirect - cloud.google.com/go/auth v0.5.1 // indirect + cloud.google.com/go/aiplatform v1.68.0 // indirect + cloud.google.com/go/auth v0.6.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.8 // indirect @@ -67,6 +68,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.4 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect @@ -75,6 +77,7 @@ require ( github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -85,7 +88,7 @@ require ( github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.4 // indirect + github.com/googleapis/gax-go/v2 v2.12.5 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/websocket v1.5.2 // indirect github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect @@ -93,6 +96,7 @@ require ( github.com/jpillora/backoff v1.0.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect @@ -108,9 +112,9 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect go.opentelemetry.io/otel/metric v1.27.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect + google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect knative.dev/pkg v0.0.0-20230616134650-eb63a40adfb0 // indirect @@ -140,9 +144,9 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/cli v26.1.4+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.0.0+incompatible // indirect + github.com/docker/docker v27.0.0+incompatible github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-connections v0.5.0 github.com/docker/go-metrics v0.0.1 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/evanphx/json-patch v5.9.0+incompatible // indirect @@ -235,7 +239,7 @@ require ( golang.org/x/net v0.26.0 golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect @@ -261,3 +265,4 @@ require ( // v1.2.0 is taken from github.com/open-policy-agent/opa v0.42.0 // v1.2.0 incompatible with github.com/docker/docker v23.0.0-rc.1+incompatible //replace oras.land/oras-go => oras.land/oras-go v1.2.4 +replace github.com/docker/docker => github.com/docker/docker v27.1.1+incompatible diff --git a/go.sum b/go.sum index dc737049ac..1e6b2cd1a1 100644 --- a/go.sum +++ b/go.sum @@ -8,20 +8,13 @@ atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1 h1:0x36l6ETxg5YDlfFTxSR+4SpL0bwLezTCUfGdcPUN44= buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1/go.mod h1:/n44w/baTCuEmDgCBgSxQ2GEiO7N645eKxLKbygzW4s= -buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240717144446-c4efcc29ff16.2 h1:68+/5HyHF3WAm5PtNvRwuzSqTD/im9JlylgyneHCPVY= -buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240717144446-c4efcc29ff16.2/go.mod h1:eYww1zlm6K5Tfwo3AfcVNMhnGJXR32t/PbZiPbvzv4s= -buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3 h1:EiautHLlnNmBZdh1wFpmrSDvV4t8sucXGwV6vaE8Xuc= buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3/go.mod h1:4QVX5iWdNcwSFhpXXIXwVH7qT/g9LKvxiqa0SvYJ9hE= -buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240717144446-c4efcc29ff16.3 h1:3HaNXtw/bEPWPXSqwLgEtBvqh39HLPYnFzG5UmZ00hs= -buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240717144446-c4efcc29ff16.3/go.mod h1:2FnWdzuB/BRUpuEQ71s/EviXJvVzzlHv8BvTlFFYgmQ= +buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240720172138-1b9bcd834f17.2 h1:/NS8lwYyuLPJqiI0q7IwqFnJeMjX0BJFmZCA7mTayjg= +buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240720172138-1b9bcd834f17.2/go.mod h1:3aZ3RYlHseQY62oAtqo5Oh5XN78nogunCXJQdxB2YO0= buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.0-20240406062209-1cc152efbf5c.1/go.mod h1:qFzoT6sNuRF9vPeDFmxd9KZ1YgU2vnnno5E5I0OUjOc= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.0-20240717144446-c4efcc29ff16.1/go.mod h1:qFzoT6sNuRF9vPeDFmxd9KZ1YgU2vnnno5E5I0OUjOc= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240406062209-1cc152efbf5c.1 h1:DLKuL/RwZg0bRweSS18Bi67GzKOW3F6YnVU0nZYXZBU= buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240406062209-1cc152efbf5c.1/go.mod h1:qEarbrHjaZEQ5GeUH6XqSqqJMvtPwAGFpAc0nkSBzrQ= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240717144446-c4efcc29ff16.1 h1:TJj+JSRc64sitUGL1XaCPY/OU090/5lNi4ABLG9jTSQ= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240717144446-c4efcc29ff16.1/go.mod h1:qEarbrHjaZEQ5GeUH6XqSqqJMvtPwAGFpAc0nkSBzrQ= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2 h1:INIYy743CJ4MEZu+O4by7oeC/m+a/l4HBk79FshPGBI= -buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2/go.mod h1:1wq1qVxvJkTEUQsF5/XjmhQYXYhbVoLSGhKnzS3ie54= +buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240720172138-1b9bcd834f17.2 h1:IGBeVvzzeoEl0Ck0uxWXIUn8/my/ZeBvQEIaXCLteOc= +buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240720172138-1b9bcd834f17.2/go.mod h1:1wq1qVxvJkTEUQsF5/XjmhQYXYhbVoLSGhKnzS3ie54= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -70,8 +63,8 @@ cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJN cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= -cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= -cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -110,8 +103,8 @@ cloud.google.com/go/aiplatform v1.57.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv6 cloud.google.com/go/aiplatform v1.58.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv65IHILGA//VEU= cloud.google.com/go/aiplatform v1.58.2/go.mod h1:c3kCiVmb6UC1dHAjZjcpDj6ZS0bHQ2slL88ZjC2LtlA= cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM= -cloud.google.com/go/aiplatform v1.67.0 h1:YWeqD4BjYwrmY4fa+isGcw0P81lJ3dKVxbWxdBchoiU= -cloud.google.com/go/aiplatform v1.67.0/go.mod h1:s/sJ6btBEr6bKnrNWdK9ZgHCvwbZNdP90b3DDtxxw+Y= +cloud.google.com/go/aiplatform v1.68.0 h1:EPPqgHDJpBZKRvv+OsB3cr0jYz3EL2pZ+802rBPcG8U= +cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhRAeNdnDKJczME= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= @@ -212,8 +205,8 @@ cloud.google.com/go/assuredworkloads v1.11.2/go.mod h1:O1dfr+oZJMlE6mw0Bp0P1KZSl cloud.google.com/go/assuredworkloads v1.11.3/go.mod h1:vEjfTKYyRUaIeA0bsGJceFV2JKpVRgyG2op3jfa59Zs= cloud.google.com/go/assuredworkloads v1.11.4/go.mod h1:4pwwGNwy1RP0m+y12ef3Q/8PaiWrIDQ6nD2E8kvWI9U= cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= -cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= -cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= +cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= +cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= @@ -1204,8 +1197,8 @@ cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7Biccwk cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k= cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= -cloud.google.com/go/storage v1.40.0 h1:VEpDQV5CJxFmJ6ueWNsKxcr1QAYOXEgxDa+sBbJahPw= -cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= @@ -1504,6 +1497,9 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembj github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= @@ -1579,8 +1575,8 @@ github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwen github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.0.0+incompatible h1:JRugTYuelmWlW0M3jakcIadDx2HUoUO6+Tf2C5jVfwA= -github.com/docker/docker v27.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -1872,8 +1868,8 @@ github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5i github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= @@ -2104,6 +2100,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -2228,8 +2226,8 @@ github.com/sashabaranov/go-openai v1.23.0 h1:KYW97r5yc35PI2MxeLZ3OofecB/6H+yxvSN github.com/sashabaranov/go-openai v1.23.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/schollz/progressbar/v3 v3.14.2 h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyMFIEa99ks= -github.com/schollz/progressbar/v3 v3.14.2/go.mod h1:aQAZQnhF4JGFtRJiw/eobaXpsqpVQAftEQ+hLGXaRc4= +github.com/schollz/progressbar/v3 v3.14.5 h1:97RrSxbBASxQuZN9yemnyGrFZ/swnG6IrEe2R0BseX8= +github.com/schollz/progressbar/v3 v3.14.5/go.mod h1:Nrzpuw3Nl0srLY0VlTvC4V6RL50pcEymjy6qyJAaLa0= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -2356,6 +2354,10 @@ go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFu go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= @@ -2379,6 +2381,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.starlark.net v0.0.0-20240520160348-046347dcd104 h1:3qhteRISupnJvaWshOmeqEUs2y9oc/+/ePPvDh3Eygg= go.starlark.net v0.0.0-20240520160348-046347dcd104/go.mod h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -2733,8 +2737,8 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -2757,8 +2761,8 @@ golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2956,8 +2960,8 @@ google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYl google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= -google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= -google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= +google.golang.org/api v0.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= +google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -3127,8 +3131,8 @@ google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqt google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE= -google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= +google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls= +google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M= google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= @@ -3161,8 +3165,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go. google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw= @@ -3208,8 +3212,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -3322,7 +3326,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= helm.sh/helm/v3 v3.15.2 h1:/3XINUFinJOBjQplGnjw92eLGpgXXp1L8chWPkCkDuw= diff --git a/pkg/ai/watsonxai.go b/pkg/ai/watsonxai.go index f6ce81c1a6..655b8b82d2 100644 --- a/pkg/ai/watsonxai.go +++ b/pkg/ai/watsonxai.go @@ -1,10 +1,10 @@ package ai import ( - "os" - "fmt" "context" "errors" + "fmt" + "os" wx "github.com/IBM/watsonx-go/pkg/models" ) @@ -14,28 +14,33 @@ const watsonxAIClientName = "watsonxai" type WatsonxAIClient struct { nopCloser - client *wx.Client - model string - temperature float32 - topP float32 - topK int32 - maxNewTokens int + client *wx.Client + model string + temperature float32 + topP float32 + topK int32 + maxNewTokens int } const ( modelMetallama = "ibm/granite-13b-chat-v2" + maxTokens = 2048 ) func (c *WatsonxAIClient) Configure(config IAIConfig) error { - if(config.GetModel() == "") { + if config.GetModel() == "" { + c.model = modelMetallama + } else { c.model = config.GetModel() + } + if config.GetMaxTokens() == 0 { + c.maxNewTokens = maxTokens } else { - c.model = modelMetallama + c.maxNewTokens = config.GetMaxTokens() } c.temperature = config.GetTemperature() c.topP = config.GetTopP() c.topK = config.GetTopK() - c.maxNewTokens = config.GetMaxTokens() // WatsonxAPIKeyEnvVarName = "WATSONX_API_KEY" // WatsonxProjectIDEnvVarName = "WATSONX_PROJECT_ID" @@ -75,7 +80,6 @@ func (c *WatsonxAIClient) GetCompletion(ctx context.Context, prompt string) (str if result.Text == "" { return "", errors.New("Expected a result, but got an empty string") } - return result.Text, nil } diff --git a/pkg/analysis/analysis.go b/pkg/analysis/analysis.go index d8c9b59d40..1a28c9846a 100644 --- a/pkg/analysis/analysis.go +++ b/pkg/analysis/analysis.go @@ -160,27 +160,57 @@ func NewAnalysis( return a, nil } +func (a *Analysis) CustomAnalyzersAreAvailable() bool { + var customAnalyzers []custom.CustomAnalyzer + if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil { + return false + } + return len(customAnalyzers) > 0 +} + func (a *Analysis) RunCustomAnalysis() { var customAnalyzers []custom.CustomAnalyzer if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil { a.Errors = append(a.Errors, err.Error()) + return } + semaphore := make(chan struct{}, a.MaxConcurrency) + var wg sync.WaitGroup + var mutex sync.Mutex for _, cAnalyzer := range customAnalyzers { + wg.Add(1) + semaphore <- struct{}{} + go func(analyzer custom.CustomAnalyzer, wg *sync.WaitGroup, semaphore chan struct{}) { + defer wg.Done() + canClient, err := custom.NewClient(cAnalyzer.Connection) + if err != nil { + mutex.Lock() + a.Errors = append(a.Errors, fmt.Sprintf("Client creation error for %s analyzer", cAnalyzer.Name)) + mutex.Unlock() + return + } - canClient, err := custom.NewClient(cAnalyzer.Connection) - if err != nil { - a.Errors = append(a.Errors, fmt.Sprintf("Client creation error for %s analyzer", cAnalyzer.Name)) - continue - } - - result, err := canClient.Run() - if err != nil { - a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", cAnalyzer.Name, err)) - } else { - a.Results = append(a.Results, result) - } + result, err := canClient.Run() + if result.Kind == "" { + // for custom analyzer name, we must use a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', + //and must start and end with an alphanumeric character (e.g. 'example.com', + //regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*') + result.Kind = cAnalyzer.Name + } + if err != nil { + mutex.Lock() + a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", cAnalyzer.Name, err)) + mutex.Unlock() + } else { + mutex.Lock() + a.Results = append(a.Results, result) + mutex.Unlock() + } + <-semaphore + }(cAnalyzer, &wg, semaphore) } + wg.Wait() } func (a *Analysis) RunAnalysis() { @@ -209,10 +239,10 @@ func (a *Analysis) RunAnalysis() { } semaphore := make(chan struct{}, a.MaxConcurrency) + var wg sync.WaitGroup + var mutex sync.Mutex // if there are no filters selected and no active_filters then run coreAnalyzer if len(a.Filters) == 0 && len(activeFilters) == 0 { - var wg sync.WaitGroup - var mutex sync.Mutex for _, analyzer := range coreAnalyzerMap { wg.Add(1) semaphore <- struct{}{} @@ -234,11 +264,8 @@ func (a *Analysis) RunAnalysis() { wg.Wait() return } - semaphore = make(chan struct{}, a.MaxConcurrency) // if the filters flag is specified if len(a.Filters) != 0 { - var wg sync.WaitGroup - var mutex sync.Mutex for _, filter := range a.Filters { if analyzer, ok := analyzerMap[filter]; ok { semaphore <- struct{}{} @@ -264,9 +291,6 @@ func (a *Analysis) RunAnalysis() { return } - var wg sync.WaitGroup - var mutex sync.Mutex - semaphore = make(chan struct{}, a.MaxConcurrency) // use active_filters for _, filter := range activeFilters { if analyzer, ok := analyzerMap[filter]; ok { diff --git a/pkg/analyzer/hpa.go b/pkg/analyzer/hpa.go index 0606d00c22..1561b6dbae 100644 --- a/pkg/analyzer/hpa.go +++ b/pkg/analyzer/hpa.go @@ -43,7 +43,7 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { "analyzer_name": kind, }) - list, err := a.Client.GetClient().AutoscalingV1().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector}) + list, err := a.Client.GetClient().AutoscalingV2().HorizontalPodAutoscalers(a.Namespace).List(a.Context, metav1.ListOptions{LabelSelector: a.LabelSelector}) if err != nil { return nil, err } @@ -53,6 +53,18 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { for _, hpa := range list.Items { var failures []common.Failure + + //check the error from status field + conditions := hpa.Status.Conditions + for _, condition := range conditions { + if condition.Status != "True" { + failures = append(failures, common.Failure{ + Text: condition.Message, + Sensitive: []common.Sensitive{}, + }) + } + } + // check ScaleTargetRef exist scaleTargetRef := hpa.Spec.ScaleTargetRef var podInfo PodInfo diff --git a/pkg/analyzer/hpaAnalyzer_test.go b/pkg/analyzer/hpaAnalyzer_test.go index 2be0d1049a..a341a46a53 100644 --- a/pkg/analyzer/hpaAnalyzer_test.go +++ b/pkg/analyzer/hpaAnalyzer_test.go @@ -22,7 +22,7 @@ import ( "github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes" "github.com/magiconair/properties/assert" appsv1 "k8s.io/api/apps/v1" - autoscalingv1 "k8s.io/api/autoscaling/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,7 +31,7 @@ import ( func TestHPAAnalyzer(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", @@ -55,14 +55,14 @@ func TestHPAAnalyzer(t *testing.T) { func TestHPAAnalyzerWithMultipleHPA(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, }, - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example-2", Namespace: "default", @@ -88,14 +88,14 @@ func TestHPAAnalyzerWithMultipleHPA(t *testing.T) { func TestHPAAnalyzerWithUnsuportedScaleTargetRef(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "unsupported", }, }, @@ -134,14 +134,14 @@ func TestHPAAnalyzerWithUnsuportedScaleTargetRef(t *testing.T) { func TestHPAAnalyzerWithNonExistentScaleTargetRef(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", Name: "non-existent", }, @@ -181,14 +181,14 @@ func TestHPAAnalyzerWithNonExistentScaleTargetRef(t *testing.T) { func TestHPAAnalyzerWithExistingScaleTargetRefAsDeployment(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", Name: "example", }, @@ -245,14 +245,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsDeployment(t *testing.T) { func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicationController(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "ReplicationController", Name: "example", }, @@ -309,14 +309,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicationController(t *testing func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicaSet(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "ReplicaSet", Name: "example", }, @@ -373,14 +373,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsReplicaSet(t *testing.T) { func TestHPAAnalyzerWithExistingScaleTargetRefAsStatefulSet(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "StatefulSet", Name: "example", }, @@ -437,14 +437,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefAsStatefulSet(t *testing.T) { func TestHPAAnalyzerWithExistingScaleTargetRefWithoutSpecifyingResources(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, - Spec: autoscalingv1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", Name: "example", }, @@ -503,14 +503,14 @@ func TestHPAAnalyzerWithExistingScaleTargetRefWithoutSpecifyingResources(t *test func TestHPAAnalyzerNamespaceFiltering(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", Annotations: map[string]string{}, }, }, - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "other-namespace", @@ -534,7 +534,7 @@ func TestHPAAnalyzerNamespaceFiltering(t *testing.T) { func TestHPAAnalyzerLabelSelectorFiltering(t *testing.T) { clientset := fake.NewSimpleClientset( - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "default", @@ -543,7 +543,7 @@ func TestHPAAnalyzerLabelSelectorFiltering(t *testing.T) { }, }, }, - &autoscalingv1.HorizontalPodAutoscaler{ + &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: "example2", Namespace: "default", @@ -565,3 +565,178 @@ func TestHPAAnalyzerLabelSelectorFiltering(t *testing.T) { } assert.Equal(t, len(analysisResults), 1) } + + +func TestHPAAnalyzerStatusFieldAbleToScale(t *testing.T) { + clientset := fake.NewSimpleClientset( + &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + Name: "example", + }, + }, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{ + Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{ + { + Type: "AbleToScale", + Status: "False", + Message: "test reason", + }, + }, + }, + }) + hpaAnalyzer := HpaAnalyzer{} + config := common.Analyzer{ + Client: &kubernetes.Client{ + Client: clientset, + }, + Context: context.Background(), + Namespace: "default", + } + analysisResults, err := hpaAnalyzer.Analyze(config) + if err != nil { + t.Error(err) + } + assert.Equal(t, len(analysisResults), 1) + +} + + +func TestHPAAnalyzerStatusFieldScalingActive(t *testing.T) { + clientset := fake.NewSimpleClientset( + &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + Name: "example", + }, + }, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{ + Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{ + { + Type: autoscalingv2.ScalingActive, + Status: "False", + Message: "test reason", + }, + }, + }, + }) + hpaAnalyzer := HpaAnalyzer{} + config := common.Analyzer{ + Client: &kubernetes.Client{ + Client: clientset, + }, + Context: context.Background(), + Namespace: "default", + } + analysisResults, err := hpaAnalyzer.Analyze(config) + if err != nil { + t.Error(err) + } + assert.Equal(t, len(analysisResults), 1) + +} + + + +func TestHPAAnalyzerStatusFieldScalingLimited(t *testing.T) { + clientset := fake.NewSimpleClientset( + &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + Name: "example", + }, + }, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{ + Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{ + { + Type: autoscalingv2.ScalingLimited, + Status: "False", + Message: "test reason", + }, + }, + }, + }) + hpaAnalyzer := HpaAnalyzer{} + config := common.Analyzer{ + Client: &kubernetes.Client{ + Client: clientset, + }, + Context: context.Background(), + Namespace: "default", + } + analysisResults, err := hpaAnalyzer.Analyze(config) + if err != nil { + t.Error(err) + } + assert.Equal(t, len(analysisResults), 1) + +} + + +func TestHPAAnalyzerStatusField(t *testing.T) { + clientset := fake.NewSimpleClientset( + &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + Name: "example", + }, + }, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{ + Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{ + { + Type: autoscalingv2.AbleToScale, + Status: "True", + Message: "recommended size matches current size", + }, + { + Type: autoscalingv2.ScalingActive, + Status: "True", + Message: "the HPA was able to successfully calculate a replica count", + }, + { + Type: autoscalingv2.ScalingLimited, + Status: "True", + Message: "the desired replica count is less than the minimum replica count", + }, + }, + }, + }) + hpaAnalyzer := HpaAnalyzer{} + config := common.Analyzer{ + Client: &kubernetes.Client{ + Client: clientset, + }, + Context: context.Background(), + Namespace: "default", + } + analysisResults, err := hpaAnalyzer.Analyze(config) + if err != nil { + t.Error(err) + } + assert.Equal(t, len(analysisResults), 1) + +} \ No newline at end of file diff --git a/pkg/common/types.go b/pkg/common/types.go index 9a3341804f..98c14140c5 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -24,7 +24,7 @@ import ( kyverno "github.com/kyverno/policy-reporter-kyverno-plugin/pkg/crd/api/policyreport/v1alpha2" regv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" - autov1 "k8s.io/api/autoscaling/v1" + autov2 "k8s.io/api/autoscaling/v2" v1 "k8s.io/api/core/v1" networkv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" @@ -54,7 +54,7 @@ type PreAnalysis struct { PersistentVolumeClaim v1.PersistentVolumeClaim Endpoint v1.Endpoints Ingress networkv1.Ingress - HorizontalPodAutoscalers autov1.HorizontalPodAutoscaler + HorizontalPodAutoscalers autov2.HorizontalPodAutoscaler PodDisruptionBudget policyv1.PodDisruptionBudget StatefulSet appsv1.StatefulSet NetworkPolicy networkv1.NetworkPolicy diff --git a/pkg/custom_analyzer/customAnalyzer.go b/pkg/custom_analyzer/customAnalyzer.go new file mode 100644 index 0000000000..ed3e03acce --- /dev/null +++ b/pkg/custom_analyzer/customAnalyzer.go @@ -0,0 +1,46 @@ +package custom_analyzer + +import ( + "fmt" + "reflect" + "regexp" +) + +type CustomAnalyzerConfiguration struct { + Name string `mapstructure:"name"` + Connection Connection `mapstructure:"connection"` +} + +type Connection struct { + Url string `mapstructure:"url"` + Port int `mapstructure:"port"` +} + +type CustomAnalyzer struct{} + +func NewCustomAnalyzer() *CustomAnalyzer { + return &CustomAnalyzer{} +} + +func (*CustomAnalyzer) Check(actualConfig []CustomAnalyzerConfiguration, name, url string, port int) error { + validNameRegex := `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + validName := regexp.MustCompile(validNameRegex) + if !validName.MatchString(name) { + return fmt.Errorf("invalid name format. Must match %s", validNameRegex) + } + + for _, analyzer := range actualConfig { + if analyzer.Name == name { + return fmt.Errorf("custom analyzer with the name '%s' already exists. Please use a different name", name) + } + + if reflect.DeepEqual(analyzer.Connection, Connection{ + Url: url, + Port: port, + }) { + return fmt.Errorf("custom analyzer with the same connection configuration (URL: '%s', Port: %d) already exists. Please use a different URL or port", url, port) + } + } + + return nil +} diff --git a/pkg/server/analyze.go b/pkg/server/analyze.go index 6ee61f776a..795c260435 100644 --- a/pkg/server/analyze.go +++ b/pkg/server/analyze.go @@ -1,10 +1,9 @@ package server import ( + schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1" "context" json "encoding/json" - - schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1" "github.com/k8sgpt-ai/k8sgpt/pkg/analysis" ) @@ -39,6 +38,9 @@ func (h *handler) Analyze(ctx context.Context, i *schemav1.AnalyzeRequest) ( } defer config.Close() + if config.CustomAnalyzersAreAvailable() { + config.RunCustomAnalysis() + } config.RunAnalysis() if i.Explain { diff --git a/pkg/server/config.go b/pkg/server/config.go index 47942cf8bb..e5156737cb 100644 --- a/pkg/server/config.go +++ b/pkg/server/config.go @@ -1,10 +1,11 @@ package server import ( - "context" - schemav1 "buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go/schema/v1" + "context" "github.com/k8sgpt-ai/k8sgpt/pkg/cache" + "github.com/k8sgpt-ai/k8sgpt/pkg/custom" + "github.com/spf13/viper" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -27,6 +28,38 @@ func (h *handler) AddConfig(ctx context.Context, i *schemav1.AddConfigRequest) ( return resp, err } + if i.CustomAnalyzers != nil { + // We need to add the custom analyzers to the viper config and save them + var customAnalyzers = make([]custom.CustomAnalyzer, 0) + if err := viper.UnmarshalKey("custom_analyzers", &customAnalyzers); err != nil { + return resp, err + } else { + // If there are analyzers are already in the config we will append the ones with new names + for _, ca := range i.CustomAnalyzers { + exists := false + for _, c := range customAnalyzers { + if c.Name == ca.Name { + exists = true + break + } + } + if !exists { + customAnalyzers = append(customAnalyzers, custom.CustomAnalyzer{ + Name: ca.Name, + Connection: custom.Connection{ + Url: ca.Connection.Url, + Port: ca.Connection.Port, + }, + }) + } + } + // save the config + viper.Set("custom_analyzers", customAnalyzers) + if err := viper.WriteConfig(); err != nil { + return resp, err + } + } + } if i.Cache != nil { var err error var remoteCache cache.CacheProvider diff --git a/pkg/server/server.go b/pkg/server/server.go index afec3600a3..0ec900c92d 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -25,11 +25,13 @@ import ( gw "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2/schema/v1/server-service/schemav1gateway" rpc "buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go/schema/v1/schemav1grpc" + "github.com/go-logr/zapr" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/prometheus/client_golang/prometheus/promhttp" "go.uber.org/zap" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" + ctrl "sigs.k8s.io/controller-runtime" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -80,6 +82,8 @@ func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Ha } func (s *Config) Serve() error { + ctrl.SetLogger(zapr.NewLogger(s.Logger)) + var lis net.Listener var err error address := fmt.Sprintf(":%s", s.Port)