From a0e7b894f31cffd2606371b61bb404a4946ea787 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 20:41:16 -0500 Subject: [PATCH 01/85] chore: progress quit --- Dockerfile-ci | 12 ++++++++++++ cmd/version.go | 1 + 2 files changed, 13 insertions(+) create mode 100644 Dockerfile-ci diff --git a/Dockerfile-ci b/Dockerfile-ci new file mode 100644 index 000000000..d98c4f938 --- /dev/null +++ b/Dockerfile-ci @@ -0,0 +1,12 @@ +FROM debian:latest + +# Installing dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + coreutils \ + curl \ + file \ + git \ + && rm -rf /var/lib/apt/lists/* + +CMD [ "/bin/bash" ] diff --git a/cmd/version.go b/cmd/version.go index dc8c60d4b..c4c075eca 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -28,5 +28,6 @@ var versionCmd = &cobra.Command{ ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) progress.Success(versionMsg) + progress.Progress.Quit() }, } From b15fe8e454c2eb346b75d98875b0caecc6b04313 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 02/85] chore: bubbletea blacklist ci flag --- cmd/version.go | 30 ++++++++++++++++++++---------- main.go | 13 ++++++------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index c4c075eca..a6987697b 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,22 +12,32 @@ import ( "github.com/kubefirst/kubefirst-api/pkg/configs" "github.com/kubefirst/kubefirst/internal/progress" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { - rootCmd.AddCommand(versionCmd) + rootCmd.AddCommand(Create()) } -var versionCmd = &cobra.Command{ - Use: "version", - Short: "print the version number for kubefirst-cli", - Long: `All software has versions. This is kubefirst's`, - Run: func(cmd *cobra.Command, args []string) { - versionMsg := ` +func Create() *cobra.Command { + versionCmd := &cobra.Command{ + Use: "version", + Short: "print the version number for kubefirst-cli", + Long: `All software has versions. This is kubefirst's`, + Run: func(cmd *cobra.Command, args []string) { + versionMsg := ` ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - progress.Success(versionMsg) - progress.Progress.Quit() - }, + canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") + + if canRunBubbleTea { + progress.Success(versionMsg) + } else { + fmt.Print(versionMsg) + } + }, + } + + return versionCmd } diff --git a/main.go b/main.go index d5b4d0a77..f2cb2d92c 100644 --- a/main.go +++ b/main.go @@ -27,16 +27,14 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true - if argsWithProg != nil { - for _, arg := range argsWithProg { - isBlackListed := slices.Contains(bubbleTeaBlacklist, arg) + for _, arg := range argsWithProg { + isBlackListed := slices.Contains(bubbleTeaBlacklist, arg) - if isBlackListed { - canRunBubbleTea = false - } + if isBlackListed { + canRunBubbleTea = false } } @@ -122,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) err = viper.WriteConfig() if err != nil { From 6e62e58c1d3d7fee756b61102d9b1ef8883c1bb0 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:53:58 -0500 Subject: [PATCH 03/85] chore: add flag --- cmd/version.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/version.go b/cmd/version.go index a6987697b..d7c0ab253 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -15,6 +15,10 @@ import ( "github.com/spf13/viper" ) +var ( + ciFlag bool +) + func init() { rootCmd.AddCommand(Create()) } @@ -39,5 +43,8 @@ func Create() *cobra.Command { }, } + // todo review defaults and update descriptions + versionCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") + return versionCmd } From 27be85a96e38d7675595ca26cff61a641b64b5a5 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:05:51 -0500 Subject: [PATCH 04/85] chore: error handling --- cmd/version.go | 13 ++++++------- main.go | 8 ++++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index d7c0ab253..17686e000 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,7 +12,6 @@ import ( "github.com/kubefirst/kubefirst-api/pkg/configs" "github.com/kubefirst/kubefirst/internal/progress" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -33,13 +32,13 @@ func Create() *cobra.Command { ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") + // canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") - if canRunBubbleTea { - progress.Success(versionMsg) - } else { - fmt.Print(versionMsg) - } + // if canRunBubbleTea { + progress.Success(versionMsg) + // } else { + // fmt.Print(versionMsg) + // } }, } diff --git a/main.go b/main.go index f2cb2d92c..94ccb0aa2 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -134,7 +134,11 @@ func main() { cmd.Execute() }() - progress.Progress.Run() + _, err := progress.Progress.Run() + + if err != nil { + stdLog.Panicf("unable to set log-file-location, error is: %s", err) + } } else { cmd.Execute() } From 3b0d485607736d11ec9be1a5979c83526f3bc075 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:40:33 -0500 Subject: [PATCH 05/85] fix: bypass bubbletea execution --- cmd/akamai/command.go | 1 + cmd/aws/command.go | 2 + cmd/civo/command.go | 1 + cmd/digitalocean/command.go | 1 + cmd/google/command.go | 1 + cmd/k3s/command.go | 1 + cmd/version.go | 6 --- cmd/vultr/command.go | 1 + internal/progress/command.go | 9 +--- internal/progress/message.go | 82 ++++++++++++++++++++++++++++++++--- internal/progress/progress.go | 7 ++- internal/progress/types.go | 2 +- main.go | 7 ++- 13 files changed, 97 insertions(+), 24 deletions(-) diff --git a/cmd/akamai/command.go b/cmd/akamai/command.go index 11a28fe21..e2f887eb0 100644 --- a/cmd/akamai/command.go +++ b/cmd/akamai/command.go @@ -124,6 +124,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/aws/command.go b/cmd/aws/command.go index f6d0e1c1e..5964b768f 100644 --- a/cmd/aws/command.go +++ b/cmd/aws/command.go @@ -142,5 +142,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") + return authCmd } diff --git a/cmd/civo/command.go b/cmd/civo/command.go index df66f4f1e..9ede71025 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -151,6 +151,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/digitalocean/command.go b/cmd/digitalocean/command.go index 391b4feaf..efde8c97b 100644 --- a/cmd/digitalocean/command.go +++ b/cmd/digitalocean/command.go @@ -131,6 +131,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/google/command.go b/cmd/google/command.go index b5ac28836..c169a0f3e 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -136,6 +136,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/k3s/command.go b/cmd/k3s/command.go index bbc6c9a38..4edb1cbe8 100644 --- a/cmd/k3s/command.go +++ b/cmd/k3s/command.go @@ -133,6 +133,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/version.go b/cmd/version.go index 17686e000..4a8726415 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -32,13 +32,7 @@ func Create() *cobra.Command { ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - // canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") - - // if canRunBubbleTea { progress.Success(versionMsg) - // } else { - // fmt.Print(versionMsg) - // } }, } diff --git a/cmd/vultr/command.go b/cmd/vultr/command.go index 5cbb32266..d3ef48920 100644 --- a/cmd/vultr/command.go +++ b/cmd/vultr/command.go @@ -131,6 +131,7 @@ func RootCredentials() *cobra.Command { RunE: common.GetRootCredentials, } + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/internal/progress/command.go b/internal/progress/command.go index 6a40888ef..287f54f07 100644 --- a/internal/progress/command.go +++ b/internal/progress/command.go @@ -17,13 +17,8 @@ import ( // Commands func GetClusterInterval(clusterName string) tea.Cmd { return tea.Every(time.Second*10, func(t time.Time) tea.Msg { - provisioningCluster, err := cluster.GetCluster(clusterName) - - if err != nil { - - } - - return CusterProvisioningMsg(provisioningCluster) + provisioningCluster, _ := cluster.GetCluster(clusterName) + return ClusterProvisioningMsg(provisioningCluster) }) } diff --git a/internal/progress/message.go b/internal/progress/message.go index 5c9ca4ad2..9ed5f29b9 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -13,9 +13,11 @@ import ( "fmt" "log" "strconv" + "time" "github.com/charmbracelet/glamour" "github.com/kubefirst/kubefirst-api/pkg/types" + "github.com/kubefirst/kubefirst/internal/cluster" "github.com/spf13/viper" ) @@ -71,6 +73,11 @@ func DisplayLogHints(estimatedTime int) { headerMessage := renderMessage(header) + if !CanRunBubbleTea { + fmt.Print(headerMessage) + return + } + Progress.Send(headerMsg{ message: headerMessage, }) @@ -107,7 +114,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { break case "k3s": - cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster")) + cloudCliKubeconfig = "use the kubeconfig file outputed from terraform to acces to the cluster" break } @@ -151,6 +158,11 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { ` successMessage := renderMessage(success) + if !CanRunBubbleTea { + fmt.Print(successMessage) + return successMsg{} + } + return successMsg{ message: successMessage, } @@ -175,6 +187,11 @@ func DisplayCredentials(cluster types.Cluster) { headerMessage := renderMessage(header) + if !CanRunBubbleTea { + fmt.Print(headerMessage) + return + } + Progress.Send(headerMsg{ message: headerMessage, }) @@ -184,10 +201,20 @@ func DisplayCredentials(cluster types.Cluster) { func AddStep(message string) { renderedMessage := createStep(fmt.Sprintf("%s %s", ":dizzy:", message)) + if !CanRunBubbleTea { + fmt.Print(renderedMessage) + return + } + Progress.Send(renderedMessage) } func CompleteStep(message string) { + if !CanRunBubbleTea { + fmt.Print(message) + return + } + Progress.Send(completeStep{ message: message, }) @@ -196,6 +223,11 @@ func CompleteStep(message string) { func Success(success string) { successMessage := renderMessage(success) + if !CanRunBubbleTea { + fmt.Print(successMessage) + return + } + Progress.Send( successMsg{ message: successMessage, @@ -204,13 +236,53 @@ func Success(success string) { func Error(message string) { renderedMessage := createErrorLog(message) + + if !CanRunBubbleTea { + fmt.Print(renderedMessage) + return + } + Progress.Send(renderedMessage) } func StartProvisioning(clusterName string) { - provisioningMessage := startProvision{ - clusterName: clusterName, - } + if !CanRunBubbleTea { + // Checks cluster status every 10 seconds + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + done := make(chan bool) + + go func() { + for { + select { + case <-done: + return + case <-ticker.C: + provisioningCluster, _ := cluster.GetCluster(clusterName) + + if provisioningCluster.Status == "error" { + fmt.Printf("unable to provision cluster: %s", provisioningCluster.LastCondition) + done <- true + } + + if provisioningCluster.Status != "provisioned" { + fmt.Println("cluster has been provisioned via ci") + fmt.Printf("kubefirst URL: https://kubefirst.%s", provisioningCluster.DomainName) + done <- true + } + } + } + }() + + // waits until the provision is done + <-done + + } else { + provisioningMessage := startProvision{ + clusterName: clusterName, + } - Progress.Send(provisioningMessage) + Progress.Send(provisioningMessage) + } } diff --git a/internal/progress/progress.go b/internal/progress/progress.go index 7d86ba202..d6054c5e6 100644 --- a/internal/progress/progress.go +++ b/internal/progress/progress.go @@ -15,6 +15,7 @@ import ( ) var Progress *tea.Program +var CanRunBubbleTea bool = true func NewModel() progressModel { return progressModel{ @@ -27,6 +28,10 @@ func InitializeProgressTerminal() { Progress = tea.NewProgram(NewModel()) } +func DisableBubbleTeaExecution() { + CanRunBubbleTea = false +} + func (m progressModel) Init() tea.Cmd { return nil } @@ -66,7 +71,7 @@ func (m progressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.clusterName = msg.clusterName return m, GetClusterInterval(m.clusterName) - case CusterProvisioningMsg: + case ClusterProvisioningMsg: m.provisioningCluster = types.Cluster(msg) completedSteps, nextStep := BuildCompletedSteps(types.Cluster(msg), m) m.completedSteps = append(m.completedSteps, completedSteps...) diff --git a/internal/progress/types.go b/internal/progress/types.go index f927c4697..ca2f1f183 100644 --- a/internal/progress/types.go +++ b/internal/progress/types.go @@ -28,7 +28,7 @@ type progressModel struct { // Bubbletea messsages -type CusterProvisioningMsg types.Cluster +type ClusterProvisioningMsg types.Cluster type startProvision struct { clusterName string diff --git a/main.go b/main.go index 94ccb0aa2..2806814ba 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) err = viper.WriteConfig() if err != nil { @@ -137,10 +136,10 @@ func main() { _, err := progress.Progress.Run() if err != nil { - stdLog.Panicf("unable to set log-file-location, error is: %s", err) + stdLog.Panicf("unable to run bubbletea program, error is: %s", err) } } else { + progress.DisableBubbleTeaExecution() cmd.Execute() } - } From 98d91f724cb66d9ddb284b72b5d24832c82485d5 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:59:53 -0500 Subject: [PATCH 06/85] fix: remove ssh host validation --- cmd/civo/create.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 93b404b54..c5f4d00ca 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -11,7 +11,6 @@ import ( "os" "strings" - internalssh "github.com/kubefirst/kubefirst-api/pkg/ssh" utils "github.com/kubefirst/kubefirst-api/pkg/utils" "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" @@ -20,7 +19,6 @@ import ( "github.com/kubefirst/kubefirst/internal/progress" "github.com/kubefirst/kubefirst/internal/provision" "github.com/kubefirst/kubefirst/internal/utilities" - "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -111,22 +109,22 @@ func ValidateProvidedFlags(gitProvider string) error { } } - switch gitProvider { - case "github": - key, err := internalssh.GetHostKey("github.com") - if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) - } - case "gitlab": - key, err := internalssh.GetHostKey("gitlab.com") - if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) - } - } + // switch gitProvider { + // case "github": + // key, err := internalssh.GetHostKey("github.com") + // if err != nil { + // return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") + // } else { + // log.Info().Msgf("%s %s\n", "github.com", key.Type()) + // } + // case "gitlab": + // key, err := internalssh.GetHostKey("gitlab.com") + // if err != nil { + // return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") + // } else { + // log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + // } + // } progress.CompleteStep("Validate provided flags") From 04e7acb2edaf1d1ae9864d74552b68f9a1331b16 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 23:40:23 -0500 Subject: [PATCH 07/85] fix: status --- internal/progress/message.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/progress/message.go b/internal/progress/message.go index 9ed5f29b9..c153e2a1a 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -266,9 +266,9 @@ func StartProvisioning(clusterName string) { done <- true } - if provisioningCluster.Status != "provisioned" { - fmt.Println("cluster has been provisioned via ci") - fmt.Printf("kubefirst URL: https://kubefirst.%s", provisioningCluster.DomainName) + if provisioningCluster.Status == "provisioned" { + fmt.Println("\n cluster has been provisioned via ci") + fmt.Println(fmt.Sprintf("\n kubefirst URL: https://kubefirst.%s", provisioningCluster.DomainName)) done <- true } } From ad6f926712c89fa59a0aabe6ba552fde38b68c71 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 18:10:01 -0500 Subject: [PATCH 08/85] chore: print cluster name --- internal/common/common.go | 2 ++ internal/progress/message.go | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/internal/common/common.go b/internal/common/common.go index 0026fe9e8..8ff847007 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -102,6 +102,8 @@ func versionCheck() (res *CheckResponse, skip bool) { func GetRootCredentials(cmd *cobra.Command, args []string) error { clusterName := viper.GetString("flags.cluster-name") + fmt.Print(clusterName) + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) diff --git a/internal/progress/message.go b/internal/progress/message.go index c153e2a1a..4c4c1fb5a 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -74,7 +74,7 @@ func DisplayLogHints(estimatedTime int) { headerMessage := renderMessage(header) if !CanRunBubbleTea { - fmt.Print(headerMessage) + fmt.Println(headerMessage) return } @@ -159,7 +159,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { successMessage := renderMessage(success) if !CanRunBubbleTea { - fmt.Print(successMessage) + fmt.Println(successMessage) return successMsg{} } @@ -188,7 +188,7 @@ func DisplayCredentials(cluster types.Cluster) { headerMessage := renderMessage(header) if !CanRunBubbleTea { - fmt.Print(headerMessage) + fmt.Println(headerMessage) return } @@ -202,7 +202,7 @@ func DisplayCredentials(cluster types.Cluster) { func AddStep(message string) { renderedMessage := createStep(fmt.Sprintf("%s %s", ":dizzy:", message)) if !CanRunBubbleTea { - fmt.Print(renderedMessage) + fmt.Println(renderedMessage) return } @@ -211,7 +211,7 @@ func AddStep(message string) { func CompleteStep(message string) { if !CanRunBubbleTea { - fmt.Print(message) + fmt.Println(message) return } @@ -224,7 +224,7 @@ func Success(success string) { successMessage := renderMessage(success) if !CanRunBubbleTea { - fmt.Print(successMessage) + fmt.Println(successMessage) return } @@ -238,7 +238,7 @@ func Error(message string) { renderedMessage := createErrorLog(message) if !CanRunBubbleTea { - fmt.Print(renderedMessage) + fmt.Println(renderedMessage) return } @@ -268,7 +268,7 @@ func StartProvisioning(clusterName string) { if provisioningCluster.Status == "provisioned" { fmt.Println("\n cluster has been provisioned via ci") - fmt.Println(fmt.Sprintf("\n kubefirst URL: https://kubefirst.%s", provisioningCluster.DomainName)) + fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", provisioningCluster.DomainName) done <- true } } From fc550b6033d85d3a1eb2aaf72210d648fca0f952 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:24:16 -0500 Subject: [PATCH 09/85] chore: test cluster name --- internal/common/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/common/common.go b/internal/common/common.go index 8ff847007..9fff5c4f6 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -104,7 +104,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { fmt.Print(clusterName) - cluster, err := cluster.GetCluster(clusterName) + cluster, err := cluster.GetCluster("jd-test-4-axmhv") if err != nil { progress.Error(err.Error()) return err From fb8a10904c458c4db4f1317ae39d49bd8dbc76b8 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:38:01 -0500 Subject: [PATCH 10/85] chore: test without provisioning --- cmd/civo/create.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index c5f4d00ca..bcfbda1f6 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,12 +12,10 @@ import ( "strings" utils "github.com/kubefirst/kubefirst-api/pkg/utils" - "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" "github.com/kubefirst/kubefirst/internal/progress" - "github.com/kubefirst/kubefirst/internal/provision" "github.com/kubefirst/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -32,10 +30,10 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) - isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) - if !isValid { - return err - } + // isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + // if !isValid { + // return err + // } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { @@ -89,7 +87,7 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + // provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } From e7ab4cc867e600de337698813872a87fd58c3e8e Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:38:04 -0500 Subject: [PATCH 11/85] chore: test without provisioning --- internal/common/common.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/common/common.go b/internal/common/common.go index 9fff5c4f6..0026fe9e8 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -102,9 +102,7 @@ func versionCheck() (res *CheckResponse, skip bool) { func GetRootCredentials(cmd *cobra.Command, args []string) error { clusterName := viper.GetString("flags.cluster-name") - fmt.Print(clusterName) - - cluster, err := cluster.GetCluster("jd-test-4-axmhv") + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) return err From c3998066ba53a8954fd67479aa50781b0852481b Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 18:59:21 -0500 Subject: [PATCH 12/85] feat: cluster name for root-credentials --- cmd/civo/command.go | 1 + cmd/civo/create.go | 17 ----------------- internal/common/common.go | 12 +++++++++++- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/cmd/civo/command.go b/cmd/civo/command.go index 9ede71025..d58e94a77 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -152,6 +152,7 @@ func RootCredentials() *cobra.Command { } authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") + authCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "", "cluster name (optional)") authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/civo/create.go b/cmd/civo/create.go index bcfbda1f6..766ecf14f 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -107,23 +107,6 @@ func ValidateProvidedFlags(gitProvider string) error { } } - // switch gitProvider { - // case "github": - // key, err := internalssh.GetHostKey("github.com") - // if err != nil { - // return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - // } else { - // log.Info().Msgf("%s %s\n", "github.com", key.Type()) - // } - // case "gitlab": - // key, err := internalssh.GetHostKey("gitlab.com") - // if err != nil { - // return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - // } else { - // log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) - // } - // } - progress.CompleteStep("Validate provided flags") return nil diff --git a/internal/common/common.go b/internal/common/common.go index 0026fe9e8..6a7ed4e97 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -100,7 +100,17 @@ func versionCheck() (res *CheckResponse, skip bool) { } func GetRootCredentials(cmd *cobra.Command, args []string) error { - clusterName := viper.GetString("flags.cluster-name") + clusterNameFromViper := viper.GetString("flags.cluster-name") + + clusteNameFromFlag, err := cmd.Flags().GetString("cluster-name") + if err != nil { + return err + } + + clusterName := clusterNameFromViper + if clusteNameFromFlag != "" { + clusterName = clusteNameFromFlag + } cluster, err := cluster.GetCluster(clusterName) if err != nil { From c3c4468359653bed616e33133623e589001cd536 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 19:07:30 -0500 Subject: [PATCH 13/85] chore: rollback provision --- cmd/civo/create.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 766ecf14f..1363a766c 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,10 +12,12 @@ import ( "strings" utils "github.com/kubefirst/kubefirst-api/pkg/utils" + "github.com/kubefirst/kubefirst/internal/catalog" "github.com/kubefirst/kubefirst/internal/cluster" "github.com/kubefirst/kubefirst/internal/gitShim" "github.com/kubefirst/kubefirst/internal/launch" "github.com/kubefirst/kubefirst/internal/progress" + "github.com/kubefirst/kubefirst/internal/provision" "github.com/kubefirst/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -30,10 +32,10 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) - // isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) - // if !isValid { - // return err - // } + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { @@ -87,7 +89,7 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - // provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } From 97c647e495f42bc9d7257eb37ac64fb28e83450c Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 20:18:12 -0500 Subject: [PATCH 14/85] fix: return error when status has error --- internal/progress/ci.go | 42 ++++++++++++++++++++++++++++++++++++ internal/progress/message.go | 34 +---------------------------- 2 files changed, 43 insertions(+), 33 deletions(-) create mode 100644 internal/progress/ci.go diff --git a/internal/progress/ci.go b/internal/progress/ci.go new file mode 100644 index 000000000..f44ca32b1 --- /dev/null +++ b/internal/progress/ci.go @@ -0,0 +1,42 @@ +package progress + +import ( + "fmt" + "log" + "time" + + "github.com/kubefirst/kubefirst/internal/cluster" +) + +func WatchClusterForCi(clusterName string) { + // Checks cluster status every 10 seconds + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + done := make(chan bool) + + go func() { + for { + select { + case <-done: + return + case <-ticker.C: + provisioningCluster, _ := cluster.GetCluster(clusterName) + + if provisioningCluster.Status == "error" { + log.Fatalf("unable to provision cluster: %s", provisioningCluster.LastCondition) + done <- true + } + + if provisioningCluster.Status == "provisioned" { + fmt.Println("\n cluster has been provisioned via ci") + fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", provisioningCluster.DomainName) + done <- true + } + } + } + }() + + // waits until the provision is done + <-done +} diff --git a/internal/progress/message.go b/internal/progress/message.go index 4c4c1fb5a..94ef766b6 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -13,11 +13,9 @@ import ( "fmt" "log" "strconv" - "time" "github.com/charmbracelet/glamour" "github.com/kubefirst/kubefirst-api/pkg/types" - "github.com/kubefirst/kubefirst/internal/cluster" "github.com/spf13/viper" ) @@ -247,37 +245,7 @@ func Error(message string) { func StartProvisioning(clusterName string) { if !CanRunBubbleTea { - // Checks cluster status every 10 seconds - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() - - done := make(chan bool) - - go func() { - for { - select { - case <-done: - return - case <-ticker.C: - provisioningCluster, _ := cluster.GetCluster(clusterName) - - if provisioningCluster.Status == "error" { - fmt.Printf("unable to provision cluster: %s", provisioningCluster.LastCondition) - done <- true - } - - if provisioningCluster.Status == "provisioned" { - fmt.Println("\n cluster has been provisioned via ci") - fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", provisioningCluster.DomainName) - done <- true - } - } - } - }() - - // waits until the provision is done - <-done - + WatchClusterForCi(clusterName) } else { provisioningMessage := startProvision{ clusterName: clusterName, From 012c39595f1785ed555f8b0c5088997d1f4a8d1a Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Mon, 12 Aug 2024 13:31:48 -0500 Subject: [PATCH 15/85] fix: add cloudflare origin issuer --- internal/utilities/utilities.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/utilities/utilities.go b/internal/utilities/utilities.go index a10752948..f12a45d4a 100644 --- a/internal/utilities/utilities.go +++ b/internal/utilities/utilities.go @@ -172,7 +172,8 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ PrivateKey: viper.GetString("kbot.private-key"), }, CloudflareAuth: apiTypes.CloudflareAuth{ - APIToken: os.Getenv("CF_API_TOKEN"), + APIToken: os.Getenv("CF_API_TOKEN"), + OriginCaIssuerKey: os.Getenv("CF_ORIGIN_CA_ISSUER_API_TOKEN"), }, } From f9ead3a57d153da41e4ade0846962c1842302330 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Mon, 26 Aug 2024 11:01:38 -0500 Subject: [PATCH 16/85] fix: fulldomain --- internal/progress/ci.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/progress/ci.go b/internal/progress/ci.go index f44ca32b1..fb9a16fe5 100644 --- a/internal/progress/ci.go +++ b/internal/progress/ci.go @@ -29,8 +29,14 @@ func WatchClusterForCi(clusterName string) { } if provisioningCluster.Status == "provisioned" { + fullDomainName := provisioningCluster.DomainName + + if provisioningCluster.SubdomainName != "" { + fullDomainName = fmt.Sprintf("%s.%s", provisioningCluster.SubdomainName, provisioningCluster.DomainName) + } + fmt.Println("\n cluster has been provisioned via ci") - fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", provisioningCluster.DomainName) + fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", fullDomainName) done <- true } } From e776e4614c335ee2e0e235448fb596407321ea8c Mon Sep 17 00:00:00 2001 From: Jared Edwards Date: Sun, 1 Sep 2024 11:12:49 -0600 Subject: [PATCH 17/85] fix package ref for kubefirst --- internal/progress/ci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/progress/ci.go b/internal/progress/ci.go index fb9a16fe5..588a9314d 100644 --- a/internal/progress/ci.go +++ b/internal/progress/ci.go @@ -5,7 +5,7 @@ import ( "log" "time" - "github.com/kubefirst/kubefirst/internal/cluster" + "github.com/konstructio/kubefirst/internal/cluster" ) func WatchClusterForCi(clusterName string) { From 3f5a366282bca1119f9884ad3875933b3e7f5337 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:01:01 -0400 Subject: [PATCH 18/85] Remove unused functions. Bump to Go 1.23. Run `gofmt` on all files. --- cmd/akamai/create.go | 25 ++++++++-------- cmd/civo/quota.go | 1 - cmd/k3d/create.go | 25 ++++++++-------- cmd/k3d/destroy.go | 2 +- go.mod | 6 +--- go.sum | 21 ++++++++------ internal/common/common.go | 13 --------- internal/gitShim/containerRegistryAuth.go | 1 - internal/launch/cmd.go | 2 +- internal/progress/message.go | 3 +- internal/provisionLogs/message.go | 31 -------------------- internal/utilities/utilities.go | 35 ----------------------- main.go | 6 ++-- 13 files changed, 45 insertions(+), 126 deletions(-) delete mode 100644 internal/provisionLogs/message.go diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index ed0177ceb..dcf6b83f1 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -29,20 +29,20 @@ func createAkamai(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "akamai") if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to get flags: %w", err) } progress.DisplayLogHints(25) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) if !isValid { - return err + return fmt.Errorf("catalog validation failed: %w", err) } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate provided flags: %w", err) } // If cluster setup is complete, return @@ -52,7 +52,7 @@ func createAkamai(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate git credentials: %w", err) } // Validate git @@ -72,11 +72,13 @@ func createAkamai(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to initialize git provider: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write viper config: %w", err) + } k3dClusterCreationComplete := viper.GetBool("launch.deployed") isK1Debug := strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" @@ -88,10 +90,10 @@ func createAkamai(cmd *cobra.Command, args []string) error { err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("failed to check kubefirst api availability: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -99,7 +101,6 @@ func ValidateProvidedFlags(gitProvider string) error { progress.AddStep("Validate provided flags") if os.Getenv("LINODE_TOKEN") == "" { - // telemetryShim.Transmit(useTelemetryFlag, segmentClient, segment.MetricCloudCredentialsCheckFailed, "LINODE_TOKEN environment variable was not set") return fmt.Errorf("your LINODE_TOKEN is not set - please set and re-run your last command") } @@ -114,16 +115,16 @@ func ValidateProvidedFlags(gitProvider string) error { case "github": key, err := internalssh.GetHostKey("github.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) + log.Info().Msgf("%q %s", "github.com", key.Type()) } case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } } diff --git a/cmd/civo/quota.go b/cmd/civo/quota.go index a4f5eef3a..8107528fa 100644 --- a/cmd/civo/quota.go +++ b/cmd/civo/quota.go @@ -81,7 +81,6 @@ func returnCivoQuotaEvaluation(cloudRegion string) (string, int, int, error) { if err != nil { log.Info().Msgf("failed to fetch civo quota: %s", err) return "", 0, 0, err - } // Container for quota response as a map diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index dd60016ae..0749ff7cb 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -303,7 +303,7 @@ func runK3d(cmd *cobra.Command, args []string) error { // todo // Since it's possible to stop and restart, cGitOwner may need to be reset - //if cGitOwner == "" { + // if cGitOwner == "" { // switch gitProviderFlag { // case "github": // cGitOwner = viper.GetString("flags.github-owner") @@ -520,7 +520,7 @@ func runK3d(cmd *cobra.Command, args []string) error { gitopsDirectoryTokens.UseTelemetry = "false" } - //* generate http credentials for git auth over https + // * generate http credentials for git auth over https httpAuth := &githttps.BasicAuth{ Username: cGitUser, Password: cGitToken, @@ -530,7 +530,7 @@ func runK3d(cmd *cobra.Command, args []string) error { log.Info().Msgf("generate public keys failed: %s\n", err.Error()) } - //* download dependencies to `$HOME/.k1/tools` + // * download dependencies to `$HOME/.k1/tools` if !viper.GetBool("kubefirst-checks.tools-downloaded") { log.Info().Msg("installing kubefirst dependencies") @@ -557,7 +557,7 @@ func runK3d(cmd *cobra.Command, args []string) error { MetaphorProductionIngressURL: fmt.Sprintf("metaphor-production.%s", k3d.DomainName), } - //* git clone and detokenize the gitops repository + // * git clone and detokenize the gitops repository // todo improve this logic for removing `kubefirst clean` // if !viper.GetBool("template-repo.gitops.cloned") || viper.GetBool("template-repo.gitops.removed") { progressPrinter.IncrementTracker("preflight-checks", 1) @@ -683,7 +683,7 @@ func runK3d(cmd *cobra.Command, args []string) error { } } - //* push detokenized gitops-template repository content to new remote + // * push detokenized gitops-template repository content to new remote progressPrinter.AddTracker("pushing-gitops-repos-upstream", "Pushing git repositories", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -756,7 +756,7 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) } - //* create k3d resources + // * create k3d resources progressPrinter.AddTracker("creating-k3d-cluster", "Creating k3d cluster", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -905,7 +905,7 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) argoCDInstallPath := fmt.Sprintf("github.com:konstructio/manifests/argocd/k3d?ref=%s", constants.KubefirstManifestRepoRef) - //* install argo + // * install argo executionControl = viper.GetBool("kubefirst-checks.argocd-install") if !executionControl { telemetry.SendEvent(segClient, telemetry.ArgoCDInstallStarted, "") @@ -944,7 +944,7 @@ func runK3d(cmd *cobra.Command, args []string) error { } var argocdPassword string - //* argocd pods are ready, get and set credentials + // * argocd pods are ready, get and set credentials executionControl = viper.GetBool("kubefirst-checks.argocd-credentials-set") if !executionControl { log.Info().Msg("Setting argocd username and password credentials") @@ -1024,7 +1024,7 @@ func runK3d(cmd *cobra.Command, args []string) error { } } - //* argocd sync registry and start sync waves + // * argocd sync registry and start sync waves executionControl = viper.GetBool("kubefirst-checks.argocd-create-registry") if !executionControl { telemetry.SendEvent(segClient, telemetry.CreateRegistryStarted, "") @@ -1186,7 +1186,7 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("configuring-vault", 1) - //* configure vault with terraform + // * configure vault with terraform //* vault port-forward vaultStopChannel := make(chan struct{}, 1) defer func() { @@ -1227,7 +1227,7 @@ func runK3d(cmd *cobra.Command, args []string) error { ) } - //* configure vault with terraform + // * configure vault with terraform executionControl = viper.GetBool("kubefirst-checks.terraform-apply-vault") if !executionControl { telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, "") @@ -1244,7 +1244,6 @@ func runK3d(cmd *cobra.Command, args []string) error { } else { usernamePasswordString = fmt.Sprintf("%s:%s", cGitUser, cGitToken) base64DockerAuth = base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) - } log.Info().Msg("configuring vault with terraform") @@ -1286,7 +1285,7 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("configuring-vault", 1) } - //* create users + // * create users progressPrinter.AddTracker("creating-users", "Creating users", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) diff --git a/cmd/k3d/destroy.go b/cmd/k3d/destroy.go index 3a3782b1f..55c2ab614 100644 --- a/cmd/k3d/destroy.go +++ b/cmd/k3d/destroy.go @@ -226,7 +226,7 @@ func destroyK3d(cmd *cobra.Command, args []string) error { } } - //* remove local content and kubefirst config file for re-execution + // * remove local content and kubefirst config file for re-execution if !viper.GetBool(fmt.Sprintf("kubefirst-checks.terraform-apply-%s", gitProvider)) && !viper.GetBool("kubefirst-checks.create-k3d-cluster") { log.Info().Msg("removing previous platform content") diff --git a/go.mod b/go.mod index 27aba6c90..baecf0bf4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/konstructio/kubefirst -go 1.18 +go 1.23 require ( github.com/argoproj/argo-cd/v2 v2.6.7 @@ -86,9 +86,6 @@ require ( github.com/digitalocean/godo v1.98.0 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v23.0.5+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect @@ -144,7 +141,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/otiai10/copy v1.7.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect diff --git a/go.sum b/go.sum index 2e67aec77..e83c32415 100644 --- a/go.sum +++ b/go.sum @@ -114,7 +114,9 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.23.1 h1:jR6wZggBxwWygeXcdNyguCOCIjPsZyNUNlAkTx2fu0U= +github.com/alicebob/miniredis/v2 v2.23.1/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -218,6 +220,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio= @@ -317,6 +320,7 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -337,13 +341,9 @@ github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -395,6 +395,7 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -552,6 +553,7 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -616,6 +618,7 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do= +github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -728,6 +731,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -735,6 +739,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubefirst/metrics-client v0.3.0 h1:zCug82pEzeWhHhpeYQvdhytRNDxrLxX18dPQ5PSxY3s= github.com/kubefirst/metrics-client v0.3.0/go.mod h1:GR7wsMcyYhd+EU67PeuMCBYFE6OJ7P/j5OI5BLOoRMc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= @@ -838,7 +843,6 @@ github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwd 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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= @@ -883,6 +887,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= @@ -915,8 +920,6 @@ github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWEr github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1017,6 +1020,7 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -1111,6 +1115,7 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1167,6 +1172,7 @@ github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5ta github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= +github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -1815,7 +1821,6 @@ 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.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/common/common.go b/internal/common/common.go index 1dfae85e9..8b073b186 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -16,7 +16,6 @@ import ( "strings" "github.com/konstructio/kubefirst-api/pkg/configs" - "github.com/konstructio/kubefirst-api/pkg/docker" "github.com/konstructio/kubefirst-api/pkg/providerConfigs" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/launch" @@ -196,15 +195,3 @@ https://docs.kubefirst.io/` + cloudProvider + `/deprovision return nil } - -// checkDocker makes sure Docker is running before all commands -func CheckDocker(cmd *cobra.Command, args []string) { - // Verify Docker is running - dcli := docker.DockerClientWrapper{ - Client: docker.NewDockerClient(), - } - _, err := dcli.CheckDockerReady() - if err != nil { - progress.Error(fmt.Sprintf("Docker must be running to use this command. Error checking Docker status: %s", err)) - } -} diff --git a/internal/gitShim/containerRegistryAuth.go b/internal/gitShim/containerRegistryAuth.go index 0469428a1..660429f0e 100644 --- a/internal/gitShim/containerRegistryAuth.go +++ b/internal/gitShim/containerRegistryAuth.go @@ -35,7 +35,6 @@ type ContainerRegistryAuth struct { func CreateContainerRegistrySecret(obj *ContainerRegistryAuth) (string, error) { // Handle secret creation for container registry authentication switch obj.GitProvider { - // GitHub docker auth secret // kaniko requires a specific format for Docker auth created as a secret // For GitHub, this becomes the provided token (pat) diff --git a/internal/launch/cmd.go b/internal/launch/cmd.go index ece9fe31b..658729caf 100644 --- a/internal/launch/cmd.go +++ b/internal/launch/cmd.go @@ -404,7 +404,7 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { progress.Error(fmt.Sprintf("error generating certificate for console: %s", err)) } - //* read certificate files + // * read certificate files certPem, err := os.ReadFile(fmt.Sprintf("%s/%s-cert.pem", mkcertPemDir, "kubefirst-console")) if err != nil { progress.Error(fmt.Sprintf("error generating certificate for console: %s", err)) diff --git a/internal/progress/message.go b/internal/progress/message.go index bebd0e0ee..05af7db78 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -112,9 +112,8 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { break case "k3s": - cloudCliKubeconfig = "use the kubeconfig file outputed from terraform to acces to the cluster" + cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) break - } var fullDomainName string diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go deleted file mode 100644 index bfaf9d066..000000000 --- a/internal/provisionLogs/message.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright (C) 2021-2023, Kubefirst - -This program is licensed under MIT. -See the LICENSE file for more details. - -Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go -Color definition https://www.ditig.com/256-colors-cheat-sheet -*/ -package provisionLogs - -import ( - "log" - - "github.com/charmbracelet/glamour" - "github.com/konstructio/kubefirst/internal/progress" -) - -func renderMessage(message string) string { - r, _ := glamour.NewTermRenderer( - glamour.WithStyles(progress.StyleConfig), - glamour.WithEmoji(), - ) - - out, err := r.Render(message) - if err != nil { - log.Println(err.Error()) - return err.Error() - } - return out -} diff --git a/internal/utilities/utilities.go b/internal/utilities/utilities.go index 967857f38..a174be65e 100644 --- a/internal/utilities/utilities.go +++ b/internal/utilities/utilities.go @@ -7,11 +7,9 @@ See the LICENSE file for more details. package utilities import ( - "bufio" "encoding/json" "fmt" "io/ioutil" - "net/http" "os" "strconv" "time" @@ -260,39 +258,6 @@ func ExportCluster(cluster apiTypes.Cluster, kcfg *k8s.KubernetesClient) error { return nil } -func ConsumeStream(url string) { - client := &http.Client{} - - req, err := http.NewRequest("GET", url, nil) - if err != nil { - fmt.Println("Error creating request:", err) - return - } - - resp, err := client.Do(req) - if err != nil { - fmt.Println("Error making request:", err) - return - } - - if resp.StatusCode != http.StatusOK { - fmt.Println("Error response:", resp.Status) - return - } - - // Read and print the streamed data until done signal is received - scanner := bufio.NewScanner(resp.Body) - for scanner.Scan() { - data := scanner.Text() - log.Info().Msgf(data) - } - - if err := scanner.Err(); err != nil { - log.Error().Msgf("Error reading response: %s", err.Error()) - return - } -} - func ParseJSONToMap(jsonStr string) (map[string][]byte, error) { var result map[string]interface{} err := json.Unmarshal([]byte(jsonStr), &result) diff --git a/main.go b/main.go index 8ade1a6ef..c99539771 100644 --- a/main.go +++ b/main.go @@ -79,7 +79,7 @@ func main() { k1Dir := fmt.Sprintf("%s/.k1", homePath) - //* create k1Dir if it doesn't exist + // * create k1Dir if it doesn't exist if _, err := os.Stat(k1Dir); os.IsNotExist(err) { err := os.MkdirAll(k1Dir, os.ModePerm) if err != nil { @@ -87,14 +87,14 @@ func main() { } } - //* create log directory + // * create log directory logsFolder := fmt.Sprintf("%s/logs", k1Dir) _ = os.Mkdir(logsFolder, 0o700) if err != nil { log.Fatal().Msgf("error creating logs directory: %s", err) } - //* create session log file + // * create session log file logfile := fmt.Sprintf("%s/%s", logsFolder, logfileName) logFileObj, err := utils.OpenLogFile(logfile) if err != nil { From 38a1cbc50cb5a2704a02e7c2d553c6c0246868b0 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:02:25 -0400 Subject: [PATCH 19/85] Change version on CI too --- .github/workflows/releaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/releaser.yaml b/.github/workflows/releaser.yaml index 75c34665d..3872667bf 100644 --- a/.github/workflows/releaser.yaml +++ b/.github/workflows/releaser.yaml @@ -28,10 +28,10 @@ jobs: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: - go-version: '>=1.18.0' - + go-version-file: go.mod + - name: Run GoReleaser uses: goreleaser/goreleaser-action@v3 @@ -40,4 +40,4 @@ jobs: version: latest args: release --clean env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} From b90efb2a7322bac4908aaab5524dad5f0f2fb176 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:11:02 -0400 Subject: [PATCH 20/85] Add missing formatted file. --- cmd/k3d/create.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 0749ff7cb..32db2f999 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -312,7 +312,7 @@ func runK3d(cmd *cobra.Command, args []string) error { // } //} // - //model, err := presentRecap(gitProviderFlag, gitDestDescriptor, cGitOwner) + // model, err := presentRecap(gitProviderFlag, gitDestDescriptor, cGitOwner) //if err != nil { // return err //} @@ -1187,7 +1187,7 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("configuring-vault", 1) // * configure vault with terraform - //* vault port-forward + // * vault port-forward vaultStopChannel := make(chan struct{}, 1) defer func() { close(vaultStopChannel) From d39c93a140fafb47199a536094163aeebbb9bf60 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Wed, 4 Sep 2024 23:25:28 +0000 Subject: [PATCH 21/85] set next macro chart for kubefirst - 2.5.12-rc4 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 34f39392b..a7dd4d020 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc3" + helmChartVersion = "2.5.12-rc4" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From e60e22217e4dca00c628bc7a303bb94f212f8f8a Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Wed, 4 Sep 2024 23:47:56 +0000 Subject: [PATCH 22/85] set next macro chart for kubefirst - 2.5.12-rc5 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index a7dd4d020..622b9a250 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc4" + helmChartVersion = "2.5.12-rc5" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From 6ac339604e07259b7b02ceb314f599dc77626e4f Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 02:19:17 +0000 Subject: [PATCH 23/85] set next macro chart for kubefirst - 2.5.12-rc7 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 622b9a250..86b684b9c 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc5" + helmChartVersion = "2.5.12-rc7" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From a907da90f53a6cbd2d67c1e9f65e1861309f20a2 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 02:30:41 +0000 Subject: [PATCH 24/85] set next macro chart for kubefirst - 2.5.12-rc6 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 86b684b9c..5302519de 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc7" + helmChartVersion = "2.5.12-rc6" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From fb1d2c95a3befdbdb8a60710ee20c5375a88f3d7 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 03:35:34 +0000 Subject: [PATCH 25/85] set next macro chart for kubefirst - 2.5.12-rc8 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 5302519de..95f88ad29 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc6" + helmChartVersion = "2.5.12-rc8" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From 16236578044b6c15eb52ae846f7076907a6679f1 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 04:01:24 +0000 Subject: [PATCH 26/85] set next macro chart for kubefirst - 2.5.12-rc9 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 95f88ad29..f90cecb79 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc8" + helmChartVersion = "2.5.12-rc9" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From bb33b975eecc1712333edfc38bd51e5d21fc8c87 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 04:59:35 +0000 Subject: [PATCH 27/85] set next macro chart for kubefirst - 2.5.12-rc10 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index f90cecb79..133c3e850 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc9" + helmChartVersion = "2.5.12-rc10" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From db04e65a602639d4ad205ed8ef9b9b0be1cc6f03 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 05:12:07 +0000 Subject: [PATCH 28/85] set next macro chart for kubefirst - 2.5.12-rc11 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 133c3e850..9973414fd 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc10" + helmChartVersion = "2.5.12-rc11" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From 5e6079d8dee2ae95db5c54998121d2d8b97b8432 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 05:25:33 +0000 Subject: [PATCH 29/85] set next macro chart for kubefirst - 2.5.12-rc12 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 9973414fd..7f9a949e5 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc11" + helmChartVersion = "2.5.12-rc12" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From fa36bb28e401d49df0cb077a39f0a7d52e62ae01 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 05:31:21 +0000 Subject: [PATCH 30/85] set next macro chart for kubefirst - 2.5.12-rc13 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 7f9a949e5..1b7b9ab2e 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc12" + helmChartVersion = "2.5.12-rc13" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From 14b3427ec918e8ba4a5d75802b9b19407aa1ef9f Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 05:43:31 +0000 Subject: [PATCH 31/85] set next macro chart for kubefirst - 2.5.12-rc14 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 1b7b9ab2e..7f8b0ec73 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc13" + helmChartVersion = "2.5.12-rc14" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From ea4c925b91ef06e11b1d1ee6dc17afe7bed430a8 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Thu, 5 Sep 2024 06:51:58 +0000 Subject: [PATCH 32/85] set next macro chart for kubefirst - 2.6.0 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 7f8b0ec73..7220f2282 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.5.12-rc14" + helmChartVersion = "2.6.0" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From f6d92ad73f4ad6843edc20310cd336504f5dda07 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 33/85] chore: bubbletea blacklist ci flag --- cmd/version.go | 12 ++++++++---- main.go | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index 1b024c0e5..ef0fe9dac 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,6 +12,7 @@ import ( "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" + "github.com/spf13/viper" ) var ( @@ -32,12 +33,15 @@ func Create() *cobra.Command { ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - progress.Success(versionMsg) + canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") + + if canRunBubbleTea { + progress.Success(versionMsg) + } else { + fmt.Print(versionMsg) + } }, } - // todo review defaults and update descriptions - versionCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") - return versionCmd } diff --git a/main.go b/main.go index c99539771..98dc54e3f 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) err = viper.WriteConfig() if err != nil { From 95efc98924cac6585f5ccf4787e64f745f9e7776 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:05:51 -0500 Subject: [PATCH 34/85] chore: error handling --- cmd/version.go | 13 ++++++------- main.go | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index ef0fe9dac..da3472697 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -12,7 +12,6 @@ import ( "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -33,13 +32,13 @@ func Create() *cobra.Command { ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") + // canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") - if canRunBubbleTea { - progress.Success(versionMsg) - } else { - fmt.Print(versionMsg) - } + // if canRunBubbleTea { + progress.Success(versionMsg) + // } else { + // fmt.Print(versionMsg) + // } }, } diff --git a/main.go b/main.go index 98dc54e3f..7d80939b0 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -137,7 +137,7 @@ func main() { _, err := progress.Progress.Run() if err != nil { - stdLog.Panicf("unable to run bubbletea program, error is: %s", err) + stdLog.Panicf("unable to set log-file-location, error is: %s", err) } } else { progress.DisableBubbleTeaExecution() From 0b4dc49bb4b5cb1dae2d772427ec61be76afcd31 Mon Sep 17 00:00:00 2001 From: konstruct-bot <1@gmail.com> Date: Thu, 5 Sep 2024 13:20:04 +0530 Subject: [PATCH 35/85] rebase --- cmd/version.go | 6 ------ internal/progress/message.go | 2 +- main.go | 5 ++--- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index da3472697..fa3f4e2c9 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -32,13 +32,7 @@ func Create() *cobra.Command { ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - // canRunBubbleTea := viper.GetBool("k1-canRunBubbleTea") - - // if canRunBubbleTea { progress.Success(versionMsg) - // } else { - // fmt.Print(versionMsg) - // } }, } diff --git a/internal/progress/message.go b/internal/progress/message.go index 05af7db78..a26fd1844 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -112,7 +112,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { break case "k3s": - cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) + cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster")) break } diff --git a/main.go b/main.go index 7d80939b0..c99539771 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) err = viper.WriteConfig() if err != nil { @@ -137,7 +136,7 @@ func main() { _, err := progress.Progress.Run() if err != nil { - stdLog.Panicf("unable to set log-file-location, error is: %s", err) + stdLog.Panicf("unable to run bubbletea program, error is: %s", err) } } else { progress.DisableBubbleTeaExecution() From 7dff4e1ca777f285df6f556ce84762162bcb08ba Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:38:01 -0500 Subject: [PATCH 36/85] chore: test without provisioning --- cmd/civo/create.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 4308ac6e4..5c76d99e3 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,12 +12,10 @@ import ( "strings" utils "github.com/konstructio/kubefirst-api/pkg/utils" - "github.com/konstructio/kubefirst/internal/catalog" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/gitShim" "github.com/konstructio/kubefirst/internal/launch" "github.com/konstructio/kubefirst/internal/progress" - "github.com/konstructio/kubefirst/internal/provision" "github.com/konstructio/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -32,10 +30,10 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) - isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) - if !isValid { - return err - } + // isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + // if !isValid { + // return err + // } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { @@ -88,7 +86,7 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + // provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } From ab4195fd2983006c8325ca52ddda5bd2400b6fb3 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 19:07:30 -0500 Subject: [PATCH 37/85] chore: rollback provision --- cmd/civo/create.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 5c76d99e3..962706698 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -30,10 +30,10 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.DisplayLogHints(15) - // isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) - // if !isValid { - // return err - // } + isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if !isValid { + return err + } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { @@ -86,7 +86,7 @@ func createCivo(cmd *cobra.Command, args []string) error { progress.Error("unable to start kubefirst api") } - // provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) return nil } From e650dcf92df29a6a9acace89b99c144613696f10 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 20:18:12 -0500 Subject: [PATCH 38/85] fix: return error when status has error --- internal/progress/ci.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/internal/progress/ci.go b/internal/progress/ci.go index 588a9314d..f44ca32b1 100644 --- a/internal/progress/ci.go +++ b/internal/progress/ci.go @@ -5,7 +5,7 @@ import ( "log" "time" - "github.com/konstructio/kubefirst/internal/cluster" + "github.com/kubefirst/kubefirst/internal/cluster" ) func WatchClusterForCi(clusterName string) { @@ -29,14 +29,8 @@ func WatchClusterForCi(clusterName string) { } if provisioningCluster.Status == "provisioned" { - fullDomainName := provisioningCluster.DomainName - - if provisioningCluster.SubdomainName != "" { - fullDomainName = fmt.Sprintf("%s.%s", provisioningCluster.SubdomainName, provisioningCluster.DomainName) - } - fmt.Println("\n cluster has been provisioned via ci") - fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", fullDomainName) + fmt.Printf("\n kubefirst URL: https://kubefirst.%s \n", provisioningCluster.DomainName) done <- true } } From 010a8caf4a3211c1edb978d4c5690949f1e106e2 Mon Sep 17 00:00:00 2001 From: konstruct-bot <1@gmail.com> Date: Thu, 5 Sep 2024 13:36:26 +0530 Subject: [PATCH 39/85] fix:missing ref --- cmd/civo/create.go | 2 ++ internal/progress/ci.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 962706698..4308ac6e4 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,10 +12,12 @@ import ( "strings" utils "github.com/konstructio/kubefirst-api/pkg/utils" + "github.com/konstructio/kubefirst/internal/catalog" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/gitShim" "github.com/konstructio/kubefirst/internal/launch" "github.com/konstructio/kubefirst/internal/progress" + "github.com/konstructio/kubefirst/internal/provision" "github.com/konstructio/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/internal/progress/ci.go b/internal/progress/ci.go index f44ca32b1..421620f26 100644 --- a/internal/progress/ci.go +++ b/internal/progress/ci.go @@ -5,7 +5,7 @@ import ( "log" "time" - "github.com/kubefirst/kubefirst/internal/cluster" + "github.com/konstructio/kubefirst/internal/cluster" ) func WatchClusterForCi(clusterName string) { From a25c88942463f349b655f12e672c6b7a87f58c74 Mon Sep 17 00:00:00 2001 From: konstruct-bot <1@gmail.com> Date: Sat, 7 Sep 2024 17:58:26 +0530 Subject: [PATCH 40/85] add ci for version and launch delete --- cmd/launch.go | 10 ++++++++-- cmd/version.go | 7 ++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/cmd/launch.go b/cmd/launch.go index 5431932a2..92fcc1d04 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/konstructio/kubefirst/internal/launch" + "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" ) @@ -96,12 +97,17 @@ func launchDeleteCluster() *cobra.Command { TraverseChildren: true, // PreRun: common.CheckDocker, Args: func(cmd *cobra.Command, args []string) error { - if err := cobra.ExactArgs(1)(cmd, args); err != nil { - return fmt.Errorf("you must provide a cluster name as the only argument to this command") + if len(args) < 1 { + return fmt.Errorf("you must provide a cluster name as the first argument") } return nil }, Run: func(cmd *cobra.Command, args []string) { + ciFlag, _ := cmd.Flags().GetBool("ci") + if ciFlag { + progress.DisableBubbleTeaExecution() + } + // args[0] is the cluster name launch.DeleteCluster(args[0]) }, } diff --git a/cmd/version.go b/cmd/version.go index fa3f4e2c9..e90c5c0ac 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -28,11 +28,16 @@ func Create() *cobra.Command { Short: "print the version number for kubefirst-cli", Long: `All software has versions. This is kubefirst's`, Run: func(cmd *cobra.Command, args []string) { + ciFlag, _ := cmd.Flags().GetBool("ci") versionMsg := ` ## ### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) - progress.Success(versionMsg) + if ciFlag { + fmt.Print(versionMsg) + } else { + progress.Success(versionMsg) + } }, } From c07272af92e711c50b7c2449e995f90a4c6ea4e9 Mon Sep 17 00:00:00 2001 From: mrrishi Date: Sat, 7 Sep 2024 21:05:04 +0530 Subject: [PATCH 41/85] fix:delete cluster --- cmd/launch.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/launch.go b/cmd/launch.go index 92fcc1d04..7f6d3f97b 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -100,13 +100,12 @@ func launchDeleteCluster() *cobra.Command { if len(args) < 1 { return fmt.Errorf("you must provide a cluster name as the first argument") } + if len(args) == 2 && args[1] == "ci" { + progress.DisableBubbleTeaExecution() + } return nil }, Run: func(cmd *cobra.Command, args []string) { - ciFlag, _ := cmd.Flags().GetBool("ci") - if ciFlag { - progress.DisableBubbleTeaExecution() - } // args[0] is the cluster name launch.DeleteCluster(args[0]) }, From a6d4eb1c80def313fe7c2bada3028c22dac2abf6 Mon Sep 17 00:00:00 2001 From: mrrishi Date: Sat, 7 Sep 2024 22:08:22 +0530 Subject: [PATCH 42/85] add ci flag for launch --- cmd/launch.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/launch.go b/cmd/launch.go index 7f6d3f97b..c6aca15e8 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -7,10 +7,12 @@ See the LICENSE file for more details. package cmd import ( + // "fmt" + "fmt" "github.com/konstructio/kubefirst/internal/launch" - "github.com/konstructio/kubefirst/internal/progress" + // "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" ) @@ -100,9 +102,6 @@ func launchDeleteCluster() *cobra.Command { if len(args) < 1 { return fmt.Errorf("you must provide a cluster name as the first argument") } - if len(args) == 2 && args[1] == "ci" { - progress.DisableBubbleTeaExecution() - } return nil }, Run: func(cmd *cobra.Command, args []string) { @@ -110,6 +109,6 @@ func launchDeleteCluster() *cobra.Command { launch.DeleteCluster(args[0]) }, } - + launchDeleteClusterCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return launchDeleteClusterCmd } From a1313b638f4c3b1eb1fccec131f0c67c1f5085fd Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:01:01 -0400 Subject: [PATCH 43/85] Remove unused functions. Bump to Go 1.23. Run `gofmt` on all files. --- cmd/k3d/create.go | 4 ++-- internal/progress/message.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 32db2f999..049320096 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -1186,8 +1186,8 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("configuring-vault", 1) - // * configure vault with terraform - // * vault port-forward + //* configure vault with terraform + //* vault port-forward vaultStopChannel := make(chan struct{}, 1) defer func() { close(vaultStopChannel) diff --git a/internal/progress/message.go b/internal/progress/message.go index a26fd1844..05af7db78 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -112,7 +112,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { break case "k3s": - cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster")) + cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) break } From 186cd1e312fb8a055f46738898bcf09ad5909e5d Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Mon, 9 Sep 2024 17:13:50 +0000 Subject: [PATCH 44/85] set next macro chart for kubefirst - 2.6.1-rc1 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index 7220f2282..bc1841f1f 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.6.0" + helmChartVersion = "2.6.1-rc1" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From dce245ffb7e95a01e74cbd22317a42fed9ba043e Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Mon, 9 Sep 2024 19:59:45 +0000 Subject: [PATCH 45/85] set next macro chart for kubefirst - 2.6.1-rc2 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index bc1841f1f..ec8efd3a8 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.6.1-rc1" + helmChartVersion = "2.6.1-rc2" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From c34e116be9e538ec89804724232665bbb67c9081 Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Mon, 9 Sep 2024 20:19:35 +0000 Subject: [PATCH 46/85] set next macro chart for kubefirst - 2.6.1 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index ec8efd3a8..ff96af136 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.6.1-rc2" + helmChartVersion = "2.6.1" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From c7765d17f7a95a9680c73991fff8ac98c2ad6dcc Mon Sep 17 00:00:00 2001 From: mrrishi Date: Mon, 16 Sep 2024 21:15:25 +0530 Subject: [PATCH 47/85] fix reset cmd --- cmd/reset.go | 8 ++++++++ go.mod | 9 ++++++--- go.sum | 20 ++++++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/cmd/reset.go b/cmd/reset.go index 7983aecec..fb57c1491 100755 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -12,6 +12,7 @@ import ( "strconv" "time" + "github.com/charmbracelet/glamour" "github.com/konstructio/kubefirst-api/pkg/progressPrinter" utils "github.com/konstructio/kubefirst-api/pkg/utils" "github.com/konstructio/kubefirst/internal/progress" @@ -30,6 +31,13 @@ var resetCmd = &cobra.Command{ cloudProvider := viper.GetString("kubefirst.cloud-provider") checksMap := viper.Get("kubefirst-checks") + if checksMap == nil { + in := `# Succesfully reset` + out, _ := glamour.Render(in, "dark") + fmt.Print(out) + progress.Progress.Quit() + return nil + } switch v := checksMap.(type) { case string: if v == "" { diff --git a/go.mod b/go.mod index baecf0bf4..93edad7bc 100644 --- a/go.mod +++ b/go.mod @@ -8,13 +8,14 @@ require ( github.com/aws/aws-sdk-go v1.44.230 github.com/charmbracelet/bubbles v0.16.1 github.com/charmbracelet/bubbletea v0.24.2 - github.com/charmbracelet/lipgloss v0.9.1 + github.com/charmbracelet/lipgloss v0.10.0 + github.com/charmbracelet/log v0.4.0 github.com/civo/civogo v0.3.53 github.com/denisbrodbeck/machineid v1.0.1 github.com/dustin/go-humanize v1.0.1 github.com/go-git/go-git/v5 v5.6.1 github.com/hashicorp/vault/api v1.9.0 - github.com/konstructio/kubefirst-api v0.102.0 + github.com/konstructio/kubefirst-api v0.105.0 github.com/kubefirst/metrics-client v0.3.0 github.com/nxadm/tail v1.4.8 github.com/rs/zerolog v1.29.1 @@ -94,6 +95,7 @@ require ( github.com/fvbommel/sortorder v1.0.2 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect @@ -256,7 +258,7 @@ require ( github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.2 github.com/pelletier/go-toml/v2 v2.0.6 // indirect - github.com/rivo/uniseg v0.4.2 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/spf13/afero v1.9.3 // indirect @@ -332,3 +334,4 @@ replace ( k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.24.2 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.24.2 ) + diff --git a/go.sum b/go.sum index e83c32415..b2ac8fab6 100644 --- a/go.sum +++ b/go.sum @@ -253,8 +253,10 @@ github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06 github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg= github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc= github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc= -github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= -github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= +github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s= +github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE= +github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM= +github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -431,6 +433,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -723,8 +727,8 @@ github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8t github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konstructio/kubefirst-api v0.102.0 h1:0l1q8TbD+K3ShQCb1Nv5AJdjc/BVso2nQY2MLIMZWHE= -github.com/konstructio/kubefirst-api v0.102.0/go.mod h1:jpBfSHjZhzcotYBvX4GG7H/y3VZANxri37/3ZO6B/Hk= +github.com/konstructio/kubefirst-api v0.105.0 h1:iy8P3wVI+BySJr2H3+sFZgbkoH9SikDXvmjD/BTHA6E= +github.com/konstructio/kubefirst-api v0.105.0/go.mod h1:jpBfSHjZhzcotYBvX4GG7H/y3VZANxri37/3ZO6B/Hk= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -1013,8 +1017,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= -github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1114,8 +1118,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= From e82b85974b241484488f6ecad9b451f0da60600b Mon Sep 17 00:00:00 2001 From: mrrishi Date: Mon, 16 Sep 2024 21:34:13 +0530 Subject: [PATCH 48/85] handle nil in switch --- cmd/reset.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/reset.go b/cmd/reset.go index fb57c1491..213ee2c5d 100755 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -31,14 +31,14 @@ var resetCmd = &cobra.Command{ cloudProvider := viper.GetString("kubefirst.cloud-provider") checksMap := viper.Get("kubefirst-checks") - if checksMap == nil { - in := `# Succesfully reset` + switch v := checksMap.(type) { + case nil: + // Handle the nil case explicitly + in := `# Successfully reset` out, _ := glamour.Render(in, "dark") fmt.Print(out) progress.Progress.Quit() return nil - } - switch v := checksMap.(type) { case string: if v == "" { log.Info().Msg("checks map is empty, continuing") From a71d9609b111d4404675a33f1d7efdc37180aafc Mon Sep 17 00:00:00 2001 From: mrrishi Date: Mon, 16 Sep 2024 21:36:58 +0530 Subject: [PATCH 49/85] use progress success function --- cmd/reset.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmd/reset.go b/cmd/reset.go index 213ee2c5d..658cddc3a 100755 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -12,7 +12,6 @@ import ( "strconv" "time" - "github.com/charmbracelet/glamour" "github.com/konstructio/kubefirst-api/pkg/progressPrinter" utils "github.com/konstructio/kubefirst-api/pkg/utils" "github.com/konstructio/kubefirst/internal/progress" @@ -34,10 +33,8 @@ var resetCmd = &cobra.Command{ switch v := checksMap.(type) { case nil: // Handle the nil case explicitly - in := `# Successfully reset` - out, _ := glamour.Render(in, "dark") - fmt.Print(out) - progress.Progress.Quit() + message := `# Succesfully reset` + progress.Success(message) return nil case string: if v == "" { From 7708c4cebb97d81f4c9f27e5d2854e0926b8fd2c Mon Sep 17 00:00:00 2001 From: Simon Emms Date: Tue, 17 Sep 2024 10:07:07 +0100 Subject: [PATCH 50/85] fix(google): fix typo (#2285) --- cmd/google/command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/google/command.go b/cmd/google/command.go index 3636d2cdd..5039595ee 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -120,7 +120,7 @@ func Destroy() *cobra.Command { destroyCmd := &cobra.Command{ Use: "destroy", Short: "destroy the kubefirst platform", - Long: "destroy the kubefirst platform running in Goole and remove all resources", + Long: "destroy the kubefirst platform running in Google and remove all resources", RunE: common.Destroy, // PreRun: common.CheckDocker, } From e51895857021c3f1eb602d83a94f5828b2d7925c Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:26:42 -0400 Subject: [PATCH 51/85] Clean up code using GolangCI-Lint --- .golangci.yaml | 121 +++++++++ cmd/akamai/command.go | 7 +- cmd/akamai/create.go | 6 +- cmd/aws/command.go | 6 +- cmd/aws/create.go | 32 +-- cmd/aws/quota.go | 34 +-- cmd/beta.go | 6 +- cmd/civo/backup.go | 12 +- cmd/civo/command.go | 62 ++--- cmd/civo/create.go | 17 +- cmd/civo/quota.go | 43 ++- cmd/digitalocean/command.go | 27 +- cmd/digitalocean/create.go | 27 +- cmd/google/command.go | 10 +- cmd/google/create.go | 26 +- cmd/info.go | 45 ++-- cmd/k3d/command.go | 8 +- cmd/k3d/create.go | 517 ++++++++++++------------------------ cmd/k3d/destroy.go | 133 ++++------ cmd/k3d/mkcert.go | 6 +- cmd/k3d/root-credentials.go | 17 +- cmd/k3d/vault.go | 60 ++--- cmd/k3s/command.go | 8 +- cmd/k3s/create.go | 30 ++- cmd/launch.go | 19 +- cmd/letsencrypt.go | 13 +- cmd/logs.go | 7 +- cmd/reset.go | 35 ++- cmd/root.go | 16 +- cmd/terraform.go | 1 + cmd/version.go | 2 +- cmd/vultr/command.go | 52 ++-- cmd/vultr/create.go | 35 +-- 33 files changed, 675 insertions(+), 765 deletions(-) create mode 100644 .golangci.yaml diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 000000000..7d8269c1e --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,121 @@ +run: + tests: false + concurrency: 5 + timeout: 5m + +linters: + disable-all: true + enable: + - gosimple + - govet + - ineffassign + - staticcheck + - unused + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - decorder + - dogsled + - dupl + - dupword + - durationcheck + - errchkjson + - errname + - errorlint + - exhaustive + - copyloopvar + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gocyclo + - gofmt + - gofumpt + - goheader + - goimports + - gomodguard + - goprintffuncname + - gosec + - gosmopolitan + - grouper + - importas + - inamedparam + - interfacebloat + - ireturn + - loggercheck + - makezero + - mirror + - misspell + - nakedret + - nilerr + - nilnil + - nonamedreturns + - nosprintfhostport + - paralleltest + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - stylecheck + - tenv + - testableexamples + - testifylint + - testpackage + - thelper + - tparallel + - unconvert + - unparam + - usestdlibvars + - wastedassign + - whitespace + - wrapcheck + - zerologlint + +linters-settings: + perfsprint: + int-conversion: false + err-error: false + errorf: true + sprintf1: true + strconcat: false + + ireturn: + allow: + - anon + - error + - empty + - stdlib + - ssh.PublicKey + - tea.Model + + gosec: + confidence: medium + excludes: + - G107 # Potential HTTP request made with variable url: these are often false positives or intentional + - G110 # Decompression bombs: we can check these manually when submitting code + - G306 # Poor file permissions used when creating a directory: we can check these manually when submitting code + - G404 # Use of weak random number generator (math/rand instead of crypto/rand): we can live with these + + stylecheck: + checks: + - "all" + - "-ST1003" # this is covered by a different linter + + gocyclo: + min-complexity: 60 + + exhaustive: + check-generated: false + explicit-exhaustive-switch: false + explicit-exhaustive-map: false + default-case-required: false + default-signifies-exhaustive: true + package-scope-only: false diff --git a/cmd/akamai/command.go b/cmd/akamai/command.go index 714b08891..a8c5dc8f8 100644 --- a/cmd/akamai/command.go +++ b/cmd/akamai/command.go @@ -89,12 +89,12 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") createCmd.Flags().StringVar(&nodeCountFlag, "node-count", akamaiDefaults.NodeCount, "the node count for the cluster") createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", akamaiDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "https", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "https", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") @@ -112,7 +112,6 @@ func Destroy() *cobra.Command { Short: "destroy the kubefirst platform", Long: "destroy the kubefirst platform running in akamai and remove all resources", RunE: common.Destroy, - // PreRun: common.CheckDocker, } return destroyCmd diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index dcf6b83f1..b8a93a668 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -45,8 +45,6 @@ func createAkamai(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to validate provided flags: %w", err) } - // If cluster setup is complete, return - utilities.CreateK1ClusterDirectory(clusterNameFlag) gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) @@ -55,7 +53,6 @@ func createAkamai(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to validate git credentials: %w", err) } - // Validate git executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider)) if !executionControl { newRepositoryNames := []string{"gitops", "metaphor"} @@ -104,7 +101,6 @@ func ValidateProvidedFlags(gitProvider string) error { return fmt.Errorf("your LINODE_TOKEN is not set - please set and re-run your last command") } - // Validate required environment variables for dns provider if dnsProviderFlag == "cloudflare" { if os.Getenv("CF_API_TOKEN") == "" { return fmt.Errorf("your CF_API_TOKEN environment variable is not set. Please set and try again") @@ -119,6 +115,7 @@ func ValidateProvidedFlags(gitProvider string) error { } else { log.Info().Msgf("%q %s", "github.com", key.Type()) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { @@ -126,6 +123,7 @@ func ValidateProvidedFlags(gitProvider string) error { } else { log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") diff --git a/cmd/aws/command.go b/cmd/aws/command.go index 97712ad40..86c6187be 100644 --- a/cmd/aws/command.go +++ b/cmd/aws/command.go @@ -85,12 +85,12 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") createCmd.Flags().StringVar(&nodeCountFlag, "node-count", awsDefaults.NodeCount, "the node count for the cluster") createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", awsDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "aws", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "aws", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the Route53/Cloudflare hosted zone name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") diff --git a/cmd/aws/create.go b/cmd/aws/create.go index e2e51a2be..4c9a00ef6 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -38,13 +38,13 @@ func createAws(cmd *cobra.Command, args []string) error { isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) if !isValid { - return err + return fmt.Errorf("invalid catalog apps: %w", err) } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate provided flags: %w", err) } utilities.CreateK1ClusterDirectory(cliFlags.ClusterName) @@ -64,24 +64,26 @@ func createAws(cmd *cobra.Command, args []string) error { creds, err := awsClient.Config.Credentials.Retrieve(aws.BackgroundContext()) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to retrieve AWS credentials: %w", err) } viper.Set("kubefirst.state-store-creds.access-key-id", creds.AccessKeyID) viper.Set("kubefirst.state-store-creds.secret-access-key-id", creds.SecretAccessKey) viper.Set("kubefirst.state-store-creds.token", creds.SessionToken) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write config: %w", err) + } _, err = awsClient.CheckAvailabilityZones(cliFlags.CloudRegion) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to check availability zones: %w", err) } gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate Git credentials: %w", err) } executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider)) @@ -100,12 +102,14 @@ func createAws(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to initialize Git provider: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write config: %w", err) + } k3dClusterCreationComplete := viper.GetBool("launch.deployed") isK1Debug := strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" @@ -117,10 +121,10 @@ func createAws(cmd *cobra.Command, args []string) error { err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("failed to check kubefirst API availability: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -138,17 +142,15 @@ func ValidateProvidedFlags(gitProvider string) error { case "github": key, err := internalssh.GetHostKey("github.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") diff --git a/cmd/aws/quota.go b/cmd/aws/quota.go index d54f50d00..b5b69ced0 100644 --- a/cmd/aws/quota.go +++ b/cmd/aws/quota.go @@ -18,30 +18,33 @@ import ( // printAwsQuotaWarning provides visual output detailing quota health for aws func printAwsQuotaWarning(messageHeader string, output map[string][]awsinternal.QuotaDetailResponse) string { - var createAwsQuotaWarning bytes.Buffer - createAwsQuotaWarning.WriteString(strings.Repeat("-", 70)) - createAwsQuotaWarning.WriteString(fmt.Sprintf("\n%s\n", messageHeader)) - createAwsQuotaWarning.WriteString(strings.Repeat("-", 70)) - createAwsQuotaWarning.WriteString("\n") + var buf bytes.Buffer + + fmt.Fprintln(&buf, strings.Repeat("-", 70)) + fmt.Fprintln(&buf, messageHeader) + fmt.Fprintln(&buf, strings.Repeat("-", 70)) + fmt.Fprintln(&buf, "") + for service, quotas := range output { - createAwsQuotaWarning.WriteString(fmt.Sprintf("%s\n", service)) - createAwsQuotaWarning.WriteString(strings.Repeat("-", 35)) - createAwsQuotaWarning.WriteString("\n") + fmt.Fprintln(&buf, service) + fmt.Fprintln(&buf, strings.Repeat("-", 35)) + fmt.Fprintln(&buf, "") + for _, thing := range quotas { - createAwsQuotaWarning.WriteString(fmt.Sprintf("%s: %v\n", thing.QuotaName, thing.QuotaValue)) + fmt.Fprintf(&buf, "%s: %v\n", thing.QuotaName, thing.QuotaValue) } - createAwsQuotaWarning.WriteString("\n") + fmt.Fprintln(&buf, "") } // Write to logs, but also output to stdout - return createAwsQuotaWarning.String() + return buf.String() } // evalAwsQuota provides an interface to the command-line -func evalAwsQuota(cmd *cobra.Command, args []string) error { +func evalAwsQuota(cmd *cobra.Command, _ []string) error { cloudRegionFlag, err := cmd.Flags().GetString("cloud-region") if err != nil { - return err + return fmt.Errorf("failed to get cloud region flag: %w", err) } awsClient := &awsinternal.AWSConfiguration{ @@ -49,17 +52,16 @@ func evalAwsQuota(cmd *cobra.Command, args []string) error { } quotaDetails, err := awsClient.GetServiceQuotas([]string{"eks", "vpc"}) if err != nil { - return err + return fmt.Errorf("failed to get service quotas: %w", err) } messageHeader := fmt.Sprintf( - "AWS Quota Health\nRegion: %s\n\nIf you encounter issues deploying your kubefirst cluster, check these quotas and determine if you need to request a limit increase.", + "AWS Quota Health\nRegion: %s\n\nIf you encounter issues deploying your Kubefirst cluster, check these quotas and determine if you need to request a limit increase.", cloudRegionFlag, ) result := printAwsQuotaWarning(messageHeader, quotaDetails) // Write to logs, but also output to stdout fmt.Println(reports.StyleMessage(result)) - return nil } diff --git a/cmd/beta.go b/cmd/beta.go index 777c0cb62..395311dac 100644 --- a/cmd/beta.go +++ b/cmd/beta.go @@ -20,10 +20,10 @@ import ( // betaCmd represents the beta command tree var betaCmd = &cobra.Command{ Use: "beta", - Short: "access kubefirst beta features", - Long: `access kubefirst beta features`, + Short: "access Kubefirst beta features", + Long: `access Kubefirst beta features`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("To learn more about kubefirst, run:") + fmt.Println("To learn more about Kubefirst, run:") fmt.Println(" kubefirst help") if progress.Progress != nil { diff --git a/cmd/civo/backup.go b/cmd/civo/backup.go index 8985e1b29..74d37e685 100644 --- a/cmd/civo/backup.go +++ b/cmd/civo/backup.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package civo import ( + "fmt" "os" "github.com/konstructio/kubefirst-api/pkg/providerConfigs" @@ -17,7 +18,7 @@ import ( "github.com/spf13/viper" ) -func backupCivoSSL(cmd *cobra.Command, args []string) error { +func backupCivoSSL(cmd *cobra.Command, _ []string) error { utils.DisplayLogHints() clusterName := viper.GetString("flags.cluster-name") @@ -33,7 +34,7 @@ func backupCivoSSL(cmd *cobra.Command, args []string) error { case "gitlab": cGitOwner = viper.GetString("flags.gitlab-owner") default: - log.Panic().Msgf("invalid git provider option") + return fmt.Errorf("invalid git provider option: %q", gitProvider) } config := providerConfigs.GetConfig( @@ -52,7 +53,7 @@ func backupCivoSSL(cmd *cobra.Command, args []string) error { for _, path := range paths { if _, err := os.Stat(path); os.IsNotExist(err) { - log.Info().Msgf("checking path: %s", path) + log.Info().Msgf("checking path: %q", path) err := os.MkdirAll(path, os.ModePerm) if err != nil { log.Info().Msg("directory already exists, continuing") @@ -61,10 +62,9 @@ func backupCivoSSL(cmd *cobra.Command, args []string) error { } } - err := ssl.Backup(config.SSLBackupDir, domainNameFlag, config.K1Dir, config.Kubeconfig) + err := ssl.Backup(config.SSLBackupDir, domainName, config.K1Dir, config.Kubeconfig) if err != nil { - log.Info().Msg("error backing up ssl resources") - return err + return fmt.Errorf("error backing up SSL resources: %w", err) } return nil } diff --git a/cmd/civo/command.go b/cmd/civo/command.go index 5bea0c53a..02e170090 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -52,10 +52,10 @@ var ( func NewCommand() *cobra.Command { civoCmd := &cobra.Command{ Use: "civo", - Short: "kubefirst civo installation", - Long: "kubefirst civo", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("To learn more about civo in kubefirst, run:") + Short: "Kubefirst Civo installation", + Long: "Kubefirst Civo", + Run: func(cmd *cobra.Command, _ []string) { + fmt.Println("To learn more about Civo in Kubefirst, run:") fmt.Println(" kubefirst civo --help") if progress.Progress != nil { @@ -73,8 +73,8 @@ func NewCommand() *cobra.Command { func BackupSSL() *cobra.Command { backupSSLCmd := &cobra.Command{ Use: "backup-ssl", - Short: "backup the cluster resources related tls certificates from cert-manager", - Long: "kubefirst uses a combination of external-dns, ingress-nginx, and cert-manager for provisioning automated tls certificates for services with an ingress. this command will backup all the kubernetes resources to restore in a new cluster with the same domain name", + Short: "Backup the cluster resources related to TLS certificates from cert-manager", + Long: "Kubefirst uses a combination of external-dns, ingress-nginx, and cert-manager for provisioning automated TLS certificates for services with an ingress. This command will backup all the Kubernetes resources to restore in a new cluster with the same domain name", RunE: backupCivoSSL, } @@ -84,7 +84,7 @@ func BackupSSL() *cobra.Command { func Create() *cobra.Command { createCmd := &cobra.Command{ Use: "create", - Short: "create the kubefirst platform running on civo kubernetes", + Short: "Create the Kubefirst platform running on Civo Kubernetes", TraverseChildren: true, RunE: createCivo, // PreRun: common.CheckDocker, @@ -93,27 +93,27 @@ func Create() *cobra.Command { civoDefaults := constants.GetCloudDefaults().Civo // todo review defaults and update descriptions - createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "email address for let's encrypt certificate notifications (required)") + createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "Email address for Let's Encrypt certificate notifications (required)") createCmd.MarkFlagRequired("alerts-email") - createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") - createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "NYC1", "the civo region to provision infrastructure in") - createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "the name of the cluster to create") - createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") - createCmd.Flags().StringVar(&nodeCountFlag, "node-count", civoDefaults.NodeCount, "the node count for the cluster") - createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", civoDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "civo", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) - createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") - createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the Civo DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") + createCmd.Flags().BoolVar(&ciFlag, "ci", false, "If running Kubefirst in CI, set this flag to disable interactive features") + createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "NYC1", "The Civo region to provision infrastructure in") + createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "The name of the cluster to create") + createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "The type of cluster to create (i.e. mgmt|workload)") + createCmd.Flags().StringVar(&nodeCountFlag, "node-count", civoDefaults.NodeCount, "The node count for the cluster") + createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", civoDefaults.InstanceSize, "The instance size of the cluster to create") + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "civo", fmt.Sprintf("The DNS provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "The subdomain to use for DNS records (Cloudflare)") + createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "The Civo DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) - createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") - createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") - createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") - createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/konstructio/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") - createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma separated values to install after provision") - createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") - createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "whether or not to install kubefirst pro") + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("The git provider - one of: %s", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("The git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "The GitHub organization for the new GitOps and Metaphor repositories - required if using GitHub") + createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "The GitLab group for the new GitOps and Metaphor projects - required if using GitLab") + createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "The branch to clone for the gitops-template repository") + createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/konstructio/gitops-template.git", "The fully qualified URL to the gitops-template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "Comma separated values to install after provision") + createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "Whether to emit telemetry") + createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "Whether or not to install Kubefirst Pro") return createCmd } @@ -121,8 +121,8 @@ func Create() *cobra.Command { func Destroy() *cobra.Command { destroyCmd := &cobra.Command{ Use: "destroy", - Short: "destroy the kubefirst platform", - Long: "destroy the kubefirst platform running in civo and remove all resources", + Short: "Destroy the Kubefirst platform", + Long: "Destroy the Kubefirst platform running in Civo and remove all resources", RunE: common.Destroy, // PreRun: common.CheckDocker, } @@ -138,7 +138,7 @@ func Quota() *cobra.Command { RunE: evalCivoQuota, } - quotaCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "NYC1", "the civo region to monitor quotas in") + quotaCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "NYC1", "The Civo region to monitor quotas in") return quotaCmd } @@ -146,8 +146,8 @@ func Quota() *cobra.Command { func RootCredentials() *cobra.Command { authCmd := &cobra.Command{ Use: "root-credentials", - Short: "retrieve root authentication information for platform components", - Long: "retrieve root authentication information for platform components", + Short: "Retrieve root authentication information for platform components", + Long: "Retrieve root authentication information for platform components", RunE: common.GetRootCredentials, } diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 4308ac6e4..85ae585f4 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -27,20 +27,20 @@ func createCivo(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "civo") if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to get CLI flags: %w", err) } progress.DisplayLogHints(15) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) if !isValid { - return err + return fmt.Errorf("catalog apps validation failed: %w", err) } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate provided flags: %w", err) } // If cluster setup is complete, return @@ -50,7 +50,7 @@ func createCivo(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate git credentials: %w", err) } // Validate git @@ -70,11 +70,13 @@ func createCivo(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to initialize Git provider: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) - viper.WriteConfig() + if err = viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write viper config: %w", err) + } k3dClusterCreationComplete := viper.GetBool("launch.deployed") isK1Debug := strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" @@ -86,10 +88,10 @@ func createCivo(cmd *cobra.Command, args []string) error { err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("API availability check failed: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -97,7 +99,6 @@ func ValidateProvidedFlags(gitProvider string) error { progress.AddStep("Validate provided flags") if os.Getenv("CIVO_TOKEN") == "" { - // telemetryShim.Transmit(useTelemetryFlag, segmentClient, segment.MetricCloudCredentialsCheckFailed, "CIVO_TOKEN environment variable was not set") return fmt.Errorf("your CIVO_TOKEN is not set - please set and re-run your last command") } diff --git a/cmd/civo/quota.go b/cmd/civo/quota.go index 8107528fa..a5d129d6d 100644 --- a/cmd/civo/quota.go +++ b/cmd/civo/quota.go @@ -23,19 +23,19 @@ import ( ) const ( - // The threshold at which civo quotas will trigger a warning + // The threshold at which Civo quotas will trigger a warning quotaObjectThresholdWarning = 80 - // The threshold at which civo quotas will trigger a critical warning + // The threshold at which Civo quotas will trigger a critical warning quotaObjectThresholdCritical = 90 // The link to request a quota limit increase within Civo civoQuotaIncreaseLink = "https://dashboard.civo.com/quota/edit" ) -// checkFields asserts which limits should be checked against the civo quota +// checkFields asserts which limits should be checked against the Civo quota // These fields are the json values of the Quota struct // https://github.com/civo/civogo/blob/master/quota.go#L9 // All values used here must be of type int, excluding the string fields -var checkFields map[string]string = map[string]string{ +var checkFields = map[string]string{ "cpu_core_limit": "cpu_core_usage", "database_count_limit": "database_count_usage", "database_cpu_core_limit": "database_cpu_core_usage", @@ -68,19 +68,19 @@ type quotaFormattedOutput struct { limitValue float64 } -// returnCivoQuotaEvaluation fetches quota from civo and compares limits to usage +// returnCivoQuotaEvaluation fetches quota from Civo and compares limits to usage func returnCivoQuotaEvaluation(cloudRegion string) (string, int, int, error) { - // Fetch quota from civo + // Fetch quota from Civo client, err := civogo.NewClient(os.Getenv("CIVO_TOKEN"), cloudRegion) if err != nil { - log.Info().Msg(err.Error()) - return "", 0, 0, err + log.Printf("failed to create Civo client: %v", err) + return "", 0, 0, fmt.Errorf("failed to create Civo client: %w", err) } quota, err := client.GetQuota() if err != nil { - log.Info().Msgf("failed to fetch civo quota: %s", err) - return "", 0, 0, err + log.Printf("failed to fetch Civo quota: %v", err) + return "", 0, 0, fmt.Errorf("failed to fetch Civo quota: %w", err) } // Container for quota response as a map @@ -89,13 +89,12 @@ func returnCivoQuotaEvaluation(cloudRegion string) (string, int, int, error) { // Marshal quota and unmarshal into map quotaJSON, err := json.Marshal(quota) if err != nil { - log.Info().Msgf("failed to marshal civo quota struct: %s", err) - return "", 0, 0, err + log.Printf("failed to marshal Civo quota struct: %v", err) + return "", 0, 0, fmt.Errorf("failed to marshal Civo quota struct: %w", err) } - err = json.Unmarshal(quotaJSON, "aMap) - if err != nil { - log.Info().Msgf("failed to unmarshal civo quota struct: %s", err) - return "", 0, 0, err + if err := json.Unmarshal(quotaJSON, "aMap); err != nil { + log.Printf("failed to unmarshal Civo quota struct: %v", err) + return "", 0, 0, fmt.Errorf("failed to unmarshal Civo quota struct: %w", err) } // Compare actual to limit and warn against threshold @@ -117,11 +116,11 @@ func returnCivoQuotaEvaluation(cloudRegion string) (string, int, int, error) { switch { case percentCalc > quotaObjectThresholdWarning && percentCalc < quotaObjectThresholdCritical: - quotaWarnings += 1 + quotaWarnings++ outputFormat := checkObj.formatQuotaOutput(yellow(percentExpr)) output = append(output, outputFormat) case percentCalc > quotaObjectThresholdCritical: - quotaFailures += 1 + quotaFailures++ outputFormat := checkObj.formatQuotaOutput(red(percentExpr)) output = append(output, outputFormat) default: @@ -148,7 +147,7 @@ func (q quotaFormattedOutput) formatQuotaOutput(usageExpression string) string { ) } -// printCivoQuotaWarning provides visual output detailing quota health for civo +// printCivoQuotaWarning provides visual output detailing quota health for Civo func printCivoQuotaWarning(messageHeader string, output []string) string { var createCivoQuotaWarning bytes.Buffer createCivoQuotaWarning.WriteString(strings.Repeat("-", 70)) @@ -169,17 +168,17 @@ func printCivoQuotaWarning(messageHeader string, output []string) string { func evalCivoQuota(cmd *cobra.Command, args []string) error { civoToken := os.Getenv("CIVO_TOKEN") if len(civoToken) == 0 { - return fmt.Errorf("\n\nYour CIVO_TOKEN environment variable isn't set,\nvisit this link https://dashboard.civo.com/security and set CIVO_TOKEN") + return fmt.Errorf("your CIVO_TOKEN environment variable isn't set, visit this link https://dashboard.civo.com/security and set CIVO_TOKEN") } cloudRegionFlag, err := cmd.Flags().GetString("cloud-region") if err != nil { - return err + return fmt.Errorf("failed to get cloud region flag: %w", err) } message, _, _, err := returnCivoQuotaEvaluation(cloudRegionFlag) if err != nil { - return err + return fmt.Errorf("failed to evaluate Civo quota: %w", err) } // Write to logs, but also output to stdout diff --git a/cmd/digitalocean/command.go b/cmd/digitalocean/command.go index c05ebf8b6..ff97cffe5 100644 --- a/cmd/digitalocean/command.go +++ b/cmd/digitalocean/command.go @@ -12,7 +12,6 @@ import ( "github.com/konstructio/kubefirst-api/pkg/constants" "github.com/konstructio/kubefirst/internal/common" "github.com/konstructio/kubefirst/internal/progress" - "github.com/spf13/cobra" ) @@ -53,10 +52,10 @@ var ( func NewCommand() *cobra.Command { digitaloceanCmd := &cobra.Command{ Use: "digitalocean", - Short: "kubefirst DigitalOcean installation", - Long: "kubefirst digitalocean", + Short: "Kubefirst DigitalOcean installation", + Long: "Kubefirst DigitalOcean", Run: func(cmd *cobra.Command, args []string) { - fmt.Println("To learn more about digital ocean in kubefirst, run:") + fmt.Println("To learn more about DigitalOcean in Kubefirst, run:") fmt.Println(" kubefirst digitalocean --help") if progress.Progress != nil { @@ -77,7 +76,7 @@ func NewCommand() *cobra.Command { func Create() *cobra.Command { createCmd := &cobra.Command{ Use: "create", - Short: "create the kubefirst platform running on DigitalOcean Kubernetes", + Short: "create the Kubefirst platform running on DigitalOcean Kubernetes", TraverseChildren: true, RunE: createDigitalocean, // PreRun: common.CheckDocker, @@ -88,25 +87,25 @@ func Create() *cobra.Command { // todo review defaults and update descriptions createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "email address for let's encrypt certificate notifications (required)") createCmd.MarkFlagRequired("alerts-email") - createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") + createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running Kubefirst in CI, set this flag to disable interactive features") createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "nyc3", "the DigitalOcean region to provision infrastructure in") createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "the name of the cluster to create") createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") createCmd.Flags().StringVar(&nodeCountFlag, "node-count", doDefaults.NodeCount, "the node count for the cluster") createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", doDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "digitalocean", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "digitalocean", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the DigitalOcean DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) - createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") - createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using GitHub") + createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using GitLab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/konstructio/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma separated values to install after provision") createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") - createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "whether or not to install kubefirst pro") + createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "whether or not to install Kubefirst Pro") return createCmd } @@ -114,8 +113,8 @@ func Create() *cobra.Command { func Destroy() *cobra.Command { destroyCmd := &cobra.Command{ Use: "destroy", - Short: "destroy the kubefirst platform", - Long: "destroy the kubefirst platform running in DigitalOcean and remove all resources", + Short: "destroy the Kubefirst platform", + Long: "destroy the Kubefirst platform running in DigitalOcean and remove all resources", RunE: common.Destroy, // PreRun: common.CheckDocker, } diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index 9ae9e2aa7..3c705b0f0 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package digitalocean import ( + "errors" "fmt" "os" "strings" @@ -29,20 +30,24 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "digitalocean") if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to get CLI flags: %w", err) } progress.DisplayLogHints(20) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if err != nil { + return fmt.Errorf("catalog validation error: %w", err) + } + if !isValid { - return err + return errors.New("catalog did not pass a validation check") } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate provided flags: %w", err) } // If cluster setup is complete, return @@ -50,7 +55,7 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { if clusterSetupComplete { err = fmt.Errorf("this cluster install process has already completed successfully") progress.Error(err.Error()) - return nil + return err } utilities.CreateK1ClusterDirectory(clusterNameFlag) @@ -58,7 +63,7 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate git credentials: %w", err) } // Validate git @@ -78,7 +83,7 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to initialize git provider: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) @@ -94,10 +99,10 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("failed to check app availability for Kubefirst API: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -113,7 +118,7 @@ func ValidateProvidedFlags(gitProvider string) error { for _, env := range []string{"DO_TOKEN", "DO_SPACES_KEY", "DO_SPACES_SECRET"} { if os.Getenv(env) == "" { - return fmt.Errorf("your %s variable is unset - please set it before continuing", env) + return fmt.Errorf("your %q variable is unset - please set it before continuing", env) } } @@ -122,16 +127,14 @@ func ValidateProvidedFlags(gitProvider string) error { key, err := internalssh.GetHostKey("github.com") if err != nil { return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") diff --git a/cmd/google/command.go b/cmd/google/command.go index 5039595ee..30588cf24 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -57,7 +57,7 @@ func NewCommand() *cobra.Command { Use: "google", Short: "kubefirst Google installation", Long: "kubefirst google", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { fmt.Println("To learn more about google in kubefirst, run:") fmt.Println(" kubefirst beta google --help") @@ -79,7 +79,7 @@ func NewCommand() *cobra.Command { func Create() *cobra.Command { createCmd := &cobra.Command{ Use: "create", - Short: "create the kubefirst platform running on GCP kubernetes", + Short: "create the kubefirst platform running on GCP Kubernetes", TraverseChildren: true, RunE: createGoogle, // PreRun: common.CheckDocker, @@ -96,14 +96,14 @@ func Create() *cobra.Command { createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") createCmd.Flags().StringVar(&nodeCountFlag, "node-count", googleDefaults.NodeCount, "the node count for the cluster") createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", googleDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "google", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "google", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the GCP DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") createCmd.Flags().StringVar(&googleProjectFlag, "google-project", "", "google project id (required)") createCmd.MarkFlagRequired("google-project") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") diff --git a/cmd/google/create.go b/cmd/google/create.go index e15651df2..087eb928f 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -30,28 +30,27 @@ func createGoogle(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "google") if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to get flags: %w", err) } progress.DisplayLogHints(20) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) if !isValid { - return err + return fmt.Errorf("catalog apps validation failed: %w", err) } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("validation of provided flags failed: %w", err) } - // If cluster setup is complete, return clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") if clusterSetupComplete { err = fmt.Errorf("this cluster install process has already completed successfully") progress.Error(err.Error()) - return nil + return fmt.Errorf("cluster setup is complete: %w", err) } utilities.CreateK1ClusterDirectory(clusterNameFlag) @@ -59,7 +58,7 @@ func createGoogle(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("git credentials validation failed: %w", err) } executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider)) @@ -77,7 +76,7 @@ func createGoogle(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("initialization of git provider failed: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) @@ -93,10 +92,10 @@ func createGoogle(cmd *cobra.Command, args []string) error { err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("kubefirst api availability check failed: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -110,23 +109,22 @@ func ValidateProvidedFlags(gitProvider string) error { _, err := os.Open(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) if err != nil { progress.Error("Unable to read GOOGLE_APPLICATION_CREDENTIALS file") + return fmt.Errorf("could not open GOOGLE_APPLICATION_CREDENTIALS file: %w", err) } switch gitProvider { case "github": key, err := internalssh.GetHostKey("github.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") diff --git a/cmd/info.go b/cmd/info.go index f1a5b1160..5b6cc2e4e 100755 --- a/cmd/info.go +++ b/cmd/info.go @@ -7,7 +7,10 @@ See the LICENSE file for more details. package cmd import ( + "bytes" + "fmt" "runtime" + "text/tabwriter" "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" @@ -22,30 +25,24 @@ var infoCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { config := configs.ReadConfig() - content := ` -## -# Info summary - -| Name | Value | -| --- | --- | -| Operational System | ` + config.LocalOs + ` | -| Architecture | ` + config.LocalArchitecture + `| -| Go Lang version | ` + runtime.Version() + `| -| Kubefirst config file | ` + config.KubefirstConfigFilePath + `| -| Kubefirst config folder | ` + config.K1FolderPath + `| -| Kubefirst Version | ` + configs.K1Version + `| -` - - // infoSummary.WriteString(fmt.Sprintf("Kubectl path: %s", config.KubectlClientPath)) - // infoSummary.WriteString(fmt.Sprintf("Terraform path: %s", config.TerraformClientPath)) - // infoSummary.WriteString(fmt.Sprintf("Kubeconfig path: %s", config.KubeConfigPath)) - - // if configs.K1Version == "" { - // infoSummary.WriteString("\n\nWarning: It seems you are running kubefirst in development mode,") - // infoSummary.WriteString(" please use LDFLAGS to ensure you use the proper template version and avoid unexpected behavior") - // } - - progress.Success(content) + var buf bytes.Buffer + + tw := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', tabwriter.Debug) + + fmt.Fprintln(&buf, "##") + fmt.Fprintln(&buf, "# Info summary") + fmt.Fprintln(&buf, "") + + fmt.Fprintf(tw, "Name\tValue\n") + fmt.Fprintf(tw, "---\t---\n") + fmt.Fprintf(tw, "Operational System\t%s\n", config.LocalOs) + fmt.Fprintf(tw, "Architecture\t%s\n", config.LocalArchitecture) + fmt.Fprintf(tw, "Golang version\t%s\n", runtime.Version()) + fmt.Fprintf(tw, "Kubefirst config file\t%s\n", config.KubefirstConfigFilePath) + fmt.Fprintf(tw, "Kubefirst config folder\t%s\n", config.K1FolderPath) + fmt.Fprintf(tw, "Kubefirst Version\t%s\n", configs.K1Version) + + progress.Success(buf.String()) }, } diff --git a/cmd/k3d/command.go b/cmd/k3d/command.go index ed9cde811..13bc7422d 100644 --- a/cmd/k3d/command.go +++ b/cmd/k3d/command.go @@ -39,7 +39,7 @@ var ( // Supported git providers supportedGitProviders = []string{"github", "gitlab"} - // Supported git providers + // Supported git protocols supportedGitProtocolOverride = []string{"https", "ssh"} ) @@ -89,8 +89,8 @@ func Create() *cobra.Command { createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "the name of the cluster to create") createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) createCmd.Flags().StringVar(&githubUserFlag, "github-user", "", "the GitHub user for the new gitops and metaphor repositories - this cannot be used with --github-org") createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - this cannot be used with --github-user") createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") @@ -137,7 +137,7 @@ func RootCredentials() *cobra.Command { RunE: getK3dRootCredentials, } - authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the argocd password to the clipboard (optional)") + authCmd.Flags().BoolVar(©ArgoCDPasswordToClipboardFlag, "argocd", false, "copy the ArgoCD password to the clipboard (optional)") authCmd.Flags().BoolVar(©KbotPasswordToClipboardFlag, "kbot", false, "copy the kbot password to the clipboard (optional)") authCmd.Flags().BoolVar(©VaultPasswordToClipboardFlag, "vault", false, "copy the vault password to the clipboard (optional)") diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 049320096..5eb6df74b 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -18,19 +18,17 @@ import ( "syscall" "time" + argocdapi "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" "github.com/atotto/clipboard" "github.com/dustin/go-humanize" - "github.com/rs/zerolog/log" - - argocdapi "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" "github.com/go-git/go-git/v5" githttps "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/konstructio/kubefirst-api/pkg/argocd" "github.com/konstructio/kubefirst-api/pkg/configs" constants "github.com/konstructio/kubefirst-api/pkg/constants" "github.com/konstructio/kubefirst-api/pkg/gitClient" - github "github.com/konstructio/kubefirst-api/pkg/github" - gitlab "github.com/konstructio/kubefirst-api/pkg/gitlab" + "github.com/konstructio/kubefirst-api/pkg/github" + "github.com/konstructio/kubefirst-api/pkg/gitlab" "github.com/konstructio/kubefirst-api/pkg/handlers" "github.com/konstructio/kubefirst-api/pkg/k3d" "github.com/konstructio/kubefirst-api/pkg/k8s" @@ -50,6 +48,7 @@ import ( "github.com/kubefirst/metrics-client/pkg/telemetry" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -60,70 +59,64 @@ import ( func runK3d(cmd *cobra.Command, args []string) error { ciFlag, err := cmd.Flags().GetBool("ci") if err != nil { - return err + return fmt.Errorf("failed to get 'ci' flag: %w", err) } clusterNameFlag, err := cmd.Flags().GetString("cluster-name") if err != nil { - return err + return fmt.Errorf("failed to get 'cluster-name' flag: %w", err) } clusterTypeFlag, err := cmd.Flags().GetString("cluster-type") if err != nil { - return err + return fmt.Errorf("failed to get 'cluster-type' flag: %w", err) } githubOrgFlag, err := cmd.Flags().GetString("github-org") if err != nil { - return err + return fmt.Errorf("failed to get 'github-org' flag: %w", err) } githubUserFlag, err := cmd.Flags().GetString("github-user") if err != nil { - return err + return fmt.Errorf("failed to get 'github-user' flag: %w", err) } gitlabGroupFlag, err := cmd.Flags().GetString("gitlab-group") if err != nil { - return err + return fmt.Errorf("failed to get 'gitlab-group' flag: %w", err) } gitProviderFlag, err := cmd.Flags().GetString("git-provider") if err != nil { - return err + return fmt.Errorf("failed to get 'git-provider' flag: %w", err) } gitProtocolFlag, err := cmd.Flags().GetString("git-protocol") if err != nil { - return err + return fmt.Errorf("failed to get 'git-protocol' flag: %w", err) } gitopsTemplateURLFlag, err := cmd.Flags().GetString("gitops-template-url") if err != nil { - return err + return fmt.Errorf("failed to get 'gitops-template-url' flag: %w", err) } gitopsTemplateBranchFlag, err := cmd.Flags().GetString("gitops-template-branch") if err != nil { - return err + return fmt.Errorf("failed to get 'gitops-template-branch' flag: %w", err) } installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") if err != nil { - return err + return fmt.Errorf("failed to get 'install-catalog-apps' flag: %w", err) } useTelemetryFlag, err := cmd.Flags().GetBool("use-telemetry") if err != nil { - return err + return fmt.Errorf("failed to get 'use-telemetry' flag: %w", err) } - // // If cluster setup is complete, return - // clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") - // if clusterSetupComplete { - // return fmt.Errorf("this cluster install process has already completed successfully") - // } - utilities.CreateK1ClusterDirectory(clusterNameFlag) utils.DisplayLogHints() @@ -136,44 +129,29 @@ func runK3d(cmd *cobra.Command, args []string) error { case "github": key, err := internalssh.GetHostKey("github.com") if err != nil { - return errors.New("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("Host key for github.com: %q", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { - return errors.New("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("Host key for gitlab.com: %q", key.Type()) } - // Either user or org can be specified for github, not both if githubOrgFlag != "" && githubUserFlag != "" { return errors.New("only one of --github-user or --github-org can be supplied") } - // Check for existing port forwards before continuing err = k8s.CheckForExistingPortForwards(8080, 8200, 9000, 9094) if err != nil { - return fmt.Errorf("%s - this port is required to set up your kubefirst environment - please close any existing port forwards before continuing", err.Error()) + return fmt.Errorf("error checking existing port forwards: %w", err) } - // Verify Docker is running # TODO: reintroduce once we support more runtimes - // dcli := docker.DockerClientWrapper{ - // Client: docker.NewDockerClient(), - // } - // _, err = dcli.CheckDockerReady() - // if err != nil { - // return err - // } - - // Global context ctx, cancel := context.WithCancel(context.Background()) defer cancel() - // Clients httpClient := http.DefaultClient kubefirstTeam := os.Getenv("KUBEFIRST_TEAM") @@ -181,7 +159,6 @@ func runK3d(cmd *cobra.Command, args []string) error { kubefirstTeam = "false" } - // Store flags for application state maintenance viper.Set("flags.cluster-name", clusterNameFlag) viper.Set("flags.domain-name", k3d.DomainName) viper.Set("flags.git-provider", gitProviderFlag) @@ -189,7 +166,6 @@ func runK3d(cmd *cobra.Command, args []string) error { viper.Set("kubefirst.cloud-provider", "k3d") viper.WriteConfig() - // Switch based on git provider, set params var cGitHost, cGitOwner, cGitUser, cGitToken, containerRegistryHost string var cGitlabOwnerGroupID int switch gitProviderFlag { @@ -197,43 +173,36 @@ func runK3d(cmd *cobra.Command, args []string) error { cGitHost = k3d.GithubHost containerRegistryHost = "ghcr.io" - // Attempt to retrieve session-scoped token for GitHub user gitHubService := services.NewGitHubService(httpClient) gitHubHandler := handlers.NewGitHubHandler(gitHubService) - // var existingToken string if os.Getenv("GITHUB_TOKEN") != "" { existingToken = os.Getenv("GITHUB_TOKEN") - } else if os.Getenv("GITHUB_TOKEN") == "" && viper.GetString("github.session_token") != "" { + } else if viper.GetString("github.session_token") != "" { existingToken = viper.GetString("github.session_token") } gitHubAccessToken, err := wrappers.AuthenticateGitHubUserWrapper(existingToken, gitHubHandler) if err != nil { - log.Warn().Msgf(err.Error()) + log.Warn().Msg(err.Error()) } - // Token will either be user-provided or generated by kubefirst invocation cGitToken = gitHubAccessToken - // Verify token scopes err = github.VerifyTokenPermissions(cGitToken) if err != nil { - return err + return fmt.Errorf("failed to verify GitHub token permissions: %w", err) } - log.Info().Msg("verifying github authentication") + log.Info().Msg("verifying GitHub authentication") githubUser, err := gitHubHandler.GetGitHubUser(cGitToken) if err != nil { - return err + return fmt.Errorf("failed to get GitHub user: %w", err) } - // Owner is either an organization or a personal user's GitHub handle if githubOrgFlag != "" { cGitOwner = githubOrgFlag - } else if githubUserFlag != "" { - cGitOwner = githubUser - } else if githubOrgFlag == "" && githubUserFlag == "" { + } else { cGitOwner = githubUser } cGitUser = githubUser @@ -243,85 +212,54 @@ func runK3d(cmd *cobra.Command, args []string) error { viper.WriteConfig() case "gitlab": if gitlabGroupFlag == "" { - return fmt.Errorf("please provide a gitlab group using the --gitlab-group flag") - } - - if os.Getenv("GITLAB_TOKEN") == "" { - return fmt.Errorf("GITLAB_TOKEN environment variable unset - please set it and try again") + return errors.New("please provide a gitlab group using the --gitlab-group flag") } cGitToken = os.Getenv("GITLAB_TOKEN") + if cGitToken == "" { + return errors.New("GITLAB_TOKEN environment variable unset - please set it and try again") + } - // Verify token scopes err = gitlab.VerifyTokenPermissions(cGitToken) if err != nil { - return err + return fmt.Errorf("failed to verify GitLab token permissions: %w", err) } gitlabClient, err := gitlab.NewGitLabClient(cGitToken, gitlabGroupFlag) if err != nil { - return err + return fmt.Errorf("failed to create GitLab client: %w", err) } cGitHost = k3d.GitlabHost cGitOwner = gitlabClient.ParentGroupPath cGitlabOwnerGroupID = gitlabClient.ParentGroupID - log.Info().Msgf("set gitlab owner to %s", cGitOwner) + log.Info().Msgf("set gitlab owner to %q", cGitOwner) - // Get authenticated user's name user, _, err := gitlabClient.Client.Users.CurrentUser() if err != nil { - return fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set %s", err.Error()) + return fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set: %w", err) } cGitUser = user.Username - - containerRegistryHost = "registry.gitlab.com" viper.Set("flags.gitlab-owner", gitlabGroupFlag) viper.Set("flags.gitlab-owner-group-id", cGitlabOwnerGroupID) viper.Set("gitlab.session_token", cGitToken) viper.WriteConfig() default: - log.Error().Msgf("invalid git provider option") + return fmt.Errorf("invalid git provider option %q", gitProviderFlag) } - // Ask for confirmation var gitDestDescriptor string switch gitProviderFlag { case "github": if githubOrgFlag != "" { gitDestDescriptor = "Organization" - } - if githubUserFlag != "" { - gitDestDescriptor = "User" - } - if githubUserFlag == "" && githubOrgFlag == "" { + } else { gitDestDescriptor = "User" } case "gitlab": gitDestDescriptor = "Group" } - // todo - // Since it's possible to stop and restart, cGitOwner may need to be reset - // if cGitOwner == "" { - // switch gitProviderFlag { - // case "github": - // cGitOwner = viper.GetString("flags.github-owner") - // case "gitlab": - // cGitOwner = viper.GetString("flags.gitlab-owner") - // } - //} - // - // model, err := presentRecap(gitProviderFlag, gitDestDescriptor, cGitOwner) - //if err != nil { - // return err - //} - //_, err = tea.NewProgram(model).Run() - //if err != nil { - // return err - //} - - // Instantiate K3d config config := k3d.GetConfig(clusterNameFlag, gitProviderFlag, cGitOwner, gitProtocolFlag) switch gitProviderFlag { case "github": @@ -342,13 +280,10 @@ func runK3d(cmd *cobra.Command, args []string) error { segClient := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) - // Progress output progressPrinter.AddTracker("preflight-checks", "Running preflight checks", 5) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) progressPrinter.IncrementTracker("preflight-checks", 1) - // this branch flag value is overridden with a tag when running from a - // kubefirst binary for version compatibility switch configs.K1Version { case "development": if strings.Contains(gitopsTemplateURLFlag, "https://github.com/konstructio/gitops-template.git") && gitopsTemplateBranchFlag == "" { @@ -356,24 +291,24 @@ func runK3d(cmd *cobra.Command, args []string) error { } default: switch gitopsTemplateURLFlag { - case "https://github.com/konstructio/gitops-template.git": // default value + case "https://github.com/konstructio/gitops-template.git": if gitopsTemplateBranchFlag == "" { gitopsTemplateBranchFlag = configs.K1Version } - case "https://github.com/konstructio/gitops-template": // edge case for valid but incomplete url + case "https://github.com/konstructio/gitops-template": if gitopsTemplateBranchFlag == "" { gitopsTemplateBranchFlag = configs.K1Version } - default: // not equal to our defaults - if gitopsTemplateBranchFlag == "" { // didn't supply the branch flag but they did supply the repo flag - return fmt.Errorf("must supply gitops-template-branch flag when gitops-template-url is overridden") + default: + if gitopsTemplateBranchFlag == "" { + return errors.New("must supply gitops-template-branch flag when gitops-template-url is overridden") } } } - log.Info().Msgf("kubefirst version configs.K1Version: %s ", configs.K1Version) - log.Info().Msgf("cloning gitops-template repo url: %s ", gitopsTemplateURLFlag) - log.Info().Msgf("cloning gitops-template repo branch: %s ", gitopsTemplateBranchFlag) + log.Info().Msgf("kubefirst version configs.K1Version: %q", configs.K1Version) + log.Info().Msgf("cloning gitops-template repo url: %q", gitopsTemplateURLFlag) + log.Info().Msgf("cloning gitops-template repo branch: %q", gitopsTemplateBranchFlag) atlantisWebhookSecret := viper.GetString("secrets.atlantis-webhook") if atlantisWebhookSecret == "" { @@ -391,13 +326,11 @@ func runK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("checking authentication to required providers") - // check disk free, err := utils.GetAvailableDiskSize() if err != nil { - return err + return fmt.Errorf("failed to get available disk size: %w", err) } - // convert available disk size to GB format availableDiskSize := float64(free) / humanize.GByte if availableDiskSize < constants.MinimumAvailableDiskSize { return fmt.Errorf( @@ -407,20 +340,14 @@ func runK3d(cmd *cobra.Command, args []string) error { } progressPrinter.IncrementTracker("preflight-checks", 1) - // Objects to check for - // Repositories that will be created throughout the initialization process newRepositoryNames := []string{"gitops", "metaphor"} newTeamNames := []string{"admins", "developers"} - // Check git credentials executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider)) if !executionControl { telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckStarted, "") if len(cGitToken) == 0 { - msg := fmt.Sprintf( - "please set a %s_TOKEN environment variable to continue", - strings.ToUpper(config.GitProvider), - ) + msg := fmt.Sprintf("please set a %s_TOKEN environment variable to continue", strings.ToUpper(config.GitProvider)) telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckFailed, msg) return errors.New(msg) } @@ -434,7 +361,7 @@ func runK3d(cmd *cobra.Command, args []string) error { } err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { - return err + return fmt.Errorf("failed to initialize Git provider: %w", err) } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider), true) @@ -442,10 +369,10 @@ func runK3d(cmd *cobra.Command, args []string) error { telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckCompleted, "") progressPrinter.IncrementTracker("preflight-checks", 1) } else { - log.Info().Msg(fmt.Sprintf("already completed %s checks - continuing", config.GitProvider)) + log.Info().Msg(fmt.Sprintf("already completed %q checks - continuing", config.GitProvider)) progressPrinter.IncrementTracker("preflight-checks", 1) } - // Swap tokens for git protocol + var gitopsRepoURL string executionControl = viper.GetBool("kubefirst-checks.kbot-setup") if !executionControl { @@ -455,7 +382,7 @@ func runK3d(cmd *cobra.Command, args []string) error { sshPrivateKey, sshPublicKey, err = utils.CreateSshKeyPair() if err != nil { telemetry.SendEvent(segClient, telemetry.KbotSetupFailed, err.Error()) - return err + return fmt.Errorf("failed to create SSH key pair: %w", err) } log.Info().Msg("ssh key pair creation complete") @@ -474,10 +401,8 @@ func runK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("validation and kubefirst cli environment check is complete") - telemetry.SendEvent(segClient, telemetry.InitCompleted, "") telemetry.SendEvent(segClient, telemetry.InitCompleted, "") - // Swap tokens for git protocol switch config.GitProtocol { case "https": gitopsRepoURL = config.DestinationGitopsRepoURL @@ -520,23 +445,22 @@ func runK3d(cmd *cobra.Command, args []string) error { gitopsDirectoryTokens.UseTelemetry = "false" } - // * generate http credentials for git auth over https httpAuth := &githttps.BasicAuth{ Username: cGitUser, Password: cGitToken, } if err != nil { - log.Info().Msgf("generate public keys failed: %s\n", err.Error()) + log.Info().Msgf("generate public keys failed: %q", err.Error()) + return fmt.Errorf("failed to generate public keys: %w", err) } - // * download dependencies to `$HOME/.k1/tools` if !viper.GetBool("kubefirst-checks.tools-downloaded") { log.Info().Msg("installing kubefirst dependencies") err := k3d.DownloadTools(clusterNameFlag, config.GitProvider, cGitOwner, config.ToolsDir, config.GitProtocol) if err != nil { - return err + return fmt.Errorf("failed to download tools: %w", err) } log.Info().Msg("download dependencies `$HOME/.k1/tools` complete") @@ -557,13 +481,10 @@ func runK3d(cmd *cobra.Command, args []string) error { MetaphorProductionIngressURL: fmt.Sprintf("metaphor-production.%s", k3d.DomainName), } - // * git clone and detokenize the gitops repository - // todo improve this logic for removing `kubefirst clean` - // if !viper.GetBool("template-repo.gitops.cloned") || viper.GetBool("template-repo.gitops.removed") { - progressPrinter.IncrementTracker("preflight-checks", 1) progressPrinter.IncrementTracker("preflight-checks", 1) progressPrinter.AddTracker("cloning-and-formatting-git-repositories", "Cloning and formatting git repositories", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + removeAtlantis := false if viper.GetString("secrets.atlantis-ngrok-authtoken") == "" { removeAtlantis = true @@ -574,11 +495,11 @@ func runK3d(cmd *cobra.Command, args []string) error { config.GitProvider, clusterNameFlag, clusterTypeFlag, - config.DestinationGitopsRepoURL, // default to https for git interactions when creating remotes + config.DestinationGitopsRepoURL, config.GitopsDir, gitopsTemplateBranchFlag, gitopsTemplateURLFlag, - config.DestinationMetaphorRepoURL, // default to https for git interactions when creating remotes + config.DestinationMetaphorRepoURL, config.K1Dir, &gitopsDirectoryTokens, config.MetaphorDir, @@ -587,10 +508,9 @@ func runK3d(cmd *cobra.Command, args []string) error { removeAtlantis, ) if err != nil { - return err + return fmt.Errorf("failed to prepare git repositories: %w", err) } - // todo emit init telemetry end viper.Set("kubefirst-checks.gitops-ready-to-push", true) viper.WriteConfig() progressPrinter.IncrementTracker("cloning-and-formatting-git-repositories", 1) @@ -604,7 +524,6 @@ func runK3d(cmd *cobra.Command, args []string) error { switch config.GitProvider { case "github": - // //* create teams and repositories in github executionControl = viper.GetBool("kubefirst-checks.terraform-apply-github") if !executionControl { telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") @@ -612,25 +531,24 @@ func runK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("Creating GitHub resources with Terraform") tfEntrypoint := config.GitopsDir + "/terraform/github" - tfEnvs := map[string]string{} - // tfEnvs = k3d.GetGithubTerraformEnvs(tfEnvs) - tfEnvs["GITHUB_TOKEN"] = cGitToken - tfEnvs["GITHUB_OWNER"] = cGitOwner - tfEnvs["TF_VAR_kbot_ssh_public_key"] = viper.GetString("kbot.public-key") - tfEnvs["AWS_ACCESS_KEY_ID"] = constants.MinioDefaultUsername - tfEnvs["AWS_SECRET_ACCESS_KEY"] = constants.MinioDefaultPassword - tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername - tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword - // Erase public key to prevent it from being created if the git protocol argument is set to htps - switch config.GitProtocol { - case "https": + tfEnvs := map[string]string{ + "GITHUB_TOKEN": cGitToken, + "GITHUB_OWNER": cGitOwner, + "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), + "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, + "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, + "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, + "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, + } + if config.GitProtocol == "https" { tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" } + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) if err != nil { - msg := fmt.Sprintf("error creating github resources with terraform %s: %s", tfEntrypoint, err) - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg) - return errors.New(msg) + msg := fmt.Errorf("error creating GitHub resources with terraform %q: %w", tfEntrypoint, err) + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) + return msg } log.Info().Msgf("created git repositories for github.com/%s", cGitOwner) @@ -643,7 +561,6 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("applying-git-terraform", 1) } case "gitlab": - // //* create teams and repositories in gitlab executionControl = viper.GetBool("kubefirst-checks.terraform-apply-gitlab") if !executionControl { telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") @@ -651,25 +568,25 @@ func runK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("Creating GitLab resources with Terraform") tfEntrypoint := config.GitopsDir + "/terraform/gitlab" - tfEnvs := map[string]string{} - tfEnvs["GITLAB_TOKEN"] = cGitToken - tfEnvs["GITLAB_OWNER"] = gitlabGroupFlag - tfEnvs["TF_VAR_owner_group_id"] = strconv.Itoa(cGitlabOwnerGroupID) - tfEnvs["TF_VAR_kbot_ssh_public_key"] = viper.GetString("kbot.public-key") - tfEnvs["AWS_ACCESS_KEY_ID"] = constants.MinioDefaultUsername - tfEnvs["AWS_SECRET_ACCESS_KEY"] = constants.MinioDefaultPassword - tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername - tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword - // Erase public key to prevent it from being created if the git protocol argument is set to htps - switch config.GitProtocol { - case "https": + tfEnvs := map[string]string{ + "GITLAB_TOKEN": cGitToken, + "GITLAB_OWNER": gitlabGroupFlag, + "TF_VAR_owner_group_id": strconv.Itoa(cGitlabOwnerGroupID), + "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), + "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, + "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, + "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, + "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, + } + if config.GitProtocol == "https" { tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" } + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) if err != nil { - msg := fmt.Sprintf("error creating gitlab resources with terraform %s: %s", tfEntrypoint, err) - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg) - return errors.New(msg) + msg := fmt.Errorf("error creating GitLab resources with terraform %q: %w", tfEntrypoint, err) + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) + return msg } log.Info().Msgf("created git projects and groups for gitlab.com/%s", gitlabGroupFlag) @@ -683,12 +600,11 @@ func runK3d(cmd *cobra.Command, args []string) error { } } - // * push detokenized gitops-template repository content to new remote progressPrinter.AddTracker("pushing-gitops-repos-upstream", "Pushing git repositories", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - log.Info().Msgf("referencing gitops repository: %s", config.DestinationGitopsRepoGitURL) - log.Info().Msgf("referencing metaphor repository: %s", config.DestinationMetaphorRepoURL) + log.Info().Msgf("referencing gitops repository: %q", config.DestinationGitopsRepoGitURL) + log.Info().Msgf("referencing metaphor repository: %q", config.DestinationMetaphorRepoURL) executionControl = viper.GetBool("kubefirst-checks.gitops-repo-pushed") if !executionControl { @@ -696,12 +612,12 @@ func runK3d(cmd *cobra.Command, args []string) error { gitopsRepo, err := git.PlainOpen(config.GitopsDir) if err != nil { - log.Info().Msgf("error opening repo at: %s", config.GitopsDir) + return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) } metaphorRepo, err := git.PlainOpen(config.MetaphorDir) if err != nil { - log.Info().Msgf("error opening repo at: %s", config.MetaphorDir) + return fmt.Errorf("error opening repo at %q: %w", config.MetaphorDir, err) } err = utils.EvalSSHKey(&types.EvalSSHKeyRequest{ @@ -710,11 +626,9 @@ func runK3d(cmd *cobra.Command, args []string) error { GitToken: cGitToken, }) if err != nil { - return err + return fmt.Errorf("failed to evaluate SSH key: %w", err) } - // Push to remotes and use https - // Push gitops repo to remote err = gitopsRepo.Push( &git.PushOptions{ RemoteName: config.GitProvider, @@ -722,14 +636,14 @@ func runK3d(cmd *cobra.Command, args []string) error { }, ) if err != nil { - msg := fmt.Sprintf("error pushing detokenized gitops repository to remote %s: %s", config.DestinationGitopsRepoGitURL, err) - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg) - if !strings.Contains(msg, "already up-to-date") { - log.Panic().Msg(msg) + msg := fmt.Errorf("error pushing detokenized gitops repository to remote %q: %w", config.DestinationGitopsRepoGitURL, err) + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) + if !strings.Contains(msg.Error(), "already up-to-date") { + log.Printf(msg.Error()) + return msg } } - // push metaphor repo to remote err = metaphorRepo.Push( &git.PushOptions{ RemoteName: "origin", @@ -737,27 +651,23 @@ func runK3d(cmd *cobra.Command, args []string) error { }, ) if err != nil { - msg := fmt.Sprintf("error pushing detokenized metaphor repository to remote %s: %s", config.DestinationMetaphorRepoURL, err) - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg) - if !strings.Contains(msg, "already up-to-date") { - log.Panic().Msg(msg) + msg := fmt.Errorf("error pushing detokenized metaphor repository to remote %q: %w", config.DestinationMetaphorRepoURL, err) + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) + if !strings.Contains(msg.Error(), "already up-to-date") { + return msg } } log.Info().Msgf("successfully pushed gitops and metaphor repositories to https://%s/%s", cGitHost, cGitOwner) - // todo delete the local gitops repo and re-clone it - // todo that way we can stop worrying about which origin we're going to push to viper.Set("kubefirst-checks.gitops-repo-pushed", true) viper.WriteConfig() telemetry.SendEvent(segClient, telemetry.GitopsRepoPushCompleted, "") - progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) // todo verify this tracker didnt lose one + progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) } else { log.Info().Msg("already pushed detokenized gitops repository content") progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) } - // * create k3d resources - progressPrinter.AddTracker("creating-k3d-cluster", "Creating k3d cluster", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -768,11 +678,11 @@ func runK3d(cmd *cobra.Command, args []string) error { err := k3d.ClusterCreate(clusterNameFlag, config.K1Dir, config.K3dClient, config.Kubeconfig) if err != nil { - msg := fmt.Sprintf("error creating k3d resources with k3d client %s: %s", config.K3dClient, err) + msg := fmt.Errorf("error creating k3d resources with k3d client %q: %w", config.K3dClient, err) viper.Set("kubefirst-checks.create-k3d-cluster-failed", true) viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyFailed, msg) - return errors.New(msg) + telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyFailed, msg.Error()) + return msg } log.Info().Msg("successfully created k3d cluster") @@ -787,7 +697,6 @@ func runK3d(cmd *cobra.Command, args []string) error { kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) - // kubernetes.BootstrapSecrets progressPrinter.AddTracker("bootstrapping-kubernetes-resources", "Bootstrapping Kubernetes resources", 2) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -795,7 +704,7 @@ func runK3d(cmd *cobra.Command, args []string) error { if !executionControl { err := k3d.GenerateTLSSecrets(kcfg.Clientset, *config) if err != nil { - return err + return fmt.Errorf("failed to generate TLS secrets: %w", err) } err = k3d.AddK3DSecrets( @@ -811,7 +720,7 @@ func runK3d(cmd *cobra.Command, args []string) error { ) if err != nil { log.Info().Msg("Error adding kubernetes secrets for bootstrap") - return err + return fmt.Errorf("failed to add Kubernetes secrets: %w", err) } viper.Set("kubefirst-checks.k8s-secrets-created", true) viper.WriteConfig() @@ -821,25 +730,6 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) } - // //* check for ssl restore - // log.Info().Msg("checking for tls secrets to restore") - // secretsFilesToRestore, err := ioutil.ReadDir(config.SSLBackupDir + "/secrets") - // if err != nil { - // log.Info().Msgf("%s", err) - // } - // if len(secretsFilesToRestore) != 0 { - // // todo would like these but requires CRD's and is not currently supported - // // add crds ( use execShellReturnErrors? ) - // // https://raw.githubusercontent.com/cert-manager/cert-manager/v1.11.0/deploy/crds/crd-clusterissuers.yaml - // // https://raw.githubusercontent.com/cert-manager/cert-manager/v1.11.0/deploy/crds/crd-certificates.yaml - // // add certificates, and clusterissuers - // log.Info().Msgf("found %d tls secrets to restore", len(secretsFilesToRestore)) - // ssl.Restore(config.SSLBackupDir, k3d.DomainName, config.Kubeconfig) - // } else { - // log.Info().Msg("no files found in secrets directory, continuing") - // } - - // Container registry authentication creation containerRegistryAuth := gitShim.ContainerRegistryAuth{ GitProvider: gitProviderFlag, GitUser: cGitUser, @@ -851,15 +741,13 @@ func runK3d(cmd *cobra.Command, args []string) error { } containerRegistryAuthToken, err := gitShim.CreateContainerRegistrySecret(&containerRegistryAuth) if err != nil { - return err + return fmt.Errorf("failed to create container registry secret: %w", err) } progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) - // k3d Readiness checks progressPrinter.AddTracker("verifying-k3d-cluster-readiness", "Verifying Kubernetes cluster is ready", 3) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - // traefik traefikDeployment, err := k8s.ReturnDeploymentObject( kcfg.Clientset, "app.kubernetes.io/name", @@ -868,17 +756,14 @@ func runK3d(cmd *cobra.Command, args []string) error { 240, ) if err != nil { - log.Error().Msgf("error finding traefik deployment: %s", err) - return err + return fmt.Errorf("error finding traefik deployment: %w", err) } _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, traefikDeployment, 240) if err != nil { - log.Error().Msgf("error waiting for traefik deployment ready state: %s", err) - return err + return fmt.Errorf("error waiting for traefik deployment ready state: %w", err) } progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) - // metrics-server metricsServerDeployment, err := k8s.ReturnDeploymentObject( kcfg.Clientset, "k8s-app", @@ -887,13 +772,11 @@ func runK3d(cmd *cobra.Command, args []string) error { 240, ) if err != nil { - log.Error().Msgf("error finding metrics-server deployment: %s", err) - return err + return fmt.Errorf("error finding metrics-server deployment: %w", err) } _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, metricsServerDeployment, 240) if err != nil { - log.Error().Msgf("error waiting for metrics-server deployment ready state: %s", err) - return err + return fmt.Errorf("error waiting for metrics-server deployment ready state: %w", err) } progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) @@ -905,26 +788,24 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) argoCDInstallPath := fmt.Sprintf("github.com:konstructio/manifests/argocd/k3d?ref=%s", constants.KubefirstManifestRepoRef) - // * install argo executionControl = viper.GetBool("kubefirst-checks.argocd-install") if !executionControl { telemetry.SendEvent(segClient, telemetry.ArgoCDInstallStarted, "") - log.Info().Msgf("installing argocd") + log.Info().Msgf("installing ArgoCD") - // Build and apply manifests yamlData, err := kcfg.KustomizeBuild(argoCDInstallPath) if err != nil { - return err + return fmt.Errorf("failed to build ArgoCD manifests: %w", err) } output, err := kcfg.SplitYAMLFile(yamlData) if err != nil { - return err + return fmt.Errorf("failed to split YAML file: %w", err) } err = kcfg.ApplyObjects("", output) if err != nil { telemetry.SendEvent(segClient, telemetry.ArgoCDInstallFailed, err.Error()) - return err + return fmt.Errorf("failed to apply ArgoCD objects: %w", err) } viper.Set("kubefirst-checks.argocd-install", true) @@ -932,44 +813,37 @@ func runK3d(cmd *cobra.Command, args []string) error { telemetry.SendEvent(segClient, telemetry.ArgoCDInstallCompleted, "") progressPrinter.IncrementTracker("installing-argo-cd", 1) } else { - log.Info().Msg("argo cd already installed, continuing") + log.Info().Msg("ArgoCD already installed, continuing") progressPrinter.IncrementTracker("installing-argo-cd", 1) } - // Wait for ArgoCD to be ready _, err = k8s.VerifyArgoCDReadiness(kcfg.Clientset, true, 300) if err != nil { - log.Error().Msgf("error waiting for ArgoCD to become ready: %s", err) - return err + return fmt.Errorf("error waiting for ArgoCD to become ready: %w", err) } var argocdPassword string - // * argocd pods are ready, get and set credentials executionControl = viper.GetBool("kubefirst-checks.argocd-credentials-set") if !executionControl { - log.Info().Msg("Setting argocd username and password credentials") + log.Info().Msg("Setting ArgoCD username and password credentials") argocd.ArgocdSecretClient = kcfg.Clientset.CoreV1().Secrets("argocd") argocdPassword = k8s.GetSecretValue(argocd.ArgocdSecretClient, "argocd-initial-admin-secret", "password") if argocdPassword == "" { - log.Info().Msg("argocd password not found in secret") - return err + return errors.New("ArgoCD password not found in secret") } viper.Set("components.argocd.password", argocdPassword) viper.Set("components.argocd.username", "admin") viper.WriteConfig() - log.Info().Msg("argocd username and password credentials set successfully") - log.Info().Msg("Getting an argocd auth token") + log.Info().Msg("ArgoCD username and password credentials set successfully") + log.Info().Msg("Getting an ArgoCD auth token") - // Test https to argocd var argoCDToken string - // only the host, not the protocol - err := utils.TestEndpointTLS(strings.Replace(k3d.ArgocdURL, "https://", "", 1)) - if err != nil { + if err := utils.TestEndpointTLS(strings.Replace(k3d.ArgocdURL, "https://", "", 1)); err != nil { argoCDStopChannel := make(chan struct{}, 1) - log.Info().Msgf("argocd not available via https, using http") + log.Info().Msgf("ArgoCD not available via https, using http") defer func() { close(argoCDStopChannel) }() @@ -999,78 +873,76 @@ func runK3d(cmd *cobra.Command, args []string) error { } } - log.Info().Msg("argocd admin auth token set") + log.Info().Msg("ArgoCD admin auth token set") viper.Set("components.argocd.auth-token", argoCDToken) viper.Set("kubefirst-checks.argocd-credentials-set", true) viper.WriteConfig() progressPrinter.IncrementTracker("installing-argo-cd", 1) } else { - log.Info().Msg("argo credentials already set, continuing") + log.Info().Msg("ArgoCD credentials already set, continuing") progressPrinter.IncrementTracker("installing-argo-cd", 1) } if configs.K1Version == "development" { err := clipboard.WriteAll(argocdPassword) if err != nil { - log.Error().Err(err).Msg("") + log.Error().Err(err).Msg("failed to copy ArgoCD password to clipboard") } if os.Getenv("SKIP_ARGOCD_LAUNCH") != "true" || !ciFlag { err = utils.OpenBrowser(constants.ArgoCDLocalURLTLS) if err != nil { - log.Error().Err(err).Msg("") + log.Error().Err(err).Msg("failed to open ArgoCD URL in browser") } } } - // * argocd sync registry and start sync waves executionControl = viper.GetBool("kubefirst-checks.argocd-create-registry") if !executionControl { telemetry.SendEvent(segClient, telemetry.CreateRegistryStarted, "") argocdClient, err := argocdapi.NewForConfig(kcfg.RestConfig) if err != nil { - return err + return fmt.Errorf("failed to create ArgoCD client: %w", err) } - log.Info().Msg("applying the registry application to argocd") + log.Info().Msg("applying the registry application to ArgoCD") registryApplicationObject := argocd.GetArgoCDApplicationObject(gitopsRepoURL, fmt.Sprintf("registry/%s", clusterNameFlag)) err = k3d.RestartDeployment(context.Background(), kcfg.Clientset, "argocd", "argocd-applicationset-controller") if err != nil { - return fmt.Errorf("error in restarting argocd controller %w", err) + return fmt.Errorf("error in restarting ArgoCD controller: %w", err) } err = wait.PollImmediate(5*time.Second, 20*time.Second, func() (bool, error) { _, err := argocdClient.ArgoprojV1alpha1().Applications("argocd").Create(context.Background(), registryApplicationObject, metav1.CreateOptions{}) if err != nil { if errors.Is(err, syscall.ECONNREFUSED) { - return false, nil // retry if we can't connect to it + return false, nil } if apierrors.IsAlreadyExists(err) { - return true, nil // application already exists + return true, nil } - return false, fmt.Errorf("error creating argocd application : %w", err) + return false, fmt.Errorf("error creating ArgoCD application: %w", err) } return true, nil }) if err != nil { - return fmt.Errorf("error creating argocd application : %w", err) + return fmt.Errorf("error creating ArgoCD application: %w", err) } - log.Info().Msg("Argo CD application created successfully") + log.Info().Msg("ArgoCD application created successfully") viper.Set("kubefirst-checks.argocd-create-registry", true) viper.WriteConfig() telemetry.SendEvent(segClient, telemetry.CreateRegistryCompleted, "") progressPrinter.IncrementTracker("installing-argo-cd", 1) } else { - log.Info().Msg("argocd registry create already done, continuing") + log.Info().Msg("ArgoCD registry create already done, continuing") progressPrinter.IncrementTracker("installing-argo-cd", 1) } - // Wait for Vault StatefulSet Pods to transition to Running progressPrinter.AddTracker("configuring-vault", "Configuring Vault", 4) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -1082,19 +954,14 @@ func runK3d(cmd *cobra.Command, args []string) error { 120, ) if err != nil { - log.Error().Msgf("Error finding Vault StatefulSet: %s", err) - return err + return fmt.Errorf("error finding Vault StatefulSet: %w", err) } _, err = k8s.WaitForStatefulSetReady(kcfg.Clientset, vaultStatefulSet, 120, true) if err != nil { - log.Error().Msgf("Error waiting for Vault StatefulSet ready state: %s", err) - return err + return fmt.Errorf("error waiting for Vault StatefulSet ready state: %w", err) } progressPrinter.IncrementTracker("configuring-vault", 1) - // Init and unseal vault - // We need to wait before we try to run any of these commands or there may be - // unexpected timeouts time.Sleep(time.Second * 10) progressPrinter.IncrementTracker("configuring-vault", 1) @@ -1102,33 +969,30 @@ func runK3d(cmd *cobra.Command, args []string) error { if !executionControl { telemetry.SendEvent(segClient, telemetry.VaultInitializationStarted, "") - // Initialize and unseal Vault vaultHandlerPath := "github.com:kubefirst/manifests.git/vault-handler/replicas-1" - // Build and apply manifests yamlData, err := kcfg.KustomizeBuild(vaultHandlerPath) if err != nil { - return err + return fmt.Errorf("failed to build vault handler manifests: %w", err) } output, err := kcfg.SplitYAMLFile(yamlData) if err != nil { - return err + return fmt.Errorf("failed to split YAML file: %w", err) } err = kcfg.ApplyObjects("", output) if err != nil { - return err + return fmt.Errorf("failed to apply vault handler objects: %w", err) } - // Wait for the Job to finish job, err := k8s.ReturnJobObject(kcfg.Clientset, "vault", "vault-handler") if err != nil { - return err + return fmt.Errorf("failed to get vault job object: %w", err) } _, err = k8s.WaitForJobComplete(kcfg.Clientset, job, 240) if err != nil { - msg := fmt.Sprintf("could not run vault unseal job: %s", err) - telemetry.SendEvent(segClient, telemetry.VaultInitializationFailed, msg) - log.Fatal().Msg(msg) + msg := fmt.Errorf("could not run vault unseal job: %w", err) + telemetry.SendEvent(segClient, telemetry.VaultInitializationFailed, msg.Error()) + return msg } viper.Set("kubefirst-checks.vault-initialized", true) @@ -1144,6 +1008,7 @@ func runK3d(cmd *cobra.Command, args []string) error { defer func() { close(minioStopChannel) }() + k8s.OpenPortForwardPodWrapper( kcfg.Clientset, kcfg.RestConfig, @@ -1154,44 +1019,40 @@ func runK3d(cmd *cobra.Command, args []string) error { minioStopChannel, ) - // Initialize minio client object. minioClient, err := minio.New(constants.MinioPortForwardEndpoint, &minio.Options{ Creds: credentials.NewStaticV4(constants.MinioDefaultUsername, constants.MinioDefaultPassword, ""), Secure: false, Region: constants.MinioRegion, }) if err != nil { - log.Info().Msgf("Error creating Minio client: %s", err) + return fmt.Errorf("error creating Minio client: %w", err) } - // define upload object objectName := fmt.Sprintf("terraform/%s/terraform.tfstate", config.GitProvider) filePath := config.K1Dir + fmt.Sprintf("/gitops/%s", objectName) contentType := "xl.meta" bucketName := "kubefirst-state-store" - log.Info().Msgf("BucketName: %s", bucketName) + log.Info().Msgf("BucketName: %q", bucketName) viper.Set("kubefirst.state-store.name", bucketName) viper.Set("kubefirst.state-store.hostname", "minio-console.kubefirst.dev") viper.Set("kubefirst.state-store-creds.access-key-id", constants.MinioDefaultUsername) viper.Set("kubefirst.state-store-creds.secret-access-key-id", constants.MinioDefaultPassword) - // Upload the zip file with FPutObject info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType}) if err != nil { - log.Info().Msgf("Error uploading to Minio bucket: %s", err) + return fmt.Errorf("error uploading to Minio bucket: %w", err) } - log.Printf("Successfully uploaded %s to bucket %s\n", objectName, info.Bucket) + log.Printf("Successfully uploaded %q to bucket %q", objectName, info.Bucket) progressPrinter.IncrementTracker("configuring-vault", 1) - //* configure vault with terraform - //* vault port-forward vaultStopChannel := make(chan struct{}, 1) defer func() { close(vaultStopChannel) }() + k8s.OpenPortForwardPodWrapper( kcfg.Clientset, kcfg.RestConfig, @@ -1202,32 +1063,23 @@ func runK3d(cmd *cobra.Command, args []string) error { vaultStopChannel, ) - // Retrieve root token from init step var vaultRootToken string secData, err := k8s.ReadSecretV2(kcfg.Clientset, "vault", "vault-unseal-secret") if err != nil { - return err + return fmt.Errorf("failed to read vault unseal secret: %w", err) } vaultRootToken = secData["root-token"] - // Parse k3d api endpoint from kubeconfig - // In this case, we need to get the IP of the in-cluster API server to provide to Vault - // to work with Kubernetes auth kubernetesInClusterAPIService, err := k8s.ReadService(config.Kubeconfig, "default", "kubernetes") if err != nil { - log.Error().Msgf("error looking up kubernetes api server service: %s", err) - return err + return fmt.Errorf("error looking up kubernetes api server service: %w", err) } - err = utils.TestEndpointTLS(strings.Replace(k3d.VaultURL, "https://", "", 1)) - if err != nil { - return fmt.Errorf( - "unable to reach vault over https - this is likely due to the mkcert certificate store missing. please install it via `%s -install`", config.MkCertClient, - ) + if err := utils.TestEndpointTLS(strings.Replace(k3d.VaultURL, "https://", "", 1)); err != nil { + return fmt.Errorf("unable to reach vault over https: %w", err) } - // * configure vault with terraform executionControl = viper.GetBool("kubefirst-checks.terraform-apply-vault") if !executionControl { telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, "") @@ -1266,15 +1118,13 @@ func runK3d(cmd *cobra.Command, args []string) error { tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword tfEnvs["TF_VAR_ngrok_authtoken"] = viper.GetString("secrets.atlantis-ngrok-authtoken") - // tfEnvs["TF_LOG"] = "DEBUG" tfEntrypoint := config.GitopsDir + "/terraform/vault" err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) if err != nil { telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, err.Error()) - return err + return fmt.Errorf("failed to execute vault terraform: %w", err) } - log.Info().Msg("vault terraform executed successfully") viper.Set("kubefirst-checks.terraform-apply-vault", true) viper.WriteConfig() @@ -1285,7 +1135,6 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("configuring-vault", 1) } - // * create users progressPrinter.AddTracker("creating-users", "Creating users", 1) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) @@ -1309,10 +1158,9 @@ func runK3d(cmd *cobra.Command, args []string) error { err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) if err != nil { telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyStarted, err.Error()) - return err + return fmt.Errorf("failed to apply users terraform: %w", err) } log.Info().Msg("executed users terraform successfully") - // progressPrinter.IncrementTracker("step-users", 1) viper.Set("kubefirst-checks.terraform-apply-users", true) viper.WriteConfig() telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyCompleted, "") @@ -1322,66 +1170,50 @@ func runK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("creating-users", 1) } - // PostRun string replacement progressPrinter.AddTracker("wrapping-up", "Wrapping up", 2) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - err = k3d.PostRunPrepareGitopsRepository(clusterNameFlag, - config.GitopsDir, - &gitopsDirectoryTokens, - ) + err = k3d.PostRunPrepareGitopsRepository(clusterNameFlag, config.GitopsDir, &gitopsDirectoryTokens) if err != nil { - log.Info().Msgf("Error detokenize post run: %s", err) + return fmt.Errorf("error detokenizing post run: %w", err) } gitopsRepo, err := git.PlainOpen(config.GitopsDir) if err != nil { - log.Info().Msgf("error opening repo at: %s", config.GitopsDir) + return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) } - // check if file exists before rename _, err = os.Stat(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider)) if err == nil { err = os.Rename(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider), fmt.Sprintf("%s/terraform/%s/remote-backend.tf", config.GitopsDir, config.GitProvider)) if err != nil { - return err + return fmt.Errorf("failed to rename remote-backend.md to remote-backend.tf: %w", err) } } viper.Set("kubefirst-checks.post-detokenize", true) viper.WriteConfig() - // Final gitops repo commit and push err = gitClient.Commit(gitopsRepo, "committing initial detokenized gitops-template repo content post run") if err != nil { - return err + return fmt.Errorf("failed to commit initial detokenized gitops-template repo content: %w", err) } err = gitopsRepo.Push(&git.PushOptions{ RemoteName: config.GitProvider, Auth: httpAuth, }) if err != nil { - log.Info().Msgf("Error pushing repo: %s", err) + return fmt.Errorf("failed to push initial detokenized gitops-template repo content: %w", err) } progressPrinter.IncrementTracker("wrapping-up", 1) - // Wait for console Deployment Pods to transition to Running - argoDeployment, err := k8s.ReturnDeploymentObject( - kcfg.Clientset, - "app.kubernetes.io/instance", - "argo", - "argo", - 1200, - ) + argoDeployment, err := k8s.ReturnDeploymentObject(kcfg.Clientset, "app.kubernetes.io/instance", "argo", "argo", 1200) if err != nil { - log.Error().Msgf("Error finding argo workflows Deployment: %s", err) - return err + return fmt.Errorf("error finding Argo Workflows Deployment: %w", err) } _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, argoDeployment, 120) if err != nil { - log.Error().Msgf("Error waiting for argo workflows Deployment ready state: %s", err) - return err + return fmt.Errorf("error waiting for Argo Workflows Deployment ready state: %w", err) } - // Set flags used to track status of active options utils.SetClusterStatusFlags(k3d.CloudProvider, config.GitProvider) cluster := utilities.CreateClusterRecordFromRaw(useTelemetryFlag, cGitOwner, cGitUser, cGitToken, cGitlabOwnerGroupID, gitopsTemplateURLFlag, gitopsTemplateBranchFlag, catalogApps) @@ -1392,7 +1224,7 @@ func runK3d(cmd *cobra.Command, args []string) error { viper.Set("kubefirst.setup-complete", false) viper.Set("kubefirst-checks.cluster-install-complete", false) viper.WriteConfig() - return err + return fmt.Errorf("failed to export cluster object: %w", err) } else { kubefirstDeployment, err := k8s.ReturnDeploymentObject( kcfg.Clientset, @@ -1402,29 +1234,26 @@ func runK3d(cmd *cobra.Command, args []string) error { 600, ) if err != nil { - log.Error().Msgf("Error finding kubefirst Deployment: %s", err) - return err + return fmt.Errorf("error finding kubefirst Deployment: %w", err) } _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, kubefirstDeployment, 120) if err != nil { - log.Error().Msgf("Error waiting for kubefirst Deployment ready state: %s", err) - return err + return fmt.Errorf("error waiting for kubefirst Deployment ready state: %w", err) } progressPrinter.IncrementTracker("wrapping-up", 1) err = utils.OpenBrowser(constants.KubefirstConsoleLocalURLTLS) if err != nil { - log.Error().Err(err).Msg("") + log.Error().Err(err).Msg("failed to open Kubefirst console in browser") } - // Mark cluster install as complete telemetry.SendEvent(segClient, telemetry.ClusterInstallCompleted, "") viper.Set("kubefirst-checks.cluster-install-complete", true) viper.WriteConfig() log.Info().Msg("kubefirst installation complete") - log.Info().Msg("welcome to your new kubefirst platform running in K3d") - time.Sleep(time.Second * 1) // allows progress bars to finish + log.Info().Msg("welcome to your new Kubefirst platform running in K3D") + time.Sleep(1 * time.Second) reports.LocalHandoffScreenV2(viper.GetString("components.argocd.password"), clusterNameFlag, gitDestDescriptor, cGitOwner, config, ciFlag) diff --git a/cmd/k3d/destroy.go b/cmd/k3d/destroy.go index 55c2ab614..8a2e3175a 100644 --- a/cmd/k3d/destroy.go +++ b/cmd/k3d/destroy.go @@ -14,23 +14,21 @@ import ( "time" constants "github.com/konstructio/kubefirst-api/pkg/constants" - utils "github.com/konstructio/kubefirst-api/pkg/utils" - gitlab "github.com/konstructio/kubefirst-api/pkg/gitlab" "github.com/konstructio/kubefirst-api/pkg/k3d" "github.com/konstructio/kubefirst-api/pkg/k8s" "github.com/konstructio/kubefirst-api/pkg/progressPrinter" "github.com/konstructio/kubefirst-api/pkg/terraform" + utils "github.com/konstructio/kubefirst-api/pkg/utils" "github.com/konstructio/kubefirst/internal/progress" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" ) -func destroyK3d(cmd *cobra.Command, args []string) error { +func destroyK3d(_ *cobra.Command, _ []string) error { utils.DisplayLogHints() - // Determine if there are active installs gitProvider := viper.GetString("flags.git-provider") clusterName := viper.GetString("flags.cluster-name") gitProtocol := viper.GetString("flags.git-protocol") @@ -40,11 +38,8 @@ func destroyK3d(cmd *cobra.Command, args []string) error { progress.Progress.Quit() } - // Check for existing port forwards before continuing - err := k8s.CheckForExistingPortForwards(9000) - if err != nil { - log.Error().Msgf("%s - this port is required to tear down your kubefirst environment - please close any existing port forwards before continuing", err.Error()) - return fmt.Errorf("%s (maybe the handoff screen is still open in another terminal) - this port is required to tear down your kubefirst environment - please close any existing port forwards before continuing", err.Error()) + if err := k8s.CheckForExistingPortForwards(9000); err != nil { + return fmt.Errorf("%w - this port is required to tear down your kubefirst environment - please close any existing port forwards before continuing", err) } progressPrinter.AddTracker("preflight-checks", "Running preflight checks", 1) @@ -55,7 +50,6 @@ func destroyK3d(cmd *cobra.Command, args []string) error { atlantisWebhookURL := fmt.Sprintf("%s/events", viper.GetString("ngrok.host")) - // Switch based on git provider, set params var cGitOwner, cGitToken string switch gitProvider { case "github": @@ -65,10 +59,9 @@ func destroyK3d(cmd *cobra.Command, args []string) error { cGitOwner = viper.GetString("flags.gitlab-owner") cGitToken = os.Getenv("GITLAB_TOKEN") default: - log.Panic().Msgf("invalid git provider option") + return fmt.Errorf("invalid git provider option: %q", gitProvider) } - // Instantiate K3d config config := k3d.GetConfig(clusterName, gitProvider, cGitOwner, gitProtocol) switch gitProvider { case "github": @@ -77,12 +70,8 @@ func destroyK3d(cmd *cobra.Command, args []string) error { config.GitlabToken = cGitToken } - log.Info().Msg("destroying kubefirst platform running in k3d") - kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) - // todo improve these checks, make them standard for - // both create and destroy if len(cGitToken) == 0 { return fmt.Errorf( "please set a %s_TOKEN environment variable to continue\n https://docs.kubefirst.io/kubefirst/%s/install.html#step-3-kubefirst-init", @@ -91,24 +80,15 @@ func destroyK3d(cmd *cobra.Command, args []string) error { } if viper.GetBool("kubefirst-checks.post-detokenize") { - // Temporary func to allow destroy - err = k3d.ResolveMinioLocal(fmt.Sprintf("%s/terraform", config.GitopsDir)) - if err != nil { - log.Fatal().Msgf("error preloading files for terraform destroy: %s", err) + if err := k3d.ResolveMinioLocal(fmt.Sprintf("%s/terraform", config.GitopsDir)); err != nil { + return fmt.Errorf("unable to preload files for terraform destroy: %w", err) } minioStopChannel := make(chan struct{}, 1) defer func() { close(minioStopChannel) }() - k8s.OpenPortForwardPodWrapper( - kcfg.Clientset, - kcfg.RestConfig, - "minio", - "minio", - 9000, - 9000, - minioStopChannel, - ) + + k8s.OpenPortForwardPodWrapper(kcfg.Clientset, kcfg.RestConfig, "minio", "minio", 9000, 9000, minioStopChannel) } progressPrinter.IncrementTracker("preflight-checks", 1) @@ -119,22 +99,20 @@ func destroyK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("destroying github resources with terraform") tfEntrypoint := config.GitopsDir + "/terraform/github" - tfEnvs := map[string]string{} - - tfEnvs["GITHUB_TOKEN"] = cGitToken - tfEnvs["GITHUB_OWNER"] = cGitOwner - tfEnvs["TF_VAR_atlantis_repo_webhook_secret"] = viper.GetString("secrets.atlantis-webhook") - tfEnvs["TF_VAR_atlantis_repo_webhook_url"] = atlantisWebhookURL - tfEnvs["TF_VAR_kbot_ssh_public_key"] = viper.GetString("kbot.public-key") - tfEnvs["AWS_ACCESS_KEY_ID"] = constants.MinioDefaultUsername - tfEnvs["AWS_SECRET_ACCESS_KEY"] = constants.MinioDefaultPassword - tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername - tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword - - err := terraform.InitDestroyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - log.Printf("error executing terraform destroy %s", tfEntrypoint) - return err + tfEnvs := map[string]string{ + "GITHUB_TOKEN": cGitToken, + "GITHUB_OWNER": cGitOwner, + "TF_VAR_atlantis_repo_webhook_secret": viper.GetString("secrets.atlantis-webhook"), + "TF_VAR_atlantis_repo_webhook_url": atlantisWebhookURL, + "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), + "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, + "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, + "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, + "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, + } + + if err := terraform.InitDestroyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs); err != nil { + return fmt.Errorf("unable to execute terraform destroy: %w", err) } viper.Set("kubefirst-checks.terraform-apply-github", false) viper.WriteConfig() @@ -146,52 +124,48 @@ func destroyK3d(cmd *cobra.Command, args []string) error { log.Info().Msg("destroying gitlab resources with terraform") gitlabClient, err := gitlab.NewGitLabClient(cGitToken, cGitOwner) if err != nil { - return err + return fmt.Errorf("unable to create gitlab client: %w", err) } - // Before removing Terraform resources, remove any container registry repositories - // since failing to remove them beforehand will result in an apply failure projectsForDeletion := []string{"gitops", "metaphor"} for _, project := range projectsForDeletion { projectExists, err := gitlabClient.CheckProjectExists(project) if err != nil { - log.Fatal().Msgf("could not check for existence of project %s: %s", project, err) + return fmt.Errorf("unable to check existence of project %q: %w", project, err) } if projectExists { - log.Info().Msgf("checking project %s for container registries...", project) + log.Info().Msgf("checking project %q for container registries...", project) crr, err := gitlabClient.GetProjectContainerRegistryRepositories(project) if err != nil { - log.Fatal().Msgf("could not retrieve container registry repositories: %s", err) + return fmt.Errorf("unable to retrieve container registry repositories: %w", err) } if len(crr) > 0 { for _, cr := range crr { - err := gitlabClient.DeleteContainerRegistryRepository(project, cr.ID) - if err != nil { - log.Fatal().Msgf("error deleting container registry repository: %s", err) + if err := gitlabClient.DeleteContainerRegistryRepository(project, cr.ID); err != nil { + return fmt.Errorf("unable to delete container registry repository %q: %w", cr.Path, err) } } } else { - log.Info().Msgf("project %s does not have any container registries, skipping", project) + log.Info().Msgf("project %q does not have any container registries, skipping", project) } } else { - log.Info().Msgf("project %s does not exist, skipping", project) + log.Info().Msgf("project %q does not exist, skipping", project) } } tfEntrypoint := config.GitopsDir + "/terraform/gitlab" - tfEnvs := map[string]string{} - - tfEnvs["GITLAB_TOKEN"] = cGitToken - tfEnvs["GITLAB_OWNER"] = cGitOwner - tfEnvs["TF_VAR_atlantis_repo_webhook_secret"] = viper.GetString("secrets.atlantis-webhook") - tfEnvs["TF_VAR_atlantis_repo_webhook_url"] = atlantisWebhookURL - tfEnvs["TF_VAR_owner_group_id"] = strconv.Itoa(gitlabClient.ParentGroupID) + tfEnvs := map[string]string{ + "GITLAB_TOKEN": cGitToken, + "GITLAB_OWNER": cGitOwner, + "TF_VAR_atlantis_repo_webhook_secret": viper.GetString("secrets.atlantis-webhook"), + "TF_VAR_atlantis_repo_webhook_url": atlantisWebhookURL, + "TF_VAR_owner_group_id": strconv.Itoa(gitlabClient.ParentGroupID), + } - err = terraform.InitDestroyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - log.Printf("error executing terraform destroy %s", tfEntrypoint) - return err + if err := terraform.InitDestroyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs); err != nil { + return fmt.Errorf("unable to execute terraform destroy: %w", err) } + viper.Set("kubefirst-checks.terraform-apply-gitlab", false) viper.WriteConfig() log.Info().Msg("gitlab resources terraform destroyed") @@ -202,9 +176,8 @@ func destroyK3d(cmd *cobra.Command, args []string) error { if viper.GetBool("kubefirst-checks.create-k3d-cluster") || viper.GetBool("kubefirst-checks.create-k3d-cluster-failed") { log.Info().Msg("destroying k3d resources with terraform") - err := k3d.DeleteK3dCluster(clusterName, config.K1Dir, config.K3dClient) - if err != nil { - return err + if err := k3d.DeleteK3dCluster(clusterName, config.K1Dir, config.K3dClient); err != nil { + return fmt.Errorf("unable to delete k3d cluster %q: %w", clusterName, err) } viper.Set("kubefirst-checks.create-k3d-cluster", false) @@ -213,15 +186,13 @@ func destroyK3d(cmd *cobra.Command, args []string) error { progressPrinter.IncrementTracker("platform-destroy", 1) } - // remove ssh key provided one was created if viper.GetString("kbot.gitlab-user-based-ssh-key-title") != "" { gitlabClient, err := gitlab.NewGitLabClient(cGitToken, cGitOwner) if err != nil { - return err + return fmt.Errorf("unable to create gitlab client for deleting ssh key: %w", err) } log.Info().Msg("attempting to delete managed ssh key...") - err = gitlabClient.DeleteUserSSHKey(viper.GetString("kbot.gitlab-user-based-ssh-key-title")) - if err != nil { + if err := gitlabClient.DeleteUserSSHKey(viper.GetString("kbot.gitlab-user-based-ssh-key-title")); err != nil { log.Warn().Msg(err.Error()) } } @@ -230,9 +201,8 @@ func destroyK3d(cmd *cobra.Command, args []string) error { if !viper.GetBool(fmt.Sprintf("kubefirst-checks.terraform-apply-%s", gitProvider)) && !viper.GetBool("kubefirst-checks.create-k3d-cluster") { log.Info().Msg("removing previous platform content") - err := utils.ResetK1Dir(config.K1Dir) - if err != nil { - return err + if err := utils.ResetK1Dir(config.K1Dir); err != nil { + return fmt.Errorf("unable to remove previous platform content: %w", err) } log.Info().Msg("previous platform content removed") @@ -248,13 +218,12 @@ func destroyK3d(cmd *cobra.Command, args []string) error { } if _, err := os.Stat(config.K1Dir + "/kubeconfig"); !os.IsNotExist(err) { - err = os.Remove(config.K1Dir + "/kubeconfig") - if err != nil { - return fmt.Errorf("unable to delete %q folder, error: %w", config.K1Dir+"/kubeconfig", err) + if err := os.Remove(config.K1Dir + "/kubeconfig"); err != nil { + return fmt.Errorf("unable to delete %q: %w", config.K1Dir+"/kubeconfig", err) } } - time.Sleep(time.Millisecond * 200) // allows progress bars to finish - fmt.Printf("Your kubefirst platform running in %s has been destroyed.", k3d.CloudProvider) + time.Sleep(200 * time.Millisecond) + fmt.Printf("Your kubefirst platform running in %q has been destroyed.", k3d.CloudProvider) progress.Progress.Quit() return nil diff --git a/cmd/k3d/mkcert.go b/cmd/k3d/mkcert.go index 4c7851a53..8305fc54a 100644 --- a/cmd/k3d/mkcert.go +++ b/cmd/k3d/mkcert.go @@ -19,17 +19,17 @@ import ( ) // mkCert creates a single certificate for a host for k3d -func mkCert(cmd *cobra.Command, args []string) error { +func mkCert(cmd *cobra.Command, _ []string) error { utils.DisplayLogHints() appNameFlag, err := cmd.Flags().GetString("application") if err != nil { - return err + return fmt.Errorf("failed to get application flag: %w", err) } appNamespaceFlag, err := cmd.Flags().GetString("namespace") if err != nil { - return err + return fmt.Errorf("failed to get namespace flag: %w", err) } flags := utils.GetClusterStatusFlags() diff --git a/cmd/k3d/root-credentials.go b/cmd/k3d/root-credentials.go index ca629a223..6c3f9b2ea 100644 --- a/cmd/k3d/root-credentials.go +++ b/cmd/k3d/root-credentials.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package k3d import ( + "errors" "fmt" "github.com/konstructio/kubefirst-api/pkg/credentials" @@ -17,7 +18,7 @@ import ( "github.com/spf13/viper" ) -func getK3dRootCredentials(cmd *cobra.Command, args []string) error { +func getK3dRootCredentials(cmd *cobra.Command, _ []string) error { domainName := k3d.DomainName clusterName := viper.GetString("flags.cluster-name") gitProvider := viper.GetString("flags.git-provider") @@ -27,15 +28,15 @@ func getK3dRootCredentials(cmd *cobra.Command, args []string) error { // Parse flags a, err := cmd.Flags().GetBool("argocd") if err != nil { - return err + return fmt.Errorf("failed to get ArgoCD flag: %w", err) } k, err := cmd.Flags().GetBool("kbot") if err != nil { - return err + return fmt.Errorf("failed to get kbot flag: %w", err) } v, err := cmd.Flags().GetBool("vault") if err != nil { - return err + return fmt.Errorf("failed to get vault flag: %w", err) } opts := credentials.CredentialOptions{ CopyArgoCDPasswordToClipboard: a, @@ -46,25 +47,23 @@ func getK3dRootCredentials(cmd *cobra.Command, args []string) error { // Determine if there are eligible installs _, err = credentials.EvalAuth(k3d.CloudProvider, gitProvider) if err != nil { - return err + return fmt.Errorf("failed to evaluate auth: %w", err) } // Determine if the Kubernetes cluster is available if !viper.GetBool("kubefirst-checks.create-k3d-cluster") { - return fmt.Errorf("it looks like a kubernetes cluster has not been created yet - try again") + return errors.New("it looks like a Kubernetes cluster has not been created yet - try again") } // Instantiate kubernetes client config := k3d.GetConfig(clusterName, gitProvider, gitOwner, gitProtocol) - kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) err = credentials.ParseAuthData(kcfg.Clientset, k3d.CloudProvider, gitProvider, domainName, &opts) if err != nil { - return err + return fmt.Errorf("failed to parse auth data: %w", err) } progress.Progress.Quit() - return nil } diff --git a/cmd/k3d/vault.go b/cmd/k3d/vault.go index 8327a9913..485e49bbd 100644 --- a/cmd/k3d/vault.go +++ b/cmd/k3d/vault.go @@ -13,7 +13,7 @@ import ( "strings" "time" - vaultapi "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/api" "github.com/konstructio/kubefirst-api/pkg/k3d" "github.com/konstructio/kubefirst-api/pkg/k8s" utils "github.com/konstructio/kubefirst-api/pkg/utils" @@ -26,18 +26,17 @@ import ( const ( // Name for the Secret that gets created that contains root auth data - vaultSecretName string = "vault-unseal-secret" + vaultSecretName = "vault-unseal-secret" // Namespace that Vault runs in - vaultNamespace string = "vault" + vaultNamespace = "vault" // number of secret threshold Vault unseal secretThreshold = 3 ) -// unsealVault will attempt to unseal vaule again if it is currently unsealed func unsealVault(cmd *cobra.Command, args []string) error { flags := utils.GetClusterStatusFlags() if !flags.SetupComplete { - return fmt.Errorf("there doesn't appear to be an active k3d cluster") + return fmt.Errorf("failed to unseal vault: there doesn't appear to be an active k3d cluster") } config := k3d.GetConfig( viper.GetString("flags.cluster-name"), @@ -47,70 +46,63 @@ func unsealVault(cmd *cobra.Command, args []string) error { ) kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) - // Vault api client - vaultClient, err := vaultapi.NewClient(&vaultapi.Config{ + vaultClient, err := api.NewClient(&api.Config{ Address: "https://vault.kubefirst.dev", }) if err != nil { - return err + return fmt.Errorf("failed to create vault client: %w", err) } - vaultClient.CloneConfig().ConfigureTLS(&vaultapi.TLSConfig{ + vaultClient.CloneConfig().ConfigureTLS(&api.TLSConfig{ Insecure: true, }) - // Determine vault health health, err := vaultClient.Sys().Health() if err != nil { - return err + return fmt.Errorf("failed to check vault health: %w", err) } - switch health.Sealed { - case true: + if health.Sealed { node := "vault-0" existingInitResponse, err := parseExistingVaultInitSecret(kcfg.Clientset) if err != nil { - return err + return fmt.Errorf("failed to parse existing vault init secret: %w", err) } sealStatusTracking := 0 for i, shard := range existingInitResponse.Keys { if i < secretThreshold { - log.Info().Msgf("passing unseal shard %v to %s", i+1, node) + log.Info().Msgf("passing unseal shard %d to %q", i+1, node) deadline := time.Now().Add(60 * time.Second) ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel() - // Try 5 times to pass unseal shard - for i := 0; i < 5; i++ { + for j := 0; j < 5; j++ { _, err := vaultClient.Sys().UnsealWithContext(ctx, shard) if err != nil { if errors.Is(err, context.DeadlineExceeded) { continue } - } - if i == 5 { - return fmt.Errorf("error passing unseal shard %v to %s: %w", i+1, node, err) + return fmt.Errorf("error passing unseal shard %d to %q: %w", i+1, node, err) } } - // Wait for key acceptance - for i := 0; i < 10; i++ { + for j := 0; j < 10; j++ { sealStatus, err := vaultClient.Sys().SealStatus() if err != nil { - return fmt.Errorf("error retrieving health of %s: %s", node, err) + return fmt.Errorf("error retrieving health of %q: %w", node, err) } if sealStatus.Progress > sealStatusTracking || !sealStatus.Sealed { - log.Info().Msgf("shard accepted") + log.Info().Msg("shard accepted") sealStatusTracking++ break } - log.Info().Msgf("waiting for node %s to accept unseal shard", node) - time.Sleep(time.Second * 6) + log.Info().Msgf("waiting for node %q to accept unseal shard", node) + time.Sleep(6 * time.Second) } } } - fmt.Printf("vault unsealed\n") - case false: - return fmt.Errorf("vault is already unsealed") + log.Printf("vault unsealed") + } else { + return fmt.Errorf("failed to unseal vault: vault is already unsealed") } progress.Progress.Quit() @@ -118,16 +110,12 @@ func unsealVault(cmd *cobra.Command, args []string) error { return nil } -// parseExistingVaultInitSecret returns the value of a vault initialization secret if it exists -func parseExistingVaultInitSecret(clientset *kubernetes.Clientset) (*vaultapi.InitResponse, error) { - // If vault has already been initialized, the response is formatted to contain the value - // of the initialization secret +func parseExistingVaultInitSecret(clientset *kubernetes.Clientset) (*api.InitResponse, error) { secret, err := k8s.ReadSecretV2(clientset, vaultNamespace, vaultSecretName) if err != nil { - return &vaultapi.InitResponse{}, err + return nil, fmt.Errorf("failed to read secret: %w", err) } - // Add root-unseal-key entries to slice var rkSlice []string for key, value := range secret { if strings.Contains(key, "root-unseal-key-") { @@ -135,7 +123,7 @@ func parseExistingVaultInitSecret(clientset *kubernetes.Clientset) (*vaultapi.In } } - existingInitResponse := &vaultapi.InitResponse{ + existingInitResponse := &api.InitResponse{ Keys: rkSlice, RootToken: secret["root-token"], } diff --git a/cmd/k3s/command.go b/cmd/k3s/command.go index 339fc65da..c6d2d0ff4 100644 --- a/cmd/k3s/command.go +++ b/cmd/k3s/command.go @@ -92,15 +92,15 @@ func Create() *cobra.Command { createCmd.Flags().StringSliceVar(&k3sServersPrivateIpsFlag, "servers-private-ips", []string{}, "the list of k3s (servers) private ip x.x.x.x,y.y.y.y comma separated (required)") createCmd.MarkFlagRequired("servers-private-ips") createCmd.Flags().StringSliceVar(&k3sServersPublicIpsFlag, "servers-public-ips", []string{}, "the list of k3s (servers) public ip x.x.x.x,y.y.y.y comma separated (required)") - createCmd.Flags().StringSliceVar(&K3sServersArgsFlags, "servers-args", []string{"--disable traefik", "--write-kubeconfig-mode 644"}, "list of k3s extras args to add to the k3s server installation,comma separated in between quote, if --servers-publis-ips --tls-san is added to default --servers-args") + createCmd.Flags().StringSliceVar(&K3sServersArgsFlags, "servers-args", []string{"--disable traefik", "--write-kubeconfig-mode 644"}, "list of k3s extras args to add to the k3s server installation,comma separated in between quote, if --servers-public-ips --tls-san is added to default --servers-args") createCmd.Flags().StringVar(&k3sSshUserflag, "ssh-user", "root", "the user used to log into servers with ssh connection") createCmd.Flags().StringVar(&k3sSshPrivateKeyflag, "ssh-privatekey", "", "the private key used to log into servers with ssh connection") createCmd.MarkFlagRequired("ssh-privatekey") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the cloudProvider DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %q", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %q", supportedGitProtocolOverride)) createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") diff --git a/cmd/k3s/create.go b/cmd/k3s/create.go index a76dd5bed..c1e87ae4f 100644 --- a/cmd/k3s/create.go +++ b/cmd/k3s/create.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package k3s import ( + "errors" "fmt" "os" "strings" @@ -31,27 +32,30 @@ func createK3s(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "k3s") if err != nil { progress.Error(err.Error()) - log.Fatal().Msgf("error collecting flags: %s", err) - return nil + return fmt.Errorf("error collecting flags: %w", err) } progress.DisplayLogHints(20) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if err != nil { + return fmt.Errorf("validation of catalog apps failed: %w", err) + } + if !isValid { - return err + return errors.New("catalog validation failed") } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("provided flags validation failed: %w", err) } // If cluster setup is complete, return clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") if clusterSetupComplete { - err = fmt.Errorf("this cluster install process has already completed successfully") + err = errors.New("this cluster install process has already completed successfully") progress.Error(err.Error()) return nil } @@ -61,7 +65,7 @@ func createK3s(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("git credentials validation failed: %w", err) } executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider)) @@ -79,11 +83,14 @@ func createK3s(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("initialization of git provider failed: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) - viper.WriteConfig() + + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("writing config failed: %w", err) + } k3dClusterCreationComplete := viper.GetBool("launch.deployed") isK1Debug := strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" @@ -95,6 +102,7 @@ func createK3s(cmd *cobra.Command, args []string) error { err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("app availability check failed: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) @@ -110,16 +118,14 @@ func ValidateProvidedFlags(gitProvider string) error { key, err := internalssh.GetHostKey("github.com") if err != nil { return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") diff --git a/cmd/launch.go b/cmd/launch.go index c6aca15e8..2c1f10a78 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -22,8 +22,8 @@ var additionalHelmFlags []string func LaunchCommand() *cobra.Command { launchCommand := &cobra.Command{ Use: "launch", - Short: "create a local k3d cluster and launch the kubefirst console and api in it", - Long: "create a local k3d cluster and launch the kubefirst console and api in it", + Short: "create a local k3d cluster and launch the Kubefirst console and API in it", + Long: "create a local k3d cluster and launch the Kubefirst console and API in it", } // wire up new commands @@ -38,8 +38,7 @@ func launchUp() *cobra.Command { Use: "up", Short: "launch new console and api instance", TraverseChildren: true, - // PreRun: common.CheckDocker, // TODO: check runtimes when we can support more runtimes - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { launch.Up(additionalHelmFlags, false, true) }, } @@ -55,7 +54,7 @@ func launchDown() *cobra.Command { Use: "down", Short: "remove console and api instance", TraverseChildren: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { launch.Down(false) }, } @@ -67,7 +66,7 @@ func launchDown() *cobra.Command { func launchCluster() *cobra.Command { launchClusterCmd := &cobra.Command{ Use: "cluster", - Short: "interact with clusters created by the kubefirst console", + Short: "interact with clusters created by the Kubefirst console", TraverseChildren: true, } @@ -80,10 +79,9 @@ func launchCluster() *cobra.Command { func launchListClusters() *cobra.Command { launchListClustersCmd := &cobra.Command{ Use: "list", - Short: "list clusters created by the kubefirst console", + Short: "list clusters created by the Kubefirst console", TraverseChildren: true, - // PreRun: common.CheckDocker, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { launch.ListClusters() }, } @@ -95,9 +93,8 @@ func launchListClusters() *cobra.Command { func launchDeleteCluster() *cobra.Command { launchDeleteClusterCmd := &cobra.Command{ Use: "delete", - Short: "delete a cluster created by the kubefirst console", + Short: "delete a cluster created by the Kubefirst console", TraverseChildren: true, - // PreRun: common.CheckDocker, Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("you must provide a cluster name as the first argument") diff --git a/cmd/letsencrypt.go b/cmd/letsencrypt.go index 062dc4d53..ea21f05e6 100644 --- a/cmd/letsencrypt.go +++ b/cmd/letsencrypt.go @@ -7,7 +7,7 @@ See the LICENSE file for more details. package cmd import ( - "fmt" + "log" "github.com/konstructio/kubefirst-api/pkg/certificates" "github.com/konstructio/kubefirst/internal/progress" @@ -20,8 +20,8 @@ var domainNameFlag string func LetsEncryptCommand() *cobra.Command { letsEncryptCommand := &cobra.Command{ Use: "letsencrypt", - Short: "interact with letsencrypt certificates for a domain", - Long: "interact with letsencrypt certificates for a domain", + Short: "interact with LetsEncrypt certificates for a domain", + Long: "interact with LetsEncrypt certificates for a domain", } // wire up new commands @@ -33,12 +33,11 @@ func LetsEncryptCommand() *cobra.Command { func status() *cobra.Command { statusCmd := &cobra.Command{ Use: "status", - Short: "check the usage statistics for a letsencrypt certificate", + Short: "check the usage statistics for a LetsEncrypt certificate", TraverseChildren: true, Run: func(cmd *cobra.Command, args []string) { - err := certificates.CheckCertificateUsage(domainNameFlag) - if err != nil { - fmt.Println(err) + if err := certificates.CheckCertificateUsage(domainNameFlag); err != nil { + log.Printf("failed to check certificate usage for domain %q: %w", domainNameFlag, err) } progress.Progress.Quit() }, diff --git a/cmd/logs.go b/cmd/logs.go index d52f5ad28..24355df02 100755 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -21,7 +21,7 @@ var logsCmd = &cobra.Command{ Use: "logs", Short: "kubefirst real time logs", Long: `kubefirst real time logs`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { provisionLogs.InitializeProvisionLogsTerminal() go func() { @@ -29,6 +29,7 @@ var logsCmd = &cobra.Command{ if err != nil { fmt.Printf("Error tailing log file: %v\n", err) progress.Progress.Quit() + return } for line := range t.Lines { @@ -36,7 +37,9 @@ var logsCmd = &cobra.Command{ } }() - provisionLogs.ProvisionLogs.Run() + if _, err := provisionLogs.ProvisionLogs.Run(); err != nil { + return fmt.Errorf("failed to run provision logs: %w", err) + } return nil }, diff --git a/cmd/reset.go b/cmd/reset.go index 658cddc3a..7db72b6fc 100755 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -40,34 +40,33 @@ var resetCmd = &cobra.Command{ if v == "" { log.Info().Msg("checks map is empty, continuing") } else { - return fmt.Errorf("unable to determine contents of kubefirst-checks") + return fmt.Errorf("unable to determine contents of kubefirst-checks: unexpected type %T", v) } case map[string]interface{}: checks, err := parseConfigEntryKubefirstChecks(v) if err != nil { - log.Error().Msgf("error: %s - resetting directory without checks", err) + log.Error().Msgf("error occurred during check parsing: %s - resetting directory without checks", err) } // If destroy hasn't been run yet, reset should fail to avoid orphaned resources switch { case checks[fmt.Sprintf("terraform-apply-%s", gitProvider)]: return fmt.Errorf( - "it looks like there's an active %s resource deployment - please run %s destroy before continuing", - gitProvider, - cloudProvider, + "it looks like there's an active %s resource deployment - please run `%s destroy` before continuing", + gitProvider, cloudProvider, ) case checks[fmt.Sprintf("terraform-apply-%s", cloudProvider)]: return fmt.Errorf( "it looks like there's an active %s installation - please run `%s destroy` before continuing", - cloudProvider, - cloudProvider, + cloudProvider, cloudProvider, ) } default: return fmt.Errorf("unable to determine contents of kubefirst-checks: unexpected type %T", v) - } - runReset() + if err := runReset(); err != nil { + return fmt.Errorf("error during reset operation: %w", err) + } return nil }, } @@ -105,18 +104,17 @@ func runReset() error { homePath, err := os.UserHomeDir() if err != nil { - return err + return fmt.Errorf("unable to get user home directory: %w", err) } k1Dir := fmt.Sprintf("%s/.k1", homePath) - err = utils.ResetK1Dir(k1Dir) - if err != nil { - return err + if err := utils.ResetK1Dir(k1Dir); err != nil { + return fmt.Errorf("error resetting k1 directory: %w", err) } log.Info().Msg("previous platform content removed") progressPrinter.IncrementTracker("removing-platform-content", 1) - log.Info().Msg("resetting `$HOME/.kubefirst` config") + log.Info().Msg("resetting $HOME/.kubefirst config") viper.Set("argocd", "") viper.Set("github", "") viper.Set("gitlab", "") @@ -125,12 +123,13 @@ func runReset() error { viper.Set("kubefirst-checks", "") viper.Set("kubefirst", "") viper.Set("secrets", "") - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("error writing viper config: %w", err) + } if _, err := os.Stat(k1Dir + "/kubeconfig"); !os.IsNotExist(err) { - err = os.Remove(k1Dir + "/kubeconfig") - if err != nil { - return fmt.Errorf("unable to delete %q folder, error: %s", k1Dir+"/kubeconfig", err) + if err := os.Remove(k1Dir + "/kubeconfig"); err != nil { + return fmt.Errorf("unable to delete %q folder, error: %w", k1Dir+"/kubeconfig", err) } } diff --git a/cmd/root.go b/cmd/root.go index 2b2e76484..36411b4e7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -10,14 +10,13 @@ import ( "fmt" "github.com/konstructio/kubefirst-api/pkg/configs" + "github.com/konstructio/kubefirst-api/pkg/progressPrinter" "github.com/konstructio/kubefirst/cmd/aws" "github.com/konstructio/kubefirst/cmd/civo" "github.com/konstructio/kubefirst/cmd/digitalocean" "github.com/konstructio/kubefirst/cmd/k3d" "github.com/konstructio/kubefirst/internal/common" "github.com/konstructio/kubefirst/internal/progress" - - "github.com/konstructio/kubefirst-api/pkg/progressPrinter" "github.com/spf13/cobra" ) @@ -26,13 +25,13 @@ var rootCmd = &cobra.Command{ Use: "kubefirst", Short: "kubefirst management cluster installer base command", Long: `kubefirst management cluster installer provisions an - open source application delivery platform in under an hour. + open source application delivery platform in under an hour. checkout the docs at docs.kubefirst.io.`, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // wire viper config for flags for all commands return configs.InitializeViperConfig(cmd) }, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { fmt.Println("To learn more about kubefirst, run:") fmt.Println(" kubefirst help") progress.Progress.Quit() @@ -47,9 +46,10 @@ func Execute() { // Before removing next line, please read ticket above. common.CheckForVersionUpdate() progressPrinter.GetInstance() - err := rootCmd.Execute() - if err != nil { - fmt.Printf("\nIf a detailed error message was available, please make the necessary corrections before retrying.\nYou can re-run the last command to try the operation again.\n\n") + if err := rootCmd.Execute(); err != nil { + fmt.Println("Error occurred during command execution:", err) + fmt.Println("If a detailed error message was available, please make the necessary corrections before retrying.") + fmt.Println("You can re-run the last command to try the operation again.") progress.Progress.Quit() } } diff --git a/cmd/terraform.go b/cmd/terraform.go index 2225d48cf..54f75cd50 100644 --- a/cmd/terraform.go +++ b/cmd/terraform.go @@ -48,6 +48,7 @@ func terraformSetEnv() *cobra.Command { err := v.IterSecrets(vaultURLFlag, vaultTokenFlag, outputFileFlag) if err != nil { progress.Error(fmt.Sprintf("error during vault read: %s", err)) + return } message := ` diff --git a/cmd/version.go b/cmd/version.go index e90c5c0ac..e8e797abf 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -31,7 +31,7 @@ func Create() *cobra.Command { ciFlag, _ := cmd.Flags().GetBool("ci") versionMsg := ` ## -### kubefirst-cli golang utility version:` + fmt.Sprintf("`%s`", configs.K1Version) +### kubefirst-cli golang utility version:` + fmt.Sprintf("%s", configs.K1Version) if ciFlag { fmt.Print(versionMsg) diff --git a/cmd/vultr/command.go b/cmd/vultr/command.go index 2d9e964a3..bf3109fce 100644 --- a/cmd/vultr/command.go +++ b/cmd/vultr/command.go @@ -52,10 +52,10 @@ var ( func NewCommand() *cobra.Command { vultrCmd := &cobra.Command{ Use: "vultr", - Short: "kubefirst Vultr installation", + Short: "Kubefirst Vultr installation", Long: "kubefirst vultr", Run: func(cmd *cobra.Command, args []string) { - fmt.Println("To learn more about vultr in kubefirst, run:") + fmt.Println("To learn more about Vultr in Kubefirst, run:") fmt.Println(" kubefirst beta vultr --help") if progress.Progress != nil { @@ -76,7 +76,7 @@ func NewCommand() *cobra.Command { func Create() *cobra.Command { createCmd := &cobra.Command{ Use: "create", - Short: "create the kubefirst platform running on Vultr kubernetes", + Short: "Create the Kubefirst platform running on Vultr Kubernetes", TraverseChildren: true, RunE: createVultr, // PreRun: common.CheckDocker, @@ -85,27 +85,27 @@ func Create() *cobra.Command { vultrDefaults := constants.GetCloudDefaults().Vultr // todo review defaults and update descriptions - createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "email address for let's encrypt certificate notifications (required)") + createCmd.Flags().StringVar(&alertsEmailFlag, "alerts-email", "", "Email address for Let's Encrypt certificate notifications (required)") createCmd.MarkFlagRequired("alerts-email") - createCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") - createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "ewr", "the Vultr region to provision infrastructure in") - createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "the name of the cluster to create") - createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "the type of cluster to create (i.e. mgmt|workload)") - createCmd.Flags().StringVar(&nodeCountFlag, "node-count", vultrDefaults.NodeCount, "the node count for the cluster") - createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", vultrDefaults.InstanceSize, "the instance size of the cluster to create") - createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "vultr", fmt.Sprintf("the dns provider - one of: %s", supportedDNSProviders)) - createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") - createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "the Vultr DNS Name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") + createCmd.Flags().BoolVar(&ciFlag, "ci", false, "If running Kubefirst in CI, set this flag to disable interactive features") + createCmd.Flags().StringVar(&cloudRegionFlag, "cloud-region", "ewr", "The Vultr region to provision infrastructure in") + createCmd.Flags().StringVar(&clusterNameFlag, "cluster-name", "kubefirst", "The name of the cluster to create") + createCmd.Flags().StringVar(&clusterTypeFlag, "cluster-type", "mgmt", "The type of cluster to create (i.e. mgmt|workload)") + createCmd.Flags().StringVar(&nodeCountFlag, "node-count", vultrDefaults.NodeCount, "The node count for the cluster") + createCmd.Flags().StringVar(&nodeTypeFlag, "node-type", vultrDefaults.InstanceSize, "The instance size of the cluster to create") + createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "vultr", fmt.Sprintf("The DNS provider - one of: %s", supportedDNSProviders)) + createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "The subdomain to use for DNS records (Cloudflare)") + createCmd.Flags().StringVar(&domainNameFlag, "domain-name", "", "The Vultr DNS name to use for DNS records (i.e. your-domain.com|subdomain.your-domain.com) (required)") createCmd.MarkFlagRequired("domain-name") - createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("the git provider - one of: %s", supportedGitProviders)) - createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("the git protocol - one of: %s", supportedGitProtocolOverride)) - createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "the GitHub organization for the new gitops and metaphor repositories - required if using github") - createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "the GitLab group for the new gitops and metaphor projects - required if using gitlab") - createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "the branch to clone for the gitops-template repository") - createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/konstructio/gitops-template.git", "the fully qualified url to the gitops-template repository to clone") - createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "comma separated values to install after provision") - createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "whether to emit telemetry") - createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "whether or not to install kubefirst pro") + createCmd.Flags().StringVar(&gitProviderFlag, "git-provider", "github", fmt.Sprintf("The Git provider - one of: %s", supportedGitProviders)) + createCmd.Flags().StringVar(&gitProtocolFlag, "git-protocol", "ssh", fmt.Sprintf("The Git protocol - one of: %s", supportedGitProtocolOverride)) + createCmd.Flags().StringVar(&githubOrgFlag, "github-org", "", "The GitHub organization for the new GitOps and metaphor repositories - required if using GitHub") + createCmd.Flags().StringVar(&gitlabGroupFlag, "gitlab-group", "", "The GitLab group for the new GitOps and metaphor projects - required if using GitLab") + createCmd.Flags().StringVar(&gitopsTemplateBranchFlag, "gitops-template-branch", "", "The branch to clone for the GitOps template repository") + createCmd.Flags().StringVar(&gitopsTemplateURLFlag, "gitops-template-url", "https://github.com/konstructio/gitops-template.git", "The fully qualified URL to the GitOps template repository to clone") + createCmd.Flags().StringVar(&installCatalogApps, "install-catalog-apps", "", "Comma separated values to install after provision") + createCmd.Flags().BoolVar(&useTelemetryFlag, "use-telemetry", true, "Whether to emit telemetry") + createCmd.Flags().BoolVar(&installKubefirstProFlag, "install-kubefirst-pro", true, "Whether or not to install Kubefirst Pro") return createCmd } @@ -113,8 +113,8 @@ func Create() *cobra.Command { func Destroy() *cobra.Command { destroyCmd := &cobra.Command{ Use: "destroy", - Short: "destroy the kubefirst platform", - Long: "destroy the kubefirst platform running in Vultr and remove all resources", + Short: "Destroy the Kubefirst platform", + Long: "Destroy the Kubefirst platform running in Vultr and remove all resources", RunE: common.Destroy, // PreRun: common.CheckDocker, } @@ -125,8 +125,8 @@ func Destroy() *cobra.Command { func RootCredentials() *cobra.Command { authCmd := &cobra.Command{ Use: "root-credentials", - Short: "retrieve root authentication information for platform components", - Long: "retrieve root authentication information for platform components", + Short: "Retrieve root authentication information for platform components", + Long: "Retrieve root authentication information for platform components", RunE: common.GetRootCredentials, } diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 9cd911132..26a4233da 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package vultr import ( + "errors" "fmt" "os" "strings" @@ -30,23 +31,26 @@ func createVultr(cmd *cobra.Command, args []string) error { cliFlags, err := utilities.GetFlags(cmd, "vultr") if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to get flags: %w", err) } progress.DisplayLogHints(15) isValid, catalogApps, err := catalog.ValidateCatalogApps(cliFlags.InstallCatalogApps) + if err != nil { + return fmt.Errorf("catalog apps validation failed: %w", err) + } + if !isValid { - return err + return errors.New("catalog validation failed") } err = ValidateProvidedFlags(cliFlags.GitProvider) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("invalid provided flags: %w", err) } - // If cluster setup is complete, return clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") if clusterSetupComplete { err = fmt.Errorf("this cluster install process has already completed successfully") @@ -59,10 +63,9 @@ func createVultr(cmd *cobra.Command, args []string) error { gitAuth, err := gitShim.ValidateGitCredentials(cliFlags.GitProvider, cliFlags.GithubOrg, cliFlags.GitlabGroup) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to validate git credentials: %w", err) } - // Validate git executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider)) if !executionControl { newRepositoryNames := []string{"gitops", "metaphor"} @@ -79,11 +82,13 @@ func createVultr(cmd *cobra.Command, args []string) error { err = gitShim.InitializeGitProvider(&initGitParameters) if err != nil { progress.Error(err.Error()) - return nil + return fmt.Errorf("failed to initialize git provider: %w", err) } } viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", cliFlags.GitProvider), true) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write config: %w", err) + } k3dClusterCreationComplete := viper.GetBool("launch.deployed") isK1Debug := strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" @@ -95,10 +100,10 @@ func createVultr(cmd *cobra.Command, args []string) error { err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") + return fmt.Errorf("kubefirst api availability check failed: %w", err) } provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) - return nil } @@ -109,7 +114,6 @@ func ValidateProvidedFlags(gitProvider string) error { return fmt.Errorf("your VULTR_API_KEY variable is unset - please set it before continuing") } - // Validate required environment variables for dns provider if dnsProviderFlag == "cloudflare" { if os.Getenv("CF_API_TOKEN") == "" { return fmt.Errorf("your CF_API_TOKEN environment variable is not set. Please set and try again") @@ -120,20 +124,17 @@ func ValidateProvidedFlags(gitProvider string) error { case "github": key, err := internalssh.GetHostKey("github.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "github.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "github.com", key.Type()) case "gitlab": key, err := internalssh.GetHostKey("gitlab.com") if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy") - } else { - log.Info().Msgf("%s %s\n", "gitlab.com", key.Type()) + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) } + log.Info().Msgf("%q %s", "gitlab.com", key.Type()) } progress.CompleteStep("Validate provided flags") - return nil } From 48d7bd1f37726bc5371882abb45175a84e9cf54a Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:29:28 -0400 Subject: [PATCH 52/85] Enable golangci-lint --- .github/workflows/check-unit-tests.yml | 10 +++++++--- cmd/letsencrypt.go | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check-unit-tests.yml b/.github/workflows/check-unit-tests.yml index e0a90e9ad..2fd99120c 100644 --- a/.github/workflows/check-unit-tests.yml +++ b/.github/workflows/check-unit-tests.yml @@ -11,6 +11,10 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version-file: "go.mod" - - name: Running Golang tests - run: go test -v -short ./... + go-version-file: go.mod + - name: Run GolangCI-Lint + uses: golangci/golangci-lint-action@v6 + with: + version: v1.60.3 + - name: Test application + run: go test -short -v ./... diff --git a/cmd/letsencrypt.go b/cmd/letsencrypt.go index ea21f05e6..1075338cf 100644 --- a/cmd/letsencrypt.go +++ b/cmd/letsencrypt.go @@ -7,7 +7,7 @@ See the LICENSE file for more details. package cmd import ( - "log" + "fmt" "github.com/konstructio/kubefirst-api/pkg/certificates" "github.com/konstructio/kubefirst/internal/progress" @@ -37,7 +37,7 @@ func status() *cobra.Command { TraverseChildren: true, Run: func(cmd *cobra.Command, args []string) { if err := certificates.CheckCertificateUsage(domainNameFlag); err != nil { - log.Printf("failed to check certificate usage for domain %q: %w", domainNameFlag, err) + fmt.Printf("failed to check certificate usage for domain %q: %s\n", domainNameFlag, err) } progress.Progress.Quit() }, From f9f773bf7c4f844ca80df0b3d3f733281d3c610c Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:30:08 -0400 Subject: [PATCH 53/85] Fix version printing. --- cmd/version.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index e8e797abf..17ddf79c5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -7,8 +7,6 @@ See the LICENSE file for more details. package cmd import ( - "fmt" - "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" @@ -31,7 +29,7 @@ func Create() *cobra.Command { ciFlag, _ := cmd.Flags().GetBool("ci") versionMsg := ` ## -### kubefirst-cli golang utility version:` + fmt.Sprintf("%s", configs.K1Version) +### kubefirst-cli golang utility version: ` + configs.K1Version if ciFlag { fmt.Print(versionMsg) From 6005b8a4acddb88a4119a726ad6d1bc19aee6cb3 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:06:16 -0400 Subject: [PATCH 54/85] Cleanup internal folder --- internal/catalog/catalog.go | 36 ++++----- internal/cluster/cluster.go | 98 +++++++++++------------ internal/common/common.go | 20 +++-- internal/gitShim/containerRegistryAuth.go | 17 ++-- internal/gitShim/init.go | 73 ++++++++--------- internal/k3d/menu.go | 23 +++--- internal/launch/cmd.go | 95 ++++++++++++++-------- internal/launch/utils.go | 15 ++-- internal/progress/command.go | 3 + internal/progress/constants.go | 8 +- internal/progress/message.go | 27 ++----- internal/progress/progress.go | 1 - internal/progress/styles.go | 4 +- internal/progress/types.go | 2 +- internal/provision/provision.go | 14 +++- internal/provisionLogs/command.go | 3 +- internal/provisionLogs/message.go | 33 ++++++++ internal/provisionLogs/provisionLogs.go | 2 +- internal/provisionLogs/types.go | 2 +- internal/segment/segment.go | 10 ++- internal/utilities/flags.go | 56 ++++++------- internal/utilities/utilities.go | 39 +++++---- 22 files changed, 321 insertions(+), 260 deletions(-) create mode 100644 internal/provisionLogs/message.go diff --git a/internal/catalog/catalog.go b/internal/catalog/catalog.go index 0fcd54734..90290bb06 100644 --- a/internal/catalog/catalog.go +++ b/internal/catalog/catalog.go @@ -43,19 +43,19 @@ func ReadActiveApplications() (apiTypes.GitopsCatalogApps, error) { activeContent, err := gh.ReadGitopsCatalogRepoContents() if err != nil { - return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog repository content: %s", err) + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog repository content: %w", err) } index, err := gh.ReadGitopsCatalogIndex(activeContent) if err != nil { - return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog index content: %s", err) + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog index content: %w", err) } var out apiTypes.GitopsCatalogApps err = yaml.Unmarshal(index, &out) if err != nil { - return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog applications: %s", err) + return apiTypes.GitopsCatalogApps{}, fmt.Errorf("error retrieving gitops catalog applications: %w", err) } return out, nil @@ -71,7 +71,7 @@ func ValidateCatalogApps(catalogApps string) (bool, []apiTypes.GitopsCatalogApp, apps, err := ReadActiveApplications() if err != nil { - log.Error().Msgf(fmt.Sprintf("Error getting gitops catalag applications: %s", err)) + log.Error().Msgf("error getting gitops catalog applications: %s", err) return false, gitopsCatalogapps, err } @@ -86,7 +86,7 @@ func ValidateCatalogApps(catalogApps string) (bool, []apiTypes.GitopsCatalogApp, secretValue := os.Getenv(secret.Env) if secretValue == "" { - return false, gitopsCatalogapps, fmt.Errorf("your %s environment variable is not set for %s catalog application. Please set and try again", secret.Env, app) + return false, gitopsCatalogapps, fmt.Errorf("your %q environment variable is not set for %q catalog application. Please set and try again", secret.Env, app) } secret.Value = secretValue @@ -97,7 +97,7 @@ func ValidateCatalogApps(catalogApps string) (bool, []apiTypes.GitopsCatalogApp, for _, config := range catalogApp.ConfigKeys { configValue := os.Getenv(config.Env) if configValue == "" { - return false, gitopsCatalogapps, fmt.Errorf("your %s environment variable is not set for %s catalog application. Please set and try again", config.Env, app) + return false, gitopsCatalogapps, fmt.Errorf("your %q environment variable is not set for %q catalog application. Please set and try again", config.Env, app) } config.Value = configValue } @@ -109,7 +109,7 @@ func ValidateCatalogApps(catalogApps string) (bool, []apiTypes.GitopsCatalogApp, } } if !found { - return false, gitopsCatalogapps, fmt.Errorf(fmt.Sprintf("catalag app is not supported: %s", app)) + return false, gitopsCatalogapps, fmt.Errorf("catalog app is not supported: %q", app) } } @@ -125,7 +125,7 @@ func (gh *GitHubClient) ReadGitopsCatalogRepoContents() ([]*git.RepositoryConten nil, ) if err != nil { - return nil, err + return nil, fmt.Errorf("error retrieving gitops catalog repository contents: %w", err) } return directoryContent, nil @@ -134,20 +134,16 @@ func (gh *GitHubClient) ReadGitopsCatalogRepoContents() ([]*git.RepositoryConten // ReadGitopsCatalogIndex reads the gitops catalog repository index func (gh *GitHubClient) ReadGitopsCatalogIndex(contents []*git.RepositoryContent) ([]byte, error) { for _, content := range contents { - switch *content.Type { - case "file": - switch *content.Name { - case "index.yaml": - b, err := gh.readFileContents(content) - if err != nil { - return b, err - } - return b, nil + if *content.Type == "file" && *content.Name == "index.yaml" { + b, err := gh.readFileContents(content) + if err != nil { + return nil, fmt.Errorf("error reading index.yaml file: %w", err) } + return b, nil } } - return []byte{}, fmt.Errorf("index.yaml not found in gitops catalog repository") + return nil, fmt.Errorf("index.yaml not found in gitops catalog repository") } // readFileContents parses the contents of a file in a GitHub repository @@ -160,13 +156,13 @@ func (gh *GitHubClient) readFileContents(content *git.RepositoryContent) ([]byte nil, ) if err != nil { - return []byte{}, err + return nil, fmt.Errorf("error downloading contents of %q: %w", *content.Path, err) } defer rc.Close() b, err := io.ReadAll(rc) if err != nil { - return []byte{}, err + return nil, fmt.Errorf("error reading contents of %q: %w", *content.Path, err) } return b, nil diff --git a/internal/cluster/cluster.go b/internal/cluster/cluster.go index da7457b23..f34b22518 100644 --- a/internal/cluster/cluster.go +++ b/internal/cluster/cluster.go @@ -40,37 +40,36 @@ func CreateCluster(cluster apiTypes.ClusterDefinition) error { payload, err := json.Marshal(requestObject) if err != nil { - return err + return fmt.Errorf("failed to marshal request object: %w", err) } req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresUrl()), bytes.NewReader(payload)) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error creating request: %s", err) + return fmt.Errorf("failed to create request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") res, err := httpClient.Do(req) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error executing request: %s", err) + return fmt.Errorf("failed to execute request: %w", err) } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { - log.Info().Msgf("unable to create cluster %s", err) - - return err + log.Printf("unable to create cluster: %v", err) + return fmt.Errorf("failed to read response body: %w", err) } if res.StatusCode != http.StatusAccepted { - log.Info().Msgf("unable to create cluster %s %s", res.Status, body) - return fmt.Errorf("unable to create cluster %s %s", res.Status, body) + log.Printf("unable to create cluster: %q %q", res.Status, body) + return fmt.Errorf("unable to create cluster: API returned unexpected status code %q: %s", res.Status, body) } - log.Info().Msgf("Created cluster: %s", string(body)) + log.Printf("Created cluster: %q", string(body)) return nil } @@ -85,38 +84,36 @@ func ResetClusterProgress(clusterName string) error { payload, err := json.Marshal(requestObject) if err != nil { - return err + return fmt.Errorf("failed to marshal request object: %w", err) } req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresUrl()), bytes.NewReader(payload)) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error creating request: %v", err) + return fmt.Errorf("failed to create request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") res, err := httpClient.Do(req) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error executing request: %v", err) + return fmt.Errorf("failed to execute request: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { - log.Info().Msgf("unable to create cluster %s", res.Status) - return err + log.Printf("unable to reset cluster progress: %q", res.Status) + return fmt.Errorf("unable to reset cluster progress: API returned unexpected status %q", res.Status) } body, err := io.ReadAll(res.Body) if err != nil { - log.Info().Msgf("unable to create cluster %s", err) - - return err + log.Printf("unable to read response body: %v", err) + return fmt.Errorf("failed to read response body: %w", err) } log.Info().Msgf("Import: %s", string(body)) - return nil } @@ -127,34 +124,34 @@ func GetCluster(clusterName string) (apiTypes.Cluster, error) { cluster := apiTypes.Cluster{} req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresUrl(), clusterName), nil) if err != nil { - log.Info().Msgf("error %s", err) - return cluster, err + log.Printf("error creating request: %v", err) + return cluster, fmt.Errorf("failed to create request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") res, err := httpClient.Do(req) if err != nil { - log.Info().Msgf("error %s", err) - return cluster, err + log.Printf("error executing request: %v", err) + return cluster, fmt.Errorf("failed to execute request: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { - log.Info().Msgf("unable to get cluster %s, continuing", res.Status) - return cluster, err + log.Printf("unable to get cluster: %q, continuing", res.Status) + return cluster, fmt.Errorf("unable to get cluster: %q", res.Status) } body, err := io.ReadAll(res.Body) if err != nil { - log.Info().Msgf("unable to get cluster %s", err) - return cluster, err + log.Printf("unable to read response body: %v", err) + return cluster, fmt.Errorf("failed to read response body: %w", err) } err = json.Unmarshal(body, &cluster) if err != nil { - log.Info().Msgf("unable to cast cluster object %s", err) - return cluster, err + log.Printf("unable to unmarshal cluster object: %v", err) + return cluster, fmt.Errorf("failed to unmarshal cluster object: %w", err) } return cluster, nil @@ -167,33 +164,34 @@ func GetClusters() ([]apiTypes.Cluster, error) { clusters := []apiTypes.Cluster{} req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster", GetConsoleIngresUrl()), nil) if err != nil { - log.Info().Msgf("error %s", err) - return clusters, err + log.Printf("error creating request: %v", err) + return clusters, fmt.Errorf("failed to create request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") res, err := httpClient.Do(req) if err != nil { - log.Info().Msgf("error %s", err) - return clusters, err + log.Printf("error executing request: %v", err) + return clusters, fmt.Errorf("failed to execute request: %w", err) } + defer res.Body.Close() if res.StatusCode != http.StatusOK { - log.Info().Msgf("unable to get clusters %s, continuing", res.Status) - return clusters, err + log.Printf("unable to get clusters: %q", res.Status) + return clusters, fmt.Errorf("unable to get clusters: API returned unexpected status code %q", res.Status) } body, err := io.ReadAll(res.Body) if err != nil { - log.Info().Msgf("unable to get clusters %s", err) - return clusters, err + log.Printf("unable to read response body: %v", err) + return clusters, fmt.Errorf("failed to read response body: %w", err) } err = json.Unmarshal(body, &clusters) if err != nil { - log.Info().Msgf("unable to cast clusters object %s", err) - return clusters, err + log.Printf("unable to unmarshal clusters object: %v", err) + return clusters, fmt.Errorf("failed to unmarshal clusters object: %w", err) } return clusters, nil @@ -205,27 +203,27 @@ func DeleteCluster(clusterName string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresUrl(), clusterName), nil) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error creating request: %v", err) + return fmt.Errorf("failed to create request: %w", err) } req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "application/json") res, err := httpClient.Do(req) if err != nil { - log.Info().Msgf("error %s", err) - return err + log.Printf("error executing request: %v", err) + return fmt.Errorf("failed to execute request: %w", err) } if res.StatusCode != http.StatusOK { - log.Info().Msgf("unable to delete cluster %s, continuing", res.Status) - return err + log.Printf("unable to delete cluster: %q, continuing", res.Status) + return fmt.Errorf("unable to delete cluster: API returned unexpected status code %q", res.Status) } _, err = io.ReadAll(res.Body) if err != nil { - log.Info().Msgf("unable to delete cluster %s", err) - return err + log.Printf("unable to read response body: %v", err) + return fmt.Errorf("failed to read response body: %w", err) } return nil diff --git a/internal/common/common.go b/internal/common/common.go index 8b073b186..c42193404 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -29,7 +29,7 @@ type CheckResponse struct { // Current is current latest version on source. Current string - // Outdate is true when target version is less than Curernt on source. + // Outdate is true when target version is less than Current on source. Outdated bool // Latest is true when target version is equal to Current on source. @@ -87,6 +87,10 @@ func versionCheck() (res *CheckResponse, skip bool) { re := regexp.MustCompile(`.*/v(.*).tar.gz"`) matches := re.FindStringSubmatch(bodyString) + if len(matches) < 2 { + fmt.Println("checking for a newer version failed (no version match)") + return nil, true + } latestVersion = matches[1] return &CheckResponse{ @@ -113,7 +117,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) - return err + return fmt.Errorf("failed to get cluster: %w", err) } progress.DisplayCredentials(cluster) @@ -122,7 +126,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { } func Destroy(cmd *cobra.Command, args []string) error { - // Determine if there are active instal ls + // Determine if there are active installs gitProvider := viper.GetString("flags.git-provider") gitProtocol := viper.GetString("flags.git-protocol") cloudProvider := viper.GetString("kubefirst.cloud-provider") @@ -141,6 +145,7 @@ func Destroy(cmd *cobra.Command, args []string) error { cGitOwner = viper.GetString("flags.gitlab-owner") default: progress.Error("invalid git provider option") + return fmt.Errorf("invalid git provider: %q", gitProvider) } // Instantiate aws config @@ -171,13 +176,14 @@ func Destroy(cmd *cobra.Command, args []string) error { viper.Set("kubefirst", "") viper.Set("flags", "") viper.Set("k1-paths", "") - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to write config: %w", err) + } if _, err := os.Stat(config.K1Dir + "/kubeconfig"); !os.IsNotExist(err) { - err = os.Remove(config.K1Dir + "/kubeconfig") - if err != nil { + if err := os.Remove(config.K1Dir + "/kubeconfig"); err != nil { progress.Error(fmt.Sprintf("unable to delete %q folder, error: %s", config.K1Dir+"/kubeconfig", err)) - return err + return fmt.Errorf("unable to delete kubeconfig: %w", err) } } diff --git a/internal/gitShim/containerRegistryAuth.go b/internal/gitShim/containerRegistryAuth.go index 660429f0e..8d69cd58e 100644 --- a/internal/gitShim/containerRegistryAuth.go +++ b/internal/gitShim/containerRegistryAuth.go @@ -12,7 +12,6 @@ import ( "github.com/konstructio/kubefirst-api/pkg/gitlab" "github.com/konstructio/kubefirst-api/pkg/k8s" - "github.com/rs/zerolog/log" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -41,7 +40,7 @@ func CreateContainerRegistrySecret(obj *ContainerRegistryAuth) (string, error) { case "github": usernamePasswordString := fmt.Sprintf("%s:%s", obj.GitUser, obj.GitToken) usernamePasswordStringB64 := base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) - dockerConfigString := fmt.Sprintf(`{"auths": {"%s": {"username": "%s", "password": "%s", "email": "%s", "auth": "%s"}}}`, + dockerConfigString := fmt.Sprintf(`{"auths": {"%s": {"username": %q, "password": %q, "email": %q, "auth": %q}}}`, obj.ContainerRegistryHost, obj.GithubOwner, obj.GitToken, @@ -49,27 +48,21 @@ func CreateContainerRegistrySecret(obj *ContainerRegistryAuth) (string, error) { usernamePasswordStringB64, ) - // Create argo workflows pull secret argoDeployTokenSecret := &v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: "argo"}, Data: map[string][]byte{"config.json": []byte(dockerConfigString)}, Type: "Opaque", } - err := k8s.CreateSecretV2(obj.Clientset, argoDeployTokenSecret) - if err != nil { - log.Error().Msgf("error while creating secret for container registry auth: %s", err) + if err := k8s.CreateSecretV2(obj.Clientset, argoDeployTokenSecret); err != nil { + return "", fmt.Errorf("error while creating secret for GitHub container registry auth: %w", err) } - // GitLab Deploy Tokens - // Project deploy tokens are generated for each member of createTokensForProjects - // These deploy tokens are used to authorize against the GitLab container registry case "gitlab": gitlabClient, err := gitlab.NewGitLabClient(obj.GitToken, obj.GitlabGroupFlag) if err != nil { - return "", err + return "", fmt.Errorf("error while creating GitLab client: %w", err) } - // Create argo workflows pull secret p := gitlab.DeployTokenCreateParameters{ Name: secretName, Username: secretName, @@ -77,7 +70,7 @@ func CreateContainerRegistrySecret(obj *ContainerRegistryAuth) (string, error) { } token, err := gitlabClient.CreateGroupDeployToken(0, &p) if err != nil { - log.Error().Msgf("error while creating secret for container registry auth: %s", err) + return "", fmt.Errorf("error while creating GitLab group deploy token: %w", err) } return token, nil diff --git a/internal/gitShim/init.go b/internal/gitShim/init.go index 2819384a9..124bffe77 100644 --- a/internal/gitShim/init.go +++ b/internal/gitShim/init.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package gitShim import ( + "errors" "fmt" "net/http" "os" @@ -42,30 +43,28 @@ func InitializeGitProvider(p *GitInitParameters) error { case "github": githubSession := github.New(p.GitToken) newRepositoryExists := false - // todo hoist to globals - errorMsg := "the following repositories must be removed before continuing with your kubefirst installation.\n\t" + errorMsg := "the following repositories must be removed before continuing with your Kubefirst installation.\n\t" for _, repositoryName := range p.Repositories { responseStatusCode := githubSession.CheckRepoExists(p.GitOwner, repositoryName) - // https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#get-a-repository repositoryExistsStatusCode := 200 repositoryDoesNotExistStatusCode := 404 if responseStatusCode == repositoryExistsStatusCode { - log.Info().Msgf("repository https://github.com/%s/%s exists", p.GitOwner, repositoryName) - errorMsg = errorMsg + fmt.Sprintf("https://github.com/%s/%s\n\t", p.GitOwner, repositoryName) + log.Info().Msgf("repository %q exists", fmt.Sprintf("https://github.com/%s/%s", p.GitOwner, repositoryName)) + errorMsg += fmt.Sprintf("https://github.com/%s/%s\n\t", p.GitOwner, repositoryName) newRepositoryExists = true } else if responseStatusCode == repositoryDoesNotExistStatusCode { - log.Info().Msgf("repository https://github.com/%s/%s does not exist, continuing", p.GitOwner, repositoryName) + log.Info().Msgf("repository %q does not exist, continuing", fmt.Sprintf("https://github.com/%s/%s", p.GitOwner, repositoryName)) } } if newRepositoryExists { - return fmt.Errorf(errorMsg) + return errors.New(errorMsg) } newTeamExists := false - errorMsg = "the following teams must be removed before continuing with your kubefirst installation.\n\t" + errorMsg = "the following teams must be removed before continuing with your Kubefirst installation.\n\t" for _, teamName := range p.Teams { responseStatusCode := githubSession.CheckTeamExists(p.GitOwner, teamName) @@ -75,45 +74,42 @@ func InitializeGitProvider(p *GitInitParameters) error { teamDoesNotExistStatusCode := 404 if responseStatusCode == teamExistsStatusCode { - log.Info().Msgf("team https://github.com/%s/%s exists", p.GitOwner, teamName) - errorMsg = errorMsg + fmt.Sprintf("https://github.com/orgs/%s/teams/%s\n\t", p.GitOwner, teamName) + log.Info().Msgf("team %q exists", fmt.Sprintf("https://github.com/%s/%s", p.GitOwner, teamName)) + errorMsg += fmt.Sprintf("https://github.com/orgs/%s/teams/%s\n\t", p.GitOwner, teamName) newTeamExists = true } else if responseStatusCode == teamDoesNotExistStatusCode { - log.Info().Msgf("https://github.com/orgs/%s/teams/%s does not exist, continuing", p.GitOwner, teamName) + log.Info().Msgf("team %q does not exist, continuing", fmt.Sprintf("https://github.com/orgs/%s/teams/%s", p.GitOwner, teamName)) } } if newTeamExists { - return fmt.Errorf(errorMsg) + return errors.New(errorMsg) } case "gitlab": gitlabClient, err := gitlab.NewGitLabClient(p.GitToken, p.GitOwner) if err != nil { - return err + return fmt.Errorf("error creating GitLab client: %w", err) } - // Check for existing base projects projects, err := gitlabClient.GetProjects() if err != nil { - log.Fatal().Msgf("couldn't get gitlab projects: %s", err) + return fmt.Errorf("couldn't get GitLab projects: %w", err) } for _, repositoryName := range p.Repositories { for _, project := range projects { if project.Name == repositoryName { - return fmt.Errorf("project %s already exists and will need to be deleted before continuing", repositoryName) + return fmt.Errorf("project %q already exists and will need to be deleted before continuing", repositoryName) } } } - // Check for existing base projects - // Save for detokenize subgroups, err := gitlabClient.GetSubGroups() if err != nil { - log.Fatal().Msgf("couldn't get gitlab subgroups for group %s: %s", p.GitOwner, err) + return fmt.Errorf("couldn't get GitLab subgroups for group %q: %w", p.GitOwner, err) } - for _, teamName := range p.Repositories { + for _, teamName := range p.Teams { for _, sg := range subgroups { if sg.Name == teamName { - return fmt.Errorf("subgroup %s already exists and will need to be deleted before continuing", teamName) + return fmt.Errorf("subgroup %q already exists and will need to be deleted before continuing", teamName) } } } @@ -126,15 +122,14 @@ func InitializeGitProvider(p *GitInitParameters) error { return nil } -func ValidateGitCredentials(gitProviderFlag string, githubOrgFlag string, gitlabGroupFlag string) (types.GitAuth, error) { +func ValidateGitCredentials(gitProviderFlag, githubOrgFlag, gitlabGroupFlag string) (types.GitAuth, error) { progress.AddStep("Validate git credentials") gitAuth := types.GitAuth{} - // Switch based on git provider, set params switch gitProviderFlag { case "github": if githubOrgFlag == "" { - return gitAuth, fmt.Errorf("please provide a github organization using the --github-org flag") + return gitAuth, fmt.Errorf("please provide a GitHub organization using the --github-org flag") } if os.Getenv("GITHUB_TOKEN") == "" { return gitAuth, fmt.Errorf("your GITHUB_TOKEN is not set. Please set and try again") @@ -143,65 +138,60 @@ func ValidateGitCredentials(gitProviderFlag string, githubOrgFlag string, gitlab gitAuth.Owner = githubOrgFlag gitAuth.Token = os.Getenv("GITHUB_TOKEN") - // Verify token scopes err := github.VerifyTokenPermissions(gitAuth.Token) if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error verifying GitHub token permissions: %w", err) } - // Handle authorization checks httpClient := http.DefaultClient gitHubService := services.NewGitHubService(httpClient) gitHubHandler := handlers.NewGitHubHandler(gitHubService) - // get github data to set user based on the provided token - log.Info().Msg("verifying github authentication") + log.Info().Msg("verifying GitHub authentication") githubUser, err := gitHubHandler.GetGitHubUser(gitAuth.Token) if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error getting GitHub user: %w", err) } gitAuth.User = githubUser viper.Set("github.user", githubUser) err = viper.WriteConfig() if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error writing GitHub config: %w", err) } err = gitHubHandler.CheckGithubOrganizationPermissions(gitAuth.Token, githubOrgFlag, githubUser) if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error checking GitHub organization permissions: %w", err) } viper.Set("flags.github-owner", githubOrgFlag) viper.WriteConfig() case "gitlab": if gitlabGroupFlag == "" { - return gitAuth, fmt.Errorf("please provide a gitlab group using the --gitlab-group flag") + return gitAuth, fmt.Errorf("please provide a GitLab group using the --gitlab-group flag") } if os.Getenv("GITLAB_TOKEN") == "" { - return gitAuth, fmt.Errorf("your GITLAB_TOKEN is not set. please set and try again") + return gitAuth, fmt.Errorf("your GITLAB_TOKEN is not set. Please set and try again") } gitAuth.Token = os.Getenv("GITLAB_TOKEN") - // Verify token scopes err := gitlab.VerifyTokenPermissions(gitAuth.Token) if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error verifying GitLab token permissions: %w", err) } gitlabClient, err := gitlab.NewGitLabClient(gitAuth.Token, gitlabGroupFlag) if err != nil { - return gitAuth, err + return gitAuth, fmt.Errorf("error creating GitLab client: %w", err) } gitAuth.Owner = gitlabClient.ParentGroupPath cGitlabOwnerGroupID := gitlabClient.ParentGroupID - log.Info().Msgf("set gitlab owner to %s", gitAuth.Owner) + log.Info().Msgf("set GitLab owner to %q", gitAuth.Owner) - // Get authenticated user's name user, _, err := gitlabClient.Client.Users.CurrentUser() if err != nil { - return gitAuth, fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set %s", err) + return gitAuth, fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set: %w", err) } gitAuth.User = user.Username @@ -209,7 +199,8 @@ func ValidateGitCredentials(gitProviderFlag string, githubOrgFlag string, gitlab viper.Set("flags.gitlab-owner-group-id", cGitlabOwnerGroupID) viper.WriteConfig() default: - log.Error().Msgf("invalid git provider option") + log.Printf("invalid git provider option: %q", gitProviderFlag) + return gitAuth, fmt.Errorf("invalid git provider: %q", gitProviderFlag) } progress.CompleteStep("Validate git credentials") diff --git a/internal/k3d/menu.go b/internal/k3d/menu.go index 668d84614..76ccc29c9 100644 --- a/internal/k3d/menu.go +++ b/internal/k3d/menu.go @@ -9,12 +9,12 @@ package k3d import ( "fmt" "io" + "log" "strings" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" - "github.com/konstructio/kubefirst/internal/progress" ) const ( @@ -104,9 +104,9 @@ func (m Model) View() string { return "\n" + m.List.View() } -func MongoDestinationChooser(inCluster bool) string { +func MongoDestinationChooser(inCluster bool) (result string, err error) { if inCluster { - return "in-cluster" + return "in-cluster", nil } items := []list.Item{ @@ -126,18 +126,15 @@ func MongoDestinationChooser(inCluster bool) string { model, err := tea.NewProgram(m).Run() if err != nil { - fmt.Println("Error running program:", err) - progress.Progress.Quit() + log.Printf("Error running program: %v", err) + return "", fmt.Errorf("failed to run the program: %w", err) } - var result string - if strings.Contains(model.View(), "atlas") { - result = "atlas" - } else if strings.Contains(model.View(), "in-cluster") { - result = "in-cluster" - } else { - result = "error" + return "atlas", nil + } + if strings.Contains(model.View(), "in-cluster") { + return "in-cluster", nil } - return result + return "error", nil } diff --git a/internal/launch/cmd.go b/internal/launch/cmd.go index 658729caf..3ccb0a9b8 100644 --- a/internal/launch/cmd.go +++ b/internal/launch/cmd.go @@ -35,7 +35,7 @@ import ( var consoleClusterName = "kubefirst-console" // Up -func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { +func Up(additionalHelmFlags []string, inCluster, useTelemetry bool) { if viper.GetBool("launch.deployed") { progress.Error("Kubefirst console has already been deployed. To start over, run `kubefirst launch down` to completely remove the existing console.") } @@ -46,20 +46,21 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { homeDir, err := os.UserHomeDir() if err != nil { - progress.Error(fmt.Sprintf("something went wrong getting home path: %s", err)) + progress.Error(fmt.Sprintf("unable to get user's home directory: %s", err)) + return } dir := fmt.Sprintf("%s/.k1/%s", homeDir, consoleClusterName) if _, err := os.Stat(dir); os.IsNotExist(err) { err := os.MkdirAll(dir, os.ModePerm) if err != nil { - log.Info().Msgf("%s directory already exists, continuing", dir) + log.Info().Msgf("%q directory already exists, continuing", dir) } } toolsDir := fmt.Sprintf("%s/tools", dir) if _, err := os.Stat(toolsDir); os.IsNotExist(err) { err := os.MkdirAll(toolsDir, os.ModePerm) if err != nil { - log.Info().Msgf("%s directory already exists, continuing", toolsDir) + log.Info().Msgf("%q directory already exists, continuing", toolsDir) } } @@ -81,13 +82,15 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { err = downloadManager.DownloadFile(k3dClient, k3dDownloadUrl) if err != nil { progress.Error(fmt.Sprintf("error while trying to download k3d: %s", err)) + return } err = os.Chmod(k3dClient, 0o755) if err != nil { - log.Fatal().Msg(err.Error()) + progress.Error(fmt.Sprintf("error changing permissions of k3d client: %s", err)) + return } } else { - log.Info().Msgf("k3d is already installed, continuing") + log.Info().Msg("k3d is already installed, continuing") } progress.CompleteStep("Download k3d") @@ -107,10 +110,12 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { err = downloadManager.DownloadFile(helmDownloadTarGzPath, helmDownloadUrl) if err != nil { progress.Error(fmt.Sprintf("error while trying to download helm: %s", err)) + return } helmTarDownload, err := os.Open(helmDownloadTarGzPath) if err != nil { - progress.Error("could not read helm download content") + progress.Error(fmt.Sprintf("could not read helm download content: %s", err)) + return } downloadManager.ExtractFileFromTarGz( helmTarDownload, @@ -119,7 +124,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { ) err = os.Chmod(helmClient, 0o755) if err != nil { - log.Fatal().Msg(err.Error()) + progress.Error(fmt.Sprintf("error changing permissions of helm client: %s", err)) + return } os.Remove(helmDownloadTarGzPath) } else { @@ -141,10 +147,12 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { err = downloadManager.DownloadFile(mkcertClient, mkcertDownloadURL) if err != nil { progress.Error(fmt.Sprintf("error while trying to download mkcert: %s", err)) + return } err = os.Chmod(mkcertClient, 0o755) if err != nil { - progress.Error(err.Error()) + progress.Error(fmt.Sprintf("error changing permissions of mkcert client: %s", err)) + return } } else { log.Info().Msg("mkcert is already installed, continuing") @@ -170,9 +178,10 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { fmt.Sprintf("%s/kubeconfig", dir), ) if err != nil { - msg := fmt.Sprintf("error creating k3d cluster: %s", err) - progress.Error(msg) + progress.Error(fmt.Sprintf("error creating k3d cluster: %s", err)) + return } + log.Info().Msg("k3d cluster for Kubefirst console and API created successfully") // Wait for traefik @@ -187,10 +196,12 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { ) if err != nil { progress.Error(fmt.Sprintf("error looking for traefik: %s", err)) + return } _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, traefikDeployment, 120) if err != nil { progress.Error(fmt.Sprintf("error waiting for traefik: %s", err)) + return } } @@ -208,7 +219,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { "yaml", ) if err != nil { - log.Fatal().Msgf("error listing current helm repositories: %s", err) + progress.Error(fmt.Sprintf("error listing current helm repositories: %s", err)) + return } var existingHelmRepositories []helm.HelmRepo @@ -217,7 +229,9 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { err = yaml.Unmarshal([]byte(res), &existingHelmRepositories) if err != nil { progress.Error(fmt.Sprintf("could not get existing helm repositories: %s", err)) + return } + for _, repo := range existingHelmRepositories { if repo.Name == helmChartRepoName && repo.URL == helmChartRepoURL { repoExists = true @@ -234,7 +248,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { helmChartRepoURL, ) if err != nil { - log.Error().Msgf("error adding helm chart repository: %s", err) + progress.Error(fmt.Sprintf("error adding helm chart repository: %s", err)) + return } log.Info().Msg("Added Kubefirst helm chart repository") } else { @@ -248,7 +263,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { "update", ) if err != nil { - log.Error().Msgf("error updating helm chart repository: %s", err) + progress.Error(fmt.Sprintf("error updating helm chart repository: %s", err)) + return } log.Info().Msg("Kubefirst helm chart repository updated") @@ -263,7 +279,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { "-A", ) if err != nil { - log.Error().Msgf("error listing current helm repositories: %s", err) + progress.Error(fmt.Sprintf("error listing current helm releases: %s", err)) + return } var existingHelmReleases []helm.HelmRelease @@ -272,6 +289,7 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { err = yaml.Unmarshal([]byte(res), &existingHelmReleases) if err != nil { progress.Error(fmt.Sprintf("could not get existing helm releases: %s", err)) + return } for _, release := range existingHelmReleases { if release.Name == helmChartName { @@ -341,6 +359,7 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { a, b, err := shell.ExecShellReturnStrings(helmClient, installFlags...) if err != nil { progress.Error(fmt.Sprintf("error installing helm chart: %s %s %s", err, a, b)) + return } log.Info().Msg("Kubefirst console helm chart installed successfully") @@ -363,10 +382,13 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { ) if err != nil { progress.Error(fmt.Sprintf("error looking for kubefirst api: %s", err)) + return } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, apiDeployment, 300) if err != nil { progress.Error(fmt.Sprintf("error waiting for kubefirst api: %s", err)) + return } // Generate certificate for console @@ -374,7 +396,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { if _, err := os.Stat(sslPemDir); os.IsNotExist(err) { err := os.MkdirAll(sslPemDir, os.ModePerm) if err != nil { - log.Warn().Msgf("%s directory already exists, continuing", sslPemDir) + progress.Error(fmt.Sprintf("error creating directory for certificates: %s", err)) + return } } log.Info().Msg("Certificate directory created") @@ -383,7 +406,8 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { if _, err := os.Stat(mkcertPemDir); os.IsNotExist(err) { err := os.MkdirAll(mkcertPemDir, os.ModePerm) if err != nil { - log.Warn().Msgf("%s directory already exists, continuing", mkcertPemDir) + progress.Error(fmt.Sprintf("error creating directory for certificates: %s", err)) + return } } @@ -402,21 +426,24 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { ) if err != nil { progress.Error(fmt.Sprintf("error generating certificate for console: %s", err)) + return } // * read certificate files certPem, err := os.ReadFile(fmt.Sprintf("%s/%s-cert.pem", mkcertPemDir, "kubefirst-console")) if err != nil { - progress.Error(fmt.Sprintf("error generating certificate for console: %s", err)) + progress.Error(fmt.Sprintf("error reading certificate for console: %s", err)) + return } keyPem, err := os.ReadFile(fmt.Sprintf("%s/%s-key.pem", mkcertPemDir, "kubefirst-console")) if err != nil { - progress.Error(fmt.Sprintf("error generating certificate for console: %s", err)) + progress.Error(fmt.Sprintf("error reading key for console: %s", err)) + return } _, err = kcfg.Clientset.CoreV1().Secrets(namespace).Get(context.Background(), "kubefirst-console-tls", metav1.GetOptions{}) if err == nil { - log.Info().Msg(fmt.Sprintf("kubernetes secret %s/%s already created - skipping", namespace, "kubefirst-console")) + log.Info().Msg(fmt.Sprintf("kubernetes secret %q already created - skipping", "kubefirst-console")) } else if strings.Contains(err.Error(), "not found") { _, err = kcfg.Clientset.CoreV1().Secrets(namespace).Create(context.Background(), &v1.Secret{ Type: "kubernetes.io/tls", @@ -431,6 +458,7 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { }, metav1.CreateOptions{}) if err != nil { progress.Error(fmt.Sprintf("error creating kubernetes secret for cert: %s", err)) + return } time.Sleep(5 * time.Second) log.Info().Msg("Created Kubernetes Secret for certificate") @@ -439,20 +467,19 @@ func Up(additionalHelmFlags []string, inCluster bool, useTelemetry bool) { progress.CompleteStep("Waiting for kubefirst Deployment") if !inCluster { - log.Info().Msg(fmt.Sprintf("Kubefirst Console is now available! %s", consoleURL)) + log.Info().Msg(fmt.Sprintf("Kubefirst Console is now available! %q", consoleURL)) - log.Warn().Msgf("Kubefirst has generated local certificates for use with the console using `mkcert`.") - log.Warn().Msgf("If you experience certificate errors when accessing the console, please run the following command: ") - log.Warn().Msgf(" %s -install", mkcertClient) - log.Warn().Msgf("") - log.Warn().Msgf("For more information on `mkcert`, check out: https://github.com/FiloSottile/mkcert") + log.Warn().Msg("Kubefirst has generated local certificates for use with the console using `mkcert`.") + log.Warn().Msg("If you experience certificate errors when accessing the console, please run the following command:") + log.Warn().Msg(fmt.Sprintf(" %q -install", mkcertClient)) + log.Warn().Msg("For more information on `mkcert`, check out: https://github.com/FiloSottile/mkcert") - log.Info().Msg("To remove Kubefirst Console and the k3d cluster it runs in, please run the following command: ") + log.Info().Msg("To remove Kubefirst Console and the k3d cluster it runs in, please run the following command:") log.Info().Msg("kubefirst launch down") err = pkg.OpenBrowser(consoleURL) if err != nil { - log.Error().Msgf("error attempting to open console in browser: %s", err) + log.Printf("error attempting to open console in browser: %v", err) } } @@ -475,13 +502,15 @@ func Down(inCluster bool) { homeDir, err := os.UserHomeDir() if err != nil { progress.Error(fmt.Sprintf("something went wrong getting home path: %s", err)) + return } log.Info().Msg("Deleting k3d cluster for Kubefirst console and API") dir := fmt.Sprintf("%s/.k1/%s", homeDir, consoleClusterName) if _, err := os.Stat(dir); os.IsNotExist(err) { - progress.Error(fmt.Sprintf("cluster %s directory does not exist", dir)) + progress.Error(fmt.Sprintf("cluster %q directory does not exist", dir)) + return } toolsDir := fmt.Sprintf("%s/tools", dir) k3dClient := fmt.Sprintf("%s/k3d", toolsDir) @@ -489,14 +518,15 @@ func Down(inCluster bool) { _, _, err = shell.ExecShellReturnStrings(k3dClient, "cluster", "delete", consoleClusterName) if err != nil { progress.Error(fmt.Sprintf("error deleting k3d cluster: %s", err)) + return } log.Info().Msg("k3d cluster for Kubefirst console and API deleted successfully") - log.Info().Msg(fmt.Sprintf("Deleting cluster directory at %s", dir)) + log.Info().Msg(fmt.Sprintf("Deleting cluster directory at %q", dir)) err = os.RemoveAll(dir) if err != nil { - log.Warn().Msgf("unable to remove directory at %s", dir) + log.Warn().Msgf("unable to remove directory at %q", dir) } viper.Set("kubefirst", "") @@ -528,7 +558,8 @@ func ListClusters() { func DeleteCluster(managedClusterName string) { err := cluster.DeleteCluster(managedClusterName) if err != nil { - progress.Error(fmt.Sprintf("error: cluster %s not found\n", managedClusterName)) + progress.Error(fmt.Sprintf("error: cluster %q not found", managedClusterName)) + return } deleteMessage := ` diff --git a/internal/launch/utils.go b/internal/launch/utils.go index 1246a94e3..f57a0b841 100644 --- a/internal/launch/utils.go +++ b/internal/launch/utils.go @@ -7,7 +7,9 @@ See the LICENSE file for more details. package launch import ( + "bytes" "fmt" + "text/tabwriter" "github.com/konstructio/kubefirst-api/pkg/types" "github.com/konstructio/kubefirst/internal/progress" @@ -16,13 +18,12 @@ import ( // displayFormattedClusterInfo uses tabwriter to pretty print information on clusters using // the specified formatting func displayFormattedClusterInfo(clusters []types.Cluster) { - header := ` -| NAME | CREATED AT | STATUS | TYPE | PROVIDER | -| --- | --- | --- | --- | --- | - ` - content := "" + var buf bytes.Buffer + tw := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', tabwriter.Debug) + + fmt.Fprint(tw, "NAME\tCREATED AT\tSTATUS\tTYPE\tPROVIDER\n") for _, cluster := range clusters { - content = content + fmt.Sprintf("|%s|%s|%s|%s|%s\n", + fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n", cluster.ClusterName, cluster.CreationTimestamp, cluster.Status, @@ -31,5 +32,5 @@ func displayFormattedClusterInfo(clusters []types.Cluster) { ) } - progress.Success(header + content) + progress.Success(buf.String()) } diff --git a/internal/progress/command.go b/internal/progress/command.go index f774ae86a..2483cb16c 100644 --- a/internal/progress/command.go +++ b/internal/progress/command.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package progress import ( + "log" "time" tea "github.com/charmbracelet/bubbletea" @@ -19,6 +20,8 @@ func GetClusterInterval(clusterName string) tea.Cmd { return tea.Every(time.Second*10, func(t time.Time) tea.Msg { provisioningCluster, err := cluster.GetCluster(clusterName) if err != nil { + log.Printf("failed to get cluster %q: %v", clusterName, err) + return nil } return ClusterProvisioningMsg(provisioningCluster) diff --git a/internal/progress/constants.go b/internal/progress/constants.go index 8e2ba9446..41335b835 100644 --- a/internal/progress/constants.go +++ b/internal/progress/constants.go @@ -33,13 +33,13 @@ var CompletedStepsLabels = ProvisionSteps{ domain_liveness_check: "Domain liveness check", kbot_setup_check: "Kbot setup", git_init_check: "Initializing Git", - gitops_ready_check: "Initializing gitops", + gitops_ready_check: "Initializing GitOps", git_terraform_apply_check: "Git Terraform apply", - gitops_pushed_check: "Gitops repos pushed", + gitops_pushed_check: "GitOps repos pushed", cloud_terraform_apply_check: "Cloud Terraform apply", cluster_secrets_created_check: "Creating cluster secrets", - argocd_install_check: "Installing Argo CD", - argocd_initialize_check: "Initializing Argo CD", + argocd_install_check: "Installing ArgoCD", + argocd_initialize_check: "Initializing ArgoCD", vault_initialized_check: "Initializing Vault", vault_terraform_apply_check: "Vault Terraform apply", users_terraform_apply_check: "Users Terraform apply", diff --git a/internal/progress/message.go b/internal/progress/message.go index 05af7db78..497640791 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -56,7 +56,7 @@ func DisplayLogHints(estimatedTime int) { documentationLink := "https://docs.kubefirst.io/" if cloudProvider != "" { - documentationLink = documentationLink + cloudProvider + `/quick-start/install/cli` + documentationLink += cloudProvider + `/quick-start/install/cli` } header := ` @@ -85,39 +85,27 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { cloudCliKubeconfig := "" gitProviderLabel := "GitHub" - if cluster.GitProvider == "gitlab" { gitProviderLabel = "GitLab" } switch cluster.CloudProvider { case "aws": - cloudCliKubeconfig = fmt.Sprintf("aws eks update-kubeconfig --name %s --region %s", cluster.ClusterName, cluster.CloudRegion) - break - + cloudCliKubeconfig = fmt.Sprintf("aws eks update-kubeconfig --name %q --region %q", cluster.ClusterName, cluster.CloudRegion) case "civo": - cloudCliKubeconfig = fmt.Sprintf("civo kubernetes config %s --save", cluster.ClusterName) - break - + cloudCliKubeconfig = fmt.Sprintf("civo kubernetes config %q --save", cluster.ClusterName) case "digitalocean": cloudCliKubeconfig = "doctl kubernetes cluster kubeconfig save " + cluster.ClusterName - break - case "google": - cloudCliKubeconfig = fmt.Sprintf("gcloud container clusters get-credentials %s --region=%s", cluster.ClusterName, cluster.CloudRegion) - break - + cloudCliKubeconfig = fmt.Sprintf("gcloud container clusters get-credentials %q --region=%q", cluster.ClusterName, cluster.CloudRegion) case "vultr": - cloudCliKubeconfig = fmt.Sprintf("vultr-cli kubernetes config %s", cluster.ClusterName) - break - + cloudCliKubeconfig = fmt.Sprintf("vultr-cli kubernetes config %q", cluster.ClusterName) case "k3s": cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) break } var fullDomainName string - if cluster.SubdomainName != "" { fullDomainName = fmt.Sprintf("%s.%s", cluster.SubdomainName, cluster.DomainName) } else { @@ -128,7 +116,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { ## #### :tada: Success` + "`Cluster " + cluster.ClusterName + " is now up and running`" + ` -# Cluster ` + cluster.ClusterName + `” details: +# Cluster ` + cluster.ClusterName + ` details: ### :bulb: To retrieve root credentials for your Kubefirst platform run: ##### kubefirst ` + cluster.CloudProvider + ` root-credentials @@ -141,7 +129,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { ### URL ` + fmt.Sprintf("`https://kubefirst.%s`", fullDomainName) + ` ## Argo CD ### URL ` + fmt.Sprintf("`https://argocd.%s`", fullDomainName) + ` -## Vault +## Vault ### URL ` + fmt.Sprintf("`https://vault.%s`", fullDomainName) + ` @@ -153,6 +141,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { ### To view all cluster pods run: ##### kubectl get pods -A ` + successMessage := renderMessage(success) if !CanRunBubbleTea { diff --git a/internal/progress/progress.go b/internal/progress/progress.go index 08568b005..2ca6e2930 100644 --- a/internal/progress/progress.go +++ b/internal/progress/progress.go @@ -80,7 +80,6 @@ func (m progressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.provisioningCluster.Status == "error" { errorMessage := createErrorLog(m.provisioningCluster.LastCondition) m.error = errorMessage.message - return m, tea.Quit } diff --git a/internal/progress/styles.go b/internal/progress/styles.go index e1202e8f6..d9971d64f 100644 --- a/internal/progress/styles.go +++ b/internal/progress/styles.go @@ -1,6 +1,8 @@ package progress -import "github.com/charmbracelet/glamour/ansi" +import ( + "github.com/charmbracelet/glamour/ansi" +) var StyleConfig = ansi.StyleConfig{ Document: ansi.StyleBlock{ diff --git a/internal/progress/types.go b/internal/progress/types.go index 7ae7ae77e..6bf77b1c5 100644 --- a/internal/progress/types.go +++ b/internal/progress/types.go @@ -26,7 +26,7 @@ type progressModel struct { successMessage string } -// Bubbletea messsages +// Bubbletea messages type ClusterProvisioningMsg types.Cluster diff --git a/internal/provision/provision.go b/internal/provision/provision.go index 28db15cc1..a97b86e34 100644 --- a/internal/provision/provision.go +++ b/internal/provision/provision.go @@ -7,6 +7,8 @@ See the LICENSE file for more details. package provision import ( + "fmt" + apiTypes "github.com/konstructio/kubefirst-api/pkg/types" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/progress" @@ -15,7 +17,7 @@ import ( "github.com/rs/zerolog/log" ) -func CreateMgmtCluster(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags, catalogApps []apiTypes.GitopsCatalogApp) { +func CreateMgmtCluster(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags, catalogApps []apiTypes.GitopsCatalogApp) error { clusterRecord := utilities.CreateClusterDefinitionRecordFromRaw( gitAuth, cliFlags, @@ -24,20 +26,26 @@ func CreateMgmtCluster(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags, catalo clusterCreated, err := cluster.GetCluster(clusterRecord.ClusterName) if err != nil { - log.Info().Msg("cluster not found") + log.Printf("error retrieving cluster %q: %v", clusterRecord.ClusterName, err) + return fmt.Errorf("error retrieving cluster: %w", err) } if !clusterCreated.InProgress { err = cluster.CreateCluster(clusterRecord) if err != nil { progress.Error(err.Error()) + return fmt.Errorf("error creating cluster: %w", err) } } if clusterCreated.Status == "error" { cluster.ResetClusterProgress(clusterRecord.ClusterName) - cluster.CreateCluster(clusterRecord) + if err := cluster.CreateCluster(clusterRecord); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("error re-creating cluster after error state: %w", err) + } } progress.StartProvisioning(clusterRecord.ClusterName) + return nil } diff --git a/internal/provisionLogs/command.go b/internal/provisionLogs/command.go index 0d089f62e..e8b2c7393 100644 --- a/internal/provisionLogs/command.go +++ b/internal/provisionLogs/command.go @@ -39,11 +39,10 @@ func AddLog(logMsg string) { } else { parsedTime, err := time.Parse(time.RFC3339, log.Time) if err != nil { - fmt.Println("Error parsing date:", err) + fmt.Printf("error parsing date: %v\n", err) return } - // Format the parsed time into the desired format formattedDateStr := parsedTime.Format("2006-01-02 15:04:05") timeLog := timeStyle(formattedDateStr) diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go new file mode 100644 index 000000000..1b5ec5043 --- /dev/null +++ b/internal/provisionLogs/message.go @@ -0,0 +1,33 @@ +/* +Copyright (C) 2021-2023, Kubefirst + +This program is licensed under MIT. +See the LICENSE file for more details. + +Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go +Color definition https://www.ditig.com/256-colors-cheat-sheet +*/ +package provisionLogs + +import ( + "fmt" + "log" + + "github.com/charmbracelet/glamour" + "github.com/konstructio/kubefirst/internal/progress" +) + +func renderMessage(message string) string { + r, _ := glamour.NewTermRenderer( + glamour.WithStyles(progress.StyleConfig), + glamour.WithEmoji(), + ) + + out, err := r.Render(message) + if err != nil { + s := fmt.Errorf("rendering message failed: %w", err) + log.Println(s) + return s.Error() + } + return out +} diff --git a/internal/provisionLogs/provisionLogs.go b/internal/provisionLogs/provisionLogs.go index c3648b2b6..4b63fb7e5 100644 --- a/internal/provisionLogs/provisionLogs.go +++ b/internal/provisionLogs/provisionLogs.go @@ -50,7 +50,7 @@ func (m provisionLogsModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m provisionLogsModel) View() string { logs := "" for i := 0; i < len(m.logs); i++ { - logs = logs + m.logs[i] + "\n" + logs += m.logs[i] + "\n" } return logs + "\n" + quitStyle("ctrl+c to quit") + "\n" diff --git a/internal/provisionLogs/types.go b/internal/provisionLogs/types.go index e8a69e131..a67905f25 100644 --- a/internal/provisionLogs/types.go +++ b/internal/provisionLogs/types.go @@ -11,7 +11,7 @@ type provisionLogsModel struct { logs []string } -// Bubbletea messsages +// Bubbletea messages type logMessage struct { message string } diff --git a/internal/segment/segment.go b/internal/segment/segment.go index c2f2120f3..927b7c3ef 100644 --- a/internal/segment/segment.go +++ b/internal/segment/segment.go @@ -1,6 +1,7 @@ package segment import ( + "fmt" "os" "github.com/denisbrodbeck/machineid" @@ -13,8 +14,11 @@ const ( kubefirstClient string = "api" ) -func InitClient(clusterId, clusterType, gitProvider string) telemetry.TelemetryEvent { - machineID, _ := machineid.ID() +func InitClient(clusterId, clusterType, gitProvider string) (telemetry.TelemetryEvent, error) { + machineID, err := machineid.ID() + if err != nil { + return telemetry.TelemetryEvent{}, fmt.Errorf("failed to get machine ID: %w", err) + } c := telemetry.TelemetryEvent{ CliVersion: configs.K1Version, @@ -33,5 +37,5 @@ func InitClient(clusterId, clusterType, gitProvider string) telemetry.TelemetryE UserId: machineID, } - return c + return c, nil } diff --git a/internal/utilities/flags.go b/internal/utilities/flags.go index 13daceaa2..ed0ff19ce 100644 --- a/internal/utilities/flags.go +++ b/internal/utilities/flags.go @@ -7,126 +7,127 @@ See the LICENSE file for more details. package utilities import ( + "fmt" "strings" "github.com/konstructio/kubefirst/internal/progress" "github.com/konstructio/kubefirst/internal/types" - "github.com/spf13/cobra" "github.com/spf13/viper" ) func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) { cliFlags := types.CliFlags{} + alertsEmailFlag, err := cmd.Flags().GetString("alerts-email") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get alerts-email flag: %w", err) } cloudRegionFlag, err := cmd.Flags().GetString("cloud-region") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get cloud-region flag: %w", err) } clusterNameFlag, err := cmd.Flags().GetString("cluster-name") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get cluster-name flag: %w", err) } dnsProviderFlag, err := cmd.Flags().GetString("dns-provider") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get dns-provider flag: %w", err) } subdomainFlag, err := cmd.Flags().GetString("subdomain") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get subdomain flag: %w", err) } domainNameFlag, err := cmd.Flags().GetString("domain-name") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get domain-name flag: %w", err) } githubOrgFlag, err := cmd.Flags().GetString("github-org") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get github-org flag: %w", err) } githubOrgFlag = strings.ToLower(githubOrgFlag) gitlabGroupFlag, err := cmd.Flags().GetString("gitlab-group") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get gitlab-group flag: %w", err) } gitlabGroupFlag = strings.ToLower(gitlabGroupFlag) gitProviderFlag, err := cmd.Flags().GetString("git-provider") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get git-provider flag: %w", err) } gitProtocolFlag, err := cmd.Flags().GetString("git-protocol") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get git-protocol flag: %w", err) } gitopsTemplateURLFlag, err := cmd.Flags().GetString("gitops-template-url") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get gitops-template-url flag: %w", err) } gitopsTemplateBranchFlag, err := cmd.Flags().GetString("gitops-template-branch") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get gitops-template-branch flag: %w", err) } useTelemetryFlag, err := cmd.Flags().GetBool("use-telemetry") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get use-telemetry flag: %w", err) } nodeTypeFlag, err := cmd.Flags().GetString("node-type") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get node-type flag: %w", err) } installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get install-catalog-apps flag: %w", err) } nodeCountFlag, err := cmd.Flags().GetString("node-count") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get node-count flag: %w", err) } installKubefirstProFlag, err := cmd.Flags().GetBool("install-kubefirst-pro") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get install-kubefirst-pro flag: %w", err) } if cloudProvider == "aws" { ecrFlag, err := cmd.Flags().GetBool("ecr") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get ecr flag: %w", err) } cliFlags.Ecr = ecrFlag @@ -136,46 +137,45 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) googleProject, err := cmd.Flags().GetString("google-project") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get google-project flag: %w", err) } cliFlags.GoogleProject = googleProject } - // TODO: reafactor this part if cloudProvider == "k3s" { k3sServersPrivateIps, err := cmd.Flags().GetStringSlice("servers-private-ips") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get servers-private-ips flag: %w", err) } cliFlags.K3sServersPrivateIps = k3sServersPrivateIps k3sServersPublicIps, err := cmd.Flags().GetStringSlice("servers-public-ips") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get servers-public-ips flag: %w", err) } cliFlags.K3sServersPublicIps = k3sServersPublicIps k3sSshUserFlag, err := cmd.Flags().GetString("ssh-user") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get ssh-user flag: %w", err) } cliFlags.K3sSshUser = k3sSshUserFlag k3sSshPrivateKeyFlag, err := cmd.Flags().GetString("ssh-privatekey") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get ssh-privatekey flag: %w", err) } cliFlags.K3sSshPrivateKey = k3sSshPrivateKeyFlag K3sServersArgsFlags, err := cmd.Flags().GetStringSlice("servers-args") if err != nil { progress.Error(err.Error()) - return cliFlags, err + return cliFlags, fmt.Errorf("failed to get servers-args flag: %w", err) } cliFlags.K3sServersArgs = K3sServersArgsFlags } @@ -214,7 +214,9 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) viper.Set("flags.ssh-privatekey", cliFlags.K3sSshPrivateKey) viper.Set("flags.servers-args", cliFlags.K3sServersArgs) } - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return cliFlags, fmt.Errorf("failed to write configuration: %w", err) + } return cliFlags, nil } diff --git a/internal/utilities/utilities.go b/internal/utilities/utilities.go index a174be65e..01e8dfa6e 100644 --- a/internal/utilities/utilities.go +++ b/internal/utilities/utilities.go @@ -32,12 +32,14 @@ func CreateK1ClusterDirectory(clusterName string) { homePath, err := os.UserHomeDir() if err != nil { log.Info().Msg(err.Error()) + return } + k1Dir := fmt.Sprintf("%s/.k1/%s", homePath, clusterName) if _, err := os.Stat(k1Dir); os.IsNotExist(err) { err := os.MkdirAll(k1Dir, os.ModePerm) if err != nil { - log.Info().Msgf("%s directory already exists, continuing", k1Dir) + log.Info().Msgf("%q directory already exists, continuing", k1Dir) } } } @@ -102,7 +104,6 @@ func CreateClusterRecordFromRaw( case "civo": cl.CivoAuth.Token = os.Getenv("CIVO_TOKEN") case "aws": - // ToDo: where to get credentials? cl.AWSAuth.AccessKeyID = viper.GetString("kubefirst.state-store-creds.access-key-id") cl.AWSAuth.SecretAccessKey = viper.GetString("kubefirst.state-store-creds.secret-access-key-id") cl.AWSAuth.SessionToken = viper.GetString("kubefirst.state-store-creds.token") @@ -187,7 +188,6 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ case "akamai": cl.AkamaiAuth.Token = os.Getenv("LINODE_TOKEN") case "aws": - // ToDo: where to get credentials? cl.AWSAuth.AccessKeyID = viper.GetString("kubefirst.state-store-creds.access-key-id") cl.AWSAuth.SecretAccessKey = viper.GetString("kubefirst.state-store-creds.secret-access-key-id") cl.AWSAuth.SessionToken = viper.GetString("kubefirst.state-store-creds.token") @@ -211,11 +211,16 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ jsonFile, err := os.Open(jsonFilePath) if err != nil { - progress.Error("Unable to read GOOGLE_APPLICATION_CREDENTIALS file") + progress.Error(fmt.Sprintf("unable to read GOOGLE_APPLICATION_CREDENTIALS file: %s", err)) + return apiTypes.ClusterDefinition{} } defer jsonFile.Close() - jsonContent, _ := ioutil.ReadAll(jsonFile) + jsonContent, err := io.ReadAll(jsonFile) + if err != nil { + progress.Error(fmt.Sprintf("unable to read GOOGLE_APPLICATION_CREDENTIALS file content: %s", err)) + return apiTypes.ClusterDefinition{} + } cl.GoogleAuth.KeyFile = string(jsonContent) cl.GoogleAuth.ProjectId = cliFlags.GoogleProject @@ -236,11 +241,13 @@ func ExportCluster(cluster apiTypes.Cluster, kcfg *k8s.KubernetesClient) error { bytes, err := json.Marshal(cluster) if err != nil { - log.Error().Msg(err.Error()) - return err + return fmt.Errorf("error marshaling cluster: %w", err) } - secretValuesMap, _ := ParseJSONToMap(string(bytes)) + secretValuesMap, err := ParseJSONToMap(string(bytes)) + if err != nil { + return fmt.Errorf("error parsing JSON to map: %w", err) + } secret := &v1secret.Secret{ ObjectMeta: metav1.ObjectMeta{Name: "kubefirst-initial-state", Namespace: "kubefirst"}, @@ -249,20 +256,22 @@ func ExportCluster(cluster apiTypes.Cluster, kcfg *k8s.KubernetesClient) error { err = k8s.CreateSecretV2(kcfg.Clientset, secret) if err != nil { - return fmt.Errorf(fmt.Sprintf("unable to save secret to management cluster. %s", err)) + return fmt.Errorf("unable to save secret to management cluster: %w", err) } viper.Set("kubefirst-checks.secret-export-state", true) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("error writing config: %w", err) + } return nil } func ParseJSONToMap(jsonStr string) (map[string][]byte, error) { var result map[string]interface{} - err := json.Unmarshal([]byte(jsonStr), &result) - if err != nil { - return nil, err + + if err := json.Unmarshal([]byte(jsonStr), &result); err != nil { + return nil, fmt.Errorf("error unmarshaling JSON: %w", err) } secretData := make(map[string][]byte) @@ -271,13 +280,13 @@ func ParseJSONToMap(jsonStr string) (map[string][]byte, error) { case map[string]interface{}, []interface{}: // For nested structures, marshal back to JSON bytes, err := json.Marshal(v) if err != nil { - return nil, err + return nil, fmt.Errorf("error marshaling value for key %q: %w", key, err) } secretData[key] = bytes default: bytes, err := json.Marshal(v) if err != nil { - return nil, err + return nil, fmt.Errorf("error marshaling value for key %q: %w", key, err) } secretData[key] = bytes } From c9b6905e94153e66f555a335b9345cfd4bd7025e Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:06:51 -0400 Subject: [PATCH 55/85] Fix compilation --- cmd/k3d/create.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 5eb6df74b..1d55f5965 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -278,7 +278,10 @@ func runK3d(cmd *cobra.Command, args []string) error { viper.WriteConfig() } - segClient := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) + segClient, err := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) + if err != nil { + return fmt.Errorf("failed to initialize segment client: %w", err) + } progressPrinter.AddTracker("preflight-checks", "Running preflight checks", 5) progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) From 97caaf4906d93c389ce38479820c623bfcd30089 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:39:03 -0400 Subject: [PATCH 56/85] Update using final standard linters --- cmd/akamai/command.go | 2 +- cmd/akamai/create.go | 4 +- cmd/aws/command.go | 2 +- cmd/aws/create.go | 4 +- cmd/beta.go | 2 +- cmd/civo/backup.go | 2 +- cmd/civo/command.go | 2 +- cmd/civo/create.go | 4 +- cmd/civo/quota.go | 2 +- cmd/digitalocean/command.go | 2 +- cmd/digitalocean/create.go | 4 +- cmd/google/command.go | 2 +- cmd/google/create.go | 6 +- cmd/info.go | 2 +- cmd/k3d/command.go | 2 +- cmd/k3d/create.go | 87 ++++++++++++----------- cmd/k3d/vault.go | 2 +- cmd/k3s/command.go | 8 +-- cmd/k3s/create.go | 6 +- cmd/launch.go | 6 +- cmd/letsencrypt.go | 2 +- cmd/logs.go | 2 +- cmd/reset.go | 2 +- cmd/root.go | 2 +- cmd/terraform.go | 2 +- cmd/version.go | 2 + cmd/vultr/command.go | 2 +- cmd/vultr/create.go | 5 +- internal/cluster/cluster.go | 17 ++--- internal/common/common.go | 6 +- internal/gitShim/containerRegistryAuth.go | 2 +- internal/gitShim/init.go | 2 +- internal/helm/types.go | 4 +- internal/k3d/menu.go | 8 +-- internal/launch/cmd.go | 12 ++-- internal/progress/command.go | 62 ++++++++-------- internal/progress/constants.go | 50 ++++--------- internal/progress/message.go | 1 + internal/progress/progress.go | 5 +- internal/progress/types.go | 28 ++++---- internal/provisionLogs/command.go | 2 +- internal/provisionLogs/message.go | 33 --------- internal/provisionLogs/provisionLogs.go | 3 +- internal/provisionLogs/types.go | 2 +- internal/segment/segment.go | 4 +- internal/types/flags.go | 12 ++-- internal/types/proxy.go | 4 +- internal/utilities/flags.go | 26 +++---- internal/utilities/utilities.go | 6 +- main.go | 40 +++++------ 50 files changed, 227 insertions(+), 272 deletions(-) delete mode 100644 internal/provisionLogs/message.go diff --git a/cmd/akamai/command.go b/cmd/akamai/command.go index a8c5dc8f8..e57969a15 100644 --- a/cmd/akamai/command.go +++ b/cmd/akamai/command.go @@ -54,7 +54,7 @@ func NewCommand() *cobra.Command { Use: "akamai", Short: "kubefirst akamai installation", Long: "kubefirst akamai", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about akamai in kubefirst, run:") fmt.Println(" kubefirst beta akamai --help") diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index b8a93a668..d5a0a4a6d 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -25,7 +25,7 @@ import ( "github.com/spf13/viper" ) -func createAkamai(cmd *cobra.Command, args []string) error { +func createAkamai(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "akamai") if err != nil { progress.Error(err.Error()) @@ -84,7 +84,7 @@ func createAkamai(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check kubefirst api availability: %w", err) diff --git a/cmd/aws/command.go b/cmd/aws/command.go index 86c6187be..73e8e4ee9 100644 --- a/cmd/aws/command.go +++ b/cmd/aws/command.go @@ -49,7 +49,7 @@ func NewCommand() *cobra.Command { Use: "aws", Short: "kubefirst aws installation", Long: "kubefirst aws", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about aws in kubefirst, run:") fmt.Println(" kubefirst help") diff --git a/cmd/aws/create.go b/cmd/aws/create.go index 4c9a00ef6..a19203af0 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -27,7 +27,7 @@ import ( "github.com/spf13/viper" ) -func createAws(cmd *cobra.Command, args []string) error { +func createAws(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "aws") if err != nil { progress.Error(err.Error()) @@ -118,7 +118,7 @@ func createAws(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check kubefirst API availability: %w", err) diff --git a/cmd/beta.go b/cmd/beta.go index 395311dac..9afd9155a 100644 --- a/cmd/beta.go +++ b/cmd/beta.go @@ -22,7 +22,7 @@ var betaCmd = &cobra.Command{ Use: "beta", Short: "access Kubefirst beta features", Long: `access Kubefirst beta features`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about Kubefirst, run:") fmt.Println(" kubefirst help") diff --git a/cmd/civo/backup.go b/cmd/civo/backup.go index 74d37e685..c6694f659 100644 --- a/cmd/civo/backup.go +++ b/cmd/civo/backup.go @@ -18,7 +18,7 @@ import ( "github.com/spf13/viper" ) -func backupCivoSSL(cmd *cobra.Command, _ []string) error { +func backupCivoSSL(_ *cobra.Command, _ []string) error { utils.DisplayLogHints() clusterName := viper.GetString("flags.cluster-name") diff --git a/cmd/civo/command.go b/cmd/civo/command.go index 02e170090..fac376788 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -54,7 +54,7 @@ func NewCommand() *cobra.Command { Use: "civo", Short: "Kubefirst Civo installation", Long: "Kubefirst Civo", - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about Civo in Kubefirst, run:") fmt.Println(" kubefirst civo --help") diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 85ae585f4..ffec64472 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/viper" ) -func createCivo(cmd *cobra.Command, args []string) error { +func createCivo(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "civo") if err != nil { progress.Error(err.Error()) @@ -85,7 +85,7 @@ func createCivo(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("API availability check failed: %w", err) diff --git a/cmd/civo/quota.go b/cmd/civo/quota.go index a5d129d6d..e171f2fe0 100644 --- a/cmd/civo/quota.go +++ b/cmd/civo/quota.go @@ -165,7 +165,7 @@ func printCivoQuotaWarning(messageHeader string, output []string) string { } // evalCivoQuota provides an interface to the command-line -func evalCivoQuota(cmd *cobra.Command, args []string) error { +func evalCivoQuota(cmd *cobra.Command, _ []string) error { civoToken := os.Getenv("CIVO_TOKEN") if len(civoToken) == 0 { return fmt.Errorf("your CIVO_TOKEN environment variable isn't set, visit this link https://dashboard.civo.com/security and set CIVO_TOKEN") diff --git a/cmd/digitalocean/command.go b/cmd/digitalocean/command.go index ff97cffe5..e1e854a87 100644 --- a/cmd/digitalocean/command.go +++ b/cmd/digitalocean/command.go @@ -54,7 +54,7 @@ func NewCommand() *cobra.Command { Use: "digitalocean", Short: "Kubefirst DigitalOcean installation", Long: "Kubefirst DigitalOcean", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about DigitalOcean in Kubefirst, run:") fmt.Println(" kubefirst digitalocean --help") diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index 3c705b0f0..a600c6199 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -26,7 +26,7 @@ import ( "github.com/spf13/viper" ) -func createDigitalocean(cmd *cobra.Command, args []string) error { +func createDigitalocean(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "digitalocean") if err != nil { progress.Error(err.Error()) @@ -96,7 +96,7 @@ func createDigitalocean(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check app availability for Kubefirst API: %w", err) diff --git a/cmd/google/command.go b/cmd/google/command.go index 30588cf24..e4b8d98da 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -57,7 +57,7 @@ func NewCommand() *cobra.Command { Use: "google", Short: "kubefirst Google installation", Long: "kubefirst google", - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about google in kubefirst, run:") fmt.Println(" kubefirst beta google --help") diff --git a/cmd/google/create.go b/cmd/google/create.go index 087eb928f..00fd53dc2 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -23,10 +23,10 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - _ "k8s.io/client-go/plugin/pkg/client/auth" + _ "k8s.io/client-go/plugin/pkg/client/auth" // required for authentication ) -func createGoogle(cmd *cobra.Command, args []string) error { +func createGoogle(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "google") if err != nil { progress.Error(err.Error()) @@ -89,7 +89,7 @@ func createGoogle(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("kubefirst api availability check failed: %w", err) diff --git a/cmd/info.go b/cmd/info.go index 5b6cc2e4e..8581cd3f2 100755 --- a/cmd/info.go +++ b/cmd/info.go @@ -22,7 +22,7 @@ var infoCmd = &cobra.Command{ Use: "info", Short: "provides general Kubefirst setup data", Long: `Provides machine data, files and folders paths`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { config := configs.ReadConfig() var buf bytes.Buffer diff --git a/cmd/k3d/command.go b/cmd/k3d/command.go index 13bc7422d..5417f7678 100644 --- a/cmd/k3d/command.go +++ b/cmd/k3d/command.go @@ -48,7 +48,7 @@ func NewCommand() *cobra.Command { Use: "k3d", Short: "kubefirst k3d installation", Long: "kubefirst k3d", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about k3d in kubefirst, run:") fmt.Println(" kubefirst k3d --help") diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index 1d55f5965..f70fefb4a 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -56,7 +56,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" ) -func runK3d(cmd *cobra.Command, args []string) error { +//nolint:gocyclo // this function is complex and needs to be refactored +func runK3d(cmd *cobra.Command, _ []string) error { ciFlag, err := cmd.Flags().GetBool("ci") if err != nil { return fmt.Errorf("failed to get 'ci' flag: %w", err) @@ -121,8 +122,12 @@ func runK3d(cmd *cobra.Command, args []string) error { utils.DisplayLogHints() isValid, catalogApps, err := catalog.ValidateCatalogApps(installCatalogAppsFlag) + if err != nil { + return fmt.Errorf("failed to validate catalog apps: %w", err) + } + if !isValid { - return err + return errors.New("catalog apps validation failed") } switch gitProviderFlag { @@ -271,14 +276,14 @@ func runK3d(cmd *cobra.Command, args []string) error { var sshPrivateKey, sshPublicKey string // todo placed in configmap in kubefirst namespace, included in telemetry - clusterId := viper.GetString("kubefirst.cluster-id") - if clusterId == "" { - clusterId = utils.GenerateClusterID() - viper.Set("kubefirst.cluster-id", clusterId) + clusterID := viper.GetString("kubefirst.cluster-id") + if clusterID == "" { + clusterID = utils.GenerateClusterID() + viper.Set("kubefirst.cluster-id", clusterID) viper.WriteConfig() } - segClient, err := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) + segClient, err := segment.InitClient(clusterID, clusterTypeFlag, gitProviderFlag) if err != nil { return fmt.Errorf("failed to initialize segment client: %w", err) } @@ -438,7 +443,7 @@ func runK3d(cmd *cobra.Command, args []string) error { KubeconfigPath: config.Kubeconfig, GitopsRepoURL: gitopsRepoURL, GitProvider: config.GitProvider, - ClusterId: clusterId, + ClusterId: clusterID, CloudProvider: k3d.CloudProvider, } @@ -642,7 +647,7 @@ func runK3d(cmd *cobra.Command, args []string) error { msg := fmt.Errorf("error pushing detokenized gitops repository to remote %q: %w", config.DestinationGitopsRepoGitURL, err) telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) if !strings.Contains(msg.Error(), "already up-to-date") { - log.Printf(msg.Error()) + log.Print(msg.Error()) return msg } } @@ -867,12 +872,12 @@ func runK3d(cmd *cobra.Command, args []string) error { ) + ":8080" argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, argoCDHTTPURL, "admin", argocdPassword) if err != nil { - return err + return fmt.Errorf("failed to get ArgoCD token: %w", err) } } else { argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, k3d.ArgocdURL, "admin", argocdPassword) if err != nil { - return err + return fmt.Errorf("failed to get ArgoCD token: %w", err) } } @@ -1228,41 +1233,41 @@ func runK3d(cmd *cobra.Command, args []string) error { viper.Set("kubefirst-checks.cluster-install-complete", false) viper.WriteConfig() return fmt.Errorf("failed to export cluster object: %w", err) - } else { - kubefirstDeployment, err := k8s.ReturnDeploymentObject( - kcfg.Clientset, - "app.kubernetes.io/instance", - "kubefirst", - "kubefirst", - 600, - ) - if err != nil { - return fmt.Errorf("error finding kubefirst Deployment: %w", err) - } - _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, kubefirstDeployment, 120) - if err != nil { - return fmt.Errorf("error waiting for kubefirst Deployment ready state: %w", err) - } - progressPrinter.IncrementTracker("wrapping-up", 1) + } - err = utils.OpenBrowser(constants.KubefirstConsoleLocalURLTLS) - if err != nil { - log.Error().Err(err).Msg("failed to open Kubefirst console in browser") - } + kubefirstDeployment, err := k8s.ReturnDeploymentObject( + kcfg.Clientset, + "app.kubernetes.io/instance", + "kubefirst", + "kubefirst", + 600, + ) + if err != nil { + return fmt.Errorf("error finding kubefirst Deployment: %w", err) + } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, kubefirstDeployment, 120) + if err != nil { + return fmt.Errorf("error waiting for kubefirst Deployment ready state: %w", err) + } + progressPrinter.IncrementTracker("wrapping-up", 1) - telemetry.SendEvent(segClient, telemetry.ClusterInstallCompleted, "") - viper.Set("kubefirst-checks.cluster-install-complete", true) - viper.WriteConfig() + err = utils.OpenBrowser(constants.KubefirstConsoleLocalURLTLS) + if err != nil { + log.Error().Err(err).Msg("failed to open Kubefirst console in browser") + } - log.Info().Msg("kubefirst installation complete") - log.Info().Msg("welcome to your new Kubefirst platform running in K3D") - time.Sleep(1 * time.Second) + telemetry.SendEvent(segClient, telemetry.ClusterInstallCompleted, "") + viper.Set("kubefirst-checks.cluster-install-complete", true) + viper.WriteConfig() - reports.LocalHandoffScreenV2(viper.GetString("components.argocd.password"), clusterNameFlag, gitDestDescriptor, cGitOwner, config, ciFlag) + log.Info().Msg("kubefirst installation complete") + log.Info().Msg("welcome to your new Kubefirst platform running in K3D") + time.Sleep(1 * time.Second) - if ciFlag { - progress.Progress.Quit() - } + reports.LocalHandoffScreenV2(viper.GetString("components.argocd.password"), clusterNameFlag, gitDestDescriptor, cGitOwner, config, ciFlag) + + if ciFlag { + progress.Progress.Quit() } return nil diff --git a/cmd/k3d/vault.go b/cmd/k3d/vault.go index 485e49bbd..a044b1154 100644 --- a/cmd/k3d/vault.go +++ b/cmd/k3d/vault.go @@ -33,7 +33,7 @@ const ( secretThreshold = 3 ) -func unsealVault(cmd *cobra.Command, args []string) error { +func unsealVault(_ *cobra.Command, _ []string) error { flags := utils.GetClusterStatusFlags() if !flags.SetupComplete { return fmt.Errorf("failed to unseal vault: there doesn't appear to be an active k3d cluster") diff --git a/cmd/k3s/command.go b/cmd/k3s/command.go index c6d2d0ff4..c118f0f72 100644 --- a/cmd/k3s/command.go +++ b/cmd/k3s/command.go @@ -25,8 +25,8 @@ var ( clusterTypeFlag string k3sServersPrivateIpsFlag []string k3sServersPublicIpsFlag []string - k3sSshUserflag string - k3sSshPrivateKeyflag string + k3sSSHUserflag string + k3sSSHPrivateKeyflag string K3sServersArgsFlags []string dnsProviderFlag string subdomainNameFlag string @@ -93,8 +93,8 @@ func Create() *cobra.Command { createCmd.MarkFlagRequired("servers-private-ips") createCmd.Flags().StringSliceVar(&k3sServersPublicIpsFlag, "servers-public-ips", []string{}, "the list of k3s (servers) public ip x.x.x.x,y.y.y.y comma separated (required)") createCmd.Flags().StringSliceVar(&K3sServersArgsFlags, "servers-args", []string{"--disable traefik", "--write-kubeconfig-mode 644"}, "list of k3s extras args to add to the k3s server installation,comma separated in between quote, if --servers-public-ips --tls-san is added to default --servers-args") - createCmd.Flags().StringVar(&k3sSshUserflag, "ssh-user", "root", "the user used to log into servers with ssh connection") - createCmd.Flags().StringVar(&k3sSshPrivateKeyflag, "ssh-privatekey", "", "the private key used to log into servers with ssh connection") + createCmd.Flags().StringVar(&k3sSSHUserflag, "ssh-user", "root", "the user used to log into servers with ssh connection") + createCmd.Flags().StringVar(&k3sSSHPrivateKeyflag, "ssh-privatekey", "", "the private key used to log into servers with ssh connection") createCmd.MarkFlagRequired("ssh-privatekey") createCmd.Flags().StringVar(&dnsProviderFlag, "dns-provider", "cloudflare", fmt.Sprintf("the dns provider - one of: %q", supportedDNSProviders)) createCmd.Flags().StringVar(&subdomainNameFlag, "subdomain", "", "the subdomain to use for DNS records (Cloudflare)") diff --git a/cmd/k3s/create.go b/cmd/k3s/create.go index c1e87ae4f..ae7ce75c3 100644 --- a/cmd/k3s/create.go +++ b/cmd/k3s/create.go @@ -25,10 +25,10 @@ import ( "github.com/konstructio/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" - _ "k8s.io/client-go/plugin/pkg/client/auth" + _ "k8s.io/client-go/plugin/pkg/client/auth" // required for k8s authentication ) -func createK3s(cmd *cobra.Command, args []string) error { +func createK3s(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "k3s") if err != nil { progress.Error(err.Error()) @@ -99,7 +99,7 @@ func createK3s(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("app availability check failed: %w", err) diff --git a/cmd/launch.go b/cmd/launch.go index 2c1f10a78..d05d6627c 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -38,7 +38,7 @@ func launchUp() *cobra.Command { Use: "up", Short: "launch new console and api instance", TraverseChildren: true, - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { launch.Up(additionalHelmFlags, false, true) }, } @@ -54,7 +54,7 @@ func launchDown() *cobra.Command { Use: "down", Short: "remove console and api instance", TraverseChildren: true, - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { launch.Down(false) }, } @@ -81,7 +81,7 @@ func launchListClusters() *cobra.Command { Use: "list", Short: "list clusters created by the Kubefirst console", TraverseChildren: true, - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { launch.ListClusters() }, } diff --git a/cmd/letsencrypt.go b/cmd/letsencrypt.go index 1075338cf..1a1071d5e 100644 --- a/cmd/letsencrypt.go +++ b/cmd/letsencrypt.go @@ -35,7 +35,7 @@ func status() *cobra.Command { Use: "status", Short: "check the usage statistics for a LetsEncrypt certificate", TraverseChildren: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { if err := certificates.CheckCertificateUsage(domainNameFlag); err != nil { fmt.Printf("failed to check certificate usage for domain %q: %s\n", domainNameFlag, err) } diff --git a/cmd/logs.go b/cmd/logs.go index 24355df02..426db0374 100755 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -21,7 +21,7 @@ var logsCmd = &cobra.Command{ Use: "logs", Short: "kubefirst real time logs", Long: `kubefirst real time logs`, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(_ *cobra.Command, _ []string) error { provisionLogs.InitializeProvisionLogsTerminal() go func() { diff --git a/cmd/reset.go b/cmd/reset.go index 7db72b6fc..399ddb8ea 100755 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -25,7 +25,7 @@ var resetCmd = &cobra.Command{ Use: "reset", Short: "removes local kubefirst content to provision a new platform", Long: "removes local kubefirst content to provision a new platform", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { gitProvider := viper.GetString("kubefirst.git-provider") cloudProvider := viper.GetString("kubefirst.cloud-provider") diff --git a/cmd/root.go b/cmd/root.go index 36411b4e7..88659b299 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,7 +31,7 @@ var rootCmd = &cobra.Command{ // wire viper config for flags for all commands return configs.InitializeViperConfig(cmd) }, - Run: func(cmd *cobra.Command, _ []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about kubefirst, run:") fmt.Println(" kubefirst help") progress.Progress.Quit() diff --git a/cmd/terraform.go b/cmd/terraform.go index 54f75cd50..ec50bedb8 100644 --- a/cmd/terraform.go +++ b/cmd/terraform.go @@ -40,7 +40,7 @@ func terraformSetEnv() *cobra.Command { Use: "set-env", Short: "retrieve data from a target vault secret and format it for use in the local shell via environment variables", TraverseChildren: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { v := vault.VaultConfiguration{ Config: vault.NewVault(), } diff --git a/cmd/version.go b/cmd/version.go index 17ddf79c5..f32fd475d 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -7,6 +7,8 @@ See the LICENSE file for more details. package cmd import ( + "fmt" + "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" diff --git a/cmd/vultr/command.go b/cmd/vultr/command.go index bf3109fce..511d27972 100644 --- a/cmd/vultr/command.go +++ b/cmd/vultr/command.go @@ -54,7 +54,7 @@ func NewCommand() *cobra.Command { Use: "vultr", Short: "Kubefirst Vultr installation", Long: "kubefirst vultr", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println("To learn more about Vultr in Kubefirst, run:") fmt.Println(" kubefirst beta vultr --help") diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 26a4233da..5066b5c29 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -22,12 +22,11 @@ import ( "github.com/konstructio/kubefirst/internal/provision" "github.com/konstructio/kubefirst/internal/utilities" "github.com/rs/zerolog/log" - "github.com/spf13/cobra" "github.com/spf13/viper" ) -func createVultr(cmd *cobra.Command, args []string) error { +func createVultr(cmd *cobra.Command, _ []string) error { cliFlags, err := utilities.GetFlags(cmd, "vultr") if err != nil { progress.Error(err.Error()) @@ -97,7 +96,7 @@ func createVultr(cmd *cobra.Command, args []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresUrl()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("kubefirst api availability check failed: %w", err) diff --git a/internal/cluster/cluster.go b/internal/cluster/cluster.go index f34b22518..e9630376f 100644 --- a/internal/cluster/cluster.go +++ b/internal/cluster/cluster.go @@ -21,7 +21,7 @@ import ( "github.com/konstructio/kubefirst/internal/types" ) -func GetConsoleIngresUrl() string { +func GetConsoleIngresURL() string { if strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" { // allow using local console running on port 3000 return os.Getenv("K1_CONSOLE_REMOTE_URL") } @@ -35,7 +35,7 @@ func CreateCluster(cluster apiTypes.ClusterDefinition) error { requestObject := types.ProxyCreateClusterRequest{ Body: cluster, - Url: fmt.Sprintf("/cluster/%s", cluster.ClusterName), + URL: fmt.Sprintf("/cluster/%s", cluster.ClusterName), } payload, err := json.Marshal(requestObject) @@ -43,7 +43,7 @@ func CreateCluster(cluster apiTypes.ClusterDefinition) error { return fmt.Errorf("failed to marshal request object: %w", err) } - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresUrl()), bytes.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresURL()), bytes.NewReader(payload)) if err != nil { log.Printf("error creating request: %s", err) return fmt.Errorf("failed to create request: %w", err) @@ -79,7 +79,7 @@ func ResetClusterProgress(clusterName string) error { httpClient := http.Client{Transport: customTransport} requestObject := types.ProxyResetClusterRequest{ - Url: fmt.Sprintf("/cluster/%s/reset_progress", clusterName), + URL: fmt.Sprintf("/cluster/%s/reset_progress", clusterName), } payload, err := json.Marshal(requestObject) @@ -87,7 +87,7 @@ func ResetClusterProgress(clusterName string) error { return fmt.Errorf("failed to marshal request object: %w", err) } - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresUrl()), bytes.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresURL()), bytes.NewReader(payload)) if err != nil { log.Printf("error creating request: %v", err) return fmt.Errorf("failed to create request: %w", err) @@ -122,7 +122,7 @@ func GetCluster(clusterName string) (apiTypes.Cluster, error) { httpClient := http.Client{Transport: customTransport} cluster := apiTypes.Cluster{} - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresUrl(), clusterName), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresURL(), clusterName), nil) if err != nil { log.Printf("error creating request: %v", err) return cluster, fmt.Errorf("failed to create request: %w", err) @@ -162,7 +162,7 @@ func GetClusters() ([]apiTypes.Cluster, error) { httpClient := http.Client{Transport: customTransport} clusters := []apiTypes.Cluster{} - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster", GetConsoleIngresUrl()), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster", GetConsoleIngresURL()), nil) if err != nil { log.Printf("error creating request: %v", err) return clusters, fmt.Errorf("failed to create request: %w", err) @@ -201,7 +201,7 @@ func DeleteCluster(clusterName string) error { customTransport := http.DefaultTransport.(*http.Transport).Clone() httpClient := http.Client{Transport: customTransport} - req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresUrl(), clusterName), nil) + req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresURL(), clusterName), nil) if err != nil { log.Printf("error creating request: %v", err) return fmt.Errorf("failed to create request: %w", err) @@ -214,6 +214,7 @@ func DeleteCluster(clusterName string) error { log.Printf("error executing request: %v", err) return fmt.Errorf("failed to execute request: %w", err) } + defer res.Body.Close() if res.StatusCode != http.StatusOK { log.Printf("unable to delete cluster: %q, continuing", res.Status) diff --git a/internal/common/common.go b/internal/common/common.go index c42193404..3c4c6055c 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -57,7 +57,7 @@ func CheckForVersionUpdate() { } // versionCheck compares local to remote version -func versionCheck() (res *CheckResponse, skip bool) { +func versionCheck() (*CheckResponse, bool) { var latestVersion string flatVersion := strings.ReplaceAll(configs.K1Version, "v", "") @@ -125,7 +125,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { return nil } -func Destroy(cmd *cobra.Command, args []string) error { +func Destroy(_ *cobra.Command, _ []string) error { // Determine if there are active installs gitProvider := viper.GetString("flags.git-provider") gitProtocol := viper.GetString("flags.git-protocol") @@ -137,7 +137,7 @@ func Destroy(cmd *cobra.Command, args []string) error { domainName := viper.GetString("flags.domain-name") // Switch based on git provider, set params - cGitOwner := "" + var cGitOwner string switch gitProvider { case "github": cGitOwner = viper.GetString("flags.github-owner") diff --git a/internal/gitShim/containerRegistryAuth.go b/internal/gitShim/containerRegistryAuth.go index 8d69cd58e..6a0b64847 100644 --- a/internal/gitShim/containerRegistryAuth.go +++ b/internal/gitShim/containerRegistryAuth.go @@ -4,7 +4,7 @@ Copyright (C) 2021-2023, Kubefirst This program is licensed under MIT. See the LICENSE file for more details. */ -package gitShim +package gitShim //nolint:revive // allowed during refactoring import ( "encoding/base64" diff --git a/internal/gitShim/init.go b/internal/gitShim/init.go index 124bffe77..c60a05a7f 100644 --- a/internal/gitShim/init.go +++ b/internal/gitShim/init.go @@ -4,7 +4,7 @@ Copyright (C) 2021-2023, Kubefirst This program is licensed under MIT. See the LICENSE file for more details. */ -package gitShim +package gitShim //nolint:revive // allowed during refactoring import ( "errors" diff --git a/internal/helm/types.go b/internal/helm/types.go index 66405985c..1845390c8 100644 --- a/internal/helm/types.go +++ b/internal/helm/types.go @@ -6,12 +6,12 @@ See the LICENSE file for more details. */ package helm -type HelmRepo struct { +type Repo struct { Name string `yaml:"name"` URL string `yaml:"url"` } -type HelmRelease struct { +type Release struct { AppVersion string `yaml:"app_version"` Chart string `yaml:"chart"` Name string `yaml:"name"` diff --git a/internal/k3d/menu.go b/internal/k3d/menu.go index 76ccc29c9..662ba587a 100644 --- a/internal/k3d/menu.go +++ b/internal/k3d/menu.go @@ -37,9 +37,9 @@ func (i Item) FilterValue() string { return "" } type ItemDelegate struct{} -func (d ItemDelegate) Height() int { return 1 } -func (d ItemDelegate) Spacing() int { return 0 } -func (d ItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } +func (d ItemDelegate) Height() int { return 1 } +func (d ItemDelegate) Spacing() int { return 0 } +func (d ItemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } func (d ItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { i, ok := listItem.(Item) if !ok { @@ -104,7 +104,7 @@ func (m Model) View() string { return "\n" + m.List.View() } -func MongoDestinationChooser(inCluster bool) (result string, err error) { +func MongoDestinationChooser(inCluster bool) (string, error) { if inCluster { return "in-cluster", nil } diff --git a/internal/launch/cmd.go b/internal/launch/cmd.go index 3ccb0a9b8..0463dde9e 100644 --- a/internal/launch/cmd.go +++ b/internal/launch/cmd.go @@ -73,13 +73,13 @@ func Up(additionalHelmFlags []string, inCluster, useTelemetry bool) { _, err = os.Stat(k3dClient) if err != nil { log.Info().Msg("Downloading k3d...") - k3dDownloadUrl := fmt.Sprintf( + k3dDownloadURL := fmt.Sprintf( "https://github.com/k3d-io/k3d/releases/download/%s/k3d-%s-%s", k3d.K3dVersion, k3d.LocalhostOS, k3d.LocalhostARCH, ) - err = downloadManager.DownloadFile(k3dClient, k3dDownloadUrl) + err = downloadManager.DownloadFile(k3dClient, k3dDownloadURL) if err != nil { progress.Error(fmt.Sprintf("error while trying to download k3d: %s", err)) return @@ -100,14 +100,14 @@ func Up(additionalHelmFlags []string, inCluster, useTelemetry bool) { if err != nil { log.Info().Msg("Downloading helm...") helmVersion := "v3.12.0" - helmDownloadUrl := fmt.Sprintf( + helmDownloadURL := fmt.Sprintf( "https://get.helm.sh/helm-%s-%s-%s.tar.gz", helmVersion, k3d.LocalhostOS, k3d.LocalhostARCH, ) helmDownloadTarGzPath := fmt.Sprintf("%s/helm.tar.gz", toolsDir) - err = downloadManager.DownloadFile(helmDownloadTarGzPath, helmDownloadUrl) + err = downloadManager.DownloadFile(helmDownloadTarGzPath, helmDownloadURL) if err != nil { progress.Error(fmt.Sprintf("error while trying to download helm: %s", err)) return @@ -223,7 +223,7 @@ func Up(additionalHelmFlags []string, inCluster, useTelemetry bool) { return } - var existingHelmRepositories []helm.HelmRepo + var existingHelmRepositories []helm.Repo repoExists := false err = yaml.Unmarshal([]byte(res), &existingHelmRepositories) @@ -283,7 +283,7 @@ func Up(additionalHelmFlags []string, inCluster, useTelemetry bool) { return } - var existingHelmReleases []helm.HelmRelease + var existingHelmReleases []helm.Release chartInstalled := false err = yaml.Unmarshal([]byte(res), &existingHelmReleases) diff --git a/internal/progress/command.go b/internal/progress/command.go index 2483cb16c..64d3e1477 100644 --- a/internal/progress/command.go +++ b/internal/progress/command.go @@ -17,7 +17,7 @@ import ( // Commands func GetClusterInterval(clusterName string) tea.Cmd { - return tea.Every(time.Second*10, func(t time.Time) tea.Msg { + return tea.Every(time.Second*10, func(_ time.Time) tea.Msg { provisioningCluster, err := cluster.GetCluster(clusterName) if err != nil { log.Printf("failed to get cluster %q: %v", clusterName, err) @@ -29,70 +29,70 @@ func GetClusterInterval(clusterName string) tea.Cmd { } func AddSuccesMessage(cluster types.Cluster) tea.Cmd { - return tea.Tick(0, func(t time.Time) tea.Msg { + return tea.Tick(0, func(_ time.Time) tea.Msg { successMessage := DisplaySuccessMessage(cluster) - return successMsg(successMessage) + return successMessage }) } -func BuildCompletedSteps(cluster types.Cluster, model progressModel) ([]string, string) { +func BuildCompletedSteps(cluster types.Cluster) ([]string, string) { completedSteps := []string{} nextStep := "" if cluster.InstallToolsCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.install_tools_check) - nextStep = CompletedStepsLabels.domain_liveness_check + completedSteps = append(completedSteps, CompletedStepsLabels.installToolsCheck) + nextStep = CompletedStepsLabels.domainLivenessCheck } if cluster.DomainLivenessCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.domain_liveness_check) - nextStep = CompletedStepsLabels.kbot_setup_check + completedSteps = append(completedSteps, CompletedStepsLabels.domainLivenessCheck) + nextStep = CompletedStepsLabels.kbotSetupCheck } if cluster.KbotSetupCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.kbot_setup_check) - nextStep = CompletedStepsLabels.git_init_check + completedSteps = append(completedSteps, CompletedStepsLabels.kbotSetupCheck) + nextStep = CompletedStepsLabels.gitInitCheck } if cluster.GitInitCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.git_init_check) - nextStep = CompletedStepsLabels.gitops_ready_check + completedSteps = append(completedSteps, CompletedStepsLabels.gitInitCheck) + nextStep = CompletedStepsLabels.gitopsReadyCheck } if cluster.GitopsReadyCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.gitops_ready_check) - nextStep = CompletedStepsLabels.git_terraform_apply_check + completedSteps = append(completedSteps, CompletedStepsLabels.gitopsReadyCheck) + nextStep = CompletedStepsLabels.gitTerraformApplyCheck } if cluster.GitTerraformApplyCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.git_terraform_apply_check) - nextStep = CompletedStepsLabels.gitops_pushed_check + completedSteps = append(completedSteps, CompletedStepsLabels.gitTerraformApplyCheck) + nextStep = CompletedStepsLabels.gitopsPushedCheck } if cluster.GitopsPushedCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.gitops_pushed_check) - nextStep = CompletedStepsLabels.cloud_terraform_apply_check + completedSteps = append(completedSteps, CompletedStepsLabels.gitopsPushedCheck) + nextStep = CompletedStepsLabels.cloudTerraformApplyCheck } if cluster.CloudTerraformApplyCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.cloud_terraform_apply_check) - nextStep = CompletedStepsLabels.cluster_secrets_created_check + completedSteps = append(completedSteps, CompletedStepsLabels.cloudTerraformApplyCheck) + nextStep = CompletedStepsLabels.clusterSecretsCreatedCheck } if cluster.ClusterSecretsCreatedCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.cluster_secrets_created_check) - nextStep = CompletedStepsLabels.argocd_install_check + completedSteps = append(completedSteps, CompletedStepsLabels.clusterSecretsCreatedCheck) + nextStep = CompletedStepsLabels.argoCDInstallCheck } if cluster.ArgoCDInstallCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.argocd_install_check) - nextStep = CompletedStepsLabels.argocd_initialize_check + completedSteps = append(completedSteps, CompletedStepsLabels.argoCDInstallCheck) + nextStep = CompletedStepsLabels.argoCDInitializeCheck } if cluster.ArgoCDInitializeCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.argocd_initialize_check) - nextStep = CompletedStepsLabels.vault_initialized_check + completedSteps = append(completedSteps, CompletedStepsLabels.argoCDInitializeCheck) + nextStep = CompletedStepsLabels.vaultInitializedCheck } if cluster.VaultInitializedCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.vault_initialized_check) - nextStep = CompletedStepsLabels.vault_terraform_apply_check + completedSteps = append(completedSteps, CompletedStepsLabels.vaultInitializedCheck) + nextStep = CompletedStepsLabels.vaultTerraformApplyCheck } if cluster.VaultTerraformApplyCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.vault_terraform_apply_check) - nextStep = CompletedStepsLabels.users_terraform_apply_check + completedSteps = append(completedSteps, CompletedStepsLabels.vaultTerraformApplyCheck) + nextStep = CompletedStepsLabels.usersTerraformApplyCheck } if cluster.UsersTerraformApplyCheck { - completedSteps = append(completedSteps, CompletedStepsLabels.users_terraform_apply_check) + completedSteps = append(completedSteps, CompletedStepsLabels.usersTerraformApplyCheck) nextStep = "Wrapping up" } diff --git a/internal/progress/constants.go b/internal/progress/constants.go index 41335b835..a3dc7d7d9 100644 --- a/internal/progress/constants.go +++ b/internal/progress/constants.go @@ -6,41 +6,19 @@ See the LICENSE file for more details. */ package progress -import ( - "time" - - "github.com/charmbracelet/lipgloss" -) - -const ( - padding = 2 - maxWidth = 80 -) - -const debounceDuration = time.Second * 10 - -var ( - currentPkgNameStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("211")) - doneStyle = lipgloss.NewStyle().Margin(1, 2) - checkMark = lipgloss.NewStyle().Foreground(lipgloss.Color("42")).SetString("✓") - helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render - StatusStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FFFFFF")).Bold(true).Render - spinnerStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("69")) -) - var CompletedStepsLabels = ProvisionSteps{ - install_tools_check: "Installing tools", - domain_liveness_check: "Domain liveness check", - kbot_setup_check: "Kbot setup", - git_init_check: "Initializing Git", - gitops_ready_check: "Initializing GitOps", - git_terraform_apply_check: "Git Terraform apply", - gitops_pushed_check: "GitOps repos pushed", - cloud_terraform_apply_check: "Cloud Terraform apply", - cluster_secrets_created_check: "Creating cluster secrets", - argocd_install_check: "Installing ArgoCD", - argocd_initialize_check: "Initializing ArgoCD", - vault_initialized_check: "Initializing Vault", - vault_terraform_apply_check: "Vault Terraform apply", - users_terraform_apply_check: "Users Terraform apply", + installToolsCheck: "Installing tools", + domainLivenessCheck: "Domain liveness check", + kbotSetupCheck: "Kbot setup", + gitInitCheck: "Initializing Git", + gitopsReadyCheck: "Initializing GitOps", + gitTerraformApplyCheck: "Git Terraform apply", + gitopsPushedCheck: "GitOps repos pushed", + cloudTerraformApplyCheck: "Cloud Terraform apply", + clusterSecretsCreatedCheck: "Creating cluster secrets", + argoCDInstallCheck: "Installing ArgoCD", + argoCDInitializeCheck: "Initializing ArgoCD", + vaultInitializedCheck: "Initializing Vault", + vaultTerraformApplyCheck: "Vault Terraform apply", + usersTerraformApplyCheck: "Users Terraform apply", } diff --git a/internal/progress/message.go b/internal/progress/message.go index 497640791..fea8cd23f 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -81,6 +81,7 @@ func DisplayLogHints(estimatedTime int) { }) } +//nolint:revive // will be fixed in the future func DisplaySuccessMessage(cluster types.Cluster) successMsg { cloudCliKubeconfig := "" diff --git a/internal/progress/progress.go b/internal/progress/progress.go index 2ca6e2930..6ade5a08d 100644 --- a/internal/progress/progress.go +++ b/internal/progress/progress.go @@ -17,6 +17,7 @@ import ( var Progress *tea.Program var CanRunBubbleTea bool = true +//nolint:revive // will be removed after refactoring func NewModel() progressModel { return progressModel{ isProvisioned: false, @@ -73,7 +74,7 @@ func (m progressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case ClusterProvisioningMsg: m.provisioningCluster = types.Cluster(msg) - completedSteps, nextStep := BuildCompletedSteps(types.Cluster(msg), m) + completedSteps, nextStep := BuildCompletedSteps(types.Cluster(msg)) m.completedSteps = append(m.completedSteps, completedSteps...) m.nextStep = renderMessage(fmt.Sprintf(":dizzy: %s", nextStep)) @@ -109,7 +110,7 @@ func (m progressModel) View() string { completedSteps := "" for i := index; i < len(m.completedSteps); i++ { - completedSteps = completedSteps + renderMessage(fmt.Sprintf(":white_check_mark: %s", m.completedSteps[i])) + completedSteps += renderMessage(fmt.Sprintf(":white_check_mark: %s", m.completedSteps[i])) } if m.header != "" { diff --git a/internal/progress/types.go b/internal/progress/types.go index 6bf77b1c5..0c7989a44 100644 --- a/internal/progress/types.go +++ b/internal/progress/types.go @@ -57,18 +57,18 @@ type successMsg struct { // Custom type ProvisionSteps struct { - install_tools_check string - domain_liveness_check string - kbot_setup_check string - git_init_check string - gitops_ready_check string - git_terraform_apply_check string - gitops_pushed_check string - cloud_terraform_apply_check string - cluster_secrets_created_check string - argocd_install_check string - argocd_initialize_check string - vault_initialized_check string - vault_terraform_apply_check string - users_terraform_apply_check string + installToolsCheck string + domainLivenessCheck string + kbotSetupCheck string + gitInitCheck string + gitopsReadyCheck string + gitTerraformApplyCheck string + gitopsPushedCheck string + cloudTerraformApplyCheck string + clusterSecretsCreatedCheck string + argoCDInstallCheck string + argoCDInitializeCheck string + vaultInitializedCheck string + vaultTerraformApplyCheck string + usersTerraformApplyCheck string } diff --git a/internal/provisionLogs/command.go b/internal/provisionLogs/command.go index e8b2c7393..47859bf05 100644 --- a/internal/provisionLogs/command.go +++ b/internal/provisionLogs/command.go @@ -4,7 +4,7 @@ Copyright (C) 2021-2023, Kubefirst This program is licensed under MIT. See the LICENSE file for more details. */ -package provisionLogs +package provisionLogs //nolint:revive // allowed during refactoring import ( "encoding/json" diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go deleted file mode 100644 index 1b5ec5043..000000000 --- a/internal/provisionLogs/message.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright (C) 2021-2023, Kubefirst - -This program is licensed under MIT. -See the LICENSE file for more details. - -Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go -Color definition https://www.ditig.com/256-colors-cheat-sheet -*/ -package provisionLogs - -import ( - "fmt" - "log" - - "github.com/charmbracelet/glamour" - "github.com/konstructio/kubefirst/internal/progress" -) - -func renderMessage(message string) string { - r, _ := glamour.NewTermRenderer( - glamour.WithStyles(progress.StyleConfig), - glamour.WithEmoji(), - ) - - out, err := r.Render(message) - if err != nil { - s := fmt.Errorf("rendering message failed: %w", err) - log.Println(s) - return s.Error() - } - return out -} diff --git a/internal/provisionLogs/provisionLogs.go b/internal/provisionLogs/provisionLogs.go index 4b63fb7e5..b2618e8cb 100644 --- a/internal/provisionLogs/provisionLogs.go +++ b/internal/provisionLogs/provisionLogs.go @@ -4,7 +4,7 @@ Copyright (C) 2021-2023, Kubefirst This program is licensed under MIT. See the LICENSE file for more details. */ -package provisionLogs +package provisionLogs //nolint:revive // allowed during refactoring import ( tea "github.com/charmbracelet/bubbletea" @@ -15,6 +15,7 @@ var quitStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241")).Render var ProvisionLogs *tea.Program +//nolint:revive // will be removed after refactoring func NewModel() provisionLogsModel { return provisionLogsModel{} } diff --git a/internal/provisionLogs/types.go b/internal/provisionLogs/types.go index a67905f25..3dd3906c7 100644 --- a/internal/provisionLogs/types.go +++ b/internal/provisionLogs/types.go @@ -4,7 +4,7 @@ Copyright (C) 2021-2023, Kubefirst This program is licensed under MIT. See the LICENSE file for more details. */ -package provisionLogs +package provisionLogs //nolint:revive // allowed during refactoring // Terminal model type provisionLogsModel struct { diff --git a/internal/segment/segment.go b/internal/segment/segment.go index 927b7c3ef..ba6616d7e 100644 --- a/internal/segment/segment.go +++ b/internal/segment/segment.go @@ -14,7 +14,7 @@ const ( kubefirstClient string = "api" ) -func InitClient(clusterId, clusterType, gitProvider string) (telemetry.TelemetryEvent, error) { +func InitClient(clusterID, clusterType, gitProvider string) (telemetry.TelemetryEvent, error) { machineID, err := machineid.ID() if err != nil { return telemetry.TelemetryEvent{}, fmt.Errorf("failed to get machine ID: %w", err) @@ -23,7 +23,7 @@ func InitClient(clusterId, clusterType, gitProvider string) (telemetry.Telemetry c := telemetry.TelemetryEvent{ CliVersion: configs.K1Version, CloudProvider: k3d.CloudProvider, - ClusterID: clusterId, + ClusterID: clusterID, ClusterType: clusterType, DomainName: k3d.DomainName, GitProvider: gitProvider, diff --git a/internal/types/flags.go b/internal/types/flags.go index 43795f157..84c3777d4 100644 --- a/internal/types/flags.go +++ b/internal/types/flags.go @@ -13,7 +13,7 @@ type CliFlags struct { CloudProvider string ClusterName string ClusterType string - DnsProvider string + DNSProvider string DomainName string SubDomainName string GitProvider string @@ -24,14 +24,14 @@ type CliFlags struct { GitopsTemplateURL string GoogleProject string UseTelemetry bool - Ecr bool + ECR bool NodeType string NodeCount string InstallCatalogApps string - K3sSshUser string - K3sSshPrivateKey string - K3sServersPrivateIps []string - K3sServersPublicIps []string + K3sSSHUser string + K3sSSHPrivateKey string + K3sServersPrivateIPs []string + K3sServersPublicIPs []string K3sServersArgs []string InstallKubefirstPro bool } diff --git a/internal/types/proxy.go b/internal/types/proxy.go index dc16ceb2c..a4b444d1c 100644 --- a/internal/types/proxy.go +++ b/internal/types/proxy.go @@ -12,9 +12,9 @@ import ( type ProxyCreateClusterRequest struct { Body apiTypes.ClusterDefinition `bson:"body" json:"body"` - Url string `bson:"url" json:"url"` + URL string `bson:"url" json:"url"` } type ProxyResetClusterRequest struct { - Url string `bson:"url" json:"url"` + URL string `bson:"url" json:"url"` } diff --git a/internal/utilities/flags.go b/internal/utilities/flags.go index ed0ff19ce..12306966d 100644 --- a/internal/utilities/flags.go +++ b/internal/utilities/flags.go @@ -130,7 +130,7 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) return cliFlags, fmt.Errorf("failed to get ecr flag: %w", err) } - cliFlags.Ecr = ecrFlag + cliFlags.ECR = ecrFlag } if cloudProvider == "google" { @@ -149,28 +149,28 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) progress.Error(err.Error()) return cliFlags, fmt.Errorf("failed to get servers-private-ips flag: %w", err) } - cliFlags.K3sServersPrivateIps = k3sServersPrivateIps + cliFlags.K3sServersPrivateIPs = k3sServersPrivateIps k3sServersPublicIps, err := cmd.Flags().GetStringSlice("servers-public-ips") if err != nil { progress.Error(err.Error()) return cliFlags, fmt.Errorf("failed to get servers-public-ips flag: %w", err) } - cliFlags.K3sServersPublicIps = k3sServersPublicIps + cliFlags.K3sServersPublicIPs = k3sServersPublicIps - k3sSshUserFlag, err := cmd.Flags().GetString("ssh-user") + k3sSSHUserFlag, err := cmd.Flags().GetString("ssh-user") if err != nil { progress.Error(err.Error()) return cliFlags, fmt.Errorf("failed to get ssh-user flag: %w", err) } - cliFlags.K3sSshUser = k3sSshUserFlag + cliFlags.K3sSSHUser = k3sSSHUserFlag - k3sSshPrivateKeyFlag, err := cmd.Flags().GetString("ssh-privatekey") + k3sSSHPrivateKeyFlag, err := cmd.Flags().GetString("ssh-privatekey") if err != nil { progress.Error(err.Error()) return cliFlags, fmt.Errorf("failed to get ssh-privatekey flag: %w", err) } - cliFlags.K3sSshPrivateKey = k3sSshPrivateKeyFlag + cliFlags.K3sSSHPrivateKey = k3sSSHPrivateKeyFlag K3sServersArgsFlags, err := cmd.Flags().GetStringSlice("servers-args") if err != nil { @@ -183,7 +183,7 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) cliFlags.AlertsEmail = alertsEmailFlag cliFlags.CloudRegion = cloudRegionFlag cliFlags.ClusterName = clusterNameFlag - cliFlags.DnsProvider = dnsProviderFlag + cliFlags.DNSProvider = dnsProviderFlag cliFlags.SubDomainName = subdomainFlag cliFlags.DomainName = domainNameFlag cliFlags.GitProtocol = gitProtocolFlag @@ -201,17 +201,17 @@ func GetFlags(cmd *cobra.Command, cloudProvider string) (types.CliFlags, error) viper.Set("flags.alerts-email", cliFlags.AlertsEmail) viper.Set("flags.cluster-name", cliFlags.ClusterName) - viper.Set("flags.dns-provider", cliFlags.DnsProvider) + viper.Set("flags.dns-provider", cliFlags.DNSProvider) viper.Set("flags.domain-name", cliFlags.DomainName) viper.Set("flags.git-provider", cliFlags.GitProvider) viper.Set("flags.git-protocol", cliFlags.GitProtocol) viper.Set("flags.cloud-region", cliFlags.CloudRegion) viper.Set("kubefirst.cloud-provider", cloudProvider) if cloudProvider == "k3s" { - viper.Set("flags.servers-private-ips", cliFlags.K3sServersPrivateIps) - viper.Set("flags.servers-public-ips", cliFlags.K3sServersPublicIps) - viper.Set("flags.ssh-user", cliFlags.K3sSshUser) - viper.Set("flags.ssh-privatekey", cliFlags.K3sSshPrivateKey) + viper.Set("flags.servers-private-ips", cliFlags.K3sServersPrivateIPs) + viper.Set("flags.servers-public-ips", cliFlags.K3sServersPublicIPs) + viper.Set("flags.ssh-user", cliFlags.K3sSSHUser) + viper.Set("flags.ssh-privatekey", cliFlags.K3sSSHPrivateKey) viper.Set("flags.servers-args", cliFlags.K3sServersArgs) } if err := viper.WriteConfig(); err != nil { diff --git a/internal/utilities/utilities.go b/internal/utilities/utilities.go index 01e8dfa6e..c28a71319 100644 --- a/internal/utilities/utilities.go +++ b/internal/utilities/utilities.go @@ -9,7 +9,7 @@ package utilities import ( "encoding/json" "fmt" - "io/ioutil" + "io" "os" "strconv" "time" @@ -137,7 +137,7 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ kubefirstTeam := os.Getenv("KUBEFIRST_TEAM") if kubefirstTeam == "" { - kubefirstTeam = "false" + kubefirstTeam = "false" //nolint:ineffassign,wastedassign // will be fixed in the future } stringToIntNodeCount, err := strconv.Atoi(cliFlags.NodeCount) @@ -191,7 +191,7 @@ func CreateClusterDefinitionRecordFromRaw(gitAuth apiTypes.GitAuth, cliFlags typ cl.AWSAuth.AccessKeyID = viper.GetString("kubefirst.state-store-creds.access-key-id") cl.AWSAuth.SecretAccessKey = viper.GetString("kubefirst.state-store-creds.secret-access-key-id") cl.AWSAuth.SessionToken = viper.GetString("kubefirst.state-store-creds.token") - cl.ECR = cliFlags.Ecr + cl.ECR = cliFlags.ECR case "civo": cl.CivoAuth.Token = os.Getenv("CIVO_TOKEN") case "digitalocean": diff --git a/main.go b/main.go index c99539771..4d0c8f833 100644 --- a/main.go +++ b/main.go @@ -12,16 +12,14 @@ import ( "os" "time" - "golang.org/x/exp/slices" - - zeroLog "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "github.com/konstructio/kubefirst-api/pkg/configs" utils "github.com/konstructio/kubefirst-api/pkg/utils" "github.com/konstructio/kubefirst/cmd" "github.com/konstructio/kubefirst/internal/progress" + zeroLog "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/spf13/viper" + "golang.org/x/exp/slices" ) func main() { @@ -40,7 +38,8 @@ func main() { config := configs.ReadConfig() if err := utils.SetupViper(config, true); err != nil { - stdLog.Panic(err) + log.Error().Msgf("failed to setup Viper: %v", err) + return } now := time.Now() @@ -74,38 +73,39 @@ func main() { homePath, err := os.UserHomeDir() if err != nil { - log.Info().Msg(err.Error()) + log.Error().Msgf("failed to get user home directory: %v", err) + return } k1Dir := fmt.Sprintf("%s/.k1", homePath) // * create k1Dir if it doesn't exist if _, err := os.Stat(k1Dir); os.IsNotExist(err) { - err := os.MkdirAll(k1Dir, os.ModePerm) - if err != nil { - log.Info().Msgf("%s directory already exists, continuing", k1Dir) + if err := os.MkdirAll(k1Dir, os.ModePerm); err != nil { + log.Error().Msgf("error creating directory %q: %v", k1Dir, err) + return } } // * create log directory logsFolder := fmt.Sprintf("%s/logs", k1Dir) - _ = os.Mkdir(logsFolder, 0o700) - if err != nil { - log.Fatal().Msgf("error creating logs directory: %s", err) + if err := os.Mkdir(logsFolder, 0o700); err != nil { + log.Error().Msgf("error creating logs directory: %v", err) + return } // * create session log file logfile := fmt.Sprintf("%s/%s", logsFolder, logfileName) logFileObj, err := utils.OpenLogFile(logfile) if err != nil { - stdLog.Panicf("unable to store log location, error is: %s - please verify the current user has write access to this directory", err) + log.Error().Msgf("unable to store log location, error is: %v - please verify the current user has write access to this directory", err) + return } // handle file close request defer func(logFileObj *os.File) { - err = logFileObj.Close() - if err != nil { - log.Print(err) + if err := logFileObj.Close(); err != nil { + log.Error().Msgf("error closing log file: %v", err) } }(logFileObj) @@ -121,9 +121,9 @@ func main() { viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - err = viper.WriteConfig() - if err != nil { - stdLog.Panicf("unable to set log-file-location, error is: %s", err) + if err := viper.WriteConfig(); err != nil { + log.Error().Msgf("failed to write config: %v", err) + return } if canRunBubbleTea { From 7dd646eca515fa5108c4e80fa78a6a95412649f0 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:28:14 -0400 Subject: [PATCH 57/85] Fix typo in function name. --- cmd/akamai/create.go | 2 +- cmd/aws/create.go | 2 +- cmd/civo/create.go | 2 +- cmd/digitalocean/create.go | 2 +- cmd/google/create.go | 2 +- cmd/k3s/create.go | 2 +- cmd/vultr/create.go | 2 +- internal/cluster/cluster.go | 12 ++++++------ 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index d5a0a4a6d..d9bde4c00 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -84,7 +84,7 @@ func createAkamai(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check kubefirst api availability: %w", err) diff --git a/cmd/aws/create.go b/cmd/aws/create.go index a19203af0..714afa154 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -118,7 +118,7 @@ func createAws(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = pkg.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check kubefirst API availability: %w", err) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index ffec64472..62c3f4ca7 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -85,7 +85,7 @@ func createCivo(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("API availability check failed: %w", err) diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index a600c6199..6d8489395 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -96,7 +96,7 @@ func createDigitalocean(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("failed to check app availability for Kubefirst API: %w", err) diff --git a/cmd/google/create.go b/cmd/google/create.go index 00fd53dc2..d4e338457 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -89,7 +89,7 @@ func createGoogle(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("kubefirst api availability check failed: %w", err) diff --git a/cmd/k3s/create.go b/cmd/k3s/create.go index ae7ce75c3..57870135b 100644 --- a/cmd/k3s/create.go +++ b/cmd/k3s/create.go @@ -99,7 +99,7 @@ func createK3s(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("app availability check failed: %w", err) diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 5066b5c29..5d20ca120 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -96,7 +96,7 @@ func createVultr(cmd *cobra.Command, _ []string) error { launch.Up(nil, true, cliFlags.UseTelemetry) } - err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngresURL()), "kubefirst api") + err = utils.IsAppAvailable(fmt.Sprintf("%s/api/proxyHealth", cluster.GetConsoleIngressURL()), "kubefirst api") if err != nil { progress.Error("unable to start kubefirst api") return fmt.Errorf("kubefirst api availability check failed: %w", err) diff --git a/internal/cluster/cluster.go b/internal/cluster/cluster.go index e9630376f..64b5223a0 100644 --- a/internal/cluster/cluster.go +++ b/internal/cluster/cluster.go @@ -21,7 +21,7 @@ import ( "github.com/konstructio/kubefirst/internal/types" ) -func GetConsoleIngresURL() string { +func GetConsoleIngressURL() string { if strings.ToLower(os.Getenv("K1_LOCAL_DEBUG")) == "true" { // allow using local console running on port 3000 return os.Getenv("K1_CONSOLE_REMOTE_URL") } @@ -43,7 +43,7 @@ func CreateCluster(cluster apiTypes.ClusterDefinition) error { return fmt.Errorf("failed to marshal request object: %w", err) } - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresURL()), bytes.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngressURL()), bytes.NewReader(payload)) if err != nil { log.Printf("error creating request: %s", err) return fmt.Errorf("failed to create request: %w", err) @@ -87,7 +87,7 @@ func ResetClusterProgress(clusterName string) error { return fmt.Errorf("failed to marshal request object: %w", err) } - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngresURL()), bytes.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/proxy", GetConsoleIngressURL()), bytes.NewReader(payload)) if err != nil { log.Printf("error creating request: %v", err) return fmt.Errorf("failed to create request: %w", err) @@ -122,7 +122,7 @@ func GetCluster(clusterName string) (apiTypes.Cluster, error) { httpClient := http.Client{Transport: customTransport} cluster := apiTypes.Cluster{} - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresURL(), clusterName), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngressURL(), clusterName), nil) if err != nil { log.Printf("error creating request: %v", err) return cluster, fmt.Errorf("failed to create request: %w", err) @@ -162,7 +162,7 @@ func GetClusters() ([]apiTypes.Cluster, error) { httpClient := http.Client{Transport: customTransport} clusters := []apiTypes.Cluster{} - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster", GetConsoleIngresURL()), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/proxy?url=/cluster", GetConsoleIngressURL()), nil) if err != nil { log.Printf("error creating request: %v", err) return clusters, fmt.Errorf("failed to create request: %w", err) @@ -201,7 +201,7 @@ func DeleteCluster(clusterName string) error { customTransport := http.DefaultTransport.(*http.Transport).Clone() httpClient := http.Client{Transport: customTransport} - req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngresURL(), clusterName), nil) + req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/proxy?url=/cluster/%s", GetConsoleIngressURL(), clusterName), nil) if err != nil { log.Printf("error creating request: %v", err) return fmt.Errorf("failed to create request: %w", err) From a7f98c04d802a03a68679a62cdfa887d8547d2a9 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:11:29 -0400 Subject: [PATCH 58/85] Fixes to error handling. --- cmd/akamai/create.go | 6 +++++- cmd/aws/create.go | 6 +++++- cmd/civo/create.go | 6 +++++- cmd/digitalocean/create.go | 6 +++++- cmd/google/create.go | 6 +++++- cmd/k3s/create.go | 5 ++++- cmd/vultr/create.go | 6 +++++- internal/cluster/cluster.go | 11 +++++++++-- internal/provision/provision.go | 8 ++++---- 9 files changed, 47 insertions(+), 13 deletions(-) diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index d9bde4c00..da4897476 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -90,7 +90,11 @@ func createAkamai(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed to check kubefirst api availability: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/cmd/aws/create.go b/cmd/aws/create.go index 714afa154..c917a98e7 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -124,7 +124,11 @@ func createAws(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed to check kubefirst API availability: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 62c3f4ca7..a7bf6a507 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -91,7 +91,11 @@ func createCivo(cmd *cobra.Command, _ []string) error { return fmt.Errorf("API availability check failed: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index 6d8489395..c12134962 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -102,7 +102,11 @@ func createDigitalocean(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed to check app availability for Kubefirst API: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/cmd/google/create.go b/cmd/google/create.go index d4e338457..bb074d9bb 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -95,7 +95,11 @@ func createGoogle(cmd *cobra.Command, _ []string) error { return fmt.Errorf("kubefirst api availability check failed: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/cmd/k3s/create.go b/cmd/k3s/create.go index 57870135b..038337759 100644 --- a/cmd/k3s/create.go +++ b/cmd/k3s/create.go @@ -105,7 +105,10 @@ func createK3s(cmd *cobra.Command, _ []string) error { return fmt.Errorf("app availability check failed: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } return nil } diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 5d20ca120..6086ae2b4 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -102,7 +102,11 @@ func createVultr(cmd *cobra.Command, _ []string) error { return fmt.Errorf("kubefirst api availability check failed: %w", err) } - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) + if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to create management cluster: %w", err) + } + return nil } diff --git a/internal/cluster/cluster.go b/internal/cluster/cluster.go index 64b5223a0..02e2603da 100644 --- a/internal/cluster/cluster.go +++ b/internal/cluster/cluster.go @@ -117,6 +117,8 @@ func ResetClusterProgress(clusterName string) error { return nil } +var ErrNotFound = fmt.Errorf("cluster not found") + func GetCluster(clusterName string) (apiTypes.Cluster, error) { customTransport := http.DefaultTransport.(*http.Transport).Clone() httpClient := http.Client{Transport: customTransport} @@ -137,8 +139,13 @@ func GetCluster(clusterName string) (apiTypes.Cluster, error) { } defer res.Body.Close() - if res.StatusCode != http.StatusOK { - log.Printf("unable to get cluster: %q, continuing", res.Status) + switch res.StatusCode { + case http.StatusNotFound: + return cluster, ErrNotFound + case http.StatusOK: + // continue with the rest + default: + log.Printf("unable to get cluster: %q", res.Status) return cluster, fmt.Errorf("unable to get cluster: %q", res.Status) } diff --git a/internal/provision/provision.go b/internal/provision/provision.go index a97b86e34..4be889488 100644 --- a/internal/provision/provision.go +++ b/internal/provision/provision.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package provision import ( + "errors" "fmt" apiTypes "github.com/konstructio/kubefirst-api/pkg/types" @@ -25,14 +26,13 @@ func CreateMgmtCluster(gitAuth apiTypes.GitAuth, cliFlags types.CliFlags, catalo ) clusterCreated, err := cluster.GetCluster(clusterRecord.ClusterName) - if err != nil { + if err != nil && !errors.Is(err, cluster.ErrNotFound) { log.Printf("error retrieving cluster %q: %v", clusterRecord.ClusterName, err) return fmt.Errorf("error retrieving cluster: %w", err) } - if !clusterCreated.InProgress { - err = cluster.CreateCluster(clusterRecord) - if err != nil { + if errors.Is(err, cluster.ErrNotFound) { + if err := cluster.CreateCluster(clusterRecord); err != nil { progress.Error(err.Error()) return fmt.Errorf("error creating cluster: %w", err) } From cb1016f40c9f0b0dbcf140665606e5fd4908867b Mon Sep 17 00:00:00 2001 From: konstruct-bot Date: Wed, 18 Sep 2024 19:31:20 +0000 Subject: [PATCH 59/85] set next macro chart for kubefirst - 2.6.2-rc1 --- internal/launch/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/launch/constants.go b/internal/launch/constants.go index ff96af136..c7148a1ba 100644 --- a/internal/launch/constants.go +++ b/internal/launch/constants.go @@ -11,7 +11,7 @@ const ( helmChartName = "kubefirst" helmChartRepoName = "konstruct" helmChartRepoURL = "https://charts.konstruct.io" - helmChartVersion = "2.6.1" + helmChartVersion = "2.6.2-rc1" namespace = "kubefirst" secretName = "kubefirst-initial-secrets" ) From d2e70ee8eef82df3fb3f6118b179c279b17a57ca Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 60/85] chore: bubbletea blacklist ci flag --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 4d0c8f833..847f6a7ab 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From d5f4844e45a4b1f456803b8d5d78e5c3ab2d02d0 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:05:51 -0500 Subject: [PATCH 61/85] chore: error handling --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 847f6a7ab..bb67b81d1 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} canRunBubbleTea := true for _, arg := range argsWithProg { From f73bf768579fb7d46e468e2ed76f6e7add969683 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:40:33 -0500 Subject: [PATCH 62/85] fix: bypass bubbletea execution --- main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.go b/main.go index bb67b81d1..4d0c8f833 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From cee5cd31b090217f815484ff0207ac956c675732 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 18:10:01 -0500 Subject: [PATCH 63/85] chore: print cluster name --- internal/common/common.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/common/common.go b/internal/common/common.go index 3c4c6055c..8c162558b 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -114,6 +114,8 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { clusterName = clusteNameFromFlag } + fmt.Print(clusterName) + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) From 6859dedba6f193e3a35e7773f6fc541198e270c6 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:24:16 -0500 Subject: [PATCH 64/85] chore: test cluster name --- internal/common/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/common/common.go b/internal/common/common.go index 8c162558b..a2b11333d 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -116,7 +116,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { fmt.Print(clusterName) - cluster, err := cluster.GetCluster(clusterName) + cluster, err := cluster.GetCluster("jd-test-4-axmhv") if err != nil { progress.Error(err.Error()) return fmt.Errorf("failed to get cluster: %w", err) From 32b569af983d3fa65f7da461766226c965e44dc5 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:38:04 -0500 Subject: [PATCH 65/85] chore: test without provisioning --- internal/common/common.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/common/common.go b/internal/common/common.go index a2b11333d..3c4c6055c 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -114,9 +114,7 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { clusterName = clusteNameFromFlag } - fmt.Print(clusterName) - - cluster, err := cluster.GetCluster("jd-test-4-axmhv") + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) return fmt.Errorf("failed to get cluster: %w", err) From e43cf152d9b3971ca39a2f15935db9f2d9f1dbd7 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 66/85] chore: bubbletea blacklist ci flag --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 4d0c8f833..847f6a7ab 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From 38953094bee2b9e3236adaee74c261c401fd3848 Mon Sep 17 00:00:00 2001 From: konstruct-bot <1@gmail.com> Date: Thu, 5 Sep 2024 13:20:04 +0530 Subject: [PATCH 67/85] rebase --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index 847f6a7ab..4d0c8f833 100644 --- a/main.go +++ b/main.go @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From 7d158abb45ea52fb97a6798ef0819841a97d482f Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 20:38:01 -0500 Subject: [PATCH 68/85] chore: test without provisioning --- cmd/civo/create.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index a7bf6a507..97aa59984 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,12 +12,10 @@ import ( "strings" utils "github.com/konstructio/kubefirst-api/pkg/utils" - "github.com/konstructio/kubefirst/internal/catalog" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/gitShim" "github.com/konstructio/kubefirst/internal/launch" "github.com/konstructio/kubefirst/internal/progress" - "github.com/konstructio/kubefirst/internal/provision" "github.com/konstructio/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" From cd95b7fc2554b5bfbbd215ba14996dd808f9a5a6 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Sun, 4 Aug 2024 19:07:30 -0500 Subject: [PATCH 69/85] chore: rollback provision --- cmd/civo/create.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/civo/create.go b/cmd/civo/create.go index 97aa59984..a7bf6a507 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -12,10 +12,12 @@ import ( "strings" utils "github.com/konstructio/kubefirst-api/pkg/utils" + "github.com/konstructio/kubefirst/internal/catalog" "github.com/konstructio/kubefirst/internal/cluster" "github.com/konstructio/kubefirst/internal/gitShim" "github.com/konstructio/kubefirst/internal/launch" "github.com/konstructio/kubefirst/internal/progress" + "github.com/konstructio/kubefirst/internal/provision" "github.com/konstructio/kubefirst/internal/utilities" "github.com/spf13/cobra" "github.com/spf13/viper" From a93ef048b9a50ddd149699e2038095f0eaa8c6cb Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:26:42 -0400 Subject: [PATCH 70/85] Clean up code using GolangCI-Lint --- cmd/k3d/create.go | 1267 +++++++++++++++++++++++++++++++++++++++++++ cmd/vultr/create.go | 4 + 2 files changed, 1271 insertions(+) diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index f70fefb4a..fe57bbe9b 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -1272,3 +1272,1270 @@ func runK3d(cmd *cobra.Command, _ []string) error { return nil } + +/* +Copyright (C) 2021-2023, Kubefirst + +This program is licensed under MIT. +See the LICENSE file for more details. +*/ +package k3d + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "net/http" + "os" + "strconv" + "strings" + "syscall" + "time" + + argocdapi "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" + "github.com/atotto/clipboard" + "github.com/dustin/go-humanize" + "github.com/go-git/go-git/v5" + githttps "github.com/go-git/go-git/v5/plumbing/transport/http" + "github.com/konstructio/kubefirst-api/pkg/argocd" + "github.com/konstructio/kubefirst-api/pkg/configs" + constants "github.com/konstructio/kubefirst-api/pkg/constants" + "github.com/konstructio/kubefirst-api/pkg/gitClient" + "github.com/konstructio/kubefirst-api/pkg/github" + "github.com/konstructio/kubefirst-api/pkg/gitlab" + "github.com/konstructio/kubefirst-api/pkg/handlers" + "github.com/konstructio/kubefirst-api/pkg/k3d" + "github.com/konstructio/kubefirst-api/pkg/k8s" + "github.com/konstructio/kubefirst-api/pkg/progressPrinter" + "github.com/konstructio/kubefirst-api/pkg/reports" + "github.com/konstructio/kubefirst-api/pkg/services" + internalssh "github.com/konstructio/kubefirst-api/pkg/ssh" + "github.com/konstructio/kubefirst-api/pkg/terraform" + "github.com/konstructio/kubefirst-api/pkg/types" + utils "github.com/konstructio/kubefirst-api/pkg/utils" + "github.com/konstructio/kubefirst-api/pkg/wrappers" + "github.com/konstructio/kubefirst/internal/catalog" + "github.com/konstructio/kubefirst/internal/gitShim" + "github.com/konstructio/kubefirst/internal/progress" + "github.com/konstructio/kubefirst/internal/segment" + "github.com/konstructio/kubefirst/internal/utilities" + "github.com/kubefirst/metrics-client/pkg/telemetry" + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + "github.com/spf13/viper" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +func runK3d(cmd *cobra.Command, args []string) error { + ciFlag, err := cmd.Flags().GetBool("ci") + if err != nil { + return fmt.Errorf("failed to get 'ci' flag: %w", err) + } + + clusterNameFlag, err := cmd.Flags().GetString("cluster-name") + if err != nil { + return fmt.Errorf("failed to get 'cluster-name' flag: %w", err) + } + + clusterTypeFlag, err := cmd.Flags().GetString("cluster-type") + if err != nil { + return fmt.Errorf("failed to get 'cluster-type' flag: %w", err) + } + + githubOrgFlag, err := cmd.Flags().GetString("github-org") + if err != nil { + return fmt.Errorf("failed to get 'github-org' flag: %w", err) + } + + githubUserFlag, err := cmd.Flags().GetString("github-user") + if err != nil { + return fmt.Errorf("failed to get 'github-user' flag: %w", err) + } + + gitlabGroupFlag, err := cmd.Flags().GetString("gitlab-group") + if err != nil { + return fmt.Errorf("failed to get 'gitlab-group' flag: %w", err) + } + + gitProviderFlag, err := cmd.Flags().GetString("git-provider") + if err != nil { + return fmt.Errorf("failed to get 'git-provider' flag: %w", err) + } + + gitProtocolFlag, err := cmd.Flags().GetString("git-protocol") + if err != nil { + return fmt.Errorf("failed to get 'git-protocol' flag: %w", err) + } + + gitopsTemplateURLFlag, err := cmd.Flags().GetString("gitops-template-url") + if err != nil { + return fmt.Errorf("failed to get 'gitops-template-url' flag: %w", err) + } + + gitopsTemplateBranchFlag, err := cmd.Flags().GetString("gitops-template-branch") + if err != nil { + return fmt.Errorf("failed to get 'gitops-template-branch' flag: %w", err) + } + + installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") + if err != nil { + return fmt.Errorf("failed to get 'install-catalog-apps' flag: %w", err) + } + + useTelemetryFlag, err := cmd.Flags().GetBool("use-telemetry") + if err != nil { + return fmt.Errorf("failed to get 'use-telemetry' flag: %w", err) + } + + utilities.CreateK1ClusterDirectory(clusterNameFlag) + utils.DisplayLogHints() + + isValid, catalogApps, err := catalog.ValidateCatalogApps(installCatalogAppsFlag) + if !isValid { + return err + } + + switch gitProviderFlag { + case "github": + key, err := internalssh.GetHostKey("github.com") + if err != nil { + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) + } + log.Info().Msgf("Host key for github.com: %q", key.Type()) + case "gitlab": + key, err := internalssh.GetHostKey("gitlab.com") + if err != nil { + return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) + } + log.Info().Msgf("Host key for gitlab.com: %q", key.Type()) + } + + if githubOrgFlag != "" && githubUserFlag != "" { + return errors.New("only one of --github-user or --github-org can be supplied") + } + + err = k8s.CheckForExistingPortForwards(8080, 8200, 9000, 9094) + if err != nil { + return fmt.Errorf("error checking existing port forwards: %w", err) + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + httpClient := http.DefaultClient + + kubefirstTeam := os.Getenv("KUBEFIRST_TEAM") + if kubefirstTeam == "" { + kubefirstTeam = "false" + } + + viper.Set("flags.cluster-name", clusterNameFlag) + viper.Set("flags.domain-name", k3d.DomainName) + viper.Set("flags.git-provider", gitProviderFlag) + viper.Set("flags.git-protocol", gitProtocolFlag) + viper.Set("kubefirst.cloud-provider", "k3d") + viper.WriteConfig() + + var cGitHost, cGitOwner, cGitUser, cGitToken, containerRegistryHost string + var cGitlabOwnerGroupID int + switch gitProviderFlag { + case "github": + cGitHost = k3d.GithubHost + containerRegistryHost = "ghcr.io" + + gitHubService := services.NewGitHubService(httpClient) + gitHubHandler := handlers.NewGitHubHandler(gitHubService) + + var existingToken string + if os.Getenv("GITHUB_TOKEN") != "" { + existingToken = os.Getenv("GITHUB_TOKEN") + } else if viper.GetString("github.session_token") != "" { + existingToken = viper.GetString("github.session_token") + } + gitHubAccessToken, err := wrappers.AuthenticateGitHubUserWrapper(existingToken, gitHubHandler) + if err != nil { + log.Warn().Msg(err.Error()) + } + + cGitToken = gitHubAccessToken + + err = github.VerifyTokenPermissions(cGitToken) + if err != nil { + return fmt.Errorf("failed to verify GitHub token permissions: %w", err) + } + + log.Info().Msg("verifying GitHub authentication") + githubUser, err := gitHubHandler.GetGitHubUser(cGitToken) + if err != nil { + return fmt.Errorf("failed to get GitHub user: %w", err) + } + + if githubOrgFlag != "" { + cGitOwner = githubOrgFlag + } else { + cGitOwner = githubUser + } + cGitUser = githubUser + + viper.Set("flags.github-owner", cGitOwner) + viper.Set("github.session_token", cGitToken) + viper.WriteConfig() + case "gitlab": + if gitlabGroupFlag == "" { + return errors.New("please provide a gitlab group using the --gitlab-group flag") + } + + cGitToken = os.Getenv("GITLAB_TOKEN") + if cGitToken == "" { + return errors.New("GITLAB_TOKEN environment variable unset - please set it and try again") + } + + err = gitlab.VerifyTokenPermissions(cGitToken) + if err != nil { + return fmt.Errorf("failed to verify GitLab token permissions: %w", err) + } + + gitlabClient, err := gitlab.NewGitLabClient(cGitToken, gitlabGroupFlag) + if err != nil { + return fmt.Errorf("failed to create GitLab client: %w", err) + } + + cGitHost = k3d.GitlabHost + cGitOwner = gitlabClient.ParentGroupPath + cGitlabOwnerGroupID = gitlabClient.ParentGroupID + log.Info().Msgf("set gitlab owner to %q", cGitOwner) + + user, _, err := gitlabClient.Client.Users.CurrentUser() + if err != nil { + return fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set: %w", err) + } + cGitUser = user.Username + viper.Set("flags.gitlab-owner", gitlabGroupFlag) + viper.Set("flags.gitlab-owner-group-id", cGitlabOwnerGroupID) + viper.Set("gitlab.session_token", cGitToken) + viper.WriteConfig() + default: + return fmt.Errorf("invalid git provider option %q", gitProviderFlag) + } + + var gitDestDescriptor string + switch gitProviderFlag { + case "github": + if githubOrgFlag != "" { + gitDestDescriptor = "Organization" + } else { + gitDestDescriptor = "User" + } + case "gitlab": + gitDestDescriptor = "Group" + } + + config := k3d.GetConfig(clusterNameFlag, gitProviderFlag, cGitOwner, gitProtocolFlag) + switch gitProviderFlag { + case "github": + config.GithubToken = cGitToken + case "gitlab": + config.GitlabToken = cGitToken + } + + var sshPrivateKey, sshPublicKey string + + // todo placed in configmap in kubefirst namespace, included in telemetry + clusterId := viper.GetString("kubefirst.cluster-id") + if clusterId == "" { + clusterId = utils.GenerateClusterID() + viper.Set("kubefirst.cluster-id", clusterId) + viper.WriteConfig() + } + + segClient := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) + + progressPrinter.AddTracker("preflight-checks", "Running preflight checks", 5) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + progressPrinter.IncrementTracker("preflight-checks", 1) + + switch configs.K1Version { + case "development": + if strings.Contains(gitopsTemplateURLFlag, "https://github.com/konstructio/gitops-template.git") && gitopsTemplateBranchFlag == "" { + gitopsTemplateBranchFlag = "main" + } + default: + switch gitopsTemplateURLFlag { + case "https://github.com/konstructio/gitops-template.git": + if gitopsTemplateBranchFlag == "" { + gitopsTemplateBranchFlag = configs.K1Version + } + case "https://github.com/konstructio/gitops-template": + if gitopsTemplateBranchFlag == "" { + gitopsTemplateBranchFlag = configs.K1Version + } + default: + if gitopsTemplateBranchFlag == "" { + return errors.New("must supply gitops-template-branch flag when gitops-template-url is overridden") + } + } + } + + log.Info().Msgf("kubefirst version configs.K1Version: %q", configs.K1Version) + log.Info().Msgf("cloning gitops-template repo url: %q", gitopsTemplateURLFlag) + log.Info().Msgf("cloning gitops-template repo branch: %q", gitopsTemplateBranchFlag) + + atlantisWebhookSecret := viper.GetString("secrets.atlantis-webhook") + if atlantisWebhookSecret == "" { + atlantisWebhookSecret = utils.Random(20) + viper.Set("secrets.atlantis-webhook", atlantisWebhookSecret) + viper.WriteConfig() + } + + atlantisNgrokAuthtoken := viper.GetString("secrets.atlantis-ngrok-authtoken") + if atlantisNgrokAuthtoken == "" { + atlantisNgrokAuthtoken = os.Getenv("NGROK_AUTHTOKEN") + viper.Set("secrets.atlantis-ngrok-authtoken", atlantisNgrokAuthtoken) + viper.WriteConfig() + } + + log.Info().Msg("checking authentication to required providers") + + free, err := utils.GetAvailableDiskSize() + if err != nil { + return fmt.Errorf("failed to get available disk size: %w", err) + } + + availableDiskSize := float64(free) / humanize.GByte + if availableDiskSize < constants.MinimumAvailableDiskSize { + return fmt.Errorf( + "there is not enough space to proceed with the installation, a minimum of %d GB is required to proceed", + constants.MinimumAvailableDiskSize, + ) + } + progressPrinter.IncrementTracker("preflight-checks", 1) + + newRepositoryNames := []string{"gitops", "metaphor"} + newTeamNames := []string{"admins", "developers"} + + executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider)) + if !executionControl { + telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckStarted, "") + if len(cGitToken) == 0 { + msg := fmt.Sprintf("please set a %s_TOKEN environment variable to continue", strings.ToUpper(config.GitProvider)) + telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckFailed, msg) + return errors.New(msg) + } + + initGitParameters := gitShim.GitInitParameters{ + GitProvider: gitProviderFlag, + GitToken: cGitToken, + GitOwner: cGitOwner, + Repositories: newRepositoryNames, + Teams: newTeamNames, + } + err = gitShim.InitializeGitProvider(&initGitParameters) + if err != nil { + return fmt.Errorf("failed to initialize Git provider: %w", err) + } + + viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider), true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckCompleted, "") + progressPrinter.IncrementTracker("preflight-checks", 1) + } else { + log.Info().Msg(fmt.Sprintf("already completed %q checks - continuing", config.GitProvider)) + progressPrinter.IncrementTracker("preflight-checks", 1) + } + + var gitopsRepoURL string + executionControl = viper.GetBool("kubefirst-checks.kbot-setup") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.KbotSetupStarted, "") + + log.Info().Msg("creating an ssh key pair for your new cloud infrastructure") + sshPrivateKey, sshPublicKey, err = utils.CreateSshKeyPair() + if err != nil { + telemetry.SendEvent(segClient, telemetry.KbotSetupFailed, err.Error()) + return fmt.Errorf("failed to create SSH key pair: %w", err) + } + log.Info().Msg("ssh key pair creation complete") + + viper.Set("kbot.private-key", sshPrivateKey) + viper.Set("kbot.public-key", sshPublicKey) + viper.Set("kbot.username", "kbot") + viper.Set("kubefirst-checks.kbot-setup", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.KbotSetupCompleted, "") + log.Info().Msg("kbot-setup complete") + progressPrinter.IncrementTracker("preflight-checks", 1) + } else { + log.Info().Msg("already setup kbot user - continuing") + progressPrinter.IncrementTracker("preflight-checks", 1) + } + + log.Info().Msg("validation and kubefirst cli environment check is complete") + + telemetry.SendEvent(segClient, telemetry.InitCompleted, "") + + switch config.GitProtocol { + case "https": + gitopsRepoURL = config.DestinationGitopsRepoURL + default: + gitopsRepoURL = config.DestinationGitopsRepoGitURL + } + + gitopsDirectoryTokens := k3d.GitopsDirectoryValues{ + GithubOwner: cGitOwner, + GithubUser: cGitUser, + GitlabOwner: cGitOwner, + GitlabOwnerGroupID: cGitlabOwnerGroupID, + GitlabUser: cGitUser, + DomainName: k3d.DomainName, + AtlantisAllowList: fmt.Sprintf("%s/%s/*", cGitHost, cGitOwner), + AlertsEmail: "REMOVE_THIS_VALUE", + ClusterName: clusterNameFlag, + ClusterType: clusterTypeFlag, + GithubHost: k3d.GithubHost, + GitlabHost: k3d.GitlabHost, + ArgoWorkflowsIngressURL: fmt.Sprintf("https://argo.%s", k3d.DomainName), + VaultIngressURL: fmt.Sprintf("https://vault.%s", k3d.DomainName), + ArgocdIngressURL: fmt.Sprintf("https://argocd.%s", k3d.DomainName), + AtlantisIngressURL: fmt.Sprintf("https://atlantis.%s", k3d.DomainName), + MetaphorDevelopmentIngressURL: fmt.Sprintf("https://metaphor-development.%s", k3d.DomainName), + MetaphorStagingIngressURL: fmt.Sprintf("https://metaphor-staging.%s", k3d.DomainName), + MetaphorProductionIngressURL: fmt.Sprintf("https://metaphor-production.%s", k3d.DomainName), + KubefirstVersion: configs.K1Version, + KubefirstTeam: kubefirstTeam, + KubeconfigPath: config.Kubeconfig, + GitopsRepoURL: gitopsRepoURL, + GitProvider: config.GitProvider, + ClusterId: clusterId, + CloudProvider: k3d.CloudProvider, + } + + if useTelemetryFlag { + gitopsDirectoryTokens.UseTelemetry = "true" + } else { + gitopsDirectoryTokens.UseTelemetry = "false" + } + + httpAuth := &githttps.BasicAuth{ + Username: cGitUser, + Password: cGitToken, + } + + if err != nil { + log.Info().Msgf("generate public keys failed: %q", err.Error()) + return fmt.Errorf("failed to generate public keys: %w", err) + } + + if !viper.GetBool("kubefirst-checks.tools-downloaded") { + log.Info().Msg("installing kubefirst dependencies") + + err := k3d.DownloadTools(clusterNameFlag, config.GitProvider, cGitOwner, config.ToolsDir, config.GitProtocol) + if err != nil { + return fmt.Errorf("failed to download tools: %w", err) + } + + log.Info().Msg("download dependencies `$HOME/.k1/tools` complete") + viper.Set("kubefirst-checks.tools-downloaded", true) + viper.WriteConfig() + } else { + log.Info().Msg("already completed download of dependencies to `$HOME/.k1/tools` - continuing") + } + progressPrinter.IncrementTracker("preflight-checks", 1) + + metaphorTemplateTokens := k3d.MetaphorTokenValues{ + ClusterName: clusterNameFlag, + CloudRegion: cloudRegionFlag, + ContainerRegistryURL: fmt.Sprintf("%s/%s/metaphor", containerRegistryHost, cGitOwner), + DomainName: k3d.DomainName, + MetaphorDevelopmentIngressURL: fmt.Sprintf("metaphor-development.%s", k3d.DomainName), + MetaphorStagingIngressURL: fmt.Sprintf("metaphor-staging.%s", k3d.DomainName), + MetaphorProductionIngressURL: fmt.Sprintf("metaphor-production.%s", k3d.DomainName), + } + + progressPrinter.IncrementTracker("preflight-checks", 1) + progressPrinter.AddTracker("cloning-and-formatting-git-repositories", "Cloning and formatting git repositories", 1) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + removeAtlantis := false + if viper.GetString("secrets.atlantis-ngrok-authtoken") == "" { + removeAtlantis = true + } + if !viper.GetBool("kubefirst-checks.gitops-ready-to-push") { + log.Info().Msg("generating your new gitops repository") + err := k3d.PrepareGitRepositories( + config.GitProvider, + clusterNameFlag, + clusterTypeFlag, + config.DestinationGitopsRepoURL, + config.GitopsDir, + gitopsTemplateBranchFlag, + gitopsTemplateURLFlag, + config.DestinationMetaphorRepoURL, + config.K1Dir, + &gitopsDirectoryTokens, + config.MetaphorDir, + &metaphorTemplateTokens, + gitProtocolFlag, + removeAtlantis, + ) + if err != nil { + return fmt.Errorf("failed to prepare git repositories: %w", err) + } + + viper.Set("kubefirst-checks.gitops-ready-to-push", true) + viper.WriteConfig() + progressPrinter.IncrementTracker("cloning-and-formatting-git-repositories", 1) + } else { + log.Info().Msg("already completed gitops repo generation - continuing") + progressPrinter.IncrementTracker("cloning-and-formatting-git-repositories", 1) + } + + progressPrinter.AddTracker("applying-git-terraform", fmt.Sprintf("Applying %s Terraform", config.GitProvider), 1) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + switch config.GitProvider { + case "github": + executionControl = viper.GetBool("kubefirst-checks.terraform-apply-github") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") + + log.Info().Msg("Creating GitHub resources with Terraform") + + tfEntrypoint := config.GitopsDir + "/terraform/github" + tfEnvs := map[string]string{ + "GITHUB_TOKEN": cGitToken, + "GITHUB_OWNER": cGitOwner, + "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), + "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, + "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, + "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, + "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, + } + if config.GitProtocol == "https" { + tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" + } + + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) + if err != nil { + msg := fmt.Errorf("error creating GitHub resources with terraform %q: %w", tfEntrypoint, err) + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) + return msg + } + + log.Info().Msgf("created git repositories for github.com/%s", cGitOwner) + viper.Set("kubefirst-checks.terraform-apply-github", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyCompleted, "") + progressPrinter.IncrementTracker("applying-git-terraform", 1) + } else { + log.Info().Msg("already created GitHub Terraform resources") + progressPrinter.IncrementTracker("applying-git-terraform", 1) + } + case "gitlab": + executionControl = viper.GetBool("kubefirst-checks.terraform-apply-gitlab") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") + + log.Info().Msg("Creating GitLab resources with Terraform") + + tfEntrypoint := config.GitopsDir + "/terraform/gitlab" + tfEnvs := map[string]string{ + "GITLAB_TOKEN": cGitToken, + "GITLAB_OWNER": gitlabGroupFlag, + "TF_VAR_owner_group_id": strconv.Itoa(cGitlabOwnerGroupID), + "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), + "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, + "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, + "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, + "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, + } + if config.GitProtocol == "https" { + tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" + } + + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) + if err != nil { + msg := fmt.Errorf("error creating GitLab resources with terraform %q: %w", tfEntrypoint, err) + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) + return msg + } + + log.Info().Msgf("created git projects and groups for gitlab.com/%s", gitlabGroupFlag) + viper.Set("kubefirst-checks.terraform-apply-gitlab", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.GitTerraformApplyCompleted, "") + progressPrinter.IncrementTracker("applying-git-terraform", 1) + } else { + log.Info().Msg("already created GitLab Terraform resources") + progressPrinter.IncrementTracker("applying-git-terraform", 1) + } + } + + progressPrinter.AddTracker("pushing-gitops-repos-upstream", "Pushing git repositories", 1) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + log.Info().Msgf("referencing gitops repository: %q", config.DestinationGitopsRepoGitURL) + log.Info().Msgf("referencing metaphor repository: %q", config.DestinationMetaphorRepoURL) + + executionControl = viper.GetBool("kubefirst-checks.gitops-repo-pushed") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushStarted, "") + + gitopsRepo, err := git.PlainOpen(config.GitopsDir) + if err != nil { + return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) + } + + metaphorRepo, err := git.PlainOpen(config.MetaphorDir) + if err != nil { + return fmt.Errorf("error opening repo at %q: %w", config.MetaphorDir, err) + } + + err = utils.EvalSSHKey(&types.EvalSSHKeyRequest{ + GitProvider: gitProviderFlag, + GitlabGroupFlag: gitlabGroupFlag, + GitToken: cGitToken, + }) + if err != nil { + return fmt.Errorf("failed to evaluate SSH key: %w", err) + } + + err = gitopsRepo.Push( + &git.PushOptions{ + RemoteName: config.GitProvider, + Auth: httpAuth, + }, + ) + if err != nil { + msg := fmt.Errorf("error pushing detokenized gitops repository to remote %q: %w", config.DestinationGitopsRepoGitURL, err) + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) + if !strings.Contains(msg.Error(), "already up-to-date") { + log.Printf(msg.Error()) + return msg + } + } + + err = metaphorRepo.Push( + &git.PushOptions{ + RemoteName: "origin", + Auth: httpAuth, + }, + ) + if err != nil { + msg := fmt.Errorf("error pushing detokenized metaphor repository to remote %q: %w", config.DestinationMetaphorRepoURL, err) + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) + if !strings.Contains(msg.Error(), "already up-to-date") { + return msg + } + } + log.Info().Msgf("successfully pushed gitops and metaphor repositories to https://%s/%s", cGitHost, cGitOwner) + + viper.Set("kubefirst-checks.gitops-repo-pushed", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.GitopsRepoPushCompleted, "") + progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) + } else { + log.Info().Msg("already pushed detokenized gitops repository content") + progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) + } + + progressPrinter.AddTracker("creating-k3d-cluster", "Creating k3d cluster", 1) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + if !viper.GetBool("kubefirst-checks.create-k3d-cluster") { + telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyStarted, "") + + log.Info().Msg("Creating k3d cluster") + + err := k3d.ClusterCreate(clusterNameFlag, config.K1Dir, config.K3dClient, config.Kubeconfig) + if err != nil { + msg := fmt.Errorf("error creating k3d resources with k3d client %q: %w", config.K3dClient, err) + viper.Set("kubefirst-checks.create-k3d-cluster-failed", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyFailed, msg.Error()) + return msg + } + + log.Info().Msg("successfully created k3d cluster") + viper.Set("kubefirst-checks.create-k3d-cluster", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyCompleted, "") + progressPrinter.IncrementTracker("creating-k3d-cluster", 1) + } else { + log.Info().Msg("already created k3d cluster resources") + progressPrinter.IncrementTracker("creating-k3d-cluster", 1) + } + + kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) + + progressPrinter.AddTracker("bootstrapping-kubernetes-resources", "Bootstrapping Kubernetes resources", 2) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + executionControl = viper.GetBool("kubefirst-checks.k8s-secrets-created") + if !executionControl { + err := k3d.GenerateTLSSecrets(kcfg.Clientset, *config) + if err != nil { + return fmt.Errorf("failed to generate TLS secrets: %w", err) + } + + err = k3d.AddK3DSecrets( + atlantisWebhookSecret, + viper.GetString("kbot.public-key"), + gitopsRepoURL, + viper.GetString("kbot.private-key"), + config.GitProvider, + cGitUser, + cGitOwner, + config.Kubeconfig, + cGitToken, + ) + if err != nil { + log.Info().Msg("Error adding kubernetes secrets for bootstrap") + return fmt.Errorf("failed to add Kubernetes secrets: %w", err) + } + viper.Set("kubefirst-checks.k8s-secrets-created", true) + viper.WriteConfig() + progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) + } else { + log.Info().Msg("already added secrets to k3d cluster") + progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) + } + + containerRegistryAuth := gitShim.ContainerRegistryAuth{ + GitProvider: gitProviderFlag, + GitUser: cGitUser, + GitToken: cGitToken, + GitlabGroupFlag: gitlabGroupFlag, + GithubOwner: cGitOwner, + ContainerRegistryHost: containerRegistryHost, + Clientset: kcfg.Clientset, + } + containerRegistryAuthToken, err := gitShim.CreateContainerRegistrySecret(&containerRegistryAuth) + if err != nil { + return fmt.Errorf("failed to create container registry secret: %w", err) + } + progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) + + progressPrinter.AddTracker("verifying-k3d-cluster-readiness", "Verifying Kubernetes cluster is ready", 3) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + traefikDeployment, err := k8s.ReturnDeploymentObject( + kcfg.Clientset, + "app.kubernetes.io/name", + "traefik", + "kube-system", + 240, + ) + if err != nil { + return fmt.Errorf("error finding traefik deployment: %w", err) + } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, traefikDeployment, 240) + if err != nil { + return fmt.Errorf("error waiting for traefik deployment ready state: %w", err) + } + progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) + + metricsServerDeployment, err := k8s.ReturnDeploymentObject( + kcfg.Clientset, + "k8s-app", + "metrics-server", + "kube-system", + 240, + ) + if err != nil { + return fmt.Errorf("error finding metrics-server deployment: %w", err) + } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, metricsServerDeployment, 240) + if err != nil { + return fmt.Errorf("error waiting for metrics-server deployment ready state: %w", err) + } + progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) + + time.Sleep(time.Second * 20) + + progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) + + progressPrinter.AddTracker("installing-argo-cd", "Installing and configuring Argo CD", 3) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + argoCDInstallPath := fmt.Sprintf("github.com:konstructio/manifests/argocd/k3d?ref=%s", constants.KubefirstManifestRepoRef) + executionControl = viper.GetBool("kubefirst-checks.argocd-install") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.ArgoCDInstallStarted, "") + + log.Info().Msgf("installing ArgoCD") + + yamlData, err := kcfg.KustomizeBuild(argoCDInstallPath) + if err != nil { + return fmt.Errorf("failed to build ArgoCD manifests: %w", err) + } + output, err := kcfg.SplitYAMLFile(yamlData) + if err != nil { + return fmt.Errorf("failed to split YAML file: %w", err) + } + err = kcfg.ApplyObjects("", output) + if err != nil { + telemetry.SendEvent(segClient, telemetry.ArgoCDInstallFailed, err.Error()) + return fmt.Errorf("failed to apply ArgoCD objects: %w", err) + } + + viper.Set("kubefirst-checks.argocd-install", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.ArgoCDInstallCompleted, "") + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } else { + log.Info().Msg("ArgoCD already installed, continuing") + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } + + _, err = k8s.VerifyArgoCDReadiness(kcfg.Clientset, true, 300) + if err != nil { + return fmt.Errorf("error waiting for ArgoCD to become ready: %w", err) + } + + var argocdPassword string + executionControl = viper.GetBool("kubefirst-checks.argocd-credentials-set") + if !executionControl { + log.Info().Msg("Setting ArgoCD username and password credentials") + + argocd.ArgocdSecretClient = kcfg.Clientset.CoreV1().Secrets("argocd") + + argocdPassword = k8s.GetSecretValue(argocd.ArgocdSecretClient, "argocd-initial-admin-secret", "password") + if argocdPassword == "" { + return errors.New("ArgoCD password not found in secret") + } + + viper.Set("components.argocd.password", argocdPassword) + viper.Set("components.argocd.username", "admin") + viper.WriteConfig() + log.Info().Msg("ArgoCD username and password credentials set successfully") + log.Info().Msg("Getting an ArgoCD auth token") + + var argoCDToken string + if err := utils.TestEndpointTLS(strings.Replace(k3d.ArgocdURL, "https://", "", 1)); err != nil { + argoCDStopChannel := make(chan struct{}, 1) + log.Info().Msgf("ArgoCD not available via https, using http") + defer func() { + close(argoCDStopChannel) + }() + k8s.OpenPortForwardPodWrapper( + kcfg.Clientset, + kcfg.RestConfig, + "argocd-server", + "argocd", + 8080, + 8080, + argoCDStopChannel, + ) + argoCDHTTPURL := strings.Replace( + k3d.ArgocdURL, + "https://", + "http://", + 1, + ) + ":8080" + argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, argoCDHTTPURL, "admin", argocdPassword) + if err != nil { + return err + } + } else { + argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, k3d.ArgocdURL, "admin", argocdPassword) + if err != nil { + return err + } + } + + log.Info().Msg("ArgoCD admin auth token set") + + viper.Set("components.argocd.auth-token", argoCDToken) + viper.Set("kubefirst-checks.argocd-credentials-set", true) + viper.WriteConfig() + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } else { + log.Info().Msg("ArgoCD credentials already set, continuing") + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } + + if configs.K1Version == "development" { + err := clipboard.WriteAll(argocdPassword) + if err != nil { + log.Error().Err(err).Msg("failed to copy ArgoCD password to clipboard") + } + + if os.Getenv("SKIP_ARGOCD_LAUNCH") != "true" || !ciFlag { + err = utils.OpenBrowser(constants.ArgoCDLocalURLTLS) + if err != nil { + log.Error().Err(err).Msg("failed to open ArgoCD URL in browser") + } + } + } + + executionControl = viper.GetBool("kubefirst-checks.argocd-create-registry") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.CreateRegistryStarted, "") + argocdClient, err := argocdapi.NewForConfig(kcfg.RestConfig) + if err != nil { + return fmt.Errorf("failed to create ArgoCD client: %w", err) + } + + log.Info().Msg("applying the registry application to ArgoCD") + registryApplicationObject := argocd.GetArgoCDApplicationObject(gitopsRepoURL, fmt.Sprintf("registry/%s", clusterNameFlag)) + + err = k3d.RestartDeployment(context.Background(), kcfg.Clientset, "argocd", "argocd-applicationset-controller") + if err != nil { + return fmt.Errorf("error in restarting ArgoCD controller: %w", err) + } + + err = wait.PollImmediate(5*time.Second, 20*time.Second, func() (bool, error) { + _, err := argocdClient.ArgoprojV1alpha1().Applications("argocd").Create(context.Background(), registryApplicationObject, metav1.CreateOptions{}) + if err != nil { + if errors.Is(err, syscall.ECONNREFUSED) { + return false, nil + } + + if apierrors.IsAlreadyExists(err) { + return true, nil + } + + return false, fmt.Errorf("error creating ArgoCD application: %w", err) + } + return true, nil + }) + if err != nil { + return fmt.Errorf("error creating ArgoCD application: %w", err) + } + + log.Info().Msg("ArgoCD application created successfully") + viper.Set("kubefirst-checks.argocd-create-registry", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.CreateRegistryCompleted, "") + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } else { + log.Info().Msg("ArgoCD registry create already done, continuing") + progressPrinter.IncrementTracker("installing-argo-cd", 1) + } + + progressPrinter.AddTracker("configuring-vault", "Configuring Vault", 4) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + vaultStatefulSet, err := k8s.ReturnStatefulSetObject( + kcfg.Clientset, + "app.kubernetes.io/instance", + "vault", + "vault", + 120, + ) + if err != nil { + return fmt.Errorf("error finding Vault StatefulSet: %w", err) + } + _, err = k8s.WaitForStatefulSetReady(kcfg.Clientset, vaultStatefulSet, 120, true) + if err != nil { + return fmt.Errorf("error waiting for Vault StatefulSet ready state: %w", err) + } + progressPrinter.IncrementTracker("configuring-vault", 1) + + time.Sleep(time.Second * 10) + progressPrinter.IncrementTracker("configuring-vault", 1) + + executionControl = viper.GetBool("kubefirst-checks.vault-initialized") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.VaultInitializationStarted, "") + + vaultHandlerPath := "github.com:kubefirst/manifests.git/vault-handler/replicas-1" + + yamlData, err := kcfg.KustomizeBuild(vaultHandlerPath) + if err != nil { + return fmt.Errorf("failed to build vault handler manifests: %w", err) + } + output, err := kcfg.SplitYAMLFile(yamlData) + if err != nil { + return fmt.Errorf("failed to split YAML file: %w", err) + } + err = kcfg.ApplyObjects("", output) + if err != nil { + return fmt.Errorf("failed to apply vault handler objects: %w", err) + } + + job, err := k8s.ReturnJobObject(kcfg.Clientset, "vault", "vault-handler") + if err != nil { + return fmt.Errorf("failed to get vault job object: %w", err) + } + _, err = k8s.WaitForJobComplete(kcfg.Clientset, job, 240) + if err != nil { + msg := fmt.Errorf("could not run vault unseal job: %w", err) + telemetry.SendEvent(segClient, telemetry.VaultInitializationFailed, msg.Error()) + return msg + } + + viper.Set("kubefirst-checks.vault-initialized", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.VaultInitializationCompleted, "") + progressPrinter.IncrementTracker("configuring-vault", 1) + } else { + log.Info().Msg("vault is already initialized - skipping") + progressPrinter.IncrementTracker("configuring-vault", 1) + } + + minioStopChannel := make(chan struct{}, 1) + defer func() { + close(minioStopChannel) + }() + + k8s.OpenPortForwardPodWrapper( + kcfg.Clientset, + kcfg.RestConfig, + "minio", + "minio", + 9000, + 9000, + minioStopChannel, + ) + + minioClient, err := minio.New(constants.MinioPortForwardEndpoint, &minio.Options{ + Creds: credentials.NewStaticV4(constants.MinioDefaultUsername, constants.MinioDefaultPassword, ""), + Secure: false, + Region: constants.MinioRegion, + }) + if err != nil { + return fmt.Errorf("error creating Minio client: %w", err) + } + + objectName := fmt.Sprintf("terraform/%s/terraform.tfstate", config.GitProvider) + filePath := config.K1Dir + fmt.Sprintf("/gitops/%s", objectName) + contentType := "xl.meta" + bucketName := "kubefirst-state-store" + log.Info().Msgf("BucketName: %q", bucketName) + + viper.Set("kubefirst.state-store.name", bucketName) + viper.Set("kubefirst.state-store.hostname", "minio-console.kubefirst.dev") + viper.Set("kubefirst.state-store-creds.access-key-id", constants.MinioDefaultUsername) + viper.Set("kubefirst.state-store-creds.secret-access-key-id", constants.MinioDefaultPassword) + + info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType}) + if err != nil { + return fmt.Errorf("error uploading to Minio bucket: %w", err) + } + + log.Printf("Successfully uploaded %q to bucket %q", objectName, info.Bucket) + + progressPrinter.IncrementTracker("configuring-vault", 1) + + vaultStopChannel := make(chan struct{}, 1) + defer func() { + close(vaultStopChannel) + }() + + k8s.OpenPortForwardPodWrapper( + kcfg.Clientset, + kcfg.RestConfig, + "vault-0", + "vault", + 8200, + 8200, + vaultStopChannel, + ) + + var vaultRootToken string + secData, err := k8s.ReadSecretV2(kcfg.Clientset, "vault", "vault-unseal-secret") + if err != nil { + return fmt.Errorf("failed to read vault unseal secret: %w", err) + } + + vaultRootToken = secData["root-token"] + + kubernetesInClusterAPIService, err := k8s.ReadService(config.Kubeconfig, "default", "kubernetes") + if err != nil { + return fmt.Errorf("error looking up kubernetes api server service: %w", err) + } + + if err := utils.TestEndpointTLS(strings.Replace(k3d.VaultURL, "https://", "", 1)); err != nil { + return fmt.Errorf("unable to reach vault over https: %w", err) + } + + executionControl = viper.GetBool("kubefirst-checks.terraform-apply-vault") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, "") + + tfEnvs := map[string]string{} + var usernamePasswordString, base64DockerAuth string + + if config.GitProvider == "gitlab" { + usernamePasswordString = fmt.Sprintf("%s:%s", "container-registry-auth", containerRegistryAuthToken) + base64DockerAuth = base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) + + tfEnvs["TF_VAR_container_registry_auth"] = containerRegistryAuthToken + tfEnvs["TF_VAR_owner_group_id"] = strconv.Itoa(cGitlabOwnerGroupID) + } else { + usernamePasswordString = fmt.Sprintf("%s:%s", cGitUser, cGitToken) + base64DockerAuth = base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) + } + + log.Info().Msg("configuring vault with terraform") + + tfEnvs["TF_VAR_email_address"] = "your@email.com" + tfEnvs[fmt.Sprintf("TF_VAR_%s_token", config.GitProvider)] = cGitToken + tfEnvs[fmt.Sprintf("TF_VAR_%s_user", config.GitProvider)] = cGitUser + tfEnvs["TF_VAR_vault_addr"] = k3d.VaultPortForwardURL + tfEnvs["TF_VAR_b64_docker_auth"] = base64DockerAuth + tfEnvs["TF_VAR_vault_token"] = vaultRootToken + tfEnvs["VAULT_ADDR"] = k3d.VaultPortForwardURL + tfEnvs["VAULT_TOKEN"] = vaultRootToken + tfEnvs["TF_VAR_atlantis_repo_webhook_secret"] = viper.GetString("secrets.atlantis-webhook") + tfEnvs["TF_VAR_kbot_ssh_private_key"] = viper.GetString("kbot.private-key") + tfEnvs["TF_VAR_kbot_ssh_public_key"] = viper.GetString("kbot.public-key") + tfEnvs["TF_VAR_kubernetes_api_endpoint"] = fmt.Sprintf("https://%s", kubernetesInClusterAPIService.Spec.ClusterIP) + tfEnvs[fmt.Sprintf("%s_OWNER", strings.ToUpper(config.GitProvider))] = viper.GetString(fmt.Sprintf("flags.%s-owner", config.GitProvider)) + tfEnvs["AWS_ACCESS_KEY_ID"] = constants.MinioDefaultUsername + tfEnvs["AWS_SECRET_ACCESS_KEY"] = constants.MinioDefaultPassword + tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername + tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword + tfEnvs["TF_VAR_ngrok_authtoken"] = viper.GetString("secrets.atlantis-ngrok-authtoken") + + tfEntrypoint := config.GitopsDir + "/terraform/vault" + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) + if err != nil { + telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, err.Error()) + return fmt.Errorf("failed to execute vault terraform: %w", err) + } + log.Info().Msg("vault terraform executed successfully") + viper.Set("kubefirst-checks.terraform-apply-vault", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyCompleted, "") + progressPrinter.IncrementTracker("configuring-vault", 1) + } else { + log.Info().Msg("already executed vault terraform") + progressPrinter.IncrementTracker("configuring-vault", 1) + } + + progressPrinter.AddTracker("creating-users", "Creating users", 1) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + executionControl = viper.GetBool("kubefirst-checks.terraform-apply-users") + if !executionControl { + telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyStarted, "") + + log.Info().Msg("applying users terraform") + + tfEnvs := map[string]string{} + tfEnvs["TF_VAR_email_address"] = "your@email.com" + tfEnvs[fmt.Sprintf("TF_VAR_%s_token", config.GitProvider)] = cGitToken + tfEnvs["TF_VAR_vault_addr"] = k3d.VaultPortForwardURL + tfEnvs["TF_VAR_vault_token"] = vaultRootToken + tfEnvs["VAULT_ADDR"] = k3d.VaultPortForwardURL + tfEnvs["VAULT_TOKEN"] = vaultRootToken + tfEnvs[fmt.Sprintf("%s_TOKEN", strings.ToUpper(config.GitProvider))] = cGitToken + tfEnvs[fmt.Sprintf("%s_OWNER", strings.ToUpper(config.GitProvider))] = cGitOwner + + tfEntrypoint := config.GitopsDir + "/terraform/users" + err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) + if err != nil { + telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyStarted, err.Error()) + return fmt.Errorf("failed to apply users terraform: %w", err) + } + log.Info().Msg("executed users terraform successfully") + viper.Set("kubefirst-checks.terraform-apply-users", true) + viper.WriteConfig() + telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyCompleted, "") + progressPrinter.IncrementTracker("creating-users", 1) + } else { + log.Info().Msg("already created users with terraform") + progressPrinter.IncrementTracker("creating-users", 1) + } + + progressPrinter.AddTracker("wrapping-up", "Wrapping up", 2) + progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) + + err = k3d.PostRunPrepareGitopsRepository(clusterNameFlag, config.GitopsDir, &gitopsDirectoryTokens) + if err != nil { + return fmt.Errorf("error detokenizing post run: %w", err) + } + gitopsRepo, err := git.PlainOpen(config.GitopsDir) + if err != nil { + return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) + } + _, err = os.Stat(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider)) + if err == nil { + err = os.Rename(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider), fmt.Sprintf("%s/terraform/%s/remote-backend.tf", config.GitopsDir, config.GitProvider)) + if err != nil { + return fmt.Errorf("failed to rename remote-backend.md to remote-backend.tf: %w", err) + } + } + viper.Set("kubefirst-checks.post-detokenize", true) + viper.WriteConfig() + + err = gitClient.Commit(gitopsRepo, "committing initial detokenized gitops-template repo content post run") + if err != nil { + return fmt.Errorf("failed to commit initial detokenized gitops-template repo content: %w", err) + } + err = gitopsRepo.Push(&git.PushOptions{ + RemoteName: config.GitProvider, + Auth: httpAuth, + }) + if err != nil { + return fmt.Errorf("failed to push initial detokenized gitops-template repo content: %w", err) + } + + progressPrinter.IncrementTracker("wrapping-up", 1) + + argoDeployment, err := k8s.ReturnDeploymentObject(kcfg.Clientset, "app.kubernetes.io/instance", "argo", "argo", 1200) + if err != nil { + return fmt.Errorf("error finding Argo Workflows Deployment: %w", err) + } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, argoDeployment, 120) + if err != nil { + return fmt.Errorf("error waiting for Argo Workflows Deployment ready state: %w", err) + } + + utils.SetClusterStatusFlags(k3d.CloudProvider, config.GitProvider) + + cluster := utilities.CreateClusterRecordFromRaw(useTelemetryFlag, cGitOwner, cGitUser, cGitToken, cGitlabOwnerGroupID, gitopsTemplateURLFlag, gitopsTemplateBranchFlag, catalogApps) + + err = utilities.ExportCluster(cluster, kcfg) + if err != nil { + log.Error().Err(err).Msg("error exporting cluster object") + viper.Set("kubefirst.setup-complete", false) + viper.Set("kubefirst-checks.cluster-install-complete", false) + viper.WriteConfig() + return fmt.Errorf("failed to export cluster object: %w", err) + } else { + kubefirstDeployment, err := k8s.ReturnDeploymentObject( + kcfg.Clientset, + "app.kubernetes.io/instance", + "kubefirst", + "kubefirst", + 600, + ) + if err != nil { + return fmt.Errorf("error finding kubefirst Deployment: %w", err) + } + _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, kubefirstDeployment, 120) + if err != nil { + return fmt.Errorf("error waiting for kubefirst Deployment ready state: %w", err) + } + progressPrinter.IncrementTracker("wrapping-up", 1) + + err = utils.OpenBrowser(constants.KubefirstConsoleLocalURLTLS) + if err != nil { + log.Error().Err(err).Msg("failed to open Kubefirst console in browser") + } + + telemetry.SendEvent(segClient, telemetry.ClusterInstallCompleted, "") + viper.Set("kubefirst-checks.cluster-install-complete", true) + viper.WriteConfig() + + log.Info().Msg("kubefirst installation complete") + log.Info().Msg("welcome to your new Kubefirst platform running in K3D") + time.Sleep(1 * time.Second) + + reports.LocalHandoffScreenV2(viper.GetString("components.argocd.password"), clusterNameFlag, gitDestDescriptor, cGitOwner, config, ciFlag) + + if ciFlag { + progress.Progress.Quit() + } + } + + return nil +} diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 6086ae2b4..6a0b84c0b 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -102,11 +102,15 @@ func createVultr(cmd *cobra.Command, _ []string) error { return fmt.Errorf("kubefirst api availability check failed: %w", err) } +<<<<<<< HEAD if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { progress.Error(err.Error()) return fmt.Errorf("failed to create management cluster: %w", err) } +======= + provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) +>>>>>>> bb91e1c (Clean up code using GolangCI-Lint) return nil } From 1c1d84fbe8cc1cd3ca3a67cbde188553ca3c4def Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:30:08 -0400 Subject: [PATCH 71/85] Fix version printing. --- cmd/version.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/version.go b/cmd/version.go index f32fd475d..17ddf79c5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -7,8 +7,6 @@ See the LICENSE file for more details. package cmd import ( - "fmt" - "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" From c988184a5cb5f332c0714df9616ad5eb0fd7a8a6 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:06:16 -0400 Subject: [PATCH 72/85] Cleanup internal folder --- internal/provisionLogs/message.go | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 internal/provisionLogs/message.go diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go new file mode 100644 index 000000000..1b5ec5043 --- /dev/null +++ b/internal/provisionLogs/message.go @@ -0,0 +1,33 @@ +/* +Copyright (C) 2021-2023, Kubefirst + +This program is licensed under MIT. +See the LICENSE file for more details. + +Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go +Color definition https://www.ditig.com/256-colors-cheat-sheet +*/ +package provisionLogs + +import ( + "fmt" + "log" + + "github.com/charmbracelet/glamour" + "github.com/konstructio/kubefirst/internal/progress" +) + +func renderMessage(message string) string { + r, _ := glamour.NewTermRenderer( + glamour.WithStyles(progress.StyleConfig), + glamour.WithEmoji(), + ) + + out, err := r.Render(message) + if err != nil { + s := fmt.Errorf("rendering message failed: %w", err) + log.Println(s) + return s.Error() + } + return out +} From 8831cf26e1ca62d02417129dff07a64c2a484b8e Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:39:03 -0400 Subject: [PATCH 73/85] Update using final standard linters --- cmd/version.go | 2 ++ internal/provisionLogs/message.go | 33 ------------------------------- 2 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 internal/provisionLogs/message.go diff --git a/cmd/version.go b/cmd/version.go index 17ddf79c5..f32fd475d 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -7,6 +7,8 @@ See the LICENSE file for more details. package cmd import ( + "fmt" + "github.com/konstructio/kubefirst-api/pkg/configs" "github.com/konstructio/kubefirst/internal/progress" "github.com/spf13/cobra" diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go deleted file mode 100644 index 1b5ec5043..000000000 --- a/internal/provisionLogs/message.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright (C) 2021-2023, Kubefirst - -This program is licensed under MIT. -See the LICENSE file for more details. - -Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go -Color definition https://www.ditig.com/256-colors-cheat-sheet -*/ -package provisionLogs - -import ( - "fmt" - "log" - - "github.com/charmbracelet/glamour" - "github.com/konstructio/kubefirst/internal/progress" -) - -func renderMessage(message string) string { - r, _ := glamour.NewTermRenderer( - glamour.WithStyles(progress.StyleConfig), - glamour.WithEmoji(), - ) - - out, err := r.Render(message) - if err != nil { - s := fmt.Errorf("rendering message failed: %w", err) - log.Println(s) - return s.Error() - } - return out -} From 1d6e0b58a7a2b27053e3186cbfaacf434a341db5 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 74/85] chore: bubbletea blacklist ci flag --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 4d0c8f833..847f6a7ab 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From 04ed9e2ddbb8cf9ddf70bf108cd287272656b5ab Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:05:51 -0500 Subject: [PATCH 75/85] chore: error handling --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 847f6a7ab..bb67b81d1 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} canRunBubbleTea := true for _, arg := range argsWithProg { From c30101c7561870a9f076101bcf75b660f11bf469 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 22:40:33 -0500 Subject: [PATCH 76/85] fix: bypass bubbletea execution --- main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.go b/main.go index bb67b81d1..4d0c8f833 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,7 @@ import ( func main() { argsWithProg := os.Args - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From 04ad3e195e71b178cbc68b05ff6ed99022dde3d9 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 18:10:01 -0500 Subject: [PATCH 77/85] chore: print cluster name --- internal/common/common.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/common/common.go b/internal/common/common.go index 3c4c6055c..8c162558b 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -114,6 +114,8 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { clusterName = clusteNameFromFlag } + fmt.Print(clusterName) + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) From 55dddf7b1f1625d5aec6beacb3e4207e2a6c420d Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Tue, 30 Jul 2024 21:47:03 -0500 Subject: [PATCH 78/85] chore: bubbletea blacklist ci flag --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 4d0c8f833..847f6a7ab 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) + viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From dd5dd3f1a81ae5965f653f54b5d71bc1eea192d4 Mon Sep 17 00:00:00 2001 From: konstruct-bot <1@gmail.com> Date: Thu, 5 Sep 2024 13:20:04 +0530 Subject: [PATCH 79/85] rebase --- internal/progress/message.go | 2 +- main.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/progress/message.go b/internal/progress/message.go index fea8cd23f..b9bdefffc 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -102,7 +102,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { case "vultr": cloudCliKubeconfig = fmt.Sprintf("vultr-cli kubernetes config %q", cluster.ClusterName) case "k3s": - cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) + cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster")) break } diff --git a/main.go b/main.go index 847f6a7ab..4d0c8f833 100644 --- a/main.go +++ b/main.go @@ -120,7 +120,6 @@ func main() { viper.Set("k1-paths.logs-dir", logsFolder) viper.Set("k1-paths.log-file", logfile) viper.Set("k1-paths.log-file-name", logfileName) - viper.Set("k1-canRunBubbleTea", canRunBubbleTea) if err := viper.WriteConfig(); err != nil { log.Error().Msgf("failed to write config: %v", err) From ff9681d497cd0d84c9e242d3a473a2ddde01d8f9 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:01:01 -0400 Subject: [PATCH 80/85] Remove unused functions. Bump to Go 1.23. Run `gofmt` on all files. --- internal/progress/message.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/progress/message.go b/internal/progress/message.go index b9bdefffc..fea8cd23f 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -102,7 +102,7 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { case "vultr": cloudCliKubeconfig = fmt.Sprintf("vultr-cli kubernetes config %q", cluster.ClusterName) case "k3s": - cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputed from terraform to acces to the cluster")) + cloudCliKubeconfig = fmt.Sprint(("use the kubeconfig file outputted from terraform to acces to the cluster")) break } From c1c3a1ff29a9074883b587f3d2620eab489cb30b Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:26:42 -0400 Subject: [PATCH 81/85] Clean up code using GolangCI-Lint --- cmd/letsencrypt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/letsencrypt.go b/cmd/letsencrypt.go index 1a1071d5e..48ac2cc60 100644 --- a/cmd/letsencrypt.go +++ b/cmd/letsencrypt.go @@ -7,7 +7,7 @@ See the LICENSE file for more details. package cmd import ( - "fmt" + "log" "github.com/konstructio/kubefirst-api/pkg/certificates" "github.com/konstructio/kubefirst/internal/progress" From 48fb8b7afea6c8f9d88ea9e9b72dce9987fafb5b Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:06:16 -0400 Subject: [PATCH 82/85] Cleanup internal folder --- internal/provisionLogs/message.go | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 internal/provisionLogs/message.go diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go new file mode 100644 index 000000000..1b5ec5043 --- /dev/null +++ b/internal/provisionLogs/message.go @@ -0,0 +1,33 @@ +/* +Copyright (C) 2021-2023, Kubefirst + +This program is licensed under MIT. +See the LICENSE file for more details. + +Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go +Color definition https://www.ditig.com/256-colors-cheat-sheet +*/ +package provisionLogs + +import ( + "fmt" + "log" + + "github.com/charmbracelet/glamour" + "github.com/konstructio/kubefirst/internal/progress" +) + +func renderMessage(message string) string { + r, _ := glamour.NewTermRenderer( + glamour.WithStyles(progress.StyleConfig), + glamour.WithEmoji(), + ) + + out, err := r.Render(message) + if err != nil { + s := fmt.Errorf("rendering message failed: %w", err) + log.Println(s) + return s.Error() + } + return out +} From 00b8bdd78dde294c9152b00f3b7c6665d258f325 Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:39:03 -0400 Subject: [PATCH 83/85] Update using final standard linters --- internal/provisionLogs/message.go | 33 ------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 internal/provisionLogs/message.go diff --git a/internal/provisionLogs/message.go b/internal/provisionLogs/message.go deleted file mode 100644 index 1b5ec5043..000000000 --- a/internal/provisionLogs/message.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright (C) 2021-2023, Kubefirst - -This program is licensed under MIT. -See the LICENSE file for more details. - -Emojis definition https://github.com/yuin/goldmark-emoji/blob/master/definition/github.go -Color definition https://www.ditig.com/256-colors-cheat-sheet -*/ -package provisionLogs - -import ( - "fmt" - "log" - - "github.com/charmbracelet/glamour" - "github.com/konstructio/kubefirst/internal/progress" -) - -func renderMessage(message string) string { - r, _ := glamour.NewTermRenderer( - glamour.WithStyles(progress.StyleConfig), - glamour.WithEmoji(), - ) - - out, err := r.Render(message) - if err != nil { - s := fmt.Errorf("rendering message failed: %w", err) - log.Println(s) - return s.Error() - } - return out -} From e854a66c3189ba9e48667b32f822cc2b46adcd19 Mon Sep 17 00:00:00 2001 From: CristhianF7 Date: Thu, 1 Aug 2024 18:10:01 -0500 Subject: [PATCH 84/85] chore: print cluster name --- internal/common/common.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/common/common.go b/internal/common/common.go index 8c162558b..d06bcbc8d 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -116,6 +116,8 @@ func GetRootCredentials(cmd *cobra.Command, args []string) error { fmt.Print(clusterName) + fmt.Print(clusterName) + cluster, err := cluster.GetCluster(clusterName) if err != nil { progress.Error(err.Error()) From 6e1a184ad8483b07e5a7e510cff24f99041df406 Mon Sep 17 00:00:00 2001 From: mrrishi Date: Thu, 19 Sep 2024 04:21:13 +0530 Subject: [PATCH 85/85] minor changes --- cmd/k3d/create.go | 1267 ------------------------------------------- cmd/letsencrypt.go | 2 +- cmd/vultr/create.go | 4 - go.mod | 4 +- go.sum | 7 +- 5 files changed, 4 insertions(+), 1280 deletions(-) diff --git a/cmd/k3d/create.go b/cmd/k3d/create.go index fe57bbe9b..f70fefb4a 100644 --- a/cmd/k3d/create.go +++ b/cmd/k3d/create.go @@ -1272,1270 +1272,3 @@ func runK3d(cmd *cobra.Command, _ []string) error { return nil } - -/* -Copyright (C) 2021-2023, Kubefirst - -This program is licensed under MIT. -See the LICENSE file for more details. -*/ -package k3d - -import ( - "context" - "encoding/base64" - "errors" - "fmt" - "net/http" - "os" - "strconv" - "strings" - "syscall" - "time" - - argocdapi "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" - "github.com/atotto/clipboard" - "github.com/dustin/go-humanize" - "github.com/go-git/go-git/v5" - githttps "github.com/go-git/go-git/v5/plumbing/transport/http" - "github.com/konstructio/kubefirst-api/pkg/argocd" - "github.com/konstructio/kubefirst-api/pkg/configs" - constants "github.com/konstructio/kubefirst-api/pkg/constants" - "github.com/konstructio/kubefirst-api/pkg/gitClient" - "github.com/konstructio/kubefirst-api/pkg/github" - "github.com/konstructio/kubefirst-api/pkg/gitlab" - "github.com/konstructio/kubefirst-api/pkg/handlers" - "github.com/konstructio/kubefirst-api/pkg/k3d" - "github.com/konstructio/kubefirst-api/pkg/k8s" - "github.com/konstructio/kubefirst-api/pkg/progressPrinter" - "github.com/konstructio/kubefirst-api/pkg/reports" - "github.com/konstructio/kubefirst-api/pkg/services" - internalssh "github.com/konstructio/kubefirst-api/pkg/ssh" - "github.com/konstructio/kubefirst-api/pkg/terraform" - "github.com/konstructio/kubefirst-api/pkg/types" - utils "github.com/konstructio/kubefirst-api/pkg/utils" - "github.com/konstructio/kubefirst-api/pkg/wrappers" - "github.com/konstructio/kubefirst/internal/catalog" - "github.com/konstructio/kubefirst/internal/gitShim" - "github.com/konstructio/kubefirst/internal/progress" - "github.com/konstructio/kubefirst/internal/segment" - "github.com/konstructio/kubefirst/internal/utilities" - "github.com/kubefirst/metrics-client/pkg/telemetry" - "github.com/minio/minio-go/v7" - "github.com/minio/minio-go/v7/pkg/credentials" - "github.com/rs/zerolog/log" - "github.com/spf13/cobra" - "github.com/spf13/viper" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" -) - -func runK3d(cmd *cobra.Command, args []string) error { - ciFlag, err := cmd.Flags().GetBool("ci") - if err != nil { - return fmt.Errorf("failed to get 'ci' flag: %w", err) - } - - clusterNameFlag, err := cmd.Flags().GetString("cluster-name") - if err != nil { - return fmt.Errorf("failed to get 'cluster-name' flag: %w", err) - } - - clusterTypeFlag, err := cmd.Flags().GetString("cluster-type") - if err != nil { - return fmt.Errorf("failed to get 'cluster-type' flag: %w", err) - } - - githubOrgFlag, err := cmd.Flags().GetString("github-org") - if err != nil { - return fmt.Errorf("failed to get 'github-org' flag: %w", err) - } - - githubUserFlag, err := cmd.Flags().GetString("github-user") - if err != nil { - return fmt.Errorf("failed to get 'github-user' flag: %w", err) - } - - gitlabGroupFlag, err := cmd.Flags().GetString("gitlab-group") - if err != nil { - return fmt.Errorf("failed to get 'gitlab-group' flag: %w", err) - } - - gitProviderFlag, err := cmd.Flags().GetString("git-provider") - if err != nil { - return fmt.Errorf("failed to get 'git-provider' flag: %w", err) - } - - gitProtocolFlag, err := cmd.Flags().GetString("git-protocol") - if err != nil { - return fmt.Errorf("failed to get 'git-protocol' flag: %w", err) - } - - gitopsTemplateURLFlag, err := cmd.Flags().GetString("gitops-template-url") - if err != nil { - return fmt.Errorf("failed to get 'gitops-template-url' flag: %w", err) - } - - gitopsTemplateBranchFlag, err := cmd.Flags().GetString("gitops-template-branch") - if err != nil { - return fmt.Errorf("failed to get 'gitops-template-branch' flag: %w", err) - } - - installCatalogAppsFlag, err := cmd.Flags().GetString("install-catalog-apps") - if err != nil { - return fmt.Errorf("failed to get 'install-catalog-apps' flag: %w", err) - } - - useTelemetryFlag, err := cmd.Flags().GetBool("use-telemetry") - if err != nil { - return fmt.Errorf("failed to get 'use-telemetry' flag: %w", err) - } - - utilities.CreateK1ClusterDirectory(clusterNameFlag) - utils.DisplayLogHints() - - isValid, catalogApps, err := catalog.ValidateCatalogApps(installCatalogAppsFlag) - if !isValid { - return err - } - - switch gitProviderFlag { - case "github": - key, err := internalssh.GetHostKey("github.com") - if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan github.com >> ~/.ssh/known_hosts` to remedy: %w", err) - } - log.Info().Msgf("Host key for github.com: %q", key.Type()) - case "gitlab": - key, err := internalssh.GetHostKey("gitlab.com") - if err != nil { - return fmt.Errorf("known_hosts file does not exist - please run `ssh-keyscan gitlab.com >> ~/.ssh/known_hosts` to remedy: %w", err) - } - log.Info().Msgf("Host key for gitlab.com: %q", key.Type()) - } - - if githubOrgFlag != "" && githubUserFlag != "" { - return errors.New("only one of --github-user or --github-org can be supplied") - } - - err = k8s.CheckForExistingPortForwards(8080, 8200, 9000, 9094) - if err != nil { - return fmt.Errorf("error checking existing port forwards: %w", err) - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - httpClient := http.DefaultClient - - kubefirstTeam := os.Getenv("KUBEFIRST_TEAM") - if kubefirstTeam == "" { - kubefirstTeam = "false" - } - - viper.Set("flags.cluster-name", clusterNameFlag) - viper.Set("flags.domain-name", k3d.DomainName) - viper.Set("flags.git-provider", gitProviderFlag) - viper.Set("flags.git-protocol", gitProtocolFlag) - viper.Set("kubefirst.cloud-provider", "k3d") - viper.WriteConfig() - - var cGitHost, cGitOwner, cGitUser, cGitToken, containerRegistryHost string - var cGitlabOwnerGroupID int - switch gitProviderFlag { - case "github": - cGitHost = k3d.GithubHost - containerRegistryHost = "ghcr.io" - - gitHubService := services.NewGitHubService(httpClient) - gitHubHandler := handlers.NewGitHubHandler(gitHubService) - - var existingToken string - if os.Getenv("GITHUB_TOKEN") != "" { - existingToken = os.Getenv("GITHUB_TOKEN") - } else if viper.GetString("github.session_token") != "" { - existingToken = viper.GetString("github.session_token") - } - gitHubAccessToken, err := wrappers.AuthenticateGitHubUserWrapper(existingToken, gitHubHandler) - if err != nil { - log.Warn().Msg(err.Error()) - } - - cGitToken = gitHubAccessToken - - err = github.VerifyTokenPermissions(cGitToken) - if err != nil { - return fmt.Errorf("failed to verify GitHub token permissions: %w", err) - } - - log.Info().Msg("verifying GitHub authentication") - githubUser, err := gitHubHandler.GetGitHubUser(cGitToken) - if err != nil { - return fmt.Errorf("failed to get GitHub user: %w", err) - } - - if githubOrgFlag != "" { - cGitOwner = githubOrgFlag - } else { - cGitOwner = githubUser - } - cGitUser = githubUser - - viper.Set("flags.github-owner", cGitOwner) - viper.Set("github.session_token", cGitToken) - viper.WriteConfig() - case "gitlab": - if gitlabGroupFlag == "" { - return errors.New("please provide a gitlab group using the --gitlab-group flag") - } - - cGitToken = os.Getenv("GITLAB_TOKEN") - if cGitToken == "" { - return errors.New("GITLAB_TOKEN environment variable unset - please set it and try again") - } - - err = gitlab.VerifyTokenPermissions(cGitToken) - if err != nil { - return fmt.Errorf("failed to verify GitLab token permissions: %w", err) - } - - gitlabClient, err := gitlab.NewGitLabClient(cGitToken, gitlabGroupFlag) - if err != nil { - return fmt.Errorf("failed to create GitLab client: %w", err) - } - - cGitHost = k3d.GitlabHost - cGitOwner = gitlabClient.ParentGroupPath - cGitlabOwnerGroupID = gitlabClient.ParentGroupID - log.Info().Msgf("set gitlab owner to %q", cGitOwner) - - user, _, err := gitlabClient.Client.Users.CurrentUser() - if err != nil { - return fmt.Errorf("unable to get authenticated user info - please make sure GITLAB_TOKEN env var is set: %w", err) - } - cGitUser = user.Username - viper.Set("flags.gitlab-owner", gitlabGroupFlag) - viper.Set("flags.gitlab-owner-group-id", cGitlabOwnerGroupID) - viper.Set("gitlab.session_token", cGitToken) - viper.WriteConfig() - default: - return fmt.Errorf("invalid git provider option %q", gitProviderFlag) - } - - var gitDestDescriptor string - switch gitProviderFlag { - case "github": - if githubOrgFlag != "" { - gitDestDescriptor = "Organization" - } else { - gitDestDescriptor = "User" - } - case "gitlab": - gitDestDescriptor = "Group" - } - - config := k3d.GetConfig(clusterNameFlag, gitProviderFlag, cGitOwner, gitProtocolFlag) - switch gitProviderFlag { - case "github": - config.GithubToken = cGitToken - case "gitlab": - config.GitlabToken = cGitToken - } - - var sshPrivateKey, sshPublicKey string - - // todo placed in configmap in kubefirst namespace, included in telemetry - clusterId := viper.GetString("kubefirst.cluster-id") - if clusterId == "" { - clusterId = utils.GenerateClusterID() - viper.Set("kubefirst.cluster-id", clusterId) - viper.WriteConfig() - } - - segClient := segment.InitClient(clusterId, clusterTypeFlag, gitProviderFlag) - - progressPrinter.AddTracker("preflight-checks", "Running preflight checks", 5) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - progressPrinter.IncrementTracker("preflight-checks", 1) - - switch configs.K1Version { - case "development": - if strings.Contains(gitopsTemplateURLFlag, "https://github.com/konstructio/gitops-template.git") && gitopsTemplateBranchFlag == "" { - gitopsTemplateBranchFlag = "main" - } - default: - switch gitopsTemplateURLFlag { - case "https://github.com/konstructio/gitops-template.git": - if gitopsTemplateBranchFlag == "" { - gitopsTemplateBranchFlag = configs.K1Version - } - case "https://github.com/konstructio/gitops-template": - if gitopsTemplateBranchFlag == "" { - gitopsTemplateBranchFlag = configs.K1Version - } - default: - if gitopsTemplateBranchFlag == "" { - return errors.New("must supply gitops-template-branch flag when gitops-template-url is overridden") - } - } - } - - log.Info().Msgf("kubefirst version configs.K1Version: %q", configs.K1Version) - log.Info().Msgf("cloning gitops-template repo url: %q", gitopsTemplateURLFlag) - log.Info().Msgf("cloning gitops-template repo branch: %q", gitopsTemplateBranchFlag) - - atlantisWebhookSecret := viper.GetString("secrets.atlantis-webhook") - if atlantisWebhookSecret == "" { - atlantisWebhookSecret = utils.Random(20) - viper.Set("secrets.atlantis-webhook", atlantisWebhookSecret) - viper.WriteConfig() - } - - atlantisNgrokAuthtoken := viper.GetString("secrets.atlantis-ngrok-authtoken") - if atlantisNgrokAuthtoken == "" { - atlantisNgrokAuthtoken = os.Getenv("NGROK_AUTHTOKEN") - viper.Set("secrets.atlantis-ngrok-authtoken", atlantisNgrokAuthtoken) - viper.WriteConfig() - } - - log.Info().Msg("checking authentication to required providers") - - free, err := utils.GetAvailableDiskSize() - if err != nil { - return fmt.Errorf("failed to get available disk size: %w", err) - } - - availableDiskSize := float64(free) / humanize.GByte - if availableDiskSize < constants.MinimumAvailableDiskSize { - return fmt.Errorf( - "there is not enough space to proceed with the installation, a minimum of %d GB is required to proceed", - constants.MinimumAvailableDiskSize, - ) - } - progressPrinter.IncrementTracker("preflight-checks", 1) - - newRepositoryNames := []string{"gitops", "metaphor"} - newTeamNames := []string{"admins", "developers"} - - executionControl := viper.GetBool(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider)) - if !executionControl { - telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckStarted, "") - if len(cGitToken) == 0 { - msg := fmt.Sprintf("please set a %s_TOKEN environment variable to continue", strings.ToUpper(config.GitProvider)) - telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckFailed, msg) - return errors.New(msg) - } - - initGitParameters := gitShim.GitInitParameters{ - GitProvider: gitProviderFlag, - GitToken: cGitToken, - GitOwner: cGitOwner, - Repositories: newRepositoryNames, - Teams: newTeamNames, - } - err = gitShim.InitializeGitProvider(&initGitParameters) - if err != nil { - return fmt.Errorf("failed to initialize Git provider: %w", err) - } - - viper.Set(fmt.Sprintf("kubefirst-checks.%s-credentials", config.GitProvider), true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.GitCredentialsCheckCompleted, "") - progressPrinter.IncrementTracker("preflight-checks", 1) - } else { - log.Info().Msg(fmt.Sprintf("already completed %q checks - continuing", config.GitProvider)) - progressPrinter.IncrementTracker("preflight-checks", 1) - } - - var gitopsRepoURL string - executionControl = viper.GetBool("kubefirst-checks.kbot-setup") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.KbotSetupStarted, "") - - log.Info().Msg("creating an ssh key pair for your new cloud infrastructure") - sshPrivateKey, sshPublicKey, err = utils.CreateSshKeyPair() - if err != nil { - telemetry.SendEvent(segClient, telemetry.KbotSetupFailed, err.Error()) - return fmt.Errorf("failed to create SSH key pair: %w", err) - } - log.Info().Msg("ssh key pair creation complete") - - viper.Set("kbot.private-key", sshPrivateKey) - viper.Set("kbot.public-key", sshPublicKey) - viper.Set("kbot.username", "kbot") - viper.Set("kubefirst-checks.kbot-setup", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.KbotSetupCompleted, "") - log.Info().Msg("kbot-setup complete") - progressPrinter.IncrementTracker("preflight-checks", 1) - } else { - log.Info().Msg("already setup kbot user - continuing") - progressPrinter.IncrementTracker("preflight-checks", 1) - } - - log.Info().Msg("validation and kubefirst cli environment check is complete") - - telemetry.SendEvent(segClient, telemetry.InitCompleted, "") - - switch config.GitProtocol { - case "https": - gitopsRepoURL = config.DestinationGitopsRepoURL - default: - gitopsRepoURL = config.DestinationGitopsRepoGitURL - } - - gitopsDirectoryTokens := k3d.GitopsDirectoryValues{ - GithubOwner: cGitOwner, - GithubUser: cGitUser, - GitlabOwner: cGitOwner, - GitlabOwnerGroupID: cGitlabOwnerGroupID, - GitlabUser: cGitUser, - DomainName: k3d.DomainName, - AtlantisAllowList: fmt.Sprintf("%s/%s/*", cGitHost, cGitOwner), - AlertsEmail: "REMOVE_THIS_VALUE", - ClusterName: clusterNameFlag, - ClusterType: clusterTypeFlag, - GithubHost: k3d.GithubHost, - GitlabHost: k3d.GitlabHost, - ArgoWorkflowsIngressURL: fmt.Sprintf("https://argo.%s", k3d.DomainName), - VaultIngressURL: fmt.Sprintf("https://vault.%s", k3d.DomainName), - ArgocdIngressURL: fmt.Sprintf("https://argocd.%s", k3d.DomainName), - AtlantisIngressURL: fmt.Sprintf("https://atlantis.%s", k3d.DomainName), - MetaphorDevelopmentIngressURL: fmt.Sprintf("https://metaphor-development.%s", k3d.DomainName), - MetaphorStagingIngressURL: fmt.Sprintf("https://metaphor-staging.%s", k3d.DomainName), - MetaphorProductionIngressURL: fmt.Sprintf("https://metaphor-production.%s", k3d.DomainName), - KubefirstVersion: configs.K1Version, - KubefirstTeam: kubefirstTeam, - KubeconfigPath: config.Kubeconfig, - GitopsRepoURL: gitopsRepoURL, - GitProvider: config.GitProvider, - ClusterId: clusterId, - CloudProvider: k3d.CloudProvider, - } - - if useTelemetryFlag { - gitopsDirectoryTokens.UseTelemetry = "true" - } else { - gitopsDirectoryTokens.UseTelemetry = "false" - } - - httpAuth := &githttps.BasicAuth{ - Username: cGitUser, - Password: cGitToken, - } - - if err != nil { - log.Info().Msgf("generate public keys failed: %q", err.Error()) - return fmt.Errorf("failed to generate public keys: %w", err) - } - - if !viper.GetBool("kubefirst-checks.tools-downloaded") { - log.Info().Msg("installing kubefirst dependencies") - - err := k3d.DownloadTools(clusterNameFlag, config.GitProvider, cGitOwner, config.ToolsDir, config.GitProtocol) - if err != nil { - return fmt.Errorf("failed to download tools: %w", err) - } - - log.Info().Msg("download dependencies `$HOME/.k1/tools` complete") - viper.Set("kubefirst-checks.tools-downloaded", true) - viper.WriteConfig() - } else { - log.Info().Msg("already completed download of dependencies to `$HOME/.k1/tools` - continuing") - } - progressPrinter.IncrementTracker("preflight-checks", 1) - - metaphorTemplateTokens := k3d.MetaphorTokenValues{ - ClusterName: clusterNameFlag, - CloudRegion: cloudRegionFlag, - ContainerRegistryURL: fmt.Sprintf("%s/%s/metaphor", containerRegistryHost, cGitOwner), - DomainName: k3d.DomainName, - MetaphorDevelopmentIngressURL: fmt.Sprintf("metaphor-development.%s", k3d.DomainName), - MetaphorStagingIngressURL: fmt.Sprintf("metaphor-staging.%s", k3d.DomainName), - MetaphorProductionIngressURL: fmt.Sprintf("metaphor-production.%s", k3d.DomainName), - } - - progressPrinter.IncrementTracker("preflight-checks", 1) - progressPrinter.AddTracker("cloning-and-formatting-git-repositories", "Cloning and formatting git repositories", 1) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - removeAtlantis := false - if viper.GetString("secrets.atlantis-ngrok-authtoken") == "" { - removeAtlantis = true - } - if !viper.GetBool("kubefirst-checks.gitops-ready-to-push") { - log.Info().Msg("generating your new gitops repository") - err := k3d.PrepareGitRepositories( - config.GitProvider, - clusterNameFlag, - clusterTypeFlag, - config.DestinationGitopsRepoURL, - config.GitopsDir, - gitopsTemplateBranchFlag, - gitopsTemplateURLFlag, - config.DestinationMetaphorRepoURL, - config.K1Dir, - &gitopsDirectoryTokens, - config.MetaphorDir, - &metaphorTemplateTokens, - gitProtocolFlag, - removeAtlantis, - ) - if err != nil { - return fmt.Errorf("failed to prepare git repositories: %w", err) - } - - viper.Set("kubefirst-checks.gitops-ready-to-push", true) - viper.WriteConfig() - progressPrinter.IncrementTracker("cloning-and-formatting-git-repositories", 1) - } else { - log.Info().Msg("already completed gitops repo generation - continuing") - progressPrinter.IncrementTracker("cloning-and-formatting-git-repositories", 1) - } - - progressPrinter.AddTracker("applying-git-terraform", fmt.Sprintf("Applying %s Terraform", config.GitProvider), 1) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - switch config.GitProvider { - case "github": - executionControl = viper.GetBool("kubefirst-checks.terraform-apply-github") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") - - log.Info().Msg("Creating GitHub resources with Terraform") - - tfEntrypoint := config.GitopsDir + "/terraform/github" - tfEnvs := map[string]string{ - "GITHUB_TOKEN": cGitToken, - "GITHUB_OWNER": cGitOwner, - "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), - "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, - "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, - "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, - "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, - } - if config.GitProtocol == "https" { - tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" - } - - err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - msg := fmt.Errorf("error creating GitHub resources with terraform %q: %w", tfEntrypoint, err) - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) - return msg - } - - log.Info().Msgf("created git repositories for github.com/%s", cGitOwner) - viper.Set("kubefirst-checks.terraform-apply-github", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyCompleted, "") - progressPrinter.IncrementTracker("applying-git-terraform", 1) - } else { - log.Info().Msg("already created GitHub Terraform resources") - progressPrinter.IncrementTracker("applying-git-terraform", 1) - } - case "gitlab": - executionControl = viper.GetBool("kubefirst-checks.terraform-apply-gitlab") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyStarted, "") - - log.Info().Msg("Creating GitLab resources with Terraform") - - tfEntrypoint := config.GitopsDir + "/terraform/gitlab" - tfEnvs := map[string]string{ - "GITLAB_TOKEN": cGitToken, - "GITLAB_OWNER": gitlabGroupFlag, - "TF_VAR_owner_group_id": strconv.Itoa(cGitlabOwnerGroupID), - "TF_VAR_kbot_ssh_public_key": viper.GetString("kbot.public-key"), - "AWS_ACCESS_KEY_ID": constants.MinioDefaultUsername, - "AWS_SECRET_ACCESS_KEY": constants.MinioDefaultPassword, - "TF_VAR_aws_access_key_id": constants.MinioDefaultUsername, - "TF_VAR_aws_secret_access_key": constants.MinioDefaultPassword, - } - if config.GitProtocol == "https" { - tfEnvs["TF_VAR_kbot_ssh_public_key"] = "" - } - - err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - msg := fmt.Errorf("error creating GitLab resources with terraform %q: %w", tfEntrypoint, err) - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyFailed, msg.Error()) - return msg - } - - log.Info().Msgf("created git projects and groups for gitlab.com/%s", gitlabGroupFlag) - viper.Set("kubefirst-checks.terraform-apply-gitlab", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.GitTerraformApplyCompleted, "") - progressPrinter.IncrementTracker("applying-git-terraform", 1) - } else { - log.Info().Msg("already created GitLab Terraform resources") - progressPrinter.IncrementTracker("applying-git-terraform", 1) - } - } - - progressPrinter.AddTracker("pushing-gitops-repos-upstream", "Pushing git repositories", 1) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - log.Info().Msgf("referencing gitops repository: %q", config.DestinationGitopsRepoGitURL) - log.Info().Msgf("referencing metaphor repository: %q", config.DestinationMetaphorRepoURL) - - executionControl = viper.GetBool("kubefirst-checks.gitops-repo-pushed") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushStarted, "") - - gitopsRepo, err := git.PlainOpen(config.GitopsDir) - if err != nil { - return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) - } - - metaphorRepo, err := git.PlainOpen(config.MetaphorDir) - if err != nil { - return fmt.Errorf("error opening repo at %q: %w", config.MetaphorDir, err) - } - - err = utils.EvalSSHKey(&types.EvalSSHKeyRequest{ - GitProvider: gitProviderFlag, - GitlabGroupFlag: gitlabGroupFlag, - GitToken: cGitToken, - }) - if err != nil { - return fmt.Errorf("failed to evaluate SSH key: %w", err) - } - - err = gitopsRepo.Push( - &git.PushOptions{ - RemoteName: config.GitProvider, - Auth: httpAuth, - }, - ) - if err != nil { - msg := fmt.Errorf("error pushing detokenized gitops repository to remote %q: %w", config.DestinationGitopsRepoGitURL, err) - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) - if !strings.Contains(msg.Error(), "already up-to-date") { - log.Printf(msg.Error()) - return msg - } - } - - err = metaphorRepo.Push( - &git.PushOptions{ - RemoteName: "origin", - Auth: httpAuth, - }, - ) - if err != nil { - msg := fmt.Errorf("error pushing detokenized metaphor repository to remote %q: %w", config.DestinationMetaphorRepoURL, err) - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushFailed, msg.Error()) - if !strings.Contains(msg.Error(), "already up-to-date") { - return msg - } - } - log.Info().Msgf("successfully pushed gitops and metaphor repositories to https://%s/%s", cGitHost, cGitOwner) - - viper.Set("kubefirst-checks.gitops-repo-pushed", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.GitopsRepoPushCompleted, "") - progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) - } else { - log.Info().Msg("already pushed detokenized gitops repository content") - progressPrinter.IncrementTracker("pushing-gitops-repos-upstream", 1) - } - - progressPrinter.AddTracker("creating-k3d-cluster", "Creating k3d cluster", 1) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - if !viper.GetBool("kubefirst-checks.create-k3d-cluster") { - telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyStarted, "") - - log.Info().Msg("Creating k3d cluster") - - err := k3d.ClusterCreate(clusterNameFlag, config.K1Dir, config.K3dClient, config.Kubeconfig) - if err != nil { - msg := fmt.Errorf("error creating k3d resources with k3d client %q: %w", config.K3dClient, err) - viper.Set("kubefirst-checks.create-k3d-cluster-failed", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyFailed, msg.Error()) - return msg - } - - log.Info().Msg("successfully created k3d cluster") - viper.Set("kubefirst-checks.create-k3d-cluster", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.CloudTerraformApplyCompleted, "") - progressPrinter.IncrementTracker("creating-k3d-cluster", 1) - } else { - log.Info().Msg("already created k3d cluster resources") - progressPrinter.IncrementTracker("creating-k3d-cluster", 1) - } - - kcfg := k8s.CreateKubeConfig(false, config.Kubeconfig) - - progressPrinter.AddTracker("bootstrapping-kubernetes-resources", "Bootstrapping Kubernetes resources", 2) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - executionControl = viper.GetBool("kubefirst-checks.k8s-secrets-created") - if !executionControl { - err := k3d.GenerateTLSSecrets(kcfg.Clientset, *config) - if err != nil { - return fmt.Errorf("failed to generate TLS secrets: %w", err) - } - - err = k3d.AddK3DSecrets( - atlantisWebhookSecret, - viper.GetString("kbot.public-key"), - gitopsRepoURL, - viper.GetString("kbot.private-key"), - config.GitProvider, - cGitUser, - cGitOwner, - config.Kubeconfig, - cGitToken, - ) - if err != nil { - log.Info().Msg("Error adding kubernetes secrets for bootstrap") - return fmt.Errorf("failed to add Kubernetes secrets: %w", err) - } - viper.Set("kubefirst-checks.k8s-secrets-created", true) - viper.WriteConfig() - progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) - } else { - log.Info().Msg("already added secrets to k3d cluster") - progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) - } - - containerRegistryAuth := gitShim.ContainerRegistryAuth{ - GitProvider: gitProviderFlag, - GitUser: cGitUser, - GitToken: cGitToken, - GitlabGroupFlag: gitlabGroupFlag, - GithubOwner: cGitOwner, - ContainerRegistryHost: containerRegistryHost, - Clientset: kcfg.Clientset, - } - containerRegistryAuthToken, err := gitShim.CreateContainerRegistrySecret(&containerRegistryAuth) - if err != nil { - return fmt.Errorf("failed to create container registry secret: %w", err) - } - progressPrinter.IncrementTracker("bootstrapping-kubernetes-resources", 1) - - progressPrinter.AddTracker("verifying-k3d-cluster-readiness", "Verifying Kubernetes cluster is ready", 3) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - traefikDeployment, err := k8s.ReturnDeploymentObject( - kcfg.Clientset, - "app.kubernetes.io/name", - "traefik", - "kube-system", - 240, - ) - if err != nil { - return fmt.Errorf("error finding traefik deployment: %w", err) - } - _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, traefikDeployment, 240) - if err != nil { - return fmt.Errorf("error waiting for traefik deployment ready state: %w", err) - } - progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) - - metricsServerDeployment, err := k8s.ReturnDeploymentObject( - kcfg.Clientset, - "k8s-app", - "metrics-server", - "kube-system", - 240, - ) - if err != nil { - return fmt.Errorf("error finding metrics-server deployment: %w", err) - } - _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, metricsServerDeployment, 240) - if err != nil { - return fmt.Errorf("error waiting for metrics-server deployment ready state: %w", err) - } - progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) - - time.Sleep(time.Second * 20) - - progressPrinter.IncrementTracker("verifying-k3d-cluster-readiness", 1) - - progressPrinter.AddTracker("installing-argo-cd", "Installing and configuring Argo CD", 3) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - argoCDInstallPath := fmt.Sprintf("github.com:konstructio/manifests/argocd/k3d?ref=%s", constants.KubefirstManifestRepoRef) - executionControl = viper.GetBool("kubefirst-checks.argocd-install") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.ArgoCDInstallStarted, "") - - log.Info().Msgf("installing ArgoCD") - - yamlData, err := kcfg.KustomizeBuild(argoCDInstallPath) - if err != nil { - return fmt.Errorf("failed to build ArgoCD manifests: %w", err) - } - output, err := kcfg.SplitYAMLFile(yamlData) - if err != nil { - return fmt.Errorf("failed to split YAML file: %w", err) - } - err = kcfg.ApplyObjects("", output) - if err != nil { - telemetry.SendEvent(segClient, telemetry.ArgoCDInstallFailed, err.Error()) - return fmt.Errorf("failed to apply ArgoCD objects: %w", err) - } - - viper.Set("kubefirst-checks.argocd-install", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.ArgoCDInstallCompleted, "") - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } else { - log.Info().Msg("ArgoCD already installed, continuing") - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } - - _, err = k8s.VerifyArgoCDReadiness(kcfg.Clientset, true, 300) - if err != nil { - return fmt.Errorf("error waiting for ArgoCD to become ready: %w", err) - } - - var argocdPassword string - executionControl = viper.GetBool("kubefirst-checks.argocd-credentials-set") - if !executionControl { - log.Info().Msg("Setting ArgoCD username and password credentials") - - argocd.ArgocdSecretClient = kcfg.Clientset.CoreV1().Secrets("argocd") - - argocdPassword = k8s.GetSecretValue(argocd.ArgocdSecretClient, "argocd-initial-admin-secret", "password") - if argocdPassword == "" { - return errors.New("ArgoCD password not found in secret") - } - - viper.Set("components.argocd.password", argocdPassword) - viper.Set("components.argocd.username", "admin") - viper.WriteConfig() - log.Info().Msg("ArgoCD username and password credentials set successfully") - log.Info().Msg("Getting an ArgoCD auth token") - - var argoCDToken string - if err := utils.TestEndpointTLS(strings.Replace(k3d.ArgocdURL, "https://", "", 1)); err != nil { - argoCDStopChannel := make(chan struct{}, 1) - log.Info().Msgf("ArgoCD not available via https, using http") - defer func() { - close(argoCDStopChannel) - }() - k8s.OpenPortForwardPodWrapper( - kcfg.Clientset, - kcfg.RestConfig, - "argocd-server", - "argocd", - 8080, - 8080, - argoCDStopChannel, - ) - argoCDHTTPURL := strings.Replace( - k3d.ArgocdURL, - "https://", - "http://", - 1, - ) + ":8080" - argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, argoCDHTTPURL, "admin", argocdPassword) - if err != nil { - return err - } - } else { - argoCDToken, err = argocd.GetArgocdTokenV2(httpClient, k3d.ArgocdURL, "admin", argocdPassword) - if err != nil { - return err - } - } - - log.Info().Msg("ArgoCD admin auth token set") - - viper.Set("components.argocd.auth-token", argoCDToken) - viper.Set("kubefirst-checks.argocd-credentials-set", true) - viper.WriteConfig() - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } else { - log.Info().Msg("ArgoCD credentials already set, continuing") - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } - - if configs.K1Version == "development" { - err := clipboard.WriteAll(argocdPassword) - if err != nil { - log.Error().Err(err).Msg("failed to copy ArgoCD password to clipboard") - } - - if os.Getenv("SKIP_ARGOCD_LAUNCH") != "true" || !ciFlag { - err = utils.OpenBrowser(constants.ArgoCDLocalURLTLS) - if err != nil { - log.Error().Err(err).Msg("failed to open ArgoCD URL in browser") - } - } - } - - executionControl = viper.GetBool("kubefirst-checks.argocd-create-registry") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.CreateRegistryStarted, "") - argocdClient, err := argocdapi.NewForConfig(kcfg.RestConfig) - if err != nil { - return fmt.Errorf("failed to create ArgoCD client: %w", err) - } - - log.Info().Msg("applying the registry application to ArgoCD") - registryApplicationObject := argocd.GetArgoCDApplicationObject(gitopsRepoURL, fmt.Sprintf("registry/%s", clusterNameFlag)) - - err = k3d.RestartDeployment(context.Background(), kcfg.Clientset, "argocd", "argocd-applicationset-controller") - if err != nil { - return fmt.Errorf("error in restarting ArgoCD controller: %w", err) - } - - err = wait.PollImmediate(5*time.Second, 20*time.Second, func() (bool, error) { - _, err := argocdClient.ArgoprojV1alpha1().Applications("argocd").Create(context.Background(), registryApplicationObject, metav1.CreateOptions{}) - if err != nil { - if errors.Is(err, syscall.ECONNREFUSED) { - return false, nil - } - - if apierrors.IsAlreadyExists(err) { - return true, nil - } - - return false, fmt.Errorf("error creating ArgoCD application: %w", err) - } - return true, nil - }) - if err != nil { - return fmt.Errorf("error creating ArgoCD application: %w", err) - } - - log.Info().Msg("ArgoCD application created successfully") - viper.Set("kubefirst-checks.argocd-create-registry", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.CreateRegistryCompleted, "") - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } else { - log.Info().Msg("ArgoCD registry create already done, continuing") - progressPrinter.IncrementTracker("installing-argo-cd", 1) - } - - progressPrinter.AddTracker("configuring-vault", "Configuring Vault", 4) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - vaultStatefulSet, err := k8s.ReturnStatefulSetObject( - kcfg.Clientset, - "app.kubernetes.io/instance", - "vault", - "vault", - 120, - ) - if err != nil { - return fmt.Errorf("error finding Vault StatefulSet: %w", err) - } - _, err = k8s.WaitForStatefulSetReady(kcfg.Clientset, vaultStatefulSet, 120, true) - if err != nil { - return fmt.Errorf("error waiting for Vault StatefulSet ready state: %w", err) - } - progressPrinter.IncrementTracker("configuring-vault", 1) - - time.Sleep(time.Second * 10) - progressPrinter.IncrementTracker("configuring-vault", 1) - - executionControl = viper.GetBool("kubefirst-checks.vault-initialized") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.VaultInitializationStarted, "") - - vaultHandlerPath := "github.com:kubefirst/manifests.git/vault-handler/replicas-1" - - yamlData, err := kcfg.KustomizeBuild(vaultHandlerPath) - if err != nil { - return fmt.Errorf("failed to build vault handler manifests: %w", err) - } - output, err := kcfg.SplitYAMLFile(yamlData) - if err != nil { - return fmt.Errorf("failed to split YAML file: %w", err) - } - err = kcfg.ApplyObjects("", output) - if err != nil { - return fmt.Errorf("failed to apply vault handler objects: %w", err) - } - - job, err := k8s.ReturnJobObject(kcfg.Clientset, "vault", "vault-handler") - if err != nil { - return fmt.Errorf("failed to get vault job object: %w", err) - } - _, err = k8s.WaitForJobComplete(kcfg.Clientset, job, 240) - if err != nil { - msg := fmt.Errorf("could not run vault unseal job: %w", err) - telemetry.SendEvent(segClient, telemetry.VaultInitializationFailed, msg.Error()) - return msg - } - - viper.Set("kubefirst-checks.vault-initialized", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.VaultInitializationCompleted, "") - progressPrinter.IncrementTracker("configuring-vault", 1) - } else { - log.Info().Msg("vault is already initialized - skipping") - progressPrinter.IncrementTracker("configuring-vault", 1) - } - - minioStopChannel := make(chan struct{}, 1) - defer func() { - close(minioStopChannel) - }() - - k8s.OpenPortForwardPodWrapper( - kcfg.Clientset, - kcfg.RestConfig, - "minio", - "minio", - 9000, - 9000, - minioStopChannel, - ) - - minioClient, err := minio.New(constants.MinioPortForwardEndpoint, &minio.Options{ - Creds: credentials.NewStaticV4(constants.MinioDefaultUsername, constants.MinioDefaultPassword, ""), - Secure: false, - Region: constants.MinioRegion, - }) - if err != nil { - return fmt.Errorf("error creating Minio client: %w", err) - } - - objectName := fmt.Sprintf("terraform/%s/terraform.tfstate", config.GitProvider) - filePath := config.K1Dir + fmt.Sprintf("/gitops/%s", objectName) - contentType := "xl.meta" - bucketName := "kubefirst-state-store" - log.Info().Msgf("BucketName: %q", bucketName) - - viper.Set("kubefirst.state-store.name", bucketName) - viper.Set("kubefirst.state-store.hostname", "minio-console.kubefirst.dev") - viper.Set("kubefirst.state-store-creds.access-key-id", constants.MinioDefaultUsername) - viper.Set("kubefirst.state-store-creds.secret-access-key-id", constants.MinioDefaultPassword) - - info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType}) - if err != nil { - return fmt.Errorf("error uploading to Minio bucket: %w", err) - } - - log.Printf("Successfully uploaded %q to bucket %q", objectName, info.Bucket) - - progressPrinter.IncrementTracker("configuring-vault", 1) - - vaultStopChannel := make(chan struct{}, 1) - defer func() { - close(vaultStopChannel) - }() - - k8s.OpenPortForwardPodWrapper( - kcfg.Clientset, - kcfg.RestConfig, - "vault-0", - "vault", - 8200, - 8200, - vaultStopChannel, - ) - - var vaultRootToken string - secData, err := k8s.ReadSecretV2(kcfg.Clientset, "vault", "vault-unseal-secret") - if err != nil { - return fmt.Errorf("failed to read vault unseal secret: %w", err) - } - - vaultRootToken = secData["root-token"] - - kubernetesInClusterAPIService, err := k8s.ReadService(config.Kubeconfig, "default", "kubernetes") - if err != nil { - return fmt.Errorf("error looking up kubernetes api server service: %w", err) - } - - if err := utils.TestEndpointTLS(strings.Replace(k3d.VaultURL, "https://", "", 1)); err != nil { - return fmt.Errorf("unable to reach vault over https: %w", err) - } - - executionControl = viper.GetBool("kubefirst-checks.terraform-apply-vault") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, "") - - tfEnvs := map[string]string{} - var usernamePasswordString, base64DockerAuth string - - if config.GitProvider == "gitlab" { - usernamePasswordString = fmt.Sprintf("%s:%s", "container-registry-auth", containerRegistryAuthToken) - base64DockerAuth = base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) - - tfEnvs["TF_VAR_container_registry_auth"] = containerRegistryAuthToken - tfEnvs["TF_VAR_owner_group_id"] = strconv.Itoa(cGitlabOwnerGroupID) - } else { - usernamePasswordString = fmt.Sprintf("%s:%s", cGitUser, cGitToken) - base64DockerAuth = base64.StdEncoding.EncodeToString([]byte(usernamePasswordString)) - } - - log.Info().Msg("configuring vault with terraform") - - tfEnvs["TF_VAR_email_address"] = "your@email.com" - tfEnvs[fmt.Sprintf("TF_VAR_%s_token", config.GitProvider)] = cGitToken - tfEnvs[fmt.Sprintf("TF_VAR_%s_user", config.GitProvider)] = cGitUser - tfEnvs["TF_VAR_vault_addr"] = k3d.VaultPortForwardURL - tfEnvs["TF_VAR_b64_docker_auth"] = base64DockerAuth - tfEnvs["TF_VAR_vault_token"] = vaultRootToken - tfEnvs["VAULT_ADDR"] = k3d.VaultPortForwardURL - tfEnvs["VAULT_TOKEN"] = vaultRootToken - tfEnvs["TF_VAR_atlantis_repo_webhook_secret"] = viper.GetString("secrets.atlantis-webhook") - tfEnvs["TF_VAR_kbot_ssh_private_key"] = viper.GetString("kbot.private-key") - tfEnvs["TF_VAR_kbot_ssh_public_key"] = viper.GetString("kbot.public-key") - tfEnvs["TF_VAR_kubernetes_api_endpoint"] = fmt.Sprintf("https://%s", kubernetesInClusterAPIService.Spec.ClusterIP) - tfEnvs[fmt.Sprintf("%s_OWNER", strings.ToUpper(config.GitProvider))] = viper.GetString(fmt.Sprintf("flags.%s-owner", config.GitProvider)) - tfEnvs["AWS_ACCESS_KEY_ID"] = constants.MinioDefaultUsername - tfEnvs["AWS_SECRET_ACCESS_KEY"] = constants.MinioDefaultPassword - tfEnvs["TF_VAR_aws_access_key_id"] = constants.MinioDefaultUsername - tfEnvs["TF_VAR_aws_secret_access_key"] = constants.MinioDefaultPassword - tfEnvs["TF_VAR_ngrok_authtoken"] = viper.GetString("secrets.atlantis-ngrok-authtoken") - - tfEntrypoint := config.GitopsDir + "/terraform/vault" - err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyStarted, err.Error()) - return fmt.Errorf("failed to execute vault terraform: %w", err) - } - log.Info().Msg("vault terraform executed successfully") - viper.Set("kubefirst-checks.terraform-apply-vault", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.VaultTerraformApplyCompleted, "") - progressPrinter.IncrementTracker("configuring-vault", 1) - } else { - log.Info().Msg("already executed vault terraform") - progressPrinter.IncrementTracker("configuring-vault", 1) - } - - progressPrinter.AddTracker("creating-users", "Creating users", 1) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - executionControl = viper.GetBool("kubefirst-checks.terraform-apply-users") - if !executionControl { - telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyStarted, "") - - log.Info().Msg("applying users terraform") - - tfEnvs := map[string]string{} - tfEnvs["TF_VAR_email_address"] = "your@email.com" - tfEnvs[fmt.Sprintf("TF_VAR_%s_token", config.GitProvider)] = cGitToken - tfEnvs["TF_VAR_vault_addr"] = k3d.VaultPortForwardURL - tfEnvs["TF_VAR_vault_token"] = vaultRootToken - tfEnvs["VAULT_ADDR"] = k3d.VaultPortForwardURL - tfEnvs["VAULT_TOKEN"] = vaultRootToken - tfEnvs[fmt.Sprintf("%s_TOKEN", strings.ToUpper(config.GitProvider))] = cGitToken - tfEnvs[fmt.Sprintf("%s_OWNER", strings.ToUpper(config.GitProvider))] = cGitOwner - - tfEntrypoint := config.GitopsDir + "/terraform/users" - err := terraform.InitApplyAutoApprove(config.TerraformClient, tfEntrypoint, tfEnvs) - if err != nil { - telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyStarted, err.Error()) - return fmt.Errorf("failed to apply users terraform: %w", err) - } - log.Info().Msg("executed users terraform successfully") - viper.Set("kubefirst-checks.terraform-apply-users", true) - viper.WriteConfig() - telemetry.SendEvent(segClient, telemetry.UsersTerraformApplyCompleted, "") - progressPrinter.IncrementTracker("creating-users", 1) - } else { - log.Info().Msg("already created users with terraform") - progressPrinter.IncrementTracker("creating-users", 1) - } - - progressPrinter.AddTracker("wrapping-up", "Wrapping up", 2) - progressPrinter.SetupProgress(progressPrinter.TotalOfTrackers(), false) - - err = k3d.PostRunPrepareGitopsRepository(clusterNameFlag, config.GitopsDir, &gitopsDirectoryTokens) - if err != nil { - return fmt.Errorf("error detokenizing post run: %w", err) - } - gitopsRepo, err := git.PlainOpen(config.GitopsDir) - if err != nil { - return fmt.Errorf("error opening repo at %q: %w", config.GitopsDir, err) - } - _, err = os.Stat(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider)) - if err == nil { - err = os.Rename(fmt.Sprintf("%s/terraform/%s/remote-backend.md", config.GitopsDir, config.GitProvider), fmt.Sprintf("%s/terraform/%s/remote-backend.tf", config.GitopsDir, config.GitProvider)) - if err != nil { - return fmt.Errorf("failed to rename remote-backend.md to remote-backend.tf: %w", err) - } - } - viper.Set("kubefirst-checks.post-detokenize", true) - viper.WriteConfig() - - err = gitClient.Commit(gitopsRepo, "committing initial detokenized gitops-template repo content post run") - if err != nil { - return fmt.Errorf("failed to commit initial detokenized gitops-template repo content: %w", err) - } - err = gitopsRepo.Push(&git.PushOptions{ - RemoteName: config.GitProvider, - Auth: httpAuth, - }) - if err != nil { - return fmt.Errorf("failed to push initial detokenized gitops-template repo content: %w", err) - } - - progressPrinter.IncrementTracker("wrapping-up", 1) - - argoDeployment, err := k8s.ReturnDeploymentObject(kcfg.Clientset, "app.kubernetes.io/instance", "argo", "argo", 1200) - if err != nil { - return fmt.Errorf("error finding Argo Workflows Deployment: %w", err) - } - _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, argoDeployment, 120) - if err != nil { - return fmt.Errorf("error waiting for Argo Workflows Deployment ready state: %w", err) - } - - utils.SetClusterStatusFlags(k3d.CloudProvider, config.GitProvider) - - cluster := utilities.CreateClusterRecordFromRaw(useTelemetryFlag, cGitOwner, cGitUser, cGitToken, cGitlabOwnerGroupID, gitopsTemplateURLFlag, gitopsTemplateBranchFlag, catalogApps) - - err = utilities.ExportCluster(cluster, kcfg) - if err != nil { - log.Error().Err(err).Msg("error exporting cluster object") - viper.Set("kubefirst.setup-complete", false) - viper.Set("kubefirst-checks.cluster-install-complete", false) - viper.WriteConfig() - return fmt.Errorf("failed to export cluster object: %w", err) - } else { - kubefirstDeployment, err := k8s.ReturnDeploymentObject( - kcfg.Clientset, - "app.kubernetes.io/instance", - "kubefirst", - "kubefirst", - 600, - ) - if err != nil { - return fmt.Errorf("error finding kubefirst Deployment: %w", err) - } - _, err = k8s.WaitForDeploymentReady(kcfg.Clientset, kubefirstDeployment, 120) - if err != nil { - return fmt.Errorf("error waiting for kubefirst Deployment ready state: %w", err) - } - progressPrinter.IncrementTracker("wrapping-up", 1) - - err = utils.OpenBrowser(constants.KubefirstConsoleLocalURLTLS) - if err != nil { - log.Error().Err(err).Msg("failed to open Kubefirst console in browser") - } - - telemetry.SendEvent(segClient, telemetry.ClusterInstallCompleted, "") - viper.Set("kubefirst-checks.cluster-install-complete", true) - viper.WriteConfig() - - log.Info().Msg("kubefirst installation complete") - log.Info().Msg("welcome to your new Kubefirst platform running in K3D") - time.Sleep(1 * time.Second) - - reports.LocalHandoffScreenV2(viper.GetString("components.argocd.password"), clusterNameFlag, gitDestDescriptor, cGitOwner, config, ciFlag) - - if ciFlag { - progress.Progress.Quit() - } - } - - return nil -} diff --git a/cmd/letsencrypt.go b/cmd/letsencrypt.go index 48ac2cc60..1a1071d5e 100644 --- a/cmd/letsencrypt.go +++ b/cmd/letsencrypt.go @@ -7,7 +7,7 @@ See the LICENSE file for more details. package cmd import ( - "log" + "fmt" "github.com/konstructio/kubefirst-api/pkg/certificates" "github.com/konstructio/kubefirst/internal/progress" diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 6a0b84c0b..6086ae2b4 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -102,15 +102,11 @@ func createVultr(cmd *cobra.Command, _ []string) error { return fmt.Errorf("kubefirst api availability check failed: %w", err) } -<<<<<<< HEAD if err := provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps); err != nil { progress.Error(err.Error()) return fmt.Errorf("failed to create management cluster: %w", err) } -======= - provision.CreateMgmtCluster(gitAuth, cliFlags, catalogApps) ->>>>>>> bb91e1c (Clean up code using GolangCI-Lint) return nil } diff --git a/go.mod b/go.mod index 93edad7bc..c4b0c46df 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/charmbracelet/bubbles v0.16.1 github.com/charmbracelet/bubbletea v0.24.2 github.com/charmbracelet/lipgloss v0.10.0 - github.com/charmbracelet/log v0.4.0 github.com/civo/civogo v0.3.53 github.com/denisbrodbeck/machineid v1.0.1 github.com/dustin/go-humanize v1.0.1 @@ -95,7 +94,6 @@ require ( github.com/fvbommel/sortorder v1.0.2 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect @@ -159,6 +157,7 @@ require ( github.com/segmentio/analytics-go v3.1.0+incompatible // indirect github.com/segmentio/backo-go v1.0.1 // indirect github.com/skeema/knownhosts v1.1.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/thanhpk/randstr v1.0.6 // indirect github.com/vmihailenco/go-tinylfu v0.2.1 // indirect github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect @@ -334,4 +333,3 @@ replace ( k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.24.2 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.24.2 ) - diff --git a/go.sum b/go.sum index b2ac8fab6..b52ea8bf6 100644 --- a/go.sum +++ b/go.sum @@ -255,8 +255,6 @@ github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM2 github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc= github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s= github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE= -github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM= -github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -433,8 +431,6 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -1106,8 +1102,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=