From e428c2e49d0b44fd0633a18fe50c5f4d22efce7b Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Tue, 16 May 2023 09:07:49 +0100 Subject: [PATCH 1/5] feat: added the ability to set a user default AI provider Signed-off-by: Alex Jones --- pkg/cache/s3_based.go | 1 + 1 file changed, 1 insertion(+) create mode 100644 pkg/cache/s3_based.go diff --git a/pkg/cache/s3_based.go b/pkg/cache/s3_based.go new file mode 100644 index 0000000000..08bf029d30 --- /dev/null +++ b/pkg/cache/s3_based.go @@ -0,0 +1 @@ +package cache From b6ae90915f9d4b4d06b928cc63f65f0dddca1d2d Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Tue, 16 May 2023 09:08:54 +0100 Subject: [PATCH 2/5] feat: added the ability to set a user default AI provider Signed-off-by: Alex Jones --- pkg/cache/s3_based.go | 1 - 1 file changed, 1 deletion(-) delete mode 100644 pkg/cache/s3_based.go diff --git a/pkg/cache/s3_based.go b/pkg/cache/s3_based.go deleted file mode 100644 index 08bf029d30..0000000000 --- a/pkg/cache/s3_based.go +++ /dev/null @@ -1 +0,0 @@ -package cache From 273d84f4a095b65d5d79896cbbdd2e289a10b1dd Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Thu, 18 May 2023 15:47:15 +0100 Subject: [PATCH 3/5] feat: s3 based caching Signed-off-by: Alex Jones --- cmd/cache/add.go | 65 +++++++++++++++++++++++++++++ cmd/cache/cache.go | 36 ++++++++++++++++ cmd/cache/list.go | 53 ++++++++++++++++++++++++ cmd/cache/remove.go | 64 +++++++++++++++++++++++++++++ cmd/root.go | 2 + go.mod | 5 +++ go.sum | 8 ++++ pkg/analysis/analysis.go | 8 +++- pkg/cache/cache.go | 28 ++++++++++++- pkg/cache/file_based.go | 19 +++++++++ pkg/cache/s3_based.go | 89 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 cmd/cache/add.go create mode 100644 cmd/cache/cache.go create mode 100644 cmd/cache/list.go create mode 100644 cmd/cache/remove.go create mode 100644 pkg/cache/s3_based.go diff --git a/cmd/cache/add.go b/cmd/cache/add.go new file mode 100644 index 0000000000..9c3ca58ce4 --- /dev/null +++ b/cmd/cache/add.go @@ -0,0 +1,65 @@ +/* +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 cache + +import ( + "fmt" + "os" + + "github.com/fatih/color" + "github.com/k8sgpt-ai/k8sgpt/pkg/cache" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// addCmd represents the add command +var addCmd = &cobra.Command{ + Use: "add", + Short: "Add a remote cache", + Long: `This command allows you to add a remote cache to store the results of an analysis. + The supported cache types are: + - S3`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(color.YellowString("Adding remote S3 based cache")) + + // Check to see whether there is cache information already + var cacheInfo cache.CacheProvider + err := viper.UnmarshalKey("cache", &cacheInfo) + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + if cacheInfo.BucketName != "" { + color.Yellow("Error: a cache is already configured, please remove it first") + os.Exit(1) + } + cacheInfo.BucketName = bucketname + + // Save the cache information + viper.Set("cache", cacheInfo) + err = viper.WriteConfig() + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + }, +} + +func init() { + CacheCmd.AddCommand(addCmd) + addCmd.Flags().StringVarP(&bucketname, "bucket", "b", "", "The name of the bucket to use for the cache") + addCmd.MarkFlagRequired("bucket") + +} diff --git a/cmd/cache/cache.go b/cmd/cache/cache.go new file mode 100644 index 0000000000..c7418dbb18 --- /dev/null +++ b/cmd/cache/cache.go @@ -0,0 +1,36 @@ +/* +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 cache + +import ( + "github.com/spf13/cobra" +) + +var ( + bucketname string +) + +// cacheCmd represents the cache command +var CacheCmd = &cobra.Command{ + Use: "cache", + Short: "For working with the cache the results of an analysis", + Long: `Cache commands allow you to add a remote cache, list the contents of the cache, and remove items from the cache.`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { +} diff --git a/cmd/cache/list.go b/cmd/cache/list.go new file mode 100644 index 0000000000..8fa91fcced --- /dev/null +++ b/cmd/cache/list.go @@ -0,0 +1,53 @@ +/* +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 cache + +import ( + "os" + + "github.com/fatih/color" + "github.com/k8sgpt-ai/k8sgpt/pkg/cache" + "github.com/spf13/cobra" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "List the contents of the cache", + Long: `This command allows you to list the contents of the cache.`, + Run: func(cmd *cobra.Command, args []string) { + + // load remote cache if it is configured + remoteCacheEnabled, err := cache.RemoteCacheEnabled() + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + c := cache.New(false, remoteCacheEnabled) + // list the contents of the cache + names, err := c.List() + if err != nil { + panic(err) + } + for _, name := range names { + println(name) + } + }, +} + +func init() { + CacheCmd.AddCommand(listCmd) + +} diff --git a/cmd/cache/remove.go b/cmd/cache/remove.go new file mode 100644 index 0000000000..2d7f453040 --- /dev/null +++ b/cmd/cache/remove.go @@ -0,0 +1,64 @@ +/* +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 cache + +import ( + "fmt" + "os" + + "github.com/fatih/color" + "github.com/k8sgpt-ai/k8sgpt/pkg/cache" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// removeCmd represents the remove command +var removeCmd = &cobra.Command{ + Use: "remove", + Short: "Remove a remote cache", + Long: `This command allows you to remove a remote cache and use the default filecache.`, + Run: func(cmd *cobra.Command, args []string) { + + // Remove the remote cache + var cacheInfo cache.CacheProvider + err := viper.UnmarshalKey("cache", &cacheInfo) + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + if cacheInfo.BucketName == "" { + color.Yellow("Error: no cache is configured") + os.Exit(1) + } + // Warn user this will delete the S3 bucket and prompt them to continue + color.Yellow("Warning: this will delete the S3 bucket %s", cacheInfo.BucketName) + color.Yellow("Are you sure you want to continue? (y/n)") + var response string + _, err = fmt.Scanln(&response) + if err != nil { + color.Red("Error: %v", err) + os.Exit(1) + } + if response != "y" { + os.Exit(0) + } + + }, +} + +func init() { + CacheCmd.AddCommand(removeCmd) + removeCmd.Flags().StringVarP(&bucketname, "bucket", "b", "", "The name of the bucket to use for the cache") +} diff --git a/cmd/root.go b/cmd/root.go index 434f61f48f..e9b5098f2b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,6 +20,7 @@ import ( "github.com/adrg/xdg" "github.com/k8sgpt-ai/k8sgpt/cmd/analyze" "github.com/k8sgpt-ai/k8sgpt/cmd/auth" + "github.com/k8sgpt-ai/k8sgpt/cmd/cache" "github.com/k8sgpt-ai/k8sgpt/cmd/filters" "github.com/k8sgpt-ai/k8sgpt/cmd/generate" "github.com/k8sgpt-ai/k8sgpt/cmd/integration" @@ -67,6 +68,7 @@ func init() { rootCmd.AddCommand(generate.GenerateCmd) rootCmd.AddCommand(integration.IntegrationCmd) rootCmd.AddCommand(serve.ServeCmd) + rootCmd.AddCommand(cache.CacheCmd) rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.k8sgpt.yaml)") 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/go.mod b/go.mod index 99261f8973..01179a43cd 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,11 @@ require ( buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.30.0-20230514071713-3d78cb8bbc06.1 ) +require ( + github.com/aws/aws-sdk-go v1.44.264 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect +) + require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect diff --git a/go.sum b/go.sum index 06ffd395a2..64f107a44f 100644 --- a/go.sum +++ b/go.sum @@ -450,6 +450,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.44.264 h1:5klL62ebn6uv3oJ0ixF7K12hKItj8lV3QqWeQPlkFSs= +github.com/aws/aws-sdk-go v1.44.264/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -777,6 +779,9 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -1239,6 +1244,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= @@ -1370,6 +1376,7 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1378,6 +1385,7 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= diff --git a/pkg/analysis/analysis.go b/pkg/analysis/analysis.go index 4ac295fd41..8f7ce408bf 100644 --- a/pkg/analysis/analysis.go +++ b/pkg/analysis/analysis.go @@ -112,13 +112,19 @@ func NewAnalysis(backend string, language string, filters []string, namespace st return nil, err } + // load remote cache if it is configured + remoteCacheEnabled, err := cache.RemoteCacheEnabled() + if err != nil { + return nil, err + } + return &Analysis{ Context: ctx, Filters: filters, Client: client, AIClient: aiClient, Namespace: namespace, - Cache: cache.New(noCache), + Cache: cache.New(noCache, remoteCacheEnabled), Explain: explain, MaxConcurrency: maxConcurrency, AnalysisAIProvider: backend, diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index a81cd46f89..d3727993d6 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -1,14 +1,40 @@ package cache +import ( + "github.com/spf13/viper" +) + type ICache interface { Store(key string, data string) error Load(key string) (string, error) + List() ([]string, error) Exists(key string) bool IsCacheDisabled() bool } -func New(noCache bool) ICache { +func New(noCache bool, remoteCache bool) ICache { + if remoteCache { + return NewS3Cache(noCache) + } return &FileBasedCache{ noCache: noCache, } } + +// CacheProvider is the configuration for the cache provider when using a remote cache +type CacheProvider struct { + BucketName string `mapstructure:"bucketname"` +} + +func RemoteCacheEnabled() (bool, error) { + // load remote cache if it is configured + var cache CacheProvider + err := viper.UnmarshalKey("cache", &cache) + if err != nil { + return false, err + } + if cache.BucketName != "" { + return true, nil + } + return false, nil +} diff --git a/pkg/cache/file_based.go b/pkg/cache/file_based.go index a4acaf8abe..9e59886bda 100644 --- a/pkg/cache/file_based.go +++ b/pkg/cache/file_based.go @@ -19,6 +19,25 @@ func (f *FileBasedCache) IsCacheDisabled() bool { return f.noCache } +func (*FileBasedCache) List() ([]string, error) { + path, err := xdg.CacheFile("k8sgpt") + if err != nil { + return nil, err + } + + files, err := os.ReadDir(path) + if err != nil { + return nil, err + } + + var result []string + for _, file := range files { + result = append(result, file.Name()) + } + + return result, nil +} + func (*FileBasedCache) Exists(key string) bool { path, err := xdg.CacheFile(filepath.Join("k8sgpt", key)) diff --git a/pkg/cache/s3_based.go b/pkg/cache/s3_based.go new file mode 100644 index 0000000000..e96d40be14 --- /dev/null +++ b/pkg/cache/s3_based.go @@ -0,0 +1,89 @@ +package cache + +import ( + "bytes" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" +) + +// Generate ICache implementation +type S3Cache struct { + noCache bool + bucketName string + session *s3.S3 +} + +func (s *S3Cache) Store(key string, data string) error { + // Store the object as a new file in the bucket with data as the content + _, err := s.session.PutObject(&s3.PutObjectInput{ + Body: aws.ReadSeekCloser(bytes.NewReader([]byte(data))), + Bucket: aws.String(s.bucketName), + Key: aws.String(key), + }) + return err + +} + +func (s *S3Cache) Load(key string) (string, error) { + + // Retrieve the object from the bucket and load it into a string + result, err := s.session.GetObject(&s3.GetObjectInput{ + Bucket: aws.String(s.bucketName), + Key: aws.String(key), + }) + if err != nil { + return "", err + } + + buf := new(bytes.Buffer) + buf.ReadFrom(result.Body) + result.Body.Close() + return buf.String(), nil +} + +func (s *S3Cache) List() ([]string, error) { + + // List the files in the bucket + result, err := s.session.ListObjectsV2(&s3.ListObjectsV2Input{Bucket: aws.String(s.bucketName)}) + if err != nil { + return nil, err + } + + var keys []string + for _, item := range result.Contents { + keys = append(keys, *item.Key) + } + + return keys, nil +} + +func (s *S3Cache) Exists(key string) bool { + // Check if the object exists in the bucket + _, err := s.session.HeadObject(&s3.HeadObjectInput{ + Bucket: aws.String(s.bucketName), + Key: aws.String(key), + }) + return err == nil + +} + +func (s *S3Cache) IsCacheDisabled() bool { + return s.noCache +} + +func NewS3Cache(nocache bool) ICache { + + sess := session.Must(session.NewSession()) + // Create a new instance of the service's client with a Session. + // Optional aws.Config values can also be provided as variadic arguments + // to the New function. This option allows you to provide service + // specific configuration. + s := s3.New(sess) + + return &S3Cache{ + noCache: nocache, + session: s, + } +} From 33c1f001dd793e08f842356cf33f1309ead4b7a3 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 19 May 2023 09:14:12 +0100 Subject: [PATCH 4/5] fix: missing version info and improvements Signed-off-by: Alex Jones --- .goreleaser.yaml | 2 ++ cmd/root.go | 10 +++++++--- cmd/version.go | 19 ++++++++++++++++++- container/Dockerfile | 6 ++++-- go.mod | 6 ++---- go.sum | 1 + main.go | 8 ++++++-- 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index cbd1deb36f..c295ef6447 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -15,6 +15,8 @@ builds: - darwin ldflags: - -s -w -X main.version={{.Version}} + - -s -w -X main.commit={{.ShortCommit}} + - -s -w -X main.Date={{.CommitDate}} nfpms: - file_name_template: '{{ .ProjectName }}_{{ .Arch }}' diff --git a/cmd/root.go b/cmd/root.go index e9b5098f2b..fae9f05c05 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -34,7 +34,9 @@ var ( cfgFile string kubecontext string kubeconfig string - version string + Version string + Commit string + Date string ) // rootCmd represents the base command when called without any subcommands @@ -49,8 +51,10 @@ var rootCmd = &cobra.Command{ // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute(v string) { - version = v +func Execute(v string, c string, d string) { + Version = v + Commit = c + Date = d err := rootCmd.Execute() if err != nil { os.Exit(1) diff --git a/cmd/version.go b/cmd/version.go index f0b65f54ed..93a49940dc 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -14,6 +14,9 @@ limitations under the License. package cmd import ( + "fmt" + "runtime/debug" + "github.com/spf13/cobra" ) @@ -23,7 +26,21 @@ var versionCmd = &cobra.Command{ Short: "Print the version number of k8sgpt", Long: `All software has versions. This is k8sgpt's`, Run: func(cmd *cobra.Command, args []string) { - cmd.Printf("k8sgpt version %s\n", version) + if Version == "dev" { + details, ok := debug.ReadBuildInfo() + if ok && details.Main.Version != "" && details.Main.Version != "(devel)" { + Version = details.Main.Version + for _, i := range details.Settings { + if i.Key == "vcs.time" { + Date = i.Value + } + if i.Key == "vcs.revision" { + Commit = i.Value + } + } + } + } + fmt.Printf("ks8gpt: %s (%s), built at: %s\n", Version, Commit, Date) }, } diff --git a/container/Dockerfile b/container/Dockerfile index d805eb6f30..be91f9d7f9 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -12,7 +12,9 @@ FROM golang:1.20.4-alpine3.16 AS builder ENV CGO_ENABLED=0 - +ARG VERSION +ARG COMMIT +ARG DATE WORKDIR /workspace COPY go.mod go.sum ./ @@ -20,7 +22,7 @@ RUN go mod download COPY ./ ./ -RUN go build -o /workspace/k8sgpt ./ +RUN go build -o /workspace/k8sgpt -ldflags "-X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}" ./ FROM gcr.io/distroless/static AS production diff --git a/go.mod b/go.mod index 01179a43cd..f60f2b73d9 100644 --- a/go.mod +++ b/go.mod @@ -26,12 +26,10 @@ require github.com/adrg/xdg v0.4.0 require ( buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20230515081240-6b5b845c638e.1 buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.30.0-20230514071713-3d78cb8bbc06.1 + github.com/aws/aws-sdk-go v1.44.264 ) -require ( - github.com/aws/aws-sdk-go v1.44.264 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect -) +require github.com/jmespath/go-jmespath v0.4.0 // indirect require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect diff --git a/go.sum b/go.sum index 64f107a44f..0c50040e30 100644 --- a/go.sum +++ b/go.sum @@ -781,6 +781,7 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= diff --git a/main.go b/main.go index 2517284e06..b177e9b15b 100644 --- a/main.go +++ b/main.go @@ -15,8 +15,12 @@ package main import "github.com/k8sgpt-ai/k8sgpt/cmd" -var version = "dev" +var ( + version = "dev" + commit = "HEAD" + date = "unknown" +) func main() { - cmd.Execute(version) + cmd.Execute(version, commit, date) } From cf8012510f22bd0ed777eb6fd94fe8bdf15b6bb0 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 19 May 2023 09:37:00 +0100 Subject: [PATCH 5/5] chore: fixing local build Signed-off-by: Alex Jones --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index deae8e9f7e..9f0e013a0e 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ all: tidy add-copyright lint cover build build: @echo "$(shell go version)" @echo "===========> Building binary $(BUILDAPP) *[Git Info]: $(VERSION)-$(GIT_COMMIT)" - @export CGO_ENABLED=0 && go build -o $(BUILDAPP) -ldflags '-s -w' $(BUILDFILE) + @export CGO_ENABLED=0 && go build -o $(BUILDAPP) -ldflags "-s -w -X main.version=dev -X main.commit=$$(git rev-parse --short HEAD) -X main.date=$$(date +%FT%TZ)" $(BUILDFILE) ## tidy: tidy go.mod .PHONY: tidy