From 16d57e5a55c2084bf1580377ae52e2961cc84922 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Sun, 4 Aug 2024 21:03:34 +0100 Subject: [PATCH] feat: initial custom analysis server mode (#1205) * chore: initial custom analysis Signed-off-by: Alex Jones * chore: saving the missing stuff Signed-off-by: Alex Jones * chore: removed redundant error handling Signed-off-by: Alex Jones * chore: missing piece of the custom analysis response Signed-off-by: Alex Jones --------- Signed-off-by: Alex Jones Signed-off-by: AlexsJones --- go.mod | 5 +++-- go.sum | 11 ++++++----- pkg/analysis/analysis.go | 14 ++++++++++++++ pkg/server/analyze.go | 6 ++++-- pkg/server/config.go | 37 +++++++++++++++++++++++++++++++++++-- 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index c8e69fbd0b..0cf3245d3d 100644 --- a/go.mod +++ b/go.mod @@ -29,8 +29,8 @@ 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 + 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 @@ -261,3 +261,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 709aabfd7e..ea81b062a8 100644 --- a/go.sum +++ b/go.sum @@ -8,12 +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/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.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.1-20240406062209-1cc152efbf5c.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= @@ -1571,8 +1572,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= diff --git a/pkg/analysis/analysis.go b/pkg/analysis/analysis.go index 80b160862e..1a28c9846a 100644 --- a/pkg/analysis/analysis.go +++ b/pkg/analysis/analysis.go @@ -160,6 +160,14 @@ 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 { @@ -184,6 +192,12 @@ func (a *Analysis) RunCustomAnalysis() { } 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)) 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