diff --git a/messages/device_groups/errors.go b/messages/device_groups/errors.go index 4d50cd0bb..47b2deadc 100644 --- a/messages/device_groups/errors.go +++ b/messages/device_groups/errors.go @@ -7,6 +7,8 @@ import ( var ( ErrorMissingApplicationIDArgument = errors.New("A mandatory flag is missing. You must provide a application-id as an argument or path to import the file. Run the command 'azioncli domains --help' to display more information and try again") ErrorGetDeviceGroups = errors.New("Failed to describe the device groups: %s. Check your settings and try again. If the error persists, contact Azion support.") - ErrorMandatoryFlags = errors.New("One or more required flags are missing. You must provide the --application-id and --group-id flags. Run the command 'azioncli rules_engine --help' to display more information and try again.") - ErrorFailToDelete = errors.New("Failed to delete the rule in Rules Engine: %s. Check your settings and try again. If the error persists, contact Azion support.") + ErrorMandatoryFlags = errors.New("One or more required flags are missing. You must provide the --application-id and --group-id flags. Run the command 'azioncli rules_engine --help' to display more information and try again.") + ErrorFailToDelete = errors.New("Failed to delete the rule in Rules Engine: %s. Check your settings and try again. If the error persists, contact Azion support.") + ErrorMandatoryCreateFlags = errors.New("Required flags are missing. You must provide application-id, name, user-agent flags when the --application-id and --in flag are not provided. Run the command 'azioncli --help' to display more information and try again.") + ErrorCreateDeviceGroups = errors.New("Failed to create the Device groups: %s. Check your settings and try again. If the error persists, contact Azion support.") ) diff --git a/messages/device_groups/messages.go b/messages/device_groups/messages.go index 956355e68..a35e68a6f 100644 --- a/messages/device_groups/messages.go +++ b/messages/device_groups/messages.go @@ -20,7 +20,18 @@ var ( DeviceGroupsDeleteLongDescription = "Deletes a Device Group based on the given '--group-id' and '--application-id'" DeviceGroupsDeleteOutputSuccess = "Device Group %d was successfully deleted\n" DeviceGroupsDeleteHelpFlag = "Displays more information about the delete subcommand" - - ApplicationFlagId = "Unique identifier for the edge application that implements this Device Group. The '--application-id' flag is required" + + // [ create ] + DeviceGroupsCreateUsage = "create [flags]" + DeviceGroupsCreateShortDescription = "Creates a new device groups" + DeviceGroupsCreateLongDescription = "Creates an device groups based on given attributes to be used in edge applications" + DeviceGroupsCreateFlagEdgeApplicationId = "Unique identifier for an edge application" + DeviceGroupsCreateFlagName = "The device group name" + DeviceGroupsCreateFlagUserAgent = "the device group flag user agent" + DeviceGroupsCreateFlagIn = "Path to a JSON file containing the attributes of the device group that will be created; you can use - for reading from stdin" + DeviceGroupsCreateOutputSuccess = "Created device group with ID %d\n" + DeviceGroupsCreateHelpFlag = "Displays more information about the create subcommand" + + ApplicationFlagId = "Unique identifier for the edge application that implements this Device Group. The '--application-id' flag is required" DeviceGroupFlagId = "Unique identifier for a Device Group. The '--group-id' flag is required" ) diff --git a/pkg/api/edge_applications/edge_applications.go b/pkg/api/edge_applications/edge_applications.go index 15cacfa08..654eb64ab 100644 --- a/pkg/api/edge_applications/edge_applications.go +++ b/pkg/api/edge_applications/edge_applications.go @@ -506,3 +506,22 @@ func (c *Client) DeleteDeviceGroup(ctx context.Context, appID int64, groupID int return nil } + +type CreateDeviceGroupsRequest struct { + sdk.CreateDeviceGroupsRequest +} + +type DeviceGroupsResponse interface { + GetId() int64 + GetName() string + GetUserAgent() string +} + +func (c *Client) CreateDeviceGroups(ctx context.Context, req *CreateDeviceGroupsRequest, applicationID int64) (DeviceGroupsResponse, error) { + resp, httpResp, err := c.apiClient.EdgeApplicationsDeviceGroupsApi.EdgeApplicationsEdgeApplicationIdDeviceGroupsPost(ctx, applicationID). + CreateDeviceGroupsRequest(req.CreateDeviceGroupsRequest).Execute() + if err != nil { + return nil, utils.ErrorPerStatusCode(httpResp, err) + } + return &resp.Results, nil +} diff --git a/pkg/api/edge_applications/main_settings_contract_api_test.go b/pkg/api/edge_applications/main_settings_contract_api_test.go index c3749ccba..a1427939e 100644 --- a/pkg/api/edge_applications/main_settings_contract_api_test.go +++ b/pkg/api/edge_applications/main_settings_contract_api_test.go @@ -41,6 +41,10 @@ func getRequest() []byte { return b } +func token() string { + return "Token " +} + func TestEdgeApplicationsAPIContract(t *testing.T) { const host string = "https://api.azionapi.net" @@ -59,7 +63,7 @@ func TestEdgeApplicationsAPIContract(t *testing.T) { methodHttp: http.MethodGet, headers: map[string]string{ "Accept": "application/json; version=3", - "Authorization": "Token ", + "Authorization": token(), "Content-Type": "application/json", }, path: "/edge_applications", @@ -72,7 +76,7 @@ func TestEdgeApplicationsAPIContract(t *testing.T) { methodHttp: http.MethodGet, headers: map[string]string{ "Accept": "application/json; version=3", - "Authorization": "Token ", + "Authorization": token(), "Content-Type": "application/json", }, path: "/edge_applications/1673635839", @@ -85,7 +89,7 @@ func TestEdgeApplicationsAPIContract(t *testing.T) { methodHttp: http.MethodPost, headers: map[string]string{ "Accept": "application/json; version=3", - "Authorization": "Token ", + "Authorization": token(), "Content-Type": "application/json", }, path: "/edge_applications", diff --git a/pkg/cmd/device_groups/create/.fixtures/request.json b/pkg/cmd/device_groups/create/.fixtures/request.json new file mode 100644 index 000000000..7bee2c2e6 --- /dev/null +++ b/pkg/cmd/device_groups/create/.fixtures/request.json @@ -0,0 +1,4 @@ +{ + "name": "Mob123ile", + "user_agent": "Mobile|Android|iPhone" +} \ No newline at end of file diff --git a/pkg/cmd/device_groups/create/.fixtures/response.json b/pkg/cmd/device_groups/create/.fixtures/response.json new file mode 100644 index 000000000..dbac3f027 --- /dev/null +++ b/pkg/cmd/device_groups/create/.fixtures/response.json @@ -0,0 +1,8 @@ +{ + "results": { + "id": 2260, + "name": "Mob123il22e", + "user_agent": "Mobile|Android|iPhone" + }, + "schema_version": 3 +} \ No newline at end of file diff --git a/pkg/cmd/device_groups/create/create.go b/pkg/cmd/device_groups/create/create.go new file mode 100644 index 000000000..c51f5eaf8 --- /dev/null +++ b/pkg/cmd/device_groups/create/create.go @@ -0,0 +1,94 @@ +package create + +import ( + "context" + "fmt" + "github.com/MakeNowJust/heredoc" + "os" + + msg "github.com/aziontech/azion-cli/messages/device_groups" + api "github.com/aziontech/azion-cli/pkg/api/edge_applications" + + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/utils" + sdk "github.com/aziontech/azionapi-go-sdk/edgeapplications" + "github.com/spf13/cobra" +) + +type Fields struct { + ApplicationID int64 + Name string + UserAgent string + Path string +} + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + fields := &Fields{} + + cmd := &cobra.Command{ + Use: msg.DeviceGroupsUsage, + Short: msg.DeviceGroupsShortDescription, + Long: msg.DeviceGroupsLongDescription, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(` + $ azioncli device_groups create --application-id 1673635839 --name "asdf" --user-agent "httpbin.org" + $ azioncli device_groups create -a 1673635839 --name "asdf" --user-agent "httpbin.org" + $ azioncli device_groups create -a 1673635839 --in "create.json" + `), + RunE: func(cmd *cobra.Command, args []string) error { + request := api.CreateDeviceGroupsRequest{} + if cmd.Flags().Changed("in") { + var ( + file *os.File + err error + ) + if fields.Path == "-" { + file = os.Stdin + } else { + file, err = os.Open(fields.Path) + if err != nil { + return fmt.Errorf("%w: %s", utils.ErrorOpeningFile, fields.Path) + } + } + err = cmdutil.UnmarshallJsonFromReader(file, &request) + if err != nil { + return utils.ErrorUnmarshalReader + } + } else { + if !cmd.Flags().Changed("application-id") || !cmd.Flags().Changed("name") || + !cmd.Flags().Changed("user-agent") { // flags requireds + return msg.ErrorMandatoryCreateFlags + } + + request.SetName(fields.Name) + request.SetUserAgent(fields.UserAgent) + } + + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + response, err := client.CreateDeviceGroups(context.Background(), &request, fields.ApplicationID) + if err != nil { + return fmt.Errorf(msg.ErrorCreateDeviceGroups.Error(), err) + } + fmt.Fprintf(f.IOStreams.Out, msg.DeviceGroupsCreateOutputSuccess, response.GetId()) + return nil + }, + } + + flags := cmd.Flags() + flags.Int64VarP(&fields.ApplicationID, "application-id", "a", 0, msg.DeviceGroupsCreateFlagEdgeApplicationId) + flags.StringVar(&fields.Name, "name", "", msg.DeviceGroupsCreateFlagName) + flags.StringVar(&fields.UserAgent, "user-agent", "", msg.DeviceGroupsCreateFlagUserAgent) + flags.StringVar(&fields.Path, "in", "", msg.DeviceGroupsCreateFlagIn) + flags.BoolP("help", "h", false, msg.DeviceGroupsFlagHelp) + return cmd +} + +func prepareAddresses(addrs []string) (addresses []sdk.CreateOriginsRequestAddresses) { + var addr sdk.CreateOriginsRequestAddresses + for _, v := range addrs { + addr.Address = v + addresses = append(addresses, addr) + } + return +} diff --git a/pkg/cmd/device_groups/create/create_test.go b/pkg/cmd/device_groups/create/create_test.go new file mode 100644 index 000000000..09570443d --- /dev/null +++ b/pkg/cmd/device_groups/create/create_test.go @@ -0,0 +1,86 @@ +package create + +import ( + "fmt" + "net/http" + "testing" + + msg "github.com/aziontech/azion-cli/messages/device_groups" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/require" +) + +func TestCreate(t *testing.T) { + t.Run("create new device groups", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("POST", "edge_applications/1673635846/device_groups"), + httpmock.JSONFromFile(".fixtures/response.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + cmd.SetArgs([]string{ + "--application-id", "1673635846", + "--name", "Mob123il22e", + "--user-agent", "Mobile|Android|iPhone", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.Equal(t, fmt.Sprintf(msg.DeviceGroupsCreateOutputSuccess, 2260), stdout.String()) + }) + + t.Run("create with file", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("POST", "edge_applications/1673635846/device_groups"), + httpmock.JSONFromFile(".fixtures/response.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + cmd.SetArgs([]string{ + "--application-id", "1673635846", + "--in", ".fixtures/request.json", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.Equal(t, fmt.Sprintf(msg.DeviceGroupsCreateOutputSuccess, 2260), stdout.String()) + }) + + t.Run("bad request status 400", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("POST", "edge_applications/1673635846/device_groups"), + httpmock.StatusStringResponse(http.StatusBadRequest, "Invalid"), + ) + + f, _, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + err := cmd.Execute() + require.Error(t, err) + }) + + t.Run("internal server error 500", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("POST", "edge_applications/1673635846/device_groups"), + httpmock.StatusStringResponse(http.StatusInternalServerError, "Invalid"), + ) + + f, _, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + err := cmd.Execute() + require.Error(t, err) + }) +} diff --git a/pkg/cmd/device_groups/device_groups.go b/pkg/cmd/device_groups/device_groups.go index 56ae546b9..cafdfe9a7 100644 --- a/pkg/cmd/device_groups/device_groups.go +++ b/pkg/cmd/device_groups/device_groups.go @@ -3,8 +3,9 @@ package device_groups import ( "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/device_groups" - "github.com/aziontech/azion-cli/pkg/cmd/device_groups/list" + "github.com/aziontech/azion-cli/pkg/cmd/device_groups/create" "github.com/aziontech/azion-cli/pkg/cmd/device_groups/delete" + "github.com/aziontech/azion-cli/pkg/cmd/device_groups/list" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/spf13/cobra" ) @@ -23,7 +24,8 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { } deviceGroupsCmd.AddCommand(list.NewCmd(f)) - deviceGroupsCmd.AddCommand(delete.NewCmd(f)) + deviceGroupsCmd.AddCommand(delete.NewCmd(f)) + deviceGroupsCmd.AddCommand(create.NewCmd(f)) deviceGroupsCmd.Flags().BoolP("help", "h", false, msg.DeviceGroupsFlagHelp) return deviceGroupsCmd }