From 0de2974e7ecc8ae1060ddbcb32a867311ff03d75 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:46:13 -0300 Subject: [PATCH 01/33] chore: only run CLA workflow on opened PRs --- .github/workflows/cla.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 56403861c..2809df04c 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -3,7 +3,7 @@ on: issue_comment: types: [created] pull_request_target: - types: [opened,closed,synchronize] + types: [opened, synchronize] jobs: CLAssistant: From e80dbfff7e98cf0be8544489e656bd8679e80788 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:38:20 -0300 Subject: [PATCH 02/33] chore: add reset command unit tests --- pkg/cmd/reset/reset.go | 89 +++++++++++++++++--------- pkg/cmd/reset/reset_test.go | 122 ++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 31 deletions(-) create mode 100644 pkg/cmd/reset/reset_test.go diff --git a/pkg/cmd/reset/reset.go b/pkg/cmd/reset/reset.go index 748fce7e2..5d05fce07 100644 --- a/pkg/cmd/reset/reset.go +++ b/pkg/cmd/reset/reset.go @@ -8,49 +8,76 @@ import ( msg "github.com/aziontech/azion-cli/messages/reset" api "github.com/aziontech/azion-cli/pkg/api/personal_token" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/pkg/token" "github.com/spf13/cobra" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - cmd := &cobra.Command{ +type ResetCmd struct { + Io *iostreams.IOStreams + ReadSettings func() (token.Settings, error) + WriteSettings func(token.Settings) error + DeleteToken func(context.Context, string) error +} + +func NewResetCmd(f *cmdutil.Factory) *ResetCmd { + return &ResetCmd{ + Io: f.IOStreams, + ReadSettings: token.ReadSettings, + WriteSettings: token.WriteSettings, + DeleteToken: func(ctx context.Context, uuid string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, uuid) + }, + } +} + +func NewCobraCmd(reset *ResetCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.USAGE, Short: msg.SHORTDESCRIPTION, Long: msg.LONGDESCRIPTION, Example: heredoc.Doc(` $ azion reset --help - `), + `), RunE: func(cmd *cobra.Command, args []string) error { - settings, err := token.ReadSettings() - if err != nil { - return err - } - - if settings.UUID != "" { - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) - err = client.Delete(context.Background(), settings.UUID) - if err != nil { - return fmt.Errorf(msg.ERRORLOGOUT, err.Error()) - } - } - - settings = token.Settings{} - err = token.WriteSettings(settings) - if err != nil { - return err - } - - resetOut := output.GeneralOutput{ - Msg: msg.SUCCESS, - Out: f.IOStreams.Out, - } - - return output.Print(&resetOut) + return reset.run() }, } - flags := cmd.Flags() - flags.BoolP("help", "h", false, msg.FLAGHELP) - return cmd + cobraCmd.Flags().BoolP("help", "h", false, msg.FLAGHELP) + + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewResetCmd(f), f) +} + +func (cmd *ResetCmd) run() error { + settings, err := cmd.ReadSettings() + if err != nil { + return err + } + + if settings.UUID != "" { + err = cmd.DeleteToken(context.Background(), settings.UUID) + if err != nil { + return fmt.Errorf(msg.ERRORLOGOUT, err.Error()) + } + } + + settings = token.Settings{} + err = cmd.WriteSettings(settings) + if err != nil { + return err + } + + resetOut := output.GeneralOutput{ + Msg: msg.SUCCESS, + Out: cmd.Io.Out, + } + + return output.Print(&resetOut) } diff --git a/pkg/cmd/reset/reset_test.go b/pkg/cmd/reset/reset_test.go new file mode 100644 index 000000000..de3c1536c --- /dev/null +++ b/pkg/cmd/reset/reset_test.go @@ -0,0 +1,122 @@ +package reset + +import ( + "context" + "errors" + "fmt" + "testing" + + msg "github.com/aziontech/azion-cli/messages/reset" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/pkg/token" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestReset(t *testing.T) { + logger.New(zapcore.DebugLevel) + + tests := []struct { + name string + tokenSettings token.Settings + mockReadError error + mockDeleteError error + mockWriteError error + expectedOutput string + expectedError error + }{ + { + name: "reset - successful reset", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: msg.SUCCESS, + expectedError: nil, + }, + { + name: "reset - no UUID", + tokenSettings: token.Settings{ + UUID: "", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: msg.SUCCESS, + expectedError: nil, + }, + { + name: "reset - failed to read settings", + tokenSettings: token.Settings{}, + mockReadError: errors.New("failed to get token dir"), + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: "", + expectedError: errors.New("failed to get token dir"), + }, + { + name: "reset - failed to delete token", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: errors.New("failed to delete token"), + mockWriteError: nil, + expectedOutput: "", + expectedError: fmt.Errorf(msg.ERRORLOGOUT, "failed to delete token"), + }, + { + name: "reset - failed to write settings", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: errors.New("Failed to write settings.toml file"), + expectedOutput: "", + expectedError: errors.New("Failed to write settings.toml file"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockReadSettings := func() (token.Settings, error) { + return tt.tokenSettings, tt.mockReadError + } + + mockWriteSettings := func(settings token.Settings) error { + return tt.mockWriteError + } + + mockDeleteToken := func(ctx context.Context, uuid string) error { + return tt.mockDeleteError + } + + mock := &httpmock.Registry{} + + f, out, _ := testutils.NewFactory(mock) + + resetCmd := &ResetCmd{ + Io: f.IOStreams, + ReadSettings: mockReadSettings, + WriteSettings: mockWriteSettings, + DeleteToken: mockDeleteToken, + } + cmd := NewCobraCmd(resetCmd, f) + + _, err := cmd.ExecuteC() + if tt.expectedError != nil { + require.Error(t, err) + assert.Equal(t, tt.expectedError.Error(), err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, out.String()) + } + }) + } +} From 23b9e2c6297f64dfa9b505906380c3a55fc7b4d3 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:30:49 -0300 Subject: [PATCH 03/33] tests: add unit tests for logout command --- pkg/cmd/logout/logout.go | 91 ++++++++++++++++--------- pkg/cmd/logout/logout_test.go | 122 ++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 32 deletions(-) create mode 100644 pkg/cmd/logout/logout_test.go diff --git a/pkg/cmd/logout/logout.go b/pkg/cmd/logout/logout.go index dc38342eb..3f1a0ec64 100644 --- a/pkg/cmd/logout/logout.go +++ b/pkg/cmd/logout/logout.go @@ -8,50 +8,77 @@ import ( msg "github.com/aziontech/azion-cli/messages/logout" api "github.com/aziontech/azion-cli/pkg/api/personal_token" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/pkg/token" "github.com/spf13/cobra" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - cmd := &cobra.Command{ +type LogoutCmd struct { + Io *iostreams.IOStreams + ReadSettings func() (token.Settings, error) + WriteSettings func(token.Settings) error + DeleteToken func(context.Context, string) error +} + +func NewLogoutCmd(f *cmdutil.Factory) *LogoutCmd { + return &LogoutCmd{ + Io: f.IOStreams, + ReadSettings: token.ReadSettings, + WriteSettings: token.WriteSettings, + DeleteToken: func(ctx context.Context, uuid string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, uuid) + }, + } +} + +func NewCobraCmd(logout *LogoutCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.USAGE, Short: msg.SHORTDESCRIPTION, Long: msg.LONGDESCRIPTION, Example: heredoc.Doc(` $ azion logout --help - `), + `), RunE: func(cmd *cobra.Command, args []string) error { - settings, err := token.ReadSettings() - if err != nil { - return err - } - - if settings.UUID != "" { - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) - err = client.Delete(context.Background(), settings.UUID) - if err != nil { - return fmt.Errorf(msg.ErrorLogout, err.Error()) - } - } - - settings.UUID = "" - settings.Token = "" - err = token.WriteSettings(settings) - if err != nil { - return err - } - - logoutOut := output.GeneralOutput{ - Msg: msg.SUCCESS, - Out: f.IOStreams.Out, - } - - return output.Print(&logoutOut) + return logout.run() }, } - flags := cmd.Flags() - flags.BoolP("help", "h", false, msg.FLAGHELP) - return cmd + cobraCmd.Flags().BoolP("help", "h", false, msg.FLAGHELP) + + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewLogoutCmd(f), f) +} + +func (cmd *LogoutCmd) run() error { + settings, err := cmd.ReadSettings() + if err != nil { + return err + } + + if settings.UUID != "" { + err = cmd.DeleteToken(context.Background(), settings.UUID) + if err != nil { + return fmt.Errorf(msg.ErrorLogout, err.Error()) + } + } + + settings.UUID = "" + settings.Token = "" + err = cmd.WriteSettings(settings) + if err != nil { + return err + } + + logoutOut := output.GeneralOutput{ + Msg: msg.SUCCESS, + Out: cmd.Io.Out, + } + + return output.Print(&logoutOut) } diff --git a/pkg/cmd/logout/logout_test.go b/pkg/cmd/logout/logout_test.go new file mode 100644 index 000000000..82c2c15d0 --- /dev/null +++ b/pkg/cmd/logout/logout_test.go @@ -0,0 +1,122 @@ +package logout + +import ( + "context" + "errors" + "fmt" + "testing" + + msg "github.com/aziontech/azion-cli/messages/logout" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/pkg/token" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestLogout(t *testing.T) { + logger.New(zapcore.DebugLevel) + + tests := []struct { + name string + tokenSettings token.Settings + mockReadError error + mockDeleteError error + mockWriteError error + expectedOutput string + expectedError error + }{ + { + name: "logout - successful logout", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: msg.SUCCESS, + expectedError: nil, + }, + { + name: "logout - no UUID", + tokenSettings: token.Settings{ + UUID: "", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: msg.SUCCESS, + expectedError: nil, + }, + { + name: "logout - failed to read settings", + tokenSettings: token.Settings{}, + mockReadError: errors.New("failed to get token dir"), + mockDeleteError: nil, + mockWriteError: nil, + expectedOutput: "", + expectedError: errors.New("failed to get token dir"), + }, + { + name: "logout - failed to delete token", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: errors.New("failed to delete token"), + mockWriteError: nil, + expectedOutput: "", + expectedError: fmt.Errorf(msg.ErrorLogout, "failed to delete token"), + }, + { + name: "logout - failed to write settings", + tokenSettings: token.Settings{ + UUID: "1234-5678", + }, + mockReadError: nil, + mockDeleteError: nil, + mockWriteError: errors.New("Failed to write settings.toml file"), + expectedOutput: "", + expectedError: errors.New("Failed to write settings.toml file"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockReadSettings := func() (token.Settings, error) { + return tt.tokenSettings, tt.mockReadError + } + + mockWriteSettings := func(settings token.Settings) error { + return tt.mockWriteError + } + + mockDeleteToken := func(ctx context.Context, uuid string) error { + return tt.mockDeleteError + } + + mock := &httpmock.Registry{} + + f, out, _ := testutils.NewFactory(mock) + + logoutCmd := &LogoutCmd{ + Io: f.IOStreams, + ReadSettings: mockReadSettings, + WriteSettings: mockWriteSettings, + DeleteToken: mockDeleteToken, + } + cmd := NewCobraCmd(logoutCmd, f) + + _, err := cmd.ExecuteC() + if tt.expectedError != nil { + require.Error(t, err) + assert.Equal(t, tt.expectedError.Error(), err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, out.String()) + } + }) + } +} From 954ed06415bf93ed53cf712fc19ffa188e231b0d Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 2 Jul 2024 14:10:52 -0300 Subject: [PATCH 04/33] feat: output init --- messages/init/messages.go | 1 + pkg/cmd/init/init.go | 42 +++++++++++++++++++++++++++------------ pkg/cmd/init/utils.go | 4 ++-- pkg/cmd/root/root.go | 11 ++++++---- pkg/cmdutil/file.go | 5 ++++- pkg/output/format.go | 4 +++- pkg/output/general.go | 6 +++--- pkg/output/slice.go | 20 +++++++++++++++++++ utils/helpers.go | 3 +-- 9 files changed, 70 insertions(+), 26 deletions(-) create mode 100644 pkg/output/slice.go diff --git a/messages/init/messages.go b/messages/init/messages.go index 2cd680fb1..3a64979e2 100644 --- a/messages/init/messages.go +++ b/messages/init/messages.go @@ -9,6 +9,7 @@ const ( FLAG_PRESET = "The Preset's name" FLAG_TEMPLATE = "The Template's name" FLAG_PACKAGE_MANAGE = "Specify the package manager to use (e.g., npm, yarn, pnpm)" + FLAG_AUTO = "If sent, the entire flow of the command will be run without interruptions" ) var ( diff --git a/pkg/cmd/init/init.go b/pkg/cmd/init/init.go index 497b72cd3..66988f139 100644 --- a/pkg/cmd/init/init.go +++ b/pkg/cmd/init/init.go @@ -15,6 +15,7 @@ import ( "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/node" + "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" thoth "github.com/aziontech/go-thoth" "github.com/go-git/go-git/v5" @@ -26,6 +27,7 @@ type initCmd struct { name string preset string template string + auto bool mode string packageManager string pathWorkingDir string @@ -104,12 +106,14 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { cmd.Flags().StringVar(&init.packageManager, "package-manager", "", msg.FLAG_PACKAGE_MANAGE) cmd.Flags().StringVar(&init.preset, "preset", "", msg.FLAG_PRESET) cmd.Flags().StringVar(&init.template, "template", "", msg.FLAG_TEMPLATE) + cmd.Flags().BoolVar(&init.auto, "auto", false, msg.FLAG_AUTO) return cmd } func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { logger.Debug("Running init command") + msgs := []string{} err := node.NodeVersion() if err != nil { return err @@ -147,7 +151,8 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { if err = cmd.createTemplateAzion(); err != nil { return err } - logger.FInfo(cmd.io.Out, msg.WebAppInitCmdSuccess) + logger.FInfoFlags(cmd.io.Out, msg.WebAppInitCmdSuccess, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.WebAppInitCmdSuccess) err = cmd.changeDir(cmd.pathWorkingDir) if err != nil { @@ -159,19 +164,21 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { if err != nil { return msg.ErrorReadingGitignore } - - if !gitignore && (cmd.f.GlobalFlagAll || utils.Confirm(cmd.f.GlobalFlagAll, msg.AskGitignore, true)) { + if !gitignore && (cmd.auto || cmd.f.GlobalFlagAll || utils.Confirm(cmd.f.GlobalFlagAll, msg.AskGitignore, true)) { if err := github.WriteGitignore(cmd.pathWorkingDir); err != nil { return msg.ErrorWritingGitignore } - logger.FInfo(cmd.f.IOStreams.Out, msg.WrittenGitignore) + logger.FInfoFlags(cmd.f.IOStreams.Out, msg.WrittenGitignore, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.WrittenGitignore) } - if cmd.shouldDevDeploy(msg.AskLocalDev, cmd.globalFlagAll, false) { + if cmd.auto || !cmd.shouldDevDeploy(msg.AskLocalDev, cmd.globalFlagAll, false) { + logger.FInfoFlags(cmd.io.Out, msg.InitDevCommand, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.InitDevCommand) + } else { if err := deps(c, cmd, msg.AskInstallDepsDev); err != nil { return err } - logger.Debug("Running dev command from init command") dev := cmd.devCmd(cmd.f) err = dev.Run(cmd.f) @@ -179,11 +186,16 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { logger.Debug("Error while running dev command called by init command", zap.Error(err)) return err } - } else { - logger.FInfo(cmd.io.Out, msg.InitDevCommand) } - if cmd.shouldDevDeploy(msg.AskDeploy, cmd.globalFlagAll, false) { + if cmd.auto || !cmd.shouldDevDeploy(msg.AskDeploy, cmd.globalFlagAll, false) { + logger.FInfoFlags(cmd.io.Out, msg.InitDeployCommand, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.InitDeployCommand) + msgEdgeAppInitSuccessFul := fmt.Sprintf(msg.EdgeApplicationsInitSuccessful, cmd.name) + logger.FInfoFlags(cmd.io.Out, fmt.Sprintf(msg.EdgeApplicationsInitSuccessful, cmd.name), + cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msgEdgeAppInitSuccessFul) + } else { if err := deps(c, cmd, msg.AskInstallDepsDeploy); err != nil { return err } @@ -195,12 +207,16 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { logger.Debug("Error while running deploy command called by init command", zap.Error(err)) return err } - } else { - logger.FInfo(cmd.io.Out, msg.InitDeployCommand) - logger.FInfo(cmd.io.Out, fmt.Sprintf(msg.EdgeApplicationsInitSuccessful, cmd.name)) } - return nil + initOut := output.SliceOutput{ + GeneralOutput: output.GeneralOutput{ + Out: cmd.f.IOStreams.Out, + Flags: cmd.f.Flags, + }, + Messages: msgs, + } + return output.Print(&initOut) } func deps(c *cobra.Command, cmd *initCmd, m string) error { diff --git a/pkg/cmd/init/utils.go b/pkg/cmd/init/utils.go index e322f9151..8e38d568a 100644 --- a/pkg/cmd/init/utils.go +++ b/pkg/cmd/init/utils.go @@ -46,7 +46,7 @@ func (cmd *initCmd) selectVulcanTemplates() error { return err } - logger.FInfo(cmd.io.Out, msg.InitGettingVulcan) + logger.FInfoFlags(cmd.io.Out, msg.InitGettingVulcan, cmd.f.Format, cmd.f.Out) cmdVulcanInit := fmt.Sprintf("init --name %s", cmd.name) if len(cmd.preset) > 0 { @@ -78,7 +78,7 @@ func (cmd *initCmd) selectVulcanTemplates() error { } func depsInstall(cmd *initCmd, packageManager string) error { - logger.FInfo(cmd.io.Out, msg.InitInstallDeps) + logger.FInfoFlags(cmd.io.Out, msg.InitInstallDeps, cmd.f.Format, cmd.f.Out) command := fmt.Sprintf("%s install", packageManager) err := cmd.commandRunInteractive(cmd.f, command) if err != nil { diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index da1fced79..1cfeb8a7b 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -191,8 +191,11 @@ func Execute() { } } } - output.Print(&output.ErrorOutput{ - GeneralOutput: output.GeneralOutput{Flags: factory.Flags}, - Err: err, - }) + + if err != nil { + output.Print(&output.ErrorOutput{ + GeneralOutput: output.GeneralOutput{Flags: factory.Flags}, + Err: err, + }) + } } diff --git a/pkg/cmdutil/file.go b/pkg/cmdutil/file.go index 3abbb204b..c26bed48f 100644 --- a/pkg/cmdutil/file.go +++ b/pkg/cmdutil/file.go @@ -2,12 +2,15 @@ package cmdutil import ( "encoding/json" + "fmt" "io" "os" "path/filepath" ) -func WriteDetailsToFile(data []byte, outPath string, writer io.Writer) error { +func WriteDetailsToFile(data []byte, outPath string) error { + fmt.Println(">>> data", string(data)) + fmt.Println(">>> outPath", outPath) err := os.MkdirAll(filepath.Dir(outPath), os.ModePerm) if err != nil { return err diff --git a/pkg/output/format.go b/pkg/output/format.go index 3009612a5..48377d37e 100644 --- a/pkg/output/format.go +++ b/pkg/output/format.go @@ -45,8 +45,10 @@ func format(v any, g GeneralOutput) error { } } + fmt.Println(">>> str", string(b)) + if len(g.Flags.Out) > 0 { - err = cmdutil.WriteDetailsToFile(b, g.Flags.Out, g.Out) + err = cmdutil.WriteDetailsToFile(b, g.Flags.Out) if err != nil { return fmt.Errorf("%s: %w", utils.ErrorWriteFile, err) } diff --git a/pkg/output/general.go b/pkg/output/general.go index a477e076c..baefed6b8 100644 --- a/pkg/output/general.go +++ b/pkg/output/general.go @@ -10,9 +10,9 @@ import ( ) type GeneralOutput struct { - Msg string `json:"message" yaml:"message" toml:"message"` - Out io.Writer `json:"-" yaml:"-" toml:"-"` - Flags cmdutil.Flags + Msg string `json:"message,omitempty" yaml:"message,omitempty" toml:"message,omitempty"` + Out io.Writer `json:"-" yaml:"-" toml:"-"` + Flags cmdutil.Flags `json:"-" yaml:"-" toml:"-"` } func (g *GeneralOutput) Format() (bool, error) { diff --git a/pkg/output/slice.go b/pkg/output/slice.go new file mode 100644 index 000000000..e737a9e87 --- /dev/null +++ b/pkg/output/slice.go @@ -0,0 +1,20 @@ +package output + +type SliceOutput struct { + Messages []string `json:"messages" yaml:"messages" toml:"messages"` + GeneralOutput +} + +func (i *SliceOutput) Format() (bool, error) { + formated := false + if len(i.Flags.Format) > 0 || len(i.Flags.Out) > 0 { + formated = true + err := format(i, *&i.GeneralOutput) + if err != nil { + return formated, err + } + } + return true, nil +} + +func (i *SliceOutput) Output() {} diff --git a/utils/helpers.go b/utils/helpers.go index b31d2ee8f..39068704f 100644 --- a/utils/helpers.go +++ b/utils/helpers.go @@ -139,13 +139,12 @@ func CommandRunInteractiveWithOutput(f *cmdutil.Factory, comm string, envVars [] func CommandRunInteractive(f *cmdutil.Factory, comm string) error { cmd := exec.Command(shell, "-c", comm) - if !f.Silent { + if !f.Silent && !(len(f.Flags.Format) > 0) && !(len(f.Flags.Out) > 0) { cmd.Stdin = f.IOStreams.In cmd.Stdout = f.IOStreams.Out } cmd.Stderr = f.IOStreams.Err - return cmd.Run() } From 1c22fd2e191b7c09fe8c6a775087b1b71e43f644 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 2 Jul 2024 14:15:18 -0300 Subject: [PATCH 05/33] refactor: lint --- pkg/output/slice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/output/slice.go b/pkg/output/slice.go index e737a9e87..49ef1e73f 100644 --- a/pkg/output/slice.go +++ b/pkg/output/slice.go @@ -9,7 +9,7 @@ func (i *SliceOutput) Format() (bool, error) { formated := false if len(i.Flags.Format) > 0 || len(i.Flags.Out) > 0 { formated = true - err := format(i, *&i.GeneralOutput) + err := format(i, i.GeneralOutput) if err != nil { return formated, err } From ec17b601fe15a8e085f8cd1b306e64539c10c48e Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:04:30 -0300 Subject: [PATCH 06/33] tests: add unit tests for unlink command --- pkg/cmd/delete/edge_application/cascade.go | 4 +- .../edge_application/edge_application.go | 4 +- pkg/cmd/sync/sync.go | 4 +- pkg/cmd/sync/sync_test.go | 97 ++++++++++++++ pkg/cmd/sync/tasks.go | 2 +- pkg/cmd/unlink/unlink.go | 3 + pkg/cmd/unlink/unlink_test.go | 118 ++++++++++++++++++ pkg/cmd/unlink/utils.go | 5 +- 8 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 pkg/cmd/sync/sync_test.go create mode 100644 pkg/cmd/unlink/unlink_test.go diff --git a/pkg/cmd/delete/edge_application/cascade.go b/pkg/cmd/delete/edge_application/cascade.go index da6fb38eb..3d37bc284 100644 --- a/pkg/cmd/delete/edge_application/cascade.go +++ b/pkg/cmd/delete/edge_application/cascade.go @@ -12,13 +12,13 @@ import ( "github.com/aziontech/azion-cli/pkg/output" ) -func (del *DeleteCmd) Cascade(ctx context.Context) error { +func CascadeDelete(ctx context.Context, del *DeleteCmd) error { azionJson, err := del.GetAzion(ProjectConf) if err != nil { if errors.Is(err, os.ErrNotExist) { return msg.ErrorMissingAzionJson } else { - return err //message with error + return err } } if azionJson.Application.ID == 0 { diff --git a/pkg/cmd/delete/edge_application/edge_application.go b/pkg/cmd/delete/edge_application/edge_application.go index cb8eb95bf..d4b240d87 100644 --- a/pkg/cmd/delete/edge_application/edge_application.go +++ b/pkg/cmd/delete/edge_application/edge_application.go @@ -28,6 +28,7 @@ type DeleteCmd struct { GetAzion func(confPath string) (*contracts.AzionApplicationOptions, error) f *cmdutil.Factory UpdateJson func(cmd *DeleteCmd) error + Cascade func(ctx context.Context, del *DeleteCmd) error } func NewCmd(f *cmdutil.Factory) *cobra.Command { @@ -40,6 +41,7 @@ func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { GetAzion: utils.GetAzionJsonContent, f: f, UpdateJson: updateAzionJson, + Cascade: CascadeDelete, } } @@ -72,7 +74,7 @@ func (del *DeleteCmd) run(cmd *cobra.Command, application_id int64) error { ctx := context.Background() if cmd.Flags().Changed("cascade") { - err := del.Cascade(ctx) + err := del.Cascade(ctx, del) if err != nil { return err } diff --git a/pkg/cmd/sync/sync.go b/pkg/cmd/sync/sync.go index bc0cbf4ab..27288c27c 100644 --- a/pkg/cmd/sync/sync.go +++ b/pkg/cmd/sync/sync.go @@ -19,6 +19,7 @@ type SyncCmd struct { GetAzionJsonContent func(confPath string) (*contracts.AzionApplicationOptions, error) WriteAzionJsonContent func(conf *contracts.AzionApplicationOptions, confPath string) error F *cmdutil.Factory + SyncResources func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error } func NewSync(f *cmdutil.Factory) *SyncCmd { @@ -27,6 +28,7 @@ func NewSync(f *cmdutil.Factory) *SyncCmd { Io: f.IOStreams, GetAzionJsonContent: utils.GetAzionJsonContent, WriteAzionJsonContent: utils.WriteAzionJsonContent, + SyncResources: SyncLocalResources, } } @@ -92,7 +94,7 @@ func Sync(cmdFac *SyncCmd) error { Conf: conf, } - err = cmdFac.SyncResources(cmdFac.F, info) + err = cmdFac.SyncResources(cmdFac.F, info, cmdFac) if err != nil { return err } diff --git a/pkg/cmd/sync/sync_test.go b/pkg/cmd/sync/sync_test.go new file mode 100644 index 000000000..8975220f0 --- /dev/null +++ b/pkg/cmd/sync/sync_test.go @@ -0,0 +1,97 @@ +package sync + +import ( + "errors" + "fmt" + "testing" + + msg "github.com/aziontech/azion-cli/messages/sync" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/contracts" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestSync(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + mockGetContentFunc func(confPath string) (*contracts.AzionApplicationOptions, error) + mockWriteFunc func(conf *contracts.AzionApplicationOptions, confPath string) error + mockSyncResources func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error + expectedError error + }{ + { + name: "sync - successful synchronization", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return &contracts.AzionApplicationOptions{ + // Mock relevant fields + }, nil + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return nil + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + // Mock synchronization logic + return nil + }, + expectedError: nil, + }, + { + name: "sync - failed to get content", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return nil, errors.New("Failed to synchronize local resources with remote resources: failed to get azion.json content") + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return nil + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + return nil + }, + expectedError: fmt.Errorf(msg.ERRORSYNC, "failed to get azion.json content"), + }, + { + name: "sync - failed to write content", + mockGetContentFunc: func(confPath string) (*contracts.AzionApplicationOptions, error) { + return &contracts.AzionApplicationOptions{ + // Mock relevant fields + }, nil + }, + mockWriteFunc: func(conf *contracts.AzionApplicationOptions, confPath string) error { + return errors.New("failed to write azion.json content") + }, + mockSyncResources: func(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { + return errors.New("failed to write azion.json content") + }, + expectedError: errors.New("failed to write azion.json content"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + f, _, _ := testutils.NewFactory(mock) + + syncCmd := NewSync(f) + + // Mock GetAzionJsonContent and WriteAzionJsonContent functions + syncCmd.GetAzionJsonContent = tt.mockGetContentFunc + syncCmd.WriteAzionJsonContent = tt.mockWriteFunc + + // Replace syncResources function with mock + syncCmd.SyncResources = tt.mockSyncResources + + err := Sync(syncCmd) + if tt.expectedError != nil { + require.Error(t, err) + assert.Equal(t, tt.expectedError.Error(), err.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/pkg/cmd/sync/tasks.go b/pkg/cmd/sync/tasks.go index 1082bbb5a..27a83bc94 100644 --- a/pkg/cmd/sync/tasks.go +++ b/pkg/cmd/sync/tasks.go @@ -18,7 +18,7 @@ var ( ctx context.Context = context.Background() ) -func (synch *SyncCmd) SyncResources(f *cmdutil.Factory, info contracts.SyncOpts) error { +func SyncLocalResources(f *cmdutil.Factory, info contracts.SyncOpts, synch *SyncCmd) error { opts = &contracts.ListOptions{ PageSize: 1000, Page: 1, diff --git a/pkg/cmd/unlink/unlink.go b/pkg/cmd/unlink/unlink.go index 6d375a179..580dcac6d 100644 --- a/pkg/cmd/unlink/unlink.go +++ b/pkg/cmd/unlink/unlink.go @@ -5,6 +5,7 @@ import ( "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/unlink" + app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/utils" "github.com/spf13/cobra" @@ -16,6 +17,7 @@ type UnlinkCmd struct { IsDirEmpty func(dirpath string) (bool, error) CleanDir func(dirpath string) error F *cmdutil.Factory + DeleteCmd func(f *cmdutil.Factory) *app.DeleteCmd } func NewUnlinkCmd(f *cmdutil.Factory) *UnlinkCmd { @@ -25,6 +27,7 @@ func NewUnlinkCmd(f *cmdutil.Factory) *UnlinkCmd { Clean: clean, IsDirEmpty: utils.IsDirEmpty, CleanDir: utils.CleanDirectory, + DeleteCmd: app.NewDeleteCmd, } } diff --git a/pkg/cmd/unlink/unlink_test.go b/pkg/cmd/unlink/unlink_test.go new file mode 100644 index 000000000..eec32a3d2 --- /dev/null +++ b/pkg/cmd/unlink/unlink_test.go @@ -0,0 +1,118 @@ +package unlink + +import ( + "context" + "errors" + "testing" + + app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func mockDelSuccess() *app.DeleteCmd { + return &app.DeleteCmd{ + Cascade: func(ctx context.Context, del *app.DeleteCmd) error { + return nil + }, + } +} + +func mockDelFail() *app.DeleteCmd { + return &app.DeleteCmd{ + Cascade: func(ctx context.Context, del *app.DeleteCmd) error { + return errors.New("Failed to cascade delete") + }, + } +} + +func TestUnlink(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + isDirEmpty bool + cleanDirError error + expectedOutput string + expectedError string + mockDeleteCmd *app.DeleteCmd + }{ + { + name: "unlink - directory is empty", + isDirEmpty: true, + cleanDirError: nil, + expectedOutput: "Unliked successfully", + expectedError: "", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - clean directory successfully", + isDirEmpty: false, + cleanDirError: nil, + expectedOutput: "Unliked successfully", + expectedError: "", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - failed to clean directory", + isDirEmpty: false, + cleanDirError: errors.New("failed to clean directory"), + expectedOutput: "", + expectedError: "failed to clean directory", + mockDeleteCmd: mockDelSuccess(), + }, + { + name: "unlink - cascade delete fails", + isDirEmpty: false, + cleanDirError: nil, + expectedOutput: "", + expectedError: "Failed to cascade delete", + mockDeleteCmd: mockDelFail(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockIsDirEmpty := func(dirpath string) (bool, error) { + return tt.isDirEmpty, nil + } + + mockCleanDir := func(dirpath string) error { + return tt.cleanDirError + } + + mockDeleteCmd := tt.mockDeleteCmd + + mock := &httpmock.Registry{} + + f, out, _ := testutils.NewFactory(mock) + f.GlobalFlagAll = true // Simulate --yes flag + + unlinkCmd := &UnlinkCmd{ + F: f, + IsDirEmpty: mockIsDirEmpty, + CleanDir: mockCleanDir, + ShouldClean: shouldClean, + Clean: clean, + DeleteCmd: func(f *cmdutil.Factory) *app.DeleteCmd { + return mockDeleteCmd + }, + } + cmd := NewCobraCmd(unlinkCmd, f) + + _, err := cmd.ExecuteC() + if tt.expectedError != "" { + require.Error(t, err) + assert.Equal(t, tt.expectedError, err.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, out.String()) + } + + }) + } +} diff --git a/pkg/cmd/unlink/utils.go b/pkg/cmd/unlink/utils.go index ca2adbda6..8d9296463 100644 --- a/pkg/cmd/unlink/utils.go +++ b/pkg/cmd/unlink/utils.go @@ -3,7 +3,6 @@ package unlink import ( "context" - app "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_application" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/logger" helpers "github.com/aziontech/azion-cli/utils" @@ -27,9 +26,9 @@ func clean(f *cmdutil.Factory, cmd *UnlinkCmd) error { } if shouldCascade { - cmd := app.NewDeleteCmd(f) + delCmd := cmd.DeleteCmd(f) ctx := context.Background() - err := cmd.Cascade(ctx) + err := delCmd.Cascade(ctx, delCmd) if err != nil { return err } From 3a0a03f6b8dc40a473601605357712fc0434355b Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Wed, 3 Jul 2024 11:56:21 -0300 Subject: [PATCH 07/33] fix: not informed out iostream return error --- pkg/cmd/root/root.go | 7 +++++-- pkg/cmdutil/file.go | 3 --- pkg/output/format.go | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 1cfeb8a7b..da0dd0ffb 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -194,8 +194,11 @@ func Execute() { if err != nil { output.Print(&output.ErrorOutput{ - GeneralOutput: output.GeneralOutput{Flags: factory.Flags}, - Err: err, + GeneralOutput: output.GeneralOutput{ + Out: streams.Out, + Flags: factory.Flags, + }, + Err: err, }) } } diff --git a/pkg/cmdutil/file.go b/pkg/cmdutil/file.go index c26bed48f..3a8979f31 100644 --- a/pkg/cmdutil/file.go +++ b/pkg/cmdutil/file.go @@ -2,15 +2,12 @@ package cmdutil import ( "encoding/json" - "fmt" "io" "os" "path/filepath" ) func WriteDetailsToFile(data []byte, outPath string) error { - fmt.Println(">>> data", string(data)) - fmt.Println(">>> outPath", outPath) err := os.MkdirAll(filepath.Dir(outPath), os.ModePerm) if err != nil { return err diff --git a/pkg/output/format.go b/pkg/output/format.go index 48377d37e..81d7e1af3 100644 --- a/pkg/output/format.go +++ b/pkg/output/format.go @@ -45,8 +45,6 @@ func format(v any, g GeneralOutput) error { } } - fmt.Println(">>> str", string(b)) - if len(g.Flags.Out) > 0 { err = cmdutil.WriteDetailsToFile(b, g.Flags.Out) if err != nil { From 98e7e29a4ac6570752b64d2b247eec4d9e62ff2f Mon Sep 17 00:00:00 2001 From: Maxwel Mazur <52722027+maxwelbm@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:07:39 -0300 Subject: [PATCH 08/33] chore: go version Vulnerability Report: GO-2024-2963 --- .github/workflows/test_and_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 7f528d739..7b61ca980 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22 steps: - name: Setting GIT From db814a2373ba3ce628ae6b3517f3782e182e4f87 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:23:29 -0300 Subject: [PATCH 09/33] tests: add unit tests for origin/cache/function delete commands --- pkg/cmd/delete/cache_setting/cache_setting.go | 51 ++++-- .../cache_setting/cache_setting_test.go | 132 +++++++++++---- pkg/cmd/delete/domain/domain.go | 48 ++++-- pkg/cmd/delete/domain/domain_test.go | 151 ++++++++++++++---- pkg/cmd/delete/edge_function/edge_function.go | 53 ++++-- .../edge_function/edge_function_test.go | 149 +++++++++++++---- pkg/cmd/delete/origin/origin.go | 56 +++++-- pkg/cmd/delete/origin/origin_test.go | 130 +++++++++++---- 8 files changed, 603 insertions(+), 167 deletions(-) diff --git a/pkg/cmd/delete/cache_setting/cache_setting.go b/pkg/cmd/delete/cache_setting/cache_setting.go index 304eac4ba..116449003 100644 --- a/pkg/cmd/delete/cache_setting/cache_setting.go +++ b/pkg/cmd/delete/cache_setting/cache_setting.go @@ -9,6 +9,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/cache_setting" api "github.com/aziontech/azion-cli/pkg/api/cache_setting" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -21,20 +22,42 @@ var ( cacheSettingsID int64 ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - cmd := &cobra.Command{ +type DeleteCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteCache func(context.Context, int64, int64) error + AskInput func(msg string) (string, error) +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteCache: func(ctx context.Context, appID int64, cacheID int64) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, appID, cacheID) + }, + AskInput: utils.AskInput, + } +} + +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.DeleteShortDescription, Long: msg.DeleteLongDescription, SilenceUsage: true, SilenceErrors: true, Example: heredoc.Doc(` - $ azion delete cache-setting --application-id 1673635839 --cache-setting-id 107313 - `), + $ azion delete cache-setting --application-id 1673635839 --cache-setting-id 107313 + `), RunE: func(cmd *cobra.Command, args []string) error { + var err error if !cmd.Flags().Changed("application-id") { - answer, err := utils.AskInput(msg.ListAskInputApplicationID) + answer, err := delete.AskInput(msg.ListAskInputApplicationID) if err != nil { return err } @@ -49,7 +72,7 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } if !cmd.Flags().Changed("cache-setting-id") { - answer, err := utils.AskInput(msg.DeleteAskInputCacheID) + answer, err := delete.AskInput(msg.DeleteAskInputCacheID) if err != nil { return err } @@ -67,7 +90,7 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { ctx := context.Background() - err := client.Delete(ctx, applicationID, cacheSettingsID) + err = client.Delete(ctx, applicationID, cacheSettingsID) if err != nil { return fmt.Errorf(msg.ErrorFailToDelete.Error(), err) } @@ -78,12 +101,16 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { Flags: f.Flags, } return output.Print(&deleteOut) - }, } - cmd.Flags().Int64Var(&applicationID, "application-id", 0, msg.DeleteFlagApplicationID) - cmd.Flags().Int64Var(&cacheSettingsID, "cache-setting-id", 0, msg.DeleteFlagCacheSettingsID) - cmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) - return cmd + cobraCmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) + cobraCmd.Flags().Int64Var(&applicationID, "application-id", 0, msg.DeleteFlagApplicationID) + cobraCmd.Flags().Int64Var(&cacheSettingsID, "cache-setting-id", 0, msg.DeleteFlagCacheSettingsID) + + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/cache_setting/cache_setting_test.go b/pkg/cmd/delete/cache_setting/cache_setting_test.go index 9a14440ad..0ea1f6b1d 100644 --- a/pkg/cmd/delete/cache_setting/cache_setting_test.go +++ b/pkg/cmd/delete/cache_setting/cache_setting_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/aziontech/azion-cli/pkg/logger" + "go.uber.org/zap" "go.uber.org/zap/zapcore" msg "github.com/aziontech/azion-cli/messages/cache_setting" @@ -14,38 +15,103 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreate(t *testing.T) { +func mockAppId(msg string) (string, error) { + return "1673635839", nil +} + +func mockCacheId(msg string) (string, error) { + return "107313", nil +} + +func mockInvalid(msg string) (string, error) { + return "invalid", nil +} + +func TestDeleteWithAskInput(t *testing.T) { logger.New(zapcore.DebugLevel) - t.Run("delete by id", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/1673635839/cache_settings/107313"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "1673635839", "--cache-setting-id", "107313"}) - - _, err := cmd.ExecuteC() - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf(msg.DeleteOutputSuccess, 107313), stdout.String()) - }) - - t.Run("delete that is not found", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/1234/cache_settings/107313"), - httpmock.StatusStringResponse(404, "Not Found"), - ) - - f, _, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "1234", "--cache-setting-id", "107313"}) - - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + + tests := []struct { + name string + applicationID string + cacheSettingID string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(msg string) (string, error) + mockError error + }{ + { + name: "ask for application id success", + cacheSettingID: "107313", + method: "DELETE", + endpoint: "edge_applications/1673635839/cache_settings/107313", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 107313), + expectError: false, + mockInputs: mockAppId, + mockError: nil, + }, + { + name: "ask for cache setting id success", + applicationID: "1673635839", + method: "DELETE", + endpoint: "edge_applications/1673635839/cache_settings/107313", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 107313), + expectError: false, + mockInputs: mockCacheId, + mockError: nil, + }, + { + name: "error in input", + cacheSettingID: "107313", + method: "DELETE", + endpoint: "edge_applications/invalid/cache_settings/107313", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--cache-setting-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs + cobraCmd := NewCobraCmd(deleteCmd, f) + + if tt.applicationID != "" && tt.cacheSettingID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID, "--cache-setting-id", tt.cacheSettingID}) + } else if tt.applicationID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID}) + } else { + cobraCmd.SetArgs([]string{"--cache-setting-id", tt.cacheSettingID}) + } + + _, err := cobraCmd.ExecuteC() + if tt.expectError { + require.Error(t, err) + logger.Debug("Expected error occurred", zap.Error(err)) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + logger.Debug("Expected output", zap.String("output", stdout.String())) + } + }) + } } diff --git a/pkg/cmd/delete/domain/domain.go b/pkg/cmd/delete/domain/domain.go index 5e4dd89d3..b853b2b48 100644 --- a/pkg/cmd/delete/domain/domain.go +++ b/pkg/cmd/delete/domain/domain.go @@ -9,6 +9,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/delete/domain" api "github.com/aziontech/azion-cli/pkg/api/domain" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -16,9 +17,31 @@ import ( "go.uber.org/zap" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var domainID int64 - cmd := &cobra.Command{ +var domainID int64 + +type DeleteCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteDomain func(context.Context, int64) error + AskInput func(string) (string, error) +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteDomain: func(ctx context.Context, domainID int64) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, domainID) + }, + AskInput: utils.AskInput, + } +} + +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.ShortDescription, Long: msg.LongDescription, @@ -26,12 +49,12 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { SilenceErrors: true, Example: heredoc.Doc(` $ azion delete domain --domain-id 1234 - `), + `), RunE: func(cmd *cobra.Command, args []string) error { + var err error if !cmd.Flags().Changed("domain-id") { - - answer, err := utils.AskInput(msg.AskDeleteInput) + answer, err := delete.AskInput(msg.AskDeleteInput) if err != nil { return err } @@ -49,7 +72,7 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { ctx := context.Background() - err := client.Delete(ctx, domainID) + err = client.Delete(ctx, domainID) if err != nil { return fmt.Errorf(msg.ErrorFailToDeleteDomain.Error(), err) } @@ -63,7 +86,12 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { }, } - cmd.Flags().Int64Var(&domainID, "domain-id", 0, msg.FlagId) - cmd.Flags().BoolP("help", "h", false, msg.HelpFlag) - return cmd + cobraCmd.Flags().Int64Var(&domainID, "domain-id", 0, msg.FlagId) + cobraCmd.Flags().BoolP("help", "h", false, msg.HelpFlag) + + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/domain/domain_test.go b/pkg/cmd/delete/domain/domain_test.go index 03e5c2b22..3afd088f0 100644 --- a/pkg/cmd/delete/domain/domain_test.go +++ b/pkg/cmd/delete/domain/domain_test.go @@ -1,53 +1,146 @@ package domain import ( + "fmt" "testing" "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/utils" "go.uber.org/zap/zapcore" + msg "github.com/aziontech/azion-cli/messages/delete/domain" "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestCreate(t *testing.T) { - logger.New(zapcore.DebugLevel) - t.Run("delete domain by id", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "domains/1234"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) +func mockDomainID(msg string) (string, error) { + return "1234", nil +} - cmd := NewCmd(f) - cmd.SetArgs([]string{"--domain-id", "1234"}) +func mockInvalid(msg string) (string, error) { + return "invalid", nil +} - _, err := cmd.ExecuteC() - require.NoError(t, err) +func mockParseError(msg string) (string, error) { + return "invalid", utils.ErrorParseResponse +} - assert.Equal(t, "Domain 1234 was successfully deleted", stdout.String()) - }) +func TestDeleteWithAskInput(t *testing.T) { + logger.New(zapcore.DebugLevel) - t.Run("delete domain - not found", func(t *testing.T) { - mock := &httpmock.Registry{} + tests := []struct { + name string + domainID string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(string) (string, error) + mockError error + }{ + { + name: "delete domain by id", + domainID: "1234", + method: "DELETE", + endpoint: "domains/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.OutputSuccess, 1234), + expectError: false, + mockInputs: mockDomainID, + mockError: nil, + }, + { + name: "delete domain - not found", + domainID: "1234", + method: "DELETE", + endpoint: "domains/1234", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockInputs: mockDomainID, + mockError: fmt.Errorf("Failed to parse your response. Check your response and try again. If the error persists, contact Azion support"), + }, + { + name: "error in input", + domainID: "1234", + method: "DELETE", + endpoint: "domains/invalid", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--domain-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + { + name: "ask for domain id success", + domainID: "", + method: "DELETE", + endpoint: "domains/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.OutputSuccess, 1234), + expectError: false, + mockInputs: mockDomainID, + mockError: nil, + }, + { + name: "ask for domain id conversion failure", + domainID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf(msg.ErrorConvertId.Error()), + }, + { + name: "error - parse answer", + domainID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockParseError, + mockError: fmt.Errorf(utils.ErrorParseResponse.Error()), + }, + } - mock.Register( - httpmock.REST("DELETE", "domains/1234"), - httpmock.StatusStringResponse(404, "Not Found"), - ) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) - f, _, _ := testutils.NewFactory(mock) + f, stdout, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs + cobraCmd := NewCobraCmd(deleteCmd, f) - cmd.SetArgs([]string{"--domain-id", "1234"}) + if tt.domainID != "" { + cobraCmd.SetArgs([]string{"--domain-id", tt.domainID}) + } - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + _, err := cobraCmd.ExecuteC() + if tt.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + } + }) + } } diff --git a/pkg/cmd/delete/edge_function/edge_function.go b/pkg/cmd/delete/edge_function/edge_function.go index 0db196094..61fc94d13 100644 --- a/pkg/cmd/delete/edge_function/edge_function.go +++ b/pkg/cmd/delete/edge_function/edge_function.go @@ -9,6 +9,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/edge_function" api "github.com/aziontech/azion-cli/pkg/api/edge_function" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -16,20 +17,44 @@ import ( "go.uber.org/zap" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var function_id int64 - cmd := &cobra.Command{ +var functionID int64 + +type DeleteCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteFunction func(context.Context, int64) error + AskInput func(string) (string, error) +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteFunction: func(ctx context.Context, functionID int64) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, functionID) + }, + AskInput: utils.AskInput, + } +} + +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.DeleteShortDescription, Long: msg.DeleteLongDescription, SilenceUsage: true, SilenceErrors: true, Example: heredoc.Doc(` - $ azion delete edge-function --function-id 1234 - `), + $ azion delete edge-function --function-id 1234 + `), RunE: func(cmd *cobra.Command, args []string) error { + var err error + if !cmd.Flags().Changed("function-id") { - answer, err := utils.AskInput(msg.AskEdgeFunctionID) + answer, err := delete.AskInput(msg.AskEdgeFunctionID) if err != nil { return err } @@ -40,20 +65,20 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { return msg.ErrorConvertIdFunction } - function_id = num + functionID = num } client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) ctx := context.Background() - err := client.Delete(ctx, function_id) + err = client.Delete(ctx, functionID) if err != nil { return fmt.Errorf(msg.ErrorFailToDeleteFunction.Error(), err) } deleteOut := output.GeneralOutput{ - Msg: fmt.Sprintf(msg.DeleteOutputSuccess, function_id), + Msg: fmt.Sprintf(msg.DeleteOutputSuccess, functionID), Out: f.IOStreams.Out, Flags: f.Flags, } @@ -61,8 +86,12 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { }, } - cmd.Flags().Int64Var(&function_id, "function-id", 0, msg.FlagID) - cmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) + cobraCmd.Flags().Int64Var(&functionID, "function-id", 0, msg.FlagID) + cobraCmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) - return cmd + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/edge_function/edge_function_test.go b/pkg/cmd/delete/edge_function/edge_function_test.go index 88ec8c21a..ac32d28dd 100644 --- a/pkg/cmd/delete/edge_function/edge_function_test.go +++ b/pkg/cmd/delete/edge_function/edge_function_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/utils" "go.uber.org/zap/zapcore" msg "github.com/aziontech/azion-cli/messages/edge_function" @@ -14,42 +15,132 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreate(t *testing.T) { - logger.New(zapcore.DebugLevel) - t.Run("delete function by id", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_functions/1234"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) +func mockFunctionID(msg string) (string, error) { + return "1234", nil +} - cmd := NewCmd(f) - cmd.SetArgs([]string{"--function-id", "1234"}) +func mockInvalidFunctionID(msg string) (string, error) { + return "invalid", nil +} - _, err := cmd.ExecuteC() - require.NoError(t, err) +func mockParseErrorFunctionID(msg string) (string, error) { + return "invalid", utils.ErrorParseResponse +} - assert.Equal(t, fmt.Sprintf(msg.DeleteOutputSuccess, 1234), stdout.String()) - }) +func TestDeleteWithAskInput(t *testing.T) { + logger.New(zapcore.DebugLevel) - t.Run("delete function that is not found", func(t *testing.T) { - mock := &httpmock.Registry{} + tests := []struct { + name string + functionID string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(string) (string, error) + mockError error + }{ + { + name: "delete function by id", + functionID: "1234", + method: "DELETE", + endpoint: "edge_functions/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 1234), + expectError: false, + mockInputs: mockFunctionID, + mockError: nil, + }, + { + name: "delete function - not found", + functionID: "1234", + method: "DELETE", + endpoint: "edge_functions/1234", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockInputs: mockFunctionID, + mockError: fmt.Errorf("Failed to parse your response. Check your response and try again. If the error persists, contact Azion support"), + }, + { + name: "error in input", + functionID: "1234", + method: "DELETE", + endpoint: "edge_functions/invalid", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalidFunctionID, + mockError: fmt.Errorf("invalid argument \"\" for \"--function-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + { + name: "ask for function id success", + functionID: "", + method: "DELETE", + endpoint: "edge_functions/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 1234), + expectError: false, + mockInputs: mockFunctionID, + mockError: nil, + }, + { + name: "ask for function id conversion failure", + functionID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalidFunctionID, + mockError: fmt.Errorf(msg.ErrorConvertIdFunction.Error()), + }, + { + name: "error - parse answer", + functionID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockParseErrorFunctionID, + mockError: fmt.Errorf(utils.ErrorParseResponse.Error()), + }, + } - mock.Register( - httpmock.REST("DELETE", "edge_functions/1234"), - httpmock.StatusStringResponse(404, "Not Found"), - ) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) - f, _, _ := testutils.NewFactory(mock) + f, stdout, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs + cobraCmd := NewCobraCmd(deleteCmd, f) - cmd.SetArgs([]string{"--function-id", "1234"}) + if tt.functionID != "" { + cobraCmd.SetArgs([]string{"--function-id", tt.functionID}) + } - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + _, err := cobraCmd.ExecuteC() + if tt.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + } + }) + } } diff --git a/pkg/cmd/delete/origin/origin.go b/pkg/cmd/delete/origin/origin.go index e28c400af..0d52f089a 100644 --- a/pkg/cmd/delete/origin/origin.go +++ b/pkg/cmd/delete/origin/origin.go @@ -9,6 +9,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/origin" api "github.com/aziontech/azion-cli/pkg/api/origin" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -16,10 +17,34 @@ import ( "go.uber.org/zap" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var applicationID int64 - var originKey string - cmd := &cobra.Command{ +var ( + applicationID int64 + originKey string +) + +type DeleteCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteOrigins func(context.Context, int64, string) error + AskInput func(string) (string, error) +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteOrigins: func(ctx context.Context, appID int64, key string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.DeleteOrigins(ctx, appID, key) + }, + AskInput: utils.AskInput, + } +} + +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.DeleteShortDescription, Long: msg.DeleteLongDescription, @@ -28,10 +53,12 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { Example: heredoc.Doc(` $ azion delete origin --application-id 1673635839 --origin-key 03a6e7bf-8e26-49c7-a66e-ab8eaa425086 $ azion delete origin - `), + `), RunE: func(cmd *cobra.Command, args []string) error { + var err error + if !cmd.Flags().Changed("application-id") { - answer, err := utils.AskInput(msg.DeleteAskInputApp) + answer, err := delete.AskInput(msg.DeleteAskInputApp) if err != nil { return err } @@ -44,7 +71,7 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } if !cmd.Flags().Changed("origin-key") { - answer, err := utils.AskInput(msg.DeleteAskInputOri) + answer, err := delete.AskInput(msg.DeleteAskInputOri) if err != nil { return err } @@ -52,9 +79,8 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } ctx := context.Background() - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) - err := client.DeleteOrigins(ctx, applicationID, originKey) + err = delete.DeleteOrigins(ctx, applicationID, originKey) if err != nil { return fmt.Errorf(msg.ErrorFailToDelete.Error(), err) } @@ -68,8 +94,12 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { }, } - cmd.Flags().Int64Var(&applicationID, "application-id", 0, msg.FlagEdgeApplicationID) - cmd.Flags().StringVar(&originKey, "origin-key", "", msg.FlagOriginKey) - cmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) - return cmd + cobraCmd.Flags().Int64Var(&applicationID, "application-id", 0, msg.FlagEdgeApplicationID) + cobraCmd.Flags().StringVar(&originKey, "origin-key", "", msg.FlagOriginKey) + cobraCmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/origin/origin_test.go b/pkg/cmd/delete/origin/origin_test.go index f68e020f4..1acab12cc 100644 --- a/pkg/cmd/delete/origin/origin_test.go +++ b/pkg/cmd/delete/origin/origin_test.go @@ -4,49 +4,121 @@ import ( "fmt" "testing" - "github.com/aziontech/azion-cli/pkg/logger" - "go.uber.org/zap/zapcore" - msg "github.com/aziontech/azion-cli/messages/origin" "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) -func TestCreate(t *testing.T) { +func mockAppID(msg string) (string, error) { + return "1673635839", nil +} + +func mockOriginKey(msg string) (string, error) { + return "58755fef-e830-4ea4-b9e0-6481f1ef496d", nil +} + +func mockInvalid(msg string) (string, error) { + return "invalid", nil +} + +func TestDeleteWithAskInput(t *testing.T) { logger.New(zapcore.DebugLevel) - t.Run("delete origin by key", func(t *testing.T) { - mock := &httpmock.Registry{} - mock.Register( - httpmock.REST("DELETE", "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d"), - httpmock.StatusStringResponse(204, ""), - ) + tests := []struct { + name string + applicationID string + originKey string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(msg string) (string, error) + mockError error + }{ + { + name: "ask for application id success", + applicationID: "1673635839", + originKey: "58755fef-e830-4ea4-b9e0-6481f1ef496d", + method: "DELETE", + endpoint: "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, "58755fef-e830-4ea4-b9e0-6481f1ef496d"), + expectError: false, + mockInputs: mockAppID, + mockError: nil, + }, + { + name: "ask for origin key success", + applicationID: "1673635839", + method: "DELETE", + endpoint: "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, "58755fef-e830-4ea4-b9e0-6481f1ef496d"), + expectError: false, + mockInputs: mockOriginKey, + mockError: nil, + }, + { + name: "error in input", + originKey: "58755fef-e830-4ea4-b9e0-6481f1ef496d", + method: "DELETE", + endpoint: "edge_applications/invalid/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--application-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + } - f, stdout, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "1673635839", "--origin-key", "58755fef-e830-4ea4-b9e0-6481f1ef496d"}) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) - _, err := cmd.ExecuteC() - require.NoError(t, err) + f, stdout, _ := testutils.NewFactory(mock) - assert.Equal(t, fmt.Sprintf(msg.DeleteOutputSuccess, "58755fef-e830-4ea4-b9e0-6481f1ef496d"), stdout.String()) - }) + // Create your delete command instance (adjust as per your package structure) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs - t.Run("delete domain - not found", func(t *testing.T) { - mock := &httpmock.Registry{} + // Create your Cobra command instance (adjust as per your package structure) + cobraCmd := NewCobraCmd(deleteCmd, f) - mock.Register( - httpmock.REST("DELETE", "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d"), - httpmock.StatusStringResponse(404, "Not Found"), - ) + // Set command line arguments based on test case + if tt.applicationID != "" && tt.originKey != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID, "--origin-key", tt.originKey}) + } else if tt.applicationID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID}) + } else { + cobraCmd.SetArgs([]string{"--origin-key", tt.originKey}) + } - f, _, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "1673635839", "--origin-key", "58755fef-e830-4ea4-b9e0-6481f1ef496d"}) + // Execute the command + _, err := cobraCmd.ExecuteC() - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + // Validate the results + if tt.expectError { + require.Error(t, err) + logger.Debug("Expected error occurred", zap.Error(err)) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + logger.Debug("Expected output", zap.String("output", stdout.String())) + } + }) + } } From cdcca687bd13b54e0aab6fbfaf278cbc81a10117 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:26:30 -0300 Subject: [PATCH 10/33] tests: add unit tests for delete personal token --- .../delete/personal_token/personal_token.go | 58 ++++++--- .../personal_token/personal_token_test.go | 116 ++++++++++++------ 2 files changed, 117 insertions(+), 57 deletions(-) diff --git a/pkg/cmd/delete/personal_token/personal_token.go b/pkg/cmd/delete/personal_token/personal_token.go index 2a76a98b8..3de668a49 100644 --- a/pkg/cmd/delete/personal_token/personal_token.go +++ b/pkg/cmd/delete/personal_token/personal_token.go @@ -8,57 +8,81 @@ import ( msg "github.com/aziontech/azion-cli/messages/delete/personal_token" api "github.com/aziontech/azion-cli/pkg/api/personal_token" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" "github.com/spf13/cobra" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var id string +var ( + tokenID string +) + +type DeleteCmd struct { + Io *iostreams.IOStreams + AskInput func(string) (string, error) + DeleteFunc func(context.Context, string) error +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + AskInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteFunc: func(ctx context.Context, id string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, id) + }, + } +} - deleteCmd := &cobra.Command{ +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.ShortDescription, Long: msg.LongDescription, - SilenceErrors: true, SilenceUsage: true, + SilenceErrors: true, Example: heredoc.Doc(` - $ azion delete personal-token --id 1234-123-321 + $ azion delete personal-token --id 1234-123-321 `), - RunE: func(cmd *cobra.Command, args []string) error { + var err error + if !cmd.Flags().Changed("id") { - answer, err := utils.AskInput(msg.AskDeleteInput) + answer, err := delete.AskInput(msg.AskDeleteInput) if err != nil { return err } - - id = answer + tokenID = answer } - if utils.IsEmpty(id) { + if utils.IsEmpty(tokenID) { return utils.ErrorArgumentIsEmpty } - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + ctx := context.Background() - err := client.Delete(context.Background(), id) + err = delete.DeleteFunc(ctx, tokenID) if err != nil { return fmt.Errorf(msg.ErrorFailToDelete.Error(), err) } deleteOut := output.GeneralOutput{ - Msg: fmt.Sprintf(msg.OutputSuccess, id), + Msg: fmt.Sprintf(msg.OutputSuccess, tokenID), Out: f.IOStreams.Out, Flags: f.Flags, } return output.Print(&deleteOut) - }, } - deleteCmd.Flags().StringVar(&id, "id", "", msg.FlagID) - deleteCmd.Flags().BoolP("help", "h", false, msg.HelpFlag) + cobraCmd.Flags().StringVar(&tokenID, "id", "", msg.FlagID) + cobraCmd.Flags().BoolP("help", "h", false, msg.HelpFlag) + return cobraCmd +} - return deleteCmd +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/personal_token/personal_token_test.go b/pkg/cmd/delete/personal_token/personal_token_test.go index 89b4aaddd..5e977164e 100644 --- a/pkg/cmd/delete/personal_token/personal_token_test.go +++ b/pkg/cmd/delete/personal_token/personal_token_test.go @@ -4,68 +4,104 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/assert" - "go.uber.org/zap/zapcore" - msg "github.com/aziontech/azion-cli/messages/delete/personal_token" "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" "github.com/aziontech/azion-cli/utils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" ) -func TestNewCmd(t *testing.T) { +func mockTokenID(msg string) (string, error) { + return "5c9c1854-45dd-11ee-be56-0242ac120002", nil +} + +func mockInvalid(msg string) (string, error) { + return "invalid", utils.ErrorParseResponse +} + +func TestDeleteCmd(t *testing.T) { logger.New(zapcore.DebugLevel) tests := []struct { - name string - args []string - mock func() *httpmock.Registry - output string - err error + name string + args []string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(msg string) (string, error) + mockError error }{ { - name: "Delete personal token by id", - args: []string{"--id", "5c9c1854-45dd-11ee-be56-0242ac120002"}, - mock: func() *httpmock.Registry { - mock := httpmock.Registry{} - mock.Register( - httpmock.REST("DELETE", "iam/personal_tokens/5c9c1854-45dd-11ee-be56-0242ac120002"), - httpmock.StatusStringResponse(204, ""), - ) - return &mock - }, - output: fmt.Sprintf(msg.OutputSuccess, "5c9c1854-45dd-11ee-be56-0242ac120002"), - err: nil, + name: "Delete personal token by ID", + args: []string{"--id", "5c9c1854-45dd-11ee-be56-0242ac120002"}, + method: "DELETE", + endpoint: "iam/personal_tokens/5c9c1854-45dd-11ee-be56-0242ac120002", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.OutputSuccess, "5c9c1854-45dd-11ee-be56-0242ac120002"), + expectError: false, + mockInputs: mockTokenID, + mockError: nil, + }, + { + name: "Delete personal token not found", + args: []string{"--id", "5c9c1854-45dd-11ee-be56-0242ac120002"}, + method: "DELETE", + endpoint: "iam/personal_tokens/5c9c1854-45dd-11ee-be56-0242ac120002", + statusCode: 404, + responseBody: "Not Found", + expectError: true, + mockInputs: mockTokenID, + mockError: fmt.Errorf(msg.ErrorFailToDelete.Error(), utils.ErrorNotFound404), }, { - name: "Delete personal tokens that is not found", - args: []string{"--id", "5c9c1854-45dd-11ee-be56-0242ac120002"}, - mock: func() *httpmock.Registry { - mock := httpmock.Registry{} - mock.Register( - httpmock.REST("DELETE", "iam/personal_tokens/5c9c1854-45dd-11ee-be56-0242ac120002"), - httpmock.StatusStringResponse(404, "Not Found"), - ) - return &mock - }, - err: fmt.Errorf(msg.ErrorFailToDelete.Error(), utils.ErrorNotFound404), + name: "error - parse answer", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf(utils.ErrorParseResponse.Error()), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - f, out, _ := testutils.NewFactory(tt.mock()) + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) - cmd := NewCmd(f) - cmd.SetArgs(tt.args) - _, err := cmd.ExecuteC() + f, stdout, _ := testutils.NewFactory(mock) - if err != nil && !(err.Error() == tt.err.Error()) { - t.Errorf("Executec() err = %v, \nexpected %v", err, tt.args) - } + // Create your delete command instance (adjust as per your package structure) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs - assert.Equal(t, tt.output, out.String()) + // Create your Cobra command instance (adjust as per your package structure) + cobraCmd := NewCobraCmd(deleteCmd, f) + + cobraCmd.SetArgs(tt.args) + + // Execute the command and capture any error + _, err := cobraCmd.ExecuteC() + + if tt.expectError { + require.Error(t, err) + assert.EqualError(t, err, tt.mockError.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + } }) } } From 5b62783e5e2fc22511806b3fa47d83e2e5fe8f28 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:22:18 -0300 Subject: [PATCH 11/33] tests: add unit tests for delete rules engine --- pkg/cmd/delete/rules_engine/rules_engine.go | 84 +++++--- .../delete/rules_engine/rules_engine_test.go | 183 ++++++++++++++---- 2 files changed, 202 insertions(+), 65 deletions(-) diff --git a/pkg/cmd/delete/rules_engine/rules_engine.go b/pkg/cmd/delete/rules_engine/rules_engine.go index 07e594676..8c027ab23 100644 --- a/pkg/cmd/delete/rules_engine/rules_engine.go +++ b/pkg/cmd/delete/rules_engine/rules_engine.go @@ -9,6 +9,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/delete/rules_engine" api "github.com/aziontech/azion-cli/pkg/api/rules_engine" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -16,86 +17,105 @@ import ( "go.uber.org/zap" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var rule_id int64 - var app_id int64 - var phase string - cmd := &cobra.Command{ +var ( + ruleID int64 + applicationID int64 + phase string +) + +type DeleteCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteRule func(context.Context, int64, int64, string) error + AskInput func(string) (string, error) +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteRule: func(ctx context.Context, ruleID, appID int64, phase string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, appID, phase, ruleID) + }, + AskInput: utils.AskInput, + } +} + +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.ShortDescription, Long: msg.LongDescription, SilenceUsage: true, SilenceErrors: true, Example: heredoc.Doc(` - $ azion delete rules-engine --rule-id 1234 --application-id 99887766 --phase request - $ azion delete rules-engine - `), + $ azion delete rules-engine --rule-id 1234 --application-id 99887766 --phase request + $ azion delete rules-engine + `), RunE: func(cmd *cobra.Command, args []string) error { - if !cmd.Flags().Changed("rule-id") { + var err error - answer, err := utils.AskInput(msg.AskInputRulesId) + if !cmd.Flags().Changed("rule-id") { + answer, err := delete.AskInput(msg.AskInputRulesId) if err != nil { return err } - num, err := strconv.ParseInt(answer, 10, 64) if err != nil { logger.Debug("Error while converting answer to int64", zap.Error(err)) return msg.ErrorConvertIdRule } - - rule_id = num + ruleID = num } if !cmd.Flags().Changed("application-id") { - - answer, err := utils.AskInput(msg.AskInputApplicationId) + answer, err := delete.AskInput(msg.AskInputApplicationId) if err != nil { return err } - num, err := strconv.ParseInt(answer, 10, 64) if err != nil { logger.Debug("Error while converting answer to int64", zap.Error(err)) - return msg.ErrorConvertIdRule + return msg.ErrorConvertIdApplication } - - app_id = num + applicationID = num } if !cmd.Flags().Changed("phase") { - - answer, err := utils.AskInput(msg.AskInputPhase) + answer, err := delete.AskInput(msg.AskInputPhase) if err != nil { return err } - phase = answer } - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) - ctx := context.Background() - err := client.Delete(ctx, app_id, phase, rule_id) + err = delete.DeleteRule(ctx, ruleID, applicationID, phase) if err != nil { return fmt.Errorf(msg.ErrorFailToDelete.Error(), err) } deleteOut := output.GeneralOutput{ - Msg: fmt.Sprintf(msg.DeleteOutputSuccess, rule_id), + Msg: fmt.Sprintf(msg.DeleteOutputSuccess, ruleID), Out: f.IOStreams.Out, Flags: f.Flags, } return output.Print(&deleteOut) - }, } - cmd.Flags().Int64Var(&rule_id, "rule-id", 0, msg.FlagRuleID) - cmd.Flags().Int64Var(&app_id, "application-id", 0, msg.FlagAppID) - cmd.Flags().StringVar(&phase, "phase", "", msg.FlagPhase) - cmd.Flags().BoolP("help", "h", false, msg.HelpFlag) + cobraCmd.Flags().Int64Var(&ruleID, "rule-id", 0, msg.FlagRuleID) + cobraCmd.Flags().Int64Var(&applicationID, "application-id", 0, msg.FlagAppID) + cobraCmd.Flags().StringVar(&phase, "phase", "", msg.FlagPhase) + cobraCmd.Flags().BoolP("help", "h", false, msg.HelpFlag) - return cmd + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/rules_engine/rules_engine_test.go b/pkg/cmd/delete/rules_engine/rules_engine_test.go index ff1dfe29c..f2c51b066 100644 --- a/pkg/cmd/delete/rules_engine/rules_engine_test.go +++ b/pkg/cmd/delete/rules_engine/rules_engine_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/aziontech/azion-cli/pkg/logger" + "go.uber.org/zap" "go.uber.org/zap/zapcore" msg "github.com/aziontech/azion-cli/messages/delete/rules_engine" @@ -14,38 +15,154 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreate(t *testing.T) { +func mockAppID(msg string) (string, error) { + return "4321", nil +} + +func mockRuleID(msg string) (string, error) { + return "1234", nil +} + +func mockPhase(msg string) (string, error) { + return "request", nil +} + +func mockInvalid(msg string) (string, error) { + return "invalid", nil +} + +func TestDeleteWithAskInput(t *testing.T) { logger.New(zapcore.DebugLevel) - t.Run("delete rules engine with success", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/4321/rules_engine/request/rules/1234"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "4321", "--phase", "request", "--rule-id", "1234"}) - - _, err := cmd.ExecuteC() - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf(msg.DeleteOutputSuccess, 1234), stdout.String()) - }) - - t.Run("delete rules engine that is not found", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/4321/rules_engine/request/rules/1234"), - httpmock.StatusStringResponse(404, "Not Found"), - ) - - f, _, _ := testutils.NewFactory(mock) - cmd := NewCmd(f) - cmd.SetArgs([]string{"--rule-id", "1234", "--application-id", "4321", "--phase", "response"}) - - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + + tests := []struct { + name string + applicationID string + ruleID string + phase string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(msg string) (string, error) + mockError error + }{ + { + name: "ask for application id and rule id success", + applicationID: "4321", + ruleID: "1234", + phase: "request", + method: "DELETE", + endpoint: "edge_applications/4321/rules_engine/request/rules/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 1234), + expectError: false, + mockInputs: mockAppID, + mockError: nil, + }, + { + name: "ask for rule id success", + phase: "request", + applicationID: "4321", + method: "DELETE", + endpoint: "edge_applications/4321/rules_engine/request/rules/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 1234), + expectError: false, + mockInputs: mockRuleID, + mockError: nil, + }, + { + name: "ask for phase success", + applicationID: "4321", + ruleID: "1234", + method: "DELETE", + endpoint: "edge_applications/4321/rules_engine/request/rules/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, 1234), + expectError: false, + mockInputs: mockPhase, + mockError: nil, + }, + { + name: "error in input", + applicationID: "invalid", + ruleID: "1234", + phase: "request", + method: "DELETE", + endpoint: "edge_applications/invalid/rules_engine/request/rules/1234", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--application-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + { + name: "error in input", + phase: "request", + ruleID: "1234", + method: "DELETE", + endpoint: "edge_applications/invalid/rules_engine/request/rules/1234", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--application-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + // Create your delete command instance (adjust as per your package structure) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs + + // Create your Cobra command instance (adjust as per your package structure) + cobraCmd := NewCobraCmd(deleteCmd, f) + + // Set command line arguments based on test case + if tt.applicationID != "" && tt.ruleID != "" && tt.phase != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID, "--rule-id", tt.ruleID, "--phase", tt.phase}) + } else if tt.applicationID != "" && tt.ruleID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID, "--rule-id", tt.ruleID}) + } else if tt.applicationID != "" && tt.phase != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID, "--phase", tt.phase}) + } else if tt.ruleID != "" && tt.phase != "" { + cobraCmd.SetArgs([]string{"--rule-id", tt.ruleID, "--phase", tt.phase}) + } else if tt.applicationID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID}) + } else if tt.ruleID != "" { + cobraCmd.SetArgs([]string{"--rule-id", tt.ruleID}) + } else if tt.phase != "" { + cobraCmd.SetArgs([]string{"--phase", tt.phase}) + } + + // Execute the command + _, err := cobraCmd.ExecuteC() + + // Validate the results + if tt.expectError { + require.Error(t, err) + logger.Debug("Expected error occurred", zap.Error(err)) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + logger.Debug("Expected output", zap.String("output", stdout.String())) + } + }) + } } From dfc8ead4494bf2deb0a2203517a032b94492ab04 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:44:57 -0300 Subject: [PATCH 12/33] tests: add unit tests for delete variables --- pkg/cmd/delete/variables/variables.go | 59 +++++++--- pkg/cmd/delete/variables/variables_test.go | 126 ++++++++++++++++----- 2 files changed, 139 insertions(+), 46 deletions(-) diff --git a/pkg/cmd/delete/variables/variables.go b/pkg/cmd/delete/variables/variables.go index b6e779681..c031e7be4 100644 --- a/pkg/cmd/delete/variables/variables.go +++ b/pkg/cmd/delete/variables/variables.go @@ -8,6 +8,7 @@ import ( msg "github.com/aziontech/azion-cli/messages/variables" api "github.com/aziontech/azion-cli/pkg/api/variables" "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" @@ -15,35 +16,56 @@ import ( "go.uber.org/zap" ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - var variableID string +var ( + variableID string +) + +type DeleteCmd struct { + Io *iostreams.IOStreams + AskInput func(string) (string, error) + Delete func(context.Context, string) error +} + +func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { + return &DeleteCmd{ + Io: f.IOStreams, + AskInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + Delete: func(ctx context.Context, id string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + return client.Delete(ctx, id) + }, + } +} - deleteCmd := &cobra.Command{ +func NewCobraCmd(delete *DeleteCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.DeleteShortDescription, Long: msg.DeleteLongDescription, SilenceErrors: true, SilenceUsage: true, Example: heredoc.Doc(` - $ azion delete variables -h - $ azion delete variables - $ azion delete variables --variable-id 7a187044-4a00-4a4a-93ed-d230900421f3 + $ azion delete variables -h + $ azion delete variables + $ azion delete variables --variable-id 7a187044-4a00-4a4a-93ed-d230900421f3 `), - RunE: func(cmd *cobra.Command, args []string) error { - if !cmd.Flags().Changed("variable-id") { - answers, err := utils.AskInput(msg.AskVariableID) + var err error + if !cmd.Flags().Changed("variable-id") { + answer, err := delete.AskInput(msg.AskVariableID) if err != nil { logger.Debug("Error while parsing answer", zap.Error(err)) return utils.ErrorParseResponse } - - variableID = answers + variableID = answer } - client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) - err := client.Delete(context.Background(), variableID) + ctx := context.Background() + + err = delete.Delete(ctx, variableID) if err != nil { return fmt.Errorf(msg.ErrorFailToDeleteVariable.Error(), err) } @@ -54,12 +76,15 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { Flags: f.Flags, } return output.Print(&deleteOut) - }, } - deleteCmd.Flags().StringVar(&variableID, "variable-id", "", msg.FlagVariableID) - deleteCmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) + cobraCmd.Flags().StringVar(&variableID, "variable-id", "", msg.FlagVariableID) + cobraCmd.Flags().BoolP("help", "h", false, msg.DeleteHelpFlag) - return deleteCmd + return cobraCmd +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewDeleteCmd(f), f) } diff --git a/pkg/cmd/delete/variables/variables_test.go b/pkg/cmd/delete/variables/variables_test.go index 1984ffcf1..50c7640ef 100644 --- a/pkg/cmd/delete/variables/variables_test.go +++ b/pkg/cmd/delete/variables/variables_test.go @@ -7,49 +7,117 @@ import ( "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" "go.uber.org/zap/zapcore" msg "github.com/aziontech/azion-cli/messages/variables" ) -func TestCreate(t *testing.T) { - logger.New(zapcore.DebugLevel) - t.Run("delete variable by id", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "variables/7a187044-4a00-4a4a-93ed-d230900421f3"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) +func mockVariableID(msg string) (string, error) { + return "7a187044-4a00-4a4a-93ed-d230900421f3", nil +} - cmd := NewCmd(f) - cmd.SetArgs([]string{"--variable-id", "7a187044-4a00-4a4a-93ed-d230900421f3"}) +func mockParse(msg string) (string, error) { + return "7a187044-4a00-4a4a-93ed-d230900421f3", utils.ErrorParseResponse +} +func TestDeleteWithAskInput(t *testing.T) { + logger.New(zapcore.DebugLevel) - _, err := cmd.ExecuteC() - require.NoError(t, err) + tests := []struct { + name string + variableID string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(msg string) (string, error) + mockError error + }{ + { + name: "delete variable by id success", + variableID: "7a187044-4a00-4a4a-93ed-d230900421f3", + method: "DELETE", + endpoint: "variables/7a187044-4a00-4a4a-93ed-d230900421f3", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.DeleteOutputSuccess, "7a187044-4a00-4a4a-93ed-d230900421f3"), + expectError: false, + mockError: nil, + }, + { + name: "delete variable not found", + variableID: "7a187044-4a00-4a4a-93ed-d230900421f3", + method: "DELETE", + endpoint: "variables/7a187044-4a00-4a4a-93ed-d230900421f3", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockError: nil, + }, + { + name: "delete variable ask id", + method: "DELETE", + endpoint: "variables/7a187044-4a00-4a4a-93ed-d230900421f3", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockInputs: mockVariableID, + mockError: nil, + }, + { + name: "delete variable ask id error parse", + method: "DELETE", + endpoint: "variables/7a187044-4a00-4a4a-93ed-d230900421f3", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockInputs: mockParse, + mockError: utils.ErrorParseResponse, + }, + } - assert.Equal(t, fmt.Sprintf(msg.DeleteOutputSuccess, "7a187044-4a00-4a4a-93ed-d230900421f3"), stdout.String()) - }) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) - t.Run("delete variable that is not found", func(t *testing.T) { - mock := &httpmock.Registry{} + f, stdout, _ := testutils.NewFactory(mock) - mock.Register( - httpmock.REST("DELETE", "variables/7a187044-4a00-4a4a-93ed-d230900421f3"), - httpmock.StatusStringResponse(404, "Not Found"), - ) + // Create your delete command instance (adjust as per your package structure) + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs - f, _, _ := testutils.NewFactory(mock) + // Create your Cobra command instance (adjust as per your package structure) + cobraCmd := NewCobraCmd(deleteCmd, f) - cmd := NewCmd(f) + if tt.variableID != "" { + // Set command line arguments based on test case + cobraCmd.SetArgs([]string{"--variable-id", tt.variableID}) + } - cmd.SetArgs([]string{"--variable-id", "7a187044-4a00-4a4a-93ed-d230900421f3"}) + // Execute the command + _, err := cobraCmd.ExecuteC() - _, err := cmd.ExecuteC() - require.Error(t, err) - }) + // Validate the results + if tt.expectError { + require.Error(t, err) + logger.Debug("Expected error occurred", zap.Error(err)) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + logger.Debug("Expected output", zap.String("output", stdout.String())) + } + }) + } } From b93f348a7c6a351c11dcb74f9dc11100eb946f40 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:26:38 -0300 Subject: [PATCH 13/33] tests: add unit tests for delete edge-storage --- .../edge_application/edge_application.go | 18 +- .../edge_application/edge_application_test.go | 173 +++++++++++++----- pkg/cmd/delete/edge_storage/bucket.go | 105 ----------- pkg/cmd/delete/edge_storage/bucket/bucket.go | 140 ++++++++++++++ .../delete/edge_storage/bucket/bucket_test.go | 114 ++++++++++++ pkg/cmd/delete/edge_storage/bucket_test.go | 73 -------- pkg/cmd/delete/edge_storage/edge_storage.go | 6 +- pkg/cmd/delete/edge_storage/models.go | 15 -- pkg/cmd/delete/edge_storage/object.go | 72 -------- pkg/cmd/delete/edge_storage/object/object.go | 99 ++++++++++ .../edge_storage/{ => object}/object_test.go | 45 ++++- 11 files changed, 523 insertions(+), 337 deletions(-) delete mode 100644 pkg/cmd/delete/edge_storage/bucket.go create mode 100644 pkg/cmd/delete/edge_storage/bucket/bucket.go create mode 100644 pkg/cmd/delete/edge_storage/bucket/bucket_test.go delete mode 100644 pkg/cmd/delete/edge_storage/bucket_test.go delete mode 100644 pkg/cmd/delete/edge_storage/models.go delete mode 100644 pkg/cmd/delete/edge_storage/object.go create mode 100644 pkg/cmd/delete/edge_storage/object/object.go rename pkg/cmd/delete/edge_storage/{ => object}/object_test.go (71%) diff --git a/pkg/cmd/delete/edge_application/edge_application.go b/pkg/cmd/delete/edge_application/edge_application.go index d4b240d87..c265fa53b 100644 --- a/pkg/cmd/delete/edge_application/edge_application.go +++ b/pkg/cmd/delete/edge_application/edge_application.go @@ -6,7 +6,6 @@ import ( "os" "strconv" - "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/delete/edge_application" app "github.com/aziontech/azion-cli/pkg/api/edge_applications" @@ -29,6 +28,7 @@ type DeleteCmd struct { f *cmdutil.Factory UpdateJson func(cmd *DeleteCmd) error Cascade func(ctx context.Context, del *DeleteCmd) error + AskInput func(string) (string, error) } func NewCmd(f *cmdutil.Factory) *cobra.Command { @@ -42,6 +42,7 @@ func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { f: f, UpdateJson: updateAzionJson, Cascade: CascadeDelete, + AskInput: utils.AskInput, } } @@ -82,20 +83,9 @@ func (del *DeleteCmd) run(cmd *cobra.Command, application_id int64) error { } if !cmd.Flags().Changed("application-id") { - qs := []*survey.Question{ - { - Name: "id", - Prompt: &survey.Input{Message: msg.AskInput}, - Validate: survey.Required, - }, - } - - answer := "" - - err := survey.Ask(qs, &answer) + answer, err := del.AskInput(msg.AskInput) if err != nil { - logger.Debug("Error while parsing answer", zap.Error(err)) - return utils.ErrorParseResponse + return err } num, err := strconv.ParseInt(answer, 10, 64) diff --git a/pkg/cmd/delete/edge_application/edge_application_test.go b/pkg/cmd/delete/edge_application/edge_application_test.go index 5d5d627f5..551fb0d6b 100644 --- a/pkg/cmd/delete/edge_application/edge_application_test.go +++ b/pkg/cmd/delete/edge_application/edge_application_test.go @@ -18,58 +18,139 @@ import ( msg "github.com/aziontech/azion-cli/messages/delete/edge_application" ) -func TestCreate(t *testing.T) { - logger.New(zapcore.DebugLevel) - t.Run("delete application by id", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/1234"), - httpmock.StatusStringResponse(204, ""), - ) - - f, stdout, _ := testutils.NewFactory(mock) - - cmd := NewCmd(f) - cmd.SetArgs([]string{"--application-id", "1234"}) - - _, err := cmd.ExecuteC() - require.NoError(t, err) - - assert.Equal(t, fmt.Sprintf(msg.OutputSuccess, 1234), stdout.String()) - - }) - - t.Run("delete application - not found", func(t *testing.T) { - mock := &httpmock.Registry{} - - mock.Register( - httpmock.REST("DELETE", "edge_applications/1234"), - httpmock.StatusStringResponse(404, "Not Found"), - ) - - f, _, _ := testutils.NewFactory(mock) - - cmd := NewCmd(f) - - cmd.SetArgs([]string{"--application-id", "1234"}) +func mockApplicationID(msg string) (string, error) { + return "1234", nil +} - _, err := cmd.ExecuteC() - require.Error(t, err) - }) +func mockInvalid(msg string) (string, error) { + return "invalid", nil +} - t.Run("delete cascade with no azion.json file", func(t *testing.T) { - mock := &httpmock.Registry{} +func mockParseError(msg string) (string, error) { + return "invalid", fmt.Errorf("error parsing input") +} - f, _, _ := testutils.NewFactory(mock) +func TestDeleteWithAskInput(t *testing.T) { + logger.New(zapcore.DebugLevel) - cmd := NewCmd(f) + tests := []struct { + name string + applicationID string + method string + endpoint string + statusCode int + responseBody string + expectedOutput string + expectError bool + mockInputs func(string) (string, error) + mockError error + }{ + { + name: "delete application by id", + applicationID: "1234", + method: "DELETE", + endpoint: "edge_applications/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.OutputSuccess, 1234), + expectError: false, + mockInputs: mockApplicationID, + mockError: nil, + }, + { + name: "delete application - not found", + applicationID: "1234", + method: "DELETE", + endpoint: "edge_applications/1234", + statusCode: 404, + responseBody: "Not Found", + expectedOutput: "", + expectError: true, + mockInputs: mockApplicationID, + mockError: fmt.Errorf("Failed to parse your response. Check your response and try again. If the error persists, contact Azion support"), + }, + { + name: "error in input", + applicationID: "1234", + method: "DELETE", + endpoint: "edge_applications/invalid", + statusCode: 400, + responseBody: "Bad Request", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf("invalid argument \"\" for \"--application-id\" flag: strconv.ParseInt: parsing \"\": invalid syntax"), + }, + { + name: "ask for application id success", + applicationID: "", + method: "DELETE", + endpoint: "edge_applications/1234", + statusCode: 204, + responseBody: "", + expectedOutput: fmt.Sprintf(msg.OutputSuccess, 1234), + expectError: false, + mockInputs: mockApplicationID, + mockError: nil, + }, + { + name: "ask for application id conversion failure", + applicationID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockInvalid, + mockError: fmt.Errorf(msg.ErrorConvertId.Error()), + }, + { + name: "error - parse answer", + applicationID: "", + method: "", + endpoint: "", + statusCode: 0, + responseBody: "", + expectedOutput: "", + expectError: true, + mockInputs: mockParseError, + mockError: fmt.Errorf("error parsing input"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(tt.method, tt.endpoint), + httpmock.StatusStringResponse(tt.statusCode, tt.responseBody), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + deleteCmd := NewDeleteCmd(f) + deleteCmd.AskInput = tt.mockInputs + cobraCmd := NewCobraCmd(deleteCmd) + + if tt.applicationID != "" { + cobraCmd.SetArgs([]string{"--application-id", tt.applicationID}) + } + + _, err := cobraCmd.ExecuteC() + if tt.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedOutput, stdout.String()) + } + }) + } +} - cmd.SetArgs([]string{"--cascade"}) +func TestCascadeDelete(t *testing.T) { + logger.New(zapcore.DebugLevel) - _, err := cmd.ExecuteC() - require.Error(t, err) - }) t.Run("cascade delete application", func(t *testing.T) { mock := &httpmock.Registry{} options := &contracts.AzionApplicationOptions{} diff --git a/pkg/cmd/delete/edge_storage/bucket.go b/pkg/cmd/delete/edge_storage/bucket.go deleted file mode 100644 index 6f9560466..000000000 --- a/pkg/cmd/delete/edge_storage/bucket.go +++ /dev/null @@ -1,105 +0,0 @@ -package edge_storage - -import ( - "context" - "fmt" - - "github.com/MakeNowJust/heredoc" - msg "github.com/aziontech/azion-cli/messages/edge_storage" - api "github.com/aziontech/azion-cli/pkg/api/storage" - "github.com/aziontech/azion-cli/pkg/cmdutil" - "github.com/aziontech/azion-cli/pkg/contracts" - "github.com/aziontech/azion-cli/pkg/logger" - "github.com/aziontech/azion-cli/pkg/output" - "github.com/aziontech/azion-cli/pkg/schedule" - "github.com/aziontech/azion-cli/utils" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func NewBucket(f *cmdutil.Factory) *cobra.Command { - bucket := bucket{ - factory: f, - } - cmd := &cobra.Command{ - Use: msg.USAGE_BUCKET, - Short: msg.SHORT_DESCRIPTION_DELETE_BUCKET, - Long: msg.LONG_DESCRIPTION_DELETE_BUCKET, - SilenceUsage: true, - SilenceErrors: true, - Example: heredoc.Doc(msg.EXAMPLE_DELETE_BUCKET), - RunE: bucket.runE, - } - bucket.addFlags(cmd.Flags()) - return cmd -} - -func (b *bucket) runE(cmd *cobra.Command, _ []string) error { - if !cmd.Flags().Changed("name") { - answer, err := utils.AskInput(msg.ASK_NAME_DELETE_BUCKET) - if err != nil { - return err - } - b.name = answer - } - client := api.NewClient( - b.factory.HttpClient, - b.factory.Config.GetString("storage_url"), - b.factory.Config.GetString("token")) - ctx := context.Background() - err := client.DeleteBucket(ctx, b.name) - if err != nil { - if msg.ERROR_NO_EMPTY_BUCKET == err.Error() { - if !b.force { - if !utils.Confirm(b.factory.GlobalFlagAll, msg.ASK_NOT_EMPTY_BUCKET, false) { - return nil - } - } - logger.FInfo(b.factory.IOStreams.Out, "Delete all objects from bucket\n") - logger.FInfo(b.factory.IOStreams.Out, "Deleting objects...") - if err := deleteAllObjects(client, ctx, b.name, ""); err != nil { - return err - } - err := client.DeleteBucket(ctx, b.name) - if err != nil { - if msg.ERROR_NO_EMPTY_BUCKET == err.Error() { - logger.FInfo(b.factory.IOStreams.Out, "Bucket deletion was scheduled successfully") - return schedule.NewSchedule(b.name, schedule.DELETE_BUCKET) - } else { - return fmt.Errorf(msg.ERROR_DELETE_BUCKET, err.Error()) - } - } - return nil - } - return fmt.Errorf(msg.ERROR_DELETE_BUCKET, err.Error()) - } - deleteOut := output.GeneralOutput{ - Msg: fmt.Sprintf(msg.OUTPUT_DELETE_BUCKET, b.name), - Out: b.factory.IOStreams.Out, - Flags: b.factory.Flags, - } - return output.Print(&deleteOut) -} - -func (f *bucket) addFlags(flags *pflag.FlagSet) { - flags.StringVar(&f.name, "name", "", msg.FLAG_NAME_BUCKET) - flags.BoolVar(&f.force, "force", false, msg.FLAG_FORCE) - flags.BoolP("help", "h", false, msg.FLAG_HELP_DELETE_BUCKET) -} - -func deleteAllObjects(client *api.Client, ctx context.Context, name, continuationToken string) error { - objects, err := client.ListObject(ctx, name, &contracts.ListOptions{ContinuationToken: continuationToken}) - if err != nil { - return err - } - if len(objects.GetResults()) > 0 { - for _, o := range objects.GetResults() { - err := client.DeleteObject(ctx, name, o.GetKey()) - if err != nil { - return err - } - } - return deleteAllObjects(client, ctx, name, continuationToken) - } - return nil -} diff --git a/pkg/cmd/delete/edge_storage/bucket/bucket.go b/pkg/cmd/delete/edge_storage/bucket/bucket.go new file mode 100644 index 000000000..755abca58 --- /dev/null +++ b/pkg/cmd/delete/edge_storage/bucket/bucket.go @@ -0,0 +1,140 @@ +package bucket + +import ( + "context" + "fmt" + + "github.com/MakeNowJust/heredoc" + msg "github.com/aziontech/azion-cli/messages/edge_storage" + api "github.com/aziontech/azion-cli/pkg/api/storage" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/contracts" + "github.com/aziontech/azion-cli/pkg/iostreams" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/output" + "github.com/aziontech/azion-cli/pkg/schedule" + "github.com/aziontech/azion-cli/utils" + "github.com/spf13/cobra" +) + +type DeleteBucketCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteBucket func(context.Context, string) error + AskInput func(string) (string, error) + DeleteAll func(*api.Client, context.Context, string, string) error + ConfirmDelete func(bool, string, bool) bool + PrintOutput func(*output.GeneralOutput) error +} + +var ( + bucketName string + forceDelete bool +) + +func NewDeleteBucketCmd(f *cmdutil.Factory) *DeleteBucketCmd { + return &DeleteBucketCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteBucket: func(ctx context.Context, bucketName string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("storage_url"), f.Config.GetString("token")) + return client.DeleteBucket(ctx, bucketName) + }, + AskInput: utils.AskInput, + DeleteAll: deleteAllObjects, + ConfirmDelete: utils.Confirm, + PrintOutput: func(out *output.GeneralOutput) error { + return output.Print(out) + }, + } +} + +func NewBucketCmd(delete *DeleteBucketCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ + Use: msg.USAGE_BUCKET, + Short: msg.SHORT_DESCRIPTION_DELETE_BUCKET, + Long: msg.LONG_DESCRIPTION_DELETE_BUCKET, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(msg.EXAMPLE_DELETE_BUCKET), + RunE: func(cmd *cobra.Command, args []string) error { + var err error + + if !cmd.Flags().Changed("name") { + answer, err := delete.AskInput(msg.ASK_NAME_DELETE_BUCKET) + if err != nil { + return err + } + bucketName = answer + } + + client := api.NewClient(f.HttpClient, f.Config.GetString("storage_url"), f.Config.GetString("token")) + + ctx := context.Background() + + err = client.DeleteBucket(ctx, bucketName) + if err != nil { + fmt.Println(err.Error()) + if msg.ERROR_NO_EMPTY_BUCKET == err.Error() { + if !forceDelete { + if !delete.ConfirmDelete(f.GlobalFlagAll, msg.ASK_NOT_EMPTY_BUCKET, false) { + return nil + } + } + logger.FInfo(f.IOStreams.Out, "Delete all objects from bucket\n") + logger.FInfo(f.IOStreams.Out, "Deleting objects...") + if err := delete.DeleteAll(client, ctx, bucketName, ""); err != nil { + return err + } + err := client.DeleteBucket(ctx, bucketName) + if err != nil { + if msg.ERROR_NO_EMPTY_BUCKET == err.Error() { + logger.FInfo(f.IOStreams.Out, "Bucket deletion was scheduled successfully") + return schedule.NewSchedule(bucketName, schedule.DELETE_BUCKET) + } else { + return fmt.Errorf(msg.ERROR_DELETE_BUCKET, err.Error()) + } + } + return nil + } + return fmt.Errorf(msg.ERROR_DELETE_BUCKET, err.Error()) + } + + deleteOut := output.GeneralOutput{ + Msg: fmt.Sprintf(msg.OUTPUT_DELETE_BUCKET, bucketName), + Out: f.IOStreams.Out, + Flags: f.Flags, + } + return delete.PrintOutput(&deleteOut) + }, + } + + cobraCmd.Flags().StringVar(&bucketName, "name", "", msg.FLAG_NAME_BUCKET) + cobraCmd.Flags().BoolVar(&forceDelete, "force", false, msg.FLAG_FORCE) + cobraCmd.Flags().BoolP("help", "h", false, msg.FLAG_HELP_DELETE_BUCKET) + + return cobraCmd +} + +func NewBucket(f *cmdutil.Factory) *cobra.Command { + return NewBucketCmd(NewDeleteBucketCmd(f), f) +} + +func deleteAllObjects(client *api.Client, ctx context.Context, name, continuationToken string) error { + objects, err := client.ListObject(ctx, name, &contracts.ListOptions{ContinuationToken: continuationToken}) + if err != nil { + return err + } + if len(objects.GetResults()) > 0 { + for _, o := range objects.GetResults() { + err := client.DeleteObject(ctx, name, o.GetKey()) + if err != nil { + return err + } + } + return deleteAllObjects(client, ctx, name, continuationToken) + } + return nil +} diff --git a/pkg/cmd/delete/edge_storage/bucket/bucket_test.go b/pkg/cmd/delete/edge_storage/bucket/bucket_test.go new file mode 100644 index 000000000..467755991 --- /dev/null +++ b/pkg/cmd/delete/edge_storage/bucket/bucket_test.go @@ -0,0 +1,114 @@ +package bucket + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap/zapcore" + + msg "github.com/aziontech/azion-cli/messages/edge_storage" + api "github.com/aziontech/azion-cli/pkg/api/storage" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" +) + +func mockBucket(msg string) (string, error) { + return "arthur-morgan", nil +} + +func TestNewBucket(t *testing.T) { + logger.New(zapcore.DebugLevel) + + tests := []struct { + name string + requests []httpmock.Matcher + responses []httpmock.Responder + args []string + output string + wantErr bool + Err string + mockInputs func(string) (string, error) + mockDeleteAll func(*api.Client, context.Context, string, string) error + mockConfirmDelete func(bool, string, bool) bool + }{ + { + name: "delete bucket command bucket of the edge-storage", + requests: []httpmock.Matcher{ + httpmock.REST(http.MethodDelete, "v4/storage/buckets/arthur-morgan"), + }, + responses: []httpmock.Responder{ + func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusNoContent, + }, nil + }, + }, + args: []string{"--name", "arthur-morgan"}, + output: fmt.Sprintf(msg.OUTPUT_DELETE_BUCKET, "arthur-morgan"), + }, + { + name: "delete bucket ask for name input", + requests: []httpmock.Matcher{ + httpmock.REST(http.MethodDelete, "v4/storage/buckets/arthur-morgan"), + }, + responses: []httpmock.Responder{ + func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusNoContent, + }, nil + }, + }, + output: fmt.Sprintf(msg.OUTPUT_DELETE_BUCKET, "arthur-morgan"), + mockInputs: mockBucket, + }, + { + name: "failed delete bucket internal error status 500", + requests: []httpmock.Matcher{ + httpmock.REST(http.MethodPost, "v4/storage/buckets/arthur-morgan"), + }, + responses: []httpmock.Responder{ + func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusInternalServerError, + Body: io.NopCloser(bytes.NewBufferString("{}")), + Header: http.Header{"Content-Type": []string{"application/json"}}, + }, nil + }, + }, + args: []string{"--name", "arthur-morgan"}, + Err: fmt.Sprintf(msg.ERROR_DELETE_BUCKET, "The server could not process the request because an internal and unexpected problem occurred. Wait a few seconds and try again. For more information run the command again using the '--debug' flag. If the problem persists, contact Azion’s support"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + for i, req := range tt.requests { + mock.Register(req, tt.responses[i]) + } + + f, out, _ := testutils.NewFactory(mock) + + deleteCmd := NewDeleteBucketCmd(f) + deleteCmd.AskInput = tt.mockInputs + cobraCmd := NewBucketCmd(deleteCmd, f) + + if len(tt.args) > 0 { + cobraCmd.SetArgs(tt.args) + } + if err := cobraCmd.Execute(); err != nil { + if !strings.EqualFold(tt.Err, err.Error()) { + t.Errorf("Error expected: %s got: %s", tt.Err, err.Error()) + } + } else { + assert.Equal(t, tt.output, out.String()) + } + }) + } +} diff --git a/pkg/cmd/delete/edge_storage/bucket_test.go b/pkg/cmd/delete/edge_storage/bucket_test.go deleted file mode 100644 index 0f6efa5e7..000000000 --- a/pkg/cmd/delete/edge_storage/bucket_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package edge_storage - -import ( - "bytes" - "fmt" - "io" - "net/http" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "go.uber.org/zap/zapcore" - - msg "github.com/aziontech/azion-cli/messages/edge_storage" - "github.com/aziontech/azion-cli/pkg/httpmock" - "github.com/aziontech/azion-cli/pkg/logger" - "github.com/aziontech/azion-cli/pkg/testutils" -) - -func TestNewBucket(t *testing.T) { - logger.New(zapcore.DebugLevel) - - tests := []struct { - name string - request httpmock.Matcher - response httpmock.Responder - args []string - output string - wantErr bool - Err string - }{ - { - name: "delete bucket command bucket of the edge-storage", - request: httpmock.REST(http.MethodDelete, "v4/storage/buckets/arthur-morgan"), - response: func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusNoContent, - }, nil - }, - args: []string{"--name", "arthur-morgan"}, - output: fmt.Sprintf(msg.OUTPUT_DELETE_BUCKET, "arthur-morgan"), - }, - { - name: "failed delete bucket internal error status 500", - request: httpmock.REST(http.MethodPost, "v4/storage/buckets/arthur-morgan"), - response: func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusInternalServerError, - Body: io.NopCloser(bytes.NewBufferString("{}")), - Header: http.Header{"Content-Type": []string{"application/json"}}, - }, nil - }, - args: []string{"--name", "arthur-morgan"}, - Err: fmt.Sprintf(msg.ERROR_DELETE_BUCKET, "The server could not process the request because an internal and unexpected problem occurred. Wait a few seconds and try again. For more information run the command again using the '--debug' flag. If the problem persists, contact Azion’s support"), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - mock := &httpmock.Registry{} - mock.Register(tt.request, tt.response) - f, out, _ := testutils.NewFactory(mock) - cmd := NewBucket(f) - cmd.SetArgs(tt.args) - if err := cmd.Execute(); err != nil { - if !strings.EqualFold(tt.Err, err.Error()) { - t.Errorf("Error expected: %s got: %s", tt.Err, err.Error()) - } - } else { - assert.Equal(t, tt.output, out.String()) - } - }) - } -} diff --git a/pkg/cmd/delete/edge_storage/edge_storage.go b/pkg/cmd/delete/edge_storage/edge_storage.go index d40128047..952cd0936 100644 --- a/pkg/cmd/delete/edge_storage/edge_storage.go +++ b/pkg/cmd/delete/edge_storage/edge_storage.go @@ -4,6 +4,8 @@ import ( "github.com/spf13/cobra" msg "github.com/aziontech/azion-cli/messages/edge_storage" + bucketpkg "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_storage/bucket" + objectpkg "github.com/aziontech/azion-cli/pkg/cmd/delete/edge_storage/object" "github.com/aziontech/azion-cli/pkg/cmdutil" ) @@ -20,8 +22,8 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { }, } - cmd.AddCommand(NewBucket(f)) - cmd.AddCommand(NewObject(f)) + cmd.AddCommand(bucketpkg.NewBucket(f)) + cmd.AddCommand(objectpkg.NewObject(f)) cmd.Flags().BoolP("help", "h", false, msg.FLAG_HELP) return cmd } diff --git a/pkg/cmd/delete/edge_storage/models.go b/pkg/cmd/delete/edge_storage/models.go deleted file mode 100644 index 49265160c..000000000 --- a/pkg/cmd/delete/edge_storage/models.go +++ /dev/null @@ -1,15 +0,0 @@ -package edge_storage - -import "github.com/aziontech/azion-cli/pkg/cmdutil" - -type bucket struct { - name string - force bool - factory *cmdutil.Factory -} - -type object struct { - bucketName string - objectKey string - factory *cmdutil.Factory -} diff --git a/pkg/cmd/delete/edge_storage/object.go b/pkg/cmd/delete/edge_storage/object.go deleted file mode 100644 index 1c0bae6d0..000000000 --- a/pkg/cmd/delete/edge_storage/object.go +++ /dev/null @@ -1,72 +0,0 @@ -package edge_storage - -import ( - "context" - "fmt" - - "github.com/MakeNowJust/heredoc" - msg "github.com/aziontech/azion-cli/messages/edge_storage" - api "github.com/aziontech/azion-cli/pkg/api/storage" - "github.com/aziontech/azion-cli/pkg/cmdutil" - "github.com/aziontech/azion-cli/pkg/output" - "github.com/aziontech/azion-cli/utils" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func NewObject(f *cmdutil.Factory) *cobra.Command { - object := object{ - factory: f, - } - cmd := &cobra.Command{ - Use: msg.USAGE_OBJECTS, - Short: msg.SHORT_DESCRIPTION_DELETE_OBJECTS, - Long: msg.LONG_DESCRIPTION_DELETE_OBJECTS, - SilenceUsage: true, - SilenceErrors: true, - Example: heredoc.Doc(msg.EXAMPLE_DELETE_OBJECTS), - RunE: object.runE, - } - object.addFlags(cmd.Flags()) - return cmd -} - -func (b *object) runE(cmd *cobra.Command, _ []string) error { - if !cmd.Flags().Changed("bucket-name") { - answer, err := utils.AskInput(msg.ASK_NAME_CREATE_BUCKET) - if err != nil { - return err - } - b.bucketName = answer - } - if !cmd.Flags().Changed("object-key") { - answer, err := utils.AskInput(msg.ASK_OBJECT_DELETE_OBJECT) - if err != nil { - return err - } - b.objectKey = answer - } - client := api.NewClient( - b.factory.HttpClient, - b.factory.Config.GetString("storage_url"), - b.factory.Config.GetString("token")) - ctx := context.Background() - err := client.DeleteObject(ctx, b.bucketName, b.objectKey) - if err != nil { - return fmt.Errorf(msg.ERROR_DELETE_OBJECT, err.Error()) - } - - deleteOut := output.GeneralOutput{ - Msg: fmt.Sprintf(msg.OUTPUT_DELETE_OBJECT, b.objectKey), - Out: b.factory.IOStreams.Out, - Flags: b.factory.Flags, - } - return output.Print(&deleteOut) - -} - -func (f *object) addFlags(flags *pflag.FlagSet) { - flags.StringVar(&f.bucketName, "bucket-name", "", msg.FLAG_NAME_BUCKET) - flags.StringVar(&f.objectKey, "object-key", "", msg.FLAG_OBJECT_KEY_OBJECT) - flags.BoolP("help", "h", false, msg.FLAG_HELP_DELETE_BUCKET) -} diff --git a/pkg/cmd/delete/edge_storage/object/object.go b/pkg/cmd/delete/edge_storage/object/object.go new file mode 100644 index 000000000..a465b4a1c --- /dev/null +++ b/pkg/cmd/delete/edge_storage/object/object.go @@ -0,0 +1,99 @@ +package object + +import ( + "context" + "fmt" + + "github.com/MakeNowJust/heredoc" + msg "github.com/aziontech/azion-cli/messages/edge_storage" + api "github.com/aziontech/azion-cli/pkg/api/storage" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" + "github.com/aziontech/azion-cli/pkg/output" + "github.com/aziontech/azion-cli/utils" + "github.com/spf13/cobra" +) + +var ( + bucket string + objectKey string +) + +type DeleteObjectCmd struct { + Io *iostreams.IOStreams + ReadInput func(string) (string, error) + DeleteObject func(context.Context, string, string) error + AskInput func(string) (string, error) + PrintOutput func(*output.GeneralOutput) error +} + +func NewDeleteObjectCmd(f *cmdutil.Factory) *DeleteObjectCmd { + return &DeleteObjectCmd{ + Io: f.IOStreams, + ReadInput: func(prompt string) (string, error) { + return utils.AskInput(prompt) + }, + DeleteObject: func(ctx context.Context, bucketName, objectKey string) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("storage_url"), f.Config.GetString("token")) + return client.DeleteObject(ctx, bucketName, objectKey) + }, + AskInput: utils.AskInput, + PrintOutput: func(out *output.GeneralOutput) error { + return output.Print(out) + }, + } +} + +func NewObjectCmd(delete *DeleteObjectCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ + Use: msg.USAGE_OBJECTS, + Short: msg.SHORT_DESCRIPTION_DELETE_OBJECTS, + Long: msg.LONG_DESCRIPTION_DELETE_OBJECTS, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(msg.EXAMPLE_DELETE_OBJECTS), + RunE: func(cmd *cobra.Command, args []string) error { + var err error + + if !cmd.Flags().Changed("bucket-name") { + answer, err := delete.AskInput(msg.ASK_NAME_CREATE_BUCKET) + if err != nil { + return err + } + bucket = answer + } + + if !cmd.Flags().Changed("object-key") { + answer, err := delete.AskInput(msg.ASK_OBJECT_DELETE_OBJECT) + if err != nil { + return err + } + objectKey = answer + } + + ctx := context.Background() + + err = delete.DeleteObject(ctx, bucket, objectKey) + if err != nil { + return fmt.Errorf(msg.ERROR_DELETE_OBJECT, err.Error()) + } + + deleteOut := output.GeneralOutput{ + Msg: fmt.Sprintf(msg.OUTPUT_DELETE_OBJECT, objectKey), + Out: f.IOStreams.Out, + Flags: f.Flags, + } + return delete.PrintOutput(&deleteOut) + }, + } + + cobraCmd.Flags().StringVar(&bucket, "bucket-name", "", msg.FLAG_NAME_BUCKET) + cobraCmd.Flags().StringVar(&objectKey, "object-key", "", msg.FLAG_OBJECT_KEY_OBJECT) + cobraCmd.Flags().BoolP("help", "h", false, msg.FLAG_HELP_DELETE_BUCKET) + + return cobraCmd +} + +func NewObject(f *cmdutil.Factory) *cobra.Command { + return NewObjectCmd(NewDeleteObjectCmd(f), f) +} diff --git a/pkg/cmd/delete/edge_storage/object_test.go b/pkg/cmd/delete/edge_storage/object/object_test.go similarity index 71% rename from pkg/cmd/delete/edge_storage/object_test.go rename to pkg/cmd/delete/edge_storage/object/object_test.go index 12f31f762..e8dbc7ad2 100644 --- a/pkg/cmd/delete/edge_storage/object_test.go +++ b/pkg/cmd/delete/edge_storage/object/object_test.go @@ -1,4 +1,4 @@ -package edge_storage +package object import ( "bytes" @@ -17,17 +17,22 @@ import ( "github.com/aziontech/azion-cli/pkg/testutils" ) +func mockObject(msg string) (string, error) { + return "revolver38", nil +} + func TestNewObject(t *testing.T) { logger.New(zapcore.DebugLevel) tests := []struct { - name string - request httpmock.Matcher - response httpmock.Responder - args []string - output string - wantErr bool - Err string + name string + request httpmock.Matcher + response httpmock.Responder + args []string + output string + wantErr bool + Err string + mockInputs func(string) (string, error) }{ { name: "delete object command - edge-storage", @@ -41,7 +46,7 @@ func TestNewObject(t *testing.T) { output: fmt.Sprintf(msg.OUTPUT_DELETE_OBJECT, "revolver38"), }, { - name: "failed delete bucket internal error status 500", + name: "failed delete object internal error status 500", request: httpmock.REST(http.MethodDelete, "v4/storage/buckets/arthur-morgan/objects/revolver38"), response: func(req *http.Request) (*http.Response, error) { return &http.Response{ @@ -53,14 +58,34 @@ func TestNewObject(t *testing.T) { args: []string{"--bucket-name", "arthur-morgan", "--object-key", "revolver38"}, Err: fmt.Sprintf(msg.ERROR_DELETE_OBJECT, "The server could not process the request because an internal and unexpected problem occurred. Wait a few seconds and try again. For more information run the command again using the '--debug' flag. If the problem persists, contact Azion’s support"), }, + { + name: "delete object ask for input", + request: httpmock.REST(http.MethodDelete, "v4/storage/buckets/arthur-morgan/objects/revolver38"), + response: func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusNoContent, + }, nil + }, + args: []string{"--bucket-name", "arthur-morgan"}, + output: fmt.Sprintf(msg.OUTPUT_DELETE_OBJECT, "revolver38"), + mockInputs: mockObject, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mock := &httpmock.Registry{} + mock.Register(tt.request, tt.response) + f, out, _ := testutils.NewFactory(mock) - cmd := NewObject(f) + + deleteCmd := NewDeleteObjectCmd(f) + if tt.mockInputs != nil { + deleteCmd.AskInput = tt.mockInputs + } + cmd := NewObjectCmd(deleteCmd, f) cmd.SetArgs(tt.args) + if err := cmd.Execute(); err != nil { if !strings.EqualFold(tt.Err, err.Error()) { t.Errorf("Error expected: %s got: %s", tt.Err, err.Error()) From 9525d3cf1fb0affa4466c92fc55aeb3b8fb98e04 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Fri, 5 Jul 2024 09:14:36 -0300 Subject: [PATCH 14/33] chore: update version go and remove workflow cla --- .github/workflows/cla.yml | 38 ---------------------------- .github/workflows/deploy_prod.yml | 2 +- .github/workflows/deploy_stage.yml | 2 +- .github/workflows/generate_docs.yml | 2 +- .github/workflows/package-audit.yaml | 2 +- .github/workflows/test_and_build.yml | 2 +- .github/workflows/test_vulcan.yml | 2 +- go.mod | 2 +- 8 files changed, 7 insertions(+), 45 deletions(-) delete mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml deleted file mode 100644 index 56403861c..000000000 --- a/.github/workflows/cla.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: "CLA Assistant" -on: - issue_comment: - types: [created] - pull_request_target: - types: [opened,closed,synchronize] - -jobs: - CLAssistant: - runs-on: ubuntu-latest - container: - image: ubuntu:18.04 - steps: - - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - # Beta Release - uses: cla-assistant/github-action@v2.1.3-beta - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # the below token should have repo scope and must be manually added by you in the repository's secret - PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_TOKEN }} - with: - path-to-signatures: 'signatures/version1/cla.json' - path-to-document: 'https://github.com/aziontech/azion/blob/main/CLA.md' - # branch should not be protected - branch: 'main' - allowlist: user1,bot* - - #below are the optional inputs - If the optional inputs are not given, then default values will be taken - remote-organization-name: 'aziontech' #enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) - remote-repository-name: 'cla' #enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) - #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' - #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' - #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' - #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' - #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' - #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) - #use-dco-flag: true - If you are using DCO instead of CLA diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml index 1ad87ae21..aef04200e 100644 --- a/.github/workflows/deploy_prod.yml +++ b/.github/workflows/deploy_prod.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 outputs: binver: ${{ steps.binversion.outputs.BIN_VERSION }} env: diff --git a/.github/workflows/deploy_stage.yml b/.github/workflows/deploy_stage.yml index 9e0403c98..fdcfd78c1 100644 --- a/.github/workflows/deploy_stage.yml +++ b/.github/workflows/deploy_stage.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml index 50cfaaa17..9a99a111a 100644 --- a/.github/workflows/generate_docs.yml +++ b/.github/workflows/generate_docs.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/.github/workflows/package-audit.yaml b/.github/workflows/package-audit.yaml index 22b5bb849..b1f3aec2d 100644 --- a/.github/workflows/package-audit.yaml +++ b/.github/workflows/package-audit.yaml @@ -9,7 +9,7 @@ jobs: name: Package Auditor (GoVulnCheck) runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 steps: - name: Checkout Repository uses: actions/checkout@v3 diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 7b61ca980..6c11132fb 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22 + image: golang:1.22.5 steps: - name: Setting GIT diff --git a/.github/workflows/test_vulcan.yml b/.github/workflows/test_vulcan.yml index a4b47dca5..ef27c4cd1 100644 --- a/.github/workflows/test_vulcan.yml +++ b/.github/workflows/test_vulcan.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/go.mod b/go.mod index a84ea6e88..b5a7b6336 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/aziontech/azion-cli -go 1.22.4 +go 1.22.5 require ( github.com/AlecAivazis/survey/v2 v2.3.7 From d3c72a1783b45b647d96eb584b3c643e42e13f52 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:56:42 -0300 Subject: [PATCH 15/33] refactor: update golang version --- .github/workflows/deploy_prod.yml | 2 +- .github/workflows/deploy_stage.yml | 2 +- .github/workflows/generate_docs.yml | 2 +- .github/workflows/package-audit.yaml | 2 +- .github/workflows/test_and_build.yml | 2 +- .github/workflows/test_vulcan.yml | 2 +- Dockerfile | 2 +- Makefile | 2 +- go.mod | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml index 1ad87ae21..aef04200e 100644 --- a/.github/workflows/deploy_prod.yml +++ b/.github/workflows/deploy_prod.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 outputs: binver: ${{ steps.binversion.outputs.BIN_VERSION }} env: diff --git a/.github/workflows/deploy_stage.yml b/.github/workflows/deploy_stage.yml index 9e0403c98..fdcfd78c1 100644 --- a/.github/workflows/deploy_stage.yml +++ b/.github/workflows/deploy_stage.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml index 50cfaaa17..9a99a111a 100644 --- a/.github/workflows/generate_docs.yml +++ b/.github/workflows/generate_docs.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/.github/workflows/package-audit.yaml b/.github/workflows/package-audit.yaml index 22b5bb849..b1f3aec2d 100644 --- a/.github/workflows/package-audit.yaml +++ b/.github/workflows/package-audit.yaml @@ -9,7 +9,7 @@ jobs: name: Package Auditor (GoVulnCheck) runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 steps: - name: Checkout Repository uses: actions/checkout@v3 diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 7f528d739..6c11132fb 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 steps: - name: Setting GIT diff --git a/.github/workflows/test_vulcan.yml b/.github/workflows/test_vulcan.yml index a4b47dca5..ef27c4cd1 100644 --- a/.github/workflows/test_vulcan.yml +++ b/.github/workflows/test_vulcan.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: golang:1.22.4 + image: golang:1.22.5 env: CGO_ENABLED: 0 # Statically linked diff --git a/Dockerfile b/Dockerfile index 6096bbcbc..50f46ec46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22.4 +FROM golang:1.22.5 WORKDIR /go/src/app diff --git a/Makefile b/Makefile index 5a40a8176..fdc864ffb 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL := env PATH=$(PATH) /bin/bash NAME := azion ifeq (, $(GO)) -$(error "No go binary found in your system, please install go 1.22.4 before continuing") +$(error "No go binary found in your system, please install go 1.22.5 before continuing") endif GOPATH ?= $(shell $(GO) env GOPATH) diff --git a/go.mod b/go.mod index aa8418102..8546ce699 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/aziontech/azion-cli -go 1.22.4 +go 1.22.5 require ( github.com/AlecAivazis/survey/v2 v2.3.7 From 8e3ddccde9aaf8f3b0376e19727a936cc1ed8331 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Fri, 5 Jul 2024 11:57:00 -0300 Subject: [PATCH 16/33] chore: add CLA back --- .github/workflows/cla.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 000000000..dd9a3c44b --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,38 @@ +name: "CLA Assistant" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, synchronize] + +jobs: + CLAssistant: + runs-on: ubuntu-latest + container: + image: ubuntu:24.04 + steps: + - name: "CLA Assistant" + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + # Beta Release + uses: cla-assistant/github-action@v2.4.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # the below token should have repo scope and must be manually added by you in the repository's secret + PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_TOKEN }} + with: + path-to-signatures: 'signatures/version1/cla.json' + path-to-document: 'https://github.com/aziontech/azion/blob/main/CLA.md' + # branch should not be protected + branch: 'main' + allowlist: user1,bot* + + #below are the optional inputs - If the optional inputs are not given, then default values will be taken + remote-organization-name: 'aziontech' #enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) + remote-repository-name: 'cla' #enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) + #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' + #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' + #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' + #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' + #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' + #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) + #use-dco-flag: true - If you are using DCO instead of CLA From 1c4b1aeff430ac7ac4982df448a9a34b0ee09dae Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Fri, 5 Jul 2024 12:00:52 -0300 Subject: [PATCH 17/33] docs: add new example to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 10a75eeca..774ff05f5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - Angular - Astro - Hexo +- React - Vite Through it, you can manage all Azion products, create automation using CI/CD scripts or pipelines, provision multiple services that make up your application with a few commands, and also manage your Azion configurations as code. From e090eec5dd4f7ee020a16a908c709f5288842b28 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Fri, 5 Jul 2024 12:01:27 -0300 Subject: [PATCH 18/33] feat: output link --- pkg/cmd/link/link.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cmd/link/link.go b/pkg/cmd/link/link.go index 796f5456f..9e54c0623 100644 --- a/pkg/cmd/link/link.go +++ b/pkg/cmd/link/link.go @@ -130,6 +130,7 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { + logger.Debug("Running link command") err := node.NodeVersion() From 8452b063345071ab193cd89b27700b988436e341 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Fri, 5 Jul 2024 14:01:42 -0300 Subject: [PATCH 19/33] feat: implemented output link for format json --- pkg/cmd/link/link.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/link/link.go b/pkg/cmd/link/link.go index 9e54c0623..60d3107a5 100644 --- a/pkg/cmd/link/link.go +++ b/pkg/cmd/link/link.go @@ -17,6 +17,7 @@ import ( "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/node" + "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" thoth "github.com/aziontech/go-thoth" "github.com/go-git/go-git/v5" @@ -130,9 +131,9 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { - logger.Debug("Running link command") + msgs := []string{} err := node.NodeVersion() if err != nil { return err @@ -196,7 +197,8 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { return err } - logger.FInfo(cmd.Io.Out, msg.WebAppLinkCmdSuccess) + logger.FInfoFlags(cmd.Io.Out, msg.WebAppLinkCmdSuccess, cmd.F.Format, cmd.F.Out) + msgs = append(msgs, msg.WebAppLinkCmdSuccess) //asks if user wants to add files to .gitignore gitignore, err := github.CheckGitignore(info.PathWorkingDir) @@ -208,7 +210,8 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { if err := github.WriteGitignore(info.PathWorkingDir); err != nil { return msg.ErrorWritingGitignore } - logger.FInfo(cmd.Io.Out, msg.WrittenGitignore) + logger.FInfoFlags(cmd.Io.Out, msg.WrittenGitignore, cmd.F.Format, cmd.F.Out) + msgs = append(msgs, msg.WrittenGitignore) } if !info.Auto { @@ -225,7 +228,8 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { return err } } else { - logger.FInfo(cmd.Io.Out, msg.LinkDevCommand) + logger.FInfoFlags(cmd.Io.Out, msg.LinkDevCommand, cmd.F.Format, cmd.F.Out) + msgs = append(msgs, msg.LinkDevCommand) } if cmd.ShouldDevDeploy(info, msg.AskDeploy, false) { @@ -241,14 +245,24 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { return err } } else { - logger.FInfo(cmd.Io.Out, msg.LinkDeployCommand) - logger.FInfo(cmd.Io.Out, fmt.Sprintf(msg.EdgeApplicationsLinkSuccessful, info.Name)) + logger.FInfoFlags(cmd.Io.Out, msg.LinkDeployCommand, cmd.F.Format, cmd.F.Out) + msgs = append(msgs, msg.LinkDeployCommand) + logger.FInfoFlags(cmd.Io.Out, fmt.Sprintf(msg.EdgeApplicationsLinkSuccessful, info.Name), cmd.F.Format, cmd.F.Out) + msgs = append(msgs, fmt.Sprintf(msg.EdgeApplicationsLinkSuccessful, info.Name)) } } } - return nil + initOut := output.SliceOutput{ + GeneralOutput: output.GeneralOutput{ + Out: cmd.F.IOStreams.Out, + Flags: cmd.F.Flags, + }, + Messages: msgs, + } + + return output.Print(&initOut) } func deps(c *cobra.Command, cmd *LinkCmd, info *LinkInfo, m string) error { From 0642e256cc9861e1ae8f0e03263a61066cf6113f Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Fri, 5 Jul 2024 14:01:58 -0300 Subject: [PATCH 20/33] tests: add unit tests for logger package --- pkg/cmd/root/pre_command.go | 2 +- pkg/logger/logger.go | 29 ------ pkg/logger/logger_test.go | 185 ++++++++++++++++++++++++++++++++++-- 3 files changed, 179 insertions(+), 37 deletions(-) diff --git a/pkg/cmd/root/pre_command.go b/pkg/cmd/root/pre_command.go index b18a7d9eb..69117bb32 100644 --- a/pkg/cmd/root/pre_command.go +++ b/pkg/cmd/root/pre_command.go @@ -112,7 +112,7 @@ func checkTokenSent(cmd *cobra.Command, f *cmdutil.Factory, configureToken strin globalSettings = &strToken - logger.LogSuccess(f.IOStreams.Out, fmt.Sprintf(msg.TokenSavedIn, filePath)) + logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.TokenSavedIn, filePath)) logger.FInfo(f.IOStreams.Out, msg.TokenUsedIn+"\n") } diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 700e0e75a..4f7ca7eb8 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -5,7 +5,6 @@ import ( "io" "github.com/aziontech/tablecli" - "github.com/fatih/color" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -109,14 +108,6 @@ func PrintRow(table tablecli.Table, format string, row []string) { } } -func Info(message string, fields ...zap.Field) { - log.Info(message, fields...) -} - -func Fatal(message string, fields ...zap.Field) { - log.Fatal(message, fields...) -} - func Debug(message string, fields ...zap.Field) { log.Debug(message, fields...) } @@ -124,23 +115,3 @@ func Debug(message string, fields ...zap.Field) { func Error(message string, fields ...zap.Field) { log.Error(message, fields...) } - -func LogSuccess(w io.Writer, message string) { - formatSuccess := color.New(color.FgGreen).SprintfFunc() - FInfo(w, formatSuccess("🚀 %s\n", message)) -} - -func LogSuccessBye(w io.Writer, message string) { - formatSuccess := color.New(color.FgBlue).SprintfFunc() - FInfo(w, formatSuccess("👋 %s\n", message)) -} - -func LogWarning(w io.Writer, message string) { - formatWarning := color.New(color.FgYellow).SprintfFunc() - FInfo(w, formatWarning("⚠️ %s\n", message)) -} - -func LogError(w io.Writer, message string) { - formatError := color.New(color.FgRed).SprintfFunc() - FInfo(w, formatError("🐛 %s\n", message)) -} diff --git a/pkg/logger/logger_test.go b/pkg/logger/logger_test.go index 7c79f69ba..642afe11b 100644 --- a/pkg/logger/logger_test.go +++ b/pkg/logger/logger_test.go @@ -2,8 +2,9 @@ package logger import ( "bytes" - "go.uber.org/zap/zapcore" "testing" + + "go.uber.org/zap/zapcore" ) func TestFInfo(t *testing.T) { @@ -11,10 +12,12 @@ func TestFInfo(t *testing.T) { message string } tests := []struct { - name string - args args - wantW string - level zapcore.Level + name string + args args + wantW string + level zapcore.Level + debug bool + silent bool }{ { name: "level debug", @@ -37,14 +40,66 @@ func TestFInfo(t *testing.T) { args: args{ "level error", }, - wantW: "", + wantW: "level error", level: zapcore.ErrorLevel, }, + { + name: "silent mode", + args: args{ + "silent mode", + }, + wantW: "", + level: zapcore.InfoLevel, + silent: true, + }, + { + name: "debug mode", + args: args{ + "debug mode", + }, + wantW: "debug mode", + level: zapcore.InfoLevel, + debug: true, + }, + { + name: "level warning", + args: args{ + "level warning", + }, + wantW: "level warning", + level: zapcore.WarnLevel, + }, + { + name: "level fatal", + args: args{ + "level fatal", + }, + wantW: "level fatal", + level: zapcore.FatalLevel, + }, + { + name: "level panic", + args: args{ + "level panic", + }, + wantW: "level panic", + level: zapcore.PanicLevel, + }, + { + name: "level info with debug mode", + args: args{ + "level info with debug mode", + }, + wantW: "level info with debug mode", + level: zapcore.InfoLevel, + debug: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := &bytes.Buffer{} - New(tt.level) + log := Logger{Debug: tt.debug, Silent: tt.silent} + LogLevel(log) FInfo(w, tt.args.message) if gotW := w.String(); gotW != tt.wantW { t.Errorf("FInfo() = %v, want %v", gotW, tt.wantW) @@ -52,3 +107,119 @@ func TestFInfo(t *testing.T) { }) } } + +func TestError(t *testing.T) { + type args struct { + message string + fields []zapcore.Field + } + tests := []struct { + name string + args args + wantW string + debug bool + silent bool + }{ + { + name: "error message in silent mode", + args: args{ + message: "error message in silent mode", + fields: nil, + }, + wantW: "", + silent: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + w := &bytes.Buffer{} + log := Logger{Debug: tt.debug, Silent: tt.silent} + LogLevel(log) + Error(tt.args.message, tt.args.fields...) + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("Error() = %v, want %v", gotW, tt.wantW) + } + }) + } +} + +func TestDebug(t *testing.T) { + type args struct { + message string + fields []zapcore.Field + } + tests := []struct { + name string + args args + wantW string + debug bool + silent bool + }{ + { + name: "debug message in silent mode", + args: args{ + message: "debug message in silent mode", + fields: nil, + }, + wantW: "", + silent: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + w := &bytes.Buffer{} + log := Logger{Debug: tt.debug, Silent: tt.silent} + LogLevel(log) + Debug(tt.args.message, tt.args.fields...) + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("Debug() = %v, want %v", gotW, tt.wantW) + } + }) + } +} + +func TestFInfoFlags(t *testing.T) { + type args struct { + message string + format string + out string + } + tests := []struct { + name string + args args + wantW string + debug bool + silent bool + }{ + { + name: "info flags with format and output", + args: args{ + message: "info flags with format and output", + format: "yaml", + out: "output", + }, + wantW: "", + }, + { + name: "info flags in silent mode", + args: args{ + message: "info flags in silent mode", + format: "", + out: "", + }, + wantW: "", + silent: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + w := &bytes.Buffer{} + log := Logger{Debug: tt.debug, Silent: tt.silent} + LogLevel(log) + FInfoFlags(w, tt.args.message, tt.args.format, tt.args.out) + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("FInfoFlags() = %v, want %v", gotW, tt.wantW) + } + }) + } +} From 86d22e290c9b570e8e502c8ec007fc478f789859 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Fri, 5 Jul 2024 14:42:49 -0300 Subject: [PATCH 21/33] feat: implemented output build for format json --- pkg/cmd/build/utils.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/build/utils.go b/pkg/cmd/build/utils.go index 6d82974e1..3687dc998 100644 --- a/pkg/cmd/build/utils.go +++ b/pkg/cmd/build/utils.go @@ -5,14 +5,19 @@ import ( msg "github.com/aziontech/azion-cli/messages/build" "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/output" "go.uber.org/zap" ) func runCommand(cmd *BuildCmd, command string) error { - logger.FInfo(cmd.Io.Out, msg.BuildStart) + msgs := []string{} + logger.FInfoFlags(cmd.Io.Out, msg.BuildStart, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.BuildStart) - logger.FInfo(cmd.Io.Out, msg.BuildRunningCmd) - logger.FInfo(cmd.Io.Out, fmt.Sprintf("$ %s\n", command)) + logger.FInfoFlags(cmd.Io.Out, msg.BuildRunningCmd, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.BuildRunningCmd) + logger.FInfoFlags(cmd.Io.Out, fmt.Sprintf("$ %s\n", command), cmd.f.Format, cmd.f.Out) + msgs = append(msgs, fmt.Sprintf("$ %s\n", command)) err := cmd.CommandRunInteractive(cmd.f, command) if err != nil { @@ -20,6 +25,16 @@ func runCommand(cmd *BuildCmd, command string) error { return msg.ErrFailedToRunBuildCommand } - logger.FInfo(cmd.Io.Out, msg.BuildSuccessful) - return nil + logger.FInfoFlags(cmd.Io.Out, msg.BuildSuccessful, cmd.f.Format, cmd.f.Out) + msgs = append(msgs, msg.BuildSuccessful) + + outSlice := output.SliceOutput{ + Messages: msgs, + GeneralOutput: output.GeneralOutput{ + Out: cmd.f.IOStreams.Out, + Flags: cmd.f.Flags, + }, + } + + return output.Print(&outSlice) } From b258753c368898475c496d8cfa43cc1f803484a6 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Mon, 8 Jul 2024 10:04:31 -0300 Subject: [PATCH 22/33] feat: implemented output dev for format json not is compatible --- pkg/cmd/dev/dev.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/cmd/dev/dev.go b/pkg/cmd/dev/dev.go index 538dee008..205ed463d 100644 --- a/pkg/cmd/dev/dev.go +++ b/pkg/cmd/dev/dev.go @@ -10,6 +10,7 @@ import ( "github.com/aziontech/azion-cli/pkg/contracts" "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" "github.com/spf13/cobra" ) @@ -64,6 +65,15 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { func (cmd *DevCmd) Run(f *cmdutil.Factory) error { logger.Debug("Running dev command") + if len(cmd.F.Flags.Format) > 0 { + outGen := output.GeneralOutput{ + Msg: "dev command is not compatible with the format flag", + Out: f.IOStreams.Out, + Flags: f.Flags, + } + return output.Print(&outGen) + } + contract := &contracts.BuildInfo{} if isFirewall { From ae9f8234f88489bc230ac5a65dfe2ed7caea1f34 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:36:08 -0300 Subject: [PATCH 23/33] tests: add unit tests for github package --- pkg/cmd/root/pre_command.go | 4 +- pkg/github/github.go | 45 +++--- pkg/github/github_test.go | 264 ++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+), 17 deletions(-) create mode 100644 pkg/github/github_test.go diff --git a/pkg/cmd/root/pre_command.go b/pkg/cmd/root/pre_command.go index 69117bb32..c47144f34 100644 --- a/pkg/cmd/root/pre_command.go +++ b/pkg/cmd/root/pre_command.go @@ -131,7 +131,9 @@ func checkForUpdateAndMetrics(cVersion string, f *cmdutil.Factory, settings *tok metric.Send(settings) } - tagName, err := github.GetVersionGitHub("azion") + git := github.NewGithub() + + tagName, err := git.GetVersionGitHub("azion") if err != nil { return err } diff --git a/pkg/github/github.go b/pkg/github/github.go index 0033670f8..a07af38cb 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -19,14 +19,36 @@ import ( gitignore "github.com/sabhiram/go-gitignore" ) +type Github struct { + GetVersionGitHub func(name string) (string, error) + Clone func(url, path string) error + GetNameRepo func(url string) string + CheckGitignore func(path string) (bool, error) + WriteGitignore func(path string) error +} + type Release struct { TagName string `json:"tag_name"` } -func GetVersionGitHub(name string) (string, error) { - apiURL := fmt.Sprintf("https://api.github.com/repos/aziontech/%s/releases/latest", name) +var ( + ApiURL string +) + +func NewGithub() *Github { + return &Github{ + GetVersionGitHub: getVersionGitHub, + Clone: clone, + GetNameRepo: getNameRepo, + CheckGitignore: checkGitignore, + WriteGitignore: writeGitignore, + } +} + +func getVersionGitHub(name string) (string, error) { + ApiURL = fmt.Sprintf("https://api.github.com/repos/aziontech/%s/releases/latest", name) - response, err := http.Get(apiURL) + response, err := http.Get(ApiURL) if err != nil { logger.Debug("Failed to get latest version of "+name, zap.Error(err)) return "", err @@ -53,8 +75,7 @@ func GetVersionGitHub(name string) (string, error) { return release.TagName, nil } -// Clone clone the repository using git -func Clone(url, path string) error { +func clone(url, path string) error { _, err := git.PlainClone(path, false, &git.CloneOptions{ URL: url, }) @@ -67,24 +88,19 @@ func Clone(url, path string) error { return nil } -// GetNameRepoFunction to get the repository name from the URL -func GetNameRepo(url string) string { - // Remove the initial part of the URL +func getNameRepo(url string) string { parts := strings.Split(url, "/") repoPart := parts[len(parts)-1] - // Remove the .git folder if it exists. repoPart = strings.TrimSuffix(repoPart, ".git") return repoPart } -func CheckGitignore(path string) (bool, error) { +func checkGitignore(path string) (bool, error) { logger.Debug("Checking .gitignore file for existence of Vulcan files") path = filepath.Join(path, ".gitignore") object, err := gitignore.CompileIgnoreFile(path) if err != nil { - // if the error is "no such file or directory" we can return false and nil for error, because the code that called this func will create - // the .gitignore file if errors.Is(err, os.ErrNotExist) { return false, nil } @@ -98,14 +114,12 @@ func CheckGitignore(path string) (bool, error) { return true, nil } -func WriteGitignore(path string) error { +func writeGitignore(path string) error { logger.Debug("Writing .gitignore file") path = filepath.Join(path, ".gitignore") - // Lines to add to .gitignore linesToAdd := []string{"#Paths added by Azion CLI", ".edge/", ".vulcan"} - // Open the file in append mode, create if not exists file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { logger.Error("Error opening file", zap.Error(err)) @@ -123,7 +137,6 @@ func WriteGitignore(path string) error { } } - // Ensure all data is written to the file if err := writer.Flush(); err != nil { logger.Error("Error flushing writer", zap.Error(err)) return err diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go new file mode 100644 index 000000000..38bb9fb73 --- /dev/null +++ b/pkg/github/github_test.go @@ -0,0 +1,264 @@ +package github + +import ( + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "github.com/aziontech/azion-cli/pkg/logger" + "go.uber.org/zap/zapcore" +) + +func TestGetVersionGitHub(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + repoName string + wantTag string + statusCode int + response string + wantErr bool + }{ + { + name: "not found", + repoName: "test-repo", + wantTag: "", + statusCode: http.StatusNotFound, + response: `{"message": "Not Found"}`, + wantErr: false, + }, + { + name: "successful response", + repoName: "azion-cli", + wantTag: "1.30.0", + statusCode: http.StatusOK, + response: `{"tag_name": "1.30.0"}`, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(tt.statusCode) + w.Write([]byte(tt.response)) + })) + defer server.Close() + + oldURL := ApiURL + ApiURL = server.URL + "/repos/aziontech/%s/releases/tag/1.30.0" + defer func() { ApiURL = oldURL }() + + gh := NewGithub() + gh.GetVersionGitHub = getVersionGitHub + + gotTag, err := gh.GetVersionGitHub(tt.repoName) + if (err != nil) != tt.wantErr { + t.Errorf("GetVersionGitHub() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotTag != tt.wantTag { + t.Errorf("GetVersionGitHub() = %v, want %v", gotTag, tt.wantTag) + } + }) + } +} + +func TestClone(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + url string + wantErr bool + setup func() (string, func()) + }{ + { + name: "invalid url", + url: "invalid-url", + wantErr: true, + setup: func() (string, func()) { + return t.TempDir(), func() {} + }, + }, + { + name: "valid url", + url: "https://github.com/aziontech/azion-cli.git", + setup: func() (string, func()) { + // Create a temporary directory + dir := t.TempDir() + // Return the directory path and a cleanup function + return dir, func() { + // Cleanup steps if needed + os.RemoveAll(dir) + } + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path, cleanup := tt.setup() + defer cleanup() + + gh := NewGithub() + gh.Clone = clone + + if err := gh.Clone(tt.url, path); (err != nil) != tt.wantErr { + t.Errorf("Clone() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetNameRepo(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + url string + want string + }{ + { + name: "with .git", + url: "https://github.com/aziontech/azion-cli.git", + want: "azion-cli", + }, + { + name: "without .git", + url: "https://github.com/aziontech/azion-cli", + want: "azion-cli", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gh := NewGithub() + gh.GetNameRepo = getNameRepo + + if got := gh.GetNameRepo(tt.url); got != tt.want { + t.Errorf("GetNameRepo() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCheckGitignore(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + setup func() string + want bool + wantErr bool + cleanup func(string) + }{ + { + name: "exists", + setup: func() string { + path := t.TempDir() + file := filepath.Join(path, ".gitignore") + os.WriteFile(file, []byte(".edge/\n.vulcan\n"), 0644) + return path + }, + want: true, + wantErr: false, + cleanup: func(path string) { + os.RemoveAll(path) + }, + }, + { + name: "does not exist", + setup: func() string { + return t.TempDir() + }, + want: false, + wantErr: false, + cleanup: func(path string) { + os.RemoveAll(path) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path := tt.setup() + defer tt.cleanup(path) + + gh := NewGithub() + gh.CheckGitignore = checkGitignore + + got, err := gh.CheckGitignore(path) + if (err != nil) != tt.wantErr { + t.Errorf("CheckGitignore() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckGitignore() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestWriteGitignore(t *testing.T) { + logger.New(zapcore.DebugLevel) + tests := []struct { + name string + setup func() string + wantErr bool + wantFile string + cleanup func(string) + }{ + { + name: "success", + setup: func() string { + return t.TempDir() + }, + wantErr: false, + wantFile: "#Paths added by Azion CLI\n.edge/\n.vulcan\n", + cleanup: func(path string) { + os.RemoveAll(path) + }, + }, + { + name: "error opening file", + setup: func() string { + path := t.TempDir() + file := filepath.Join(path, ".gitignore") + os.WriteFile(file, []byte{}, 0444) // Create a read-only file + return path + }, + wantErr: true, + cleanup: func(path string) { + os.Chmod(filepath.Join(path, ".gitignore"), 0644) // Restore permissions before cleanup + os.RemoveAll(path) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path := tt.setup() + defer tt.cleanup(path) + + gh := NewGithub() + gh.WriteGitignore = writeGitignore + + err := gh.WriteGitignore(path) + if (err != nil) != tt.wantErr { + t.Errorf("WriteGitignore() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr { + got, err := os.ReadFile(filepath.Join(path, ".gitignore")) + if err != nil { + t.Errorf("Error reading .gitignore file: %v", err) + return + } + if string(got) != tt.wantFile { + t.Errorf("WriteGitignore() = %v, want %v", string(got), tt.wantFile) + } + } + }) + } +} From a79013e46b869c7ba8c296a69f372dd4a0b98041 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:39:35 -0300 Subject: [PATCH 24/33] chore: use new github structure --- pkg/cmd/init/init.go | 6 ++++-- pkg/cmd/link/link.go | 10 ++++++---- pkg/metric/count.go | 4 +++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/init/init.go b/pkg/cmd/init/init.go index 66988f139..6f4549d53 100644 --- a/pkg/cmd/init/init.go +++ b/pkg/cmd/init/init.go @@ -160,12 +160,14 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { return msg.ErrorWorkingDir } - gitignore, err := github.CheckGitignore(cmd.pathWorkingDir) + git := github.NewGithub() + + gitignore, err := git.CheckGitignore(cmd.pathWorkingDir) if err != nil { return msg.ErrorReadingGitignore } if !gitignore && (cmd.auto || cmd.f.GlobalFlagAll || utils.Confirm(cmd.f.GlobalFlagAll, msg.AskGitignore, true)) { - if err := github.WriteGitignore(cmd.pathWorkingDir); err != nil { + if err := git.WriteGitignore(cmd.pathWorkingDir); err != nil { return msg.ErrorWritingGitignore } logger.FInfoFlags(cmd.f.IOStreams.Out, msg.WrittenGitignore, cmd.f.Format, cmd.f.Out) diff --git a/pkg/cmd/link/link.go b/pkg/cmd/link/link.go index 60d3107a5..7cd718de1 100644 --- a/pkg/cmd/link/link.go +++ b/pkg/cmd/link/link.go @@ -146,15 +146,17 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { } info.PathWorkingDir = path + git := github.NewGithub() + if len(info.remote) > 0 { logger.Debug("flag remote", zap.Any("repository", info.remote)) urlFull, _ := regexp.MatchString(`^https?://(?:www\.)?(?:github\.com|gitlab\.com)/[\w.-]+/[\w.-]+(\.git)?$`, info.remote) if !urlFull { info.remote = fmt.Sprintf("https://github.com/%s.git", info.remote) } - nameRepo := github.GetNameRepo(info.remote) + nameRepo := git.GetNameRepo(info.remote) info.PathWorkingDir = filepath.Join(info.PathWorkingDir, nameRepo) - err = github.Clone(info.remote, filepath.Join(path, nameRepo)) + err = git.Clone(info.remote, filepath.Join(path, nameRepo)) if err != nil { logger.Debug("Error while cloning the repository", zap.Error(err)) return err @@ -201,13 +203,13 @@ func (cmd *LinkCmd) run(c *cobra.Command, info *LinkInfo) error { msgs = append(msgs, msg.WebAppLinkCmdSuccess) //asks if user wants to add files to .gitignore - gitignore, err := github.CheckGitignore(info.PathWorkingDir) + gitignore, err := git.CheckGitignore(info.PathWorkingDir) if err != nil { return msg.ErrorReadingGitignore } if !gitignore && (info.Auto || info.GlobalFlagAll || utils.Confirm(info.GlobalFlagAll, msg.AskGitignore, true)) { - if err := github.WriteGitignore(info.PathWorkingDir); err != nil { + if err := git.WriteGitignore(info.PathWorkingDir); err != nil { return msg.ErrorWritingGitignore } logger.FInfoFlags(cmd.Io.Out, msg.WrittenGitignore, cmd.F.Format, cmd.F.Out) diff --git a/pkg/metric/count.go b/pkg/metric/count.go index 7e1ed5b29..dbf4da304 100644 --- a/pkg/metric/count.go +++ b/pkg/metric/count.go @@ -64,7 +64,9 @@ func TotalCommandsCount(cmd *cobra.Command, commandName string, executionTime fl return err } - tagName, err := github.GetVersionGitHub("vulcan") + git := github.NewGithub() + + tagName, err := git.GetVersionGitHub("vulcan") if err != nil { return err } From 3b418bce7dae7334b23dc4f344eebc686e7bd20a Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:41:01 -0300 Subject: [PATCH 25/33] refactor: add comment back --- pkg/github/github.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/github/github.go b/pkg/github/github.go index a07af38cb..65096ff35 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -101,6 +101,8 @@ func checkGitignore(path string) (bool, error) { object, err := gitignore.CompileIgnoreFile(path) if err != nil { + // if the error is "no such file or directory" we can return false and nil for error, because the code that called this func will create + // the .gitignore file if errors.Is(err, os.ErrNotExist) { return false, nil } From 27cb7065fc6b313b4054553bc1264efe871ee8eb Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:22:36 -0300 Subject: [PATCH 26/33] refactor: update write test --- pkg/github/github_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index 38bb9fb73..2d146c1b9 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -223,15 +223,11 @@ func TestWriteGitignore(t *testing.T) { { name: "error opening file", setup: func() string { - path := t.TempDir() - file := filepath.Join(path, ".gitignore") - os.WriteFile(file, []byte{}, 0444) // Create a read-only file - return path + return "does/not/exist" }, wantErr: true, cleanup: func(path string) { - os.Chmod(filepath.Join(path, ".gitignore"), 0644) // Restore permissions before cleanup - os.RemoveAll(path) + return }, }, } From 2d70fb2351b7c8a9668ceb70f86dc2af4cea15bc Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:30:42 -0300 Subject: [PATCH 27/33] refactor: update write test --- pkg/github/github_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index 2d146c1b9..14d363215 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -158,7 +158,10 @@ func TestCheckGitignore(t *testing.T) { setup: func() string { path := t.TempDir() file := filepath.Join(path, ".gitignore") - os.WriteFile(file, []byte(".edge/\n.vulcan\n"), 0644) + err := os.WriteFile(file, []byte(".edge/\n.vulcan\n"), 0644) + if err != nil { + return err.Error() + } return path }, want: true, @@ -227,7 +230,6 @@ func TestWriteGitignore(t *testing.T) { }, wantErr: true, cleanup: func(path string) { - return }, }, } From 2fe8a9a99f06f8fd4edfd3fb3b40fb53306331ab Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:33:36 -0300 Subject: [PATCH 28/33] refactor: update write test --- pkg/github/github_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index 14d363215..fd6c07aa8 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -43,7 +43,10 @@ func TestGetVersionGitHub(t *testing.T) { t.Run(tt.name, func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, err := w.Write([]byte(tt.response)) + if err != nil { + panic(err) + } })) defer server.Close() From ec7f1c132b6beb8b77224e601e0ec5af40c0e197 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:35:54 -0300 Subject: [PATCH 29/33] refactor: update write test --- pkg/github/github_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/github/github_test.go b/pkg/github/github_test.go index fd6c07aa8..4b3d2849a 100644 --- a/pkg/github/github_test.go +++ b/pkg/github/github_test.go @@ -163,7 +163,7 @@ func TestCheckGitignore(t *testing.T) { file := filepath.Join(path, ".gitignore") err := os.WriteFile(file, []byte(".edge/\n.vulcan\n"), 0644) if err != nil { - return err.Error() + panic(err) } return path }, From 87e4c072404335354cef5dcdea5be33e76e5238e Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Mon, 8 Jul 2024 14:43:59 -0300 Subject: [PATCH 30/33] feat: implemented output command deploy format output --- pkg/cmd/deploy/bucket.go | 14 ++++- pkg/cmd/deploy/deploy.go | 43 +++++++++----- pkg/cmd/deploy/requests.go | 116 +++++++++++++++++++++---------------- pkg/cmd/deploy/upload.go | 9 ++- pkg/cmd/sync/tasks.go | 11 +++- pkg/manifest/manifest.go | 57 +++++++++++++----- 6 files changed, 163 insertions(+), 87 deletions(-) diff --git a/pkg/cmd/deploy/bucket.go b/pkg/cmd/deploy/bucket.go index fe06e6bc5..6c62c856b 100644 --- a/pkg/cmd/deploy/bucket.go +++ b/pkg/cmd/deploy/bucket.go @@ -16,7 +16,11 @@ import ( "github.com/aziontech/azion-cli/utils" ) -func (cmd *DeployCmd) doBucket(client *api.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) doBucket( + client *api.Client, + ctx context.Context, + conf *contracts.AzionApplicationOptions, + msgs *[]string) error { if conf.Bucket != "" || (conf.Preset == "javascript" || conf.Preset == "typescript") { return nil } @@ -30,7 +34,9 @@ func (cmd *DeployCmd) doBucket(client *api.Client, ctx context.Context, conf *co // If the name is already in use, try 10 times with different names for i := 0; i < 10; i++ { nameB := fmt.Sprintf("%s-%s", nameBucket, utils.Timestamp()) - logger.FInfo(cmd.Io.Out, fmt.Sprintf(msg.NameInUseBucket, nameB)) + msgf := fmt.Sprintf(msg.NameInUseBucket, nameB) + logger.FInfoFlags(cmd.Io.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) err := client.CreateBucket(ctx, api.RequestBucket{ BucketCreate: storage.BucketCreate{Name: nameB, EdgeAccess: storage.READ_WRITE}}) if err != nil { @@ -46,7 +52,9 @@ func (cmd *DeployCmd) doBucket(client *api.Client, ctx context.Context, conf *co conf.Bucket = nameBucket } - logger.FInfo(cmd.Io.Out, fmt.Sprintf(msg.BucketSuccessful, conf.Bucket)) + msgf := fmt.Sprintf(msg.BucketSuccessful, conf.Bucket) + logger.FInfoFlags(cmd.Io.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return cmd.WriteAzionJsonContent(conf, ProjectConf) } diff --git a/pkg/cmd/deploy/deploy.go b/pkg/cmd/deploy/deploy.go index 29dee690b..dc044eea1 100644 --- a/pkg/cmd/deploy/deploy.go +++ b/pkg/cmd/deploy/deploy.go @@ -20,6 +20,7 @@ import ( "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" manifestInt "github.com/aziontech/azion-cli/pkg/manifest" + "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/utils" sdk "github.com/aziontech/azionapi-go-sdk/edgeapplications" "github.com/spf13/cobra" @@ -108,6 +109,7 @@ func (cmd *DeployCmd) ExternalRun(f *cmdutil.Factory, configPath string) error { func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { logger.Debug("Running deploy command") + msgs := []string{} ctx := context.Background() err := checkToken(f) @@ -155,17 +157,17 @@ func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { return err } - err = cmd.doApplication(clients.EdgeApplication, context.Background(), conf) + err = cmd.doApplication(clients.EdgeApplication, context.Background(), conf, &msgs) if err != nil { return err } - singleOriginId, err := cmd.doOriginSingle(clients.Origin, ctx, conf) + singleOriginId, err := cmd.doOriginSingle(clients.Origin, ctx, conf, &msgs) if err != nil { return err } - err = cmd.doBucket(clients.Bucket, ctx, conf) + err = cmd.doBucket(clients.Bucket, ctx, conf, &msgs) if err != nil { return err } @@ -174,14 +176,14 @@ func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { if _, err := os.Stat(PathStatic); os.IsNotExist(err) { logger.Debug(msg.SkipUpload) } else { - err = cmd.uploadFiles(f, conf) + err = cmd.uploadFiles(f, conf, &msgs) if err != nil { return err } } conf.Function.File = ".edge/worker.js" - err = cmd.doFunction(clients, ctx, conf) + err = cmd.doFunction(clients, ctx, conf, &msgs) if err != nil { return err } @@ -229,30 +231,45 @@ func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { } } - manifestStructure, err := interpreter.ReadManifest(pathManifest, f) + manifestStructure, err := interpreter.ReadManifest(pathManifest, f, &msgs) if err != nil { return err } if len(conf.RulesEngine.Rules) == 0 { - err = cmd.doRulesDeploy(ctx, conf, clients.EdgeApplication) + err = cmd.doRulesDeploy(ctx, conf, clients.EdgeApplication, &msgs) if err != nil { return err } } - err = interpreter.CreateResources(conf, manifestStructure, f, ProjectConf) + err = interpreter.CreateResources(conf, manifestStructure, f, ProjectConf, &msgs) if err != nil { return err } - err = cmd.doDomain(clients.Domain, ctx, conf) + err = cmd.doDomain(clients.Domain, ctx, conf, &msgs) if err != nil { return err } - logger.FInfo(cmd.F.IOStreams.Out, msg.DeploySuccessful) - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputDomainSuccess, conf.Domain.Url)) - logger.FInfo(cmd.F.IOStreams.Out, msg.DeployPropagation) - return nil + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.DeploySuccessful, f.Format, f.Out) + msgs = append(msgs, msg.DeploySuccessful) + + msgfOutputDomainSuccess := fmt.Sprintf(msg.DeployOutputDomainSuccess, conf.Domain.Url) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgfOutputDomainSuccess, f.Format, f.Out) + msgs = append(msgs, msgfOutputDomainSuccess) + + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.DeployPropagation, f.Format, f.Out) + msgs = append(msgs, msg.DeployPropagation) + + outSlice := output.SliceOutput{ + Messages: msgs, + GeneralOutput: output.GeneralOutput{ + Out: cmd.F.IOStreams.Out, + Flags: cmd.F.Flags, + }, + } + + return output.Print(&outSlice) } diff --git a/pkg/cmd/deploy/requests.go b/pkg/cmd/deploy/requests.go index 91c56b775..a376e40b8 100644 --- a/pkg/cmd/deploy/requests.go +++ b/pkg/cmd/deploy/requests.go @@ -35,14 +35,14 @@ var injectIntoFunction = ` ` -func (cmd *DeployCmd) doFunction(clients *Clients, ctx context.Context, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) doFunction(clients *Clients, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) error { if conf.Function.ID == 0 { var projName string - functionId, err := cmd.createFunction(clients.EdgeFunction, ctx, conf) + functionId, err := cmd.createFunction(clients.EdgeFunction, ctx, conf, msgs) if err != nil { for i := 0; i < 10; i++ { projName = fmt.Sprintf("%s-%s", conf.Function.Name, utils.Timestamp()) - functionId, err := cmd.createFunction(clients.EdgeFunction, ctx, conf) + functionId, err := cmd.createFunction(clients.EdgeFunction, ctx, conf, msgs) if err != nil { if errors.Is(err, utils.ErrorNameInUse) && i < 9 { continue @@ -68,7 +68,8 @@ func (cmd *DeployCmd) doFunction(clients *Clients, ctx context.Context, conf *co if err != nil { // if the name is already in use, we ask for another one if errors.Is(err, utils.ErrorNameInUse) { - logger.FInfo(cmd.Io.Out, msg.FuncInstInUse) + logger.FInfoFlags(cmd.Io.Out, msg.FuncInstInUse, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.FuncInstInUse) if Auto { projName = thoth.GenerateName() } else { @@ -94,7 +95,7 @@ func (cmd *DeployCmd) doFunction(clients *Clients, ctx context.Context, conf *co return nil } - _, err := cmd.updateFunction(clients.EdgeFunction, ctx, conf) + _, err := cmd.updateFunction(clients.EdgeFunction, ctx, conf, msgs) if err != nil { return err } @@ -107,21 +108,28 @@ func (cmd *DeployCmd) doFunction(clients *Clients, ctx context.Context, conf *co return nil } -func (cmd *DeployCmd) doApplication(client *apiapp.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) doApplication( + client *apiapp.Client, + ctx context.Context, + conf *contracts.AzionApplicationOptions, + msgs *[]string) error { if conf.Application.ID == 0 { var projName string for { - applicationId, err := cmd.createApplication(client, ctx, conf) + applicationId, err := cmd.createApplication(client, ctx, conf, msgs) if err != nil { // if the name is already in use, we ask for another one if strings.Contains(err.Error(), utils.ErrorNameInUse.Error()) { if NoPrompt { return err } - logger.FInfo(cmd.Io.Out, msg.AppInUse) + logger.FInfoFlags(cmd.Io.Out, msg.AppInUse, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.AppInUse) if Auto { projName = fmt.Sprintf("%s-%s", conf.Name, utils.Timestamp()) - logger.FInfo(cmd.Io.Out, fmt.Sprintf(msg.NameInUseApplication, projName)) + msgf := fmt.Sprintf(msg.NameInUseApplication, projName) + logger.FInfoFlags(cmd.Io.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) } else { projName, err = askForInput(msg.AskInputName, thoth.GenerateName()) if err != nil { @@ -143,7 +151,7 @@ func (cmd *DeployCmd) doApplication(client *apiapp.Client, ctx context.Context, return err } } else { - err := cmd.updateApplication(client, ctx, conf) + err := cmd.updateApplication(client, ctx, conf, msgs) if err != nil { logger.Debug("Error while updating Edge Application", zap.Error(err)) return err @@ -152,7 +160,7 @@ func (cmd *DeployCmd) doApplication(client *apiapp.Client, ctx context.Context, return nil } -func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) error { var domain apidom.DomainResponse var err error @@ -160,17 +168,20 @@ func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf if conf.Domain.Id == 0 { var projName string for { - domain, err = cmd.createDomain(client, ctx, conf) + domain, err = cmd.createDomain(client, ctx, conf, msgs) if err != nil { // if the name is already in use, we ask for another one if strings.Contains(err.Error(), utils.ErrorNameInUse.Error()) { if NoPrompt { return err } - logger.FInfo(cmd.Io.Out, msg.DomainInUse) + logger.FInfoFlags(cmd.Io.Out, msg.DomainInUse, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.DomainInUse) if Auto { projName = fmt.Sprintf("%s-%s", conf.Name, utils.Timestamp()) - logger.FInfo(cmd.Io.Out, fmt.Sprintf(msg.NameInUseApplication, projName)) + msgf := fmt.Sprintf(msg.NameInUseApplication, projName) + logger.FInfoFlags(cmd.Io.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) projName = thoth.GenerateName() } else { projName, err = askForInput(msg.AskInputName, thoth.GenerateName()) @@ -198,7 +209,7 @@ func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf } } else { - domain, err = cmd.updateDomain(client, ctx, conf) + domain, err = cmd.updateDomain(client, ctx, conf, msgs) if err != nil { logger.Debug("Error while updating domain", zap.Error(err)) return err @@ -216,7 +227,11 @@ func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf return nil } -func (cmd *DeployCmd) doRulesDeploy(ctx context.Context, conf *contracts.AzionApplicationOptions, client *apiapp.Client) error { +func (cmd *DeployCmd) doRulesDeploy( + ctx context.Context, + conf *contracts.AzionApplicationOptions, + client *apiapp.Client, + msgs *[]string) error { if conf.NotFirstRun { return nil } @@ -238,7 +253,8 @@ func (cmd *DeployCmd) doRulesDeploy(ctx context.Context, conf *contracts.AzionAp logger.Debug("Error while creating Cache Settings", zap.Error(err)) return err } - logger.FInfo(cmd.F.IOStreams.Out, msg.CacheSettingsSuccessful) + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.CacheSettingsSuccessful, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.CacheSettingsSuccessful) cacheId = cache.GetId() } @@ -253,7 +269,11 @@ func (cmd *DeployCmd) doRulesDeploy(ctx context.Context, conf *contracts.AzionAp return nil } -func (cmd *DeployCmd) doOriginSingle(clientOrigin *apiori.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (int64, error) { +func (cmd *DeployCmd) doOriginSingle( + clientOrigin *apiori.Client, + ctx context.Context, + conf *contracts.AzionApplicationOptions, + msgs *[]string) (int64, error) { var DefaultOrigin = [1]string{"httpbin.org"} if conf.NotFirstRun { @@ -272,7 +292,8 @@ func (cmd *DeployCmd) doOriginSingle(clientOrigin *apiori.Client, ctx context.Co logger.Debug("Error while creating default origin ", zap.Any("Error", err)) return 0, err } - logger.FInfo(cmd.F.IOStreams.Out, msg.OriginsSuccessful) + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.OriginsSuccessful, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.OriginsSuccessful) newOrigin := contracts.AzionJsonDataOrigin{ OriginId: origin.GetOriginId(), OriginKey: origin.GetOriginKey(), @@ -283,7 +304,7 @@ func (cmd *DeployCmd) doOriginSingle(clientOrigin *apiori.Client, ctx context.Co return newOrigin.OriginId, nil } -func (cmd *DeployCmd) createFunction(client *api.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (int64, error) { +func (cmd *DeployCmd) createFunction(client *api.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) (int64, error) { reqCre := api.CreateRequest{} code, err := cmd.FileReader(conf.Function.File) @@ -322,11 +343,13 @@ func (cmd *DeployCmd) createFunction(client *api.Client, ctx context.Context, co logger.Debug("Error while creating Edge Function", zap.Error(err)) return 0, fmt.Errorf(msg.ErrorCreateFunction.Error(), err) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputEdgeFunctionCreate, response.GetName(), response.GetId())) + msgf := fmt.Sprintf(msg.DeployOutputEdgeFunctionCreate, response.GetName(), response.GetId()) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return response.GetId(), nil } -func (cmd *DeployCmd) updateFunction(client *api.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (int64, error) { +func (cmd *DeployCmd) updateFunction(client *api.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) (int64, error) { reqUpd := api.UpdateRequest{} code, err := cmd.FileReader(conf.Function.File) @@ -365,11 +388,13 @@ func (cmd *DeployCmd) updateFunction(client *api.Client, ctx context.Context, co return 0, fmt.Errorf(msg.ErrorUpdateFunction.Error(), err) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputEdgeFunctionUpdate, response.GetName(), conf.Function.ID)) + msgf := fmt.Sprintf(msg.DeployOutputEdgeFunctionUpdate, response.GetName(), conf.Function.ID) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return response.GetId(), nil } -func (cmd *DeployCmd) createApplication(client *apiapp.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (int64, error) { +func (cmd *DeployCmd) createApplication(client *apiapp.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) (int64, error) { reqApp := apiapp.CreateRequest{} if conf.Application.Name == "__DEFAULT__" { reqApp.SetName(conf.Name) @@ -383,7 +408,10 @@ func (cmd *DeployCmd) createApplication(client *apiapp.Client, ctx context.Conte return 0, fmt.Errorf(msg.ErrorCreateApplication.Error(), err) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputEdgeApplicationCreate, application.GetName(), application.GetId())) + msgf := fmt.Sprintf( + msg.DeployOutputEdgeApplicationCreate, application.GetName(), application.GetId()) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) reqUpApp := apiapp.UpdateRequest{} reqUpApp.SetEdgeFunctions(true) @@ -399,7 +427,7 @@ func (cmd *DeployCmd) createApplication(client *apiapp.Client, ctx context.Conte return application.GetId(), nil } -func (cmd *DeployCmd) updateApplication(client *apiapp.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) updateApplication(client *apiapp.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) error { reqApp := apiapp.UpdateRequest{} if conf.Application.Name == "__DEFAULT__" { reqApp.SetName(conf.Name) @@ -411,11 +439,14 @@ func (cmd *DeployCmd) updateApplication(client *apiapp.Client, ctx context.Conte if err != nil { return err } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputEdgeApplicationUpdate, application.GetName(), application.GetId())) + msgf := fmt.Sprintf( + msg.DeployOutputEdgeApplicationUpdate, application.GetName(), application.GetId()) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return nil } -func (cmd *DeployCmd) createDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (apidom.DomainResponse, error) { +func (cmd *DeployCmd) createDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) (apidom.DomainResponse, error) { reqDom := apidom.CreateRequest{} if conf.Domain.Name == "__DEFAULT__" { reqDom.SetName(conf.Name) @@ -430,11 +461,13 @@ func (cmd *DeployCmd) createDomain(client *apidom.Client, ctx context.Context, c if err != nil { return nil, fmt.Errorf(msg.ErrorCreateDomain.Error(), err) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputDomainCreate, conf.Name, domain.GetId())) + msgf := fmt.Sprintf(msg.DeployOutputDomainCreate, conf.Name, domain.GetId()) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return domain, nil } -func (cmd *DeployCmd) updateDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions) (apidom.DomainResponse, error) { +func (cmd *DeployCmd) updateDomain(client *apidom.Client, ctx context.Context, conf *contracts.AzionApplicationOptions, msgs *[]string) (apidom.DomainResponse, error) { reqDom := apidom.UpdateRequest{} if conf.Domain.Name == "__DEFAULT__" { reqDom.SetName(conf.Name) @@ -447,7 +480,9 @@ func (cmd *DeployCmd) updateDomain(client *apidom.Client, ctx context.Context, c if err != nil { return nil, fmt.Errorf(msg.ErrorUpdateDomain.Error(), err) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputDomainUpdate, conf.Name, domain.GetId())) + msgf := fmt.Sprintf(msg.DeployOutputDomainUpdate, conf.Name, domain.GetId()) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgf) return domain, nil } @@ -531,25 +566,6 @@ func (cmd *DeployCmd) updateInstance(ctx context.Context, client *apiapp.Client, return resp, nil } -// TODO: Use this method later -// func checkNameInUse(errMsg error, printMessage string, Out io.Writer) (string, error) { -// var name string -// if strings.Contains(errMsg.Error(), utils.ErrorNameInUse.Error()) { -// logger.FInfo(Out, printMessage) -// if Auto { -// name = thoth.GenerateName() -// } else { -// answer, err := askForInput(msg.AskInputName, thoth.GenerateName()) -// if err != nil { -// return "", err -// } -// name = answer -// } -// return name, nil -// } -// return "", errMsg -// } - func checkToken(f *cmdutil.Factory) error { configureToken := f.Config.GetString("token") diff --git a/pkg/cmd/deploy/upload.go b/pkg/cmd/deploy/upload.go index ec98ca5a6..4c421e404 100644 --- a/pkg/cmd/deploy/upload.go +++ b/pkg/cmd/deploy/upload.go @@ -20,7 +20,8 @@ var ( Retries int64 ) -func (cmd *DeployCmd) uploadFiles(f *cmdutil.Factory, conf *contracts.AzionApplicationOptions) error { +func (cmd *DeployCmd) uploadFiles( + f *cmdutil.Factory, conf *contracts.AzionApplicationOptions, msgs *[]string) error { // Get total amount of files to display progress totalFiles := 0 if err := cmd.FilepathWalk(PathStatic, func(path string, info os.FileInfo, err error) error { @@ -40,7 +41,8 @@ func (cmd *DeployCmd) uploadFiles(f *cmdutil.Factory, conf *contracts.AzionAppli clientUpload := storage.NewClient(cmd.F.HttpClient, cmd.F.Config.GetString("storage_url"), cmd.F.Config.GetString("token")) - logger.FInfo(cmd.F.IOStreams.Out, msg.UploadStart) + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.UploadStart, f.Format, f.Out) + *msgs = append(*msgs, msg.UploadStart) noOfWorkers := 5 var currentFile int64 @@ -114,7 +116,8 @@ func (cmd *DeployCmd) uploadFiles(f *cmdutil.Factory, conf *contracts.AzionAppli // All jobs are processed, no more values will be sent on results: close(results) - logger.FInfo(cmd.F.IOStreams.Out, msg.UploadSuccessful) + logger.FInfoFlags(cmd.F.IOStreams.Out, msg.UploadSuccessful, f.Format, f.Out) + *msgs = append(*msgs, msg.UploadSuccessful) return nil } diff --git a/pkg/cmd/sync/tasks.go b/pkg/cmd/sync/tasks.go index 27a83bc94..93b7a8a9b 100644 --- a/pkg/cmd/sync/tasks.go +++ b/pkg/cmd/sync/tasks.go @@ -64,7 +64,11 @@ func (synch *SyncCmd) syncOrigin(info contracts.SyncOpts, f *cmdutil.Factory) er logger.Debug("Error while writing azion.json file", zap.Error(err)) return err } - logger.FInfo(synch.Io.Out, fmt.Sprintf(msg.SYNCMESSAGEORIGIN, origin.Name)) + logger.FInfoFlags( + synch.Io.Out, + fmt.Sprintf(msg.SYNCMESSAGEORIGIN, origin.Name), + synch.F.Format, + synch.F.Out) } return nil } @@ -89,7 +93,7 @@ func (synch *SyncCmd) syncCache(info contracts.SyncOpts, f *cmdutil.Factory) err logger.Debug("Error while writing azion.json file", zap.Error(err)) return err } - logger.FInfo(synch.Io.Out, fmt.Sprintf(msg.SYNCMESSAGECACHE, cache.Name)) + logger.FInfoFlags(synch.Io.Out, fmt.Sprintf(msg.SYNCMESSAGECACHE, cache.Name), synch.F.Format, synch.F.Out) } return nil } @@ -116,7 +120,8 @@ func (synch *SyncCmd) syncRules(info contracts.SyncOpts, f *cmdutil.Factory) err logger.Debug("Error while writing azion.json file", zap.Error(err)) return err } - logger.FInfo(synch.Io.Out, fmt.Sprintf(msg.SYNCMESSAGERULE, rule.Name)) + logger.FInfoFlags( + synch.Io.Out, fmt.Sprintf(msg.SYNCMESSAGERULE, rule.Name), synch.F.Format, synch.F.Out) } return nil } diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go index 7e68a120d..89b7aa6cc 100644 --- a/pkg/manifest/manifest.go +++ b/pkg/manifest/manifest.go @@ -54,8 +54,10 @@ func (man *ManifestInterpreter) ManifestPath() (string, error) { return utils.Concat(pathWorkingDir, manifestFilePath), nil } -func (man *ManifestInterpreter) ReadManifest(path string, f *cmdutil.Factory) (*contracts.Manifest, error) { - logger.FInfo(f.IOStreams.Out, msg.ReadingManifest) +func (man *ManifestInterpreter) ReadManifest( + path string, f *cmdutil.Factory, msgs *[]string) (*contracts.Manifest, error) { + logger.FInfoFlags(f.IOStreams.Out, msg.ReadingManifest, f.Format, f.Out) + *msgs = append(*msgs, msg.ReadingManifest) manifest := &contracts.Manifest{} byteManifest, err := man.FileReader(path) @@ -71,8 +73,14 @@ func (man *ManifestInterpreter) ReadManifest(path string, f *cmdutil.Factory) (* return manifest, nil } -func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplicationOptions, manifest *contracts.Manifest, f *cmdutil.Factory, projectConf string) error { - logger.FInfo(f.IOStreams.Out, msg.CreatingManifest) +func (man *ManifestInterpreter) CreateResources( + conf *contracts.AzionApplicationOptions, + manifest *contracts.Manifest, + f *cmdutil.Factory, + projectConf string, + msgs *[]string) error { + logger.FInfoFlags(f.IOStreams.Out, msg.CreatingManifest, f.Format, f.Out) + *msgs = append(*msgs, msg.CreatingManifest) client := apiEdgeApplications.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) clientCache := apiCache.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) @@ -121,7 +129,10 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication Name: updated.GetName(), } originConf = append(originConf, newEntry) - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestUpdateOrigin, origin.Name, updated.GetOriginKey())) + + msgf := fmt.Sprintf(msg.ManifestUpdateOrigin, origin.Name, updated.GetOriginKey()) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } else { requestCreate := makeOriginCreateRequest(origin, conf) if origin.Name != "" { @@ -142,7 +153,9 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication originConf = append(originConf, newOrigin) OriginIds[created.GetName()] = created.GetOriginId() OriginKeys[created.GetName()] = created.GetOriginKey() - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestCreateOrigin, origin.Name, created.GetOriginId())) + msgf := fmt.Sprintf(msg.ManifestCreateOrigin, origin.Name, created.GetOriginId()) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } } @@ -171,7 +184,9 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication Name: updated.GetName(), } cacheConf = append(cacheConf, newCache) - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestUpdateCache, *cache.Name, id)) + msgf := fmt.Sprintf(msg.ManifestUpdateCache, *cache.Name, id) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } else { requestUpdate := makeCacheRequestCreate(cache) if cache.Name != nil { @@ -189,7 +204,9 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication } cacheConf = append(cacheConf, newCache) CacheIds[newCache.Name] = newCache.Id - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestCreateCache, *cache.Name, newCache.Id)) + msgf := fmt.Sprintf(msg.ManifestCreateCache, *cache.Name, newCache.Id) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } } @@ -226,7 +243,9 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication Name: updated.GetName(), Phase: updated.GetPhase(), } - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestUpdateRule, newRule.Name, newRule.Id)) + msgf := fmt.Sprintf(msg.ManifestUpdateRule, newRule.Name, newRule.Id) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) ruleConf = append(ruleConf, newRule) delete(RuleIds, rule.Name) } else { @@ -251,7 +270,9 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication Phase: created.GetPhase(), } ruleConf = append(ruleConf, newRule) - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msg.ManifestCreateRule, newRule.Name, newRule.Id)) + msgf := fmt.Sprintf(msg.ManifestCreateRule, newRule.Name, newRule.Id) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } } @@ -262,7 +283,7 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication return err } - err = deleteResources(ctx, f, conf) + err = deleteResources(ctx, f, conf, msgs) if err != nil { return err } @@ -271,7 +292,7 @@ func (man *ManifestInterpreter) CreateResources(conf *contracts.AzionApplication } // this is called to delete resources no longer present in manifest.json -func deleteResources(ctx context.Context, f *cmdutil.Factory, conf *contracts.AzionApplicationOptions) error { +func deleteResources(ctx context.Context, f *cmdutil.Factory, conf *contracts.AzionApplicationOptions, msgs *[]string) error { client := apiEdgeApplications.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) clientCache := apiCache.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) clientOrigin := apiOrigin.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) @@ -287,7 +308,9 @@ func deleteResources(ctx context.Context, f *cmdutil.Factory, conf *contracts.Az if err != nil { return err } - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msgrule.DeleteOutputSuccess+"\n", value.Id)) + msgf := fmt.Sprintf(msgrule.DeleteOutputSuccess+"\n", value.Id) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } for i, value := range OriginKeys { @@ -298,7 +321,9 @@ func deleteResources(ctx context.Context, f *cmdutil.Factory, conf *contracts.Az if err != nil { return err } - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msgorigin.DeleteOutputSuccess+"\n", value)) + msgf := fmt.Sprintf(msgorigin.DeleteOutputSuccess+"\n", value) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } for _, value := range CacheIds { @@ -306,7 +331,9 @@ func deleteResources(ctx context.Context, f *cmdutil.Factory, conf *contracts.Az if err != nil { return err } - logger.FInfo(f.IOStreams.Out, fmt.Sprintf(msgcache.DeleteOutputSuccess+"\n", value)) + msgf := fmt.Sprintf(msgcache.DeleteOutputSuccess+"\n", value) + logger.FInfoFlags(f.IOStreams.Out, msgf, f.Format, f.Out) + *msgs = append(*msgs, msgf) } return nil From a18e2a48d7eb60630225c6741fdcbdaa73f95519 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Mon, 8 Jul 2024 14:58:56 -0300 Subject: [PATCH 31/33] chore: update test with param msgs --- pkg/cmd/deploy/deploy_test.go | 289 +--------------------------------- pkg/manifest/manifest_test.go | 7 +- 2 files changed, 7 insertions(+), 289 deletions(-) diff --git a/pkg/cmd/deploy/deploy_test.go b/pkg/cmd/deploy/deploy_test.go index 65df37068..1bc273e73 100644 --- a/pkg/cmd/deploy/deploy_test.go +++ b/pkg/cmd/deploy/deploy_test.go @@ -17,66 +17,6 @@ import ( "github.com/stretchr/testify/require" ) -// var successRespRule string = ` -// { -// "results": { -// "id": 234567, -// "name": "enable gzip", -// "phase": "response", -// "behaviors": [ -// { -// "name": "enable_gzip", -// } -// ], -// "criteria": [ -// [ -// { -// "variable": "${uri}", -// "operator": "exists", -// "conditional": "if", -// "input_value": "" -// } -// ] -// ], -// "is_active": true, -// "order": 1, -// }, -// "schema_version": 3 -// } -// ` - -// var successRespOrigin string = ` -// -// { -// "results": { -// "origin_id": 0, -// "origin_key": "000000-000000-00000-00000-000000", -// "name": "name", -// "origin_type": "single_origin", -// "addresses": [ -// { -// "address": "httpbin.org", -// "weight": null, -// "server_role": "primary", -// "is_active": true -// } -// ], -// "origin_protocol_policy": "http", -// "is_origin_redirection_enabled": false, -// "host_header": "${host}", -// "method": "", -// "origin_path": "/requests", -// "connection_timeout": 60, -// "timeout_between_bytes": 120, -// "hmac_authentication": false, -// "hmac_region_name": "", -// "hmac_access_key": "", -// "hmac_secret_key": "" -// }, -// "schema_version": 3 -// } -// -// ` var successResponseApp string = ` { "results":{ @@ -105,233 +45,10 @@ var successResponseApp string = ` } ` -// var sucRespInst string = `{ -// "results": { -// "edge_function_id": 1111, -// "name": "Edge Function", -// "args": {}, -// "id": 101001 -// }, -// "schema_version": 3 -// } -// ` - -// var sucRespFunc string = `{ -// "results": { -// "id": 1111, -// "name": "Function Test API", -// "language": "javascript", -// "code": "{\r\n async function handleRequest(request) {\r\n return new Response(\"Hello world in a new response\");\r\n }\r\n\r\n addEventListener(\"fetch\", (event) => {\r\n event.respondWith(handleRequest(event.request));\r\n });\r\n}", -// "json_args": { -// "key": "value" -// }, -// "function_to_run": "", -// "initiator_type": "edge_application", -// "active": true, -// "last_editor": "mail@mail.com", -// "modified": "2023-04-27T17:37:12.389389Z", -// "reference_count": 1 -// }, -// "schema_version": 3 -// } -// ` - -// var sucRespDomain string = `{ -// "results": { -// "id": 1702659986, -// "name": "My Domain", -// "cnames": [], -// "cname_access_only": false, -// "digital_certificate_id": null, -// "edge_application_id": 1697666970, -// "is_active": true, -// "domain_name": "ja65r2loc3.map.azionedge.net", -// "is_mtls_enabled": false, -// "mtls_verification": "enforce", -// "mtls_trusted_ca_certificate_id": null -// }, -// "schema_version": 3 -// }` - -// var sucRespOrigin string = `{ -// "results": { -// "origin_id": 116207, -// "origin_key": "35e3a635-2227-4bb6-976c-5e8c8fa58a67", -// "name": "Create Origin22", -// "origin_type": "single_origin", -// "addresses": [ -// { -// "address": "httpbin.org", -// "weight": null, -// "server_role": "primary", -// "is_active": true -// } -// ], -// "origin_protocol_policy": "http", -// "is_origin_redirection_enabled": false, -// "host_header": "${host}", -// "method": "", -// "origin_path": "/requests", -// "connection_timeout": 60, -// "timeout_between_bytes": 120, -// "hmac_authentication": false, -// "hmac_region_name": "", -// "hmac_access_key": "", -// "hmac_secret_key": "" -// }, -// "schema_version": 3 -// }` - -// var sucRespCacheSettings = `{ -// "results": { -// "id": 138708, -// "name": "Default Cache Settings2234", -// "browser_cache_settings": "override", -// "browser_cache_settings_maximum_ttl": 0, -// "cdn_cache_settings": "override", -// "cdn_cache_settings_maximum_ttl": 60, -// "cache_by_query_string": "ignore", -// "query_string_fields": null, -// "enable_query_string_sort": false, -// "cache_by_cookies": "ignore", -// "cookie_names": null, -// "adaptive_delivery_action": "ignore", -// "device_group": [], -// "enable_caching_for_post": false, -// "l2_caching_enabled": false, -// "is_slice_configuration_enabled": false, -// "is_slice_edge_caching_enabled": false, -// "is_slice_l2_caching_enabled": false, -// "slice_configuration_range": 1024, -// "enable_caching_for_options": false, -// "enable_stale_cache": true, -// "l2_region": null -// }, -// "schema_version": 3 -// }` - -// var sucRespRules = `{ -// "results": { -// "id": 214790, -// "name": "testorigin2", -// "phase": "request", -// "behaviors": [ -// { -// "name": "set_origin", -// "target": "116207" -// } -// ], -// "criteria": [ -// [ -// { -// "variable": "${uri}", -// "operator": "starts_with", -// "conditional": "if", -// "input_value": "/" -// } -// ] -// ], -// "is_active": true, -// "order": 1, -// "description": "" -// }, -// "schema_version": 3 -// }` - func TestDeployCmd(t *testing.T) { logger.New(zapcore.DebugLevel) - // t.Run("full flow manifest empty", func(t *testing.T) { - // mock := &httpmock.Registry{} - - // options := &contracts.AzionApplicationOptions{ - // Name: "LovelyName", - // Bucket: "LovelyName", - // } - - // dat, _ := os.ReadFile("./fixtures/create_app.json") - // _ = json.Unmarshal(dat, options) - - // mock.Register( - // httpmock.REST("POST", "edge_applications"), - // httpmock.JSONFromString(successResponseApp), - // ) - - // mock.Register( - // httpmock.REST("POST", "v4/storage/buckets"), - // httpmock.JSONFromString(""), - // ) - - // mock.Register( - // httpmock.REST("POST", "edge_functions"), - // httpmock.JSONFromString(sucRespFunc), - // ) - - // mock.Register( - // httpmock.REST("POST", "edge_applications/1697666970/origins"), - // httpmock.JSONFromString(successRespOrigin), - // ) - - // mock.Register( - // httpmock.REST("POST", "edge_applications/1697666970/functions_instances"), - // httpmock.JSONFromString(sucRespInst), - // ) - - // mock.Register( - // httpmock.REST("POST", "domains"), - // httpmock.JSONFromString(sucRespDomain), - // ) - - // mock.Register( - // httpmock.REST("PATCH", "edge_applications/1697666970"), - // httpmock.JSONFromString(successResponseApp), - // ) - - // mock.Register( - // httpmock.REST("POST", "edge_applications/1697666970/rules_engine/response/rules"), - // httpmock.JSONFromString(successRespRule), - // ) - - // f, _, _ := testutils.NewFactory(mock) - // deployCmd := NewDeployCmd(f) - - // deployCmd.FilepathWalk = func(root string, fn filepath.WalkFunc) error { - // return nil - // } - // deployCmd.WriteAzionJsonContent = func(conf *contracts.AzionApplicationOptions) error { - // return nil - // } - - // deployCmd.FileReader = func(path string) ([]byte, error) { - // return []byte{}, nil - // } - - // deployCmd.Unmarshal = func(data []byte, v interface{}) error { - // return nil - // } - - // deployCmd.GetAzionJsonContent = func() (*contracts.AzionApplicationOptions, error) { - // return &contracts.AzionApplicationOptions{}, nil - // } - - // deployCmd.Interpreter = func() *manifestInt.ManifestInterpreter { - // return &manifestInt.ManifestInterpreter{ - // FileReader: func(path string) ([]byte, error) { - // return []byte{'{', '}'}, nil - // }, - // WriteAzionJsonContent: func(conf *contracts.AzionApplicationOptions) error { - // return nil - // }, - // GetWorkDir: func() (string, error) { - // return "", nil - // }, - // } - // } - - // err := deployCmd.Run(f) - // // err := manifest.Interpreted(f, deployCmd, options, clients) - // require.NoError(t, err) - // }) + msgs := []string{} t.Run("without azion.json", func(t *testing.T) { f, _, _ := testutils.NewFactory(nil) @@ -373,7 +90,7 @@ func TestDeployCmd(t *testing.T) { cmd := NewDeployCmd(f) - _, err := cmd.createApplication(cliapp, ctx, options) + _, err := cmd.createApplication(cliapp, ctx, options, &msgs) require.ErrorContains(t, err, "Failed to create the Edge Application") }) @@ -409,7 +126,7 @@ func TestDeployCmd(t *testing.T) { cmd := NewDeployCmd(f) - _, err := cmd.createApplication(cliapp, ctx, options) + _, err := cmd.createApplication(cliapp, ctx, options, &msgs) require.NoError(t, err) }) } diff --git a/pkg/manifest/manifest_test.go b/pkg/manifest/manifest_test.go index 16aad3f1f..7c648c585 100644 --- a/pkg/manifest/manifest_test.go +++ b/pkg/manifest/manifest_test.go @@ -13,6 +13,7 @@ import ( func TestDeployCmd(t *testing.T) { logger.New(zapcore.DebugLevel) + msgs := []string{} t.Run("get manifest path", func(t *testing.T) { interpreter := NewManifestInterpreter() @@ -26,7 +27,7 @@ func TestDeployCmd(t *testing.T) { interpreter := NewManifestInterpreter() pathManifest := "fixtures/manifest.json" - _, err := interpreter.ReadManifest(pathManifest, f) + _, err := interpreter.ReadManifest(pathManifest, f, &msgs) require.NoError(t, err) }) @@ -58,9 +59,9 @@ func TestDeployCmd(t *testing.T) { } pathManifest := "fixtures/manifest.json" - manifest, err := interpreter.ReadManifest(pathManifest, f) + manifest, err := interpreter.ReadManifest(pathManifest, f, &msgs) require.NoError(t, err) - err = interpreter.CreateResources(options, manifest, f, "azion") + err = interpreter.CreateResources(options, manifest, f, "azion", &msgs) require.NoError(t, err) }) From be4842e020a0e8880e75d1ae5e1307c94af24b87 Mon Sep 17 00:00:00 2001 From: PatrickMenoti <82882574+PatrickMenoti@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:05:23 -0300 Subject: [PATCH 32/33] tests: increase delete edge-application tests --- .../edge_application/edge_application.go | 10 +++- .../edge_application/edge_application_test.go | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/delete/edge_application/edge_application.go b/pkg/cmd/delete/edge_application/edge_application.go index c265fa53b..10eb1f668 100644 --- a/pkg/cmd/delete/edge_application/edge_application.go +++ b/pkg/cmd/delete/edge_application/edge_application.go @@ -3,6 +3,7 @@ package edgeapplication import ( "context" "fmt" + "io/fs" "os" "strconv" @@ -29,6 +30,8 @@ type DeleteCmd struct { UpdateJson func(cmd *DeleteCmd) error Cascade func(ctx context.Context, del *DeleteCmd) error AskInput func(string) (string, error) + ReadFile func(name string) ([]byte, error) + WriteFile func(name string, data []byte, perm fs.FileMode) error } func NewCmd(f *cmdutil.Factory) *cobra.Command { @@ -43,6 +46,8 @@ func NewDeleteCmd(f *cmdutil.Factory) *DeleteCmd { UpdateJson: updateAzionJson, Cascade: CascadeDelete, AskInput: utils.AskInput, + ReadFile: os.ReadFile, + WriteFile: os.WriteFile, } } @@ -118,8 +123,9 @@ func updateAzionJson(cmd *DeleteCmd) error { return utils.ErrorInternalServerError } azionJson := path + "/azion/azion.json" - byteAzionJson, err := os.ReadFile(azionJson) + byteAzionJson, err := cmd.ReadFile(azionJson) if err != nil { + logger.Debug("Error while parsing json", zap.Error(err)) return utils.ErrorUnmarshalAzionJsonFile } jsonReplaceFunc, err := sjson.Set(string(byteAzionJson), "function.id", 0) @@ -137,7 +143,7 @@ func updateAzionJson(cmd *DeleteCmd) error { return msg.ErrorFailedUpdateAzionJson } - err = os.WriteFile(azionJson, []byte(jsonReplaceDomain), 0644) + err = cmd.WriteFile(azionJson, []byte(jsonReplaceDomain), 0644) if err != nil { return fmt.Errorf(utils.ErrorCreateFile.Error(), azionJson) } diff --git a/pkg/cmd/delete/edge_application/edge_application_test.go b/pkg/cmd/delete/edge_application/edge_application_test.go index 551fb0d6b..b15562498 100644 --- a/pkg/cmd/delete/edge_application/edge_application_test.go +++ b/pkg/cmd/delete/edge_application/edge_application_test.go @@ -3,6 +3,7 @@ package edgeapplication import ( "encoding/json" "fmt" + "io/fs" "os" "testing" @@ -189,3 +190,62 @@ func TestCascadeDelete(t *testing.T) { assert.Equal(t, msg.CascadeSuccess, stdout.String()) }) } + +func TestUpdateAzionJson(t *testing.T) { + logger.New(zapcore.DebugLevel) + + t.Run("update azion.json with new IDs", func(t *testing.T) { + // Mocking the content of azion.json + mockAzionJsonContent := `{ + "function": { + "id": 1 + }, + "application": { + "id": 2 + }, + "domain": { + "id": 3 + } + }` + + // Create a temporary file for testing + tempFile, err := os.CreateTemp("", "azion.json") + require.NoError(t, err) + defer os.Remove(tempFile.Name()) + + // Write mock JSON content to the temporary file + _, err = tempFile.WriteString(mockAzionJsonContent) + require.NoError(t, err) + tempFile.Close() + + mock := &httpmock.Registry{} + + f, _, _ := testutils.NewFactory(mock) + + // Prepare the DeleteCmd instance with mock dependencies + del := &DeleteCmd{ + f: f, + Io: f.IOStreams, + GetAzion: func(confPath string) (*contracts.AzionApplicationOptions, error) { + conf := &contracts.AzionApplicationOptions{} + conf.Function.ID = 1 + conf.Application.ID = 2 + conf.Domain.Id = 3 + return conf, nil + }, + UpdateJson: func(cmd *DeleteCmd) error { + return nil + }, + ReadFile: func(name string) ([]byte, error) { + return []byte(mockAzionJsonContent), nil + }, + WriteFile: func(name string, data []byte, perm fs.FileMode) error { + return nil + }, + } + + // Run the test + err = updateAzionJson(del) + require.NoError(t, err) + }) +} From af785739999650b083a330457a1fd264f6062c30 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 9 Jul 2024 11:46:42 -0300 Subject: [PATCH 33/33] fix: deploy command calls the build and executes the build print --- pkg/cmd/build/build.go | 11 ++++------- pkg/cmd/build/run.go | 8 ++++---- pkg/cmd/build/utils.go | 22 +++++++++++++++------- pkg/cmd/build/vulcan.go | 4 ++-- pkg/cmd/deploy/bucket.go | 3 ++- pkg/cmd/deploy/deploy.go | 5 +++-- pkg/cmd/deploy/purge.go | 6 ++++-- pkg/cmd/deploy/requests.go | 2 +- pkg/cmd/dev/dev.go | 2 +- 9 files changed, 36 insertions(+), 27 deletions(-) diff --git a/pkg/cmd/build/build.go b/pkg/cmd/build/build.go index 904fbc816..717faa48e 100644 --- a/pkg/cmd/build/build.go +++ b/pkg/cmd/build/build.go @@ -44,7 +44,8 @@ func NewCobraCmd(build *BuildCmd) *cobra.Command { SilenceUsage: true, Example: heredoc.Doc("\n$ azion build\n"), RunE: func(cmd *cobra.Command, args []string) error { - return build.run(fields) + msgs := []string{} + return build.run(fields, &msgs) }, } @@ -83,11 +84,7 @@ func NewBuildCmd(f *cmdutil.Factory) *BuildCmd { } } -func (cmd *BuildCmd) Run(fields *contracts.BuildInfo) error { - return cmd.run(fields) -} - -func (cmd *BuildCmd) ExternalRun(fields *contracts.BuildInfo, confPath string) error { +func (cmd *BuildCmd) ExternalRun(fields *contracts.BuildInfo, confPath string, msgs *[]string) error { fields.ProjectPath = confPath - return cmd.run(fields) + return cmd.run(fields, msgs) } diff --git a/pkg/cmd/build/run.go b/pkg/cmd/build/run.go index ac832d56d..6e5e2a44d 100644 --- a/pkg/cmd/build/run.go +++ b/pkg/cmd/build/run.go @@ -10,10 +10,10 @@ import ( "go.uber.org/zap" ) -func (cmd *BuildCmd) run(fields *contracts.BuildInfo) error { +func (cmd *BuildCmd) run(fields *contracts.BuildInfo, msgs *[]string) error { logger.Debug("Running build command") - err := RunBuildCmdLine(cmd, fields) + err := RunBuildCmdLine(cmd, fields, msgs) if err != nil { return err } @@ -21,7 +21,7 @@ func (cmd *BuildCmd) run(fields *contracts.BuildInfo) error { return nil } -func RunBuildCmdLine(cmd *BuildCmd, fields *contracts.BuildInfo) error { +func RunBuildCmdLine(cmd *BuildCmd, fields *contracts.BuildInfo, msgs *[]string) error { var err error conf, err := cmd.GetAzionJsonContent(fields.ProjectPath) @@ -64,6 +64,6 @@ func RunBuildCmdLine(cmd *BuildCmd, fields *contracts.BuildInfo) error { vulcanParams += " --firewall " } - return vulcan(cmd, conf, vulcanParams, fields) + return vulcan(cmd, conf, vulcanParams, fields, msgs) } diff --git a/pkg/cmd/build/utils.go b/pkg/cmd/build/utils.go index 3687dc998..68a5e66a2 100644 --- a/pkg/cmd/build/utils.go +++ b/pkg/cmd/build/utils.go @@ -9,15 +9,19 @@ import ( "go.uber.org/zap" ) -func runCommand(cmd *BuildCmd, command string) error { - msgs := []string{} +func runCommand(cmd *BuildCmd, command string, msgs *[]string) error { + var hasDeployMessage bool + if len(*msgs) > 0 { + hasDeployMessage = true + } + logger.FInfoFlags(cmd.Io.Out, msg.BuildStart, cmd.f.Format, cmd.f.Out) - msgs = append(msgs, msg.BuildStart) + *msgs = append(*msgs, msg.BuildStart) logger.FInfoFlags(cmd.Io.Out, msg.BuildRunningCmd, cmd.f.Format, cmd.f.Out) - msgs = append(msgs, msg.BuildRunningCmd) + *msgs = append(*msgs, msg.BuildRunningCmd) logger.FInfoFlags(cmd.Io.Out, fmt.Sprintf("$ %s\n", command), cmd.f.Format, cmd.f.Out) - msgs = append(msgs, fmt.Sprintf("$ %s\n", command)) + *msgs = append(*msgs, fmt.Sprintf("$ %s\n", command)) err := cmd.CommandRunInteractive(cmd.f, command) if err != nil { @@ -26,10 +30,14 @@ func runCommand(cmd *BuildCmd, command string) error { } logger.FInfoFlags(cmd.Io.Out, msg.BuildSuccessful, cmd.f.Format, cmd.f.Out) - msgs = append(msgs, msg.BuildSuccessful) + *msgs = append(*msgs, msg.BuildSuccessful) + + if hasDeployMessage { + return nil + } outSlice := output.SliceOutput{ - Messages: msgs, + Messages: *msgs, GeneralOutput: output.GeneralOutput{ Out: cmd.f.IOStreams.Out, Flags: cmd.f.Flags, diff --git a/pkg/cmd/build/vulcan.go b/pkg/cmd/build/vulcan.go index 3e6457e4a..a576d21a5 100644 --- a/pkg/cmd/build/vulcan.go +++ b/pkg/cmd/build/vulcan.go @@ -12,7 +12,7 @@ import ( "go.uber.org/zap" ) -func vulcan(cmd *BuildCmd, conf *contracts.AzionApplicationOptions, vulcanParams string, fields *contracts.BuildInfo) error { +func vulcan(cmd *BuildCmd, conf *contracts.AzionApplicationOptions, vulcanParams string, fields *contracts.BuildInfo, msgs *[]string) error { // checking if vulcan major is correct vulcanVer, err := cmd.CommandRunner(cmd.f, "npm show edge-functions version", []string{}) if err != nil { @@ -26,7 +26,7 @@ func vulcan(cmd *BuildCmd, conf *contracts.AzionApplicationOptions, vulcanParams command := vul.Command("", "build --preset %s --mode %s%s", cmd.f) - err = runCommand(cmd, fmt.Sprintf(command, strings.ToLower(conf.Preset), strings.ToLower(conf.Mode), vulcanParams)) + err = runCommand(cmd, fmt.Sprintf(command, strings.ToLower(conf.Preset), strings.ToLower(conf.Mode), vulcanParams), msgs) if err != nil { return fmt.Errorf(msg.ErrorVulcanExecute.Error(), err.Error()) } diff --git a/pkg/cmd/deploy/bucket.go b/pkg/cmd/deploy/bucket.go index 6c62c856b..609aafd7e 100644 --- a/pkg/cmd/deploy/bucket.go +++ b/pkg/cmd/deploy/bucket.go @@ -25,7 +25,8 @@ func (cmd *DeployCmd) doBucket( return nil } - logger.FInfo(cmd.Io.Out, msg.ProjectNameMessage) + logger.FInfoFlags(cmd.Io.Out, msg.ProjectNameMessage, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msg.ProjectNameMessage) nameBucket := replaceInvalidChars(conf.Name) err := client.CreateBucket(ctx, api.RequestBucket{ diff --git a/pkg/cmd/deploy/deploy.go b/pkg/cmd/deploy/deploy.go index dc044eea1..7385d9ede 100644 --- a/pkg/cmd/deploy/deploy.go +++ b/pkg/cmd/deploy/deploy.go @@ -108,8 +108,9 @@ func (cmd *DeployCmd) ExternalRun(f *cmdutil.Factory, configPath string) error { } func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { - logger.Debug("Running deploy command") msgs := []string{} + logger.FInfoFlags(cmd.F.IOStreams.Out, "Running deploy command", cmd.F.Format, cmd.F.Out) + msgs = append(msgs, "Running deploy command") ctx := context.Background() err := checkToken(f) @@ -127,7 +128,7 @@ func (cmd *DeployCmd) Run(f *cmdutil.Factory) error { if !SkipBuild { buildCmd := cmd.BuildCmd(f) - err = buildCmd.ExternalRun(&contracts.BuildInfo{}, ProjectConf) + err = buildCmd.ExternalRun(&contracts.BuildInfo{}, ProjectConf, &msgs) if err != nil { logger.Debug("Error while running build command called by deploy command", zap.Error(err)) return err diff --git a/pkg/cmd/deploy/purge.go b/pkg/cmd/deploy/purge.go index 467b46284..040dc38b8 100644 --- a/pkg/cmd/deploy/purge.go +++ b/pkg/cmd/deploy/purge.go @@ -52,7 +52,7 @@ func (cmd *DeployCmd) PurgeUrls(domain []string, path string) error { return nil } -func PurgeForUpdatedFiles(cmd *DeployCmd, domain apidom.DomainResponse, confPath string) error { +func PurgeForUpdatedFiles(cmd *DeployCmd, domain apidom.DomainResponse, confPath string, msgs *[]string) error { listURLsDomains := domain.GetCnames() if !domain.GetCnameAccessOnly() { listURLsDomains = append(listURLsDomains, domain.GetDomainName()) @@ -69,7 +69,9 @@ func PurgeForUpdatedFiles(cmd *DeployCmd, domain apidom.DomainResponse, confPath if err := cmd.PurgeWildcard([]string{v}, wildCard); err != nil { logger.Debug("Error purge path domain", zap.String("wildCard", wildCard), zap.Error(err)) } - logger.FInfo(cmd.F.IOStreams.Out, fmt.Sprintf(msg.DeployOutputCachePurgeWildCard, v)) + msgsf := fmt.Sprintf(msg.DeployOutputCachePurgeWildCard, v) + logger.FInfoFlags(cmd.F.IOStreams.Out, msgsf, cmd.F.Format, cmd.F.Out) + *msgs = append(*msgs, msgsf) } } diff --git a/pkg/cmd/deploy/requests.go b/pkg/cmd/deploy/requests.go index a376e40b8..7e68cf13d 100644 --- a/pkg/cmd/deploy/requests.go +++ b/pkg/cmd/deploy/requests.go @@ -217,7 +217,7 @@ func (cmd *DeployCmd) doDomain(client *apidom.Client, ctx context.Context, conf } if conf.RtPurge.PurgeOnPublish && !newDomain { - err = PurgeForUpdatedFiles(cmd, domain, ProjectConf) + err = PurgeForUpdatedFiles(cmd, domain, ProjectConf, msgs) if err != nil { logger.Debug("Error while purging domain", zap.Error(err)) return err diff --git a/pkg/cmd/dev/dev.go b/pkg/cmd/dev/dev.go index 205ed463d..ae652ee6f 100644 --- a/pkg/cmd/dev/dev.go +++ b/pkg/cmd/dev/dev.go @@ -45,7 +45,7 @@ func NewCobraCmd(dev *DevCmd) *cobra.Command { Long: msg.DevLongDescription, SilenceUsage: true, SilenceErrors: true, - Example: heredoc.Doc(` + Example: heredoc.Doc(` $ azion dev $ azion dev --help `),