From ab3aad4d5098505cc0213912041ebe043da62f8f Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Sun, 16 Feb 2020 20:13:32 +0800 Subject: [PATCH] Implement the resolver for CNAB This commit introduces a new resolver to resolver metadata for CNAB Signed-off-by: Wenkai Yin --- src/api/artifact/abstractor/abstractor.go | 35 +-- .../artifact/abstractor/abstractor_test.go | 22 -- .../artifact/abstractor/resolver/cnab/cnab.go | 130 ++++++++++ .../abstractor/resolver/cnab/cnab_test.go | 144 +++++++++++ src/api/artifact/controller.go | 21 +- src/api/artifact/descriptor/descriptor.go | 46 ++-- .../artifact/descriptor/descriptor_test.go | 50 ++++ src/pkg/distribution/distribution.go | 2 + src/server/router/router.go | 3 +- .../manifest/ocischema/builder.go | 107 ++++++++ .../manifest/ocischema/manifest.go | 124 ++++++++++ src/vendor/modules.txt | 233 +++++++++--------- 12 files changed, 722 insertions(+), 195 deletions(-) create mode 100644 src/api/artifact/abstractor/resolver/cnab/cnab.go create mode 100644 src/api/artifact/abstractor/resolver/cnab/cnab_test.go create mode 100644 src/api/artifact/descriptor/descriptor_test.go create mode 100644 src/vendor/github.com/docker/distribution/manifest/ocischema/builder.go create mode 100644 src/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go diff --git a/src/api/artifact/abstractor/abstractor.go b/src/api/artifact/abstractor/abstractor.go index 7ee3e55a9..c3c168524 100644 --- a/src/api/artifact/abstractor/abstractor.go +++ b/src/api/artifact/abstractor/abstractor.go @@ -27,15 +27,8 @@ import ( "github.com/goharbor/harbor/src/pkg/artifact" "github.com/goharbor/harbor/src/pkg/repository" "github.com/opencontainers/image-spec/specs-go/v1" - "regexp" - "strings" ) -// ArtifactTypeUnknown defines the type for the unknown artifacts -const ArtifactTypeUnknown = "UNKNOWN" - -var artifactTypeRegExp = regexp.MustCompile(`^application/vnd\.[^.]*\.(.*)\.config\.[^.]*\+json$`) - // Abstractor abstracts the specific information for different types of artifacts type Abstractor interface { // AbstractMetadata abstracts the metadata for the specific artifact type into the artifact model, @@ -60,8 +53,6 @@ type abstractor struct { blobFetcher blob.Fetcher } -// TODO try CNAB, how to forbid CNAB - // TODO add white list for supported artifact type func (a *abstractor) AbstractMetadata(ctx context.Context, artifact *artifact.Artifact) error { repository, err := a.repoMgr.Get(ctx, artifact.RepositoryID) @@ -101,9 +92,8 @@ func (a *abstractor) AbstractMetadata(ctx context.Context, artifact *artifact.Ar artifact.Annotations = manifest.Annotations // OCI index/docker manifest list case v1.MediaTypeImageIndex, manifestlist.MediaTypeManifestList: - // the identity of index is still in progress, only handle image index for now - // and use the manifestMediaType as the media type of artifact - // If we want to support CNAB, we should get the media type from annotation + // the identity of index is still in progress, we use the manifest mediaType + // as the media type of artifact artifact.MediaType = artifact.ManifestMediaType index := &v1.Index{} @@ -115,7 +105,15 @@ func (a *abstractor) AbstractMetadata(ctx context.Context, artifact *artifact.Ar // set annotations artifact.Annotations = index.Annotations - // TODO handle references in resolvers + + // Currently, CNAB put its media type inside the annotations + // try to parse the artifact media type from the annotations + if artifact.Annotations != nil { + mediaType := artifact.Annotations["org.opencontainers.artifactType"] + if len(mediaType) > 0 { + artifact.MediaType = mediaType + } + } default: return fmt.Errorf("unsupported manifest media type: %s", artifact.ManifestMediaType) } @@ -125,8 +123,6 @@ func (a *abstractor) AbstractMetadata(ctx context.Context, artifact *artifact.Ar return resolver.ResolveMetadata(ctx, content, artifact) } - // if got no resolver, try to parse the artifact type based on the media type - artifact.Type = parseArtifactType(artifact.MediaType) return nil } @@ -138,12 +134,3 @@ func (a *abstractor) AbstractAddition(ctx context.Context, artifact *artifact.Ar } return resolver.ResolveAddition(ctx, artifact, addition) } - -func parseArtifactType(mediaType string) string { - strs := artifactTypeRegExp.FindStringSubmatch(mediaType) - if len(strs) == 2 { - return strings.ToUpper(strs[1]) - } - // can not get the artifact type from the media type, return unknown - return ArtifactTypeUnknown -} diff --git a/src/api/artifact/abstractor/abstractor_test.go b/src/api/artifact/abstractor/abstractor_test.go index de11b2fc0..c368f5642 100644 --- a/src/api/artifact/abstractor/abstractor_test.go +++ b/src/api/artifact/abstractor/abstractor_test.go @@ -284,28 +284,6 @@ func (a *abstractorTestSuite) TestAbstractMetadataOfUnsupported() { a.Require().NotNil(err) } -func (a *abstractorTestSuite) TestParseArtifactType() { - mediaType := "" - typee := parseArtifactType(mediaType) - a.Equal(ArtifactTypeUnknown, typee) - - mediaType = "unknown" - typee = parseArtifactType(mediaType) - a.Equal(ArtifactTypeUnknown, typee) - - mediaType = "application/vnd.oci.image.config.v1+json" - typee = parseArtifactType(mediaType) - a.Equal("IMAGE", typee) - - mediaType = "application/vnd.cncf.helm.chart.config.v1+json" - typee = parseArtifactType(mediaType) - a.Equal("HELM.CHART", typee) - - mediaType = "application/vnd.sylabs.sif.config.v1+json" - typee = parseArtifactType(mediaType) - a.Equal("SIF", typee) -} - func (a *abstractorTestSuite) TestAbstractAddition() { resolver.Register(a.resolver, v1.MediaTypeImageConfig) // cannot get the resolver diff --git a/src/api/artifact/abstractor/resolver/cnab/cnab.go b/src/api/artifact/abstractor/resolver/cnab/cnab.go new file mode 100644 index 000000000..c65eb4633 --- /dev/null +++ b/src/api/artifact/abstractor/resolver/cnab/cnab.go @@ -0,0 +1,130 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cnab + +import ( + "context" + "encoding/json" + "github.com/goharbor/harbor/src/api/artifact/abstractor/blob" + resolv "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver" + "github.com/goharbor/harbor/src/api/artifact/descriptor" + "github.com/goharbor/harbor/src/common/utils/log" + ierror "github.com/goharbor/harbor/src/internal/error" + "github.com/goharbor/harbor/src/pkg/artifact" + "github.com/goharbor/harbor/src/pkg/repository" + v1 "github.com/opencontainers/image-spec/specs-go/v1" +) + +// const definitions +const ( + ArtifactTypeCNAB = "CNAB" + mediaType = "application/vnd.cnab.manifest.v1" +) + +func init() { + resolver := &resolver{ + repoMgr: repository.Mgr, + argMgr: artifact.Mgr, + blobFetcher: blob.Fcher, + } + if err := resolv.Register(resolver, mediaType); err != nil { + log.Errorf("failed to register resolver for media type %s: %v", mediaType, err) + return + } + if err := descriptor.Register(resolver, mediaType); err != nil { + log.Errorf("failed to register descriptor for media type %s: %v", mediaType, err) + return + } +} + +type resolver struct { + repoMgr repository.Manager + argMgr artifact.Manager + blobFetcher blob.Fetcher +} + +func (r *resolver) ResolveMetadata(ctx context.Context, manifest []byte, art *artifact.Artifact) error { + index := &v1.Index{} + if err := json.Unmarshal(manifest, index); err != nil { + return err + } + cfgManiDgt := "" + // populate the referenced artifacts + for _, mani := range index.Manifests { + digest := mani.Digest.String() + // make sure the child artifact exist + ar, err := r.argMgr.GetByDigest(ctx, art.RepositoryID, digest) + if err != nil { + return err + } + art.References = append(art.References, &artifact.Reference{ + ChildID: ar.ID, + Platform: mani.Platform, + }) + // try to get the digest of the manifest that the config layer is referenced by + if mani.Annotations != nil && + mani.Annotations["io.cnab.manifest.type"] == "config" { + cfgManiDgt = mani.Digest.String() + } + } + if len(cfgManiDgt) == 0 { + return nil + } + + // resolve the config of CNAB + repository, err := r.repoMgr.Get(ctx, art.RepositoryID) + if err != nil { + return err + } + // get the manifest that the config layer is referenced by + _, cfgMani, err := r.blobFetcher.FetchManifest(repository.Name, cfgManiDgt) + if err != nil { + return err + } + m := &v1.Manifest{} + if err := json.Unmarshal(cfgMani, m); err != nil { + return err + } + cfgDgt := m.Config.Digest.String() + // get the config layer + cfg, err := r.blobFetcher.FetchLayer(repository.Name, cfgDgt) + if err != nil { + return err + } + metadata := map[string]interface{}{} + if err := json.Unmarshal(cfg, &metadata); err != nil { + return err + } + if art.ExtraAttrs == nil { + art.ExtraAttrs = map[string]interface{}{} + } + for k, v := range metadata { + art.ExtraAttrs[k] = v + } + return nil +} + +func (r *resolver) ResolveAddition(ctx context.Context, artifact *artifact.Artifact, addition string) (*resolv.Addition, error) { + return nil, ierror.New(nil).WithCode(ierror.BadRequestCode). + WithMessage("addition %s isn't supported for %s", addition, ArtifactTypeCNAB) +} + +func (r *resolver) GetArtifactType() string { + return ArtifactTypeCNAB +} + +func (r *resolver) ListAdditionTypes() []string { + return nil +} diff --git a/src/api/artifact/abstractor/resolver/cnab/cnab_test.go b/src/api/artifact/abstractor/resolver/cnab/cnab_test.go new file mode 100644 index 000000000..637f60613 --- /dev/null +++ b/src/api/artifact/abstractor/resolver/cnab/cnab_test.go @@ -0,0 +1,144 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cnab + +import ( + "github.com/goharbor/harbor/src/common/models" + ierror "github.com/goharbor/harbor/src/internal/error" + "github.com/goharbor/harbor/src/pkg/artifact" + "github.com/goharbor/harbor/src/testing/api/artifact/abstractor/blob" + testingartifact "github.com/goharbor/harbor/src/testing/pkg/artifact" + "github.com/goharbor/harbor/src/testing/pkg/repository" + "github.com/stretchr/testify/suite" + "testing" +) + +type resolverTestSuite struct { + suite.Suite + resolver *resolver + repoMgr *repository.FakeManager + artMgr *testingartifact.FakeManager + blobFetcher *blob.FakeFetcher +} + +func (r *resolverTestSuite) SetupTest() { + r.repoMgr = &repository.FakeManager{} + r.artMgr = &testingartifact.FakeManager{} + r.blobFetcher = &blob.FakeFetcher{} + r.resolver = &resolver{ + repoMgr: r.repoMgr, + argMgr: r.artMgr, + blobFetcher: r.blobFetcher, + } + +} + +func (r *resolverTestSuite) TestResolveMetadata() { + index := `{ + "schemaVersion": 2, + "manifests": [ + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:b9616da7500f8c7c9a5e8d915714cd02d11bcc71ff5b4fd190bb77b1355c8549", + "size": 193, + "annotations": { + "io.cnab.manifest.type": "config" + } + }, + { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6", + "size": 942, + "annotations": { + "io.cnab.manifest.type": "invocation" + } + } + ], + "annotations": { + "io.cnab.keywords": "[\"helloworld\",\"cnab\",\"tutorial\"]", + "io.cnab.runtime_version": "v1.0.0", + "org.opencontainers.artifactType": "application/vnd.cnab.manifest.v1", + "org.opencontainers.image.authors": "[{\"name\":\"Jane Doe\",\"email\":\"jane.doe@example.com\",\"url\":\"https://example.com\"}]", + "org.opencontainers.image.description": "A short description of your bundle", + "org.opencontainers.image.title": "helloworld", + "org.opencontainers.image.version": "0.1.1" + } +}` + + manifest := `{ + "schemaVersion": 2, + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "digest": "sha256:e91b9dfcbbb3b88bac94726f276b89de46e4460b55f6e6d6f876e666b150ec5b", + "size": 498 + }, + "layers": null +}` + config := `{ + "description": "A short description of your bundle", + "invocationImages": [ + { + "contentDigest": "sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6", + "image": "cnab/helloworld:0.1.1", + "imageType": "docker", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "size": 942 + } + ], + "keywords": [ + "helloworld", + "cnab", + "tutorial" + ], + "maintainers": [ + { + "email": "jane.doe@example.com", + "name": "Jane Doe", + "url": "https://example.com" + } + ], + "name": "helloworld", + "schemaVersion": "v1.0.0", + "version": "0.1.1" +}` + art := &artifact.Artifact{} + r.artMgr.On("GetByDigest").Return(&artifact.Artifact{ID: 1}, nil) + r.repoMgr.On("Get").Return(&models.RepoRecord{}, nil) + r.blobFetcher.On("FetchManifest").Return("", []byte(manifest), nil) + r.blobFetcher.On("FetchLayer").Return([]byte(config), nil) + err := r.resolver.ResolveMetadata(nil, []byte(index), art) + r.Require().Nil(err) + r.Len(art.References, 2) + r.Equal("0.1.1", art.ExtraAttrs["version"].(string)) + r.Equal("helloworld", art.ExtraAttrs["name"].(string)) +} + +func (r *resolverTestSuite) TestResolveAddition() { + _, err := r.resolver.ResolveAddition(nil, nil, "") + r.Require().NotNil(err) + r.True(ierror.IsErr(err, ierror.BadRequestCode)) +} + +func (r *resolverTestSuite) TestGetArtifactType() { + r.Assert().Equal(ArtifactTypeCNAB, r.resolver.GetArtifactType()) +} + +func (r *resolverTestSuite) TestListAdditionTypes() { + r.Nil(r.resolver.ListAdditionTypes()) +} + +func TestResolverTestSuite(t *testing.T) { + suite.Run(t, &resolverTestSuite{}) +} diff --git a/src/api/artifact/controller.go b/src/api/artifact/controller.go index a7df07a26..a6e096748 100644 --- a/src/api/artifact/controller.go +++ b/src/api/artifact/controller.go @@ -17,9 +17,6 @@ package artifact import ( "context" "fmt" - "strings" - "time" - "github.com/goharbor/harbor/src/api/artifact/abstractor" "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver" "github.com/goharbor/harbor/src/api/artifact/descriptor" @@ -36,11 +33,14 @@ import ( "github.com/goharbor/harbor/src/pkg/registry" "github.com/goharbor/harbor/src/pkg/signature" "github.com/opencontainers/go-digest" - + "strings" + "time" // registry image resolvers _ "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver/image" // register chart resolver _ "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver/chart" + // register CNAB resolver + _ "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver/cnab" "github.com/goharbor/harbor/src/common/utils/log" ierror "github.com/goharbor/harbor/src/internal/error" "github.com/goharbor/harbor/src/pkg/artifact" @@ -170,11 +170,7 @@ func (c *controller) ensureArtifact(ctx context.Context, repositoryID int64, dig } // populate the artifact type - typee, err := descriptor.GetArtifactType(artifact.MediaType) - if err != nil { - return false, 0, err - } - artifact.Type = typee + artifact.Type = descriptor.GetArtifactType(artifact.MediaType) // create it id, err := c.artMgr.Create(ctx, artifact) @@ -658,12 +654,7 @@ func (c *controller) populateImmutableStatus(ctx context.Context, tag *Tag) { } func (c *controller) populateAdditionLinks(ctx context.Context, artifact *Artifact) { - types, err := descriptor.ListAdditionTypes(artifact.MediaType) - if err != nil { - log.Error(err.Error()) - return - } - + types := descriptor.ListAdditionTypes(artifact.MediaType) if len(types) > 0 { version := internal.GetAPIVersion(ctx) for _, t := range types { diff --git a/src/api/artifact/descriptor/descriptor.go b/src/api/artifact/descriptor/descriptor.go index 0254e31df..d6bf21ba8 100644 --- a/src/api/artifact/descriptor/descriptor.go +++ b/src/api/artifact/descriptor/descriptor.go @@ -17,10 +17,16 @@ package descriptor import ( "fmt" "github.com/goharbor/harbor/src/common/utils/log" + "regexp" + "strings" ) +// ArtifactTypeUnknown defines the type for the unknown artifacts +const ArtifactTypeUnknown = "UNKNOWN" + var ( - registry = map[string]Descriptor{} + registry = map[string]Descriptor{} + artifactTypeRegExp = regexp.MustCompile(`^application/vnd\.[^.]*\.(.*)\.config\.[^.]*\+json$`) ) // Descriptor describes the static information for one kind of media type @@ -45,28 +51,34 @@ func Register(descriptor Descriptor, mediaTypes ...string) error { } // Get the descriptor according to the media type -func Get(mediaType string) (Descriptor, error) { - descriptor := registry[mediaType] - if descriptor == nil { - return nil, fmt.Errorf("descriptor for media type %s not found", mediaType) - } - return descriptor, nil +func Get(mediaType string) Descriptor { + return registry[mediaType] } // GetArtifactType gets the artifact type according to the media type -func GetArtifactType(mediaType string) (string, error) { - descriptor, err := Get(mediaType) - if err != nil { - return "", err +func GetArtifactType(mediaType string) string { + descriptor := Get(mediaType) + if descriptor != nil { + return descriptor.GetArtifactType() } - return descriptor.GetArtifactType(), nil + // if got no descriptor, try to parse the artifact type based on the media type + return parseArtifactType(mediaType) } // ListAdditionTypes lists the supported addition types according to the media type -func ListAdditionTypes(mediaType string) ([]string, error) { - descriptor, err := Get(mediaType) - if err != nil { - return nil, err +func ListAdditionTypes(mediaType string) []string { + descriptor := Get(mediaType) + if descriptor != nil { + return descriptor.ListAdditionTypes() } - return descriptor.ListAdditionTypes(), nil + return nil +} + +func parseArtifactType(mediaType string) string { + strs := artifactTypeRegExp.FindStringSubmatch(mediaType) + if len(strs) == 2 { + return strings.ToUpper(strs[1]) + } + // can not get the artifact type from the media type, return unknown + return ArtifactTypeUnknown } diff --git a/src/api/artifact/descriptor/descriptor_test.go b/src/api/artifact/descriptor/descriptor_test.go new file mode 100644 index 000000000..b4e7d2af2 --- /dev/null +++ b/src/api/artifact/descriptor/descriptor_test.go @@ -0,0 +1,50 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package descriptor + +import ( + "github.com/stretchr/testify/suite" + "testing" +) + +type descriptorTestSuite struct { + suite.Suite +} + +func (d *descriptorTestSuite) TestParseArtifactType() { + mediaType := "" + typee := parseArtifactType(mediaType) + d.Equal(ArtifactTypeUnknown, typee) + + mediaType = "unknown" + typee = parseArtifactType(mediaType) + d.Equal(ArtifactTypeUnknown, typee) + + mediaType = "application/vnd.oci.image.config.v1+json" + typee = parseArtifactType(mediaType) + d.Equal("IMAGE", typee) + + mediaType = "application/vnd.cncf.helm.chart.config.v1+json" + typee = parseArtifactType(mediaType) + d.Equal("HELM.CHART", typee) + + mediaType = "application/vnd.sylabs.sif.config.v1+json" + typee = parseArtifactType(mediaType) + d.Equal("SIF", typee) +} + +func TestDescriptorTestSuite(t *testing.T) { + suite.Run(t, &descriptorTestSuite{}) +} diff --git a/src/pkg/distribution/distribution.go b/src/pkg/distribution/distribution.go index fc7d5ce4c..6a4fc122b 100644 --- a/src/pkg/distribution/distribution.go +++ b/src/pkg/distribution/distribution.go @@ -25,6 +25,8 @@ import ( _ "github.com/docker/distribution/manifest/schema2" // manifestlist _ "github.com/docker/distribution/manifest/manifestlist" + // oci schema + _ "github.com/docker/distribution/manifest/ocischema" ref "github.com/docker/distribution/reference" "github.com/goharbor/harbor/src/common/utils" ) diff --git a/src/server/router/router.go b/src/server/router/router.go index 73cd10383..569057527 100644 --- a/src/server/router/router.go +++ b/src/server/router/router.go @@ -88,8 +88,9 @@ func (r *Route) Handler(handler http.Handler) { middleware.WithMiddlewares(handler, middlewares...). ServeHTTP(ctx.ResponseWriter, ctx.Request) }) + if len(methods) == 0 { - beego.Any(r.path, filterFunc) + beego.Any(path, filterFunc) return } for _, method := range methods { diff --git a/src/vendor/github.com/docker/distribution/manifest/ocischema/builder.go b/src/vendor/github.com/docker/distribution/manifest/ocischema/builder.go new file mode 100644 index 000000000..023a8a0bd --- /dev/null +++ b/src/vendor/github.com/docker/distribution/manifest/ocischema/builder.go @@ -0,0 +1,107 @@ +package ocischema + +import ( + "context" + "errors" + + "github.com/docker/distribution" + "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" + "github.com/opencontainers/image-spec/specs-go/v1" +) + +// Builder is a type for constructing manifests. +type Builder struct { + // bs is a BlobService used to publish the configuration blob. + bs distribution.BlobService + + // configJSON references + configJSON []byte + + // layers is a list of layer descriptors that gets built by successive + // calls to AppendReference. + layers []distribution.Descriptor + + // Annotations contains arbitrary metadata relating to the targeted content. + annotations map[string]string + + // For testing purposes + mediaType string +} + +// NewManifestBuilder is used to build new manifests for the current schema +// version. It takes a BlobService so it can publish the configuration blob +// as part of the Build process, and annotations. +func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder { + mb := &Builder{ + bs: bs, + configJSON: make([]byte, len(configJSON)), + annotations: annotations, + mediaType: v1.MediaTypeImageManifest, + } + copy(mb.configJSON, configJSON) + + return mb +} + +// SetMediaType assigns the passed mediatype or error if the mediatype is not a +// valid media type for oci image manifests currently: "" or "application/vnd.oci.image.manifest.v1+json" +func (mb *Builder) SetMediaType(mediaType string) error { + if mediaType != "" && mediaType != v1.MediaTypeImageManifest { + return errors.New("Invalid media type for OCI image manifest") + } + + mb.mediaType = mediaType + return nil +} + +// Build produces a final manifest from the given references. +func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) { + m := Manifest{ + Versioned: manifest.Versioned{ + SchemaVersion: 2, + MediaType: mb.mediaType, + }, + Layers: make([]distribution.Descriptor, len(mb.layers)), + Annotations: mb.annotations, + } + copy(m.Layers, mb.layers) + + configDigest := digest.FromBytes(mb.configJSON) + + var err error + m.Config, err = mb.bs.Stat(ctx, configDigest) + switch err { + case nil: + // Override MediaType, since Put always replaces the specified media + // type with application/octet-stream in the descriptor it returns. + m.Config.MediaType = v1.MediaTypeImageConfig + return FromStruct(m) + case distribution.ErrBlobUnknown: + // nop + default: + return nil, err + } + + // Add config to the blob store + m.Config, err = mb.bs.Put(ctx, v1.MediaTypeImageConfig, mb.configJSON) + // Override MediaType, since Put always replaces the specified media + // type with application/octet-stream in the descriptor it returns. + m.Config.MediaType = v1.MediaTypeImageConfig + if err != nil { + return nil, err + } + + return FromStruct(m) +} + +// AppendReference adds a reference to the current ManifestBuilder. +func (mb *Builder) AppendReference(d distribution.Describable) error { + mb.layers = append(mb.layers, d.Descriptor()) + return nil +} + +// References returns the current references added to this builder. +func (mb *Builder) References() []distribution.Descriptor { + return mb.layers +} diff --git a/src/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go b/src/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go new file mode 100644 index 000000000..09ce78b5d --- /dev/null +++ b/src/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go @@ -0,0 +1,124 @@ +package ocischema + +import ( + "encoding/json" + "errors" + "fmt" + + "github.com/docker/distribution" + "github.com/docker/distribution/manifest" + "github.com/opencontainers/go-digest" + "github.com/opencontainers/image-spec/specs-go/v1" +) + +var ( + // SchemaVersion provides a pre-initialized version structure for this + // packages version of the manifest. + SchemaVersion = manifest.Versioned{ + SchemaVersion: 2, // historical value here.. does not pertain to OCI or docker version + MediaType: v1.MediaTypeImageManifest, + } +) + +func init() { + ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) { + m := new(DeserializedManifest) + err := m.UnmarshalJSON(b) + if err != nil { + return nil, distribution.Descriptor{}, err + } + + dgst := digest.FromBytes(b) + return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: v1.MediaTypeImageManifest}, err + } + err := distribution.RegisterManifestSchema(v1.MediaTypeImageManifest, ocischemaFunc) + if err != nil { + panic(fmt.Sprintf("Unable to register manifest: %s", err)) + } +} + +// Manifest defines a ocischema manifest. +type Manifest struct { + manifest.Versioned + + // Config references the image configuration as a blob. + Config distribution.Descriptor `json:"config"` + + // Layers lists descriptors for the layers referenced by the + // configuration. + Layers []distribution.Descriptor `json:"layers"` + + // Annotations contains arbitrary metadata for the image manifest. + Annotations map[string]string `json:"annotations,omitempty"` +} + +// References returns the descriptors of this manifests references. +func (m Manifest) References() []distribution.Descriptor { + references := make([]distribution.Descriptor, 0, 1+len(m.Layers)) + references = append(references, m.Config) + references = append(references, m.Layers...) + return references +} + +// Target returns the target of this manifest. +func (m Manifest) Target() distribution.Descriptor { + return m.Config +} + +// DeserializedManifest wraps Manifest with a copy of the original JSON. +// It satisfies the distribution.Manifest interface. +type DeserializedManifest struct { + Manifest + + // canonical is the canonical byte representation of the Manifest. + canonical []byte +} + +// FromStruct takes a Manifest structure, marshals it to JSON, and returns a +// DeserializedManifest which contains the manifest and its JSON representation. +func FromStruct(m Manifest) (*DeserializedManifest, error) { + var deserialized DeserializedManifest + deserialized.Manifest = m + + var err error + deserialized.canonical, err = json.MarshalIndent(&m, "", " ") + return &deserialized, err +} + +// UnmarshalJSON populates a new Manifest struct from JSON data. +func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { + m.canonical = make([]byte, len(b), len(b)) + // store manifest in canonical + copy(m.canonical, b) + + // Unmarshal canonical JSON into Manifest object + var manifest Manifest + if err := json.Unmarshal(m.canonical, &manifest); err != nil { + return err + } + + if manifest.MediaType != "" && manifest.MediaType != v1.MediaTypeImageManifest { + return fmt.Errorf("if present, mediaType in manifest should be '%s' not '%s'", + v1.MediaTypeImageManifest, manifest.MediaType) + } + + m.Manifest = manifest + + return nil +} + +// MarshalJSON returns the contents of canonical. If canonical is empty, +// marshals the inner contents. +func (m *DeserializedManifest) MarshalJSON() ([]byte, error) { + if len(m.canonical) > 0 { + return m.canonical, nil + } + + return nil, errors.New("JSON representation not initialized in DeserializedManifest") +} + +// Payload returns the raw content of the manifest. The contents can be used to +// calculate the content identifier. +func (m DeserializedManifest) Payload() (string, []byte, error) { + return v1.MediaTypeImageManifest, m.canonical, nil +} diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 6cfa456d4..35b17b6ac 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -14,82 +14,82 @@ github.com/Unknwon/goconfig github.com/agl/ed25519 github.com/agl/ed25519/edwards25519 # github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190726115642-cd293c93fd97 -github.com/aliyun/alibaba-cloud-sdk-go/services/cr github.com/aliyun/alibaba-cloud-sdk-go/sdk github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth -github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests -github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider +github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors +github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests +github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils -github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers +github.com/aliyun/alibaba-cloud-sdk-go/services/cr # github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a github.com/asaskevich/govalidator # github.com/astaxie/beego v1.12.1 +github.com/astaxie/beego github.com/astaxie/beego/cache github.com/astaxie/beego/cache/redis -github.com/astaxie/beego -github.com/astaxie/beego/validation -github.com/astaxie/beego/orm -github.com/astaxie/beego/session/redis -github.com/astaxie/beego/context github.com/astaxie/beego/config +github.com/astaxie/beego/context github.com/astaxie/beego/context/param github.com/astaxie/beego/grace github.com/astaxie/beego/logs +github.com/astaxie/beego/orm github.com/astaxie/beego/session +github.com/astaxie/beego/session/redis github.com/astaxie/beego/toolbox github.com/astaxie/beego/utils +github.com/astaxie/beego/validation # github.com/aws/aws-sdk-go v1.19.47 github.com/aws/aws-sdk-go/aws github.com/aws/aws-sdk-go/aws/awserr -github.com/aws/aws-sdk-go/aws/credentials -github.com/aws/aws-sdk-go/aws/session -github.com/aws/aws-sdk-go/service/ecr -github.com/aws/aws-sdk-go/aws/endpoints -github.com/aws/aws-sdk-go/internal/sdkio -github.com/aws/aws-sdk-go/internal/ini -github.com/aws/aws-sdk-go/internal/shareddefaults +github.com/aws/aws-sdk-go/aws/awsutil github.com/aws/aws-sdk-go/aws/client +github.com/aws/aws-sdk-go/aws/client/metadata github.com/aws/aws-sdk-go/aws/corehandlers +github.com/aws/aws-sdk-go/aws/credentials +github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds +github.com/aws/aws-sdk-go/aws/credentials/endpointcreds github.com/aws/aws-sdk-go/aws/credentials/processcreds github.com/aws/aws-sdk-go/aws/credentials/stscreds github.com/aws/aws-sdk-go/aws/csm github.com/aws/aws-sdk-go/aws/defaults -github.com/aws/aws-sdk-go/aws/request -github.com/aws/aws-sdk-go/aws/awsutil -github.com/aws/aws-sdk-go/aws/client/metadata -github.com/aws/aws-sdk-go/aws/signer/v4 -github.com/aws/aws-sdk-go/private/protocol -github.com/aws/aws-sdk-go/private/protocol/jsonrpc -github.com/aws/aws-sdk-go/internal/sdkrand -github.com/aws/aws-sdk-go/service/sts -github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds -github.com/aws/aws-sdk-go/aws/credentials/endpointcreds github.com/aws/aws-sdk-go/aws/ec2metadata -github.com/aws/aws-sdk-go/private/protocol/rest -github.com/aws/aws-sdk-go/private/protocol/json/jsonutil -github.com/aws/aws-sdk-go/private/protocol/query +github.com/aws/aws-sdk-go/aws/endpoints +github.com/aws/aws-sdk-go/aws/request +github.com/aws/aws-sdk-go/aws/session +github.com/aws/aws-sdk-go/aws/signer/v4 +github.com/aws/aws-sdk-go/internal/ini +github.com/aws/aws-sdk-go/internal/sdkio +github.com/aws/aws-sdk-go/internal/sdkrand github.com/aws/aws-sdk-go/internal/sdkuri +github.com/aws/aws-sdk-go/internal/shareddefaults +github.com/aws/aws-sdk-go/private/protocol +github.com/aws/aws-sdk-go/private/protocol/json/jsonutil +github.com/aws/aws-sdk-go/private/protocol/jsonrpc +github.com/aws/aws-sdk-go/private/protocol/query github.com/aws/aws-sdk-go/private/protocol/query/queryutil +github.com/aws/aws-sdk-go/private/protocol/rest github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil +github.com/aws/aws-sdk-go/service/ecr +github.com/aws/aws-sdk-go/service/sts # github.com/beego/i18n v0.0.0-20140604031826-e87155e8f0c0 github.com/beego/i18n # github.com/bmatcuk/doublestar v1.1.1 github.com/bmatcuk/doublestar # github.com/casbin/casbin v1.7.0 github.com/casbin/casbin -github.com/casbin/casbin/model -github.com/casbin/casbin/persist -github.com/casbin/casbin/util +github.com/casbin/casbin/config github.com/casbin/casbin/effect github.com/casbin/casbin/log +github.com/casbin/casbin/model +github.com/casbin/casbin/persist github.com/casbin/casbin/persist/file-adapter github.com/casbin/casbin/rbac github.com/casbin/casbin/rbac/default-role-manager -github.com/casbin/casbin/config +github.com/casbin/casbin/util # github.com/coreos/go-oidc v2.0.0+incompatible github.com/coreos/go-oidc # github.com/cyphar/filepath-securejoin v0.2.2 @@ -101,27 +101,28 @@ github.com/dghubble/sling # github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go # github.com/docker/distribution v2.7.1+incompatible -github.com/docker/distribution/manifest/manifestlist -github.com/docker/distribution/manifest/schema1 -github.com/docker/distribution/manifest/schema2 github.com/docker/distribution -github.com/docker/distribution/registry/auth/token -github.com/docker/distribution/reference -github.com/docker/distribution/registry/client/auth/challenge -github.com/docker/distribution/health -github.com/docker/distribution/registry/auth -github.com/docker/distribution/manifest github.com/docker/distribution/context github.com/docker/distribution/digestset +github.com/docker/distribution/health +github.com/docker/distribution/manifest +github.com/docker/distribution/manifest/manifestlist +github.com/docker/distribution/manifest/ocischema +github.com/docker/distribution/manifest/schema1 +github.com/docker/distribution/manifest/schema2 +github.com/docker/distribution/reference github.com/docker/distribution/registry/api/errcode +github.com/docker/distribution/registry/auth +github.com/docker/distribution/registry/auth/token +github.com/docker/distribution/registry/client/auth/challenge github.com/docker/distribution/uuid # github.com/docker/go v0.0.0-20160303222718-d30aec9fd63c github.com/docker/go/canonical/json # github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 github.com/docker/libtrust # github.com/garyburd/redigo v1.6.0 -github.com/garyburd/redigo/redis github.com/garyburd/redigo/internal +github.com/garyburd/redigo/redis # github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml # github.com/go-openapi/analysis v0.19.5 @@ -137,8 +138,8 @@ github.com/go-openapi/jsonreference github.com/go-openapi/loads # github.com/go-openapi/runtime v0.19.5 github.com/go-openapi/runtime -github.com/go-openapi/runtime/middleware github.com/go-openapi/runtime/logger +github.com/go-openapi/runtime/middleware github.com/go-openapi/runtime/middleware/denco github.com/go-openapi/runtime/middleware/header github.com/go-openapi/runtime/middleware/untyped @@ -158,11 +159,11 @@ github.com/go-stack/stack # github.com/gobwas/glob v0.2.3 github.com/gobwas/glob github.com/gobwas/glob/compiler -github.com/gobwas/glob/syntax github.com/gobwas/glob/match +github.com/gobwas/glob/syntax github.com/gobwas/glob/syntax/ast -github.com/gobwas/glob/util/runes github.com/gobwas/glob/syntax/lexer +github.com/gobwas/glob/util/runes github.com/gobwas/glob/util/strings # github.com/gocraft/work v0.5.1 github.com/gocraft/work @@ -171,19 +172,19 @@ github.com/gogo/protobuf/proto github.com/gogo/protobuf/sortkeys # github.com/golang-migrate/migrate v3.3.0+incompatible github.com/golang-migrate/migrate -github.com/golang-migrate/migrate/database/postgres -github.com/golang-migrate/migrate/source/file github.com/golang-migrate/migrate/database +github.com/golang-migrate/migrate/database/postgres github.com/golang-migrate/migrate/source +github.com/golang-migrate/migrate/source/file # github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/glog # github.com/golang/protobuf v1.3.1 +github.com/golang/protobuf/proto github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/timestamp -github.com/golang/protobuf/proto # github.com/gomodule/redigo v2.0.0+incompatible -github.com/gomodule/redigo/redis github.com/gomodule/redigo/internal +github.com/gomodule/redigo/redis # github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 github.com/google/go-querystring/query # github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf @@ -211,9 +212,9 @@ github.com/lib/pq github.com/lib/pq/oid github.com/lib/pq/scram # github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e +github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter -github.com/mailru/easyjson/buffer # github.com/mattn/go-runewidth v0.0.4 github.com/mattn/go-runewidth # github.com/miekg/pkcs11 v0.0.0-20170220202408-7283ca79f35e @@ -229,8 +230,8 @@ github.com/olekukonko/tablewriter # github.com/opencontainers/go-digest v1.0.0-rc0 github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/image-spec/specs-go/v1 github.com/opencontainers/image-spec/specs-go +github.com/opencontainers/image-spec/specs-go/v1 # github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go github.com/opentracing/opentracing-go/log @@ -252,53 +253,53 @@ github.com/spf13/pflag # github.com/stretchr/objx v0.2.0 github.com/stretchr/objx # github.com/stretchr/testify v1.4.0 -github.com/stretchr/testify/mock -github.com/stretchr/testify/suite github.com/stretchr/testify/assert +github.com/stretchr/testify/mock github.com/stretchr/testify/require +github.com/stretchr/testify/suite # github.com/theupdateframework/notary v0.6.1 -github.com/theupdateframework/notary/tuf/data github.com/theupdateframework/notary github.com/theupdateframework/notary/client -github.com/theupdateframework/notary/trustpinning github.com/theupdateframework/notary/client/changelist github.com/theupdateframework/notary/cryptoservice github.com/theupdateframework/notary/storage github.com/theupdateframework/notary/trustmanager github.com/theupdateframework/notary/trustmanager/yubikey +github.com/theupdateframework/notary/trustpinning github.com/theupdateframework/notary/tuf +github.com/theupdateframework/notary/tuf/data github.com/theupdateframework/notary/tuf/signed github.com/theupdateframework/notary/tuf/utils github.com/theupdateframework/notary/tuf/validation # go.mongodb.org/mongo-driver v1.1.1 go.mongodb.org/mongo-driver/bson -go.mongodb.org/mongo-driver/bson/bsontype -go.mongodb.org/mongo-driver/bson/primitive go.mongodb.org/mongo-driver/bson/bsoncodec go.mongodb.org/mongo-driver/bson/bsonrw +go.mongodb.org/mongo-driver/bson/bsontype +go.mongodb.org/mongo-driver/bson/primitive go.mongodb.org/mongo-driver/x/bsonx/bsoncore # golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 -golang.org/x/crypto/pbkdf2 -golang.org/x/crypto/acme/autocert -golang.org/x/crypto/openpgp -golang.org/x/crypto/openpgp/clearsign -golang.org/x/crypto/openpgp/packet golang.org/x/crypto/acme -golang.org/x/crypto/ed25519 -golang.org/x/crypto/ssh/terminal -golang.org/x/crypto/openpgp/armor -golang.org/x/crypto/openpgp/errors -golang.org/x/crypto/openpgp/s2k +golang.org/x/crypto/acme/autocert golang.org/x/crypto/cast5 -golang.org/x/crypto/openpgp/elgamal +golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 +golang.org/x/crypto/openpgp +golang.org/x/crypto/openpgp/armor +golang.org/x/crypto/openpgp/clearsign +golang.org/x/crypto/openpgp/elgamal +golang.org/x/crypto/openpgp/errors +golang.org/x/crypto/openpgp/packet +golang.org/x/crypto/openpgp/s2k +golang.org/x/crypto/pbkdf2 +golang.org/x/crypto/ssh/terminal # golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 -golang.org/x/net/http2 -golang.org/x/net/idna +golang.org/x/net/context golang.org/x/net/context/ctxhttp golang.org/x/net/http/httpguts +golang.org/x/net/http2 golang.org/x/net/http2/hpack -golang.org/x/net/context +golang.org/x/net/idna # golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 golang.org/x/oauth2 golang.org/x/oauth2/clientcredentials @@ -308,21 +309,21 @@ golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.2 golang.org/x/text/secure/bidirule +golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -golang.org/x/text/transform golang.org/x/text/width # golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/time/rate # google.golang.org/appengine v1.4.0 google.golang.org/appengine/cloudsql -google.golang.org/appengine/urlfetch google.golang.org/appengine/internal -google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/base google.golang.org/appengine/internal/datastore google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api +google.golang.org/appengine/internal/urlfetch +google.golang.org/appengine/urlfetch # gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 gopkg.in/asn1-ber.v1 # gopkg.in/inf.v0 v0.9.1 @@ -338,13 +339,13 @@ gopkg.in/square/go-jose.v2/json # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190222213804-5cb15d344471 -k8s.io/api/authentication/v1beta1 k8s.io/api/admissionregistration/v1alpha1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/authentication/v1 +k8s.io/api/authentication/v1beta1 k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 k8s.io/api/autoscaling/v1 @@ -368,69 +369,69 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 # k8s.io/apimachinery v0.0.0-20180704011316-f534d624797b -k8s.io/apimachinery/pkg/apis/meta/v1 -k8s.io/apimachinery/pkg/runtime/schema -k8s.io/apimachinery/pkg/runtime/serializer -k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/runtime +k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/resource +k8s.io/apimachinery/pkg/apis/meta/v1 +k8s.io/apimachinery/pkg/apis/meta/v1/unstructured k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/conversion/queryparams k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/labels -k8s.io/apimachinery/pkg/selection -k8s.io/apimachinery/pkg/types -k8s.io/apimachinery/pkg/util/intstr -k8s.io/apimachinery/pkg/util/runtime -k8s.io/apimachinery/pkg/watch +k8s.io/apimachinery/pkg/runtime +k8s.io/apimachinery/pkg/runtime/schema +k8s.io/apimachinery/pkg/runtime/serializer k8s.io/apimachinery/pkg/runtime/serializer/json k8s.io/apimachinery/pkg/runtime/serializer/protobuf k8s.io/apimachinery/pkg/runtime/serializer/recognizer -k8s.io/apimachinery/pkg/runtime/serializer/versioning -k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/runtime/serializer/streaming -k8s.io/apimachinery/pkg/util/net -k8s.io/apimachinery/pkg/util/sets -k8s.io/apimachinery/pkg/conversion/queryparams -k8s.io/apimachinery/pkg/util/errors -k8s.io/apimachinery/pkg/util/json -k8s.io/apimachinery/third_party/forked/golang/reflect -k8s.io/apimachinery/pkg/util/validation -k8s.io/apimachinery/pkg/util/wait -k8s.io/apimachinery/pkg/util/framer -k8s.io/apimachinery/pkg/util/yaml -k8s.io/apimachinery/pkg/apis/meta/v1/unstructured -k8s.io/apimachinery/pkg/util/validation/field +k8s.io/apimachinery/pkg/runtime/serializer/versioning +k8s.io/apimachinery/pkg/selection +k8s.io/apimachinery/pkg/types k8s.io/apimachinery/pkg/util/clock +k8s.io/apimachinery/pkg/util/errors +k8s.io/apimachinery/pkg/util/framer +k8s.io/apimachinery/pkg/util/intstr +k8s.io/apimachinery/pkg/util/json +k8s.io/apimachinery/pkg/util/net +k8s.io/apimachinery/pkg/util/runtime +k8s.io/apimachinery/pkg/util/sets +k8s.io/apimachinery/pkg/util/validation +k8s.io/apimachinery/pkg/util/validation/field +k8s.io/apimachinery/pkg/util/wait +k8s.io/apimachinery/pkg/util/yaml +k8s.io/apimachinery/pkg/version +k8s.io/apimachinery/pkg/watch +k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/client-go v8.0.0+incompatible k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/rest +k8s.io/client-go/pkg/apis/clientauthentication +k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 +k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/pkg/version k8s.io/client-go/plugin/pkg/client/auth/exec +k8s.io/client-go/rest k8s.io/client-go/rest/watch k8s.io/client-go/tools/clientcmd/api k8s.io/client-go/tools/metrics k8s.io/client-go/transport k8s.io/client-go/util/cert -k8s.io/client-go/util/flowcontrol -k8s.io/client-go/pkg/apis/clientauthentication -k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 -k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/util/connrotation -k8s.io/client-go/util/integer +k8s.io/client-go/util/flowcontrol k8s.io/client-go/util/homedir +k8s.io/client-go/util/integer # k8s.io/helm v2.16.1+incompatible k8s.io/helm/cmd/helm/search k8s.io/helm/pkg/chartutil -k8s.io/helm/pkg/proto/hapi/chart -k8s.io/helm/pkg/repo -k8s.io/helm/pkg/ignore -k8s.io/helm/pkg/proto/hapi/version -k8s.io/helm/pkg/sympath -k8s.io/helm/pkg/version k8s.io/helm/pkg/getter -k8s.io/helm/pkg/provenance -k8s.io/helm/pkg/urlutil k8s.io/helm/pkg/helm/environment -k8s.io/helm/pkg/plugin -k8s.io/helm/pkg/tlsutil k8s.io/helm/pkg/helm/helmpath +k8s.io/helm/pkg/ignore +k8s.io/helm/pkg/plugin +k8s.io/helm/pkg/proto/hapi/chart +k8s.io/helm/pkg/proto/hapi/version +k8s.io/helm/pkg/provenance +k8s.io/helm/pkg/repo +k8s.io/helm/pkg/sympath +k8s.io/helm/pkg/tlsutil +k8s.io/helm/pkg/urlutil +k8s.io/helm/pkg/version