Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions cmd/importURL.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ func NewImportURLCommand(globalClientOpts *connectors.ClientOptions) *cobra.Comm
mainArtifact := true
secret := ""

f, mainArtifact, secret = parseImportURLArg(f)
var err error
f, mainArtifact, secret, err = parseImportURLArg(f)
if err != nil {
return err
}

// Try downloading the artifcat
msg, err := mc.DownloadArtifact(f, mainArtifact, secret)
Expand All @@ -64,7 +68,15 @@ func NewImportURLCommand(globalClientOpts *connectors.ClientOptions) *cobra.Comm
return importURLCmd
}

func parseImportURLArg(f string) (string, bool, string) {
func parseImportURLArg(f string) (string, bool, string, error) {
if !strings.HasPrefix(f, "https://") && !strings.HasPrefix(f, "http://") {
return "", false, "", errors.Wrapf(
errors.KindUsage,
"invalid artifact URL '%s': must start with http:// or https://",
f,
)
}

mainArtifact := true
secret := ""

Expand All @@ -84,5 +96,5 @@ func parseImportURLArg(f string) (string, bool, string) {
}
}
}
return f, mainArtifact, secret
return f, mainArtifact, secret, nil
}
193 changes: 116 additions & 77 deletions cmd/importURL_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,148 +19,187 @@ package cmd
import (
"testing"

"github.com/microcks/microcks-cli/pkg/errors"
"github.com/stretchr/testify/assert"
)

