From bf0ea44cbbfc1e4c575018956280be30947a03ec Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Sat, 28 Mar 2020 20:41:04 -0700 Subject: [PATCH] Only optionally grab repotags in raw inspect out For images with a lot of tags it can take a significant amount of time to list tags. This can often cause timeouts causing the operation to fail or if ignore-missing is set wrongly skip an image. This change will only grab tags during "inspect --raw" and not during non-raw inspect or push. Since some repos are so large they always timeout a new parameter --tags has been added to inspect do disable including tags on raw inspect. Signed-off-by: Darren Shepherd --- docker/createml.go | 2 +- docker/inspect.go | 15 ++++++++------- docker/inspect_v2.go | 19 +++++++++++-------- inspect.go | 6 +++++- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/docker/createml.go b/docker/createml.go index 22fa2fcd..90c533eb 100644 --- a/docker/createml.go +++ b/docker/createml.go @@ -66,7 +66,7 @@ func PutManifestList(a *types.AuthInfo, yamlInput types.YAMLInput, ignoreMissing // for the constituent images: logrus.Info("Retrieving digests of images...") for _, img := range yamlInput.Manifests { - mfstData, repoInfo, err := GetImageData(a, img.Image, insecure) + mfstData, repoInfo, err := GetImageData(a, img.Image, insecure, false) if err != nil { // if ignoreMissing is true, we will skip this error and simply // log a warning that we couldn't find it in the registry diff --git a/docker/inspect.go b/docker/inspect.go index 1ab6d02d..939c97af 100644 --- a/docker/inspect.go +++ b/docker/inspect.go @@ -149,7 +149,7 @@ func checkHTTPRedirect(req *http.Request, via []*http.Request) error { } // GetImageData takes registry authentication information and a name of the image to return information about -func GetImageData(a *types.AuthInfo, name string, insecure bool) ([]types.ImageInspect, *registry.RepositoryInfo, error) { +func GetImageData(a *types.AuthInfo, name string, insecure, includeTags bool) ([]types.ImageInspect, *registry.RepositoryInfo, error) { if err := validateName(name); err != nil { return nil, nil, err } @@ -215,7 +215,7 @@ func GetImageData(a *types.AuthInfo, name string, insecure bool) ([]types.ImageI logrus.Debugf("Trying to fetch image manifest of %s repository from %s %s", repoInfo.Name.Name(), endpoint.URL, endpoint.Version) - fetcher, err := newManifestFetcher(endpoint, repoInfo, authConfig, registryService) + fetcher, err := newManifestFetcher(endpoint, repoInfo, authConfig, registryService, includeTags) if err != nil { lastErr = err continue @@ -263,14 +263,15 @@ func GetImageData(a *types.AuthInfo, name string, insecure bool) ([]types.ImageI return nil, nil, lastErr } -func newManifestFetcher(endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, authConfig engineTypes.AuthConfig, registryService registry.Service) (manifestFetcher, error) { +func newManifestFetcher(endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, authConfig engineTypes.AuthConfig, registryService registry.Service, includeTags bool) (manifestFetcher, error) { switch endpoint.Version { case registry.APIVersion2: return &v2ManifestFetcher{ - endpoint: endpoint, - authConfig: authConfig, - service: registryService, - repoInfo: repoInfo, + endpoint: endpoint, + authConfig: authConfig, + service: registryService, + repoInfo: repoInfo, + includeTags: includeTags, }, nil case registry.APIVersion1: return &v1ManifestFetcher{ diff --git a/docker/inspect_v2.go b/docker/inspect_v2.go index d67ec4d1..fde3ca19 100644 --- a/docker/inspect_v2.go +++ b/docker/inspect_v2.go @@ -29,6 +29,7 @@ type v2ManifestFetcher struct { repoInfo *registry.RepositoryInfo repo distribution.Repository confirmedV2 bool + includeTags bool authConfig engineTypes.AuthConfig service registry.Service } @@ -108,14 +109,16 @@ func (mf *v2ManifestFetcher) fetchWithRepository(ctx context.Context, ref refere // the other side speaks the v2 protocol. mf.confirmedV2 = true - tagList, err = mf.repo.Tags(ctx).All(ctx) - if err != nil { - // If this repository doesn't exist on V2, we should - // permit a fallback to V1. - if !strings.Contains(err.Error(), "unauthorized") { - // only error out if the the "list all tags" endpoint isn't blocked by the registry - // some registries may have a reason to not allow complete tag list queries - return nil, allowV1Fallback(err) + if mf.includeTags { + tagList, err = mf.repo.Tags(ctx).All(ctx) + if err != nil { + // If this repository doesn't exist on V2, we should + // permit a fallback to V1. + if !strings.Contains(err.Error(), "unauthorized") { + // only error out if the the "list all tags" endpoint isn't blocked by the registry + // some registries may have a reason to not allow complete tag list queries + return nil, allowV1Fallback(err) + } } } diff --git a/inspect.go b/inspect.go index c215bcb8..0015003c 100644 --- a/inspect.go +++ b/inspect.go @@ -18,12 +18,16 @@ var inspectCmd = cli.Command{ Name: "raw", Usage: "raw JSON output", }, + cli.BoolTFlag{ + Name: "tags", + Usage: "include RepoTags in raw response", + }, }, Action: func(c *cli.Context) { name := c.Args().First() a := getAuthInfo(c) - imgInspect, _, err := docker.GetImageData(a, name, c.GlobalBool("insecure")) + imgInspect, _, err := docker.GetImageData(a, name, c.GlobalBool("insecure"), c.Bool("raw") && c.Bool("tags")) if err != nil { logrus.Fatal(err) }