Skip to content

Commit

Permalink
Merge pull request #289 from aziontech/feat-origins-created
Browse files Browse the repository at this point in the history
Feat: create command create to origins
  • Loading branch information
maxwelbm authored Feb 10, 2023
2 parents 88ad5db + 83d66b7 commit 7cc2a22
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 19 deletions.
3 changes: 3 additions & 0 deletions messages/origins/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ var (
ErrorGetOrigin = errors.New("Failed to describe the origin. Check your settings and try again. If the error persists, contact Azion support.")
ErrorMissingApplicationIDArgument = errors.New("A required flag is missing. You must supply an application_id as an argument. Run 'azioncli origins list --help' command to display more information and try again")
ErrorMissingArguments = errors.New("A required flag is missing. You must supply an application_id and origin_id as an argument. Run 'azioncli origins list --help' command to display more information and try again")
ErrorMandatoryCreateFlags = errors.New("A mandatory flag is missing. You must provide --application-id, --name, --addresses and --host-header flags when the --application-id and --in flag is not provided. Run the command 'azioncli domains create --help' to display more information and try again.")
ErrorHmacAuthenticationFlag = errors.New("Invalid --hmac-authentication flag provided. The flag must have 'true' or 'false' values. Run the command 'azioncli domains <subcommand> --help' to display more information and try again.")
ErrorCreateOrigin = errors.New("Failed to create the Origin: %s. Check your settings and try again. If the error persists, contact Azion support.")
)
55 changes: 37 additions & 18 deletions messages/origins/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,47 @@ package origins

