Skip to content

Commit

Permalink
fix(harbor): detect usage of harbor without --repo-container-registry…
Browse files Browse the repository at this point in the history
…=harbor option

Added warning when an error occurs which is known to be an error from the harbor.
This warning instructs user to specify --repo-container-registry=harbor option (possibly forgotten).
  • Loading branch information
distorhead committed Dec 14, 2021
1 parent bf7a874 commit a3843f9
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 24 deletions.
2 changes: 1 addition & 1 deletion pkg/docker_registry/aws_ecr.go
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker_registry/azure_cr.go
Expand Up @@ -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
}
Expand Down
51 changes: 39 additions & 12 deletions pkg/docker_registry/default.go
Expand Up @@ -5,25 +5,64 @@ import (
"fmt"
"strings"

"github.com/werf/logboek"
"github.com/werf/werf/pkg/image"
)

const DefaultImplementationName = "default"

type defaultImplementation struct {
*api
Implementation string
}

type defaultImplementationOptions struct {
apiOptions
}

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")
}
Expand Down Expand Up @@ -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: <?xml version="1.0" encoding="UTF-8"?>
// <Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Resource>/harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/3d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/data</Resource><RequestId>c5bb943c-1e85-5930-b455-c3e8edbbaccd</RequestId></Error>

return strings.Contains(err.Error(), "unsupported status code 404")
}
2 changes: 1 addition & 1 deletion pkg/docker_registry/docker_hub.go
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker_registry/gcr.go
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker_registry/github_packages.go
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker_registry/gitlab_registry.go
Expand Up @@ -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
}
Expand Down
22 changes: 17 additions & 5 deletions pkg/docker_registry/harbor.go
Expand Up @@ -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
}
Expand All @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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: <?xml version="1.0" encoding="UTF-8"?>
// <Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Resource>/harbor/s3/object/name/prefix/docker/registry/v2/blobs/sha256/3d/3d8c68cd9df32f1beb4392298a123eac58aba1433a15b3258b2f3728bad4b7d1/data</Resource><RequestId>c5bb943c-1e85-5930-b455-c3e8edbbaccd</RequestId></Error>

return strings.Contains(err.Error(), "unsupported status code 404")
}
2 changes: 1 addition & 1 deletion pkg/docker_registry/quay.go
Expand Up @@ -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
}
Expand Down

0 comments on commit a3843f9

Please sign in to comment.