Update ParseNamed to require canonical form
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)master
							parent
							
								
									954b4e8154
								
							
						
					
					
						commit
						6170ac53da
					
				|  | @ -208,6 +208,13 @@ func TestParseRepositoryInfo(t *testing.T) { | |||
| 			AmbiguousName: "index.docker.io/library/ubuntu-12.04-base", | ||||
| 			Domain:        "docker.io", | ||||
| 		}, | ||||
| 		{ | ||||
| 			RemoteName:    "library/foo", | ||||
| 			FamiliarName:  "foo", | ||||
| 			FullName:      "docker.io/library/foo", | ||||
| 			AmbiguousName: "docker.io/foo", | ||||
| 			Domain:        "docker.io", | ||||
| 		}, | ||||
| 		{ | ||||
| 			RemoteName:    "library/foo/bar", | ||||
| 			FamiliarName:  "library/foo/bar", | ||||
|  |  | |||
|  | @ -55,6 +55,9 @@ var ( | |||
| 
 | ||||
| 	// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
 | ||||
| 	ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax) | ||||
| 
 | ||||
| 	// ErrNameNotCanonical is returned when a name is not canonical.
 | ||||
| 	ErrNameNotCanonical = errors.New("repository name must be canonical") | ||||
| ) | ||||
| 
 | ||||
| // Reference is an opaque object reference identifier that may include
 | ||||
|  | @ -231,18 +234,17 @@ func Parse(s string) (Reference, error) { | |||
| } | ||||
| 
 | ||||
| // ParseNamed parses s and returns a syntactically valid reference implementing
 | ||||
| // the Named interface. The reference must have a name, otherwise an error is
 | ||||
| // returned.
 | ||||
| // the Named interface. The reference must have a name and be in the canonical
 | ||||
| // form, otherwise an error is returned.
 | ||||
| // If an error was encountered it is returned, along with a nil Reference.
 | ||||
| // NOTE: ParseNamed will not handle short digests.
 | ||||
| func ParseNamed(s string) (Named, error) { | ||||
| 	ref, err := Parse(s) | ||||
| 	named, err := ParseNormalizedNamed(s) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	named, isNamed := ref.(Named) | ||||
| 	if !isNamed { | ||||
| 		return nil, fmt.Errorf("reference %s has no name", ref.String()) | ||||
| 	if named.String() != s { | ||||
| 		return nil, ErrNameNotCanonical | ||||
| 	} | ||||
| 	return named, nil | ||||
| } | ||||
|  |  | |||
|  | @ -583,3 +583,77 @@ func TestWithDigest(t *testing.T) { | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestParseNamed(t *testing.T) { | ||||
| 	testcases := []struct { | ||||
| 		input  string | ||||
| 		domain string | ||||
| 		name   string | ||||
| 		err    error | ||||
| 	}{ | ||||
| 		{ | ||||
| 			input:  "test.com/foo", | ||||
| 			domain: "test.com", | ||||
| 			name:   "foo", | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  "test:8080/foo", | ||||
| 			domain: "test:8080", | ||||
| 			name:   "foo", | ||||
| 		}, | ||||
| 		{ | ||||
| 			input: "test_com/foo", | ||||
| 			err:   ErrNameNotCanonical, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input: "test.com", | ||||
| 			err:   ErrNameNotCanonical, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input: "foo", | ||||
| 			err:   ErrNameNotCanonical, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input: "library/foo", | ||||
| 			err:   ErrNameNotCanonical, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  "docker.io/library/foo", | ||||
| 			domain: "docker.io", | ||||
| 			name:   "library/foo", | ||||
| 		}, | ||||
| 		// Ambiguous case, parser will add "library/" to foo
 | ||||
| 		{ | ||||
| 			input: "docker.io/foo", | ||||
| 			err:   ErrNameNotCanonical, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, testcase := range testcases { | ||||
| 		failf := func(format string, v ...interface{}) { | ||||
| 			t.Logf(strconv.Quote(testcase.input)+": "+format, v...) | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 
 | ||||
| 		named, err := ParseNamed(testcase.input) | ||||
| 		if err != nil && testcase.err == nil { | ||||
| 			failf("error parsing name: %s", err) | ||||
| 			continue | ||||
| 		} else if err == nil && testcase.err != nil { | ||||
| 			failf("parsing succeded: expected error %v", testcase.err) | ||||
| 			continue | ||||
| 		} else if err != testcase.err { | ||||
| 			failf("unexpected error %v, expected %v", err, testcase.err) | ||||
| 			continue | ||||
| 		} else if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		domain, name := SplitHostname(named) | ||||
| 		if domain != testcase.domain { | ||||
| 			failf("unexpected domain: got %q, expected %q", domain, testcase.domain) | ||||
| 		} | ||||
| 		if name != testcase.name { | ||||
| 			failf("unexpected name: got %q, expected %q", name, testcase.name) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue