diff --git a/pkg/cmd/purge/fixtures/response.json b/pkg/cmd/purge/fixtures/response.json new file mode 100644 index 000000000..06aa70efc --- /dev/null +++ b/pkg/cmd/purge/fixtures/response.json @@ -0,0 +1,3 @@ +{ + "detail":"Purge request successfully created" +} \ No newline at end of file diff --git a/pkg/cmd/purge/purge.go b/pkg/cmd/purge/purge.go index 98fdc9e8f..16b870b9b 100644 --- a/pkg/cmd/purge/purge.go +++ b/pkg/cmd/purge/purge.go @@ -1,12 +1,13 @@ package purge import ( + "context" "strings" "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/purge" - "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/iostreams" "github.com/aziontech/azion-cli/pkg/logger" "github.com/spf13/cobra" ) @@ -18,8 +19,28 @@ var ( Layer string ) -func NewCmd(f *cmdutil.Factory) *cobra.Command { - cmd := &cobra.Command{ +type PurgeCmd struct { + Io *iostreams.IOStreams + PurgeUrls func([]string, *cmdutil.Factory) error + PurgeWildcard func([]string, *cmdutil.Factory) error + PurgeCacheKeys func([]string, *cmdutil.Factory) error + GetPurgeType func() (string, error) + AskForInput func() ([]string, error) +} + +func NewPurgeCmd(f *cmdutil.Factory) *PurgeCmd { + return &PurgeCmd{ + Io: f.IOStreams, + PurgeUrls: purgeUrls, + PurgeWildcard: purgeWildcard, + PurgeCacheKeys: purgeCacheKeys, + GetPurgeType: getPurgeType, + AskForInput: askForInput, + } +} + +func NewCobraCmd(purge *PurgeCmd, f *cmdutil.Factory) *cobra.Command { + cobraCmd := &cobra.Command{ Use: msg.Usage, Short: msg.ShortDescription, Long: msg.LongDescription, @@ -30,75 +51,79 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { $ azion purge --urls "www.example.com,www.pudim.com" $ azion purge --cache-key "www.domain.com/@@cookie_name=cookie_value,www.domain.com/test.js" `), - RunE: runE(f), + RunE: func(cmd *cobra.Command, _ []string) error { + ctx := context.Background() + return purge.Run(ctx, cmd, f) + }, } - cmd.Flags().StringVar(&urls, "urls", "", msg.FlagUrls) - cmd.Flags().StringVar(&wildcard, "wildcard", "", msg.FlagWildcard) - cmd.Flags().StringVar(&cachekeys, "cache-key", "", msg.FlagCacheKeys) - cmd.Flags().StringVar(&Layer, "layer", "edge_caching", msg.FlagLayer) - cmd.Flags().BoolP("help", "h", false, msg.FlagHelp) + cobraCmd.Flags().StringVar(&urls, "urls", "", msg.FlagUrls) + cobraCmd.Flags().StringVar(&wildcard, "wildcard", "", msg.FlagWildcard) + cobraCmd.Flags().StringVar(&cachekeys, "cache-key", "", msg.FlagCacheKeys) + cobraCmd.Flags().StringVar(&Layer, "layer", "edge_caching", msg.FlagLayer) + cobraCmd.Flags().BoolP("help", "h", false, msg.FlagHelp) - return cmd + return cobraCmd } -func runE(f *cmdutil.Factory) func(cmd *cobra.Command, _ []string) error { - return func(cmd *cobra.Command, _ []string) error { +func (purge *PurgeCmd) Run(ctx context.Context, cmd *cobra.Command, f *cmdutil.Factory) error { + if !cmd.Flags().Changed("urls") && !cmd.Flags().Changed("wildcard") && !cmd.Flags().Changed("cache-key") { + answer, err := purge.GetPurgeType() + if err != nil { + return err + } - if !cmd.Flags().Changed("urls") && !cmd.Flags().Changed("wildcard") && !cmd.Flags().Changed("cache-key") { - answer, err := getPurgeType() + listOfUrls, err := purge.AskForInput() + if err != nil { + return err + } + + switch strings.ToLower(answer) { + case "urls": + err := purge.PurgeUrls(listOfUrls, f) if err != nil { return err } - - listOfUrls, err := askForInput() + case "wildcard": + err := purge.PurgeWildcard(listOfUrls, f) if err != nil { return err } - - switch strings.ToLower(answer) { - case "urls": - err := purgeUrls(listOfUrls, f) - if err != nil { - return err - } - case "wildcard": - err := purgeWildcard(listOfUrls, f) - if err != nil { - return err - } - case "cache-key": - err := purgeCacheKeys(listOfUrls, f) - if err != nil { - return err - } - } - - return nil - } - - if cmd.Flags().Changed("urls") { - err := purgeUrls(strings.Split(urls, ","), f) + case "cache-key": + err := purge.PurgeCacheKeys(listOfUrls, f) if err != nil { return err } } - if cmd.Flags().Changed("wildcard") { - err := purgeWildcard(strings.Split(wildcard, ","), f) - if err != nil { - return err - } + return nil + } + + if cmd.Flags().Changed("urls") { + err := purge.PurgeUrls(strings.Split(urls, ","), f) + if err != nil { + return err } + } - if cmd.Flags().Changed("cache-key") { - err := purgeCacheKeys(strings.Split(cachekeys, ","), f) - if err != nil { - return err - } + if cmd.Flags().Changed("wildcard") { + err := purge.PurgeWildcard(strings.Split(wildcard, ","), f) + if err != nil { + return err } + } - logger.FInfo(f.IOStreams.Out, msg.PurgeSuccessful) - return nil + if cmd.Flags().Changed("cache-key") { + err := purge.PurgeCacheKeys(strings.Split(cachekeys, ","), f) + if err != nil { + return err + } } + + logger.FInfo(f.IOStreams.Out, msg.PurgeSuccessful) + return nil +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + return NewCobraCmd(NewPurgeCmd(f), f) } diff --git a/pkg/cmd/purge/purge_test.go b/pkg/cmd/purge/purge_test.go index 9f64bcfc2..21860308c 100644 --- a/pkg/cmd/purge/purge_test.go +++ b/pkg/cmd/purge/purge_test.go @@ -1,6 +1,7 @@ package purge import ( + "net/http" "testing" msg "github.com/aziontech/azion-cli/messages/purge" @@ -74,3 +75,158 @@ func TestUpdate(t *testing.T) { }) } + +func TestPurge(t *testing.T) { + logger.New(zapcore.DebugLevel) + + tests := []struct { + name string + request httpmock.Matcher + response httpmock.Responder + args []string + expectErr bool + mockInput func() ([]string, error) + mockGetPurge func() (string, error) + }{ + { + name: "purge urls", + request: httpmock.REST("POST", "purge/url"), + response: httpmock.StatusStringResponse(201, ""), + args: []string{"--urls", "http://www.example.com/,http://www.pudim.com/"}, + expectErr: false, + }, + { + name: "purge urls - ask input", + request: httpmock.REST("POST", "purge/url"), + response: httpmock.StatusStringResponse(201, ""), + expectErr: false, + mockInput: func() ([]string, error) { + return []string{"www.example.com/", "www.pudim.com/"}, nil + }, + mockGetPurge: func() (string, error) { + return "URLs", nil + }, + }, + { + name: "purge wildcard - ask input", + request: httpmock.REST("POST", "purge/wildcard"), + response: httpmock.StatusStringResponse(201, ""), + expectErr: false, + mockInput: func() ([]string, error) { + return []string{"www.example.com/*"}, nil + }, + mockGetPurge: func() (string, error) { + return "Wildcard", nil + }, + }, + { + name: "purge cachekey - ask input", + request: httpmock.REST("POST", "purge/cachekey"), + response: httpmock.StatusStringResponse(201, ""), + expectErr: false, + mockInput: func() ([]string, error) { + return []string{"www.domain.com/@@cookie_name=cookie_value"}, nil + }, + mockGetPurge: func() (string, error) { + return "Cache-Key", nil + }, + }, + { + name: "purge wildcard", + request: httpmock.REST("POST", "purge/wildcard"), + response: httpmock.StatusStringResponse(201, ""), + args: []string{"--wildcard", "www.example.com/*"}, + expectErr: false, + }, + { + name: "purge cache keys", + request: httpmock.REST("POST", "purge/cachekey"), + response: httpmock.JSONFromFile("./fixtures/response.json"), + args: []string{"--cache-key", "www.domain.com/@@cookie_name=cookie_value,www.domain.com/test.js"}, + expectErr: false, + }, + { + name: "invalid urls", + request: httpmock.REST("POST", "purge/url"), + response: httpmock.StatusStringResponse(http.StatusBadRequest, "Invalid URL"), + args: []string{"--urls", "invalid-url"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register(tt.request, tt.response) + + f, _, _ := testutils.NewFactory(mock) + purgeCmd := NewPurgeCmd(f) + purgeCmd.AskForInput = tt.mockInput + purgeCmd.GetPurgeType = tt.mockGetPurge + cmd := NewCobraCmd(purgeCmd, f) + cmd.SetArgs(tt.args) + + err := cmd.Execute() + + if tt.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestGetPurgeType(t *testing.T) { + tests := []struct { + name string + input string + wantAnswer string + wantErr bool + }{ + { + name: "select URLs", + input: "URLs\n", + wantAnswer: "URLs", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := getPurgeType() + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestAskForInput(t *testing.T) { + tests := []struct { + name string + input string + wantAnswer []string + wantErr bool + }{ + { + name: "single URL", + input: "www.example.com\n", + wantAnswer: []string{"www.example.com"}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := askForInput() + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/pkg/cmd/purge/requests.go b/pkg/cmd/purge/requests.go index df7091c17..ce30d853b 100644 --- a/pkg/cmd/purge/requests.go +++ b/pkg/cmd/purge/requests.go @@ -2,6 +2,7 @@ package purge import ( "context" + "fmt" "strings" "github.com/AlecAivazis/survey/v2" @@ -35,6 +36,7 @@ func purgeUrls(urls []string, f *cmdutil.Factory) error { clipurge := apipurge.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) err := clipurge.PurgeUrls(ctx, urls) if err != nil { + fmt.Println(err.Error()) logger.Debug("Error while purging URLs", zap.Error(err)) return err }