Skip to content

Commit 1ebf89d

Browse files
committed
Add pkg/image/registryclient/v2
This is a separate module that is compatible with pkg/image/registryclient, but uses distribution/[email protected]. Since distribution/[email protected] has removed the client package being used by library-go currently, or rather moved it into internal, this patch includes copying the packages from distribution/v3/internal/client into registryclient/v2/internal. Some of the logic is exported as required to make oc work as that is where this patch has been tested. So the approach taken was to copy registryclient into registryclient/v2, then copy distribution/v3/internal/client into registryclient/v2/internal, then keep exporting functionality so that oc can be ported to distributions/[email protected] and registryclient/v2. Generally when a project importing library-go wants to migrate to the current distribution/v3, they can just import this module instead of using pkg/image/registryclient. The interface is compatible with pkg/image/registryclient and all that is needed is changing the import path.
1 parent ccdcf64 commit 1ebf89d

26 files changed

+9671
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package auth
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
)
7+
8+
// APIVersions gets the API versions out of an HTTP response using the provided
9+
// version header as the key for the HTTP header.
10+
func APIVersions(resp *http.Response, versionHeader string) []string {
11+
var versions []string
12+
if versionHeader != "" {
13+
for _, supportedVersions := range resp.Header[http.CanonicalHeaderKey(versionHeader)] {
14+
for _, version := range strings.Fields(supportedVersions) {
15+
versions = append(versions, version)
16+
}
17+
}
18+
}
19+
return versions
20+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package auth
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
"testing"
7+
8+
"github.com/google/go-cmp/cmp"
9+
)
10+
11+
func TestAPIVersions(t *testing.T) {
12+
const header = "Docker-Distribution-API-Version"
13+
14+
tests := []struct {
15+
name string
16+
headerName string
17+
headerValue string
18+
expectedVersions []string
19+
}{{
20+
name: "HeaderPresentExactName",
21+
headerName: header,
22+
headerValue: "registry/2.0",
23+
expectedVersions: []string{"registry/2.0"},
24+
}, {
25+
name: "HeaderPresentLowerCaseName",
26+
headerName: strings.ToLower(header),
27+
headerValue: "registry/2.0",
28+
expectedVersions: []string{"registry/2.0"},
29+
}, {
30+
name: "HeaderPresentMultipleValues",
31+
headerName: header,
32+
headerValue: "registry/2.0 registry/3.0",
33+
expectedVersions: []string{"registry/2.0", "registry/3.0"},
34+
}, {
35+
name: "HeaderMissing",
36+
headerName: header,
37+
headerValue: "",
38+
expectedVersions: nil,
39+
}}
40+
41+
for _, test := range tests {
42+
t.Run(test.name, func(t *testing.T) {
43+
resp := http.Response{
44+
Header: make(map[string][]string),
45+
}
46+
if test.headerValue != "" {
47+
resp.Header.Set(test.headerName, test.headerValue)
48+
}
49+
50+
versions := APIVersions(&resp, header)
51+
if !cmp.Equal(test.expectedVersions, versions) {
52+
t.Error("Unexpected versions slice:\n", cmp.Diff(test.expectedVersions, versions))
53+
}
54+
})
55+
}
56+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package auth
2+
3+
import "net/url"
4+
5+
// CredentialStore is an interface for getting credentials for a given URL.
6+
type CredentialStore interface {
7+
// Basic returns basic auth for the given URL
8+
Basic(*url.URL) (string, string)
9+
10+
// RefreshToken returns a refresh token for the
11+
// given URL and service
12+
RefreshToken(*url.URL, string) string
13+
14+
// SetRefreshToken sets the refresh token if none
15+
// is provided for the given url and service
16+
SetRefreshToken(realm *url.URL, service, token string)
17+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package auth
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
// Scope is a type which is serializable to a string
9+
// using the allow scope grammar.
10+
type Scope interface {
11+
String() string
12+
}
13+
14+
// RepositoryScope represents a token scope for access
15+
// to a repository.
16+
type RepositoryScope struct {
17+
Repository string
18+
Class string
19+
Actions []string
20+
}
21+
22+
// String returns the string representation of the repository
23+
// using the scope grammar
24+
func (rs RepositoryScope) String() string {
25+
repoType := "repository"
26+
// Keep existing format for image class to maintain backwards compatibility
27+
// with authorization servers which do not support the expanded grammar.
28+
if rs.Class != "" && rs.Class != "image" {
29+
repoType = fmt.Sprintf("%s(%s)", repoType, rs.Class)
30+
}
31+
return fmt.Sprintf("%s:%s:%s", repoType, rs.Repository, strings.Join(rs.Actions, ","))
32+
}

0 commit comments

Comments
 (0)