diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml index e468d9096..6e1d6e138 100644 --- a/.github/workflows/deploy_prod.yml +++ b/.github/workflows/deploy_prod.yml @@ -34,9 +34,13 @@ jobs: run: git fetch --tags - name: Build + env: + STORAGE_API: ${{ secrets.STORAGE_API_STAGE }} run: make build ENVFILE=./env/prod - name: Cross-build + env: + STORAGE_API: ${{ secrets.STORAGE_API_STAGE }} run: make cross-build ENVFILE=./env/prod - name: Install AWS CLI @@ -76,5 +80,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} API_URL: https://api.azionapi.net + STORAGE_URL: ${{ secrets.STORAGE_API_STAGE }} AUTH_URL: https://sso.azion.com/api/user/me TEMPLATE_BRANCH: main diff --git a/.github/workflows/deploy_stage.yml b/.github/workflows/deploy_stage.yml index fb12f52ae..37fc02d02 100644 --- a/.github/workflows/deploy_stage.yml +++ b/.github/workflows/deploy_stage.yml @@ -38,12 +38,14 @@ jobs: env: AZION_API: ${{ secrets.AZION_API_STAGE }} AZION_SSO: ${{ secrets.AZION_SSO_STAGE }} + STORAGE_API: ${{ secrets.STORAGE_API_STAGE }} run: make build ENVFILE=./env/stage - name: Cross-build env: AZION_API: ${{ secrets.AZION_API_STAGE }} AZION_SSO: ${{ secrets.AZION_SSO_STAGE }} + STORAGE_API: ${{ secrets.STORAGE_API_STAGE }} run: make cross-build ENVFILE=./env/stage - name: Install AWS CLI diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 3d3883cb4..eea7f88ce 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -8,6 +8,7 @@ builds: - -X github.com/aziontech/azion-cli/pkg/cmd/version.BinVersion={{ .Env.BIN_VERSION }} - -X github.com/aziontech/azion-cli/pkg/constants.AuthURL={{ .Env.AUTH_URL }} - -X github.com/aziontech/azion-cli/pkg/constants.ApiURL={{ .Env.API_URL }} + - -X github.com/aziontech/azion-cli/pkg/constants.StorageApiURL={{ .Env.STORAGE_URL }} - -X github.com/aziontech/azion-cli/pkg/pkg/cmd/edge_applications/init.TemplateBranch={{ .Env.TEMPLATE_BRANCH }} binary: azioncli goos: diff --git a/Makefile b/Makefile index 4fdabb9df..962937127 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ BIN := azioncli BIN_VERSION=$(shell git describe --tags) # The variables with $$ should be sourced from an envfile LDFLAGS=-X github.com/aziontech/azion-cli/pkg/cmd/version.BinVersion=$(BIN_VERSION) \ + -X github.com/aziontech/azion-cli/pkg/constants.StorageApiURL=$$STORAGE_URL \ -X github.com/aziontech/azion-cli/pkg/constants.AuthURL=$$AUTH_URL \ -X github.com/aziontech/azion-cli/pkg/constants.ApiURL=$$API_URL \ -X github.com/aziontech/azion-cli/pkg/cmd/edge_applications/init.TemplateBranch=$$TEMPLATE_BRANCH \ diff --git a/env/prod b/env/prod index b51c5f271..d574c64e3 100644 --- a/env/prod +++ b/env/prod @@ -1,4 +1,5 @@ API_URL=https://api.azionapi.net AUTH_URL=https://sso.azion.com/api/user/me +STORAGE_URL=${STORAGE_API} TEMPLATE_BRANCH=main TEMPLATE_MAJOR=0 \ No newline at end of file diff --git a/env/stage b/env/stage index 4b742e92c..9304c5fda 100644 --- a/env/stage +++ b/env/stage @@ -1,4 +1,5 @@ API_URL=https://${AZION_API} AUTH_URL=https://${AZION_SSO}/api/user/me +STORAGE_URL=https://${STORAGE_API} TEMPLATE_BRANCH=dev -TEMPLATE_MAJOR=0 +TEMPLATE_MAJOR=0 \ No newline at end of file diff --git a/go.mod b/go.mod index 23d1f1461..a192e70b5 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/aziontech/azion-cli go 1.17 require ( - github.com/MaxwelMazur/tablecli v0.0.0-20230111205821-634576290228 - github.com/aziontech/azionapi-go-sdk v0.20.0 + github.com/MaxwelMazur/tablecli v0.0.0-20230208145104-c9458b902b58 + github.com/aziontech/azionapi-go-sdk v0.23.0 github.com/fatih/color v1.13.0 github.com/go-git/go-git/v5 v5.4.2 github.com/spf13/cobra v1.6.1 @@ -52,6 +52,7 @@ require ( github.com/spf13/afero v1.9.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect diff --git a/go.sum b/go.sum index a552197d8..7e0509d02 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/MaxwelMazur/tablecli v0.0.0-20230111205821-634576290228 h1:0v/h/69n72chjEeAWInSZ+0+WVGff/e/HK71DxcZPOo= -github.com/MaxwelMazur/tablecli v0.0.0-20230111205821-634576290228/go.mod h1:XTbnIbjcCDbZenA2rqSIQK9aa4MSL//Wt/b04tgdCO4= +github.com/MaxwelMazur/tablecli v0.0.0-20230208145104-c9458b902b58 h1:bqFhGlAuzkZzX+2P6fwKhg4PECvXF7Lr8V6g2iDrG0s= +github.com/MaxwelMazur/tablecli v0.0.0-20230208145104-c9458b902b58/go.mod h1:eepQZpVhQN9tZIbJ+/nLb+Gi/vUAjzQsB0eLhfnB5gk= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -212,8 +212,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aziontech/azionapi-go-sdk v0.20.0 h1:a4hYtDlYMehwDBNGKaSgTFnKG9NNyjyE37HIsjlmGc8= -github.com/aziontech/azionapi-go-sdk v0.20.0/go.mod h1:2caFKH52viwZI346MWCGDZzU0jGll6udJZZMDJNrWgg= +github.com/aziontech/azionapi-go-sdk v0.23.0 h1:hVRgXSAwmX5MSx2Mhjpd1ifuL34zZAZLvFBSmEDLKz0= +github.com/aziontech/azionapi-go-sdk v0.23.0/go.mod h1:wL7eJYyE2qU853U2iKnQuFHoY69N5WwGnQJwySsdtX0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -471,6 +471,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -524,6 +525,7 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= @@ -556,6 +558,7 @@ github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+eg github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/messages/edge_applications/errors.go b/messages/edge_applications/errors.go index fd06b9cdf..321dc0d04 100644 --- a/messages/edge_applications/errors.go +++ b/messages/edge_applications/errors.go @@ -63,4 +63,6 @@ var ( ErrorMissingApplicationIdJson = errors.New("Application ID is missing from azion.json. Please initialize and publish your project first before using cascade delete") ErrorMissingAzionJson = errors.New("Azion.json file is missing. Please initialize and publish your project first before using cascade delete") ErrorFailedUpdateAzionJson = errors.New("Failed to update azion.json file to remove IDs of deleted resource") + + ErrorGetVersionId = errors.New("Failed to get Version Id: %s") ) diff --git a/messages/edge_applications/messages.go b/messages/edge_applications/messages.go index fb059fbdd..5f648369c 100644 --- a/messages/edge_applications/messages.go +++ b/messages/edge_applications/messages.go @@ -8,18 +8,18 @@ var ( //edge_applications cmd EdgeApplicationsUsage = "edge_applications" - EdgeApplicationsShortDescription = "Creates Web Applications on Azion's platform" - EdgeApplicationsLongDescription = "Build your Web applications in minutes without the need to manage infrastructure or security" + EdgeApplicationsShortDescription = "Creates Edge Applications on Azion's platform" + EdgeApplicationsLongDescription = "Build your Edge applications in minutes without the need to manage infrastructure or security" EdgeApplicationsFlagHelp = "Displays more information about the edge_application command" EdgeApplicationsAutoDetectec = "Auto-detected Project Settings (%s)\n" //build cmd EdgeApplicationsBuildUsage = "build [flags]" - EdgeApplicationsBuildShortDescription = "Builds a Web Application" - EdgeApplicationsBuildLongDescription = "Builds your Web Application to run on Azion’s Edge Computing Platform" + EdgeApplicationsBuildShortDescription = "Builds an Edge Application" + EdgeApplicationsBuildLongDescription = "Builds your Edge Application to run on Azion’s Edge Computing Platform" EdgeApplicationsBuildRunningCmd = "Running build step command:\n\n" - EdgeApplicationsBuildStart = "Building your Web Application\n" - EdgeApplicationsBuildSuccessful = "Your Web Application was built successfully\n" + EdgeApplicationsBuildStart = "Building your Edge Application\n" + EdgeApplicationsBuildSuccessful = "Your Edge Application was built successfully\n" EdgeApplicationsBuildFlagHelp = "Displays more information about the build subcommand" EdgeApplicationsBuildCdn = "Skipping build step. Build isn't applied to the type 'CDN'" @@ -30,11 +30,11 @@ var ( javascript Create a serverless Javascript application on edge. flareact Create a serverless Flareact application on edge. nextjs Create a serverless NextJS edge-runtime application on edge.` - EdgeApplicationsInitShortDescription = "Initializes a Web Application" - EdgeApplicationsInitLongDescription = "Defines primary parameters based on a given name and application type to start a Web Application on Azion’s platform" + EdgeApplicationsInitShortDescription = "Initializes an Edge Application" + EdgeApplicationsInitLongDescription = "Defines primary parameters based on a given name and application type to start a Edge Application on Azion’s platform" EdgeApplicationsInitRunningCmd = "Running init step command:\n\n" - EdgeApplicationsInitFlagName = "The Web application's name" - EdgeApplicationsInitFlagType = "The type of Web application " + EdgeApplicationsInitFlagName = "The Edge application's name" + EdgeApplicationsInitFlagType = "The type of Edge application " EdgeApplicationsInitFlagYes = "Forces the automatic response 'yes' to all user input" EdgeApplicationsInitFlagNo = "Forces the automatic response 'no' to all user input" WebAppInitContentOverridden = "This project was already configured. Do you want to override the previous configuration? (default: no) " @@ -47,10 +47,10 @@ var ( //publish cmd EdgeApplicationsPublishUsage = "publish" - EdgeApplicationsPublishShortDescription = "Publishes a Web Application on the Azion platform" - EdgeApplicationsPublishLongDescription = "Publishes a Web Application based on the Azion’s Platform" + EdgeApplicationsPublishShortDescription = "Publishes an Edge Application on the Azion platform" + EdgeApplicationsPublishLongDescription = "Publishes an Edge Application based on the Azion’s Platform" EdgeApplicationsPublishRunningCmd = "Running pre publish command:\n\n" - EdgeApplicationsPublishSuccessful = "Your Web Application was published successfully\n" + EdgeApplicationsPublishSuccessful = "Your Edge Application was published successfully\n" EdgeApplicationsCdnPublishSuccessful = "Your CDN Edge Application was published successfully\n" EdgeApplicationsPublishOutputDomainSuccess = "\nTo visualize your application access the domain: %s\n" EdgeApplicationsPublishOutputCachePurge = "Domain cache was purged\n" diff --git a/messages/origins/errors.go b/messages/origins/errors.go new file mode 100644 index 000000000..3362a8eea --- /dev/null +++ b/messages/origins/errors.go @@ -0,0 +1,17 @@ +package origins + +import "errors" + +var ( + ErrorGetOrigins = errors.New("Failed to describe the origins: %s. Check your settings and try again. If the error persists, contact Azion support.") + 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 application-id as an argument. Run 'azioncli --help' command to display more information and try again") + ErrorMissingArguments = errors.New("Required flags are missing. You must supply application-id and origin-id as arguments. Run 'azioncli --help' command to display more information and try again") + ErrorMissingArgumentsDelete = errors.New("Required flags are missing. You must supply application-id and origin-key as arguments. Run 'azioncli --help' command to display more information and try again") + ErrorMandatoryCreateFlags = errors.New("Required flags are missing. You must provide application-id, name, addresses and host-header flags when the --application-id and --in flag are not provided. Run the command 'azioncli --help' to display more information and try again.") + ErrorMandatoryUpdateFlags = errors.New("Required flags are missing. You must provide application-id and origin-id flags when the --application-id and --in flag are not provided. Run the command 'azioncli --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 --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.") + ErrorUpdateOrigin = errors.New("Failed to update the Origin: %s. Check your settings and try again. If the error persists, contact Azion support.") + ErrorFailToDelete = errors.New("Failed to delete the Origin: %s. Check your settings and try again. If the error persists, contact Azion support.") +) diff --git a/messages/origins/messages.go b/messages/origins/messages.go new file mode 100644 index 000000000..6d7cb74b9 --- /dev/null +++ b/messages/origins/messages.go @@ -0,0 +1,77 @@ +package origins + +var ( + // [ origins ] + OriginsUsage = "origins" + OriginsShortDescription = "Origins is the original source of data." + OriginsLongDescription = "Origins is the original source of data on edge platforms, where data is fetched when cache is not available." + OriginsFlagHelp = "Displays more information about the origins command" + + // [ list ] + OriginsListUsage = "list [flags]" + OriginsListShortDescription = "Displays your origins" + OriginsListLongDescription = "Displays all origins related to your applications" + OriginsListHelpFlag = "Displays more information about the list subcommand" + OriginsListFlagEdgeApplicationID = "Unique identifier for an edge application." + + // [ describe ] + OriginsDescribeUsage = "describe --application-id --origin-id [flags]" + OriginsDescribeShortDescription = "Returns information about a specific origin" + OriginsDescribeLongDescription = "Returns information about a specific origin, based on a given ID, in details" + OriginsDescribeFlagApplicationID = "Unique identifier for an edge application. The '--application-id' flag is mandatory" + OriginsDescribeFlagOriginID = "Unique identifier for an origin. The '--origin-id' flag is mandatory" + OriginsDescribeFlagOut = "Exports the output to the given " + OriginsDescribeFlagFormat = "Changes the output format passing the json value to the flag" + OriginsDescribeHelpFlag = "Displays more information about the describe subcommand" + + // [ create ] + OriginsCreateUsage = "create [flags]" + OriginsCreateShortDescription = "Creates a new origin" + OriginsCreateLongDescription = "Creates an origin based on given attributes to be used in edge applications" + OriginsCreateFlagEdgeApplicationId = "Unique identifier for an edge application" + OriginsCreateFlagName = "The origin's name" + OriginsCreateFlagOriginType = `Identifies the source of a record. I.e. "single_origin"` + OriginsCreateFlagAddresses = "Passes a list of addresses linked to the origin" + OriginsCreateFlagOriginProtocolPolicy = "Tells the protocol policy used in the origin" + OriginsCreateFlagHostHeader = "Specifies the hostname of the server being accessed" + OriginsCreateFlagOriginPath = "Path to be appended to the URI when forwarding the request to the origin. Leave it in blank to use only the URI" + OriginsCreateFlagHmacAuthentication = "Whether Hmac Authentication is used or not" + OriginsCreateFlagHmacRegionName = "Informs Hmac region name" + OriginsCreateFlagHmacAccessKey = "Informs Hmac Access Key" + OriginsCreateFlagHmacSecretKey = "Informs Hmac Secret Key" + OriginsCreateFlagIn = "Path to a JSON file containing the attributes of the origin that will be created; you can use - for reading from stdin" + OriginsCreateOutputSuccess = "Created origin with ID %d\n" + OriginsCreateHelpFlag = "Displays more information about the create subcommand" + + // [ update ] + OriginsUpdateUsage = "update [flags]" + OriginsUpdateShortDescription = "Updates an Origin" + OriginsUpdateLongDescription = "Updates an Origin based on its ID and given attributes" + OriginsUpdateFlagOriginKey = "The Origin's key unique identifier" + OriginsUpdateFlagEdgeApplicationId = "Unique identifier for an edge application" + OriginsUpdateFlagName = "The origin's name" + OriginsUpdateFlagOriginType = `Identifies the source of a record. I.e. "single_origin"` + OriginsUpdateFlagAddresses = "Passes a list of addresses linked to the origin" + OriginsUpdateFlagOriginProtocolPolicy = "Tells the protocol policy used in the origin" + OriginsUpdateFlagHostHeader = "Specifies the hostname of the server being accessed" + OriginsUpdateFlagOriginPath = "Path to be appended to the URI when forwarding the request to the origin. Leave it in blank to use only the URI" + OriginsUpdateFlagHmacAuthentication = "Whether Hmac Authentication is used or not" + OriginsUpdateFlagHmacRegionName = "Informs Hmac region name" + OriginsUpdateFlagHmacAccessKey = "Informs Hmac Access Key" + OriginsUpdateFlagHmacSecretKey = "Informs Hmac Secret Key" + OriginsUpdateFlagIn = "Path to a JSON file containing the attributes of the origin that will be updated; you can use - for reading from stdin" + OriginsUpdateOutputSuccess = "Updated origin with ID %s\n" + OriginsUpdateHelpFlag = "Displays more information about the update subcommand" + + // [ delete ] + OriginsDeleteUsage = "delete [flags]" + OriginsDeleteShortDescription = "Deletes an Origin" + OriginsDeleteLongDescription = "Deletes an Origin from the Edge Applications library based on its given ID" + OriginsDeleteOutputSuccess = "Origin %s was successfully deleted\n" + OriginsDeleteFlagApplicationID = "Unique identifier for an edge application" + OriginsDeleteFlagOriginKey = "The Origin's key unique identifier" + OriginsDeleteHelpFlag = "Displays more information about the delete subcommand" + + // [ general ] + OriginsFileWritten = "File successfully written to: %s\n" +) diff --git a/pkg/api/domains/domains.go b/pkg/api/domains/domains.go index 9c985101d..5deb2c2d9 100644 --- a/pkg/api/domains/domains.go +++ b/pkg/api/domains/domains.go @@ -81,11 +81,11 @@ func (c *Client) Update(ctx context.Context, req *UpdateRequest) (DomainResponse return &domainsResponse.Results, nil } -func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (sdk.DomainResponseWithResults, error) { +func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (*sdk.DomainResponseWithResults, error) { resp, httpResp, err := c.apiClient.DomainsApi.GetDomains(ctx).Execute() if err != nil { - return sdk.DomainResponseWithResults{}, utils.ErrorPerStatusCode(httpResp, err) + return &sdk.DomainResponseWithResults{}, utils.ErrorPerStatusCode(httpResp, err) } return resp, nil diff --git a/pkg/api/edge_applications/edge_applications.go b/pkg/api/edge_applications/edge_applications.go index e282eedb3..5710fac55 100644 --- a/pkg/api/edge_applications/edge_applications.go +++ b/pkg/api/edge_applications/edge_applications.go @@ -2,13 +2,13 @@ package edgeapplications import ( "context" + "errors" "net/http" "strconv" "time" - "github.com/aziontech/azion-cli/pkg/contracts" - "github.com/aziontech/azion-cli/pkg/cmd/version" + "github.com/aziontech/azion-cli/pkg/contracts" "github.com/aziontech/azion-cli/utils" sdk "github.com/aziontech/azionapi-go-sdk/edgeapplications" ) @@ -188,7 +188,7 @@ func (c *Client) Delete(ctx context.Context, id int64) error { return nil } -func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (sdk.GetApplicationsResponse, error) { +func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (*sdk.GetApplicationsResponse, error) { if opts.OrderBy == "" { opts.OrderBy = "id" } @@ -200,8 +200,70 @@ func (c *Client) List(ctx context.Context, opts *contracts.ListOptions) (sdk.Get Sort(opts.Sort).Execute() if err != nil { - return sdk.GetApplicationsResponse{}, utils.ErrorPerStatusCode(httpResp, err) + return &sdk.GetApplicationsResponse{}, utils.ErrorPerStatusCode(httpResp, err) + } + + return resp, nil +} + +type CreateOriginsRequest struct { + sdk.CreateOriginsRequest +} + +type UpdateOriginsRequest struct { + sdk.PatchOriginsRequest +} + +type OriginsResponse interface { + GetOriginKey() string + 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 { + return sdk.OriginsResultResponse{}, utils.ErrorPerStatusCode(httpResp, err) } + if len(resp.Results) > 0 { + for _, result := range resp.Results { + if result.OriginId == originID { + return result, nil + } + } + } + return sdk.OriginsResultResponse{}, utils.ErrorPerStatusCode(&http.Response{Status: "404 Not Found", StatusCode: http.StatusNotFound}, errors.New("404 Not Found")) +} +func (c *Client) ListOrigins(ctx context.Context, opts *contracts.ListOptions, edgeApplicationID int64) (*sdk.OriginsResponse, error) { + resp, httpResp, err := c.apiClient.EdgeApplicationsOriginsApi.EdgeApplicationsEdgeApplicationIdOriginsGet(ctx, edgeApplicationID).Execute() + if err != nil { + return &sdk.OriginsResponse{}, utils.ErrorPerStatusCode(httpResp, err) + } 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 +} + +func (c *Client) UpdateOrigins(ctx context.Context, edgeApplicationID int64, originKey string, req *UpdateOriginsRequest) (OriginsResponse, error) { + resp, httpResp, err := c.apiClient.EdgeApplicationsOriginsApi. + EdgeApplicationsEdgeApplicationIdOriginsOriginKeyPatch(ctx, edgeApplicationID, originKey).PatchOriginsRequest(req.PatchOriginsRequest).Execute() + if err != nil { + return nil, utils.ErrorPerStatusCode(httpResp, err) + } + return &resp.Results, nil +} + +func (c *Client) DeleteOrigins(ctx context.Context, edgeApplicationID int64, originKey string) error { + httpResp, err := c.apiClient.EdgeApplicationsOriginsApi.EdgeApplicationsEdgeApplicationIdOriginsOriginKeyDelete(ctx, edgeApplicationID, originKey).Execute() + if err != nil { + return utils.ErrorPerStatusCode(httpResp, err) + } + return nil +} diff --git a/pkg/api/storage_api/storage_api.go b/pkg/api/storage_api/storage_api.go new file mode 100644 index 000000000..d533792e0 --- /dev/null +++ b/pkg/api/storage_api/storage_api.go @@ -0,0 +1,50 @@ +package storageapi + +import ( + "context" + "net/http" + "time" + + "github.com/aziontech/azion-cli/pkg/cmd/version" + "github.com/aziontech/azion-cli/utils" + sdk "github.com/aziontech/azionapi-go-sdk/storageapi" +) + +type Client struct { + apiClient *sdk.APIClient +} + +type CreateRequest struct { + sdk.ApiCreateVersionRequest +} + +type VersionIdResponse interface { + GetVersionId() string +} + +func NewClient(c *http.Client, url string, token string) *Client { + conf := sdk.NewConfiguration() + conf.HTTPClient = c + conf.AddDefaultHeader("Authorization", "token "+token) + conf.AddDefaultHeader("Accept", "application/json;version=3") + conf.UserAgent = "Azion_CLI/" + version.BinVersion + conf.Servers = sdk.ServerConfigurations{ + {URL: url}, + } + conf.HTTPClient.Timeout = 30 * time.Second + + return &Client{ + apiClient: sdk.NewAPIClient(conf), + } +} + +func (c *Client) CreateVersionId(ctx context.Context, id string) (VersionIdResponse, error) { + req := c.apiClient.EdgeApplicationsApi.CreateVersion(ctx, id) + + res, httpResp, err := req.Execute() + if err != nil { + return nil, utils.ErrorPerStatusCode(httpResp, err) + } + + return res, nil +} diff --git a/pkg/cmd/edge_applications/build/build.go b/pkg/cmd/edge_applications/build/build.go index 12622d6a9..c91b3e4b7 100644 --- a/pkg/cmd/edge_applications/build/build.go +++ b/pkg/cmd/edge_applications/build/build.go @@ -1,6 +1,7 @@ package build import ( + "context" "encoding/json" "errors" "fmt" @@ -8,9 +9,11 @@ import ( "os" "github.com/tidwall/gjson" + "github.com/tidwall/sjson" "github.com/MakeNowJust/heredoc" msg "github.com/aziontech/azion-cli/messages/edge_applications" + api "github.com/aziontech/azion-cli/pkg/api/storage_api" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/contracts" "github.com/aziontech/azion-cli/pkg/iostreams" @@ -27,6 +30,8 @@ type BuildCmd struct { GetWorkDir func() (string, error) EnvLoader func(path string) ([]string, error) Stat func(path string) (fs.FileInfo, error) + GetVerId func(cmd *BuildCmd, appID string) (string, error) + f *cmdutil.Factory } func NewCmd(f *cmdutil.Factory) *cobra.Command { @@ -65,6 +70,8 @@ func newBuildCmd(f *cmdutil.Factory) *BuildCmd { EnvLoader: utils.LoadEnvVarsFromFile, WriteFile: os.WriteFile, Stat: os.Stat, + GetVerId: GetVersionID, + f: f, } } @@ -78,20 +85,7 @@ func (cmd *BuildCmd) run() error { return err } - jsonConf := path + "/azion/azion.json" - file, err := cmd.FileReader(jsonConf) - if err != nil { - return msg.ErrorOpeningAzionFile - } - - typeLang := gjson.Get(string(file), "type") - - if typeLang.String() == "cdn" { - fmt.Fprintf(cmd.Io.Out, "%s\n", msg.EdgeApplicationsBuildCdn) - return nil - } - - err = RunBuildCmdLine(cmd, typeLang.String()) + err = RunBuildCmdLine(cmd, path) if err != nil { return err } @@ -99,15 +93,24 @@ func (cmd *BuildCmd) run() error { return nil } -func RunBuildCmdLine(cmd *BuildCmd, typeLang string) error { +func RunBuildCmdLine(cmd *BuildCmd, path string) error { var err error - conf, err := getConfig(cmd) + azionJson := path + "/azion/azion.json" + file, err := cmd.FileReader(azionJson) if err != nil { - return err + return msg.ErrorOpeningAzionFile } - path, err := utils.GetWorkingDir() + typeLang := gjson.Get(string(file), "type") + applicationId := gjson.Get(string(file), "application.id") + + if typeLang.String() == "cdn" { + fmt.Fprintf(cmd.Io.Out, "%s\n", msg.EdgeApplicationsBuildCdn) + return nil + } + + conf, err := getConfig(cmd) if err != nil { return err } @@ -122,7 +125,7 @@ func RunBuildCmdLine(cmd *BuildCmd, typeLang string) error { return msg.ErrReadEnvFile } } else if errors.Is(err, os.ErrNotExist) { - if typeLang == "nextjs" || typeLang == "flareact" { + if typeLang.String() == "nextjs" || typeLang.String() == "flareact" { envs = insertAWSCredentials(cmd) notFound = true } @@ -135,9 +138,29 @@ func RunBuildCmdLine(cmd *BuildCmd, typeLang string) error { return err } - switch typeLang { - case "javascript", "nextjs", "flareact": - err := runCommand(cmd, conf, envs) + switch typeLang.String() { + case "nextjs", "flareact": + + var verId string = "" + + if applicationId.String() != "" && applicationId.String() != "0" { + verId, err = cmd.GetVerId(cmd, applicationId.String()) + if err != nil { + return err + } + } + + jsonReplaceFunc, err := sjson.Set(string(file), "version-id", verId) + if err != nil { + return msg.ErrorFailedUpdateAzionJson + } + + err = cmd.WriteFile(azionJson, []byte(jsonReplaceFunc), 0644) + if err != nil { + return fmt.Errorf(utils.ErrorCreateFile.Error(), azionJson) + } + + err = runCommand(cmd, conf, envs) if err != nil { return err } @@ -147,6 +170,11 @@ func RunBuildCmdLine(cmd *BuildCmd, typeLang string) error { return errEnv } } + case "javascript": + err := runCommand(cmd, conf, envs) + if err != nil { + return err + } default: return utils.ErrorUnsupportedType @@ -284,3 +312,17 @@ func writeWebdevEnvFile(cmd *BuildCmd, path string, envs []string) error { } return nil } + +func GetVersionID(cmd *BuildCmd, appID string) (string, error) { + + client := api.NewClient(cmd.f.HttpClient, cmd.f.Config.GetString("storage_url"), cmd.f.Config.GetString("token")) + + ctx := context.Background() + + verId, err := client.CreateVersionId(ctx, appID) + if err != nil { + return "", fmt.Errorf(msg.ErrorGetVersionId.Error(), err) + } + + return verId.GetVersionId(), nil +} diff --git a/pkg/cmd/edge_applications/build/build_test.go b/pkg/cmd/edge_applications/build/build_test.go index 7cb898a36..159fede2e 100644 --- a/pkg/cmd/edge_applications/build/build_test.go +++ b/pkg/cmd/edge_applications/build/build_test.go @@ -54,7 +54,7 @@ func TestBuild(t *testing.T) { err := command.run() require.NoError(t, err) - require.Contains(t, stdout.String(), `Your Web Application was built successfully`) + require.Contains(t, stdout.String(), `Your Edge Application was built successfully`) }) t.Run("cmd failed", func(t *testing.T) { diff --git a/pkg/cmd/edge_applications/edge_applications_test.go b/pkg/cmd/edge_applications/edge_applications_test.go index b61cb0347..c637be00c 100644 --- a/pkg/cmd/edge_applications/edge_applications_test.go +++ b/pkg/cmd/edge_applications/edge_applications_test.go @@ -1,7 +1,6 @@ package edge_applications import ( - "fmt" "io/fs" "os" "testing" @@ -244,6 +243,10 @@ func TestEdgeApplicationsCmd(t *testing.T) { return "Build completed", 0, nil } + buildCommand.GetVerId = func(cmd *buildcmd.BuildCmd, appID string) (string, error) { + return "v123456789", nil + } + buildCommand.Stat = func(path string) (fs.FileInfo, error) { return nil, nil } @@ -295,7 +298,6 @@ func TestEdgeApplicationsCmd(t *testing.T) { cmdPublish := publishcmd.NewCobraCmd(publishCmd) errPublish := cmdPublish.Execute() - fmt.Println(errPublish) require.NoError(t, err) @@ -406,6 +408,10 @@ func TestEdgeApplicationsCmd(t *testing.T) { return "Build completed", 0, nil } + buildCommand.GetVerId = func(cmd *buildcmd.BuildCmd, appID string) (string, error) { + return "v123456789", nil + } + buildCommand.EnvLoader = func(path string) ([]string, error) { return buildEnvs, nil } @@ -457,7 +463,6 @@ func TestEdgeApplicationsCmd(t *testing.T) { cmdPublish := publishcmd.NewCobraCmd(publishCmd) errPublish := cmdPublish.Execute() - fmt.Println(errPublish) require.NoError(t, err) diff --git a/pkg/cmd/edge_applications/init/init.go b/pkg/cmd/edge_applications/init/init.go index e7b4bdc8f..dd9b553c3 100644 --- a/pkg/cmd/edge_applications/init/init.go +++ b/pkg/cmd/edge_applications/init/init.go @@ -17,7 +17,6 @@ import ( "github.com/aziontech/azion-cli/utils" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/storer" "github.com/go-git/go-git/v5/storage/memory" "github.com/spf13/cobra" "github.com/tidwall/gjson" @@ -284,7 +283,11 @@ func (cmd *InitCmd) fetchTemplates(info *InitInfo) error { return nil } -func sortTag(tags storer.ReferenceIter, major, branch string) (string, error) { +type ReferenceIter interface { + ForEach(func(*plumbing.Reference) error) error +} + +func sortTag(tags ReferenceIter, major, branch string) (string, error) { var tagCurrent int = 0 var tagCurrentStr string var tagWithMajorOk int = 0 @@ -321,14 +324,13 @@ func sortTag(tags storer.ReferenceIter, major, branch string) (string, error) { } // formatTag slice tag by '/' taking index 2 where the version is, transforming it into a list taking only the numbers -func formatTag(tag string) string { - var t string +func formatTag(tag string) (version string) { for _, v := range strings.Split(strings.Split(tag, "/")[2], "") { if _, err := strconv.Atoi(v); err == nil { - t += v + version += v } } - return t + return } func checkBranch(num, branch string) string { @@ -594,7 +596,6 @@ func initCdn(cmd *InitCmd, path string, info *InitInfo) error { if shouldFetchTemplates { pathWorker := path + "/azion" if err := cmd.Mkdir(pathWorker, os.ModePerm); err != nil { - fmt.Println(err) return msg.ErrorFailedCreatingAzionDirectory } @@ -610,7 +611,6 @@ func initCdn(cmd *InitCmd, path string, info *InitInfo) error { err = cmd.WriteFile(path+"/azion/azion.json", data, 0644) if err != nil { - fmt.Println(err) return utils.ErrorInternalServerError } diff --git a/pkg/cmd/edge_applications/init/init_test.go b/pkg/cmd/edge_applications/init/init_test.go index 5e49e7726..e16b0775e 100644 --- a/pkg/cmd/edge_applications/init/init_test.go +++ b/pkg/cmd/edge_applications/init/init_test.go @@ -14,8 +14,9 @@ import ( "github.com/aziontech/azion-cli/pkg/testutils" "github.com/aziontech/azion-cli/utils" "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/storer" - "github.com/go-git/go-git/v5/storage/memory" + + "github.com/go-git/go-git/v5/plumbing" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -158,7 +159,6 @@ func TestCobraCmd(t *testing.T) { f.IOStreams.In = io.NopCloser(in) err := cmd.Execute() - // fmt.Println(err.Error()) require.NoError(t, err) require.Contains(t, stdout.String(), `Template successfully fetched and configured`) @@ -644,42 +644,38 @@ func Test_checkBranch(t *testing.T) { } } -func Test_sortTag(t *testing.T) { - r, _ := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{URL: "https://github.com/MaxwelMazur/action-testing.git"}) - tags, _ := r.Tags() +type mockReferenceIter struct { + mock.Mock +} - type args struct { - tags storer.ReferenceIter - major string - branch string - } - tests := []struct { - name string - args args - wantTag string - wantErr bool - }{ - { - name: "branch main with major 0", - args: args{ - tags: tags, - major: "1", - branch: "main", - }, - wantTag: "refs/tags/v1.0.0", - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotTag, err := sortTag(tt.args.tags, tt.args.major, tt.args.branch) - if (err != nil) != tt.wantErr { - t.Errorf("sortTag() error = %v, wantErr %v", err, tt.wantErr) - return - } - if gotTag != tt.wantTag { - t.Errorf("sortTag() gotTag = %v, want %v", gotTag, tt.wantTag) +func (m *mockReferenceIter) ForEach(f func(*plumbing.Reference) error) error { + args := m.Called(f) + return args.Error(0) +} + +func Test_SortTag(t *testing.T) { + mockIter := new(mockReferenceIter) + + // defines the mock action + mockIter.On("ForEach", mock.Anything).Run(func(args mock.Arguments) { + f := args.Get(0).(func(*plumbing.Reference) error) + refs := []*plumbing.Reference{ + plumbing.NewReferenceFromStrings("refs/tags/v2.0.0", "beefdead"), + plumbing.NewReferenceFromStrings("refs/tags/v1.0.0", "deadbeef"), + plumbing.NewReferenceFromStrings("refs/tags/v3.0.0", "deafbeef"), + } + + for _, ref := range refs { + if err := f(ref); err != nil { + panic(err) } - }) - } + } + }).Return(nil) + + // call func sortTag with the mock + result, err := sortTag(mockIter, "2", "main") + require.NoError(t, err) + + expected := "refs/tags/v2.0.0" + require.Equal(t, expected, result) } diff --git a/pkg/cmd/origins/create/create.go b/pkg/cmd/origins/create/create.go new file mode 100644 index 000000000..d95126a1a --- /dev/null +++ b/pkg/cmd/origins/create/create.go @@ -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 +} diff --git a/pkg/cmd/origins/create/create_test.go b/pkg/cmd/origins/create/create_test.go new file mode 100644 index 000000000..f8d505f1c --- /dev/null +++ b/pkg/cmd/origins/create/create_test.go @@ -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", "onepieceisthebest", + "--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) + }) +} diff --git a/pkg/cmd/origins/create/fixtures/create.json b/pkg/cmd/origins/create/fixtures/create.json new file mode 100644 index 000000000..30383f111 --- /dev/null +++ b/pkg/cmd/origins/create/fixtures/create.json @@ -0,0 +1,9 @@ +{ + "name": "Create Or22i21231222n2", + "addresses": [ + { + "address": "httpbin.org" + } + ], + "host_header": "asdf.asdfom" +} diff --git a/pkg/cmd/origins/create/fixtures/response.json b/pkg/cmd/origins/create/fixtures/response.json new file mode 100644 index 000000000..c54abbce7 --- /dev/null +++ b/pkg/cmd/origins/create/fixtures/response.json @@ -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 +} diff --git a/pkg/cmd/origins/delete/delete.go b/pkg/cmd/origins/delete/delete.go new file mode 100644 index 000000000..b3622ab92 --- /dev/null +++ b/pkg/cmd/origins/delete/delete.go @@ -0,0 +1,46 @@ +package delete + +import ( + "context" + "fmt" + + "github.com/MakeNowJust/heredoc" + msg "github.com/aziontech/azion-cli/messages/origins" + api "github.com/aziontech/azion-cli/pkg/api/edge_applications" + "github.com/spf13/cobra" + "github.com/aziontech/azion-cli/pkg/cmdutil" +) + + + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + var applicationID int64 + var originKey string + cmd := &cobra.Command{ + Use: msg.OriginsDeleteUsage, + Short: msg.OriginsDeleteShortDescription, + Long: msg.OriginsDeleteLongDescription, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(` + $ azioncli origins delete --application-id 1234 --origin-key 03a6e7bf-8e26-49c7-a66e-ab8eaa425086 + $ azioncli origins delete -a 1234 -o 03a6e7bf-8e26-49c7-a66e-ab8eaa425086 + `), + RunE: func(cmd *cobra.Command, args []string) error { + if !cmd.Flags().Changed("application-id") || !cmd.Flags().Changed("origin-key") { + return msg.ErrorMissingArgumentsDelete + } + if err := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")). + DeleteOrigins(context.Background(), applicationID, originKey); err != nil { + return fmt.Errorf(msg.ErrorFailToDelete.Error(), err) + } + fmt.Fprintf(f.IOStreams.Out, msg.OriginsDeleteOutputSuccess, originKey) + return nil + }, + } + + cmd.Flags().Int64VarP(&applicationID, "application-id", "a", 0, msg.OriginsDeleteFlagApplicationID) + cmd.Flags().StringVarP(&originKey, "origin-key", "o", "", msg.OriginsDeleteFlagOriginKey) + cmd.Flags().BoolP("help", "h", false, msg.OriginsDeleteHelpFlag) + return cmd +} diff --git a/pkg/cmd/origins/delete/delete_test.go b/pkg/cmd/origins/delete/delete_test.go new file mode 100644 index 000000000..0738173af --- /dev/null +++ b/pkg/cmd/origins/delete/delete_test.go @@ -0,0 +1,48 @@ +package delete + +import ( + "fmt" + "testing" + + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + msg "github.com/aziontech/azion-cli/messages/origins" +) + +func TestCreate(t *testing.T) { + + t.Run("delete domain by id", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("DELETE", "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef496d"), + httpmock.StatusStringResponse(204, ""), + ) + + f, stdout, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + cmd.SetArgs([]string{"--application-id", "1673635839", "--origin-key", "58755fef-e830-4ea4-b9e0-6481f1ef496d"}) + + _, err := cmd.ExecuteC() + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf(msg.OriginsDeleteOutputSuccess, "58755fef-e830-4ea4-b9e0-6481f1ef496d"), stdout.String()) + }) + + t.Run("delete domain that is not found", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("DELETE", "edge_applications/1673635839/origins/58755fef-e830-4ea4-b9e0-6481f1ef497a"), + httpmock.StatusStringResponse(404, "Not Found"), + ) + + f, _, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + cmd.SetArgs([]string{"-d", "1234"}) + + _, err := cmd.ExecuteC() + require.Error(t, err) + }) +} diff --git a/pkg/cmd/origins/describe/describe.go b/pkg/cmd/origins/describe/describe.go new file mode 100644 index 000000000..89fa233ca --- /dev/null +++ b/pkg/cmd/origins/describe/describe.go @@ -0,0 +1,114 @@ +package describe + +import ( + "context" + "encoding/json" + "fmt" + "path/filepath" + + "github.com/fatih/color" + + "github.com/MakeNowJust/heredoc" + "github.com/MaxwelMazur/tablecli" + 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/pkg/contracts" + "github.com/aziontech/azion-cli/utils" + sdk "github.com/aziontech/azionapi-go-sdk/edgeapplications" + "github.com/spf13/cobra" +) + +var ( + applicationID int64 + originID int64 +) + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + opts := &contracts.DescribeOptions{} + cmd := &cobra.Command{ + Use: msg.OriginsDescribeUsage, + Short: msg.OriginsDescribeShortDescription, + Long: msg.OriginsDescribeLongDescription, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(` + $ azioncli origins describe --application-id 4312 --origin-id 31223 + $ azioncli origins describe --application-id 1337 --origin-id 31223--format json + $ azioncli origins describe --application-id 1337 --origin-id 31223--out "./tmp/test.json" --format json + `), + RunE: func(cmd *cobra.Command, args []string) error { + if !cmd.Flags().Changed("application-id") || !cmd.Flags().Changed("origin-id") { + return msg.ErrorMissingArguments + } + + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + ctx := context.Background() + origin, err := client.GetOrigin(ctx, applicationID, originID) + if err != nil { + return msg.ErrorGetOrigin + } + + out := f.IOStreams.Out + formattedFuction, err := format(cmd, origin) + if err != nil { + return utils.ErrorFormatOut + } + + if cmd.Flags().Changed("out") { + err := cmdutil.WriteDetailsToFile(formattedFuction, opts.OutPath, out) + if err != nil { + return fmt.Errorf("%s: %w", utils.ErrorWriteFile, err) + } + fmt.Fprintf(out, msg.OriginsFileWritten, filepath.Clean(opts.OutPath)) + } else { + _, err := out.Write(formattedFuction[:]) + if err != nil { + return err + } + } + + return nil + }, + } + + cmd.Flags().Int64VarP(&applicationID, "application-id", "a", 0, msg.OriginsDescribeFlagApplicationID) + cmd.Flags().Int64VarP(&originID, "origin-id", "o", 0, msg.OriginsDescribeFlagOriginID) + cmd.Flags().StringVar(&opts.OutPath, "out", "", msg.OriginsDescribeFlagOut) + cmd.Flags().StringVar(&opts.Format, "format", "", msg.OriginsDescribeFlagFormat) + cmd.Flags().BoolP("help", "h", false, msg.OriginsDescribeHelpFlag) + + return cmd +} + +func format(cmd *cobra.Command, origin sdk.OriginsResultResponse) ([]byte, error) { + format, err := cmd.Flags().GetString("format") + if err != nil { + return nil, err + } + + if format == "json" || cmd.Flags().Changed("out") { + return json.MarshalIndent(origin, "", " ") + } + + tbl := tablecli.New("", "") + tbl.WithFirstColumnFormatter(color.New(color.FgGreen).SprintfFunc()) + tbl.AddRow("Origin ID: ", origin.OriginId) + tbl.AddRow("Name: ", origin.Name) + tbl.AddRow("Origin Type: ", origin.OriginType) + tbl.AddRow("Addresses: ", origin.Addresses) + tbl.AddRow("Origin Protocol Policy: ", origin.OriginProtocolPolicy) + tbl.AddRow("Is Origin Redirection Enable: ", origin.IsOriginRedirectionEnabled) + tbl.AddRow("Host Header: ", origin.HostHeader) + tbl.AddRow("Method: ", origin.Method) + tbl.AddRow("Origin Path: ", origin.OriginPath) + tbl.AddRow("Connection Timeout: ", origin.ConnectionTimeout) + tbl.AddRow("Timeout Between Bytes: ", origin.TimeoutBetweenBytes) + tbl.AddRow("Hmac Authentication: ", origin.HmacAuthentication) + tbl.AddRow("Hmac Region Name: ", origin.HmacRegionName) + tbl.AddRow("Hmac Secret Key: ", origin.HmacSecretKey) + tbl.AddRow("Hmac Access Key: ", origin.HmacAccessKey) + return tbl.GetByteFormat(), nil +} + diff --git a/pkg/cmd/origins/describe/describe_test.go b/pkg/cmd/origins/describe/describe_test.go new file mode 100644 index 000000000..1f823c91d --- /dev/null +++ b/pkg/cmd/origins/describe/describe_test.go @@ -0,0 +1,95 @@ +package describe + +import ( + "log" + "os" + "net/http" + "testing" + + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/require" +) + + +func TestDescribe(t *testing.T) { + t.Run("describe an domains", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origins"), + httpmock.JSONFromFile("./fixtures/origins.json"), + ) + + f, _, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + cmd.SetArgs([]string{"-a", "123423424", "-o", "88144"}) + + err := cmd.Execute() + require.NoError(t, err) + }) + t.Run("not found", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origin"), + httpmock.StatusStringResponse(http.StatusNotFound, "Not Found"), + ) + + f, _, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + + err := cmd.Execute() + require.Error(t, err) + }) + + t.Run("no id sent", func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origins"), + httpmock.StatusStringResponse(http.StatusNotFound, "Not Found"), + ) + + f, _, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + cmd.SetArgs([]string{"-a", "123423424", "-o", "88149"}) + + err := cmd.Execute() + require.Error(t, err) + }) + + t.Run("export to a file", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origins"), + httpmock.JSONFromFile("./fixtures/origins.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + path := "./out.json" + cmd.SetArgs([]string{"-a", "123423424", "-o", "88144", "--out", path}) + + err := cmd.Execute() + if err != nil { + log.Println("error executing cmd err: ", err.Error()) + } + + _, err = os.ReadFile(path) + if err != nil { + t.Fatalf("error reading `out.json`: %v", err) + } + defer func() { + _ = os.Remove(path) + }() + + require.NoError(t, err) + + require.Equal(t, `File successfully written to: out.json +`, stdout.String()) + }) +} diff --git a/pkg/cmd/origins/describe/fixtures/noorigins.json b/pkg/cmd/origins/describe/fixtures/noorigins.json new file mode 100644 index 000000000..cc69cb477 --- /dev/null +++ b/pkg/cmd/origins/describe/fixtures/noorigins.json @@ -0,0 +1,10 @@ +{ + "count": 1, + "total_pages": 0, + "schema_version": 3, + "links": { + "previous": null, + "next": null + }, + "results": [] +} diff --git a/pkg/cmd/origins/describe/fixtures/origins.json b/pkg/cmd/origins/describe/fixtures/origins.json new file mode 100644 index 000000000..143543346 --- /dev/null +++ b/pkg/cmd/origins/describe/fixtures/origins.json @@ -0,0 +1,61 @@ +{ + "count": 2, + "total_pages": 1, + "schema_version": 3, + "links": { + "previous": null, + "next": null + }, + "results": [ + { + "origin_id": 88144, + "origin_key": "0cee30cd-1743-4202-b0dd-da9b636a6035", + "name": "Default Origin", + "origin_type": "single_origin", + "addresses": [ + { + "address": "www.new.api", + "weight": null, + "server_role": "primary", + "is_active": true + } + ], + "origin_protocol_policy": "preserve", + "is_origin_redirection_enabled": false, + "host_header": "www.new.api", + "method": "", + "origin_path": "", + "connection_timeout": 60, + "timeout_between_bytes": 120, + "hmac_authentication": false, + "hmac_region_name": "", + "hmac_access_key": "", + "hmac_secret_key": "" + }, + { + "origin_id": 91799, + "origin_key": "e4f0761b-d2ac-4168-aa4b-f525d08396fd", + "name": "Create Origin", + "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": "" + } + ] +} diff --git a/pkg/cmd/origins/list/fixtures/noorigins.json b/pkg/cmd/origins/list/fixtures/noorigins.json new file mode 100644 index 000000000..cc69cb477 --- /dev/null +++ b/pkg/cmd/origins/list/fixtures/noorigins.json @@ -0,0 +1,10 @@ +{ + "count": 1, + "total_pages": 0, + "schema_version": 3, + "links": { + "previous": null, + "next": null + }, + "results": [] +} diff --git a/pkg/cmd/origins/list/fixtures/origins.json b/pkg/cmd/origins/list/fixtures/origins.json new file mode 100644 index 000000000..143543346 --- /dev/null +++ b/pkg/cmd/origins/list/fixtures/origins.json @@ -0,0 +1,61 @@ +{ + "count": 2, + "total_pages": 1, + "schema_version": 3, + "links": { + "previous": null, + "next": null + }, + "results": [ + { + "origin_id": 88144, + "origin_key": "0cee30cd-1743-4202-b0dd-da9b636a6035", + "name": "Default Origin", + "origin_type": "single_origin", + "addresses": [ + { + "address": "www.new.api", + "weight": null, + "server_role": "primary", + "is_active": true + } + ], + "origin_protocol_policy": "preserve", + "is_origin_redirection_enabled": false, + "host_header": "www.new.api", + "method": "", + "origin_path": "", + "connection_timeout": 60, + "timeout_between_bytes": 120, + "hmac_authentication": false, + "hmac_region_name": "", + "hmac_access_key": "", + "hmac_secret_key": "" + }, + { + "origin_id": 91799, + "origin_key": "e4f0761b-d2ac-4168-aa4b-f525d08396fd", + "name": "Create Origin", + "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": "" + } + ] +} diff --git a/pkg/cmd/origins/list/list.go b/pkg/cmd/origins/list/list.go new file mode 100644 index 000000000..2ee732a32 --- /dev/null +++ b/pkg/cmd/origins/list/list.go @@ -0,0 +1,90 @@ +package list + +import ( + "context" + "fmt" + "strings" + + "github.com/fatih/color" + + "github.com/MakeNowJust/heredoc" + table "github.com/MaxwelMazur/tablecli" + 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/pkg/contracts" + "github.com/spf13/cobra" +) + + +var edgeApplicationID int64 = 0 + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + opts := &contracts.ListOptions{} + cmd := &cobra.Command{ + Use: msg.OriginsListUsage, + Short: msg.OriginsListShortDescription, + Long: msg.OriginsListLongDescription, + SilenceUsage: true, + SilenceErrors: true, Example: heredoc.Doc(` + $ azioncli domains list + $ azioncli origins list -a 16736354321 + $ azioncli origins list --application-id 16736354321 + $ azioncli origins list --application-id 16736354321 --details + `), + RunE: func(cmd *cobra.Command, args []string) error { + if !cmd.Flags().Changed("application-id") { + return msg.ErrorMissingApplicationIDArgument + } + + if err := PrintTable(cmd, f, opts); err != nil { + return fmt.Errorf(msg.ErrorGetOrigins.Error(), err) + } + return nil + }, + } + + cmdutil.AddAzionApiFlags(cmd, opts) + flags := cmd.Flags() + flags.Int64VarP(&edgeApplicationID, "application-id", "a", 0, msg.OriginsListFlagEdgeApplicationID) + flags.BoolP("help", "h", false, msg.OriginsListHelpFlag) + return cmd +} + +func PrintTable(cmd *cobra.Command, f *cmdutil.Factory, opts *contracts.ListOptions) error { + client := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + ctx := context.Background() + + response, err := client.ListOrigins(ctx, opts, edgeApplicationID) + if err != nil { + return fmt.Errorf(msg.ErrorGetOrigins.Error(), err) + } + + tbl := table.New("ID", "NAME") + tbl.WithWriter(f.IOStreams.Out) + if cmd.Flags().Changed("details") { + tbl = table.New("ID", "NAME", "ORIGIN TYPE", "ORIGIN PATH", "ADDRESSES", "CONNECTION TIMEOUT") + } + + headerFmt := color.New(color.FgBlue, color.Underline).SprintfFunc() + columnFmt := color.New(color.FgGreen).SprintfFunc() + tbl.WithHeaderFormatter(headerFmt).WithFirstColumnFormatter(columnFmt) + if cmd.Flags().Changed("details") { + for _, v := range response.Results { + tbl.AddRow(v.OriginId, v.Name, v.OriginType, v.OriginPath, v.Addresses, v.ConnectionTimeout) + } + } else { + for _, v := range response.Results { + tbl.AddRow(v.OriginId, v.Name) + } + } + + format := strings.Repeat("%s", len(tbl.GetHeader())) + "\n" + tbl.CalculateWidths([]string{}) + tbl.PrintHeader(format) + for _, row := range tbl.GetRows() { + tbl.PrintRow(format, row) + } + return nil +} + diff --git a/pkg/cmd/origins/list/list_test.go b/pkg/cmd/origins/list/list_test.go new file mode 100644 index 000000000..c6a299ca9 --- /dev/null +++ b/pkg/cmd/origins/list/list_test.go @@ -0,0 +1,48 @@ +package list + +import ( + "testing" + + "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 TestList(t *testing.T) { + t.Run("list page 1", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origins"), + httpmock.JSONFromFile("./fixtures/origins.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + + cmd.SetArgs([]string{"-a", "123423424"}) + + _, err := cmd.ExecuteC() + require.NoError(t, err) + assert.Equal(t, "ID NAME \n88144 Default Origin \n91799 Create Origin \n", stdout.String()) + }) + + t.Run("no itens", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST("GET", "edge_applications/123423424/origins"), + httpmock.JSONFromFile("./fixtures/noorigins.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + + cmd.SetArgs([]string{"-a", "123423424"}) + + _, err := cmd.ExecuteC() + require.NoError(t, err) + assert.Equal(t, "ID NAME \n", stdout.String()) + }) +} diff --git a/pkg/cmd/origins/origins.go b/pkg/cmd/origins/origins.go new file mode 100644 index 000000000..4984295a4 --- /dev/null +++ b/pkg/cmd/origins/origins.go @@ -0,0 +1,34 @@ +package origins + +import ( + "github.com/MakeNowJust/heredoc" + msg "github.com/aziontech/azion-cli/messages/origins" + "github.com/aziontech/azion-cli/pkg/cmd/origins/describe" + "github.com/aziontech/azion-cli/pkg/cmd/origins/list" + "github.com/aziontech/azion-cli/pkg/cmd/origins/create" + "github.com/aziontech/azion-cli/pkg/cmd/origins/update" + "github.com/aziontech/azion-cli/pkg/cmd/origins/delete" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/spf13/cobra" +) + +func NewCmd(f *cmdutil.Factory) *cobra.Command { + originsCmd := &cobra.Command{ + Use: msg.OriginsUsage, + Short: msg.OriginsShortDescription, + Long: msg.OriginsLongDescription, Example: heredoc.Doc(` + $ azioncli origins --help + `), + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + + originsCmd.AddCommand(list.NewCmd(f)) + originsCmd.AddCommand(describe.NewCmd(f)) + originsCmd.AddCommand(create.NewCmd(f)) + originsCmd.AddCommand(update.NewCmd(f)) + originsCmd.AddCommand(delete.NewCmd(f)) + originsCmd.Flags().BoolP("help", "h", false, msg.OriginsFlagHelp) + return originsCmd +} diff --git a/pkg/cmd/origins/update/fixtures/response.json b/pkg/cmd/origins/update/fixtures/response.json new file mode 100644 index 000000000..f95e3eaaa --- /dev/null +++ b/pkg/cmd/origins/update/fixtures/response.json @@ -0,0 +1,28 @@ +{ + "results": { + "origin_id": 92760, + "origin_key": "03a6e7bf-8e26-49c7-a66e-ab8eaa425086", + "name": "onepiece", + "origin_type": "single_origin", + "addresses": [ + { + "address": "asdfsd.cvdf", + "weight": null, + "server_role": "primary", + "is_active": true + } + ], + "origin_protocol_policy": "preserve", + "is_origin_redirection_enabled": false, + "host_header": "asdfsdfsd.cvdf", + "method": "", + "origin_path": "", + "connection_timeout": 60, + "timeout_between_bytes": 120, + "hmac_authentication": false, + "hmac_region_name": "", + "hmac_access_key": "", + "hmac_secret_key": "" + }, + "schema_version": 3 +} diff --git a/pkg/cmd/origins/update/fixtures/update.json b/pkg/cmd/origins/update/fixtures/update.json new file mode 100644 index 000000000..d41a41324 --- /dev/null +++ b/pkg/cmd/origins/update/fixtures/update.json @@ -0,0 +1,7 @@ +{ + "name": "onepiece", + "addresses": [{ + "address": "asdfsd.cvdf" + }], + "host_header": "asdfsdfsd.cvdf" +} diff --git a/pkg/cmd/origins/update/update.go b/pkg/cmd/origins/update/update.go new file mode 100644 index 000000000..f5f931a2a --- /dev/null +++ b/pkg/cmd/origins/update/update.go @@ -0,0 +1,144 @@ +package update + +import ( + "context" + "fmt" + "os" + "strconv" + + "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 { + OriginKey string + 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.OriginsUpdateUsage, + Short: msg.OriginsUpdateShortDescription, + Long: msg.OriginsUpdateLongDescription, + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(` + $ azioncli origins update --application-id 1673635839 --origin-key "58755fef-e830-4ea4-b9e0-6481f1ef496d" --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 update --application-id 1673635839 --origin-key "58755fef-e830-4ea4-b9e0-6481f1ef496d" --name "drink coffe" --addresses "asdfg.asd" --host-header "host" + $ azioncli origins update --in "update.json" + `), + RunE: func(cmd *cobra.Command, args []string) error { + request := api.UpdateOriginsRequest{} + 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("origin-key") { + return msg.ErrorMandatoryUpdateFlags + } + if cmd.Flags().Changed("name") { + request.SetName(fields.Name) + } + if cmd.Flags().Changed("addresses") { + request.SetAddresses(prepareAddresses(fields.Addresses)) + } + if cmd.Flags().Changed("host-header") { + 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.UpdateOrigins(context.Background(), fields.ApplicationID, fields.OriginKey, &request) + if err != nil { + return fmt.Errorf(msg.ErrorUpdateOrigin.Error(), err) + } + fmt.Fprintf(f.IOStreams.Out, msg.OriginsUpdateOutputSuccess, response.GetOriginKey()) + return nil + }, + } + + flags := cmd.Flags() + flags.StringVarP(&fields.OriginKey, "origin-key", "o", "", msg.OriginsUpdateFlagOriginKey) + 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 +} diff --git a/pkg/cmd/origins/update/update_test.go b/pkg/cmd/origins/update/update_test.go new file mode 100644 index 000000000..8d27846e1 --- /dev/null +++ b/pkg/cmd/origins/update/update_test.go @@ -0,0 +1,86 @@ +package update + +import ( + "fmt" + "net/http" + "testing" + + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/stretchr/testify/require" + msg "github.com/aziontech/azion-cli/messages/origins" +) + +func TestUpdate(t *testing.T) { + t.Run("update edge application", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST(http.MethodPatch, "edge_applications/1673635839/origins/03a6e7bf-8e26-49c7-a66e-ab8eaa425086"), + httpmock.JSONFromFile("./fixtures/response.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + cmd := NewCmd(f) + + cmd.SetArgs([]string{ + "--application-id", "1673635839", + "--origin-key", "03a6e7bf-8e26-49c7-a66e-ab8eaa425086", + "--name", "onepiece", + "--addresses", "asdfsd.cvdf", + "--host-header", "asdfsdfsd.cvdf", + }) + + err := cmd.Execute() + require.NoError(t, err) + require.Equal(t, fmt.Sprintf(msg.OriginsUpdateOutputSuccess, "03a6e7bf-8e26-49c7-a66e-ab8eaa425086"), stdout.String()) + }) + + t.Run("bad request", func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register( + httpmock.REST(http.MethodPatch, "edge_applications/1673635839/origins/03a6e7bf-8e26-49c7-a66e-ab8eaa425086"), + httpmock.StatusStringResponse(http.StatusBadRequest, `{"details": "invalid field active"}`), + ) + + f, _, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + + cmd.SetArgs([]string{ + "--application-id", "1673635839", + "--origin-key", "03a6e7bf-8e26-49c7-a66e-ab8eaa425086", + "--name", "onepiece", + "--addresses", "asdfsd.cvdf", + "--host-header", "asdfsdfsd.cvdf", + }) + + err := cmd.Execute() + + require.Error(t, err) + }) + + t.Run("update with file", func(t *testing.T) { + mock := &httpmock.Registry{} + + mock.Register( + httpmock.REST(http.MethodPatch, "edge_applications/1673635839/origins/03a6e7bf-8e26-49c7-a66e-ab8eaa425086"), + httpmock.JSONFromFile("./fixtures/response.json"), + ) + + f, stdout, _ := testutils.NewFactory(mock) + + cmd := NewCmd(f) + + cmd.SetArgs([]string{ + "--application-id", "1673635839", + "--origin-key", "03a6e7bf-8e26-49c7-a66e-ab8eaa425086", + "--in", "./fixtures/update.json", + }) + + err := cmd.Execute() + + require.NoError(t, err) + require.Equal(t, fmt.Sprintf(msg.OriginsUpdateOutputSuccess, "03a6e7bf-8e26-49c7-a66e-ab8eaa425086"), stdout.String()) + }) +} diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 4c8bc2205..401347a41 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -12,6 +12,7 @@ import ( "github.com/aziontech/azion-cli/pkg/cmd/edge_applications" "github.com/aziontech/azion-cli/pkg/cmd/edge_functions" "github.com/aziontech/azion-cli/pkg/cmd/edge_services" + "github.com/aziontech/azion-cli/pkg/cmd/origins" "github.com/aziontech/azion-cli/pkg/cmd/version" "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/constants" @@ -51,6 +52,7 @@ func NewRootCmd(f *cmdutil.Factory) *cobra.Command { rootCmd.AddCommand(edge_functions.NewCmd(f)) rootCmd.AddCommand(edge_applications.NewCmd(f)) rootCmd.AddCommand(domains.NewCmd(f)) + rootCmd.AddCommand(origins.NewCmd(f)) rootCmd.Flags().BoolP("help", "h", false, msg.RootHelpFlag) return rootCmd } @@ -67,6 +69,7 @@ func Execute() { viper.AutomaticEnv() viper.SetDefault("token", tok) viper.SetDefault("api_url", constants.ApiURL) + viper.SetDefault("storage_url", constants.StorageApiURL) factory := &cmdutil.Factory{ HttpClient: httpClient, diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index a25b35b23..67cb50550 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -2,6 +2,7 @@ package constants // These variables have their values set at link time through the Makefile var ( - ApiURL string - AuthURL string + ApiURL string + AuthURL string + StorageApiURL string ) diff --git a/pkg/contracts/contracts.go b/pkg/contracts/contracts.go index 7f75908d4..0ee31d0bd 100644 --- a/pkg/contracts/contracts.go +++ b/pkg/contracts/contracts.go @@ -19,6 +19,7 @@ type AzionApplicationOptions struct { Name string `json:"name"` Type string `json:"type"` Env string `json:"env"` + VersionID string `json:"version-id"` Function AzionJsonDataFunction `json:"function"` Application AzionJsonDataApplication `json:"application"` Domain AzionJsonDataDomain `json:"domain"`