Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix: harbor regular NOT_FOUND error treated as 'broken image' interna…
…l registry error

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
  • Loading branch information
distorhead committed May 15, 2023
1 parent a7eb34b commit bc4ef3d
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 36 deletions.
24 changes: 15 additions & 9 deletions pkg/docker_registry/api.go
Expand Up @@ -88,27 +88,33 @@ func (api *api) IsRepoImageExists(ctx context.Context, reference string) (bool,
}
}

func (api *api) TryGetRepoImage(ctx context.Context, reference string) (*image.Info, error) {
func (api *api) tryGetRepoImage(ctx context.Context, reference, implementation string) (*image.Info, error) {
if imgInfo, err := api.GetRepoImage(ctx, reference); err != nil {
if IsStatusNotFoundErr(err) || IsQuayTagExpiredErr(err) {
// TODO: 1. auto reject images with manifest-unknown or blob-unknown errors
// TODO: 2. why TryGetRepoImage for rejected image records gives manifest-unknown errors?
// TODO: 3. make sure werf never ever creates rejected image records for name-unknown errors.
// TODO: 4. werf-cleanup should remove broken images

if implementation != "" {
if IsQuayTagExpiredErr(err) && implementation != QuayImplementationName {
logboek.Context(ctx).Error().LogF("WARNING: Detected error specific for quay container registry implementation!\n")
logboek.Context(ctx).Error().LogF("WARNING: Use --repo-container-registry=quay option (or WERF_CONTAINER_REGISTRY env var)\n")
logboek.Context(ctx).Error().LogF("WARNING: to instruct werf to use quay driver.\n")
}
}
if IsImageNotFoundError(err) || IsBrokenImageError(err) {
// TODO: 1. make sure werf never ever creates rejected image records for name-unknown errors.
// TODO: 2. werf-cleanup should remove broken images
if os.Getenv("WERF_DOCKER_REGISTRY_DEBUG") == "1" {
logboek.Context(ctx).Error().LogF("WARNING: Got an error when inspecting repo image %q: %s\n", reference, err)
}

return nil, nil
}

return imgInfo, err
} else {
return imgInfo, nil
}
}

func (api *api) TryGetRepoImage(ctx context.Context, reference string) (*image.Info, error) {
return api.tryGetRepoImage(ctx, reference, "")
}

func (api *api) GetRepoImage(ctx context.Context, reference string) (*image.Info, error) {
desc, _, err := api.getImageDesc(reference)
if err != nil {
Expand Down
21 changes: 1 addition & 20 deletions pkg/docker_registry/default.go
Expand Up @@ -51,18 +51,7 @@ func (r *defaultImplementation) IsTagExist(_ context.Context, _ string, _ ...Opt
}

func (r *defaultImplementation) TryGetRepoImage(ctx context.Context, reference string) (*image.Info, error) {
info, err := r.api.TryGetRepoImage(ctx, reference)
if err != nil {
if IsQuayTagExpiredErr(err) && r.Implementation != QuayImplementationName {
logboek.Context(ctx).Error().LogF("WARNING: Detected error specific for quay container registry implementation!\n")
logboek.Context(ctx).Error().LogF("WARNING: Use --repo-container-registry=quay option (or WERF_CONTAINER_REGISTRY env var)\n")
logboek.Context(ctx).Error().LogF("WARNING: to instruct werf to use quay driver.\n")
}

return nil, err
}

return info, nil
return r.tryGetRepoImage(ctx, reference, r.Implementation)
}

func (r *defaultImplementation) CreateRepo(_ context.Context, _ string) error {
Expand All @@ -84,11 +73,3 @@ func (r *defaultImplementation) DeleteRepoImage(ctx context.Context, repoImage *
func (r *defaultImplementation) String() string {
return DefaultImplementationName
}

func IsManifestUnknownError(err error) bool {
return (err != nil) && strings.Contains(err.Error(), "MANIFEST_UNKNOWN")
}

func IsNameUnknownError(err error) bool {
return (err != nil) && strings.Contains(err.Error(), "NAME_UNKNOWN")
}
48 changes: 48 additions & 0 deletions pkg/docker_registry/errors.go
@@ -0,0 +1,48 @@
package docker_registry

import (
"strings"

"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)

var (
BrokenImageCodes = []transport.ErrorCode{
transport.BlobUnknownErrorCode,
transport.BlobUploadInvalidErrorCode,
transport.BlobUploadUnknownErrorCode,
transport.DigestInvalidErrorCode,
transport.ManifestBlobUnknownErrorCode,
transport.ManifestInvalidErrorCode,
transport.ManifestUnverifiedErrorCode,
transport.NameInvalidErrorCode,
}

NotFoundImageCodes = []transport.ErrorCode{
transport.ManifestUnknownErrorCode,
transport.NameUnknownErrorCode,
}
)

func isErrorMatched(err error, codes []transport.ErrorCode) bool {
if err != nil {
for _, code := range codes {
if strings.Contains(err.Error(), string(code)) {
return true
}
}
}
return false
}

func IsBrokenImageError(err error) bool {
return isErrorMatched(err, BrokenImageCodes) || IsQuayTagExpiredErr(err)
}

func IsImageNotFoundError(err error) bool {
return isErrorMatched(err, NotFoundImageCodes) || IsHarborNotFoundError(err)
}

func IsHarborNotFoundError(err error) bool {
return (err != nil) && strings.Contains(err.Error(), "NOT_FOUND")
}
3 changes: 1 addition & 2 deletions pkg/docker_registry/generic_api.go
Expand Up @@ -38,7 +38,7 @@ func (api *genericApi) GetRepoImageConfigFile(ctx context.Context, reference str
for _, mirrorReference := range mirrorReferenceList {
config, err := api.getRepoImageConfigFile(ctx, mirrorReference)
if err != nil {
if IsStatusNotFoundErr(err) || IsQuayTagExpiredErr(err) {
if IsStatusNotFoundErr(err) || IsImageNotFoundError(err) || IsBrokenImageError(err) {
continue
}

Expand Down Expand Up @@ -76,7 +76,6 @@ func (api *genericApi) GetRepoImage(ctx context.Context, reference string) (*ima
if err != nil {
return nil, fmt.Errorf("unable to try getting mirror repo image %q: %w", mirrorReference, err)
}

if info != nil {
return info, nil
}
Expand Down
7 changes: 2 additions & 5 deletions pkg/storage/repo_stages_storage.go
Expand Up @@ -269,15 +269,12 @@ func (storage *RepoStagesStorage) GetStageDescription(ctx context.Context, proje
logboek.Context(ctx).Debug().LogF("-- RepoStagesStorage stageImageName = %q\n", stageImageName)

imgInfo, err := storage.DockerRegistry.GetRepoImage(ctx, stageImageName)

if docker_registry.IsNameUnknownError(err) || docker_registry.IsManifestUnknownError(err) {
if docker_registry.IsImageNotFoundError(err) {
return nil, nil
}

if docker_registry.IsStatusNotFoundErr(err) || docker_registry.IsQuayTagExpiredErr(err) {
if docker_registry.IsBrokenImageError(err) {
return nil, ErrBrokenImage
}

if err != nil {
return nil, fmt.Errorf("unable to inspect repo image %s: %w", stageImageName, err)
}
Expand Down

0 comments on commit bc4ef3d

Please sign in to comment.