mirror of
https://github.com/containers/podman.git
synced 2025-07-03 01:08:02 +08:00
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
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
github.com/sirupsen/logrus v1.0.0
|
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/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
|
||||||
github.com/ostreedev/ostree-go master
|
github.com/ostreedev/ostree-go master
|
||||||
github.com/containers/storage 1824cf917a6b42d8c41179e807bb20a5fd6c0f0a
|
github.com/containers/storage 1824cf917a6b42d8c41179e807bb20a5fd6c0f0a
|
||||||
|
2
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
2
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
@ -70,7 +70,7 @@ func newImageDestination(ref dirReference, compress bool) (types.ImageDestinatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create version file
|
// create version file
|
||||||
err = ioutil.WriteFile(d.ref.versionPath(), []byte(version), 0755)
|
err = ioutil.WriteFile(d.ref.versionPath(), []byte(version), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error creating version file %q", d.ref.versionPath())
|
return nil, errors.Wrapf(err, "error creating version file %q", d.ref.versionPath())
|
||||||
}
|
}
|
||||||
|
140
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
140
vendor/github.com/containers/image/docker/docker_client.go
generated
vendored
@ -8,7 +8,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -24,8 +26,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dockerHostname = "docker.io"
|
dockerHostname = "docker.io"
|
||||||
dockerRegistry = "registry-1.docker.io"
|
dockerV1Hostname = "index.docker.io"
|
||||||
|
dockerRegistry = "registry-1.docker.io"
|
||||||
|
|
||||||
systemPerHostCertDirPath = "/etc/docker/certs.d"
|
systemPerHostCertDirPath = "/etc/docker/certs.d"
|
||||||
|
|
||||||
@ -66,9 +69,10 @@ type extensionSignatureList struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type bearerToken struct {
|
type bearerToken struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
ExpiresIn int `json:"expires_in"`
|
AccessToken string `json:"access_token"`
|
||||||
IssuedAt time.Time `json:"issued_at"`
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
IssuedAt time.Time `json:"issued_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// dockerClient is configuration for dealing with a single Docker registry.
|
// dockerClient is configuration for dealing with a single Docker registry.
|
||||||
@ -96,6 +100,24 @@ type authScope struct {
|
|||||||
actions string
|
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
|
// this is cloned from docker/go-connections because upstream docker has changed
|
||||||
// it and make deps here fails otherwise.
|
// it and make deps here fails otherwise.
|
||||||
// We'll drop this once we upgrade to docker 1.13.x deps.
|
// 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.
|
// 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/.
|
// 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var token bearerToken
|
|
||||||
if err := json.Unmarshal(tokenBlob, &token); err != nil {
|
return newBearerTokenFromJSONBlob(tokenBlob)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// detectProperties detects various properties of the registry.
|
// detectProperties detects various properties of the registry.
|
||||||
|
8
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
8
vendor/github.com/containers/image/docker/docker_image_dest.go
generated
vendored
@ -131,7 +131,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
|
|||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
if res.StatusCode != http.StatusAccepted {
|
if res.StatusCode != http.StatusAccepted {
|
||||||
logrus.Debugf("Error initiating layer upload, response %#v", *res)
|
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()
|
uploadLocation, err := res.Location()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -167,7 +167,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI
|
|||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
if res.StatusCode != http.StatusCreated {
|
if res.StatusCode != http.StatusCreated {
|
||||||
logrus.Debugf("Error uploading layer, response %#v", *res)
|
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)
|
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
|
return true, getBlobSize(res), nil
|
||||||
case http.StatusUnauthorized:
|
case http.StatusUnauthorized:
|
||||||
logrus.Debugf("... not authorized")
|
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:
|
case http.StatusNotFound:
|
||||||
logrus.Debugf("... not present")
|
logrus.Debugf("... not present")
|
||||||
return false, -1, nil
|
return false, -1, nil
|
||||||
@ -447,7 +447,7 @@ sigExists:
|
|||||||
logrus.Debugf("Error body %s", string(body))
|
logrus.Debugf("Error body %s", string(body))
|
||||||
}
|
}
|
||||||
logrus.Debugf("Error uploading signature, status %d, %#v", res.StatusCode, res)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
vendor/github.com/containers/image/image/oci.go
generated
vendored
10
vendor/github.com/containers/image/image/oci.go
generated
vendored
@ -149,6 +149,16 @@ func (m *manifestOCI1) UpdatedImage(options types.ManifestUpdateOptions) (types.
|
|||||||
|
|
||||||
switch options.ManifestMIMEType {
|
switch options.ManifestMIMEType {
|
||||||
case "": // No conversion, OK
|
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:
|
case manifest.DockerV2Schema2MediaType:
|
||||||
return copy.convertToManifestSchema2()
|
return copy.convertToManifestSchema2()
|
||||||
default:
|
default:
|
||||||
|
10
vendor/github.com/containers/image/ostree/ostree_dest.go
generated
vendored
10
vendor/github.com/containers/image/ostree/ostree_dest.go
generated
vendored
@ -14,6 +14,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -175,7 +176,10 @@ func fixFiles(selinuxHnd *C.struct_selabel_handle, root string, dir string, user
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
relPathC := C.CString(relPath)
|
||||||
defer C.free(unsafe.Pointer(relPathC))
|
defer C.free(unsafe.Pointer(relPathC))
|
||||||
@ -237,7 +241,7 @@ func generateTarSplitMetadata(output *bytes.Buffer, file string) error {
|
|||||||
}
|
}
|
||||||
defer stream.Close()
|
defer stream.Close()
|
||||||
|
|
||||||
gzReader, err := gzip.NewReader(stream)
|
gzReader, err := archive.DecompressStream(stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -383,7 +387,7 @@ func (d *ostreeImageDestination) Commit() error {
|
|||||||
var selinuxHnd *C.struct_selabel_handle
|
var selinuxHnd *C.struct_selabel_handle
|
||||||
|
|
||||||
if os.Getuid() == 0 && selinux.GetEnabled() {
|
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 {
|
if selinuxHnd == nil {
|
||||||
return errors.Wrapf(err, "cannot open the SELinux DB")
|
return errors.Wrapf(err, "cannot open the SELinux DB")
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/containers/image/tarball/tarball_reference.go
generated
vendored
2
vendor/github.com/containers/image/tarball/tarball_reference.go
generated
vendored
@ -89,5 +89,5 @@ func (r *tarballReference) DeleteImage(ctx *types.SystemContext) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *tarballReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, 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`)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user