diff --git a/pkg/docker_registry/aws_ecr.go b/pkg/docker_registry/aws_ecr.go index baf3f92054..f44567cf0d 100644 --- a/pkg/docker_registry/aws_ecr.go +++ b/pkg/docker_registry/aws_ecr.go @@ -29,7 +29,7 @@ type awsEcrOptions struct { } func newAwsEcr(options awsEcrOptions) (*awsEcr, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(AwsEcrImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/azure_cr.go b/pkg/docker_registry/azure_cr.go index cfbe55c62b..e10c0f4dbd 100644 --- a/pkg/docker_registry/azure_cr.go +++ b/pkg/docker_registry/azure_cr.go @@ -40,7 +40,7 @@ type azureCrOptions struct { } func newAzureCr(options azureCrOptions) (*azureCr, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(AzureCrImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/default.go b/pkg/docker_registry/default.go index f28a03184e..8b5abc2ac5 100644 --- a/pkg/docker_registry/default.go +++ b/pkg/docker_registry/default.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/werf/logboek" "github.com/werf/werf/pkg/image" ) @@ -12,6 +13,7 @@ const DefaultImplementationName = "default" type defaultImplementation struct { *api + Implementation string } type defaultImplementationOptions struct { @@ -19,11 +21,48 @@ type defaultImplementationOptions struct { } func newDefaultImplementation(options defaultImplementationOptions) (*defaultImplementation, error) { + return newDefaultAPIForImplementation(DefaultImplementationName, options) +} + +func newDefaultAPIForImplementation(implementation string, options defaultImplementationOptions) (*defaultImplementation, error) { d := &defaultImplementation{} d.api = newAPI(options.apiOptions) + d.Implementation = implementation return d, nil } +func (r *defaultImplementation) Tags(ctx context.Context, reference string) ([]string, error) { + tags, err := r.api.Tags(ctx, reference) + + if (IsHarbor404Error(err) || IsHarborNotFoundError(err)) && r.Implementation != HarborImplementationName { + logboek.Context(ctx).Error().LogF("WARNING: Detected error specific for harbor container registry implementation!\n") + logboek.Context(ctx).Error().LogF("WARNING: Use --repo-container-registry=harbor option (or WERF_CONTAINER_REGISTRY env var)\n") + logboek.Context(ctx).Error().LogF("WARNING: to instruct werf to use harbor driver.\n") + } + + return tags, err +} + +func (r *defaultImplementation) IsRepoImageExists(ctx context.Context, reference string) (bool, error) { + if imgInfo, err := r.TryGetRepoImage(ctx, reference); err != nil { + return false, err + } else { + return imgInfo != nil, nil + } +} + +func (r *defaultImplementation) TryGetRepoImage(ctx context.Context, reference string) (*image.Info, error) { + info, err := r.api.TryGetRepoImage(ctx, reference) + + if (IsHarbor404Error(err) || IsHarborNotFoundError(err)) && r.Implementation != HarborImplementationName { + logboek.Context(ctx).Error().LogF("WARNING: Detected error specific for harbor container registry implementation!\n") + logboek.Context(ctx).Error().LogF("WARNING: Use --repo-container-registry=harbor option (or WERF_CONTAINER_REGISTRY env var)\n") + logboek.Context(ctx).Error().LogF("WARNING: to instruct werf to use harbor driver.\n") + } + + return info, err +} + func (r *defaultImplementation) CreateRepo(_ context.Context, _ string) error { return fmt.Errorf("method is not implemented") } @@ -55,15 +94,3 @@ func IsBlobUnknownError(err error) bool { func IsNameUnknownError(err error) bool { return (err != nil) && strings.Contains(err.Error(), "NAME_UNKNOWN") } - -func IsHarbor404Error(err error) bool { - if err == nil { - return false - } - - // Example error: - // GET https://domain/harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/2d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/data?X-Amz-Algorithm=REDACTED&X-Amz-Credential=REDACTED&X-Amz-Date=REDACTED&X-Amz-Expires=REDACTED&X-Amz-Signature=REDACTED&X-Amz-SignedHeaders=REDACTED: unsupported status code 404; body: - // NoSuchKeyThe specified key does not exist./harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/3d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/datac5bb943c-1e85-5930-b455-c3e8edbbaccd - - return strings.Contains(err.Error(), "unsupported status code 404") -} diff --git a/pkg/docker_registry/docker_hub.go b/pkg/docker_registry/docker_hub.go index 6db010ca6c..f492bb7dc9 100644 --- a/pkg/docker_registry/docker_hub.go +++ b/pkg/docker_registry/docker_hub.go @@ -64,7 +64,7 @@ type dockerHubCredentials struct { } func newDockerHub(options dockerHubOptions) (*dockerHub, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(DockerHubImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/gcr.go b/pkg/docker_registry/gcr.go index e7c96acb8e..25fb4dba83 100644 --- a/pkg/docker_registry/gcr.go +++ b/pkg/docker_registry/gcr.go @@ -20,7 +20,7 @@ type GcrOptions struct { } func newGcr(options GcrOptions) (*gcr, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(GcrImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/github_packages.go b/pkg/docker_registry/github_packages.go index 9de278da38..442b27249f 100644 --- a/pkg/docker_registry/github_packages.go +++ b/pkg/docker_registry/github_packages.go @@ -68,7 +68,7 @@ type gitHubPackagesOptions struct { } func newGitHubPackages(options gitHubPackagesOptions) (*gitHubPackages, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(GitHubPackagesImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/gitlab_registry.go b/pkg/docker_registry/gitlab_registry.go index a219378325..6339c84f02 100644 --- a/pkg/docker_registry/gitlab_registry.go +++ b/pkg/docker_registry/gitlab_registry.go @@ -41,7 +41,7 @@ type gitLabRegistryOptions struct { } func newGitLabRegistry(options gitLabRegistryOptions) (*gitLabRegistry, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(GitLabRegistryImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } diff --git a/pkg/docker_registry/harbor.go b/pkg/docker_registry/harbor.go index 9f4c70f98b..07cc1084b2 100644 --- a/pkg/docker_registry/harbor.go +++ b/pkg/docker_registry/harbor.go @@ -47,7 +47,7 @@ type harborCredentials struct { } func newHarbor(options harborOptions) (*harbor, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(HarborImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func newHarbor(options harborOptions) (*harbor, error) { func (r *harbor) Tags(ctx context.Context, reference string) ([]string, error) { tags, err := r.defaultImplementation.Tags(ctx, reference) if err != nil { - if IsNotFoundError(err) { + if IsHarborNotFoundError(err) { return []string{}, nil } return nil, err @@ -84,7 +84,7 @@ func (r *harbor) IsRepoImageExists(ctx context.Context, reference string) (bool, func (r *harbor) TryGetRepoImage(ctx context.Context, reference string) (*image.Info, error) { res, err := r.api.TryGetRepoImage(ctx, reference) if err != nil { - if IsNotFoundError(err) { + if IsHarborNotFoundError(err) { return nil, nil } @@ -130,6 +130,18 @@ func (r *harbor) parseReference(reference string) (string, string, error) { return parsedReference.RegistryStr(), parsedReference.RepositoryStr(), nil } -func IsNotFoundError(err error) bool { - return strings.Contains(err.Error(), "NOT_FOUND") +func IsHarborNotFoundError(err error) bool { + return err != nil && strings.Contains(err.Error(), "NOT_FOUND") +} + +func IsHarbor404Error(err error) bool { + if err == nil { + return false + } + + // Example error: + // GET https://domain/harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/2d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/data?X-Amz-Algorithm=REDACTED&X-Amz-Credential=REDACTED&X-Amz-Date=REDACTED&X-Amz-Expires=REDACTED&X-Amz-Signature=REDACTED&X-Amz-SignedHeaders=REDACTED: unsupported status code 404; body: + // NoSuchKeyThe specified key does not exist./harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/3d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/datac5bb943c-1e85-5930-b455-c3e8edbbaccd + + return strings.Contains(err.Error(), "unsupported status code 404") } diff --git a/pkg/docker_registry/quay.go b/pkg/docker_registry/quay.go index 327926afe6..dec0302f60 100644 --- a/pkg/docker_registry/quay.go +++ b/pkg/docker_registry/quay.go @@ -46,7 +46,7 @@ type quayCredentials struct { } func newQuay(options quayOptions) (*quay, error) { - d, err := newDefaultImplementation(options.defaultImplementationOptions) + d, err := newDefaultAPIForImplementation(QuayImplementationName, options.defaultImplementationOptions) if err != nil { return nil, err }