Repository: tetratelabs/getenvoy
Pull request #29 (2019-08-02 07:25:23)

Autofill Platform if not passed in via reference
Signed-off-by: Liam White <liam@tetrate.io>


Patch:
diff --git a/pkg/manifest/locate.go b/pkg/manifest/locate.go
index 1d1e122..2eee541 100644
--- a/pkg/manifest/locate.go
+++ b/pkg/manifest/locate.go
@@ -24,12 +24,15 @@ import (
 
 // NewKey creates a manifest key based on the reference it is given
 func NewKey(reference string) (*Key, error) {
-	r := regexp.MustCompile(`^(.+):(.+)/(.+)$`)
+	r := regexp.MustCompile(`^([\w\d-\._]+):([\w\d-\._]+)/?([\w\d-\._]+)?$`)
 	matches := r.FindStringSubmatch(reference)
 	if len(matches) != 4 {
 		return nil, fmt.Errorf("reference %v is not of valid format <flavor>:<version>/<platform>", reference)
 	}
-
+	// If platform is empty, fill it in.
+	if len(matches[3]) == 0 {
+		matches[3] = platform()
+	}
 	return &Key{strings.ToLower(matches[1]), strings.ToLower(matches[2]), platformToEnum(matches[3])}, nil
 }
 
@@ -50,7 +53,10 @@ type Key struct {
 // The build version is searched for as a prefix of the OperatingSystemVersion.
 // If the OperatingSystemVersion is empty it returns the first build listed for that operating system
 func Locate(key *Key, manifestLocation string) (string, error) {
-	if _, err := url.Parse(manifestLocation); err != nil {
+	if key == nil {
+		return "", errors.New("passed key was nil")
+	}
+	if u, err := url.Parse(manifestLocation); err != nil || u.Host == "" || u.Scheme == "" {
 		return "", errors.New("only URL manifest locations are supported")
 	}
 	manifest, err := fetch(manifestLocation)
diff --git a/pkg/manifest/platform_darwin.go b/pkg/manifest/platform_darwin.go
new file mode 100644
index 0000000..30459dc
--- /dev/null
+++ b/pkg/manifest/platform_darwin.go
@@ -0,0 +1,19 @@
+// Copyright 2019 Tetrate
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package manifest
+
+func platform() string {
+	return "darwin"
+}
diff --git a/pkg/manifest/platform_linux.go b/pkg/manifest/platform_linux.go
new file mode 100644
index 0000000..90c0b8b
--- /dev/null
+++ b/pkg/manifest/platform_linux.go
@@ -0,0 +1,19 @@
+// Copyright 2019 Tetrate
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package manifest
+
+func platform() string {
+	return "linux-glibc"
+}


Test patch:
diff --git a/pkg/manifest/locate_test.go b/pkg/manifest/locate_test.go
index a5bc6cb..fd0a0d4 100644
--- a/pkg/manifest/locate_test.go
+++ b/pkg/manifest/locate_test.go
@@ -15,6 +15,7 @@
 package manifest
 
 import (
+	"fmt"
 	"net/http"
 	"testing"
 
@@ -23,42 +24,65 @@ import (
 
 func TestLocate(t *testing.T) {
 	tests := []struct {
-		name             string
-		reference        string
-		locationOverride string
-		want             string
-		wantErr          bool
+		name               string
+		reference          string
+		locationOverride   string
+		responseStatusCode int
+		want               string
+		wantErr            bool
 	}{
 		{
-			name:      "standard 1.11.0 linux-glibc matches",
-			reference: "standard:1.11.0/linux-glibc",
-			want:      "standard:1.11.0/linux-glibc",
+			name:               "standard 1.11.0 linux-glibc matches",
+			reference:          "standard:1.11.0/linux-glibc",
+			want:               "standard:1.11.0/linux-glibc",
+			responseStatusCode: http.StatusOK,
 		},
 		{
-			name:      "standard-fips1402:1.10.0/linux-glibc matches",
-			reference: "standard-fips1402:1.10.0/linux-glibc",
-			want:      "standard-fips1402:1.10.0/linux-glibc",
+			name:               "standard 1.11.0 matches",
+			reference:          "standard:1.11.0",
+			want:               fmt.Sprintf("standard:1.11.0/%v", platform()),
+			responseStatusCode: http.StatusOK,
 		},
 		{
-			name:      "sTanDard:nIgHTLY/LiNuX-gLiBc matches",
-			reference: "sTanDard:nIgHTLY/LiNuX-gLiBc",
-			want:      "standard:nightly/linux-glibc",
+			name:               "standard-fips1402:1.10.0/linux-glibc matches",
+			reference:          "standard-fips1402:1.10.0/linux-glibc",
+			want:               "standard-fips1402:1.10.0/linux-glibc",
+			responseStatusCode: http.StatusOK,
 		},
 		{
-			name:      "Error if not found",
-			reference: "notaFlavor:1.11.0/notaPlatform",
+			name:               "sTanDard:nIgHTLY/LiNuX-gLiBc matches",
+			reference:          "sTanDard:nIgHTLY/LiNuX-gLiBc",
+			want:               "standard:nightly/linux-glibc",
+			responseStatusCode: http.StatusOK,
+		},
+		{
+			name:               "Error if not found",
+			reference:          "notaFlavor:1.11.0/notaPlatform",
+			responseStatusCode: http.StatusOK,
+			wantErr:            true,
+		},
+		{
+			name:      "Error if passed nil key",
+			reference: "notAReference",
 			wantErr:   true,
 		},
 		{
 			name:             "Error on non-url manifest locations",
+			reference:        "standard:1.11.0",
 			locationOverride: "not-a-url",
 			wantErr:          true,
 		},
+		{
+			name:               "Error on failed fetch",
+			reference:          "standard:1.11.0",
+			responseStatusCode: http.StatusTeapot,
+			wantErr:            true,
+		},
 	}
 	for _, tt := range tests {
 		tc := tt
 		t.Run(tc.name, func(t *testing.T) {
-			mock := mockServer(http.StatusOK, "manifest.golden")
+			mock := mockServer(tc.responseStatusCode, "manifest.golden")
 			defer mock.Close()
 			location := mock.URL
 			if tc.locationOverride != "" {
@@ -82,11 +106,13 @@ func TestNewKey(t *testing.T) {
 		want      *Key
 		wantErr   bool
 	}{
+		{"flavor:version/platform/platform", nil, true},
 		{"flavor:version/platform", &Key{Flavor: "flavor", Version: "version", Platform: "PLATFORM"}, false},
 		{"flavor:version/platform-glibc", &Key{Flavor: "flavor", Version: "version", Platform: "PLATFORM_GLIBC"}, false},
 		{"fLaVoR:VeRsIoN/pLaTfOrM", &Key{Flavor: "flavor", Version: "version", Platform: "PLATFORM"}, false},
-		{"flavor:version/", nil, true},
-		{"flavor:version", nil, true},
+		{"flavor:version/", &Key{Flavor: "flavor", Version: "version", Platform: platformToEnum(platform())}, false},
+		{"flavor:version", &Key{Flavor: "flavor", Version: "version", Platform: platformToEnum(platform())}, false},
+		{"fLaVoR:VeRsIoN", &Key{Flavor: "flavor", Version: "version", Platform: platformToEnum(platform())}, false},
 		{"flavor:", nil, true},
 		{"flavor", nil, true},
 	}