func TestParseImportURLArg(t *testing.T) {
tests := []struct {
name string
input string
expectedURL string
name string
input string
expectedURL string
expectedMainArtifact bool
expectedSecret string
expectedSecret string
wantErr bool
expectedErrMsg string
}{
{
name: "standard URL without suffixes",
input: "https://example.com/openapi.yaml",
expectedURL: "https://example.com/openapi.yaml",
name: "standard URL without suffixes",
input: "https://example.com/openapi.yaml",
expectedURL: "https://example.com/openapi.yaml",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "standard URL with mainArtifact true",
input: "https://example.com/spec1.yaml:true",
expectedURL: "https://example.com/spec1.yaml",
name: "standard URL with mainArtifact true",
input: "https://example.com/spec1.yaml:true",
expectedURL: "https://example.com/spec1.yaml",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "standard URL with mainArtifact false",
input: "https://example.com/spec1.yaml:false",
expectedURL: "https://example.com/spec1.yaml",
name: "standard URL with mainArtifact false",
input: "https://example.com/spec1.yaml:false",
expectedURL: "https://example.com/spec1.yaml",
expectedMainArtifact: false,
expectedSecret: "",
expectedSecret: "",
},
{
name: "standard URL with mainArtifact and secret",
input: "https://example.com/spec1.yaml:true:my-secret",
expectedURL: "https://example.com/spec1.yaml",
name: "standard URL with mainArtifact and secret",
input: "https://example.com/spec1.yaml:true:my-secret",
expectedURL: "https://example.com/spec1.yaml",
expectedMainArtifact: true,
expectedSecret: "my-secret",
expectedSecret: "my-secret",
},
{
name: "standard URL with mainArtifact false and secret",
input: "https://example.com/spec1.yaml:false:my-secret-token",
expectedURL: "https://example.com/spec1.yaml",
name: "standard URL with mainArtifact false and secret",
input: "https://example.com/spec1.yaml:false:my-secret-token",
expectedURL: "https://example.com/spec1.yaml",
expectedMainArtifact: false,
expectedSecret: "my-secret-token",
expectedSecret: "my-secret-token",
},
{
name: "URL with port and no suffixes",
input: "http://localhost:8585/spec.yaml",
expectedURL: "http://localhost:8585/spec.yaml",
name: "URL with port and no suffixes",
input: "http://localhost:8585/spec.yaml",
expectedURL: "http://localhost:8585/spec.yaml",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "URL with port and mainArtifact true",
input: "http://localhost:8585/spec.yaml:true",
expectedURL: "http://localhost:8585/spec.yaml",
name: "URL with port and mainArtifact true",
input: "http://localhost:8585/spec.yaml:true",
expectedURL: "http://localhost:8585/spec.yaml",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "URL with port and mainArtifact false",
input: "http://localhost:8585/spec.yaml:false",
expectedURL: "http://localhost:8585/spec.yaml",
name: "URL with port and mainArtifact false",
input: "http://localhost:8585/spec.yaml:false",
expectedURL: "http://localhost:8585/spec.yaml",
expectedMainArtifact: false,
expectedSecret: "",
expectedSecret: "",
},
{
name: "URL with port, mainArtifact and secret",
input: "http://localhost:8585/spec.yaml:true:my-secret-token",
expectedURL: "http://localhost:8585/spec.yaml",
name: "URL with port, mainArtifact and secret",
input: "http://localhost:8585/spec.yaml:true:my-secret-token",
expectedURL: "http://localhost:8585/spec.yaml",
expectedMainArtifact: true,
expectedSecret: "my-secret-token",
expectedSecret: "my-secret-token",
},
{
name: "URL with port, mainArtifact false and secret",
input: "http://localhost:8585/spec.yaml:false:my-secret-token",
expectedURL: "http://localhost:8585/spec.yaml",
name: "URL with port, mainArtifact false and secret",
input: "http://localhost:8585/spec.yaml:false:my-secret-token",
expectedURL: "http://localhost:8585/spec.yaml",
expectedMainArtifact: false,
expectedSecret: "my-secret-token",
expectedSecret: "my-secret-token",
},
{
name: "malformed bool suffix preserves URL",
input: "http://localhost:8585/spec.yaml:tru",
expectedURL: "http://localhost:8585/spec.yaml:tru",
name: "malformed bool suffix preserves URL",
input: "http://localhost:8585/spec.yaml:tru",
expectedURL: "http://localhost:8585/spec.yaml:tru",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "malformed bool with secret preserves URL",
input: "http://localhost:8585/spec.yaml:tru:mysecret",
expectedURL: "http://localhost:8585/spec.yaml:tru:mysecret",
name: "malformed bool with secret preserves URL",
input: "http://localhost:8585/spec.yaml:tru:mysecret",
expectedURL: "http://localhost:8585/spec.yaml:tru:mysecret",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "URL with path and no port",
input: "https://raw.githubusercontent.com/org/repo/main/spec.yaml",
expectedURL: "https://raw.githubusercontent.com/org/repo/main/spec.yaml",
name: "URL with path and no port",
input: "https://raw.githubusercontent.com/org/repo/main/spec.yaml",
expectedURL: "https://raw.githubusercontent.com/org/repo/main/spec.yaml",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "short URL without path",
input: "http://localhost:true",
expectedURL: "http://localhost",
name: "short URL without path",
input: "http://localhost:true",
expectedURL: "http://localhost",
expectedMainArtifact: true,
expectedSecret: "",
expectedSecret: "",
},
{
name: "boolean-like secret is not consumed as primary flag",
input: "http://example.com/api:true:false",
expectedURL: "http://example.com/api",
name: "boolean-like secret is not consumed as primary flag",
input: "http://example.com/api:true:false",
expectedURL: "http://example.com/api",
expectedMainArtifact: true,
expectedSecret: "false",
expectedSecret: "false",
},
{
name: "secret containing colons",
input: "http://example.com/api:true:my:secret:token",
expectedURL: "http://example.com/api",
name: "secret containing colons",
input: "http://example.com/api:true:my:secret:token",
expectedURL: "http://example.com/api",
expectedMainArtifact: true,
expectedSecret: "my:secret:token",
expectedSecret: "my:secret:token",
},
{
name: "URL with port and secret containing colons",
input: "http://localhost:8080/api:false:auth:basic:user:pass",
expectedURL: "http://localhost:8080/api",
name: "URL with port and secret containing colons",
input: "http://localhost:8080/api:false:auth:basic:user:pass",
expectedURL: "http://localhost:8080/api",
expectedMainArtifact: false,
expectedSecret: "auth:basic:user:pass",
expectedSecret: "auth:basic:user:pass",
},
{
name: "boolean host with port does not get misparsed as primary flag",
input: "http://true:8080/api:false:secret",
expectedURL: "http://true:8080/api",
name: "boolean host with port does not get misparsed as primary flag",
input: "http://true:8080/api:false:secret",
expectedURL: "http://true:8080/api",
expectedMainArtifact: false,
expectedSecret: "secret",
expectedSecret: "secret",
},
{
name: "relative path without scheme",
input: "spec.yaml",
wantErr: true,
expectedErrMsg: "invalid artifact URL 'spec.yaml': must start with http:// or https://",
},
{
name: "relative path with suffixes without scheme",
input: "spec.yaml:true:mysecret",
wantErr: true,
expectedErrMsg: "invalid artifact URL 'spec.yaml:true:mysecret': must start with http:// or https://",
},
{
name: "unsupported ftp scheme",
input: "ftp://example.com/spec.yaml",
wantErr: true,
expectedErrMsg: "invalid artifact URL 'ftp://example.com/spec.yaml': must start with http:// or https://",
},
{
name: "file scheme",
input: "file:///tmp/spec.yaml",
wantErr: true,
expectedErrMsg: "invalid artifact URL 'file:///tmp/spec.yaml': must start with http:// or https://",
},
{
name: "empty string",
input: "",
wantErr: true,
expectedErrMsg: "invalid artifact URL '': must start with http:// or https://",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
url, mainArtifact, secret := parseImportURLArg(tt.input)
url, mainArtifact, secret, err := parseImportURLArg(tt.input)
if tt.wantErr {
assert.EqualError(t, err, tt.expectedErrMsg)
assert.Equal(t, errors.KindUsage, errors.KindOf(err))
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedURL, url)
assert.Equal(t, tt.expectedMainArtifact, mainArtifact)
assert.Equal(t, tt.expectedSecret, secret)
Expand Down
Loading