summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorumohnani8 <umohnani@redhat.com>2018-02-05 12:18:18 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-02-06 18:09:31 +0000
commit1a48a7a7c0dafe98ed4c8461adabc6b8ece1a8c3 (patch)
tree693666bf636e1eda906c0e6104f7ddbdb103ded0
parent31c56e2b9ca029b7dbab15d19ad38008e2d3776c (diff)
downloadpodman-1a48a7a7c0dafe98ed4c8461adabc6b8ece1a8c3.tar.gz
podman-1a48a7a7c0dafe98ed4c8461adabc6b8ece1a8c3.tar.bz2
podman-1a48a7a7c0dafe98ed4c8461adabc6b8ece1a8c3.zip
Vendor in latest containers/image
Latest containers/image has support for searching registries. Signed-off-by: umohnani8 <umohnani@redhat.com> Closes: #241 Approved by: rhatdan
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/containers/image/directory/directory_dest.go2
-rw-r--r--vendor/github.com/containers/image/docker/docker_client.go140
-rw-r--r--vendor/github.com/containers/image/docker/docker_image_dest.go8
-rw-r--r--vendor/github.com/containers/image/image/oci.go10
-rw-r--r--vendor/github.com/containers/image/ostree/ostree_dest.go10
-rw-r--r--vendor/github.com/containers/image/tarball/tarball_reference.go2
7 files changed, 147 insertions, 27 deletions
diff --git a/vendor.conf b/vendor.conf
index 4ce659199..4e7bff400 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -1,6 +1,6 @@
#
github.com/sirupsen/logrus v1.0.0
-github.com/containers/image 9b4510f6d1627c8e53c3303a8fe48ca7842c2ace
+github.com/containers/image 2524e50daed223ad84b827238ed409bbf44296c5
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
github.com/ostreedev/ostree-go master
github.com/containers/storage 1824cf917a6b42d8c41179e807bb20a5fd6c0f0a
diff --git a/vendor/github.com/containers/image/directory/directory_dest.go b/vendor/github.com/containers/image/directory/directory_dest.go
index 47d59d9fe..5f7443fa0 100644
--- a/vendor/github.com/containers/image/directory/directory_dest.go
+++ b/vendor/github.com/containers/image/directory/directory_dest.go
@@ -70,7 +70,7 @@ func newImageDestination(ref dirReference, compress bool) (types.ImageDestinatio
}
}
// create version file
- err = ioutil.WriteFile(d.ref.versionPath(), []byte(version), 0755)
+ err = ioutil.WriteFile(d.ref.versionPath(), []byte(version), 0644)
if err != nil {
return nil, errors.Wrapf(err, "error creating version file %q", d.ref.versionPath())
}
diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go
index 217e9dcbf..b1256b9cb 100644
--- a/vendor/github.com/containers/image/docker/docker_client.go
+++ b/vendor/github.com/containers/image/docker/docker_client.go
@@ -8,7 +8,9 @@ import (
"io"
"io/ioutil"
"net/http"
+ "net/url"
"path/filepath"
+ "strconv"
"strings"
"time"
@@ -24,8 +26,9 @@ import (
)
const (
- dockerHostname = "docker.io"
- dockerRegistry = "registry-1.docker.io"
+ dockerHostname = "docker.io"
+ dockerV1Hostname = "index.docker.io"
+ dockerRegistry = "registry-1.docker.io"
systemPerHostCertDirPath = "/etc/docker/certs.d"
@@ -66,9 +69,10 @@ type extensionSignatureList struct {
}
type bearerToken struct {
- Token string `json:"token"`
- ExpiresIn int `json:"expires_in"`
- IssuedAt time.Time `json:"issued_at"`
+ Token string `json:"token"`
+ AccessToken string `json:"access_token"`
+ ExpiresIn int `json:"expires_in"`
+ IssuedAt time.Time `json:"issued_at"`
}
// dockerClient is configuration for dealing with a single Docker registry.
@@ -96,6 +100,24 @@ type authScope struct {
actions string
}
+func newBearerTokenFromJSONBlob(blob []byte) (*bearerToken, error) {
+ token := new(bearerToken)
+ if err := json.Unmarshal(blob, &token); err != nil {
+ return nil, err
+ }
+ if token.Token == "" {
+ token.Token = token.AccessToken
+ }
+ if token.ExpiresIn < minimumTokenLifetimeSeconds {
+ token.ExpiresIn = minimumTokenLifetimeSeconds
+ logrus.Debugf("Increasing token expiration to: %d seconds", token.ExpiresIn)
+ }
+ if token.IssuedAt.IsZero() {
+ token.IssuedAt = time.Now().UTC()
+ }
+ return token, nil
+}
+
// this is cloned from docker/go-connections because upstream docker has changed
// it and make deps here fails otherwise.
// We'll drop this once we upgrade to docker 1.13.x deps.
@@ -202,6 +224,100 @@ func CheckAuth(ctx context.Context, sCtx *types.SystemContext, username, passwor
}
}
+// SearchResult holds the information of each matching image
+// It matches the output returned by the v1 endpoint
+type SearchResult struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ // StarCount states the number of stars the image has
+ StarCount int `json:"star_count"`
+ IsTrusted bool `json:"is_trusted"`
+ // IsAutomated states whether the image is an automated build
+ IsAutomated bool `json:"is_automated"`
+ // IsOfficial states whether the image is an official build
+ IsOfficial bool `json:"is_official"`
+}
+
+// SearchRegistry queries a registry for images that contain "image" in their name
+// The limit is the max number of results desired
+// Note: The limit value doesn't work with all registries
+// for example registry.access.redhat.com returns all the results without limiting it to the limit value
+func SearchRegistry(ctx context.Context, sCtx *types.SystemContext, registry, image string, limit int) ([]SearchResult, error) {
+ type V2Results struct {
+ // Repositories holds the results returned by the /v2/_catalog endpoint
+ Repositories []string `json:"repositories"`
+ }
+ type V1Results struct {
+ // Results holds the results returned by the /v1/search endpoint
+ Results []SearchResult `json:"results"`
+ }
+ v2Res := &V2Results{}
+ v1Res := &V1Results{}
+
+ // The /v2/_catalog endpoint has been disabled for docker.io therefore the call made to that endpoint will fail
+ // So using the v1 hostname for docker.io for simplicity of implementation and the fact that it returns search results
+ if registry == dockerHostname {
+ registry = dockerV1Hostname
+ }
+
+ client, err := newDockerClientWithDetails(sCtx, registry, "", "", "", nil, "")
+ if err != nil {
+ return nil, errors.Wrapf(err, "error creating new docker client")
+ }
+
+ logrus.Debugf("trying to talk to v2 search endpoint\n")
+ resp, err := client.makeRequest(ctx, "GET", "/v2/_catalog", nil, nil)
+ if err != nil {
+ logrus.Debugf("error getting search results from v2 endpoint %q: %v", registry, err)
+ } else {
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ logrus.Debugf("error getting search results from v2 endpoint %q, status code %q", registry, resp.StatusCode)
+ } else {
+ if err := json.NewDecoder(resp.Body).Decode(v2Res); err != nil {
+ return nil, err
+ }
+ searchRes := []SearchResult{}
+ for _, repo := range v2Res.Repositories {
+ if strings.Contains(repo, image) {
+ res := SearchResult{
+ Name: repo,
+ }
+ searchRes = append(searchRes, res)
+ }
+ }
+ return searchRes, nil
+ }
+ }
+
+ // set up the query values for the v1 endpoint
+ u := url.URL{
+ Path: "/v1/search",
+ }
+ q := u.Query()
+ q.Set("q", image)
+ q.Set("n", strconv.Itoa(limit))
+ u.RawQuery = q.Encode()
+
+ logrus.Debugf("trying to talk to v1 search endpoint\n")
+ resp, err = client.makeRequest(ctx, "GET", u.String(), nil, nil)
+ if err != nil {
+ logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, err)
+ } else {
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ logrus.Debugf("error getting search results from v1 endpoint %q, status code %q", registry, resp.StatusCode)
+ } else {
+ if err := json.NewDecoder(resp.Body).Decode(v1Res); err != nil {
+ return nil, err
+ }
+ return v1Res.Results, nil
+ }
+ }
+
+ return nil, errors.Wrapf(err, "couldn't search registry %q", registry)
+}
+
// 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(ctx context.Context, method, path string, headers map[string][]string, stream io.Reader) (*http.Response, error) {
@@ -332,18 +448,8 @@ func (c *dockerClient) getBearerToken(ctx context.Context, realm, service, scope
if err != nil {
return nil, err
}
- var token bearerToken
- if err := json.Unmarshal(tokenBlob, &token); err != nil {
- return nil, err
- }
- if token.ExpiresIn < minimumTokenLifetimeSeconds {
- token.ExpiresIn = minimumTokenLifetimeSeconds
- logrus.Debugf("Increasing token expiration to: %d seconds", token.ExpiresIn)
- }
- if token.IssuedAt.IsZero() {
- token.IssuedAt = time.Now().UTC()
- }
- return &token, nil
+
+ return newBearerTokenFromJSONBlob(tokenBlob)
}
// detectProperties detects various properties of the registry.
diff --git a/vendor/github.com/containers/image/docker/docker_image_dest.go b/vendor/github.com/containers/image/docker/docker_image_dest.go
index 79c386225..2f3b6c2c3 100644
--- a/vendor/github.com/containers/image/docker/docker_image_dest.go
+++ b/vendor/github.com/containers/image/docker/docker_image_dest.go
@@ -131,7 +131,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
defer res.Body.Close()
if res.StatusCode != http.StatusAccepted {
logrus.Debugf("Error initiating layer upload, response %#v", *res)
- return types.BlobInfo{}, errors.Errorf("Error initiating layer upload to %s, status %d", uploadPath, res.StatusCode)
+ return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error initiating layer upload to %s", uploadPath)
}
uploadLocation, err := res.Location()
if err != nil {
@@ -167,7 +167,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
defer res.Body.Close()
if res.StatusCode != http.StatusCreated {
logrus.Debugf("Error uploading layer, response %#v", *res)
- return types.BlobInfo{}, errors.Errorf("Error uploading layer to %s, status %d", uploadLocation, res.StatusCode)
+ return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error uploading layer to %s", uploadLocation)
}
logrus.Debugf("Upload of layer %s complete", computedDigest)
@@ -196,7 +196,7 @@ func (d *dockerImageDestination) HasBlob(info types.BlobInfo) (bool, int64, erro
return true, getBlobSize(res), nil
case http.StatusUnauthorized:
logrus.Debugf("... not authorized")
- return false, -1, errors.Errorf("not authorized to read from destination repository %s", reference.Path(d.ref.ref))
+ return false, -1, client.HandleErrorResponse(res)
case http.StatusNotFound:
logrus.Debugf("... not present")
return false, -1, nil
@@ -447,7 +447,7 @@ sigExists:
logrus.Debugf("Error body %s", string(body))
}
logrus.Debugf("Error uploading signature, status %d, %#v", res.StatusCode, res)
- return errors.Errorf("Error uploading signature to %s, status %d", path, res.StatusCode)
+ return errors.Wrapf(client.HandleErrorResponse(res), "Error uploading signature to %s", path)
}
}
diff --git a/vendor/github.com/containers/image/image/oci.go b/vendor/github.com/containers/image/image/oci.go
index 3c03e49bb..e7780c5a6 100644
--- a/vendor/github.com/containers/image/image/oci.go
+++ b/vendor/github.com/containers/image/image/oci.go
@@ -149,6 +149,16 @@ func (m *manifestOCI1) UpdatedImage(options types.ManifestUpdateOptions) (types.
switch options.ManifestMIMEType {
case "": // No conversion, OK
+ case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType:
+ // We can't directly convert to V1, but we can transitively convert via a V2 image
+ m2, err := copy.convertToManifestSchema2()
+ if err != nil {
+ return nil, err
+ }
+ return m2.UpdatedImage(types.ManifestUpdateOptions{
+ ManifestMIMEType: options.ManifestMIMEType,
+ InformationOnly: options.InformationOnly,
+ })
case manifest.DockerV2Schema2MediaType:
return copy.convertToManifestSchema2()
default:
diff --git a/vendor/github.com/containers/image/ostree/ostree_dest.go b/vendor/github.com/containers/image/ostree/ostree_dest.go
index 8154c9851..d5f0ff80c 100644
--- a/vendor/github.com/containers/image/ostree/ostree_dest.go
+++ b/vendor/github.com/containers/image/ostree/ostree_dest.go
@@ -14,6 +14,7 @@ import (
"os/exec"
"path/filepath"
"strconv"
+ "strings"
"syscall"
"time"
"unsafe"
@@ -175,7 +176,10 @@ func fixFiles(selinuxHnd *C.struct_selabel_handle, root string, dir string, user
if err != nil {
return err
}
- relPath = fmt.Sprintf("/%s", relPath)
+ // Handle /exports/hostfs as a special case. Files under this directory are copied to the host,
+ // thus we benefit from maintaining the same SELinux label they would have on the host as we could
+ // use hard links instead of copying the files.
+ relPath = fmt.Sprintf("/%s", strings.TrimPrefix(relPath, "exports/hostfs/"))
relPathC := C.CString(relPath)
defer C.free(unsafe.Pointer(relPathC))
@@ -237,7 +241,7 @@ func generateTarSplitMetadata(output *bytes.Buffer, file string) error {
}
defer stream.Close()
- gzReader, err := gzip.NewReader(stream)
+ gzReader, err := archive.DecompressStream(stream)
if err != nil {
return err
}
@@ -383,7 +387,7 @@ func (d *ostreeImageDestination) Commit() error {
var selinuxHnd *C.struct_selabel_handle
if os.Getuid() == 0 && selinux.GetEnabled() {
- selinuxHnd, err := C.selabel_open(C.SELABEL_CTX_FILE, nil, 0)
+ selinuxHnd, err = C.selabel_open(C.SELABEL_CTX_FILE, nil, 0)
if selinuxHnd == nil {
return errors.Wrapf(err, "cannot open the SELinux DB")
}
diff --git a/vendor/github.com/containers/image/tarball/tarball_reference.go b/vendor/github.com/containers/image/tarball/tarball_reference.go
index 4ccfb4063..a0819ac58 100644
--- a/vendor/github.com/containers/image/tarball/tarball_reference.go
+++ b/vendor/github.com/containers/image/tarball/tarball_reference.go
@@ -89,5 +89,5 @@ func (r *tarballReference) DeleteImage(ctx *types.SystemContext) error {
}
func (r *tarballReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
- return nil, fmt.Errorf("destination not implemented yet")
+ return nil, fmt.Errorf(`"tarball:" locations can only be read from, not written to`)
}