Skip to content

Commit

Permalink
introduce schemaless toggle to allow for short urls for topology path…
Browse files Browse the repository at this point in the history
…s only
  • Loading branch information
hellt committed Nov 7, 2023
1 parent 596c19a commit 99b0a70
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 25 deletions.
2 changes: 1 addition & 1 deletion clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func WithTopoPath(path, varsFile string) ClabOption {
return err
}
// if the path is not a local file and a URL, download the file and store it in the tmp dir
case !utils.FileOrDirExists(path) && utils.IsHttpURL(path):
case !utils.FileOrDirExists(path) && utils.IsHttpURL(path, true):
file, err = c.downloadTopoFile(path)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (c *CLab) processStartupConfig(nodeCfg *types.NodeConfig) error {
// it contains at least one newline
isEmbeddedConfig := strings.Count(p, "\n") >= 1
// downloadable config starts with http(s)://
isDownloadableConfig := utils.IsHttpURL(p)
isDownloadableConfig := utils.IsHttpURL(p, false)

if isEmbeddedConfig || isDownloadableConfig {
// both embedded and downloadable configs are require clab tmp dir to be created
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func getTopoFilePath(cmd *cobra.Command) error {
if err != nil {
return err
}
case utils.IsHttpURL(topo):
case utils.IsHttpURL(topo, true):
// canonize the passed topo as URL by adding https schema if it was missing
if !strings.HasPrefix(topo, "http://") && !strings.HasPrefix(topo, "https://") {
topo = "https://" + topo
Expand Down
2 changes: 1 addition & 1 deletion nodes/srl/srl.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func (s *srl) PreDeploy(_ context.Context, params *nodes.PreDeployParams) error
for _, fullpath := range agents {
basename := filepath.Base(fullpath)
// if it is a url extract filename from url or content-disposition header
if utils.IsHttpURL(fullpath) {
if utils.IsHttpURL(fullpath, false) {
basename = utils.FilenameForURL(fullpath)
}
// enforce yml extension
Expand Down
22 changes: 18 additions & 4 deletions utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func FileOrDirExists(filename string) bool {
// mode is the desired target file permissions, e.g. "0644".
func CopyFile(src, dst string, mode os.FileMode) (err error) {
var sfi os.FileInfo
if !IsHttpURL(src) {
if !IsHttpURL(src, false) {
sfi, err = os.Stat(src)
if err != nil {
return err
Expand Down Expand Up @@ -82,7 +82,21 @@ func CopyFile(src, dst string, mode os.FileMode) (err error) {
}

// IsHttpURL checks if the url is a downloadable HTTP URL.
func IsHttpURL(s string) bool {
// The allowSchemaless toggle when set to true will allow URLs without a schema
// such as "srlinux.dev/clab-srl". This is shortened notion that is used with
// "deploy -t <url>" only.
// Other callers of IsHttpURL should set the toggle to false.
func IsHttpURL(s string, allowSchemaless bool) bool {
// '-' denotes stdin and not the URL
if s == "-" {
return false
}

//
if !allowSchemaless && !strings.HasPrefix(s, "http://") && !strings.HasPrefix(s, "https://") {
return false
}

if !strings.HasPrefix(s, "http://") && !strings.HasPrefix(s, "https://") {
s = "https://" + s
}
Expand All @@ -100,7 +114,7 @@ func IsHttpURL(s string) bool {
func CopyFileContents(src, dst string, mode os.FileMode) (err error) {
var in io.ReadCloser

if IsHttpURL(src) {
if IsHttpURL(src, false) {
client := NewHTTPClient()

// download using client
Expand Down Expand Up @@ -280,7 +294,7 @@ func FilenameForURL(rawUrl string) string {
}

// try extracting the filename from "content-disposition" header
if IsHttpURL(rawUrl) {
if IsHttpURL(rawUrl, false) {
resp, err := http.Head(rawUrl)
if err != nil {
return filepath.Base(u.Path)
Expand Down
50 changes: 33 additions & 17 deletions utils/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,36 +87,52 @@ func TestFileLines(t *testing.T) {

func TestIsHttpURL(t *testing.T) {
tests := []struct {
name string
url string
want bool
name string
url string
allowSchemaless bool
want bool
}{
{
name: "Valid HTTP URL",
url: "http://example.com",
want: true,
name: "Valid HTTP URL",
url: "http://example.com",
allowSchemaless: false,
want: true,
},
{
name: "Valid HTTPS URL",
url: "https://example.com",
allowSchemaless: false,
want: true,
},
{
name: "Valid URL without scheme",
url: "srlinux.dev/clab-srl",
allowSchemaless: true,
want: true,
},
{
name: "Valid HTTPS URL",
url: "https://example.com",
want: true,
name: "Valid URL without scheme and schemaless not allowed",
url: "srlinux.dev/clab-srl",
allowSchemaless: false,
want: false,
},
{
name: "Valid URL without scheme",
url: "srlinux.dev/clab-srl",
want: true,
name: "Invalid URL",
url: "/foo/bar",
allowSchemaless: false,
want: false,
},
{
name: "Invalid URL",
url: "/foo/bar",
want: false,
name: "stdin symbol '-'",
url: "-",
allowSchemaless: false,
want: false,
},
// Add more test cases as needed
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsHttpURL(tt.url); got != tt.want {
if got := IsHttpURL(tt.url, tt.allowSchemaless); got != tt.want {
t.Errorf("IsHttpUri() = %v, want %v", got, tt.want)
}
})
Expand Down

0 comments on commit 99b0a70

Please sign in to comment.