diff --git a/cmd/root.go b/cmd/root.go index 57ad93f44d..d39704bbe2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,12 +6,14 @@ package cmd import ( "errors" + "fmt" "os" "path/filepath" "time" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/srl-labs/containerlab/utils" ) var ( @@ -106,12 +108,27 @@ func getTopoFilePath(cmd *cobra.Command) error { return nil } + var err error + if utils.IsHttpUri(topo){ + switch { + case utils.IsGitHubURL(topo): + err := utils.CheckSuffix(topo) + if err != nil { + return err + } + rawUrl := utils.GetRawURL(topo) + topo = utils.FilenameForURL(topo) + utils.CopyFileContents(rawUrl, topo, 0754) + default: + return fmt.Errorf("unsupported git repositoy: %s", topo) + } + } + // if topo or name flags have been provided, don't try to derive the topo file if topo != "" || name != "" { return nil } - var err error log.Debugf("trying to find topology files automatically") diff --git a/utils/http.go b/utils/http.go new file mode 100644 index 0000000000..64249d7647 --- /dev/null +++ b/utils/http.go @@ -0,0 +1,30 @@ +package utils + +import ( + "strings" + "errors" +) + + +func GetRawURL(url string) string { + if strings.Contains(url, "github.com") { + raw:=strings.Replace(url, "github.com", "raw.githubusercontent.com", 1) + return strings.Replace(raw, "/blob", "", 1) + } + return url +} + +func IsGitHubURL(url string) bool { + return strings.Contains(url, "github") + +} + +// required global variable for tests, otherwise comparison operator fails as error instances were not equal +var ErrInvalidSuffix = errors.New("valid URL passed in as topology file, but does not end with .yml or .yaml, endpoint must be an actual topology file") +func CheckSuffix(url string) error { + // check if topo ends with either .yml or .yaml + if !strings.HasSuffix(url, ".yml") && !strings.HasSuffix(url, ".yaml") { + return ErrInvalidSuffix + } + return nil +} diff --git a/utils/http_test.go b/utils/http_test.go new file mode 100644 index 0000000000..46d3c46023 --- /dev/null +++ b/utils/http_test.go @@ -0,0 +1,67 @@ +package utils + +import ( + "testing" +) + +func TestIsGithubURL(t *testing.T) { + // tests that github urls are detected + var tests = []struct { + input string + expected bool + }{ + {"github.com", true}, + {"github.com/containers/containerlab/blob/master/README.md", true}, + {"google.com/containers", false}, + {"google.com/containers/containerlab/blob/master/README.md", false}, + {"gitlab.com/containers", false}, + {"raw.githubusercontent.com/containers", true}, + } + for _, test := range tests { + if output := IsGitHubURL(test.input); output != test.expected { + t.Error("Test Failed: {} inputted, {} expected, recieved: {}", test.input, test.expected, output) + } + } +} + +func TestGetRawURL(t *testing.T) { + // tests that github urls are converted to raw urls evething else is left as is + var tests = []struct { + input string + expected string + }{ + {"github.com", "raw.githubusercontent.com"}, + {"github.com/containers/containerlab/blob/master/README.md", "raw.githubusercontent.com/containers/containerlab/master/README.md"}, + {"google.com/containers", "google.com/containers"}, + {"google.com/containers/containerlab/blob/master/README.md", "google.com/containers/containerlab/blob/master/README.md"}, + {"gitlab.com/containers", "gitlab.com/containers"}, + {"raw.githubusercontent.com/containers", "raw.githubusercontent.com/containers"}, + } + for _, test := range tests { + if output := GetRawURL(test.input); output != test.expected { + t.Error("Test Failed: {} inputted, {} expected, recieved: {}", test.input, test.expected, output) + } + } +} + +func TestCheckSuffix(t *testing.T) { + // tests for valid suffix + var tests = []struct { + input string + expected error + }{ + {"github.com", ErrInvalidSuffix}, + {"github.com/containers/containerlab/blob/master/README.md", ErrInvalidSuffix}, + {"google.com/containers", ErrInvalidSuffix}, + {"google.com/containers/containerlab/blob/master/README.md", ErrInvalidSuffix}, + {"gitlab.com/containers", ErrInvalidSuffix}, + {"raw.githubusercontent.com/containers", ErrInvalidSuffix}, + {"github.com/containers/containerlab/blob/master/README.yml", nil}, + {"github.com/containers/containerlab/blob/master/README.yaml", nil}, + } + for _, test := range tests { + if output := CheckSuffix(test.input); output != test.expected { + t.Error("Test Failed: {} inputted, {} expected, recieved: {}", test.input, test.expected, output) + } + } +}