diff --git a/pkg/cmd/agent/agent.go b/pkg/cmd/agent/agent.go index e4617ea09c..e3be7c3c70 100644 --- a/pkg/cmd/agent/agent.go +++ b/pkg/cmd/agent/agent.go @@ -26,7 +26,7 @@ var AgentCmd = &cobra.Command{ Use: "agent", Short: "Start the agent process", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { setLogLevel() agentMode := config.ModeProject @@ -37,7 +37,7 @@ var AgentCmd = &cobra.Command{ c, err := config.GetConfig(agentMode) if err != nil { - log.Fatal(err) + return err } c.ProjectDir = filepath.Join(os.Getenv("HOME"), c.ProjectName) @@ -50,7 +50,7 @@ var AgentCmd = &cobra.Command{ if c.LogFilePath != nil { logFile, err := os.OpenFile(*c.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { - log.Fatal(err) + return err } defer logFile.Close() gitLogWriter = io.MultiWriter(os.Stdout, logFile) @@ -91,10 +91,7 @@ var AgentCmd = &cobra.Command{ TelemetryEnabled: telemetryEnabled, } - err = agent.Start() - if err != nil { - log.Fatal(err) - } + return agent.Start() }, } diff --git a/pkg/cmd/agent/logs.go b/pkg/cmd/agent/logs.go index a98f7da634..219aff530a 100644 --- a/pkg/cmd/agent/logs.go +++ b/pkg/cmd/agent/logs.go @@ -5,13 +5,13 @@ package agent import ( "context" + "errors" "fmt" "io" "os" "github.com/daytonaio/daytona/internal/util" "github.com/daytonaio/daytona/pkg/agent/config" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -20,16 +20,16 @@ var followFlag bool var logsCmd = &cobra.Command{ Use: "logs", Short: "Output Daytona Agent logs", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { logFilePath := config.GetLogFilePath() if logFilePath == nil { - log.Fatal("Log file path not set") + return errors.New("log file path not set") } file, err := os.Open(*logFilePath) if err != nil { - log.Fatal(err) + return err } defer file.Close() @@ -41,13 +41,13 @@ var logsCmd = &cobra.Command{ for { select { case <-context.Background().Done(): - return + return nil case err := <-errChan: if err != nil { if err != io.EOF { - log.Fatal(err) + return err } - return + return nil } case msg := <-msgChan: fmt.Println(string(msg)) diff --git a/pkg/cmd/apikey/generate.go b/pkg/cmd/apikey/generate.go index 69feb25ba8..5c58e4785f 100644 --- a/pkg/cmd/apikey/generate.go +++ b/pkg/cmd/apikey/generate.go @@ -5,8 +5,8 @@ package apikey import ( "context" + "errors" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/internal/util" @@ -21,18 +21,18 @@ var GenerateCmd = &cobra.Command{ Short: "Generate a new API key", Aliases: []string{"g", "new"}, Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var keyName string apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } apiKeyList, _, err := apiClient.ApiKeyAPI.ListClientApiKeys(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(nil, err)) + return apiclient_util.HandleErrorResponse(nil, err) } if len(args) == 1 { @@ -43,26 +43,27 @@ var GenerateCmd = &cobra.Command{ for _, key := range apiKeyList { if key.Name == keyName { - log.Fatal("key name already exists, please choose a different one") + return errors.New("key name already exists, please choose a different one") } } key, _, err := apiClient.ApiKeyAPI.GenerateApiKey(ctx, keyName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(nil, err)) + return apiclient_util.HandleErrorResponse(nil, err) } serverConfig, _, err := apiClient.ServerAPI.GetConfigExecute(apiclient.ApiGetConfigRequest{}) if err != nil { - log.Fatal(err) + return err } if serverConfig.Frps == nil { - log.Fatal("frps config is missing") + return errors.New("frps config is missing") } apiUrl := util.GetFrpcApiUrl(serverConfig.Frps.Protocol, serverConfig.Id, serverConfig.Frps.Domain) view.Render(key, apiUrl) + return nil }, } diff --git a/pkg/cmd/apikey/list.go b/pkg/cmd/apikey/list.go index 8acdd0e9bc..1b01b22b0d 100644 --- a/pkg/cmd/apikey/list.go +++ b/pkg/cmd/apikey/list.go @@ -9,7 +9,6 @@ import ( "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views/server/apikey" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -17,26 +16,27 @@ var listCmd = &cobra.Command{ Use: "list", Short: "List API keys", Aliases: []string{"ls"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } - apiKeyList, _, err := apiClient.ApiKeyAPI.ListClientApiKeys(ctx).Execute() + apiKeyList, res, err := apiClient.ApiKeyAPI.ListClientApiKeys(ctx).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(nil, err)) + return apiclient.HandleErrorResponse(res, err) } if format.FormatFlag != "" { formattedData := format.NewFormatter(apiKeyList) formattedData.Print() - return + return nil } apikey.ListApiKeys(apiKeyList) + return nil }, } diff --git a/pkg/cmd/apikey/revoke.go b/pkg/cmd/apikey/revoke.go index 616970bc57..36835a13bb 100644 --- a/pkg/cmd/apikey/revoke.go +++ b/pkg/cmd/apikey/revoke.go @@ -5,10 +5,10 @@ package apikey import ( "context" + "errors" "fmt" "github.com/charmbracelet/huh" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/cmd/daytona/config" @@ -27,29 +27,29 @@ var revokeCmd = &cobra.Command{ Short: "Revoke an API key", Aliases: []string{"r", "rm", "delete"}, Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } var selectedApiKey *apiclient.ApiKey apiKeyList, _, err := apiClient.ApiKeyAPI.ListClientApiKeys(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(nil, err)) + return apiclient_util.HandleErrorResponse(nil, err) } if len(args) == 1 { @@ -63,15 +63,15 @@ var revokeCmd = &cobra.Command{ selectedApiKey, err = apikey.GetApiKeyFromPrompt(apiKeyList, "Select an API key to revoke", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } } if selectedApiKey == nil { - log.Fatal("No API key selected") + return errors.New("No API key selected") } if !yesFlag { @@ -93,20 +93,22 @@ var revokeCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } } if yesFlag { - _, err = apiClient.ApiKeyAPI.RevokeApiKey(ctx, selectedApiKey.Name).Execute() + res, err := apiClient.ApiKeyAPI.RevokeApiKey(ctx, selectedApiKey.Name).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(nil, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("API key revoked") } else { fmt.Println("Operation canceled.") } + + return nil }, } diff --git a/pkg/cmd/autocomplete.go b/pkg/cmd/autocomplete.go index 844bd21a0d..944a2cf2a4 100644 --- a/pkg/cmd/autocomplete.go +++ b/pkg/cmd/autocomplete.go @@ -16,12 +16,11 @@ var AutoCompleteCmd = &cobra.Command{ Use: "autocomplete [bash|zsh|fish|powershell]", Short: "Adds completion script for your shell enviornment", Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { shell := args[0] homeDir, err := os.UserHomeDir() if err != nil { - fmt.Printf("Error finding user home directory: %s\n", err) - return + return fmt.Errorf("Error finding user home directory: %s\n", err) } var filePath, profilePath string @@ -39,14 +38,12 @@ var AutoCompleteCmd = &cobra.Command{ filePath = filepath.Join(homeDir, "daytona.completion_script.ps1") profilePath = filepath.Join(homeDir, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1") default: - fmt.Println("Unsupported shell type. Please use bash, zsh, fish, or powershell.") - return + return fmt.Errorf("Unsupported shell type. Please use bash, zsh, fish, or powershell.") } file, err := os.Create(filePath) if err != nil { - fmt.Printf("Error creating completion script file: %s\n", err) - return + return fmt.Errorf("Error creating completion script file: %s\n", err) } defer file.Close() @@ -62,8 +59,7 @@ var AutoCompleteCmd = &cobra.Command{ } if err != nil { - fmt.Printf("Error generating completion script: %s\n", err) - return + return fmt.Errorf("Error generating completion script: %s\n", err) } sourceCommand := fmt.Sprintf("\nsource %s\n", filePath) @@ -87,19 +83,19 @@ var AutoCompleteCmd = &cobra.Command{ // Append the source command to the shell's profile file if not present profile, err := os.OpenFile(profilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { - fmt.Printf("Error opening profile file (%s): %s\n", profilePath, err) - return + return fmt.Errorf("Error opening profile file (%s): %s\n", profilePath, err) } defer profile.Close() if _, err := profile.WriteString(sourceCommand); err != nil { - fmt.Printf("Error writing to profile file (%s): %s\n", profilePath, err) - return + return fmt.Errorf("Error writing to profile file (%s): %s\n", profilePath, err) } } fmt.Println("Autocomplete script generated and injected successfully.") fmt.Printf("Please source your %s profile to apply the changes or restart your terminal.\n", shell) fmt.Printf("For manual sourcing, use: source %s\n", profilePath) + + return nil }, } diff --git a/pkg/cmd/build/delete.go b/pkg/cmd/build/delete.go index 509626c66c..62e63be40a 100644 --- a/pkg/cmd/build/delete.go +++ b/pkg/cmd/build/delete.go @@ -6,7 +6,6 @@ package build import ( "context" "fmt" - "log" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/views" @@ -19,44 +18,44 @@ var buildDeleteCmd = &cobra.Command{ Short: "Delete a build", Aliases: []string{"remove", "rm"}, Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var buildId string apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if allFlag { res, err := apiClient.BuildAPI.DeleteAllBuilds(ctx).Force(forceFlag).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("All builds have been marked for deletion") - return + return nil } if prebuildIdFlag != "" { res, err := apiClient.BuildAPI.DeleteBuildsFromPrebuild(ctx, prebuildIdFlag).Force(forceFlag).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage(fmt.Sprintf("All builds from prebuild %s have been marked for deletion\n", prebuildIdFlag)) - return + return nil } if len(args) == 0 { buildList, res, err := apiClient.BuildAPI.ListBuilds(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } build := selection.GetBuildFromPrompt(buildList, "Delete") if build == nil { - return + return nil } buildId = build.Id } else { @@ -65,9 +64,10 @@ var buildDeleteCmd = &cobra.Command{ res, err := apiClient.BuildAPI.DeleteBuild(ctx, buildId).Force(forceFlag).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage(fmt.Sprintf("Build %s has been marked for deletion", buildId)) + return nil }, } diff --git a/pkg/cmd/build/info.go b/pkg/cmd/build/info.go index b373a7af7b..2e4c646ef6 100644 --- a/pkg/cmd/build/info.go +++ b/pkg/cmd/build/info.go @@ -5,7 +5,6 @@ package build import ( "context" - "log" "net/http" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" @@ -21,24 +20,24 @@ var buildInfoCmd = &cobra.Command{ Short: "Show build info", Aliases: []string{"view", "inspect"}, Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var build *apiclient.Build apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(args) == 0 { buildList, res, err := apiClient.BuildAPI.ListBuilds(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if format.FormatFlag != "" { @@ -51,23 +50,24 @@ var buildInfoCmd = &cobra.Command{ } if build == nil { - return + return nil } } else { var res *http.Response build, res, err = apiClient.BuildAPI.GetBuild(ctx, args[0]).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if format.FormatFlag != "" { formattedData := format.NewFormatter(build) formattedData.Print() - return + return nil } info.Render(build, apiServerConfig, false) + return nil }, } diff --git a/pkg/cmd/build/list.go b/pkg/cmd/build/list.go index f9f0827070..71edc1170b 100644 --- a/pkg/cmd/build/list.go +++ b/pkg/cmd/build/list.go @@ -5,7 +5,6 @@ package build import ( "context" - "log" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/cmd/format" @@ -19,36 +18,37 @@ var buildListCmd = &cobra.Command{ Short: "List all builds", Aliases: []string{"ls"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } buildList, res, err := apiClient.BuildAPI.ListBuilds(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(buildList) == 0 { views.RenderInfoMessage("No builds found.") - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(buildList) formattedData.Print() - return + return nil } view.ListBuilds(buildList, apiServerConfig) + return nil }, } diff --git a/pkg/cmd/build/logs.go b/pkg/cmd/build/logs.go index cf11202e18..293067f29d 100644 --- a/pkg/cmd/build/logs.go +++ b/pkg/cmd/build/logs.go @@ -6,7 +6,6 @@ package build import ( "context" "fmt" - "log" "net/http" "slices" "time" @@ -25,15 +24,15 @@ var buildLogsCmd = &cobra.Command{ Short: "View logs for build", Args: cobra.RangeArgs(0, 1), Aliases: []string{"log"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } query := "" @@ -46,17 +45,17 @@ var buildLogsCmd = &cobra.Command{ apiClient, err := apiclient_util.GetApiClient(&activeProfile) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { buildList, res, err := apiClient.BuildAPI.ListBuilds(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } build := selection.GetBuildFromPrompt(buildList, "Get Logs For") if build == nil { - return + return nil } buildId = build.Id } else { @@ -71,7 +70,7 @@ var buildLogsCmd = &cobra.Command{ if !continueOnCompletedFlag { exists, err = waitForBuildToComplete(buildId, apiClient) if err != nil { - log.Fatal(err) + return err } } else { // Sleep indefinitely @@ -84,6 +83,7 @@ var buildLogsCmd = &cobra.Command{ if exists != nil && !*exists { views.RenderInfoMessage(fmt.Sprintf("Build with ID %s does not exist in the database", buildId)) } + return nil }, } diff --git a/pkg/cmd/build/run.go b/pkg/cmd/build/run.go index ad8e2869bf..d4422f1232 100644 --- a/pkg/cmd/build/run.go +++ b/pkg/cmd/build/run.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "log" "github.com/daytonaio/daytona/internal/util" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" @@ -23,45 +22,46 @@ var buildRunCmd = &cobra.Command{ Short: "Run a build from a project config", Aliases: []string{"create"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var projectConfig *apiclient.ProjectConfig ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } projectConfigList, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } projectConfig = selection.GetProjectConfigFromPrompt(projectConfigList, 0, false, false, "Build") if projectConfig == nil { - return + return nil } if projectConfig.BuildConfig == nil { - log.Fatal("The chosen project config does not have a build configuration") + return errors.New("The chosen project config does not have a build configuration") } chosenBranch, err := workspace_util.GetBranchFromProjectConfig(projectConfig, apiClient, 0) if err != nil { - log.Fatal(err) + return err } if chosenBranch == nil { fmt.Println("Operation canceled") - return + return nil } buildId, err := CreateBuild(apiClient, projectConfig, chosenBranch.Name, nil) if err != nil { - log.Fatal(err) + return err } views.RenderViewBuildLogsMessage(buildId) + return nil }, } diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index c7f23fb7e5..3a6749dad2 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -6,6 +6,7 @@ package cmd import ( "fmt" "os" + "os/signal" "strings" "time" @@ -39,6 +40,8 @@ var rootCmd = &cobra.Command{ Use: "daytona", Short: "Daytona is a Dev Environment Manager", Long: "Daytona is a Dev Environment Manager", + SilenceUsage: true, + SilenceErrors: true, DisableAutoGenTag: true, Run: RunInitialScreenFlow, } @@ -79,22 +82,91 @@ func Execute() { SetupRootCommand(rootCmd) - cmd, err := validateCommands(rootCmd, os.Args[1:]) + var telemetryService telemetry.TelemetryService + clientId := config.GetClientId() + telemetryEnabled := config.TelemetryEnabled() + + if telemetryEnabled { + telemetryService = posthogservice.NewTelemetryService(posthogservice.PosthogServiceConfig{ + ApiKey: internal.PosthogApiKey, + Endpoint: internal.PosthogEndpoint, + }) + } + + cmd, err := ValidateCommands(rootCmd, os.Args[1:]) if err != nil { fmt.Printf("Error: %v\n\n", err) - err := cmd.Help() - if err != nil { + helpErr := cmd.Help() + if telemetryEnabled { + props := GetCmdTelemetryData(cmd) + props["command"] = os.Args[1] + props["called_as"] = os.Args[1] + err := telemetryService.TrackCliEvent(telemetry.CliEventInvalidCmd, clientId, props) + if err != nil { + log.Error(err) + } + telemetryService.Close() + } + + if helpErr != nil { log.Fatal(err) } return } - if err := rootCmd.Execute(); err != nil { + startTime := time.Now() + + if telemetryEnabled { + err := telemetryService.TrackCliEvent(telemetry.CliEventCmdStart, clientId, GetCmdTelemetryData(cmd)) + if err != nil { + log.Error(err) + } + + go func() { + interruptChannel := make(chan os.Signal, 1) + signal.Notify(interruptChannel, os.Interrupt) + + for range interruptChannel { + endTime := time.Now() + execTime := endTime.Sub(startTime) + props := GetCmdTelemetryData(cmd) + props["exec time (µs)"] = execTime.Microseconds() + props["error"] = "interrupted" + + err := telemetryService.TrackCliEvent(telemetry.CliEventCmdEnd, clientId, props) + if err != nil { + log.Error(err) + } + telemetryService.Close() + os.Exit(0) + } + }() + } + + err = rootCmd.Execute() + + endTime := time.Now() + if telemetryService != nil { + execTime := endTime.Sub(startTime) + props := GetCmdTelemetryData(cmd) + props["exec time (µs)"] = execTime.Microseconds() + if err != nil { + props["error"] = err.Error() + } + + err := telemetryService.TrackCliEvent(telemetry.CliEventCmdEnd, clientId, props) + if err != nil { + log.Error(err) + } + telemetryService.Close() + } + + if err != nil { log.Fatal(err) } } -func validateCommands(rootCmd *cobra.Command, args []string) (cmd *cobra.Command, err error) { +func ValidateCommands(rootCmd *cobra.Command, args []string) (cmd *cobra.Command, err error) { rootCmd.InitDefaultHelpCmd() currentCmd := rootCmd @@ -145,19 +217,6 @@ func SetupRootCommand(cmd *cobra.Command) { cmd.PersistentFlags().BoolP("help", "", false, "help for daytona") cmd.Flags().BoolP("version", "v", false, "Display the version of Daytona") - var telemetryService telemetry.TelemetryService - clientId := config.GetClientId() - telemetryEnabled := config.TelemetryEnabled() - - if telemetryEnabled { - telemetryService = posthogservice.NewTelemetryService(posthogservice.PosthogServiceConfig{ - ApiKey: internal.PosthogApiKey, - Endpoint: internal.PosthogEndpoint, - }) - } - - startTime := time.Now() - cmd.PreRun = func(cmd *cobra.Command, args []string) { versionFlag, _ := cmd.Flags().GetBool("version") if versionFlag { @@ -165,31 +224,6 @@ func SetupRootCommand(cmd *cobra.Command) { os.Exit(0) } } - - cmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { - if telemetryService != nil { - err := telemetryService.TrackCliEvent(telemetry.CliEventCmdStart, clientId, getCmdTelemetryData(cmd)) - if err != nil { - log.Error(err) - } - } - } - - cmd.PersistentPostRun = func(cmd *cobra.Command, args []string) { - endTime := time.Now() - - if telemetryService != nil { - defer telemetryService.Close() - execTime := endTime.Sub(startTime) - props := getCmdTelemetryData(cmd) - props["exec time (µs)"] = execTime.Microseconds() - - err := telemetryService.TrackCliEvent(telemetry.CliEventCmdEnd, clientId, props) - if err != nil { - log.Error(err) - } - } - } } func RunInitialScreenFlow(cmd *cobra.Command, args []string) { @@ -223,7 +257,7 @@ func RunInitialScreenFlow(cmd *cobra.Command, args []string) { } } -func getCmdTelemetryData(cmd *cobra.Command) map[string]interface{} { +func GetCmdTelemetryData(cmd *cobra.Command) map[string]interface{} { path := cmd.CommandPath() // Trim daytona from the path if a non-root command was invoked diff --git a/pkg/cmd/config.go b/pkg/cmd/config.go index a2cd76600b..7992e0b33e 100644 --- a/pkg/cmd/config.go +++ b/pkg/cmd/config.go @@ -7,7 +7,6 @@ import ( "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/cmd/format" config_view "github.com/daytonaio/daytona/pkg/views/config" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -18,10 +17,10 @@ var configCmd = &cobra.Command{ Short: "Output Daytona configuration", Aliases: []string{"cfg"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } if format.FormatFlag != "" { @@ -34,10 +33,11 @@ var configCmd = &cobra.Command{ formattedData := format.NewFormatter(&c) formattedData.Print() - return + return nil } config_view.Render(c, showApiKeysFlag) + return nil }, } diff --git a/pkg/cmd/containerregistry/delete.go b/pkg/cmd/containerregistry/delete.go index d937c0cf7d..ab007d2791 100644 --- a/pkg/cmd/containerregistry/delete.go +++ b/pkg/cmd/containerregistry/delete.go @@ -13,7 +13,6 @@ import ( "github.com/daytonaio/daytona/pkg/common" "github.com/daytonaio/daytona/pkg/views" containerregistry_view "github.com/daytonaio/daytona/pkg/views/containerregistry" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -22,42 +21,42 @@ var containerRegistryDeleteCmd = &cobra.Command{ Aliases: []string{"remove", "rm"}, Short: "Delete a container registry", Args: cobra.RangeArgs(0, 2), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var registryDto *apiclient.ContainerRegistry var selectedServer string apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } containerRegistries, res, err := apiClient.ContainerRegistryAPI.ListContainerRegistries(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(containerRegistries) == 0 { views.RenderInfoMessage("No container registries found") - return + return nil } registryDto, err = containerregistry_view.GetRegistryFromPrompt(containerRegistries, activeProfile.Name, false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } @@ -68,9 +67,10 @@ var containerRegistryDeleteCmd = &cobra.Command{ res, err := apiClient.ContainerRegistryAPI.RemoveContainerRegistry(context.Background(), url.QueryEscape(selectedServer)).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Container registry deleted successfully") + return nil }, } diff --git a/pkg/cmd/containerregistry/list.go b/pkg/cmd/containerregistry/list.go index 349e223572..437099abee 100644 --- a/pkg/cmd/containerregistry/list.go +++ b/pkg/cmd/containerregistry/list.go @@ -11,7 +11,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views" containerregistry_view "github.com/daytonaio/daytona/pkg/views/containerregistry/list" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -20,29 +19,30 @@ var containerRegistryListCmd = &cobra.Command{ Short: "Lists container registries", Aliases: []string{"ls"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } containerRegistries, res, err := apiClient.ContainerRegistryAPI.ListContainerRegistries(context.Background()).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } if len(containerRegistries) == 0 { views.RenderInfoMessage("No container registries found. Set a new container registry by running 'daytona container-registry set'") - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(containerRegistries) formattedData.Print() - return + return nil } containerregistry_view.ListRegistries(containerRegistries) + return nil }, } diff --git a/pkg/cmd/containerregistry/set.go b/pkg/cmd/containerregistry/set.go index a7aced1526..aa81686be6 100644 --- a/pkg/cmd/containerregistry/set.go +++ b/pkg/cmd/containerregistry/set.go @@ -14,8 +14,6 @@ import ( "github.com/daytonaio/daytona/pkg/views" containerregistry_view "github.com/daytonaio/daytona/pkg/views/containerregistry" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var containerRegistrySetCmd = &cobra.Command{ @@ -23,18 +21,18 @@ var containerRegistrySetCmd = &cobra.Command{ Short: "Set container registry", Args: cobra.NoArgs, Aliases: []string{"add", "update", "register"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var registryDto *apiclient.ContainerRegistry selectedServer := serverFlag c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } registryView := containerregistry_view.RegistryView{ @@ -45,12 +43,12 @@ var containerRegistrySetCmd = &cobra.Command{ apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } containerRegistries, res, err := apiClient.ContainerRegistryAPI.ListContainerRegistries(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if serverFlag == "" || usernameFlag == "" || passwordFlag == "" { @@ -61,9 +59,9 @@ var containerRegistrySetCmd = &cobra.Command{ registryDto, err := containerregistry_view.GetRegistryFromPrompt(containerRegistries, activeProfile.Name, true) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } @@ -91,10 +89,11 @@ var containerRegistrySetCmd = &cobra.Command{ res, err = apiClient.ContainerRegistryAPI.SetContainerRegistry(context.Background(), url.QueryEscape(selectedServer)).ContainerRegistry(*registryDto).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Registry set successfully") + return nil }, } diff --git a/pkg/cmd/docs.go b/pkg/cmd/docs.go index 135ed1b8dc..a1042b7fac 100644 --- a/pkg/cmd/docs.go +++ b/pkg/cmd/docs.go @@ -5,7 +5,6 @@ package cmd import ( "fmt" - "log" "github.com/charmbracelet/lipgloss" "github.com/daytonaio/daytona/pkg/views" @@ -22,12 +21,9 @@ var DocsCmd = &cobra.Command{ Short: "Opens the Daytona documentation in your default browser.", Args: cobra.NoArgs, Aliases: []string{"documentation", "doc"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { output := views.GetBoldedInfoMessage("Opening the Daytona documentation in your default browser. If opening fails, you can go to " + linkStyle.Render(docsURL) + " manually.") fmt.Println(output) - err := browser.OpenURL(docsURL) - if err != nil { - log.Fatal(err) - } + return browser.OpenURL(docsURL) }, } diff --git a/pkg/cmd/generatedocs.go b/pkg/cmd/generatedocs.go index a329cf836c..2cbb4dca28 100644 --- a/pkg/cmd/generatedocs.go +++ b/pkg/cmd/generatedocs.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) @@ -19,10 +18,10 @@ var defaultDirectory = "docs" var generateDocsCmd = &cobra.Command{ Use: "generate-docs", Short: "Generate documentation for the Daytona CLI", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { directory, err := cmd.Flags().GetString("directory") if err != nil { - log.Fatal(err) + return err } if directory == "" { @@ -31,25 +30,26 @@ var generateDocsCmd = &cobra.Command{ err = os.MkdirAll(directory, os.ModePerm) if err != nil { - log.Fatal(err) + return err } err = os.MkdirAll(filepath.Join(yamlDirectory, directory), os.ModePerm) if err != nil { - log.Fatal(err) + return err } err = doc.GenMarkdownTree(cmd.Root(), directory) if err != nil { - log.Fatal(err) + return err } err = doc.GenYamlTree(cmd.Root(), filepath.Join(yamlDirectory, directory)) if err != nil { - log.Fatal(err) + return err } fmt.Printf("Documentation generated at %s\n", directory) + return nil }, Hidden: true, } diff --git a/pkg/cmd/gitprovider/add.go b/pkg/cmd/gitprovider/add.go index ad986ffcc7..7d6cc7c8d8 100644 --- a/pkg/cmd/gitprovider/add.go +++ b/pkg/cmd/gitprovider/add.go @@ -10,7 +10,6 @@ import ( "github.com/daytonaio/daytona/pkg/apiclient" "github.com/daytonaio/daytona/pkg/views" gitprovider_view "github.com/daytonaio/daytona/pkg/views/gitprovider" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -18,12 +17,12 @@ var GitProviderAddCmd = &cobra.Command{ Use: "add", Aliases: []string{"new", "register", "update"}, Short: "Register a Git providers", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } setGitProviderConfig := apiclient.SetGitProviderConfig{} @@ -33,14 +32,15 @@ var GitProviderAddCmd = &cobra.Command{ gitprovider_view.GitProviderSelectionView(&setGitProviderConfig, nil, false) if setGitProviderConfig.Id == "" { - return + return nil } res, err := apiClient.GitProviderAPI.SetGitProvider(ctx).GitProviderConfig(setGitProviderConfig).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Git provider has been registered") + return nil }, } diff --git a/pkg/cmd/gitprovider/delete.go b/pkg/cmd/gitprovider/delete.go index 3a3ef75c0c..66c835fdbe 100644 --- a/pkg/cmd/gitprovider/delete.go +++ b/pkg/cmd/gitprovider/delete.go @@ -5,6 +5,7 @@ package gitprovider import ( "context" + "errors" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/apiclient" @@ -18,17 +19,17 @@ var gitProviderDeleteCmd = &cobra.Command{ Use: "delete", Aliases: []string{"remove", "rm"}, Short: "Unregister a Git providers", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } var gitProviderData apiclient.SetGitProviderConfig @@ -37,14 +38,13 @@ var gitProviderDeleteCmd = &cobra.Command{ if len(gitProviders) == 0 { views.RenderInfoMessage("No git providers registered") - return + return nil } gitprovider_view.GitProviderSelectionView(&gitProviderData, gitProviders, true) if gitProviderData.Id == "" { - log.Fatal("Git provider id can not be blank") - return + return errors.New("Git provider id can not be blank") } _, err = apiClient.GitProviderAPI.RemoveGitProvider(ctx, gitProviderData.Id).Execute() @@ -53,5 +53,6 @@ var gitProviderDeleteCmd = &cobra.Command{ } views.RenderInfoMessage("Git provider has been removed") + return nil }, } diff --git a/pkg/cmd/gitprovider/list.go b/pkg/cmd/gitprovider/list.go index 33e1e89f7c..707bd3acd3 100644 --- a/pkg/cmd/gitprovider/list.go +++ b/pkg/cmd/gitprovider/list.go @@ -12,7 +12,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views" gitprovider_view "github.com/daytonaio/daytona/pkg/views/gitprovider" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -20,20 +19,20 @@ var gitProviderListCmd = &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "Lists your registered Git providers", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(context.Background()).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } if len(gitProviders) == 0 { views.RenderInfoMessage("No git providers registered. Add a new git provider by\npreparing a Personal Access Token and running 'daytona git-providers add'") - return + return nil } views.RenderMainTitle("Registered Git Providers:") @@ -58,12 +57,13 @@ var gitProviderListCmd = &cobra.Command{ if format.FormatFlag != "" { formattedData := format.NewFormatter(gitProviderViewList) formattedData.Print() - return + return nil } for _, gitProviderView := range gitProviderViewList { views.RenderListLine(fmt.Sprintf("%s (%s)", gitProviderView.Name, gitProviderView.Username)) } + return nil }, } diff --git a/pkg/cmd/ide.go b/pkg/cmd/ide.go index 3f7f67b228..713e231bc1 100644 --- a/pkg/cmd/ide.go +++ b/pkg/cmd/ide.go @@ -22,10 +22,10 @@ var ideCmd = &cobra.Command{ Use: "ide", Short: "Choose the default IDE", GroupID: util.PROFILE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } ideList := config.GetIdeList() @@ -34,7 +34,7 @@ var ideCmd = &cobra.Command{ chosenIdeId := ide.GetIdeIdFromPrompt(ideList) if chosenIdeId == "" { - return + return nil } for _, ide := range ideList { @@ -70,10 +70,11 @@ var ideCmd = &cobra.Command{ err = c.Save() if err != nil { - log.Fatal(err) + return err } content := fmt.Sprintf("%s %s", views.GetPropertyKey("Default IDE: "), chosenIde.Name) views.RenderContainerLayout(views.GetInfoMessage(content)) + return nil }, } diff --git a/pkg/cmd/ports/forward.go b/pkg/cmd/ports/forward.go index 46d934c2f6..21a381c4db 100644 --- a/pkg/cmd/ports/forward.go +++ b/pkg/cmd/ports/forward.go @@ -32,23 +32,23 @@ var PortForwardCmd = &cobra.Command{ Short: "Forward a port from a project to your local machine", GroupID: util.WORKSPACE_GROUP, Args: cobra.RangeArgs(2, 3), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } port, err := strconv.Atoi(args[0]) if err != nil { - log.Fatal(err) + return err } workspace, err := apiclient.GetWorkspace(args[1], true) if err != nil { - log.Fatal(err) + return err } workspaceId = workspace.Id @@ -57,7 +57,7 @@ var PortForwardCmd = &cobra.Command{ } else { projectName, err = apiclient.GetFirstWorkspaceProjectName(workspaceId, projectName, nil) if err != nil { - log.Fatal(err) + return err } } @@ -65,7 +65,7 @@ var PortForwardCmd = &cobra.Command{ if hostPort == nil { if err = <-errChan; err != nil { - log.Fatal(err) + return err } } else { if *hostPort != uint16(port) { diff --git a/pkg/cmd/prebuild/add.go b/pkg/cmd/prebuild/add.go index 27966b5d40..b0e710bacb 100644 --- a/pkg/cmd/prebuild/add.go +++ b/pkg/cmd/prebuild/add.go @@ -5,8 +5,8 @@ package prebuild import ( "context" + "errors" "fmt" - "log" "strconv" "github.com/daytonaio/daytona/internal/util" @@ -26,60 +26,60 @@ var prebuildAddCmd = &cobra.Command{ Short: "Add a prebuild configuration", Args: cobra.NoArgs, Aliases: []string{"new", "create"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var prebuildAddView add.PrebuildAddView var projectConfig *apiclient.ProjectConfig ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(gitProviders) == 0 { views.RenderInfoMessage("No registered Git providers have been found - please register a Git provider using 'daytona git-provider add' in order to start using prebuilds.") - return + return nil } projectConfigList, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } projectConfig = selection.GetProjectConfigFromPrompt(projectConfigList, 0, false, true, "Prebuild") if projectConfig == nil { - log.Fatal("No project config selected") + return errors.New("No project config selected") } if projectConfig.Name == selection.NewProjectConfigIdentifier { projectConfig, err = projectconfig.RunProjectConfigAddFlow(apiClient, gitProviders, ctx) if err != nil { - log.Fatal(err) + return err } if projectConfig == nil { - return + return nil } } prebuildAddView.ProjectConfigName = projectConfig.Name if projectConfig.BuildConfig == nil { - log.Fatal("The chosen project config does not have a build configuration") + return errors.New("The chosen project config does not have a build configuration") } chosenBranch, err := workspace_util.GetBranchFromProjectConfig(projectConfig, apiClient, 0) if err != nil { - log.Fatal(err) + return err } if chosenBranch == nil { fmt.Println("Operation canceled") - return + return nil } prebuildAddView.RunBuildOnAdd = runOnAddFlag @@ -91,13 +91,13 @@ var prebuildAddCmd = &cobra.Command{ if prebuildAddView.CommitInterval != "" { commitInterval, err = strconv.Atoi(prebuildAddView.CommitInterval) if err != nil { - log.Fatal("commit interval must be a number") + return errors.New("commit interval must be a number") } } retention, err := strconv.Atoi(prebuildAddView.Retention) if err != nil { - log.Fatal("retention must be a number") + return errors.New("retention must be a number") } @@ -116,7 +116,7 @@ var prebuildAddCmd = &cobra.Command{ prebuildId, res, err := apiClient.PrebuildAPI.SetPrebuild(ctx, prebuildAddView.ProjectConfigName).Prebuild(newPrebuild).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Prebuild added successfully") @@ -124,11 +124,13 @@ var prebuildAddCmd = &cobra.Command{ if prebuildAddView.RunBuildOnAdd { buildId, err := build.CreateBuild(apiClient, projectConfig, chosenBranch.Name, &prebuildId) if err != nil { - log.Fatal(err) + return err } views.RenderViewBuildLogsMessage(buildId) } + + return nil }, } diff --git a/pkg/cmd/prebuild/delete.go b/pkg/cmd/prebuild/delete.go index f51f7958fb..a6ee3a96f5 100644 --- a/pkg/cmd/prebuild/delete.go +++ b/pkg/cmd/prebuild/delete.go @@ -5,7 +5,6 @@ package prebuild import ( "context" - "log" "net/http" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" @@ -22,14 +21,14 @@ var prebuildDeleteCmd = &cobra.Command{ Short: "Delete a prebuild configuration", Aliases: []string{"remove", "rm"}, Args: cobra.MaximumNArgs(2), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var selectedPrebuild *apiclient.PrebuildDTO var selectedPrebuildId string var selectedProjectConfigName string apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) < 2 { @@ -40,23 +39,23 @@ var prebuildDeleteCmd = &cobra.Command{ selectedProjectConfigName = args[0] prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuildsForProjectConfig(context.Background(), selectedProjectConfigName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } else { prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuilds(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if len(prebuilds) == 0 { views.RenderInfoMessage("No prebuilds found") - return + return nil } selectedPrebuild = selection.GetPrebuildFromPrompt(prebuilds, "Delete") if selectedPrebuild == nil { - return + return nil } selectedPrebuildId = selectedPrebuild.Id selectedProjectConfigName = selectedPrebuild.ProjectConfigName @@ -67,10 +66,12 @@ var prebuildDeleteCmd = &cobra.Command{ res, err := apiClient.PrebuildAPI.DeletePrebuild(context.Background(), selectedProjectConfigName, selectedPrebuildId).Force(forceFlag).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Prebuild deleted successfully") + + return nil }, } diff --git a/pkg/cmd/prebuild/info.go b/pkg/cmd/prebuild/info.go index 84a155a2c9..249184c6f7 100644 --- a/pkg/cmd/prebuild/info.go +++ b/pkg/cmd/prebuild/info.go @@ -5,7 +5,6 @@ package prebuild import ( "context" - "log" "net/http" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" @@ -21,7 +20,7 @@ var prebuildInfoCmd = &cobra.Command{ Use: "info", Short: "Show prebuild configuration info", Args: cobra.MaximumNArgs(2), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var prebuild *apiclient.PrebuildDTO var res *http.Response @@ -29,7 +28,7 @@ var prebuildInfoCmd = &cobra.Command{ apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) < 2 { @@ -40,18 +39,18 @@ var prebuildInfoCmd = &cobra.Command{ selectedProjectConfigName = args[0] prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuildsForProjectConfig(context.Background(), selectedProjectConfigName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } else { prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuilds(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if len(prebuilds) == 0 { views.RenderInfoMessage("No prebuilds found") - return + return nil } if format.FormatFlag != "" { @@ -64,22 +63,23 @@ var prebuildInfoCmd = &cobra.Command{ } if prebuild == nil { - return + return nil } } else { prebuild, res, err = apiClient.PrebuildAPI.GetPrebuild(ctx, args[0], args[1]).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if format.FormatFlag != "" { formattedData := format.NewFormatter(prebuild) formattedData.Print() - return + return nil } info.Render(prebuild, false) + return nil }, } diff --git a/pkg/cmd/prebuild/list.go b/pkg/cmd/prebuild/list.go index 1893ba2d86..e9e3d89332 100644 --- a/pkg/cmd/prebuild/list.go +++ b/pkg/cmd/prebuild/list.go @@ -5,7 +5,6 @@ package prebuild import ( "context" - "log" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/cmd/format" @@ -19,31 +18,32 @@ var prebuildListCmd = &cobra.Command{ Short: "List prebuild configurations", Aliases: []string{"ls"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } prebuildList, res, err := apiClient.PrebuildAPI.ListPrebuilds(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(prebuildList) == 0 { views.RenderInfoMessage("No prebuilds found. Add a new prebuild by running 'daytona prebuild add'") - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(prebuildList) formattedData.Print() - return + return nil } view.ListPrebuilds(prebuildList) + return nil }, } diff --git a/pkg/cmd/prebuild/update.go b/pkg/cmd/prebuild/update.go index db1cfe9629..a1b612976b 100644 --- a/pkg/cmd/prebuild/update.go +++ b/pkg/cmd/prebuild/update.go @@ -5,7 +5,7 @@ package prebuild import ( "context" - "log" + "errors" "net/http" "strconv" @@ -23,24 +23,24 @@ var prebuildUpdateCmd = &cobra.Command{ Use: "update", Short: "Update a prebuild configuration", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var prebuildAddView add.PrebuildAddView var prebuild *apiclient.PrebuildDTO ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } userGitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(userGitProviders) == 0 { views.RenderInfoMessage("No registered Git providers have been found - please register a Git provider using 'daytona git-provider add' in order to start using prebuilds.") - return + return nil } if len(args) < 2 { @@ -52,28 +52,28 @@ var prebuildUpdateCmd = &cobra.Command{ selectedProjectConfigName = args[0] prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuildsForProjectConfig(context.Background(), selectedProjectConfigName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } else { prebuilds, res, err = apiClient.PrebuildAPI.ListPrebuilds(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if len(prebuilds) == 0 { views.RenderInfoMessage("No prebuilds found") - return + return nil } prebuild = selection.GetPrebuildFromPrompt(prebuilds, "Update") if prebuild == nil { - return + return nil } } else { prebuild, res, err = apiClient.PrebuildAPI.GetPrebuild(ctx, args[0], args[1]).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } @@ -96,13 +96,13 @@ var prebuildUpdateCmd = &cobra.Command{ if prebuildAddView.CommitInterval != "" { commitInterval, err = strconv.Atoi(prebuildAddView.CommitInterval) if err != nil { - log.Fatal("commit interval must be a number") + return errors.New("commit interval must be a number") } } retention, err := strconv.Atoi(prebuildAddView.Retention) if err != nil { - log.Fatal("retention must be a number") + return errors.New("retention must be a number") } newPrebuild := apiclient.CreatePrebuildDTO{ @@ -121,7 +121,7 @@ var prebuildUpdateCmd = &cobra.Command{ prebuildId, res, err := apiClient.PrebuildAPI.SetPrebuild(ctx, prebuildAddView.ProjectConfigName).Prebuild(newPrebuild).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Prebuild updated successfully") @@ -129,16 +129,17 @@ var prebuildUpdateCmd = &cobra.Command{ if prebuildAddView.RunBuildOnAdd { projectConfig, res, err := apiClient.ProjectConfigAPI.GetProjectConfig(ctx, prebuildAddView.ProjectConfigName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } buildId, err := build.CreateBuild(apiClient, projectConfig, *newPrebuild.Branch, &prebuildId) if err != nil { - log.Fatal(err) + return err } views.RenderViewBuildLogsMessage(buildId) } + return nil }, } diff --git a/pkg/cmd/profile/add.go b/pkg/cmd/profile/add.go index 21e63904eb..b1a1ac0ad7 100644 --- a/pkg/cmd/profile/add.go +++ b/pkg/cmd/profile/add.go @@ -8,7 +8,6 @@ import ( "github.com/daytonaio/daytona/internal/util" "github.com/daytonaio/daytona/pkg/views/profile" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -17,11 +16,11 @@ var ProfileAddCmd = &cobra.Command{ Short: "Add profile", Args: cobra.NoArgs, Aliases: []string{"new"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { if !config.IsNotExist(err) { - log.Fatal(err) + return err } c = &config.Config{ @@ -30,7 +29,7 @@ var ProfileAddCmd = &cobra.Command{ } if err := c.Save(); err != nil { - log.Fatal(err) + return err } } @@ -46,9 +45,7 @@ var ProfileAddCmd = &cobra.Command{ _, err = CreateProfile(c, &profileAddView, true) } - if err != nil { - log.Fatal(err) - } + return err }, } diff --git a/pkg/cmd/profile/delete.go b/pkg/cmd/profile/delete.go index 87d655b81d..c623b13056 100644 --- a/pkg/cmd/profile/delete.go +++ b/pkg/cmd/profile/delete.go @@ -4,6 +4,8 @@ package profile import ( + "errors" + "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/views/profile" @@ -16,10 +18,10 @@ var profileDeleteCmd = &cobra.Command{ Short: "Delete profile [PROFILE_NAME]", Args: cobra.RangeArgs(0, 1), Aliases: []string{"remove", "rm"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } var chosenProfileId string @@ -30,11 +32,11 @@ var profileDeleteCmd = &cobra.Command{ chosenProfile, err = profile.GetProfileFromPrompt(profilesList, c.ActiveProfileId, false) if err != nil { - log.Fatal(err) + return err } if chosenProfile == nil { - return + return nil } chosenProfileId = chosenProfile.Id @@ -43,7 +45,7 @@ var profileDeleteCmd = &cobra.Command{ } if chosenProfileId == "default" { - log.Fatal("Can not delete default profile") + return errors.New("can not delete default profile") } for _, profile := range c.Profiles { @@ -54,8 +56,7 @@ var profileDeleteCmd = &cobra.Command{ } if chosenProfile == nil { - log.Fatal("Profile does not exist") - return + return errors.New("profile does not exist") } if c.ActiveProfileId == chosenProfile.Id { @@ -66,12 +67,13 @@ var profileDeleteCmd = &cobra.Command{ if profile.Name == chosenProfile.Name || profile.Id == chosenProfile.Id { err = c.RemoveProfile(profile.Id) if err != nil { - log.Fatal(err) + return err } break } } log.Infof("Deleted profile %s", chosenProfile.Name) + return nil }, } diff --git a/pkg/cmd/profile/edit.go b/pkg/cmd/profile/edit.go index 8e25b62733..a68b03353f 100644 --- a/pkg/cmd/profile/edit.go +++ b/pkg/cmd/profile/edit.go @@ -9,7 +9,6 @@ import ( "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/views/profile" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -17,10 +16,10 @@ var profileEditCmd = &cobra.Command{ Use: "edit", Short: "Edit profile [PROFILE_NAME]", Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } var chosenProfileId string @@ -29,11 +28,11 @@ var profileEditCmd = &cobra.Command{ if len(args) == 0 { chosenProfile, err = profile.GetProfileFromPrompt(c.Profiles, c.ActiveProfileId, false) if err != nil { - log.Fatal(err) + return err } if chosenProfile == nil { - return + return nil } } else { chosenProfileId = args[0] @@ -46,7 +45,7 @@ var profileEditCmd = &cobra.Command{ } if chosenProfile == nil { - log.Fatal("Profile does not exist") + return errors.New("profile does not exist") } if profileNameFlag != "" { @@ -60,11 +59,7 @@ var profileEditCmd = &cobra.Command{ } if profileNameFlag == "" || apiUrlFlag == "" || apiKeyFlag == "" { - err = EditProfile(c, true, chosenProfile) - if err != nil { - log.Fatal(err) - } - return + return EditProfile(c, true, chosenProfile) } profileEditView := profile.ProfileAddView{ @@ -73,10 +68,7 @@ var profileEditCmd = &cobra.Command{ ApiKey: apiKeyFlag, } - err = editProfile(chosenProfile, profileEditView, c, true) - if err != nil { - log.Fatal(err) - } + return editProfile(chosenProfile, profileEditView, c, true) }, } diff --git a/pkg/cmd/profile/list.go b/pkg/cmd/profile/list.go index 609cc30d47..9e03e4e0e9 100644 --- a/pkg/cmd/profile/list.go +++ b/pkg/cmd/profile/list.go @@ -10,7 +10,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views/profile" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -18,24 +17,25 @@ var profileListCmd = &cobra.Command{ Use: "list", Short: "List profiles", Aliases: []string{"ls"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } if format.FormatFlag != "" { formattedData := format.NewFormatter(c.Profiles) formattedData.Print() - return + return nil } output, err := profile.ListProfiles(c.Profiles, c.ActiveProfileId, false) if err != nil { - log.Fatal(err) + return err } fmt.Print(output) + return nil }, } diff --git a/pkg/cmd/profile/use.go b/pkg/cmd/profile/use.go index 13f849abbb..6ab6d78f5f 100644 --- a/pkg/cmd/profile/use.go +++ b/pkg/cmd/profile/use.go @@ -9,8 +9,6 @@ import ( "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/internal/util" - log "github.com/sirupsen/logrus" - "github.com/daytonaio/daytona/pkg/views" "github.com/daytonaio/daytona/pkg/views/profile" "github.com/spf13/cobra" @@ -21,10 +19,10 @@ var ProfileUseCmd = &cobra.Command{ Short: "Use profile [PROFILE_NAME]", Args: cobra.MaximumNArgs(1), GroupID: util.PROFILE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { @@ -32,45 +30,42 @@ var ProfileUseCmd = &cobra.Command{ if len(profilesList) == 0 { views.RenderInfoMessage("Add a profile by running `daytona profile add`") - return + return nil } if len(profilesList) == 1 { views.RenderInfoMessage(fmt.Sprintf("You are using profile %s. Add a new profile by running `daytona profile add`", profilesList[0].Name)) - return + return nil } chosenProfile, err := profile.GetProfileFromPrompt(profilesList, c.ActiveProfileId, true) if err != nil { - log.Fatal(err) + return err } if chosenProfile == nil { - return + return nil } if chosenProfile.Id == profile.NewProfileId { _, err = CreateProfile(c, nil, true) - if err != nil { - log.Fatal(err) - } - return + return err } if chosenProfile.Id == "" { - return + return nil } profile, err := c.GetProfile(chosenProfile.Id) if err != nil { - log.Fatal(err) + return err } c.ActiveProfileId = profile.Id err = c.Save() if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage(fmt.Sprintf("Active profile set to: %s", profile.Name)) @@ -87,17 +82,18 @@ var ProfileUseCmd = &cobra.Command{ } if chosenProfile == (config.Profile{}) { - log.Fatal("Profile does not exist: ", profileArg) + return fmt.Errorf("profile does not exist: %s", profileArg) } c.ActiveProfileId = chosenProfile.Id err = c.Save() if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage(fmt.Sprintf("Active profile set to: %s", chosenProfile.Name)) } + return nil }, } diff --git a/pkg/cmd/profiledata/env/list.go b/pkg/cmd/profiledata/env/list.go index 638d904b28..c92106b809 100644 --- a/pkg/cmd/profiledata/env/list.go +++ b/pkg/cmd/profiledata/env/list.go @@ -11,24 +11,22 @@ import ( "github.com/daytonaio/daytona/pkg/views" "github.com/daytonaio/daytona/pkg/views/env" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var listCmd = &cobra.Command{ Use: "list", Short: "List profile environment variables", Aliases: []string{"ls"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } ctx := context.Background() profileData, res, err := apiClient.ProfileAPI.GetProfileData(ctx).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } if format.FormatFlag != "" { @@ -37,15 +35,16 @@ var listCmd = &cobra.Command{ } formattedData := format.NewFormatter(profileData.EnvVars) formattedData.Print() - return + return nil } if len(profileData.EnvVars) == 0 { views.RenderInfoMessageBold("No environment variables set") - return + return nil } env.List(profileData.EnvVars) + return nil }, } diff --git a/pkg/cmd/profiledata/env/set.go b/pkg/cmd/profiledata/env/set.go index 367ca035d2..a372ba2148 100644 --- a/pkg/cmd/profiledata/env/set.go +++ b/pkg/cmd/profiledata/env/set.go @@ -19,16 +19,16 @@ var setCmd = &cobra.Command{ Use: "set [KEY=VALUE]...", Short: "Set profile environment variables", Aliases: []string{"s", "update", "add", "delete", "rm"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } ctx := context.Background() profileData, res, err := apiClient.ProfileAPI.GetProfileData(ctx).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } if profileData.EnvVars == nil { @@ -58,9 +58,10 @@ var setCmd = &cobra.Command{ res, err = apiClient.ProfileAPI.SetProfileData(ctx).ProfileData(*profileData).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } views.RenderInfoMessageBold("Profile environment variables have been successfully set") + return nil }, } diff --git a/pkg/cmd/projectconfig/add.go b/pkg/cmd/projectconfig/add.go index 6a9cf9a615..7b14f3858b 100644 --- a/pkg/cmd/projectconfig/add.go +++ b/pkg/cmd/projectconfig/add.go @@ -25,28 +25,28 @@ var projectConfigAddCmd = &cobra.Command{ Aliases: []string{"new", "create"}, Short: "Add a project config", Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var projectConfig *apiclient.ProjectConfig var projectConfigName *string ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(args) == 0 { projectConfig, err = RunProjectConfigAddFlow(apiClient, gitProviders, ctx) if err != nil { - log.Fatal(err) + return err } if projectConfig == nil { - return + return nil } projectConfigName = &projectConfig.Name } else { @@ -57,10 +57,11 @@ var projectConfigAddCmd = &cobra.Command{ } if projectConfigName == nil { - log.Fatal("project config name is required") + return errors.New("project config name is required") } views.RenderInfoMessage(fmt.Sprintf("Project config %s added successfully", *projectConfigName)) + return nil }, } @@ -70,7 +71,10 @@ func RunProjectConfigAddFlow(apiClient *apiclient.APIClient, gitProviders []apic } var createDtos []apiclient.CreateProjectDTO - existingProjectConfigNames := getExistingProjectConfigNames(apiClient) + existingProjectConfigNames, err := getExistingProjectConfigNames(apiClient) + if err != nil { + return nil, err + } apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { @@ -176,7 +180,10 @@ func processCmdArgument(argument string, apiClient *apiclient.APIClient, ctx con return nil, apiclient_util.HandleErrorResponse(res, err) } - existingProjectConfigNames := getExistingProjectConfigNames(apiClient) + existingProjectConfigNames, err := getExistingProjectConfigNames(apiClient) + if err != nil { + return nil, err + } repoUrl, err := util.GetValidatedUrl(argument) if err != nil { @@ -228,19 +235,19 @@ func processCmdArgument(argument string, apiClient *apiclient.APIClient, ctx con return &newProjectConfig.Name, nil } -func getExistingProjectConfigNames(apiClient *apiclient.APIClient) []string { +func getExistingProjectConfigNames(apiClient *apiclient.APIClient) ([]string, error) { var existingProjectConfigNames []string existingProjectConfigs, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return nil, apiclient_util.HandleErrorResponse(res, err) } for _, pc := range existingProjectConfigs { existingProjectConfigNames = append(existingProjectConfigNames, pc.Name) } - return existingProjectConfigNames + return existingProjectConfigNames, nil } var nameFlag string diff --git a/pkg/cmd/projectconfig/delete.go b/pkg/cmd/projectconfig/delete.go index 4b839bd119..cd015a704c 100644 --- a/pkg/cmd/projectconfig/delete.go +++ b/pkg/cmd/projectconfig/delete.go @@ -25,13 +25,13 @@ var projectConfigDeleteCmd = &cobra.Command{ Aliases: []string{"remove", "rm"}, Short: "Delete a project config", Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var selectedProjectConfig *apiclient.ProjectConfig var selectedProjectConfigName string apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if allFlag { @@ -47,23 +47,23 @@ var projectConfigDeleteCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } if !yesFlag { fmt.Println("Operation canceled.") - return + return nil } } projectConfigs, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(projectConfigs) == 0 { views.RenderInfoMessage("No project configs found") - return + return nil } for _, projectConfig := range projectConfigs { @@ -75,23 +75,23 @@ var projectConfigDeleteCmd = &cobra.Command{ } views.RenderInfoMessage("Deleted project config: " + selectedProjectConfigName) } - return + return nil } if len(args) == 0 { projectConfigs, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(projectConfigs) == 0 { views.RenderInfoMessage("No project configs found") - return + return nil } selectedProjectConfig = selection.GetProjectConfigFromPrompt(projectConfigs, 0, false, false, "Delete") if selectedProjectConfig == nil { - return + return nil } selectedProjectConfigName = selectedProjectConfig.Name } else { @@ -100,10 +100,11 @@ var projectConfigDeleteCmd = &cobra.Command{ res, err := apiClient.ProjectConfigAPI.DeleteProjectConfig(context.Background(), selectedProjectConfigName).Force(forceFlag).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Project config deleted successfully") + return nil }, } diff --git a/pkg/cmd/projectconfig/info.go b/pkg/cmd/projectconfig/info.go index 54b1931d43..ee149e54c8 100644 --- a/pkg/cmd/projectconfig/info.go +++ b/pkg/cmd/projectconfig/info.go @@ -12,7 +12,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views/projectconfig/info" "github.com/daytonaio/daytona/pkg/views/workspace/selection" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -21,17 +20,17 @@ var projectConfigInfoCmd = &cobra.Command{ Short: "Show project config info", Aliases: []string{"view", "inspect"}, Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } var projectConfig *apiclient.ProjectConfig @@ -39,7 +38,7 @@ var projectConfigInfoCmd = &cobra.Command{ if len(args) == 0 { projectConfigList, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if format.FormatFlag != "" { @@ -55,21 +54,22 @@ var projectConfigInfoCmd = &cobra.Command{ var res *http.Response projectConfig, res, err = apiClient.ProjectConfigAPI.GetProjectConfig(ctx, args[0]).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if projectConfig == nil { - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(projectConfig) formattedData.Print() - return + return nil } info.Render(projectConfig, apiServerConfig, false) + return nil }, } diff --git a/pkg/cmd/projectconfig/list.go b/pkg/cmd/projectconfig/list.go index a4e0a50600..23dc84b179 100644 --- a/pkg/cmd/projectconfig/list.go +++ b/pkg/cmd/projectconfig/list.go @@ -10,7 +10,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views" projectconfig_view "github.com/daytonaio/daytona/pkg/views/projectconfig/list" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -19,18 +18,18 @@ var projectConfigListCmd = &cobra.Command{ Short: "Lists project configs", Aliases: []string{"ls"}, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var specifyGitProviders bool apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(gitProviders) > 1 { @@ -39,26 +38,27 @@ var projectConfigListCmd = &cobra.Command{ apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } projectConfigs, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(projectConfigs) == 0 { views.RenderInfoMessage("No project configs found. Add a new project config by running 'daytona project-config add'") - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(projectConfigs) formattedData.Print() - return + return nil } projectconfig_view.ListProjectConfigs(projectConfigs, apiServerConfig, specifyGitProviders) + return nil }, } diff --git a/pkg/cmd/projectconfig/setdefault.go b/pkg/cmd/projectconfig/setdefault.go index 288d9d5442..c43bb47141 100644 --- a/pkg/cmd/projectconfig/setdefault.go +++ b/pkg/cmd/projectconfig/setdefault.go @@ -10,7 +10,6 @@ import ( apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/views" "github.com/daytonaio/daytona/pkg/views/workspace/selection" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -18,24 +17,24 @@ var projectConfigSetDefaultCmd = &cobra.Command{ Use: "set-default", Short: "Set project config info", Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var projectConfigName string ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { projectConfigList, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } projectConfig := selection.GetProjectConfigFromPrompt(projectConfigList, 0, false, false, "Make Default") if projectConfig == nil { - return + return nil } projectConfigName = projectConfig.Name } else { @@ -44,10 +43,11 @@ var projectConfigSetDefaultCmd = &cobra.Command{ res, err := apiClient.ProjectConfigAPI.SetDefaultProjectConfig(ctx, projectConfigName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage(fmt.Sprintf("Project config '%s' set as default", projectConfigName)) + return nil }, } diff --git a/pkg/cmd/projectconfig/update.go b/pkg/cmd/projectconfig/update.go index b5471b9cd5..19a9f4b021 100644 --- a/pkg/cmd/projectconfig/update.go +++ b/pkg/cmd/projectconfig/update.go @@ -13,7 +13,6 @@ import ( views_util "github.com/daytonaio/daytona/pkg/views/util" "github.com/daytonaio/daytona/pkg/views/workspace/create" "github.com/daytonaio/daytona/pkg/views/workspace/selection" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -21,35 +20,35 @@ var projectConfigUpdateCmd = &cobra.Command{ Use: "update", Short: "Update a project config", Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var projectConfig *apiclient.ProjectConfig var res *http.Response ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { projectConfigList, res, err := apiClient.ProjectConfigAPI.ListProjectConfigs(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } projectConfig = selection.GetProjectConfigFromPrompt(projectConfigList, 0, false, false, "Update") if projectConfig == nil { - return + return nil } } else { projectConfig, res, err = apiClient.ProjectConfigAPI.GetProjectConfig(ctx, args[0]).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } } if projectConfig == nil { - return + return nil } createDto := []apiclient.CreateProjectDTO{ @@ -77,7 +76,7 @@ var projectConfigUpdateCmd = &cobra.Command{ create.ProjectsConfigurationChanged, err = create.RunProjectConfiguration(&createDto, *projectDefaults) if err != nil { - log.Fatal(err) + return err } newProjectConfig := apiclient.CreateProjectConfigDTO{ @@ -91,9 +90,10 @@ var projectConfigUpdateCmd = &cobra.Command{ res, err = apiClient.ProjectConfigAPI.SetProjectConfig(ctx).ProjectConfig(newProjectConfig).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Project config updated successfully") + return nil }, } diff --git a/pkg/cmd/provider/install.go b/pkg/cmd/provider/install.go index e8cbc62972..de4ce38afd 100644 --- a/pkg/cmd/provider/install.go +++ b/pkg/cmd/provider/install.go @@ -5,6 +5,7 @@ package provider import ( "context" + "errors" "fmt" "slices" @@ -20,8 +21,6 @@ import ( "github.com/daytonaio/daytona/pkg/views/target" views_util "github.com/daytonaio/daytona/pkg/views/util" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var yesFlag bool @@ -31,31 +30,31 @@ var providerInstallCmd = &cobra.Command{ Short: "Install provider", Args: cobra.NoArgs, Aliases: []string{"i"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } serverConfig, res, err := apiClient.ServerAPI.GetConfigExecute(apiclient.ApiGetConfigRequest{}) if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } providerManager := manager.NewProviderManager(manager.ProviderManagerConfig{RegistryUrl: serverConfig.RegistryUrl}) providersManifest, err := providerManager.GetProvidersManifest() if err != nil { - log.Fatal(err) + return err } if providersManifest == nil { - log.Fatal("Could not get providers manifest") + return errors.New("could not get providers manifest") } providersManifestLatest := providersManifest.GetLatestVersions() if providersManifestLatest == nil { - log.Fatal("Could not get providers manifest") + return errors.New("could not get providers manifest") } providerList := GetProviderListFromManifest(providersManifestLatest) @@ -66,14 +65,14 @@ var providerInstallCmd = &cobra.Command{ providerToInstall, err := provider.GetProviderFromPrompt(provider.ProviderListToView(providerList), "Choose a Provider to Install", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } if providerToInstall == nil { - return + return nil } if providerToInstall.Name == specificProviderName { @@ -82,33 +81,33 @@ var providerInstallCmd = &cobra.Command{ providerToInstall, err = provider.GetProviderFromPrompt(provider.ProviderListToView(providerList), "Choose a specific provider to install", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } if providerToInstall == nil { - return + return nil } } err = InstallProvider(apiClient, *providerToInstall, providersManifest) if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessageBold(fmt.Sprintf("Provider %s has been successfully installed", providerToInstall.Name)) targets, res, err := apiClient.TargetAPI.ListTargets(context.Background()).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if slices.ContainsFunc(targets, func(t apiclient.ProviderTarget) bool { return t.ProviderInfo.Name == providerToInstall.Name }) { - return + return nil } if !yesFlag { @@ -122,14 +121,14 @@ var providerInstallCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } } if yesFlag { targetManifest, res, err := apiClient.ProviderAPI.GetTargetManifest(context.Background(), providerToInstall.Name).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } targetToSet := &apiclient.ProviderTarget{ @@ -142,24 +141,25 @@ var providerInstallCmd = &cobra.Command{ err = target.NewTargetNameInput(&targetToSet.Name, []string{}) if err != nil { - log.Fatal(err) + return err } err = target.SetTargetForm(targetToSet, *targetManifest) if err != nil { - log.Fatal(err) + return err } res, err = apiClient.TargetAPI.SetTarget(context.Background()).Target(*targetToSet).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage("Target set successfully") } + return nil }, } diff --git a/pkg/cmd/provider/list.go b/pkg/cmd/provider/list.go index 86d1b2bb67..59c070e62a 100644 --- a/pkg/cmd/provider/list.go +++ b/pkg/cmd/provider/list.go @@ -13,8 +13,6 @@ import ( "github.com/daytonaio/daytona/pkg/views/provider" provider_view "github.com/daytonaio/daytona/pkg/views/provider" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var providerListCmd = &cobra.Command{ @@ -22,35 +20,36 @@ var providerListCmd = &cobra.Command{ Short: "List installed providers", Args: cobra.NoArgs, Aliases: []string{"ls"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } providerList, res, err := apiClient.ProviderAPI.ListProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if format.FormatFlag != "" { formattedData := format.NewFormatter(providerList) formattedData.Print() - return + return nil } provider.List(providerList) + return nil }, } -func GetProviderViewOptions(apiClient *apiclient.APIClient, latestProviders []apiclient.Provider, ctx context.Context) []provider_view.ProviderView { +func GetProviderViewOptions(apiClient *apiclient.APIClient, latestProviders []apiclient.Provider, ctx context.Context) ([]provider_view.ProviderView, error) { var result []provider_view.ProviderView installedProviders, res, err := apiClient.ProviderAPI.ListProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return nil, apiclient_util.HandleErrorResponse(res, err) } providerMap := make(map[string]provider_view.ProviderView) @@ -77,7 +76,7 @@ func GetProviderViewOptions(apiClient *apiclient.APIClient, latestProviders []ap result = append(result, provider) } - return result + return result, nil } func init() { diff --git a/pkg/cmd/provider/uninstall.go b/pkg/cmd/provider/uninstall.go index 42d945bc8b..90d2a2011e 100644 --- a/pkg/cmd/provider/uninstall.go +++ b/pkg/cmd/provider/uninstall.go @@ -13,8 +13,6 @@ import ( "github.com/daytonaio/daytona/pkg/views" "github.com/daytonaio/daytona/pkg/views/provider" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var providerUninstallCmd = &cobra.Command{ @@ -22,37 +20,38 @@ var providerUninstallCmd = &cobra.Command{ Short: "Uninstall provider", Args: cobra.NoArgs, Aliases: []string{"u"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } providerList, res, err := apiClient.ProviderAPI.ListProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } providerToUninstall, err := provider.GetProviderFromPrompt(provider.ProviderListToView(providerList), "Choose a Provider to Uninstall", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } if providerToUninstall == nil { - return + return nil } res, err = apiClient.ProviderAPI.UninstallProvider(ctx, providerToUninstall.Name).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } views.RenderInfoMessageBold(fmt.Sprintf("Provider %s has been successfully uninstalled", providerToUninstall.Name)) + return nil }, } diff --git a/pkg/cmd/provider/update.go b/pkg/cmd/provider/update.go index a068a16c88..f8419958e2 100644 --- a/pkg/cmd/provider/update.go +++ b/pkg/cmd/provider/update.go @@ -24,29 +24,29 @@ var providerUpdateCmd = &cobra.Command{ Short: "Update provider", Args: cobra.NoArgs, Aliases: []string{"up"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } providerList, res, err := apiClient.ProviderAPI.ListProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } serverConfig, res, err := apiClient.ServerAPI.GetConfigExecute(apiclient.ApiGetConfigRequest{}) if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } providerManager := manager.NewProviderManager(manager.ProviderManagerConfig{RegistryUrl: serverConfig.RegistryUrl}) providersManifest, err := providerManager.GetProvidersManifest() if err != nil { - log.Fatal(err) + return err } if allFlag { @@ -60,34 +60,35 @@ var providerUpdateCmd = &cobra.Command{ } } - return + return nil } providerToUpdate, err := provider.GetProviderFromPrompt(provider.ProviderListToView(providerList), "Choose a Provider to Update", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } if providerToUpdate == nil { - return + return nil } err = updateProvider(providerToUpdate.Name, providersManifest, apiClient) if err != nil { - log.Fatal(err) + return err } fmt.Printf("Provider %s has been successfully updated\n", providerToUpdate.Name) + return nil }, } func updateProvider(providerName string, providersManifest *manager.ProvidersManifest, apiClient *apiclient.APIClient) error { providerManifest, ok := (*providersManifest)[providerName] if !ok { - return fmt.Errorf("Provider %s not found in manifest", providerName) + return fmt.Errorf("provider %s not found in manifest", providerName) } version, ok := providerManifest.Versions["latest"] diff --git a/pkg/cmd/purge.go b/pkg/cmd/purge.go index 5cd34445e5..273c3259ea 100644 --- a/pkg/cmd/purge.go +++ b/pkg/cmd/purge.go @@ -30,29 +30,29 @@ var purgeCmd = &cobra.Command{ Short: "Purges all Daytona data from the current device", Long: "Purges all Daytona data from the current device - including all workspaces, configuration files, and SSH files. This command is irreversible.", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var confirmCheck bool var serverStoppedCheck bool var defaultProfileNoticeConfirm bool c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } serverConfig, err := server.GetConfig() if err != nil { - log.Fatal(err) + return err } serverConfigDir, err := server.GetConfigDir() if err != nil { - log.Fatal(err) + return err } buildRunnerConfig, err := build.GetConfig() if err != nil { - log.Fatal(err) + return err } if c.ActiveProfileId != "default" { @@ -60,26 +60,26 @@ var purgeCmd = &cobra.Command{ view.DefaultProfileNoticePrompt(&defaultProfileNoticeConfirm) if !defaultProfileNoticeConfirm { fmt.Println("Operation cancelled.") - return + return nil } } } defaultProfile, err := c.GetProfile("default") if err != nil { - log.Fatal(err) + return err } _, err = apiclient.GetApiClient(&defaultProfile) if err != nil { if !apiclient.IsHealthCheckFailed(err) { - log.Fatal(err) + return err } } else { view.ServerStoppedPrompt(&serverStoppedCheck) if !serverStoppedCheck { fmt.Println("Operation cancelled.") - return + return nil } } @@ -87,7 +87,7 @@ var purgeCmd = &cobra.Command{ view.ConfirmPrompt(&confirmCheck) if !confirmCheck { fmt.Println("Operation cancelled.") - return + return nil } } @@ -101,11 +101,11 @@ var purgeCmd = &cobra.Command{ fmt.Println("Purging the server") server, err := server_cmd.GetInstance(serverConfig, serverConfigDir, telemetryService) if err != nil { - log.Fatal(err) + return err } buildRunner, err := server_cmd.GetBuildRunner(serverConfig, buildRunnerConfig, telemetryService) if err != nil { - log.Fatal(err) + return err } ctx := context.Background() @@ -118,7 +118,7 @@ var purgeCmd = &cobra.Command{ err = buildRunner.Start() if err != nil { if !forceFlag { - log.Fatal(err) + return err } } @@ -142,19 +142,19 @@ var purgeCmd = &cobra.Command{ fmt.Println("\nDeleting the SSH configuration file") err = config.UnlinkSshFiles() if err != nil { - log.Fatal(err) + return err } fmt.Println("Deleting autocompletion data") err = config.DeleteAutocompletionData() if err != nil { - log.Fatal(err) + return err } fmt.Println("Deleting the Daytona config directory") err = config.DeleteConfigDir() if err != nil { - log.Fatal(err) + return err } binaryMessage := "You may now delete the binary" @@ -164,6 +164,7 @@ var purgeCmd = &cobra.Command{ } views.RenderInfoMessage(fmt.Sprintf("All Daytona data has been successfully cleared from the device.\n%s", binaryMessage)) + return nil }, } diff --git a/pkg/cmd/server/config.go b/pkg/cmd/server/config.go index 6311cef7fa..0ea3079936 100644 --- a/pkg/cmd/server/config.go +++ b/pkg/cmd/server/config.go @@ -5,7 +5,6 @@ package server import ( view "github.com/daytonaio/daytona/pkg/views/server" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/pkg/cmd/format" @@ -15,18 +14,20 @@ import ( var configCmd = &cobra.Command{ Use: "config", Short: "Output local Daytona Server config", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { config, err := server.GetConfig() if err != nil { - log.Fatal(err) + return err } if format.FormatFlag != "" { formattedData := format.NewFormatter(config) formattedData.Print() + return nil } view.RenderConfig(config) + return nil }, } diff --git a/pkg/cmd/server/configure.go b/pkg/cmd/server/configure.go index 4bb4e91669..17be48ed01 100644 --- a/pkg/cmd/server/configure.go +++ b/pkg/cmd/server/configure.go @@ -9,39 +9,39 @@ import ( "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/views" server_view "github.com/daytonaio/daytona/pkg/views/server" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var configureCmd = &cobra.Command{ Use: "configure", Short: "Configure Daytona Server", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } apiServerConfig, res, err := apiClient.ServerAPI.GetConfig(context.Background()).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } containerRegistries, res, err := apiClient.ContainerRegistryAPI.ListContainerRegistries(context.Background()).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } apiServerConfig, err = server_view.ConfigurationForm(apiServerConfig, containerRegistries) if err != nil { - log.Fatal(err) + return err } _, res, err = apiClient.ServerAPI.SetConfig(context.Background()).Config(*apiServerConfig).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } views.RenderContainerLayout(views.GetInfoMessage("Server configuration updated. You need to restart the server for the changes to take effect.")) + return nil }, } diff --git a/pkg/cmd/server/logs.go b/pkg/cmd/server/logs.go index f6f683e747..9f6f131219 100644 --- a/pkg/cmd/server/logs.go +++ b/pkg/cmd/server/logs.go @@ -25,15 +25,15 @@ var fileFlag bool var logsCmd = &cobra.Command{ Use: "logs", Short: "Output Daytona Server logs", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } query := "" @@ -43,7 +43,7 @@ var logsCmd = &cobra.Command{ switch { case fileFlag: - readServerLogFile() + return readServerLogFile() default: ws, res, err := apiclient.GetWebsocketConn(context.Background(), "/log/server", &activeProfile, &query) @@ -52,7 +52,7 @@ var logsCmd = &cobra.Command{ log.Error(apiclient.HandleErrorResponse(res, err)) if activeProfile.Id != "default" { - return + return nil } readLogsFile := true @@ -64,39 +64,38 @@ var logsCmd = &cobra.Command{ ).WithTheme(views.GetCustomTheme()) formErr := form.Run() if formErr != nil { - log.Fatal(formErr) + return formErr } if readLogsFile { - readServerLogFile() + return readServerLogFile() } - return + return nil } for { _, msg, err := ws.ReadMessage() if err != nil { - return + return nil } fmt.Println(string(msg)) } } - }, } -func readServerLogFile() { +func readServerLogFile() error { views.RenderBorderedMessage("Reading from server log file...") cfg, err := server.GetConfig() if err != nil { - log.Fatal(fmt.Errorf("failed to get server config: %w", err).Error()) + return fmt.Errorf("failed to get server config: %w", err) } file, err := os.Open(cfg.LogFilePath) if err != nil { - log.Fatal(fmt.Errorf("while opening server logs: %w", err).Error()) + return fmt.Errorf("while opening server logs: %w", err) } defer file.Close() msgChan := make(chan []byte) @@ -107,13 +106,13 @@ func readServerLogFile() { for { select { case <-context.Background().Done(): - return + return nil case err := <-errChan: if err != nil { if err != io.EOF { - log.Fatal(err) + return err } - return + return nil } case msg := <-msgChan: fmt.Println(string(msg)) diff --git a/pkg/cmd/server/restart.go b/pkg/cmd/server/restart.go index 90358303e3..1687716657 100644 --- a/pkg/cmd/server/restart.go +++ b/pkg/cmd/server/restart.go @@ -4,7 +4,6 @@ package server import ( - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/pkg/cmd/server/daemon" @@ -15,23 +14,24 @@ import ( var restartCmd = &cobra.Command{ Use: "restart", Short: "Restarts the Daytona Server daemon", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { views.RenderInfoMessage("Stopping the Daytona Server daemon...") err := daemon.Stop() if err != nil { - log.Fatal(err) + return err } c, err := server.GetConfig() if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage("Starting the Daytona Server daemon...") err = daemon.Start(c.LogFilePath) if err != nil { - log.Fatal(err) + return err } views.RenderContainerLayout(views.GetBoldedInfoMessage("Daytona Server daemon restarted successfully")) + return nil }, } diff --git a/pkg/cmd/server/serve.go b/pkg/cmd/server/serve.go index eda908a237..93dfdeb631 100644 --- a/pkg/cmd/server/serve.go +++ b/pkg/cmd/server/serve.go @@ -49,7 +49,7 @@ var ServeCmd = &cobra.Command{ Short: "Run the server process in the current terminal session", GroupID: util.SERVER_GROUP, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if os.Getenv("USER") == "root" { views.RenderInfoMessageBold("Running the server as root is not recommended because\nDaytona will not be able to remap project directory ownership.\nPlease run the server as a non-root user.") } @@ -61,12 +61,12 @@ var ServeCmd = &cobra.Command{ configDir, err := server.GetConfigDir() if err != nil { - log.Fatal(err) + return err } c, err := server.GetConfig() if err != nil { - log.Fatal(err) + return err } telemetryService := posthogservice.NewTelemetryService(posthogservice.PosthogServiceConfig{ @@ -80,7 +80,6 @@ var ServeCmd = &cobra.Command{ for range interruptChannel { log.Info("Shutting down") - telemetryService.Close() } }() @@ -91,35 +90,35 @@ var ServeCmd = &cobra.Command{ server, err := GetInstance(c, configDir, telemetryService) if err != nil { - log.Fatal(err) + return err } errCh := make(chan error) err = server.Start(errCh) if err != nil { - log.Fatal(err) + return err } buildRunnerConfig, err := build.GetConfig() if err != nil { - log.Fatal(err) + return err } buildRunner, err := GetBuildRunner(c, buildRunnerConfig, telemetryService) if err != nil { - log.Fatal(err) + return err } err = buildRunner.Start() if err != nil { - log.Fatal(err) + return err } go func() { err := apiServer.Start() if err != nil { - log.Fatal(err) + errCh <- err } }() @@ -127,27 +126,23 @@ var ServeCmd = &cobra.Command{ err := <-errCh if err != nil { buildRunner.Stop() - log.Fatal(err) } }() err = waitForServerToStart(apiServer) if err != nil { - log.Fatal(err) + return err } printServerStartedMessage(c, false) err = setDefaultConfig(server, c.ApiPort) if err != nil { - log.Fatal(err) + return err } - err = <-errCh - if err != nil { - log.Fatal(err) - } + return <-errCh }, } @@ -179,7 +174,7 @@ func GetInstance(c *server.Config, configDir string, telemetryService telemetry. } buildStore, err := db.NewBuildStore(dbConnection) if err != nil { - log.Fatal(err) + return nil, err } projectConfigStore, err := db.NewProjectConfigStore(dbConnection) if err != nil { diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index f3c5b4dd25..50aa4cf66b 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -26,14 +26,14 @@ var ServerCmd = &cobra.Command{ Short: "Start the server process in daemon mode", GroupID: util.SERVER_GROUP, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { confirmCheck := true if !yesFlag { view.ConfirmPrompt(&confirmCheck) if !confirmCheck { views.RenderInfoMessage("Operation cancelled.") - return + return nil } } @@ -44,7 +44,7 @@ var ServerCmd = &cobra.Command{ c, err := server.GetConfig() if err != nil { - log.Fatal(err) + return err } apiServer := api.NewApiServer(api.ApiServerConfig{ @@ -54,11 +54,11 @@ var ServerCmd = &cobra.Command{ views.RenderInfoMessageBold("Starting the Daytona Server daemon...") err = daemon.Start(c.LogFilePath) if err != nil { - log.Fatal(err) + return err } err = waitForServerToStart(apiServer) if err != nil { - log.Fatal(err) + return err } printServerStartedMessage(c, true) @@ -66,13 +66,14 @@ var ServerCmd = &cobra.Command{ case "linux": fmt.Printf("Use `loginctl enable-linger %s` to allow the service to run after logging out.\n", os.Getenv("USER")) } + return nil }, } var startCmd = &cobra.Command{ Use: "start", Short: "Start the Daytona Server daemon", - Run: ServerCmd.Run, + RunE: ServerCmd.RunE, } func init() { diff --git a/pkg/cmd/server/stop.go b/pkg/cmd/server/stop.go index 122af45694..12d9ca72ac 100644 --- a/pkg/cmd/server/stop.go +++ b/pkg/cmd/server/stop.go @@ -4,7 +4,6 @@ package server import ( - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/pkg/cmd/server/daemon" @@ -14,11 +13,8 @@ import ( var stopCmd = &cobra.Command{ Use: "stop", Short: "Stops the Daytona Server daemon", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { views.RenderInfoMessageBold("Stopping the Daytona Server daemon...") - err := daemon.Stop() - if err != nil { - log.Fatal(err) - } + return daemon.Stop() }, } diff --git a/pkg/cmd/target/list.go b/pkg/cmd/target/list.go index 07a2358294..a55622784a 100644 --- a/pkg/cmd/target/list.go +++ b/pkg/cmd/target/list.go @@ -5,7 +5,6 @@ package target import ( "context" - "log" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/cmd/format" @@ -19,32 +18,33 @@ var targetListCmd = &cobra.Command{ Short: "List targets", Args: cobra.NoArgs, Aliases: []string{"ls"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } targetList, res, err := apiClient.TargetAPI.ListTargets(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if len(targetList) == 0 { views.RenderInfoMessageBold("No targets found") views.RenderInfoMessage("Use 'daytona target set' to add a target") - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(targetList) formattedData.Print() - return + return nil } list_view.ListTargets(targetList) + return nil }, } diff --git a/pkg/cmd/target/remove.go b/pkg/cmd/target/remove.go index cf994b3350..af55862307 100644 --- a/pkg/cmd/target/remove.go +++ b/pkg/cmd/target/remove.go @@ -27,37 +27,37 @@ var targetRemoveCmd = &cobra.Command{ Short: "Remove target", Args: cobra.RangeArgs(0, 1), Aliases: []string{"rm", "delete"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var selectedTargetName string ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } targetList, res, err := apiClient.TargetAPI.ListTargets(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } selectedTarget, err := target.GetTargetFromPrompt(targetList, activeProfile.Name, false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } @@ -71,7 +71,7 @@ var targetRemoveCmd = &cobra.Command{ err := RemoveTargetWorkspaces(ctx, apiClient, selectedTargetName) if err != nil { - log.Fatal(err) + return err } } else { form := huh.NewForm( @@ -85,13 +85,13 @@ var targetRemoveCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } if yesFlag { err := RemoveTargetWorkspaces(ctx, apiClient, selectedTargetName) if err != nil { - log.Fatal(err) + return err } } else { fmt.Println("Proceeding with target removal without deleting workspaces.") @@ -100,10 +100,11 @@ var targetRemoveCmd = &cobra.Command{ res, err := apiClient.TargetAPI.RemoveTarget(ctx, selectedTargetName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessageBold(fmt.Sprintf("Target %s removed successfully", selectedTargetName)) + return nil }, } diff --git a/pkg/cmd/target/set.go b/pkg/cmd/target/set.go index a6525e3678..6008ba7bd8 100644 --- a/pkg/cmd/target/set.go +++ b/pkg/cmd/target/set.go @@ -5,6 +5,7 @@ package target import ( "context" + "errors" "fmt" "github.com/daytonaio/daytona/cmd/daytona/config" @@ -27,27 +28,27 @@ var TargetSetCmd = &cobra.Command{ Short: "Set provider target", Args: cobra.NoArgs, Aliases: []string{"s", "add", "update", "register", "edit"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } serverConfig, res, err := apiClient.ServerAPI.GetConfigExecute(apiclient.ApiGetConfigRequest{}) if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } providersManifest, err := manager.NewProviderManager(manager.ProviderManagerConfig{ @@ -61,7 +62,7 @@ var TargetSetCmd = &cobra.Command{ if providersManifest != nil { providersManifestLatest := providersManifest.GetLatestVersions() if providersManifestLatest == nil { - log.Fatal("Could not get latest provider versions") + return errors.New("could not get latest provider versions") } latestProviders = provider.GetProviderListFromManifest(providersManifestLatest) @@ -69,34 +70,37 @@ var TargetSetCmd = &cobra.Command{ fmt.Println("Could not get provider manifest. Can't check for new providers to install") } - providerViewList := provider.GetProviderViewOptions(apiClient, latestProviders, ctx) + providerViewList, err := provider.GetProviderViewOptions(apiClient, latestProviders, ctx) + if err != nil { + return err + } selectedProvider, err := provider_view.GetProviderFromPrompt(providerViewList, "Choose a Provider", false) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } if selectedProvider == nil { - return + return nil } if selectedProvider.Installed != nil && !*selectedProvider.Installed { if providersManifest == nil { - log.Fatal("Could not get providers manifest") + return errors.New("could not get providers manifest") } err = provider.InstallProvider(apiClient, *selectedProvider, providersManifest) if err != nil { - log.Fatal(err) + return err } } targets, res, err := apiClient.TargetAPI.ListTargets(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } filteredTargets := []apiclient.ProviderTarget{} @@ -109,15 +113,15 @@ var TargetSetCmd = &cobra.Command{ selectedTarget, err := target.GetTargetFromPrompt(filteredTargets, activeProfile.Name, true) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } targetManifest, res, err := apiClient.ProviderAPI.GetTargetManifest(context.Background(), selectedProvider.Name).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if selectedTarget.Name == target.NewTargetName { @@ -126,13 +130,13 @@ var TargetSetCmd = &cobra.Command{ return t.Name })) if err != nil { - log.Fatal(err) + return err } } err = target.SetTargetForm(selectedTarget, *targetManifest) if err != nil { - log.Fatal(err) + return err } selectedTarget.ProviderInfo = apiclient.ProviderProviderInfo{ @@ -142,9 +146,10 @@ var TargetSetCmd = &cobra.Command{ res, err = apiClient.TargetAPI.SetTarget(context.Background()).Target(*selectedTarget).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } views.RenderInfoMessage("Target set successfully") + return nil }, } diff --git a/pkg/cmd/telemetry/disable.go b/pkg/cmd/telemetry/disable.go index 7ec26be96e..ac13cca680 100644 --- a/pkg/cmd/telemetry/disable.go +++ b/pkg/cmd/telemetry/disable.go @@ -7,7 +7,6 @@ import ( "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/views" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -15,17 +14,18 @@ var disableCmd = &cobra.Command{ Use: "disable", Short: "Disable telemetry collection", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } err = c.DisableTelemetry() if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage("Telemetry collection disabled") + return nil }, } diff --git a/pkg/cmd/telemetry/enable.go b/pkg/cmd/telemetry/enable.go index 8ad9bd8db5..3ba24ac420 100644 --- a/pkg/cmd/telemetry/enable.go +++ b/pkg/cmd/telemetry/enable.go @@ -7,7 +7,6 @@ import ( "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/views" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -15,17 +14,18 @@ var enableCmd = &cobra.Command{ Use: "enable", Short: "Enable telemetry collection", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } err = c.EnableTelemetry() if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage("Telemetry collection enabled") + return nil }, } diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go index 43102a6f41..0145e30a5e 100644 --- a/pkg/cmd/version.go +++ b/pkg/cmd/version.go @@ -13,7 +13,8 @@ import ( var versionCmd = &cobra.Command{ Use: "version", Short: "Print the version number", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { fmt.Println("Daytona version", internal.Version) + return nil }, } diff --git a/pkg/cmd/whoami.go b/pkg/cmd/whoami.go index 4795ade349..1d8a68ab32 100644 --- a/pkg/cmd/whoami.go +++ b/pkg/cmd/whoami.go @@ -9,7 +9,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" view "github.com/daytonaio/daytona/pkg/views/whoami" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -19,24 +18,25 @@ var whoamiCmd = &cobra.Command{ Args: cobra.NoArgs, Aliases: []string{"who", "user"}, GroupID: util.PROFILE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } profile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } if format.FormatFlag != "" { formattedData := format.NewFormatter(profile) formattedData.Print() - return + return nil } view.Render(profile) + return nil }, } diff --git a/pkg/cmd/workspace/code.go b/pkg/cmd/workspace/code.go index ced6c2900c..65a7f68f64 100644 --- a/pkg/cmd/workspace/code.go +++ b/pkg/cmd/workspace/code.go @@ -32,10 +32,10 @@ var CodeCmd = &cobra.Command{ Args: cobra.RangeArgs(0, 2), Aliases: []string{"open"}, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } ctx := context.Background() @@ -46,25 +46,25 @@ var CodeCmd = &cobra.Command{ activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } ideId = c.DefaultIdeId apiClient, err := apiclient_util.GetApiClient(&activeProfile) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Verbose(true).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspace = selection.GetWorkspaceFromPrompt(workspaceList, "Open") if workspace == nil { - return + return nil } workspaceId = workspace.Id } else { @@ -72,9 +72,9 @@ var CodeCmd = &cobra.Command{ if err != nil { if strings.Contains(err.Error(), workspaces.ErrWorkspaceNotFound.Error()) { log.Debug(err) - log.Fatal("Workspace not found. You can see all workspace names by running the command `daytona list`") + return errors.New("workspace not found. You can see all workspace names by running the command `daytona list`") } - log.Fatal(err) + return err } workspaceId = workspace.Id } @@ -82,10 +82,10 @@ var CodeCmd = &cobra.Command{ if len(args) == 0 || len(args) == 1 { selectedProject, err := selectWorkspaceProject(workspaceId, &activeProfile) if err != nil { - log.Fatal(err) + return err } if selectedProject == nil { - return + return nil } projectName = selectedProject.Name } @@ -101,10 +101,10 @@ var CodeCmd = &cobra.Command{ if !workspace_util.IsProjectRunning(workspace, projectName) { wsRunningStatus, err := AutoStartWorkspace(workspace.Name, projectName) if err != nil { - log.Fatal(err) + return err } if !wsRunningStatus { - return + return nil } } @@ -112,16 +112,14 @@ var CodeCmd = &cobra.Command{ if ideId != "ssh" { providerMetadata, err = workspace_util.GetProjectProviderMetadata(workspace, projectName) if err != nil { - log.Fatal(err) + return err } } yesFlag, _ := cmd.Flags().GetBool("yes") ideList := config.GetIdeList() ide_views.RenderIdeOpeningMessage(workspace.Name, projectName, ideId, ideList) - if err := openIDE(ideId, activeProfile, workspaceId, projectName, providerMetadata, yesFlag); err != nil { - log.Fatal(err) - } + return openIDE(ideId, activeProfile, workspaceId, projectName, providerMetadata, yesFlag) }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) >= 2 { diff --git a/pkg/cmd/workspace/create.go b/pkg/cmd/workspace/create.go index 6d7a5c9919..ceaa68a08c 100644 --- a/pkg/cmd/workspace/create.go +++ b/pkg/cmd/workspace/create.go @@ -31,7 +31,6 @@ import ( "github.com/docker/docker/pkg/stringid" "tailscale.com/tsnet" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/daytonaio/daytona/cmd/daytona/config" @@ -41,7 +40,7 @@ var CreateCmd = &cobra.Command{ Use: "create [REPOSITORY_URL | PROJECT_CONFIG_NAME]...", Short: "Create a workspace", GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var projects []apiclient.CreateProjectDTO var workspaceName string @@ -50,22 +49,22 @@ var CreateCmd = &cobra.Command{ apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } profileData, res, err := apiClient.ProfileAPI.GetProfileData(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if nameFlag != "" { @@ -74,7 +73,7 @@ var CreateCmd = &cobra.Command{ workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } for _, workspaceInfo := range workspaceList { existingWorkspaceNames = append(existingWorkspaceNames, workspaceInfo.Name) @@ -84,15 +83,15 @@ var CreateCmd = &cobra.Command{ err = processPrompting(ctx, apiClient, &workspaceName, &projects, existingWorkspaceNames) if err != nil { if common.IsCtrlCAbort(err) { - return + return nil } else { - log.Fatal(err) + return err } } } else { existingProjectConfigNames, err = processCmdArguments(ctx, args, apiClient, &projects) if err != nil { - log.Fatal(err) + return err } initialSuggestion := projects[0].Name @@ -103,8 +102,7 @@ var CreateCmd = &cobra.Command{ } if workspaceName == "" || len(projects) == 0 { - log.Fatal("workspace name and repository urls are required") - return + return errors.New("workspace name and repository urls are required") } projectNames := []string{} @@ -135,24 +133,24 @@ var CreateCmd = &cobra.Command{ targetList, res, err := apiClient.TargetAPI.ListTargets(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } target, err := getTarget(targetList, activeProfile.Name) if err != nil { - log.Fatal(err) + return err } activeProfile, err = c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } var tsConn *tsnet.Server if target.Name != "local" || activeProfile.Id != "default" { tsConn, err = tailscale.GetConnection(&activeProfile) if err != nil { - log.Fatal(err) + return err } } @@ -169,12 +167,14 @@ var CreateCmd = &cobra.Command{ Projects: projects, }).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + stopLogs() + return apiclient_util.HandleErrorResponse(res, err) } err = waitForDial(createdWorkspace, &activeProfile, tsConn) if err != nil { - log.Fatal(err) + stopLogs() + return err } stopLogs() @@ -184,7 +184,7 @@ var CreateCmd = &cobra.Command{ wsInfo, res, err := apiClient.WorkspaceAPI.GetWorkspace(ctx, workspaceName).Verbose(true).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } chosenIdeId := c.DefaultIdeId @@ -206,7 +206,7 @@ var CreateCmd = &cobra.Command{ if !codeFlag { views.RenderCreationInfoMessage("Run 'daytona code' when you're ready to start developing") - return + return nil } views.RenderCreationInfoMessage(fmt.Sprintf("Opening the workspace in %s ...", chosenIde.Name)) @@ -214,14 +214,10 @@ var CreateCmd = &cobra.Command{ projectName := wsInfo.Projects[0].Name providerMetadata, err := workspace_util.GetProjectProviderMetadata(wsInfo, projectName) if err != nil { - log.Fatal(err) + return err } - err = openIDE(chosenIdeId, activeProfile, createdWorkspace.Id, wsInfo.Projects[0].Name, providerMetadata, yesFlag) - - if err != nil { - log.Fatal(err) - } + return openIDE(chosenIdeId, activeProfile, createdWorkspace.Id, wsInfo.Projects[0].Name, providerMetadata, yesFlag) }, } diff --git a/pkg/cmd/workspace/delete.go b/pkg/cmd/workspace/delete.go index a16060e30a..1ffbc5ff8b 100644 --- a/pkg/cmd/workspace/delete.go +++ b/pkg/cmd/workspace/delete.go @@ -29,13 +29,13 @@ var DeleteCmd = &cobra.Command{ Short: "Delete a workspace", GroupID: util.WORKSPACE_GROUP, Aliases: []string{"remove", "rm"}, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if allFlag { if yesFlag { fmt.Println("Deleting all workspaces.") err := DeleteAllWorkspaces(forceFlag) if err != nil { - log.Fatal(err) + return err } } else { form := huh.NewForm( @@ -49,19 +49,19 @@ var DeleteCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } if yesFlag { err := DeleteAllWorkspaces(forceFlag) if err != nil { - log.Fatal(err) + return err } } else { fmt.Println("Operation canceled.") } } - return + return nil } ctx := context.Background() @@ -70,13 +70,13 @@ var DeleteCmd = &cobra.Command{ var workspaceDeleteListNames = []string{} apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspaceDeleteList = selection.GetWorkspacesFromPrompt(workspaceList, "Delete") for _, workspace := range workspaceDeleteList { @@ -95,7 +95,7 @@ var DeleteCmd = &cobra.Command{ } if len(workspaceDeleteList) == 0 { - return + return nil } if !yesFlag { @@ -110,7 +110,7 @@ var DeleteCmd = &cobra.Command{ err := form.Run() if err != nil { - log.Fatal(err) + return err } } @@ -125,6 +125,7 @@ var DeleteCmd = &cobra.Command{ views.RenderInfoMessage(fmt.Sprintf("Workspace '%s' successfully deleted", workspace.Name)) } } + return nil }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { diff --git a/pkg/cmd/workspace/info.go b/pkg/cmd/workspace/info.go index fd5de8900e..e65e0226b2 100644 --- a/pkg/cmd/workspace/info.go +++ b/pkg/cmd/workspace/info.go @@ -12,7 +12,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views/workspace/info" "github.com/daytonaio/daytona/pkg/views/workspace/selection" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -22,12 +21,12 @@ var InfoCmd = &cobra.Command{ Aliases: []string{"view", "inspect"}, Args: cobra.RangeArgs(0, 1), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } var workspace *apiclient.WorkspaceDTO @@ -35,7 +34,7 @@ var InfoCmd = &cobra.Command{ if len(args) == 0 { workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Verbose(true).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } if format.FormatFlag != "" { @@ -50,21 +49,22 @@ var InfoCmd = &cobra.Command{ } else { workspace, err = apiclient_util.GetWorkspace(args[0], true) if err != nil { - log.Fatal(err) + return err } } if workspace == nil { - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(workspace) formattedData.Print() - return + return nil } info.Render(workspace, "", false) + return nil }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { diff --git a/pkg/cmd/workspace/list.go b/pkg/cmd/workspace/list.go index 84b1a92e21..dafdd19e39 100644 --- a/pkg/cmd/workspace/list.go +++ b/pkg/cmd/workspace/list.go @@ -13,7 +13,6 @@ import ( "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views" list_view "github.com/daytonaio/daytona/pkg/views/workspace/list" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -25,24 +24,24 @@ var ListCmd = &cobra.Command{ Args: cobra.ExactArgs(0), Aliases: []string{"ls"}, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() var specifyGitProviders bool apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Verbose(verbose).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } gitProviders, res, err := apiClient.GitProviderAPI.ListGitProviders(ctx).Execute() if err != nil { - log.Fatal(apiclient.HandleErrorResponse(res, err)) + return apiclient.HandleErrorResponse(res, err) } if len(gitProviders) > 1 { @@ -52,25 +51,27 @@ var ListCmd = &cobra.Command{ if format.FormatFlag != "" { formattedData := format.NewFormatter(workspaceList) formattedData.Print() - return + return nil } if len(workspaceList) == 0 { views.RenderInfoMessage("The workspace list is empty. Start off by running 'daytona create'.") - return + return nil } c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } list_view.ListWorkspaces(workspaceList, specifyGitProviders, verbose, activeProfile.Name) + + return nil }, } diff --git a/pkg/cmd/workspace/restart.go b/pkg/cmd/workspace/restart.go index 15f9600181..a8e667e279 100644 --- a/pkg/cmd/workspace/restart.go +++ b/pkg/cmd/workspace/restart.go @@ -12,7 +12,6 @@ import ( "github.com/daytonaio/daytona/pkg/apiclient" "github.com/daytonaio/daytona/pkg/views" "github.com/daytonaio/daytona/pkg/views/workspace/selection" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -23,33 +22,33 @@ var RestartCmd = &cobra.Command{ Short: "Restart a workspace", Args: cobra.RangeArgs(0, 1), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var workspaceId string ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { if restartProjectFlag != "" { err := cmd.Help() if err != nil { - log.Fatal(err) + return err } - return + return nil } workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspace := selection.GetWorkspaceFromPrompt(workspaceList, "Restart") if workspace == nil { - return + return nil } workspaceId = workspace.Name } else { @@ -58,13 +57,14 @@ var RestartCmd = &cobra.Command{ err = RestartWorkspace(apiClient, workspaceId, restartProjectFlag) if err != nil { - log.Fatal(err) + return err } if restartProjectFlag != "" { views.RenderInfoMessage(fmt.Sprintf("Project '%s' from workspace '%s' successfully restarted", restartProjectFlag, workspaceId)) } else { views.RenderInfoMessage(fmt.Sprintf("Workspace '%s' successfully restarted", workspaceId)) } + return nil }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) >= 1 { diff --git a/pkg/cmd/workspace/ssh-proxy.go b/pkg/cmd/workspace/ssh-proxy.go index fb2f64455e..194aa31857 100644 --- a/pkg/cmd/workspace/ssh-proxy.go +++ b/pkg/cmd/workspace/ssh-proxy.go @@ -29,10 +29,10 @@ var SshProxyCmd = &cobra.Command{ Use: "ssh-proxy [PROFILE_ID] [WORKSPACE_ID] [PROJECT]", Args: cobra.RangeArgs(2, 3), Hidden: true, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } profileId := args[0] @@ -41,7 +41,7 @@ var SshProxyCmd = &cobra.Command{ profile, err := c.GetProfile(profileId) if err != nil { - log.Fatal(err) + return err } if len(args) == 3 { @@ -49,13 +49,13 @@ var SshProxyCmd = &cobra.Command{ } else { projectName, err = apiclient.GetFirstWorkspaceProjectName(workspaceId, projectName, &profile) if err != nil { - log.Fatal(err) + return err } } workspace, err := apiclient.GetWorkspace(workspaceId, true) if err != nil { - log.Fatal(err) + return err } if workspace.Target == "local" && profile.Id == "default" { @@ -73,7 +73,7 @@ var SshProxyCmd = &cobra.Command{ cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { - log.Fatal(err) + return err } dockerClient := docker.NewDockerClient(docker.DockerClientConfig{ @@ -93,7 +93,7 @@ var SshProxyCmd = &cobra.Command{ response, err := cli.ContainerExecCreate(ctx, containerName, config) if err != nil { - log.Fatal(err) + return err } resp, err := cli.ContainerExecAttach(ctx, response.ID, container.ExecStartOptions{ @@ -101,7 +101,7 @@ var SshProxyCmd = &cobra.Command{ }) if err != nil { - log.Fatal(err) + return err } go func() { @@ -121,7 +121,7 @@ var SshProxyCmd = &cobra.Command{ for { res, err := cli.ContainerExecInspect(ctx, response.ID) if err != nil { - log.Fatal(err) + return err } if !res.Running { @@ -134,14 +134,14 @@ var SshProxyCmd = &cobra.Command{ tsConn, err := tailscale.GetConnection(&profile) if err != nil { - log.Fatal(err) + return err } errChan := make(chan error) dialConn, err := tsConn.Dial(context.Background(), "tcp", fmt.Sprintf("%s:%d", project.GetProjectHostname(workspaceId, projectName), ssh_config.SSH_PORT)) if err != nil { - log.Fatal(err) + return err } // pipe stdio to con @@ -161,8 +161,6 @@ var SshProxyCmd = &cobra.Command{ errChan <- nil }() - if err := <-errChan; err != nil { - log.Fatal(err) - } + return <-errChan }, } diff --git a/pkg/cmd/workspace/ssh.go b/pkg/cmd/workspace/ssh.go index 5890c7b95e..775b0d3b7b 100644 --- a/pkg/cmd/workspace/ssh.go +++ b/pkg/cmd/workspace/ssh.go @@ -15,8 +15,6 @@ import ( "github.com/daytonaio/daytona/pkg/views/workspace/selection" "github.com/spf13/cobra" - - log "github.com/sirupsen/logrus" ) var SshCmd = &cobra.Command{ @@ -24,15 +22,15 @@ var SshCmd = &cobra.Command{ Short: "SSH into a project using the terminal", Args: cobra.ArbitraryArgs, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } ctx := context.Background() @@ -41,33 +39,33 @@ var SshCmd = &cobra.Command{ apiClient, err := apiclient_util.GetApiClient(&activeProfile) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspace = selection.GetWorkspaceFromPrompt(workspaceList, "SSH Into") if workspace == nil { - return + return nil } } else { workspace, err = apiclient_util.GetWorkspace(args[0], true) if err != nil { - log.Fatal(err) + return err } } if len(args) == 0 || len(args) == 1 { selectedProject, err := selectWorkspaceProject(workspace.Id, &activeProfile) if err != nil { - log.Fatal(err) + return err } if selectedProject == nil { - return + return nil } projectName = selectedProject.Name } @@ -79,10 +77,10 @@ var SshCmd = &cobra.Command{ if !workspace_util.IsProjectRunning(workspace, projectName) { wsRunningStatus, err := AutoStartWorkspace(workspace.Name, projectName) if err != nil { - log.Fatal(err) + return err } if !wsRunningStatus { - return + return nil } } @@ -91,10 +89,7 @@ var SshCmd = &cobra.Command{ sshArgs = append(sshArgs, args[2:]...) } - err = ide.OpenTerminalSsh(activeProfile, workspace.Id, projectName, sshArgs...) - if err != nil { - log.Fatal(err) - } + return ide.OpenTerminalSsh(activeProfile, workspace.Id, projectName, sshArgs...) }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) >= 2 { diff --git a/pkg/cmd/workspace/start.go b/pkg/cmd/workspace/start.go index 11323eaa2e..1e3b9def22 100644 --- a/pkg/cmd/workspace/start.go +++ b/pkg/cmd/workspace/start.go @@ -36,7 +36,7 @@ var StartCmd = &cobra.Command{ Short: "Start a workspace", Args: cobra.RangeArgs(0, 1), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var workspaceIdOrName string var activeProfile config.Profile var ideId string @@ -45,36 +45,28 @@ var StartCmd = &cobra.Command{ projectProviderMetadata := "" if allFlag { - err := startAllWorkspaces() - if err != nil { - log.Fatal(err) - } - return + return startAllWorkspaces() } ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { if startProjectFlag != "" { - err := cmd.Help() - if err != nil { - log.Fatal(err) - } - return + return cmd.Help() } workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspace := selection.GetWorkspaceFromPrompt(workspaceList, "Start") if workspace == nil { - return + return nil } workspaceIdOrName = workspace.Name } else { @@ -84,20 +76,20 @@ var StartCmd = &cobra.Command{ if codeFlag { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } ideList = config.GetIdeList() activeProfile, err = c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } ideId = c.DefaultIdeId wsInfo, res, err := apiClient.WorkspaceAPI.GetWorkspace(ctx, workspaceIdOrName).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspaceId = wsInfo.Id if startProjectFlag == "" { @@ -106,14 +98,14 @@ var StartCmd = &cobra.Command{ if ideId != "ssh" { projectProviderMetadata, err = workspace_util.GetProjectProviderMetadata(wsInfo, wsInfo.Projects[0].Name) if err != nil { - log.Fatal(err) + return err } } } err = StartWorkspace(apiClient, workspaceIdOrName, startProjectFlag) if err != nil { - log.Fatal(err) + return err } if startProjectFlag == "" { @@ -125,10 +117,11 @@ var StartCmd = &cobra.Command{ ide_views.RenderIdeOpeningMessage(workspaceIdOrName, startProjectFlag, ideId, ideList) err = openIDE(ideId, activeProfile, workspaceId, startProjectFlag, projectProviderMetadata, yesFlag) if err != nil { - log.Fatal(err) + return err } } } + return nil }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { diff --git a/pkg/cmd/workspace/stop.go b/pkg/cmd/workspace/stop.go index 2caa20bcdc..cd4e8b8a5e 100644 --- a/pkg/cmd/workspace/stop.go +++ b/pkg/cmd/workspace/stop.go @@ -24,40 +24,32 @@ var StopCmd = &cobra.Command{ Short: "Stop a workspace", GroupID: util.WORKSPACE_GROUP, Args: cobra.RangeArgs(0, 1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var workspaceId string if allFlag { - err := stopAllWorkspaces() - if err != nil { - log.Fatal(err) - } - return + return stopAllWorkspaces() } ctx := context.Background() apiClient, err := apiclient_util.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } if len(args) == 0 { if stopProjectFlag != "" { - err := cmd.Help() - if err != nil { - log.Fatal(err) - } - return + return cmd.Help() } workspaceList, res, err := apiClient.WorkspaceAPI.ListWorkspaces(ctx).Execute() if err != nil { - log.Fatal(apiclient_util.HandleErrorResponse(res, err)) + return apiclient_util.HandleErrorResponse(res, err) } workspace := selection.GetWorkspaceFromPrompt(workspaceList, "Stop") if workspace == nil { - return + return nil } workspaceId = workspace.Name } else { @@ -66,13 +58,14 @@ var StopCmd = &cobra.Command{ err = StopWorkspace(apiClient, workspaceId, stopProjectFlag) if err != nil { - log.Fatal(err) + return err } if stopProjectFlag != "" { views.RenderInfoMessage(fmt.Sprintf("Project '%s' from workspace '%s' successfully stopped", stopProjectFlag, workspaceId)) } else { views.RenderInfoMessage(fmt.Sprintf("Workspace '%s' successfully stopped", workspaceId)) } + return nil }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) >= 1 { diff --git a/pkg/cmd/workspacemode/expose.go b/pkg/cmd/workspacemode/expose.go index f821829277..ef95e27242 100644 --- a/pkg/cmd/workspacemode/expose.go +++ b/pkg/cmd/workspacemode/expose.go @@ -20,17 +20,17 @@ var exposeCmd = &cobra.Command{ Short: "Expose a local port over stdout - Used by the Daytona CLI to make direct connections to the project", Args: cobra.ExactArgs(1), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { port, err := strconv.Atoi(args[0]) if err != nil { - log.Fatal(err) + return err } targetUrl := fmt.Sprintf("localhost:%d", port) dialConn, err := net.Dial("tcp", targetUrl) if err != nil { - log.Fatal(err) + return err } go func() { diff --git a/pkg/cmd/workspacemode/forward.go b/pkg/cmd/workspacemode/forward.go index 8b9e1f50a1..d7c5555e90 100644 --- a/pkg/cmd/workspacemode/forward.go +++ b/pkg/cmd/workspacemode/forward.go @@ -23,26 +23,26 @@ var portForwardCmd = &cobra.Command{ Short: "Forward a port from the project to your local machine", Args: cobra.ExactArgs(1), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { c, err := config.GetConfig() if err != nil { - log.Fatal(err) + return err } activeProfile, err := c.GetActiveProfile() if err != nil { - log.Fatal(err) + return err } port, err := strconv.Atoi(args[0]) if err != nil { - log.Fatal(err) + return err } hostPort, errChan := tailscale.ForwardPort(workspaceId, projectName, uint16(port), activeProfile) if hostPort == nil { if err = <-errChan; err != nil { - log.Fatal(err) + return err } } else { if *hostPort != uint16(port) { diff --git a/pkg/cmd/workspacemode/git_cred.go b/pkg/cmd/workspacemode/git_cred.go index 2a8a7f7b31..1c37d3bbc5 100644 --- a/pkg/cmd/workspacemode/git_cred.go +++ b/pkg/cmd/workspacemode/git_cred.go @@ -7,7 +7,6 @@ import ( "bufio" "context" "fmt" - "log" "net/url" "os" "strings" @@ -21,21 +20,21 @@ var gitCredCmd = &cobra.Command{ Aliases: []string{"rev"}, Args: cobra.ExactArgs(1), Hidden: true, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if args[0] != "get" { - return + return nil } ctx := context.Background() result, err := parseFromStdin() host := result["host"] if err != nil || host == "" { fmt.Println("error parsing 'host' from stdin") - return + return nil } apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } encodedUrl := url.QueryEscape(host) @@ -43,11 +42,11 @@ var gitCredCmd = &cobra.Command{ if gitProvider == nil { fmt.Println("error: git provider not found") os.Exit(1) - return } fmt.Println("username=" + gitProvider.Username) fmt.Println("password=" + gitProvider.Token) + return nil }, } diff --git a/pkg/cmd/workspacemode/info.go b/pkg/cmd/workspacemode/info.go index 808f6a0b6c..10137d2a50 100644 --- a/pkg/cmd/workspacemode/info.go +++ b/pkg/cmd/workspacemode/info.go @@ -9,7 +9,6 @@ import ( "github.com/daytonaio/daytona/pkg/apiclient" "github.com/daytonaio/daytona/pkg/cmd/format" "github.com/daytonaio/daytona/pkg/views/workspace/info" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -19,25 +18,26 @@ var infoCmd = &cobra.Command{ Aliases: []string{"view", "inspect"}, Args: cobra.ExactArgs(0), GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var workspace *apiclient.WorkspaceDTO workspace, err := apiclient_util.GetWorkspace(workspaceId, true) if err != nil { - log.Fatal(err) + return err } if workspace == nil { - return + return nil } if format.FormatFlag != "" { formattedData := format.NewFormatter(workspace) formattedData.Print() - return + return nil } info.Render(workspace, "", false) + return nil }, } diff --git a/pkg/cmd/workspacemode/restart.go b/pkg/cmd/workspacemode/restart.go index 43f5f5dd4c..466c6d47b4 100644 --- a/pkg/cmd/workspacemode/restart.go +++ b/pkg/cmd/workspacemode/restart.go @@ -10,7 +10,6 @@ import ( "github.com/daytonaio/daytona/internal/util/apiclient" workspace_cmd "github.com/daytonaio/daytona/pkg/cmd/workspace" "github.com/daytonaio/daytona/pkg/views" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -19,15 +18,15 @@ var restartCmd = &cobra.Command{ Short: "Restart the project", Args: cobra.NoArgs, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } err = workspace_cmd.RestartWorkspace(apiClient, workspaceId, projectName) if err != nil { - log.Fatal(err) + return err } if projectName != "" { @@ -35,5 +34,6 @@ var restartCmd = &cobra.Command{ } else { views.RenderInfoMessage(fmt.Sprintf("Workspace '%s' successfully restarted", workspaceId)) } + return nil }, } diff --git a/pkg/cmd/workspacemode/start.go b/pkg/cmd/workspacemode/start.go index 2e7fff88d3..2473068e82 100644 --- a/pkg/cmd/workspacemode/start.go +++ b/pkg/cmd/workspacemode/start.go @@ -8,7 +8,6 @@ import ( "github.com/daytonaio/daytona/internal/util/apiclient" workspace_cmd "github.com/daytonaio/daytona/pkg/cmd/workspace" "github.com/daytonaio/daytona/pkg/views" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -17,17 +16,18 @@ var startCmd = &cobra.Command{ Short: "Start the project", Args: cobra.NoArgs, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } err = workspace_cmd.StartWorkspace(apiClient, workspaceId, projectName) if err != nil { - log.Fatal(err) + return err } views.RenderInfoMessage("Project successfully started") + return nil }, } diff --git a/pkg/cmd/workspacemode/stop.go b/pkg/cmd/workspacemode/stop.go index c31d985373..f11e885ece 100644 --- a/pkg/cmd/workspacemode/stop.go +++ b/pkg/cmd/workspacemode/stop.go @@ -10,7 +10,6 @@ import ( "github.com/daytonaio/daytona/internal/util/apiclient" workspace_cmd "github.com/daytonaio/daytona/pkg/cmd/workspace" "github.com/daytonaio/daytona/pkg/views" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -19,15 +18,15 @@ var stopCmd = &cobra.Command{ Short: "Stop the project", Args: cobra.NoArgs, GroupID: util.WORKSPACE_GROUP, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { apiClient, err := apiclient.GetApiClient(nil) if err != nil { - log.Fatal(err) + return err } err = workspace_cmd.StopWorkspace(apiClient, workspaceId, projectName) if err != nil { - log.Fatal(err) + return err } if projectName != "" { @@ -35,5 +34,6 @@ var stopCmd = &cobra.Command{ } else { views.RenderInfoMessage(fmt.Sprintf("Workspace '%s' successfully stopped", workspaceId)) } + return nil }, } diff --git a/pkg/cmd/workspacemode/workspace_mode.go b/pkg/cmd/workspacemode/workspace_mode.go index b0e53e9c1b..ae39ed0a95 100644 --- a/pkg/cmd/workspacemode/workspace_mode.go +++ b/pkg/cmd/workspacemode/workspace_mode.go @@ -4,11 +4,17 @@ package workspacemode import ( + "fmt" "os" + "time" + "github.com/daytonaio/daytona/cmd/daytona/config" + "github.com/daytonaio/daytona/internal" "github.com/daytonaio/daytona/internal/util" cmd "github.com/daytonaio/daytona/pkg/cmd" . "github.com/daytonaio/daytona/pkg/cmd/agent" + "github.com/daytonaio/daytona/pkg/posthogservice" + "github.com/daytonaio/daytona/pkg/telemetry" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -22,6 +28,8 @@ var workspaceModeRootCmd = &cobra.Command{ Short: "Use the Daytona CLI to manage your workspace", Long: "Use the Daytona CLI to manage your workspace", DisableAutoGenTag: true, + SilenceUsage: true, + SilenceErrors: true, Run: func(cmd *cobra.Command, args []string) { err := cmd.Help() if err != nil { @@ -42,7 +50,66 @@ func Execute() { workspaceModeRootCmd.AddCommand(portForwardCmd) workspaceModeRootCmd.AddCommand(exposeCmd) - if err := workspaceModeRootCmd.Execute(); err != nil { + var telemetryService telemetry.TelemetryService + clientId := config.GetClientId() + telemetryEnabled := config.TelemetryEnabled() + + if telemetryEnabled { + telemetryService = posthogservice.NewTelemetryService(posthogservice.PosthogServiceConfig{ + ApiKey: internal.PosthogApiKey, + Endpoint: internal.PosthogEndpoint, + }) + } + + command, err := cmd.ValidateCommands(workspaceModeRootCmd, os.Args[1:]) + if err != nil { + fmt.Printf("Error: %v\n\n", err) + helpErr := command.Help() + if telemetryEnabled { + props := cmd.GetCmdTelemetryData(command) + props["command"] = os.Args[1] + props["called_as"] = os.Args[1] + err := telemetryService.TrackCliEvent(telemetry.CliEventInvalidCmd, clientId, props) + if err != nil { + log.Error(err) + } + telemetryService.Close() + } + + if helpErr != nil { + log.Fatal(err) + } + return + } + + if telemetryEnabled { + err := telemetryService.TrackCliEvent(telemetry.CliEventCmdStart, clientId, cmd.GetCmdTelemetryData(command)) + if err != nil { + log.Error(err) + } + } + + startTime := time.Now() + + err = workspaceModeRootCmd.Execute() + + endTime := time.Now() + if telemetryService != nil { + execTime := endTime.Sub(startTime) + props := cmd.GetCmdTelemetryData(command) + props["exec time (µs)"] = execTime.Microseconds() + if err != nil { + props["error"] = err.Error() + } + + err := telemetryService.TrackCliEvent(telemetry.CliEventCmdEnd, clientId, props) + if err != nil { + log.Error(err) + } + telemetryService.Close() + } + + if err != nil { log.Fatal(err) } } diff --git a/pkg/server/server.go b/pkg/server/server.go index 72d6c5c1be..1916109eef 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -173,9 +173,7 @@ func (s *Server) Start(errCh chan error) error { signal.Notify(interruptChannel, os.Interrupt) for range interruptChannel { - log.Info("Shutting down") plugin.CleanupClients() - os.Exit(0) } }() diff --git a/pkg/telemetry/cli_events.go b/pkg/telemetry/cli_events.go index ad75d2bffd..175e9b9225 100644 --- a/pkg/telemetry/cli_events.go +++ b/pkg/telemetry/cli_events.go @@ -6,8 +6,9 @@ package telemetry type CliEvent string const ( - CliEventCmdStart CliEvent = "cli_cmd_start" - CliEventCmdEnd CliEvent = "cli_cmd_end" + CliEventCmdStart CliEvent = "cli_cmd_start" + CliEventCmdEnd CliEvent = "cli_cmd_end" + CliEventInvalidCmd CliEvent = "cli_invalid_cmd" ) var AdditionalData map[string]interface{} = map[string]interface{}{}