update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
19a32db84d
commit
94d1cfbfbf
10501 changed files with 2307943 additions and 29279 deletions
8
vendor/github.com/genuinetools/reg/registry/authchallenge.go
generated
vendored
8
vendor/github.com/genuinetools/reg/registry/authchallenge.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -12,6 +13,9 @@ var (
|
|||
bearerRegex = regexp.MustCompile(
|
||||
`^\s*Bearer\s+(.*)$`)
|
||||
basicRegex = regexp.MustCompile(`^\s*Basic\s+.*$`)
|
||||
|
||||
// ErrBasicAuth indicates that the repository requires basic rather than token authentication.
|
||||
ErrBasicAuth = errors.New("basic auth required")
|
||||
)
|
||||
|
||||
func parseAuthHeader(header http.Header) (*authService, error) {
|
||||
|
@ -25,14 +29,14 @@ func parseAuthHeader(header http.Header) (*authService, error) {
|
|||
|
||||
func parseChallenge(challengeHeader string) (*authService, error) {
|
||||
if basicRegex.MatchString(challengeHeader) {
|
||||
return nil, nil
|
||||
return nil, ErrBasicAuth
|
||||
}
|
||||
|
||||
match := bearerRegex.FindAllStringSubmatch(challengeHeader, -1)
|
||||
if d := len(match); d != 1 {
|
||||
return nil, fmt.Errorf("malformed auth challenge header: '%s', %d", challengeHeader, d)
|
||||
}
|
||||
parts := strings.Split(strings.TrimSpace(match[0][1]), ",")
|
||||
parts := strings.SplitN(strings.TrimSpace(match[0][1]), ",", 3)
|
||||
|
||||
var realm, service string
|
||||
var scope []string
|
||||
|
|
52
vendor/github.com/genuinetools/reg/registry/authchallenge_test.go
generated
vendored
52
vendor/github.com/genuinetools/reg/registry/authchallenge_test.go
generated
vendored
|
@ -1,7 +1,6 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -22,13 +21,13 @@ func (asm authServiceMock) equalTo(v *authService) bool {
|
|||
if asm.service != v.Service {
|
||||
return false
|
||||
}
|
||||
if reflect.DeepEqual(asm.scope, v.Scope) {
|
||||
return false
|
||||
for i, v := range v.Scope {
|
||||
if v != asm.scope[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if asm.realm != v.Realm.String() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
return asm.realm == v.Realm.String()
|
||||
}
|
||||
|
||||
func TestParseChallenge(t *testing.T) {
|
||||
|
@ -40,8 +39,47 @@ func TestParseChallenge(t *testing.T) {
|
|||
realm: "https://foobar.com/api/v1/token",
|
||||
},
|
||||
},
|
||||
{
|
||||
header: `Bearer realm="https://r.j3ss.co/auth",service="Docker registry",scope="repository:chrome:pull"`,
|
||||
value: authServiceMock{
|
||||
service: "Docker registry",
|
||||
realm: "https://r.j3ss.co/auth",
|
||||
scope: []string{"repository:chrome:pull"},
|
||||
},
|
||||
},
|
||||
{
|
||||
header: `Basic realm="https://r.j3ss.co/auth",service="Docker registry"`,
|
||||
errorString: "basic auth required",
|
||||
},
|
||||
{
|
||||
header: `Basic realm="Registry Realm",service="Docker registry"`,
|
||||
errorString: "basic auth required",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range challengeHeaderCases {
|
||||
val, err := parseChallenge(tc.header)
|
||||
if err != nil && !strings.Contains(err.Error(), tc.errorString) {
|
||||
t.Fatalf("expected error to contain %v, got %s", tc.errorString, err)
|
||||
}
|
||||
if err == nil && !tc.value.equalTo(val) {
|
||||
t.Fatalf("got %v, expected %v", val, tc.value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseChallengePush(t *testing.T) {
|
||||
challengeHeaderCases := []challengeTestCase{
|
||||
{
|
||||
header: `Bearer realm="https://foo.com/v2/token",service="foo.com",scope="repository:pdr/tls:pull,push"`,
|
||||
value: authServiceMock{
|
||||
realm: "https://foo.com/v2/token",
|
||||
service: "foo.com",
|
||||
scope: []string{"repository:pdr/tls:pull,push"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range challengeHeaderCases {
|
||||
val, err := parseChallenge(tc.header)
|
||||
if err != nil && !strings.Contains(err.Error(), tc.errorString) {
|
||||
|
|
2
vendor/github.com/genuinetools/reg/registry/basictransport.go
generated
vendored
2
vendor/github.com/genuinetools/reg/registry/basictransport.go
generated
vendored
|
@ -15,7 +15,7 @@ type BasicTransport struct {
|
|||
|
||||
// RoundTrip defines the round tripper for basic auth transport.
|
||||
func (t *BasicTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if strings.HasPrefix(req.URL.String(), t.URL) {
|
||||
if strings.HasPrefix(req.URL.String(), t.URL) && req.Header.Get("Authorization") == "" {
|
||||
if t.Username != "" || t.Password != "" {
|
||||
req.SetBasicAuth(t.Username, t.Password)
|
||||
}
|
||||
|
|
24
vendor/github.com/genuinetools/reg/registry/customtransport.go
generated
vendored
Normal file
24
vendor/github.com/genuinetools/reg/registry/customtransport.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CustomTransport defines the data structure for custom http.Request options.
|
||||
type CustomTransport struct {
|
||||
Transport http.RoundTripper
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
// RoundTrip defines the round tripper for the error transport.
|
||||
func (t *CustomTransport) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
if len(t.Headers) != 0 {
|
||||
for header, value := range t.Headers {
|
||||
request.Header.Add(header, value)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := t.Transport.RoundTrip(request)
|
||||
|
||||
return resp, err
|
||||
}
|
20
vendor/github.com/genuinetools/reg/registry/delete.go
generated
vendored
20
vendor/github.com/genuinetools/reg/registry/delete.go
generated
vendored
|
@ -5,24 +5,12 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
ocd "github.com/opencontainers/go-digest"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// Delete removes a repository digest or reference from the registry.
|
||||
// Delete removes a repository digest from the registry.
|
||||
// https://docs.docker.com/registry/spec/api/#deleting-an-image
|
||||
func (r *Registry) Delete(repository, digest string) error {
|
||||
// If digest is not valid try resolving it as a reference
|
||||
if _, err := ocd.Parse(digest); err != nil {
|
||||
digest, err = r.Digest(repository, digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if digest == "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the image.
|
||||
func (r *Registry) Delete(repository string, digest digest.Digest) (err error) {
|
||||
url := r.url("/v2/%s/manifests/%s", repository, digest)
|
||||
r.Logf("registry.manifests.delete url=%s repository=%s digest=%s",
|
||||
url, repository, digest)
|
||||
|
@ -32,7 +20,7 @@ func (r *Registry) Delete(repository, digest string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", schema2.MediaTypeManifest)
|
||||
req.Header.Add("Accept", fmt.Sprintf("%s;q=0.9", schema2.MediaTypeManifest))
|
||||
resp, err := r.Client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
19
vendor/github.com/genuinetools/reg/registry/digest.go
generated
vendored
19
vendor/github.com/genuinetools/reg/registry/digest.go
generated
vendored
|
@ -5,20 +5,26 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// Digest returns the digest for a repository and reference.
|
||||
func (r *Registry) Digest(repository, ref string) (string, error) {
|
||||
url := r.url("/v2/%s/manifests/%s", repository, ref)
|
||||
// Digest returns the digest for an image.
|
||||
func (r *Registry) Digest(image Image) (digest.Digest, error) {
|
||||
if len(image.Digest) > 1 {
|
||||
// return early if we already have an image digest.
|
||||
return image.Digest, nil
|
||||
}
|
||||
|
||||
url := r.url("/v2/%s/manifests/%s", image.Path, image.Tag)
|
||||
r.Logf("registry.manifests.get url=%s repository=%s ref=%s",
|
||||
url, repository, ref)
|
||||
url, image.Path, image.Tag)
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Accept", schema2.MediaTypeManifest)
|
||||
|
||||
req.Header.Add("Accept", schema2.MediaTypeManifest)
|
||||
resp, err := r.Client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -29,6 +35,5 @@ func (r *Registry) Digest(repository, ref string) (string, error) {
|
|||
return "", fmt.Errorf("Got status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
digest := resp.Header.Get("Docker-Content-Digest")
|
||||
return digest, nil
|
||||
return digest.Parse(resp.Header.Get("Docker-Content-Digest"))
|
||||
}
|
||||
|
|
49
vendor/github.com/genuinetools/reg/registry/digest_test.go
generated
vendored
Normal file
49
vendor/github.com/genuinetools/reg/registry/digest_test.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/genuinetools/reg/repoutils"
|
||||
)
|
||||
|
||||
func TestDigestFromDockerHub(t *testing.T) {
|
||||
auth, err := repoutils.GetAuthConfig("", "", "docker.io")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get auth config: %s", err)
|
||||
}
|
||||
|
||||
r, err := New(auth, Opt{})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create registry instance: %s", err)
|
||||
}
|
||||
|
||||
d, err := r.Digest(Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get digest: %s", err)
|
||||
}
|
||||
|
||||
if d == "" {
|
||||
t.Error("Empty digest received")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDigestFromGCR(t *testing.T) {
|
||||
auth, err := repoutils.GetAuthConfig("", "", "gcr.io")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get auth config: %s", err)
|
||||
}
|
||||
|
||||
r, err := New(auth, Opt{})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create registry instance: %s", err)
|
||||
}
|
||||
|
||||
d, err := r.Digest(Image{Domain: "gcr.io", Path: "google_containers/hyperkube", Tag: "v1.9.9"})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get digest: %s", err)
|
||||
}
|
||||
|
||||
if d == "" {
|
||||
t.Error("Empty digest received")
|
||||
}
|
||||
}
|
67
vendor/github.com/genuinetools/reg/registry/image.go
generated
vendored
Normal file
67
vendor/github.com/genuinetools/reg/registry/image.go
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// Image holds information about an image.
|
||||
type Image struct {
|
||||
Domain string
|
||||
Path string
|
||||
Tag string
|
||||
Digest digest.Digest
|
||||
named reference.Named
|
||||
}
|
||||
|
||||
// String returns the string representation of an image.
|
||||
func (i Image) String() string {
|
||||
return i.named.String()
|
||||
}
|
||||
|
||||
// Reference returns either the digest if it is non-empty or the tag for the image.
|
||||
func (i Image) Reference() string {
|
||||
if len(i.Digest.String()) > 1 {
|
||||
return i.Digest.String()
|
||||
}
|
||||
|
||||
return i.Tag
|
||||
}
|
||||
|
||||
// WithDigest sets the digest for an image.
|
||||
func (i *Image) WithDigest(digest digest.Digest) (err error) {
|
||||
i.Digest = digest
|
||||
i.named, err = reference.WithDigest(i.named, digest)
|
||||
return err
|
||||
}
|
||||
|
||||
// ParseImage returns an Image struct with all the values filled in for a given image.
|
||||
func ParseImage(image string) (Image, error) {
|
||||
// Parse the image name and tag.
|
||||
named, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return Image{}, fmt.Errorf("parsing image %q failed: %v", image, err)
|
||||
}
|
||||
// Add the latest lag if they did not provide one.
|
||||
named = reference.TagNameOnly(named)
|
||||
|
||||
i := Image{
|
||||
named: named,
|
||||
Domain: reference.Domain(named),
|
||||
Path: reference.Path(named),
|
||||
}
|
||||
|
||||
// Add the tag if there was one.
|
||||
if tagged, ok := named.(reference.Tagged); ok {
|
||||
i.Tag = tagged.Tag()
|
||||
}
|
||||
|
||||
// Add the digest if there was one.
|
||||
if canonical, ok := named.(reference.Canonical); ok {
|
||||
i.Digest = canonical.Digest()
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
13
vendor/github.com/genuinetools/reg/registry/layer.go
generated
vendored
13
vendor/github.com/genuinetools/reg/registry/layer.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"fmt"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
@ -24,7 +25,7 @@ func (r *Registry) DownloadLayer(repository string, digest digest.Digest) (io.Re
|
|||
|
||||
// UploadLayer uploads a specific layer by digest for a repository.
|
||||
func (r *Registry) UploadLayer(repository string, digest reference.Reference, content io.Reader) error {
|
||||
uploadURL, err := r.initiateUpload(repository)
|
||||
uploadURL, token, err := r.initiateUpload(repository)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -39,6 +40,7 @@ func (r *Registry) UploadLayer(repository string, digest reference.Reference, co
|
|||
return err
|
||||
}
|
||||
upload.Header.Set("Content-Type", "application/octet-stream")
|
||||
upload.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
|
||||
_, err = r.Client.Do(upload)
|
||||
return err
|
||||
|
@ -70,20 +72,21 @@ func (r *Registry) HasLayer(repository string, digest digest.Digest) (bool, erro
|
|||
return false, err
|
||||
}
|
||||
|
||||
func (r *Registry) initiateUpload(repository string) (*url.URL, error) {
|
||||
func (r *Registry) initiateUpload(repository string) (*url.URL, string, error) {
|
||||
initiateURL := r.url("/v2/%s/blobs/uploads/", repository)
|
||||
r.Logf("registry.layer.initiate-upload url=%s repository=%s", initiateURL, repository)
|
||||
|
||||
resp, err := r.Client.Post(initiateURL, "application/octet-stream", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
token := resp.Header.Get("Request-Token")
|
||||
defer resp.Body.Close()
|
||||
|
||||
location := resp.Header.Get("Location")
|
||||
locationURL, err := url.Parse(location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, token, err
|
||||
}
|
||||
return locationURL, nil
|
||||
return locationURL, token, nil
|
||||
}
|
||||
|
|
29
vendor/github.com/genuinetools/reg/registry/manifest.go
generated
vendored
29
vendor/github.com/genuinetools/reg/registry/manifest.go
generated
vendored
|
@ -1,6 +1,9 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
|
@ -20,8 +23,7 @@ func (r *Registry) Manifest(repository, ref string) (distribution.Manifest, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Add("Accept", schema2.MediaTypeManifest)
|
||||
req.Header.Add("Accept", manifestlist.MediaTypeManifestList)
|
||||
req.Header.Add("Accept", fmt.Sprintf("%s;q=0.9", schema2.MediaTypeManifest))
|
||||
|
||||
resp, err := r.Client.Do(req)
|
||||
if err != nil {
|
||||
|
@ -84,3 +86,26 @@ func (r *Registry) ManifestV1(repository, ref string) (schema1.SignedManifest, e
|
|||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// PutManifest calls a PUT for the specific manifest for an image.
|
||||
func (r *Registry) PutManifest(repository, ref string, manifest distribution.Manifest) error {
|
||||
url := r.url("/v2/%s/manifests/%s", repository, ref)
|
||||
r.Logf("registry.manifest.put url=%s repository=%s reference=%s", url, repository, ref)
|
||||
|
||||
b, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", schema2.MediaTypeManifest)
|
||||
resp, err := r.Client.Do(req)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
52
vendor/github.com/genuinetools/reg/registry/registry.go
generated
vendored
52
vendor/github.com/genuinetools/reg/registry/registry.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
|
@ -22,6 +23,7 @@ type Registry struct {
|
|||
Password string
|
||||
Client *http.Client
|
||||
Logf LogfCallback
|
||||
Opt Opt
|
||||
}
|
||||
|
||||
var reProtocol = regexp.MustCompile("^https?://")
|
||||
|
@ -37,26 +39,31 @@ func Log(format string, args ...interface{}) {
|
|||
log.Printf(format, args...)
|
||||
}
|
||||
|
||||
// Opt holds the options for a new registry.
|
||||
type Opt struct {
|
||||
Insecure bool
|
||||
Debug bool
|
||||
SkipPing bool
|
||||
Timeout time.Duration
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
// New creates a new Registry struct with the given URL and credentials.
|
||||
func New(auth types.AuthConfig, debug bool) (*Registry, error) {
|
||||
func New(auth types.AuthConfig, opt Opt) (*Registry, error) {
|
||||
transport := http.DefaultTransport
|
||||
|
||||
return newFromTransport(auth, transport, debug)
|
||||
}
|
||||
|
||||
// NewInsecure creates a new Registry struct with the given URL and credentials,
|
||||
// using a http.Transport that will not verify an SSL certificate.
|
||||
func NewInsecure(auth types.AuthConfig, debug bool) (*Registry, error) {
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
if opt.Insecure {
|
||||
transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return newFromTransport(auth, transport, debug)
|
||||
return newFromTransport(auth, transport, opt)
|
||||
}
|
||||
|
||||
func newFromTransport(auth types.AuthConfig, transport http.RoundTripper, debug bool) (*Registry, error) {
|
||||
func newFromTransport(auth types.AuthConfig, transport http.RoundTripper, opt Opt) (*Registry, error) {
|
||||
url := strings.TrimSuffix(auth.ServerAddress, "/")
|
||||
|
||||
if !reProtocol.MatchString(url) {
|
||||
|
@ -77,10 +84,14 @@ func newFromTransport(auth types.AuthConfig, transport http.RoundTripper, debug
|
|||
errorTransport := &ErrorTransport{
|
||||
Transport: basicAuthTransport,
|
||||
}
|
||||
customTransport := &CustomTransport{
|
||||
Transport: errorTransport,
|
||||
Headers: opt.Headers,
|
||||
}
|
||||
|
||||
// set the logging
|
||||
logf := Quiet
|
||||
if debug {
|
||||
if opt.Debug {
|
||||
logf = Log
|
||||
}
|
||||
|
||||
|
@ -88,15 +99,19 @@ func newFromTransport(auth types.AuthConfig, transport http.RoundTripper, debug
|
|||
URL: url,
|
||||
Domain: reProtocol.ReplaceAllString(url, ""),
|
||||
Client: &http.Client{
|
||||
Transport: errorTransport,
|
||||
Timeout: opt.Timeout,
|
||||
Transport: customTransport,
|
||||
},
|
||||
Username: auth.Username,
|
||||
Password: auth.Password,
|
||||
Logf: logf,
|
||||
Opt: opt,
|
||||
}
|
||||
|
||||
if err := registry.Ping(); err != nil {
|
||||
return nil, err
|
||||
if !opt.SkipPing {
|
||||
if err := registry.Ping(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return registry, nil
|
||||
|
@ -115,8 +130,7 @@ func (r *Registry) getJSON(url string, response interface{}, addV2Header bool) (
|
|||
return nil, err
|
||||
}
|
||||
if addV2Header {
|
||||
req.Header.Add("Accept", schema2.MediaTypeManifest)
|
||||
req.Header.Add("Accept", manifestlist.MediaTypeManifestList)
|
||||
req.Header.Add("Accept", fmt.Sprintf("%s,%s;q=0.9", schema2.MediaTypeManifest, manifestlist.MediaTypeManifestList))
|
||||
}
|
||||
resp, err := r.Client.Do(req)
|
||||
if err != nil {
|
||||
|
|
50
vendor/github.com/genuinetools/reg/registry/tokentransport.go
generated
vendored
50
vendor/github.com/genuinetools/reg/registry/tokentransport.go
generated
vendored
|
@ -1,6 +1,8 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -44,7 +46,11 @@ func (t *TokenTransport) authAndRetry(authService *authService, req *http.Reques
|
|||
return authResp, err
|
||||
}
|
||||
|
||||
return t.retry(req, token)
|
||||
response, err := t.retry(req, token)
|
||||
if response != nil {
|
||||
response.Header.Set("request-token", token)
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (t *TokenTransport) auth(authService *authService) (string, *http.Response, error) {
|
||||
|
@ -114,7 +120,8 @@ func isTokenDemand(resp *http.Response) (*authService, error) {
|
|||
return parseAuthHeader(resp.Header)
|
||||
}
|
||||
|
||||
// Token returns the required token for the specific resource url.
|
||||
// Token returns the required token for the specific resource url. If the registry requires basic authentication, this
|
||||
// function returns ErrBasicAuth.
|
||||
func (r *Registry) Token(url string) (string, error) {
|
||||
r.Logf("registry.token url=%s", url)
|
||||
|
||||
|
@ -123,7 +130,19 @@ func (r *Registry) Token(url string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
resp, err := r.Client.Do(req)
|
||||
client := http.DefaultClient
|
||||
if r.Opt.Insecure {
|
||||
client = &http.Client{
|
||||
Timeout: r.Opt.Timeout,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -143,7 +162,7 @@ func (r *Registry) Token(url string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp, err = r.Client.Do(authReq)
|
||||
resp, err = http.DefaultClient.Do(authReq)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -164,3 +183,26 @@ func (r *Registry) Token(url string) (string, error) {
|
|||
|
||||
return authToken.Token, nil
|
||||
}
|
||||
|
||||
// Headers returns the authorization headers for a specific uri.
|
||||
func (r *Registry) Headers(uri string) (map[string]string, error) {
|
||||
// Get the token.
|
||||
token, err := r.Token(uri)
|
||||
if err != nil {
|
||||
if err == ErrBasicAuth {
|
||||
// If we couldn't get a token because the server requires basic auth, just return basic auth headers.
|
||||
return map[string]string{
|
||||
"Authorization": fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(r.Username+":"+r.Password))),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(token) < 1 {
|
||||
r.Logf("got empty token for %s", uri)
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
"Authorization": fmt.Sprintf("Bearer %s", token),
|
||||
}, nil
|
||||
}
|
||||
|
|
38
vendor/github.com/genuinetools/reg/registry/tokentransport_test.go
generated
vendored
Normal file
38
vendor/github.com/genuinetools/reg/registry/tokentransport_test.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
func TestErrBasicAuth(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/" {
|
||||
w.Header().Set("www-authenticate", `Basic realm="Registry Realm",service="Docker registry"`)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
authConfig := types.AuthConfig{
|
||||
Username: "j3ss",
|
||||
Password: "ss3j",
|
||||
ServerAddress: ts.URL,
|
||||
}
|
||||
r, err := New(authConfig, Opt{Insecure: true, Debug: true})
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error creating client, got %v", err)
|
||||
}
|
||||
token, err := r.Token(ts.URL)
|
||||
if err != ErrBasicAuth {
|
||||
t.Fatalf("expected ErrBasicAuth getting token, got %v", err)
|
||||
}
|
||||
if token != "" {
|
||||
t.Fatalf("expected empty token, got %v", err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue