From f759c8fd646368d8bfd39c04fb74f75d1bd3d74d Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Sun, 19 Jan 2020 09:40:15 +0800 Subject: [PATCH] Implement the resolver for helm chart Implement the resolver for helm chart Signed-off-by: Wenkai Yin --- .../artifact/abstractor/abstractor_test.go | 4 + .../abstractor/resolver/chart/chart.go | 71 ++++++++++++ .../abstractor/resolver/chart/chart_test.go | 104 ++++++++++++++++++ .../abstractor/resolver/image/index.go | 4 + .../abstractor/resolver/image/index_test.go | 4 + .../abstractor/resolver/image/manifest_v1.go | 4 + .../resolver/image/manifest_v1_test.go | 4 + .../abstractor/resolver/image/manifest_v2.go | 4 + .../resolver/image/manifest_v2_test.go | 4 + .../abstractor/resolver/resolver_test.go | 4 + src/api/artifact/controller.go | 4 +- 11 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/api/artifact/abstractor/resolver/chart/chart_test.go diff --git a/src/api/artifact/abstractor/abstractor_test.go b/src/api/artifact/abstractor/abstractor_test.go index 0de9c609b..f5e33d6d4 100644 --- a/src/api/artifact/abstractor/abstractor_test.go +++ b/src/api/artifact/abstractor/abstractor_test.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/chart/chart.go b/src/api/artifact/abstractor/resolver/chart/chart.go index 89ed387fd..266fcf3ba 100644 --- a/src/api/artifact/abstractor/resolver/chart/chart.go +++ b/src/api/artifact/abstractor/resolver/chart/chart.go @@ -1,3 +1,7 @@ +// 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 @@ -9,3 +13,70 @@ // limitations under the License. package chart + +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/common/utils/log" + "github.com/goharbor/harbor/src/pkg/artifact" + "github.com/goharbor/harbor/src/pkg/repository" + v1 "github.com/opencontainers/image-spec/specs-go/v1" +) + +const ( + // ArtifactTypeChart defines the artifact type for helm chart + ArtifactTypeChart = "CHART" + // TODO import it from helm chart repository + mediaType = "application/vnd.cncf.helm.config.v1+json" +) + +func init() { + resolver := &resolver{ + repoMgr: repository.Mgr, + blobFetcher: blob.Fcher, + } + if err := resolv.Register(resolver, mediaType); err != nil { + log.Errorf("failed to register resolver for artifact %s: %v", resolver.ArtifactType(), err) + return + } +} + +type resolver struct { + repoMgr repository.Manager + blobFetcher blob.Fetcher +} + +func (r *resolver) ArtifactType() string { + return ArtifactTypeChart +} + +func (r *resolver) Resolve(ctx context.Context, manifest []byte, artifact *artifact.Artifact) error { + repository, err := r.repoMgr.Get(ctx, artifact.RepositoryID) + if err != nil { + return err + } + m := &v1.Manifest{} + if err := json.Unmarshal(manifest, m); err != nil { + return err + } + digest := m.Config.Digest.String() + layer, err := r.blobFetcher.FetchLayer(repository.Name, digest) + if err != nil { + return err + } + // TODO should we abstract all values? + metadata := map[string]interface{}{} + if err := json.Unmarshal(layer, &metadata); err != nil { + return err + } + if artifact.ExtraAttrs == nil { + artifact.ExtraAttrs = map[string]interface{}{} + } + for k, v := range metadata { + artifact.ExtraAttrs[k] = v + } + + return nil +} diff --git a/src/api/artifact/abstractor/resolver/chart/chart_test.go b/src/api/artifact/abstractor/resolver/chart/chart_test.go new file mode 100644 index 000000000..6171084b4 --- /dev/null +++ b/src/api/artifact/abstractor/resolver/chart/chart_test.go @@ -0,0 +1,104 @@ +// 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 chart + +import ( + "github.com/goharbor/harbor/src/common/models" + "github.com/goharbor/harbor/src/pkg/artifact" + htesting "github.com/goharbor/harbor/src/testing" + "github.com/goharbor/harbor/src/testing/api/artifact/abstractor/blob" + "github.com/stretchr/testify/suite" + "testing" +) + +type resolverTestSuite struct { + suite.Suite + resolver *resolver + repoMgr *htesting.FakeRepositoryManager + blobFetcher *blob.FakeFetcher +} + +func (r *resolverTestSuite) SetupTest() { + r.repoMgr = &htesting.FakeRepositoryManager{} + r.blobFetcher = &blob.FakeFetcher{} + r.resolver = &resolver{ + repoMgr: r.repoMgr, + blobFetcher: r.blobFetcher, + } + +} + +func (r *resolverTestSuite) TestArtifactType() { + r.Assert().Equal(ArtifactTypeChart, r.resolver.ArtifactType()) +} + +func (r *resolverTestSuite) TestResolve() { + content := `{ + "schemaVersion": 2, + "config": { + "mediaType": "application/vnd.cncf.helm.config.v1+json", + "digest": "sha256:c87983b066bd08616c6135832363ed42784d66386814694b237f5608213be325", + "size": 542 + }, + "layers": [ + { + "mediaType": "application/vnd.cncf.helm.chart.content.layer.v1+tar", + "digest": "sha256:0f8c0650d55f5e00d11d7462381c340454a3b9e517e15a0187011dc305690541", + "size": 28776 + } + ] +}` + config := `{ + "name": "harbor", + "home": "https://goharbor.io", + "sources": [ + "https://github.com/goharbor/harbor", + "https://github.com/goharbor/harbor-helm" + ], + "version": "1.1.2", + "description": "An open source trusted cloud native registry that stores, signs, and scans content", + "keywords": [ + "docker", + "registry", + "harbor" + ], + "maintainers": [ + { + "name": "Jesse Hu", + "email": "huh@vmware.com" + }, + { + "name": "paulczar", + "email": "username.taken@gmail.com" + } + ], + "icon": "https://raw.githubusercontent.com/goharbor/harbor/master/docs/img/harbor_logo.png", + "apiVersion": "v1", + "appVersion": "1.8.2" +}` + artifact := &artifact.Artifact{} + r.repoMgr.On("Get").Return(&models.RepoRecord{}, nil) + r.blobFetcher.On("FetchLayer").Return([]byte(config), nil) + err := r.resolver.Resolve(nil, []byte(content), artifact) + r.Require().Nil(err) + r.repoMgr.AssertExpectations(r.T()) + r.blobFetcher.AssertExpectations(r.T()) + r.Assert().Equal("1.1.2", artifact.ExtraAttrs["version"].(string)) + r.Assert().Equal("1.8.2", artifact.ExtraAttrs["appVersion"].(string)) +} + +func TestResolverTestSuite(t *testing.T) { + suite.Run(t, &resolverTestSuite{}) +} diff --git a/src/api/artifact/abstractor/resolver/image/index.go b/src/api/artifact/abstractor/resolver/image/index.go index b1cc5d454..54b2a6288 100644 --- a/src/api/artifact/abstractor/resolver/image/index.go +++ b/src/api/artifact/abstractor/resolver/image/index.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/image/index_test.go b/src/api/artifact/abstractor/resolver/image/index_test.go index 151e3244b..aae67dc30 100644 --- a/src/api/artifact/abstractor/resolver/image/index_test.go +++ b/src/api/artifact/abstractor/resolver/image/index_test.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/image/manifest_v1.go b/src/api/artifact/abstractor/resolver/image/manifest_v1.go index 76cc4d594..f7fa9527c 100644 --- a/src/api/artifact/abstractor/resolver/image/manifest_v1.go +++ b/src/api/artifact/abstractor/resolver/image/manifest_v1.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/image/manifest_v1_test.go b/src/api/artifact/abstractor/resolver/image/manifest_v1_test.go index 8fdcce10c..eb4aec8ac 100644 --- a/src/api/artifact/abstractor/resolver/image/manifest_v1_test.go +++ b/src/api/artifact/abstractor/resolver/image/manifest_v1_test.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/image/manifest_v2.go b/src/api/artifact/abstractor/resolver/image/manifest_v2.go index 6a55bd798..8964d9ae6 100644 --- a/src/api/artifact/abstractor/resolver/image/manifest_v2.go +++ b/src/api/artifact/abstractor/resolver/image/manifest_v2.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/image/manifest_v2_test.go b/src/api/artifact/abstractor/resolver/image/manifest_v2_test.go index 898926b9f..41c48a9b9 100644 --- a/src/api/artifact/abstractor/resolver/image/manifest_v2_test.go +++ b/src/api/artifact/abstractor/resolver/image/manifest_v2_test.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/abstractor/resolver/resolver_test.go b/src/api/artifact/abstractor/resolver/resolver_test.go index 457064551..8d417645a 100644 --- a/src/api/artifact/abstractor/resolver/resolver_test.go +++ b/src/api/artifact/abstractor/resolver/resolver_test.go @@ -1,3 +1,7 @@ +// 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 diff --git a/src/api/artifact/controller.go b/src/api/artifact/controller.go index 6c4082c5d..d93ddcfbe 100644 --- a/src/api/artifact/controller.go +++ b/src/api/artifact/controller.go @@ -18,8 +18,10 @@ import ( "context" "fmt" "github.com/goharbor/harbor/src/api/artifact/abstractor" - // registry image resolvers + // register 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" "github.com/goharbor/harbor/src/common/utils/log" ierror "github.com/goharbor/harbor/src/internal/error" "github.com/goharbor/harbor/src/pkg/artifact"