diff --git a/cmd/container/main.go b/cmd/container/main.go index 78f276b6..b660fd11 100644 --- a/cmd/container/main.go +++ b/cmd/container/main.go @@ -5,11 +5,10 @@ import ( "os" "path/filepath" - "github.com/spf13/cobra" - "github.com/controlplaneio/simulator/v2/core/tools" "github.com/controlplaneio/simulator/v2/internal/cli" "github.com/controlplaneio/simulator/v2/internal/config" + "github.com/controlplaneio/simulator/v2/internal/logging" ) func main() { @@ -75,6 +74,7 @@ func main() { ), ) - err := simulator.Execute() - cobra.CheckErr(err) + if err := simulator.Execute(); err != nil { + logging.LogFatal("Simulator CLI returned an error", err) + } } diff --git a/cmd/simulator/main.go b/cmd/simulator/main.go index 0cc9fb53..7e487a6a 100644 --- a/cmd/simulator/main.go +++ b/cmd/simulator/main.go @@ -6,13 +6,12 @@ import ( "os" "path/filepath" - "github.com/spf13/cobra" - "github.com/controlplaneio/simulator/v2/core/aws" "github.com/controlplaneio/simulator/v2/core/tools" "github.com/controlplaneio/simulator/v2/internal/cli" "github.com/controlplaneio/simulator/v2/internal/config" "github.com/controlplaneio/simulator/v2/internal/docker" + "github.com/controlplaneio/simulator/v2/internal/logging" ) const ( @@ -167,8 +166,9 @@ func main() { }), ) - err = simulator.Execute() - cobra.CheckErr(err) + if err := simulator.Execute(); err != nil { + logging.LogFatal("Simulator CLI returned an error", err) + } } func mkDirsIfNotExist(dirs ...string) { diff --git a/internal/cli/ami.go b/internal/cli/ami.go index 3c63e0d5..15a68412 100644 --- a/internal/cli/ami.go +++ b/internal/cli/ami.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "os" "os/signal" "syscall" @@ -32,11 +33,13 @@ func WithAMIListCmd(manager aws.AMIManager) SimulatorCmdOptions { amiListCmd := &cobra.Command{ Use: "list", Short: "List simulator AMIs", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, _ []string) error { ctx := context.Background() amis, err := manager.List(ctx) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to list simulator AMI: %w", err) + } table := tablewriter.NewWriter(os.Stdout) @@ -64,6 +67,7 @@ func WithAMIListCmd(manager aws.AMIManager) SimulatorCmdOptions { table.SetRowLine(true) } table.Render() + return nil }, } @@ -77,12 +81,15 @@ func WithAMIDeleteCmd(manager aws.AMIManager) SimulatorCmdOptions { Use: "delete [ami id]", Short: "Delete a simulator AMI", Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { ctx := context.Background() id := args[0] err := manager.Delete(ctx, id) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to delete simulator AMI: %w", err) + } + return nil }, } @@ -98,20 +105,16 @@ func WithAmiBuildCmd(builder tools.AMIBuilder) SimulatorCmdOptions { Use: "build [name]", Short: "Build the packer image", Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() - var err error id := args[0] - - // go func() { - err = builder.Build(ctx, id) - // }() - // - // <-ctx.Done() //TODO: Check out quitting - stop() - - cobra.CheckErr(err) + err := builder.Build(ctx, id) + if err != nil { + return fmt.Errorf("unable to build packer image: %w", err) + } + return nil }, } diff --git a/internal/cli/bucket.go b/internal/cli/bucket.go index f6abf62f..768444bf 100644 --- a/internal/cli/bucket.go +++ b/internal/cli/bucket.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "log/slog" "os" @@ -29,7 +30,7 @@ func WithBucketCmd(opts ...SimulatorCmdOptions) SimulatorCmdOptions { func WithCreateBucketCmd(config config.Config, manager aws.BucketManager) SimulatorCmdOptions { bucketCreateCommand := &cobra.Command{ Use: "create", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, _ []string) error { ctx := context.Background() if config.Bucket == "" { @@ -38,7 +39,10 @@ func WithCreateBucketCmd(config config.Config, manager aws.BucketManager) Simula } err := manager.Create(ctx, config.Bucket) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to create bucket: %w", err) + } + return nil }, } @@ -50,11 +54,14 @@ func WithCreateBucketCmd(config config.Config, manager aws.BucketManager) Simula func WithDeleteBucketCmd(config config.Config, manager aws.BucketManager) SimulatorCmdOptions { bucketCreateCommand := &cobra.Command{ Use: "delete", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, _ []string) error { ctx := context.Background() err := manager.Delete(ctx, config.Bucket) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to delete bucket: %w", err) + } + return nil }, } diff --git a/internal/cli/config.go b/internal/cli/config.go index 09f07978..176222e2 100644 --- a/internal/cli/config.go +++ b/internal/cli/config.go @@ -24,13 +24,16 @@ func WithConfigCmd(conf config.Config) SimulatorCmdOptions { configCmd.PersistentFlags().BoolVar(&dev, "dev", false, "developer mode") configCmd.PersistentFlags().BoolVar(&rootless, "rootless", false, "docker running in rootless mode") - configCmd.Run = func(_ *cobra.Command, _ []string) { + configCmd.RunE = func(_ *cobra.Command, _ []string) error { if printDir { dir, err := config.SimulatorDir() - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to get simulator config directory: %w", err) + } + //nolint: forbidigo fmt.Println(dir) - return + return nil } if name != "" { @@ -46,7 +49,9 @@ func WithConfigCmd(conf config.Config) SimulatorCmdOptions { conf.Container.Image = "controlplane/simulator:dev" baseDir, err := os.Getwd() - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to current working directory: %w", err) + } conf.BaseDir = baseDir } else { @@ -58,7 +63,10 @@ func WithConfigCmd(conf config.Config) SimulatorCmdOptions { conf.Container.Rootless = rootless err := conf.Write() - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to write simulator config to disk: %w", err) + } + return nil } return func(command *cobra.Command) { diff --git a/internal/cli/container.go b/internal/cli/container.go index 92baa97e..71afd256 100644 --- a/internal/cli/container.go +++ b/internal/cli/container.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "github.com/spf13/cobra" @@ -28,10 +29,13 @@ func WithContainerPullCmd(config config.Config, client *docker.Client) Simulator imagePullCmd := &cobra.Command{ Use: "pull", Short: "Pull the Simulator Container Image", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, _ []string) error { ctx := context.Background() err := client.PullImage(ctx, config.Container.Image) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to pull simulator container image: %w", err) + } + return nil }, } diff --git a/internal/cli/infra.go b/internal/cli/infra.go index f496a4bc..455f3292 100644 --- a/internal/cli/infra.go +++ b/internal/cli/infra.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "os" "os/signal" "syscall" @@ -30,13 +31,20 @@ func WithInfraCreateCmd(manager tools.InfraManager, opts ...SimulatorCmdOptions) infraCreateCmd := &cobra.Command{ Use: "create", Short: "Create simulator infrastructure", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() - stateBucket, stateKey, name := getTerraformFlags(cmd) - err := manager.Create(ctx, stateBucket, stateKey, name) - cobra.CheckErr(err) + stateBucket, stateKey, name, err := getTerraformFlags(cmd) + if err != nil { + return fmt.Errorf("unable to get terraform flags: %w", err) + } + + err = manager.Create(ctx, stateBucket, stateKey, name) + if err != nil { + return fmt.Errorf("creating simulator infrastructure failed: %w", err) + } + return nil }, } @@ -53,13 +61,20 @@ func WithInfraDestroyCmd(manager tools.InfraManager, opts ...SimulatorCmdOptions infraDestroyCmd := &cobra.Command{ Use: "destroy", Short: "Destroy simulator infrastructure", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() - stateBucket, stateKey, name := getTerraformFlags(cmd) - err := manager.Destroy(ctx, stateBucket, stateKey, name) - cobra.CheckErr(err) + stateBucket, stateKey, name, err := getTerraformFlags(cmd) + if err != nil { + return fmt.Errorf("unable to get terraform flags: %w", err) + } + + err = manager.Destroy(ctx, stateBucket, stateKey, name) + if err != nil { + return fmt.Errorf("unable to destroy simulator infrastructure: %w", err) + } + return nil }, } @@ -72,16 +87,26 @@ func WithInfraDestroyCmd(manager tools.InfraManager, opts ...SimulatorCmdOptions } } -func getTerraformFlags(cmd *cobra.Command) (string, string, string) { - stateBucket, err := cmd.Flags().GetString("stateBucket") - cobra.CheckErr(err) +func getTerraformFlags(cmd *cobra.Command) (string, string, string, error) { + var err error + var stateBucket, stateKey, name string + + stateBucket, err = cmd.Flags().GetString("stateBucket") + if err != nil { + return stateBucket, stateKey, name, fmt.Errorf("unable to get stateBucket flag: %w", err) + } - stateKey, err := cmd.Flags().GetString("stateKey") - cobra.CheckErr(err) + stateKey, err = cmd.Flags().GetString("stateKey") + if err != nil { + return stateBucket, stateKey, name, fmt.Errorf("unable to get stateKey flag: %w", err) + } + + name, err = cmd.Flags().GetString("name") + if err != nil { + return stateBucket, stateKey, name, fmt.Errorf("unable to get name flag: %w", err) + } - name, err := cmd.Flags().GetString("name") - cobra.CheckErr(err) - return stateBucket, stateKey, name + return stateBucket, stateKey, name, nil } func WithFlag(name, value, usage string) SimulatorCmdOptions { diff --git a/internal/cli/scenario.go b/internal/cli/scenario.go index 17909c23..c3ffcb44 100644 --- a/internal/cli/scenario.go +++ b/internal/cli/scenario.go @@ -2,6 +2,7 @@ package cli import ( "context" + "fmt" "os" "os/signal" @@ -31,11 +32,14 @@ func WithScenarioListCmd() SimulatorCmdOptions { scenarioListCmd := &cobra.Command{ Use: "list", Short: "List available scenarios", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, _ []string) error { list, err := scenarios.List() - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to list available scenarios: %w", err) + } tabulateScenarios(list) + return nil }, } @@ -49,13 +53,16 @@ func WithScenarioDescribeCmd() SimulatorCmdOptions { Use: "describe [id]", Short: "Describes a scenario", Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { scenarioID := args[0] s, err := scenarios.Find(scenarioID) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to describe scenario: %w", err) + } tabulateScenarios([]scenarios.Scenario{s}) + return nil }, } @@ -69,13 +76,16 @@ func WithScenarioInstallCmd(manager tools.ScenarioManager) SimulatorCmdOptions { Use: "install [id]", Short: "Install the scenario into the simulator infrastructure", Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() scenarioID := args[0] err := manager.Install(ctx, scenarioID) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to install the scenario: %w", err) + } + return nil }, } @@ -89,13 +99,16 @@ func WithScenarioUninstallCmd(manager tools.ScenarioManager) SimulatorCmdOptions Use: "uninstall [id]", Short: "Uninstall the scenario from the simulator infrastructure", Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() scenarioID := args[0] err := manager.Uninstall(ctx, scenarioID) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to uninstall the scenario: %w", err) + } + return nil }, } diff --git a/internal/cli/simulator.go b/internal/cli/simulator.go index 32d64a55..a223c6b9 100644 --- a/internal/cli/simulator.go +++ b/internal/cli/simulator.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "os" "github.com/controlplaneio/simulator/v2/internal/logging" @@ -22,12 +23,18 @@ func NewSimulatorCmd(opts ...SimulatorCmdOptions) *cobra.Command { simulator.PersistentFlags().String("log-level", logLevel(), "Log level (error, warn, info, debug)") - simulator.PersistentPreRun = func(cmd *cobra.Command, _ []string) { - logLevel, err := cmd.Flags().GetString("log-level") - cobra.CheckErr(err) + simulator.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error { + logLevel, err := cmd.Flags().GetString("log-level222") + if err != nil { + return fmt.Errorf("unable to get log-level flag: %w", err) + } err = logging.Configure(logLevel) - cobra.CheckErr(err) + if err != nil { + return fmt.Errorf("unable to configure logging: %w", err) + } + + return nil } for _, opt := range opts { diff --git a/internal/logging/factory.go b/internal/logging/factory.go index 2f544c74..1be9b821 100644 --- a/internal/logging/factory.go +++ b/internal/logging/factory.go @@ -32,3 +32,8 @@ func Configure(level string) error { return nil } + +func LogFatal(msg string, err error) { + slog.Error(msg, "error", err) + os.Exit(1) +}