var (
// [ origins ]
OriginsUsage = "origins"
OriginsShortDescription = "Origins is where data is fetched when the cache is not available."
OriginsLongDescription = "Origins is the original source of data in content delivery systems (CDN), where data is fetched when cache is not available. Data is stored at origin and can be retrieved by clients through cache servers distributed around the world. The fetch is done from the cache first, and if the data is not available, it is fetched from origin and saved in the cache for future use. This allows for fast data delivery."
OriginsFlagHelp = "Displays more information about the origins command"
OriginsUsage = "origins"
OriginsShortDescription = "Origins is where data is fetched when the cache is not available."
OriginsLongDescription = "Origins is the original source of data in content delivery systems (CDN) where data is fetched when cache is not available. Data is stored at origin and can be retrieved by clients through cache servers distributed around the world. The fetch is done from the cache first, and if the data is not available, it is fetched from origin and saved in the cache for future use. This allows for fast data delivery."
OriginsFlagHelp = "Displays more information about the origins command"

// [ list ]
OriginsListUsage = "list [flags]"
OriginsListShortDescription = "Displays yours origins"
OriginsListLongDescription = "Displays all your origins references to your edges"
OriginsListHelpFlag = "Displays more information about the list subcommand"
OriginsListFlagEdgeApplicationID = "Is a unique identifier for the edge application that references the origins to direct data requests correctly."
OriginsListUsage = "list [flags]"
OriginsListShortDescription = "Displays yours origins"
OriginsListLongDescription = "Displays all your origins references to your edges"
OriginsListHelpFlag = "Displays more information about the list subcommand"
OriginsListFlagEdgeApplicationID = "Is a unique identifier for the edge application that references the origins to direct data requests correctly."

// [ describe ]
OriginsDescribeUsage = "describe --application-id <domain_id> --origin-id <origin_id> [flags]"
OriginsDescribeShortDescription = "Returns the origin data"
OriginsDescribeLongDescription = "Displays information about the origin via a given ID to show the application’s attributes in detail"
OriginsDescribeFlagApplicationID = "Is a unique identifier for the edge application that references the origins to direct data requests correctly."
OriginsDescribeFlagOriginID = `is a unique identifier that identifies an "origins" in a list of results returned by the API. The "GetOrigin" function uses the "Origin Id" to search for the desired "origins" and returns an error if it is not found.`
OriginsDescribeFlagOut = "Exports the output to the given <file_path/file_name.ext>"
OriginsDescribeFlagFormat = "Changes the output format passing the json value to the flag"
OriginsDescribeHelpFlag = "Displays more information about the describe command"
OriginsDescribeUsage = "describe --application-id <domain_id> --origin-id <origin_id> [flags]"
OriginsDescribeShortDescription = "Returns the origin data"
OriginsDescribeLongDescription = "Displays information about the origin via a given ID to show the application’s attributes in detail"
OriginsDescribeFlagApplicationID = "Is a unique identifier for the edge application that references the origins to direct data requests correctly."
OriginsDescribeFlagOriginID = `is a unique identifier that identifies an "origins" in a list of results returned by the API. The "GetOrigin" function uses the "Origin Id" to search for the desired "origins" and returns an error if it is not found.`
OriginsDescribeFlagOut = "Exports the output to the given <file_path/file_name.ext>"
OriginsDescribeFlagFormat = "Changes the output format passing the json value to the flag"
OriginsDescribeHelpFlag = "Displays more information about the describe command"

// [ create ]
OriginsCreateUsage = "create [flags]"
OriginsCreateShortDescription = "Makes a new origin"
OriginsCreateLongDescription = "Makes a Origin based on given attributes to be used in Edge Applications"
OriginsCreateFlagEdgeApplicationId = "The Edge Application's unique identifier"
OriginsCreateFlagName = "The Origin name"
OriginsCreateFlagOriginType = "Origin Type is a field used to identify the source of a record. It is typically used to differentiate between records that were created manually or automatically. For example, a record may have an Origin Type of 'Manual' if it was created by a user, or 'Automatic' if it was created by a system. Origin Type can also be used to differentiate between records that were imported from an external source, such as a CSV file, or created within the system."
OriginsCreateFlagAddresses = "Addresses linked to origins"
OriginsCreateFlagOriginProtocolPolicy = "Is an origin protocol policy that specifies how Amazon CloudFront should respond to requests for content. This policy specifies whether CloudFront should use the origin protocol (HTTP or HTTPS) to get content from an origin server, or whether it should use the origin protocol regardless of the protocol used for the request."
OriginsCreateFlagHostHeader = "The HostHeader is an HTTP header field that specifies the hostname of the server being accessed. It is used to identify which website or application is being accessed. The HostHeader is sent by the browser to the web server and is used to determine which website or application to load."
OriginsCreateFlagOriginPath = "OriginPath is a file path that is used to identify the source of a file or directory. It is typically used to track the original location of a file or directory before it was moved or copied to a new location. OriginPath is often used in backup and restore operations to ensure that the original file or directory is not overwritten or lost."
OriginsCreateFlagHmacAuthentication = "HmacAuthentication is a type of authentication that uses a cryptographic hash function to verify the integrity of a message. It is a form of message authentication code (MAC) that uses a shared secret key between two parties to generate a signature for a message. The signature is then used to verify that the message has not been tampered with or altered in any way. HmacAuthentication is used to ensure that the message is authentic and has not been modified in transit. It is commonly used in web applications and APIs to secure data transmission"
OriginsCreateFlagHmacRegionName = "HmacRegionName is a field used in the Amazon Web Services (AWS) API to identify the region in which a particular request is being made. It is used to ensure that requests are routed to the correct region and that the correct authentication credentials are used."
OriginsCreateFlagHmacAccessKey = "HmacAccessKey is a type of authentication key used to access an API or other secure system. It is a combination of a secret key and a cryptographic hash algorithm, such as SHA-256, to generate a unique signature for each request. The signature is then used to verify the authenticity of the request and ensure that it has not been tampered with. HmacAccessKey is often used in combination with other authentication methods, such as OAuth or API keys, to provide an additional layer of security."
OriginsCreateFlagHmacSecretKey = "HmacSecretKey is a type of cryptographic key used in the HMAC (Hash-based Message Authentication Code) algorithm. It is a secret key that is used to generate a cryptographic hash of a message, which is then used to verify the authenticity and integrity of the message. The key is typically a string of random characters that is known only to the sender and receiver of the message."
OriginsCreateFlagIn = " Path to a JSON file containing the attributes that will be updated; you can use - for reading from stdin"
OriginsCreateOutputSuccess = "Created origin with ID %d\n"
OriginsCreateHelpFlag = "Displays more information about the create subcommand"

// [ general ]
OriginsFileWritten = "File successfully written to: %s\n"
OriginsFileWritten = "File successfully written to: %s\n"
)
18 changes: 17 additions & 1 deletion pkg/api/edge_applications/edge_applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/aziontech/azion-cli/pkg/contracts"

