diff --git a/cmd/akamai/command.go b/cmd/akamai/command.go index f3e4566e..c1ab5200 100644 --- a/cmd/akamai/command.go +++ b/cmd/akamai/command.go @@ -128,6 +128,7 @@ func RootCredentials() *cobra.Command { 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)") + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return authCmd } diff --git a/cmd/akamai/create.go b/cmd/akamai/create.go index 68230813..0c879ca3 100644 --- a/cmd/akamai/create.go +++ b/cmd/akamai/create.go @@ -39,10 +39,12 @@ func createAkamai(cmd *cobra.Command, _ []string) error { return fmt.Errorf("catalog validation failed: %w", err) } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("failed to validate flags: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to validate flags: %w", err) + } } utilities.CreateK1ClusterDirectory(clusterNameFlag) diff --git a/cmd/aws/command.go b/cmd/aws/command.go index f011c82a..73e8e4ee 100644 --- a/cmd/aws/command.go +++ b/cmd/aws/command.go @@ -136,5 +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") + return authCmd } diff --git a/cmd/aws/create.go b/cmd/aws/create.go index 80c19481..b5fa37cf 100644 --- a/cmd/aws/create.go +++ b/cmd/aws/create.go @@ -41,10 +41,12 @@ func createAws(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid catalog apps: %w", err) } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("failed to validate provided flags: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to validate provided flags: %w", err) + } } utilities.CreateK1ClusterDirectory(cliFlags.ClusterName) diff --git a/cmd/azure/command.go b/cmd/azure/command.go index ea63d6be..a66d200b 100644 --- a/cmd/azure/command.go +++ b/cmd/azure/command.go @@ -137,6 +137,7 @@ func RootCredentials() *cobra.Command { 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)") + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return authCmd } diff --git a/cmd/azure/create.go b/cmd/azure/create.go index b42352f3..6fd666bf 100644 --- a/cmd/azure/create.go +++ b/cmd/azure/create.go @@ -51,10 +51,12 @@ func createAzure(cmd *cobra.Command, _ []string) error { return nil } - err = ValidateProvidedFlags(cliFlags.GitProvider, cliFlags.DNSProvider, cliFlags.DNSAzureRG) - if err != nil { - progress.Error(err.Error()) - return nil + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider, cliFlags.DNSProvider, cliFlags.DNSAzureRG) + if err != nil { + progress.Error(err.Error()) + return nil + } } // If cluster setup is complete, return @@ -113,8 +115,9 @@ func createAzure(cmd *cobra.Command, _ []string) error { } func ValidateProvidedFlags(gitProvider, dnsProvider, dnsAzureResourceGroup string) error { - progress.AddStep("Validate provided flags") - + if progress.CanRunBubbleTea { + progress.AddStep("Validate provided flags") + } for _, env := range envvarSecrets { if os.Getenv(env) == "" { return fmt.Errorf("your %s is not set - please set and re-run your last command", env) diff --git a/cmd/civo/command.go b/cmd/civo/command.go index 2ea8bbc7..5b641c39 100644 --- a/cmd/civo/command.go +++ b/cmd/civo/command.go @@ -154,6 +154,7 @@ func RootCredentials() *cobra.Command { 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)") + 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/create.go b/cmd/civo/create.go index 14592cea..e5c278e8 100644 --- a/cmd/civo/create.go +++ b/cmd/civo/create.go @@ -39,10 +39,12 @@ func createCivo(cmd *cobra.Command, _ []string) error { return fmt.Errorf("catalog apps validation failed: %w", err) } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("failed to validate provided flags: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to validate provided flags: %w", err) + } } // If cluster setup is complete, return diff --git a/cmd/digitalocean/command.go b/cmd/digitalocean/command.go index 2ca962a0..ba16be63 100644 --- a/cmd/digitalocean/command.go +++ b/cmd/digitalocean/command.go @@ -133,6 +133,7 @@ func RootCredentials() *cobra.Command { 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)") + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return authCmd } diff --git a/cmd/digitalocean/create.go b/cmd/digitalocean/create.go index c1213496..85675d03 100644 --- a/cmd/digitalocean/create.go +++ b/cmd/digitalocean/create.go @@ -44,10 +44,12 @@ func createDigitalocean(cmd *cobra.Command, _ []string) error { return errors.New("catalog did not pass a validation check") } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("failed to validate provided flags: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("failed to validate provided flags: %w", err) + } } // If cluster setup is complete, return diff --git a/cmd/google/command.go b/cmd/google/command.go index bed2ddc2..3004a8c5 100644 --- a/cmd/google/command.go +++ b/cmd/google/command.go @@ -139,6 +139,7 @@ func RootCredentials() *cobra.Command { 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)") + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return authCmd } diff --git a/cmd/google/create.go b/cmd/google/create.go index bb074d9b..0099cfd6 100644 --- a/cmd/google/create.go +++ b/cmd/google/create.go @@ -40,10 +40,12 @@ func createGoogle(cmd *cobra.Command, _ []string) error { return fmt.Errorf("catalog apps validation failed: %w", err) } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("validation of provided flags failed: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("validation of provided flags failed: %w", err) + } } clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") diff --git a/cmd/launch.go b/cmd/launch.go index 88b23c5a..4bc09ea3 100644 --- a/cmd/launch.go +++ b/cmd/launch.go @@ -13,6 +13,8 @@ import ( "github.com/spf13/cobra" ) +var ciFlag bool + // additionalHelmFlags can optionally pass user-supplied flags to helm var additionalHelmFlags []string @@ -102,6 +104,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 } diff --git a/cmd/root.go b/cmd/root.go index 3a9b4059..527eea69 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -68,4 +68,7 @@ func init() { LetsEncryptCommand(), TerraformCommand(), ) + + rootCmd.PersistentFlags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") + } diff --git a/cmd/vultr/command.go b/cmd/vultr/command.go index 3490f6dd..6b40fd5f 100644 --- a/cmd/vultr/command.go +++ b/cmd/vultr/command.go @@ -133,6 +133,7 @@ func RootCredentials() *cobra.Command { 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)") + authCmd.Flags().BoolVar(&ciFlag, "ci", false, "if running kubefirst in ci, set this flag to disable interactive features") return authCmd } diff --git a/cmd/vultr/create.go b/cmd/vultr/create.go index 6086ae2b..5fc3c868 100644 --- a/cmd/vultr/create.go +++ b/cmd/vultr/create.go @@ -44,10 +44,12 @@ func createVultr(cmd *cobra.Command, _ []string) error { return errors.New("catalog validation failed") } - err = ValidateProvidedFlags(cliFlags.GitProvider) - if err != nil { - progress.Error(err.Error()) - return fmt.Errorf("invalid provided flags: %w", err) + if progress.CanRunBubbleTea { + err = ValidateProvidedFlags(cliFlags.GitProvider) + if err != nil { + progress.Error(err.Error()) + return fmt.Errorf("invalid provided flags: %w", err) + } } clusterSetupComplete := viper.GetBool("kubefirst-checks.cluster-install-complete") @@ -139,5 +141,6 @@ func ValidateProvidedFlags(gitProvider string) error { } progress.CompleteStep("Validate provided flags") + return nil } diff --git a/internal/progress/ci.go b/internal/progress/ci.go new file mode 100644 index 00000000..bafd0095 --- /dev/null +++ b/internal/progress/ci.go @@ -0,0 +1,39 @@ +package progress + +import ( + "fmt" + "time" + + "github.com/konstructio/kubefirst/internal/cluster" +) + +func WatchClusterForCi(clusterName string) { + 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 + } + } + } + }() + + <-done +} diff --git a/internal/progress/message.go b/internal/progress/message.go index c6313abb..6dfdd8a4 100644 --- a/internal/progress/message.go +++ b/internal/progress/message.go @@ -71,6 +71,11 @@ func DisplayLogHints(estimatedTime int) { headerMessage := renderMessage(header) + if !CanRunBubbleTea { + fmt.Println(headerMessage) + return + } + Progress.Send(headerMsg{ message: headerMessage, }) @@ -141,6 +146,11 @@ func DisplaySuccessMessage(cluster types.Cluster) successMsg { successMessage := renderMessage(success) + if !CanRunBubbleTea { + fmt.Println(successMessage) + return successMsg{} + } + return successMsg{ message: successMessage, } @@ -165,6 +175,11 @@ func DisplayCredentials(cluster types.Cluster) { headerMessage := renderMessage(header) + if !CanRunBubbleTea { + fmt.Println(headerMessage) + return + } + Progress.Send(headerMsg{ message: headerMessage, }) @@ -174,10 +189,21 @@ func DisplayCredentials(cluster types.Cluster) { func AddStep(message string) { renderedMessage := createStep(fmt.Sprintf("%s %s", ":dizzy:", message)) + + if !CanRunBubbleTea { + fmt.Println(renderedMessage) + return + } + Progress.Send(renderedMessage) } func CompleteStep(message string) { + if !CanRunBubbleTea { + fmt.Println(message) + return + } + Progress.Send(completeStep{ message: message, }) @@ -186,6 +212,11 @@ func CompleteStep(message string) { func Success(success string) { successMessage := renderMessage(success) + if !CanRunBubbleTea { + fmt.Println(successMessage) + return + } + Progress.Send( successMsg{ message: successMessage, @@ -194,13 +225,23 @@ func Success(success string) { func Error(message string) { renderedMessage := createErrorLog(message) + + if !CanRunBubbleTea { + fmt.Println(renderedMessage) + return + } + Progress.Send(renderedMessage) } func StartProvisioning(clusterName string) { - provisioningMessage := startProvision{ - clusterName: clusterName, - } + if !CanRunBubbleTea { + WatchClusterForCi(clusterName) + } else { + provisioningMessage := startProvision{ + clusterName: clusterName, + } - Progress.Send(provisioningMessage) + Progress.Send(provisioningMessage) + } } diff --git a/internal/progress/progress.go b/internal/progress/progress.go index 6d0b42c7..7fcf7cdf 100644 --- a/internal/progress/progress.go +++ b/internal/progress/progress.go @@ -14,7 +14,10 @@ import ( "github.com/spf13/viper" ) -var Progress *tea.Program +var ( + Progress *tea.Program + CanRunBubbleTea bool +) //nolint:revive // will be removed after refactoring func NewModel() progressModel { @@ -23,6 +26,10 @@ func NewModel() progressModel { } } +func DisableBubbleTeaExecution() { + CanRunBubbleTea = false +} + // Bubbletea functions func InitializeProgressTerminal() { Progress = tea.NewProgram(NewModel()) diff --git a/main.go b/main.go index e030707e..e9b2378f 100644 --- a/main.go +++ b/main.go @@ -24,8 +24,8 @@ import ( func main() { argsWithProg := os.Args - - bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs"} + fmt.Println(argsWithProg) + bubbleTeaBlacklist := []string{"completion", "help", "--help", "-h", "quota", "logs", "--ci"} canRunBubbleTea := true for _, arg := range argsWithProg { @@ -143,5 +143,6 @@ func main() { progress.Progress.Run() } else { cmd.Execute() + progress.DisableBubbleTeaExecution() } }