Переглянути джерело

opts: implement IsReservedLabelNamespace() function

Extract the prefix-check to a function

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 4 роки тому
батько
коміт
693c2b0c43
2 змінених файлів з 99 додано та 5 видалено
  1. 18 4
      opts/opts.go
  2. 81 1
      opts/opts_test.go

+ 18 - 4
opts/opts.go

@@ -259,13 +259,12 @@ func validateDomain(val string) (string, error) {
 // and returns it.
 // Labels are in the form on key=value.
 func ValidateLabel(val string) (string, error) {
-	if strings.Count(val, "=") < 1 {
+	kv := strings.SplitN(val, "=", 2)
+	if len(kv) != 2 {
 		return "", fmt.Errorf("bad attribute format: %s", val)
 	}
 
-	lowered := strings.ToLower(val)
-	if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") ||
-		strings.HasPrefix(lowered, "org.dockerproject.") {
+	if IsReservedLabelNamespace(kv[0]) {
 		return "", fmt.Errorf(
 			"label %s is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
 			val)
@@ -274,6 +273,21 @@ func ValidateLabel(val string) (string, error) {
 	return val, nil
 }
 
+var reservedLabelNamespaces = []string{"com.docker", "io.docker", "org.dockerproject"}
+
+// IsReservedLabelNamespace checks if a given label uses a reserved namespace
+// Reserved namespaces are com.docker.*, io.docker.*, and org.dockerproject.*
+// (case insensitive).
+func IsReservedLabelNamespace(name string) bool {
+	lowered := strings.ToLower(name)
+	for _, ns := range reservedLabelNamespaces {
+		if lowered == ns || strings.HasPrefix(lowered, ns+".") {
+			return true
+		}
+	}
+	return false
+}
+
 // ValidateSingleGenericResource validates that a single entry in the
 // generic resource list is valid.
 // i.e 'GPU=UID1' is valid however 'GPU:UID1' or 'UID1' isn't

+ 81 - 1
opts/opts_test.go

@@ -184,7 +184,7 @@ func TestValidateLabel(t *testing.T) {
 		expectedErr    string
 	}{
 		{
-			name:        "lable with bad attribute format",
+			name:        "label with bad attribute format",
 			label:       "label",
 			expectedErr: "bad attribute format: label",
 		},
@@ -268,6 +268,86 @@ func TestValidateLabel(t *testing.T) {
 	}
 }
 
+func TestIsReservedLabelNamespace(t *testing.T) {
+	tests := []struct {
+		label    string
+		expected bool
+	}{
+		{
+			label:    "my-label",
+			expected: false,
+		},
+		{
+			label:    "com.dockerpsychnotreserved.label",
+			expected: false,
+		},
+		{
+			label:    "io.dockerproject.not",
+			expected: false,
+		},
+		{
+			label:    "org.docker.not",
+			expected: false,
+		},
+		{
+			label:    "com.docker",
+			expected: true,
+		},
+		{
+			label:    "com.docker.",
+			expected: true,
+		},
+		{
+			label:    "com.docker.feature",
+			expected: true,
+		},
+		{
+			label:    "COM.docker.feature",
+			expected: true,
+		},
+		{
+			label:    "io.docker",
+			expected: true,
+		},
+		{
+			label:    "io.docker.",
+			expected: true,
+		},
+		{
+			label:    "io.docker.feature",
+			expected: true,
+		},
+		{
+			label:    "io.docker.feature",
+			expected: true,
+		},
+		{
+			label:    "org.dockerproject",
+			expected: true,
+		},
+		{
+			label:    "org.dockerproject.",
+			expected: true,
+		},
+		{
+			label:    "org.dockerproject.feature",
+			expected: true,
+		},
+		{
+			label:    "org.dockerproject.feature",
+			expected: true,
+		},
+	}
+
+	for _, tc := range tests {
+		testCase := tc
+		t.Run(testCase.label, func(t *testing.T) {
+			result := IsReservedLabelNamespace(testCase.label)
+			assert.Equal(t, result, testCase.expected)
+		})
+	}
+}
+
 func logOptsValidator(val string) (string, error) {
 	allowedKeys := map[string]string{"max-size": "1", "max-file": "2"}
 	vals := strings.Split(val, "=")