"github.com/aziontech/azion-cli/pkg/cmd/version"
"github.com/aziontech/azion-cli/utils"
sdk "github.com/aziontech/azionapi-go-sdk/edgeapplications"
Expand Down Expand Up @@ -207,6 +206,15 @@ func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (sdk.Get
return resp, nil
}

type CreateOriginsRequest struct {
sdk.CreateOriginsRequest
}

type OriginsResponse interface {
GetOriginId() int64
GetName() string
}

func (c *Client) GetOrigin(ctx context.Context, edgeApplicationID, originID int64) (sdk.OriginsResultResponse, error) {
resp, httpResp, err := c.apiClient.EdgeApplicationsOriginsApi.EdgeApplicationsEdgeApplicationIdOriginsGet(ctx, edgeApplicationID).Execute()
if err != nil {
Expand All @@ -229,3 +237,11 @@ func (c *Client) ListOrigins(ctx context.Context, opts *contracts.ListOptions, e
}
return resp, nil
}

func (c *Client) CreateOrigins(ctx context.Context, edgeApplicationID int64, req *CreateOriginsRequest) (OriginsResponse, error) {
resp, httpResp, err := c.apiClient.EdgeApplicationsOriginsApi.EdgeApplicationsEdgeApplicationIdOriginsPost(ctx, edgeApplicationID).CreateOriginsRequest(req.CreateOriginsRequest).Execute()
if err != nil {
return nil, utils.ErrorPerStatusCode(httpResp, err)
}
return &resp.Results, nil
}
138 changes: 138 additions & 0 deletions pkg/cmd/origins/create/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package create

import (
"strconv"
"context"
"fmt"
"os"

"github.com/MakeNowJust/heredoc"

msg "github.com/aziontech/azion-cli/messages/origins"
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
OriginType string
Addresses []string
OriginProtocolPolicy string
HostHeader string
OriginPath string
HmacAuthentication string
HmacRegionName string
HmacAccessKey string
HmacSecretKey string
Path string
}

func NewCmd(f *cmdutil.Factory) *cobra.Command {
fields := &Fields{}

cmd := &cobra.Command{
Use: msg.OriginsCreateUsage,
Short: msg.OriginsCreateShortDescription,
Long: msg.OriginsCreateLongDescription,
SilenceUsage: true,
SilenceErrors: true,
Example: heredoc.Doc(`
$ azioncli origins create --application-id 1673635839 --name "ffcafe222sdsdffdf" --addresses "httpbin.org" --host-header "asdf.safe" --origin-type "single_origin" --origin-protocol-policy "http" --origin-path "/requests" --hmac-authentication "false"
$ azioncli origins create --application-id 1673635839 --name "drink coffe" --addresses "asdfg.asd" --host-header "host"
$ azioncli origins create --application-id 1673635839 --in "create.json"
`),
RunE: func(cmd *cobra.Command, args []string) error {
request := api.CreateOriginsRequest{}
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("addresses") || !cmd.Flags().Changed("host-header") { // flags requireds
return msg.ErrorMandatoryCreateFlags
}

request.SetName(fields.Name)
request.SetAddresses(prepareAddresses(fields.Addresses))
request.SetHostHeader(fields.HostHeader)
if cmd.Flags().Changed("origin-type") {
request.SetOriginType(fields.OriginType)
}
if cmd.Flags().Changed("origin-protocol-policy") {
request.SetOriginProtocolPolicy(fields.OriginProtocolPolicy)
}
if cmd.Flags().Changed("origin-path") {
request.SetOriginPath(fields.OriginPath)
}
if cmd.Flags().Changed("hmac-authentication") {
hmacAuth, err := strconv.ParseBool(fields.HmacAuthentication)
if err != nil {
return fmt.Errorf("%w: %q", msg.ErrorHmacAuthenticationFlag, fields.HmacAuthentication)
}
request.SetHmacAuthentication(hmacAuth)
}
if cmd.Flags().Changed("hmac-region-name") {
request.SetHmacRegionName(fields.HmacRegionName)
}
if cmd.Flags().Changed("hmac-access-key") {
request.SetHmacAccessKey(fields.HmacAccessKey)
}
if cmd.Flags().Changed("hmac-secret-key") {
request.SetHmacSecretKey(fields.HmacSecretKey)
}
}

client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token"))
response, err := client.CreateOrigins(context.Background(), fields.ApplicationID, &request)
if err != nil {
return fmt.Errorf(msg.ErrorCreateOrigin.Error(), err)
}
fmt.Fprintf(f.IOStreams.Out, msg.OriginsCreateOutputSuccess, response.GetOriginId())
return nil
},
}

flags := cmd.Flags()
flags.Int64VarP(&fields.ApplicationID, "application-id", "a", 0, msg.OriginsCreateFlagEdgeApplicationId)
flags.StringVar(&fields.Name, "name", "", msg.OriginsCreateFlagName)
flags.StringVar(&fields.OriginType, "origin-type", "", msg.OriginsCreateFlagOriginType)
flags.StringSliceVar(&fields.Addresses, "addresses", []string{}, msg.OriginsCreateFlagAddresses)
flags.StringVar(&fields.OriginProtocolPolicy, "origin-protocol-policy", "", msg.OriginsCreateFlagOriginProtocolPolicy)
flags.StringVar(&fields.HostHeader, "host-header", "", msg.OriginsCreateFlagHostHeader)
flags.StringVar(&fields.OriginPath, "origin-path", "", msg.OriginsCreateFlagOriginPath)
flags.StringVar(&fields.HmacAuthentication, "hmac-authentication", "", msg.OriginsCreateFlagHmacAuthentication)
flags.StringVar(&fields.HmacRegionName, "hmac-region-name", "", msg.OriginsCreateFlagHmacRegionName)
flags.StringVar(&fields.HmacAccessKey, "hmac-access-key", "", msg.OriginsCreateFlagHmacAccessKey)
flags.StringVar(&fields.HmacSecretKey, "hmac-secret-key", "", msg.OriginsCreateFlagHmacSecretKey)
flags.StringVar(&fields.Path, "in", "", msg.OriginsCreateFlagIn)
flags.BoolP("help", "h", false, msg.OriginsCreateHelpFlag)
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
}
87 changes: 87 additions & 0 deletions pkg/cmd/origins/create/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package create

