Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap bubbletea on each command execution. #2336

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions cmd/beta.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,28 @@ import (
"github.com/konstructio/kubefirst/cmd/k3s"
"github.com/konstructio/kubefirst/cmd/vultr"
"github.com/konstructio/kubefirst/internal/progress"
"github.com/konstructio/kubefirst/internal/teawrapper"
"github.com/spf13/cobra"
)

// betaCmd represents the beta command tree
var betaCmd = &cobra.Command{
Use: "beta",
Short: "access Kubefirst beta features",
Long: `access Kubefirst beta features`,
Run: func(_ *cobra.Command, _ []string) {
fmt.Println("To learn more about Kubefirst, run:")
fmt.Println(" kubefirst help")

if progress.Progress != nil {
progress.Progress.Quit()
}
},
}
func getBetaCommand() *cobra.Command {
// betaCmd represents the beta command tree
betaCmd := &cobra.Command{
Use: "beta",
Short: "access Kubefirst beta features",
Long: `access Kubefirst beta features`,
RunE: teawrapper.WrapBubbleTea(func(_ *cobra.Command, _ []string) error {
fmt.Println("To learn more about Kubefirst, run:")
fmt.Println(" kubefirst help")

if progress.Progress != nil {
progress.Progress.Quit()
}

return nil
}),
}

func init() {
cobra.OnInitialize()
betaCmd.AddCommand(
akamai.NewCommand(),
Expand All @@ -42,4 +45,6 @@ func init() {
google.NewCommand(),
vultr.NewCommand(),
)

return betaCmd
}
10 changes: 4 additions & 6 deletions cmd/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/konstructio/kubefirst-api/pkg/configs"
"github.com/konstructio/kubefirst/internal/progress"
"github.com/konstructio/kubefirst/internal/teawrapper"
"github.com/spf13/cobra"
)

Expand All @@ -22,7 +23,7 @@ var infoCmd = &cobra.Command{
Use: "info",
Short: "provides general Kubefirst setup data",
Long: `Provides machine data, files and folders paths`,
RunE: func(_ *cobra.Command, _ []string) error {
RunE: teawrapper.WrapBubbleTea(func(_ *cobra.Command, _ []string) error {
config, err := configs.ReadConfig()
if err != nil {
return fmt.Errorf("failed to read config: %w", err)
Expand All @@ -44,12 +45,9 @@ var infoCmd = &cobra.Command{
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)
tw.Flush()

progress.Success(buf.String())
return nil
},
}

func init() {
rootCmd.AddCommand(infoCmd)
}),
}
4 changes: 0 additions & 4 deletions cmd/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,3 @@ var logsCmd = &cobra.Command{
return nil
},
}

func init() {
rootCmd.AddCommand(logsCmd)
}
4 changes: 0 additions & 4 deletions cmd/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ var resetCmd = &cobra.Command{
},
}

func init() {
rootCmd.AddCommand(resetCmd)
}

// parseConfigEntryKubefirstChecks gathers the kubefirst-checks section of the Viper
// config file and parses as a map[string]bool
func parseConfigEntryKubefirstChecks(checks map[string]interface{}) (map[string]bool, error) {
Expand Down
63 changes: 29 additions & 34 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,35 @@
"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/internal/teawrapper"
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
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.
checkout the docs at https://kubefirst.konstruct.io/docs/.`,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// wire viper config for flags for all commands
return configs.InitializeViperConfig(cmd)
},
Run: func(_ *cobra.Command, _ []string) {
fmt.Println("To learn more about kubefirst, run:")
fmt.Println(" kubefirst help")
progress.Progress.Quit()
},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
// This will allow all child commands to have informUser available for free.
// Refers: https://github.com/konstructio/runtime/issues/525
// Before removing next line, please read ticket above.
common.CheckForVersionUpdate()
progressPrinter.GetInstance()
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()
func Execute() error {
// rootCmd represents the base command when called without any subcommands
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.
checkout the docs at https://kubefirst.konstruct.io/docs/.`,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// wire viper config for flags for all commands
return configs.InitializeViperConfig(cmd)
},
SilenceUsage: true,
RunE: teawrapper.WrapBubbleTea(func(_ *cobra.Command, _ []string) error {
fmt.Println("To learn more about kubefirst, run:")
fmt.Println(" kubefirst help")
return nil
}),
}
}

