Skip to content

Commit

Permalink
pass context.Context to signature retrieval http calls
Browse files Browse the repository at this point in the history
  • Loading branch information
mfojtik committed Jul 31, 2017
1 parent 6ee6294 commit 61bb862
Show file tree
Hide file tree
Showing 20 changed files with 94 additions and 53 deletions.
3 changes: 2 additions & 1 deletion copy/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package copy
import (
"bytes"
"compress/gzip"
"context"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -171,7 +172,7 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
sigs = [][]byte{}
} else {
writeReport("Getting image source signatures\n")
s, err := src.Signatures()
s, err := src.Signatures(context.TODO())
if err != nil {
return errors.Wrap(err, "Error reading signatures")
}
Expand Down
3 changes: 2 additions & 1 deletion copy/manifest_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package copy

import (
"context"
"errors"
"fmt"
"testing"
Expand Down Expand Up @@ -43,7 +44,7 @@ func (f fakeImageSource) Manifest() ([]byte, string, error) {
}
return nil, string(f), nil
}
func (f fakeImageSource) Signatures() ([][]byte, error) {
func (f fakeImageSource) Signatures(context.Context) ([][]byte, error) {
panic("Unexpected call to a mock function")
}
func (f fakeImageSource) ConfigInfo() types.BlobInfo {
Expand Down
3 changes: 2 additions & 1 deletion directory/directory_src.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package directory

import (
"context"
"io"
"io/ioutil"
"os"
Expand Down Expand Up @@ -59,7 +60,7 @@ func (s *dirImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64, err
return r, fi.Size(), nil
}

func (s *dirImageSource) GetSignatures() ([][]byte, error) {
func (s *dirImageSource) GetSignatures(ctx context.Context) ([][]byte, error) {
signatures := [][]byte{}
for i := 0; ; i++ {
signature, err := ioutil.ReadFile(s.ref.signaturePath(i))
Expand Down
3 changes: 2 additions & 1 deletion directory/directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package directory

import (
"bytes"
"context"
"io/ioutil"
"os"
"testing"
Expand Down Expand Up @@ -145,7 +146,7 @@ func TestGetPutSignatures(t *testing.T) {
src, err := ref.NewImageSource(nil, nil)
require.NoError(t, err)
defer src.Close()
sigs, err := src.GetSignatures()
sigs, err := src.GetSignatures(context.Background())
assert.NoError(t, err)
assert.Equal(t, signatures, sigs)
}
Expand Down
26 changes: 17 additions & 9 deletions docker/docker_client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package docker

import (
"context"
"crypto/tls"
"encoding/base64"
"encoding/json"
Expand Down Expand Up @@ -254,24 +255,29 @@ func newDockerClient(ctx *types.SystemContext, ref dockerReference, write bool,

// makeRequest creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
// The host name and schema is taken from the client or autodetected, and the path is relative to it, i.e. the path usually starts with /v2/.
func (c *dockerClient) makeRequest(method, path string, headers map[string][]string, stream io.Reader) (*http.Response, error) {
if err := c.detectProperties(); err != nil {
func (c *dockerClient) makeRequest(ctx context.Context, method, path string, headers map[string][]string, stream io.Reader) (*http.Response, error) {
if err := c.detectProperties(ctx); err != nil {
return nil, err
}

url := fmt.Sprintf("%s://%s%s", c.scheme, c.registry, path)
return c.makeRequestToResolvedURL(method, url, headers, stream, -1, true)
return c.makeRequestToResolvedURL(ctx, method, url, headers, stream, -1, true)
}

// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
// streamLen, if not -1, specifies the length of the data expected on stream.
// makeRequest should generally be preferred.
// TODO(runcom): too many arguments here, use a struct
func (c *dockerClient) makeRequestToResolvedURL(method, url string, headers map[string][]string, stream io.Reader, streamLen int64, sendAuth bool) (*http.Response, error) {
func (c *dockerClient) makeRequestToResolvedURL(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, sendAuth bool) (*http.Response, error) {
req, err := http.NewRequest(method, url, stream)
if err != nil {
return nil, err
}
if ctx != nil {
req = req.WithContext(ctx)
} else {
req = req.WithContext(context.Background())
}
if streamLen != -1 { // Do not blindly overwrite if streamLen == -1, http.NewRequest above can figure out the length of bytes.Reader and similar objects without us having to compute it.
req.ContentLength = streamLen
}
Expand Down Expand Up @@ -447,14 +453,15 @@ func getAuth(ctx *types.SystemContext, registry string) (string, string, error)

// detectProperties detects various properties of the registry.
// See the dockerClient documentation for members which are affected by this.
func (c *dockerClient) detectProperties() error {
func (c *dockerClient) detectProperties(ctx context.Context) error {
if c.scheme != "" {
return nil
}

ping := func(scheme string) error {
url := fmt.Sprintf(resolvedPingV2URL, scheme, c.registry)
resp, err := c.makeRequestToResolvedURL("GET", url, nil, nil, -1, true)
// FIXME: Pass the context.Context
resp, err := c.makeRequestToResolvedURL(ctx, "GET", url, nil, nil, -1, true)
logrus.Debugf("Ping %s err %#v", url, err)
if err != nil {
return err
Expand All @@ -481,7 +488,8 @@ func (c *dockerClient) detectProperties() error {
// best effort to understand if we're talking to a V1 registry
pingV1 := func(scheme string) bool {
url := fmt.Sprintf(resolvedPingV1URL, scheme, c.registry)
resp, err := c.makeRequestToResolvedURL("GET", url, nil, nil, -1, true)
// FIXME: Pass the context.Context
resp, err := c.makeRequestToResolvedURL(ctx, "GET", url, nil, nil, -1, true)
logrus.Debugf("Ping %s err %#v", url, err)
if err != nil {
return false
Expand All @@ -506,9 +514,9 @@ func (c *dockerClient) detectProperties() error {

// getExtensionsSignatures returns signatures from the X-Registry-Supports-Signatures API extension,
// using the original data structures.
func (c *dockerClient) getExtensionsSignatures(ref dockerReference, manifestDigest digest.Digest) (*extensionSignatureList, error) {
func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerReference, manifestDigest digest.Digest) (*extensionSignatureList, error) {
path := fmt.Sprintf(extensionsSignaturePath, reference.Path(ref.ref), manifestDigest)
res, err := c.makeRequest("GET", path, nil, nil)
res, err := c.makeRequest(ctx, "GET", path, nil, nil)
if err != nil {
return nil, err
}
Expand Down
4 changes: 3 additions & 1 deletion docker/docker_image.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package docker

import (
"context"
"encoding/json"
"fmt"
"net/http"
Expand Down Expand Up @@ -41,7 +42,8 @@ func (i *Image) SourceRefFullName() string {
// GetRepositoryTags list all tags available in the repository. Note that this has no connection with the tag(s) used for this specific image, if any.
func (i *Image) GetRepositoryTags() ([]string, error) {
path := fmt.Sprintf(tagsPath, reference.Path(i.src.ref.ref))
res, err := i.src.c.makeRequest("GET", path, nil, nil)
// FIXME: Pass the context.Context
res, err := i.src.c.makeRequest(context.TODO(), "GET", path, nil, nil)
if err != nil {
return nil, err
}
Expand Down
19 changes: 10 additions & 9 deletions docker/docker_image_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package docker

import (
"bytes"
"context"
"crypto/rand"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -75,7 +76,7 @@ func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil.
func (d *dockerImageDestination) SupportsSignatures() error {
if err := d.c.detectProperties(); err != nil {
if err := d.c.detectProperties(context.TODO()); err != nil {
return err
}
switch {
Expand Down Expand Up @@ -132,7 +133,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
// FIXME? Chunked upload, progress reporting, etc.
uploadPath := fmt.Sprintf(blobUploadPath, reference.Path(d.ref.ref))
logrus.Debugf("Uploading %s", uploadPath)
res, err := d.c.makeRequest("POST", uploadPath, nil, nil)
res, err := d.c.makeRequest(context.Background(), "POST", uploadPath, nil, nil)
if err != nil {
return types.BlobInfo{}, err
}
Expand All @@ -149,7 +150,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
digester := digest.Canonical.Digester()
sizeCounter := &sizeCounter{}
tee := io.TeeReader(stream, io.MultiWriter(digester.Hash(), sizeCounter))
res, err = d.c.makeRequestToResolvedURL("PATCH", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, tee, inputInfo.Size, true)
res, err = d.c.makeRequestToResolvedURL(context.Background(), "PATCH", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, tee, inputInfo.Size, true)
if err != nil {
logrus.Debugf("Error uploading layer chunked, response %#v", res)
return types.BlobInfo{}, err
Expand All @@ -168,7 +169,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
// TODO: check inputInfo.Digest == computedDigest https://github.com/containers/image/pull/70#discussion_r77646717
locationQuery.Set("digest", computedDigest.String())
uploadLocation.RawQuery = locationQuery.Encode()
res, err = d.c.makeRequestToResolvedURL("PUT", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, nil, -1, true)
res, err = d.c.makeRequestToResolvedURL(context.Background(), "PUT", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, nil, -1, true)
if err != nil {
return types.BlobInfo{}, err
}
Expand All @@ -193,7 +194,7 @@ func (d *dockerImageDestination) HasBlob(info types.BlobInfo) (bool, int64, erro
checkPath := fmt.Sprintf(blobsPath, reference.Path(d.ref.ref), info.Digest.String())

logrus.Debugf("Checking %s", checkPath)
res, err := d.c.makeRequest("HEAD", checkPath, nil, nil)
res, err := d.c.makeRequest(context.TODO(), "HEAD", checkPath, nil, nil)
if err != nil {
return false, -1, err
}
Expand Down Expand Up @@ -239,7 +240,7 @@ func (d *dockerImageDestination) PutManifest(m []byte) error {
if mimeType != "" {
headers["Content-Type"] = []string{mimeType}
}
res, err := d.c.makeRequest("PUT", path, headers, bytes.NewReader(m))
res, err := d.c.makeRequest(context.Background(), "PUT", path, headers, bytes.NewReader(m))
if err != nil {
return err
}
Expand Down Expand Up @@ -275,7 +276,7 @@ func (d *dockerImageDestination) PutSignatures(signatures [][]byte) error {
if len(signatures) == 0 {
return nil
}
if err := d.c.detectProperties(); err != nil {
if err := d.c.detectProperties(context.TODO()); err != nil {
return err
}
switch {
Expand Down Expand Up @@ -396,7 +397,7 @@ func (d *dockerImageDestination) putSignaturesToAPIExtension(signatures [][]byte
// always adds signatures. Eventually we should also allow removing signatures,
// but the X-Registry-Supports-Signatures API extension does not support that yet.

existingSignatures, err := d.c.getExtensionsSignatures(d.ref, d.manifestDigest)
existingSignatures, err := d.c.getExtensionsSignatures(nil, d.ref, d.manifestDigest)
if err != nil {
return err
}
Expand Down Expand Up @@ -438,7 +439,7 @@ sigExists:
}

path := fmt.Sprintf(extensionsSignaturePath, reference.Path(d.ref.ref), d.manifestDigest.String())
res, err := d.c.makeRequest("PUT", path, nil, bytes.NewReader(body))
res, err := d.c.makeRequest(context.Background(), "PUT", path, nil, bytes.NewReader(body))
if err != nil {
return err
}
Expand Down
38 changes: 23 additions & 15 deletions docker/docker_image_src.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package docker

import (
"context"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -96,7 +97,7 @@ func (s *dockerImageSource) fetchManifest(tagOrDigest string) ([]byte, string, e
path := fmt.Sprintf(manifestPath, reference.Path(s.ref.ref), tagOrDigest)
headers := make(map[string][]string)
headers["Accept"] = s.requestedManifestMIMETypes
res, err := s.c.makeRequest("GET", path, headers, nil)
res, err := s.c.makeRequest(context.Background(), "GET", path, headers, nil)
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -150,7 +151,7 @@ func (s *dockerImageSource) getExternalBlob(urls []string) (io.ReadCloser, int64
err error
)
for _, url := range urls {
resp, err = s.c.makeRequestToResolvedURL("GET", url, nil, nil, -1, false)
resp, err = s.c.makeRequestToResolvedURL(context.Background(), "GET", url, nil, nil, -1, false)
if err == nil {
if resp.StatusCode != http.StatusOK {
err = errors.Errorf("error fetching external blob from %q: %d", url, resp.StatusCode)
Expand Down Expand Up @@ -181,7 +182,7 @@ func (s *dockerImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64,

path := fmt.Sprintf(blobsPath, reference.Path(s.ref.ref), info.Digest.String())
logrus.Debugf("Downloading %s", path)
res, err := s.c.makeRequest("GET", path, nil, nil)
res, err := s.c.makeRequest(context.Background(), "GET", path, nil, nil)
if err != nil {
return nil, 0, err
}
Expand All @@ -192,23 +193,23 @@ func (s *dockerImageSource) GetBlob(info types.BlobInfo) (io.ReadCloser, int64,
return res.Body, getBlobSize(res), nil
}

func (s *dockerImageSource) GetSignatures() ([][]byte, error) {
if err := s.c.detectProperties(); err != nil {
func (s *dockerImageSource) GetSignatures(ctx context.Context) ([][]byte, error) {
if err := s.c.detectProperties(ctx); err != nil {
return nil, err
}
switch {
case s.c.signatureBase != nil:
return s.getSignaturesFromLookaside()
return s.getSignaturesFromLookaside(ctx)
case s.c.supportsSignatures:
return s.getSignaturesFromAPIExtension()
return s.getSignaturesFromAPIExtension(ctx)
default:
return [][]byte{}, nil
}
}

// getSignaturesFromLookaside implements GetSignatures() from the lookaside location configured in s.c.signatureBase,
// which is not nil.
func (s *dockerImageSource) getSignaturesFromLookaside() ([][]byte, error) {
func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context) ([][]byte, error) {
if err := s.ensureManifestIsLoaded(); err != nil {
return nil, err
}
Expand All @@ -224,7 +225,7 @@ func (s *dockerImageSource) getSignaturesFromLookaside() ([][]byte, error) {
if url == nil {
return nil, errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
}
signature, missing, err := s.getOneSignature(url)
signature, missing, err := s.getOneSignature(ctx, url)
if err != nil {
return nil, err
}
Expand All @@ -239,7 +240,7 @@ func (s *dockerImageSource) getSignaturesFromLookaside() ([][]byte, error) {
// getOneSignature downloads one signature from url.
// If it successfully determines that the signature does not exist, returns with missing set to true and error set to nil.
// NOTE: Keep this in sync with docs/signature-protocols.md!
func (s *dockerImageSource) getOneSignature(url *url.URL) (signature []byte, missing bool, err error) {
func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (signature []byte, missing bool, err error) {
switch url.Scheme {
case "file":
logrus.Debugf("Reading %s", url.Path)
Expand All @@ -254,7 +255,14 @@ func (s *dockerImageSource) getOneSignature(url *url.URL) (signature []byte, mis

case "http", "https":
logrus.Debugf("GET %s", url)
res, err := s.c.client.Get(url.String())
req, err := http.NewRequest("GET", url.String(), nil)
if err != nil {
return nil, false, err
}
if ctx != nil {
req = req.WithContext(ctx)
}
res, err := s.c.client.Do(req)
if err != nil {
return nil, false, err
}
Expand All @@ -276,7 +284,7 @@ func (s *dockerImageSource) getOneSignature(url *url.URL) (signature []byte, mis
}

// getSignaturesFromAPIExtension implements GetSignatures() using the X-Registry-Supports-Signatures API extension.
func (s *dockerImageSource) getSignaturesFromAPIExtension() ([][]byte, error) {
func (s *dockerImageSource) getSignaturesFromAPIExtension(ctx context.Context) ([][]byte, error) {
if err := s.ensureManifestIsLoaded(); err != nil {
return nil, err
}
Expand All @@ -285,7 +293,7 @@ func (s *dockerImageSource) getSignaturesFromAPIExtension() ([][]byte, error) {
return nil, err
}

parsedBody, err := s.c.getExtensionsSignatures(s.ref, manifestDigest)
parsedBody, err := s.c.getExtensionsSignatures(ctx, s.ref, manifestDigest)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -316,7 +324,7 @@ func deleteImage(ctx *types.SystemContext, ref dockerReference) error {
return err
}
getPath := fmt.Sprintf(manifestPath, reference.Path(ref.ref), refTail)
get, err := c.makeRequest("GET", getPath, headers, nil)
get, err := c.makeRequest(context.Background(), "GET", getPath, headers, nil)
if err != nil {
return err
}
Expand All @@ -338,7 +346,7 @@ func deleteImage(ctx *types.SystemContext, ref dockerReference) error {

// When retrieving the digest from a registry >= 2.3 use the following header:
// "Accept": "application/vnd.docker.distribution.manifest.v2+json"
delete, err := c.makeRequest("DELETE", deletePath, headers, nil)
delete, err := c.makeRequest(context.Background(), "DELETE", deletePath, headers, nil)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 61bb862

Please sign in to comment.