import (
"fmt"
"net/http"
"testing"

msg "github.com/aziontech/azion-cli/messages/origins"
"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 domains", func(t *testing.T) {
mock := &httpmock.Registry{}

mock.Register(
httpmock.REST("POST", "edge_applications/1673635841/origins"),
httpmock.JSONFromFile("./fixtures/response.json"),
)

f, stdout, _ := testutils.NewFactory(mock)
cmd := NewCmd(f)
cmd.SetArgs([]string{
"--application-id", "1673635841",
"--name", "one piece is the best",
"--addresses", "asdfsd.cvdf",
"--host-header", "asdfsdfsd.cvdf",
})

err := cmd.Execute()
require.NoError(t, err)
require.Equal(t, fmt.Sprintf(msg.OriginsCreateOutputSuccess, 92779), stdout.String())
})

t.Run("create with file", func(t *testing.T) {
mock := &httpmock.Registry{}

mock.Register(
httpmock.REST("POST", "edge_applications/1673635841/origins"),
httpmock.JSONFromFile("./fixtures/response.json"),
)

f, stdout, _ := testutils.NewFactory(mock)

cmd := NewCmd(f)
cmd.SetArgs([]string{
"--application-id", "1673635841",
"--in", "./fixtures/create.json",
})

err := cmd.Execute()
require.NoError(t, err)
require.Equal(t, fmt.Sprintf(msg.OriginsCreateOutputSuccess, 92779), stdout.String())
})

t.Run("bad request status 400", func(t *testing.T) {
mock := &httpmock.Registry{}

mock.Register(
httpmock.REST("POST", "edge_applications/1673635841/origin"),
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/1673635841/origin"),
httpmock.StatusStringResponse(http.StatusInternalServerError, "Invalid"),
)

f, _, _ := testutils.NewFactory(mock)

cmd := NewCmd(f)
err := cmd.Execute()
require.Error(t, err)
})
}
9 changes: 9 additions & 0 deletions pkg/cmd/origins/create/fixtures/create.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "Create Or22i21231222n2",
"addresses": [
{
"address": "httpbin.org"
}
],
"host_header": "asdf.asdfom"
}
28 changes: 28 additions & 0 deletions pkg/cmd/origins/create/fixtures/response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"results": {
"origin_id": 92779,
"origin_key": "176fa5e2-a895-4862-9657-e2e37d9125a7",
"name": "Create Or22i21231222n2",
"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": "asdf.asdfom",
"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
}
Loading

0 comments on commit 7cc2a22

Please sign in to comment.