func init() {
cobra.OnInitialize()
rootCmd.SilenceUsage = true
rootCmd.AddCommand(
betaCmd,
getBetaCommand(),
aws.NewCommand(),
civo.NewCommand(),
digitalocean.NewCommand(),
Expand All @@ -67,5 +53,14 @@
LaunchCommand(),
LetsEncryptCommand(),
TerraformCommand(),
infoCmd,
logsCmd,
resetCmd,
versionCmd,
)

common.CheckForVersionUpdate()
progressPrinter.GetInstance()

return rootCmd.Execute()

Check failure on line 65 in cmd/root.go

View workflow job for this annotation

GitHub Actions / build

error returned from external package is unwrapped: sig: func (*github.com/spf13/cobra.Command).Execute() error (wrapcheck)
}
4 changes: 0 additions & 4 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ import (
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
Use: "version",
Short: "print the version number for kubefirst-cli",
Expand Down
9 changes: 4 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ require (
github.com/argoproj/argo-cd/v2 v2.9.3
github.com/atotto/clipboard v0.1.4
github.com/aws/aws-sdk-go v1.55.5
github.com/charmbracelet/bubbles v0.20.0
github.com/charmbracelet/bubbletea v1.2.4
github.com/charmbracelet/bubbles v0.16.1
github.com/charmbracelet/bubbletea v0.24.2
github.com/charmbracelet/glamour v0.8.0
github.com/charmbracelet/lipgloss v1.0.0
github.com/charmbracelet/lipgloss v0.12.1
github.com/civo/civogo v0.3.53
github.com/denisbrodbeck/machineid v1.0.1
github.com/dustin/go-humanize v1.0.1
Expand Down Expand Up @@ -103,9 +103,9 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v0.1.0 // indirect
github.com/charmbracelet/x/ansi v0.4.5 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cloudflare/cloudflare-go v0.73.0 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand All @@ -114,7 +114,6 @@ require (
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/emicklei/go-restful/v3 v3.10.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fatih/camelcase v1.0.0 // indirect
Expand Down
23 changes: 10 additions & 13 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -272,20 +272,18 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chai2010/gettext-go v0.1.0 h1:aA1B8BzqN7Df1JOuH91iwchFl+9wckvwUUTMCiQ0qXM=
github.com/chai2010/gettext-go v0.1.0/go.mod h1:PBHWqCsO+bS+OxcVEwt0tCMNOXKykAEfB63RjWDvNvM=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06RaW2cx/SY=
github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg=
github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs=
github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw=
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs=
github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8=
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4 h1:6KzMkQeAF56rggw2NZu1L+TH7j9+DM1/2Kmh7KUxg1I=
github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
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=
Expand Down Expand Up @@ -314,6 +312,8 @@ github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f2
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
Expand Down Expand Up @@ -389,8 +389,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
Expand Down Expand Up @@ -1459,7 +1457,6 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
15 changes: 13 additions & 2 deletions internal/progress/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ package progress

import (
"fmt"
"os"
"sync"

tea "github.com/charmbracelet/bubbletea"
"github.com/konstructio/kubefirst-api/pkg/types"
"github.com/spf13/viper"
)

var Progress *tea.Program
var (
Progress *tea.Program
prOnce sync.Once
)

//nolint:revive // will be removed after refactoring
func NewModel() progressModel {
Expand All @@ -25,7 +30,13 @@ func NewModel() progressModel {

// Bubbletea functions
func InitializeProgressTerminal() {
Progress = tea.NewProgram(NewModel())
prOnce.Do(func() {
if os.Getenv("CI") == "true" {
Progress = tea.NewProgram(NewModel(), tea.WithoutRenderer())
} else {
Progress = tea.NewProgram(NewModel())
}
})
}

func (m progressModel) Init() tea.Cmd {
Expand Down
42 changes: 42 additions & 0 deletions internal/teawrapper/teawrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package teawrapper

import (
"github.com/konstructio/kubefirst/internal/progress"
"github.com/spf13/cobra"
)

// WrapBubbleTea wraps the main user's function with the progress terminal
// so its errors can be handled while still allowing the main command function
// to handle additional, outside-of-the-progress-terminal errors.
func WrapBubbleTea(fn func(*cobra.Command, []string) error) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
// Initialize the progress terminal
progress.InitializeProgressTerminal()

// Run the progress terminal, and listen for errors
chTeaError := make(chan error, 1)
go func() {
_, err := progress.Progress.Run()
chTeaError <- err
}()

// Run the main user's function
if err := fn(cmd, args); err != nil {
// print the error and send it to the progress terminal, but don't
// return here, we want the error to be handled by bubbletea
progress.Error(err.Error())
}

// Quit the progress terminal if the execution succeeded
// so it can stop `progress.Run()`
progress.Progress.Quit()

// Receive the error from the progress terminal, and check
// if it's not nil, then return it
if err := <-chTeaError; err != nil {
return err
}

return nil
}
}
Loading
Loading