From efd9632e96079f0f9a9f5783804c7c3cd0708f6a Mon Sep 17 00:00:00 2001 From: MinerYang Date: Fri, 8 Jul 2022 09:56:10 +0800 Subject: [PATCH] add nydus middleware (#17126) Signed-off-by: yminer remove comments Signed-off-by: yminer update ut manifest Signed-off-by: yminer modify comment manifest Signed-off-by: yminer updtae ut testcase Signed-off-by: yminer fixwhitespace lint Signed-off-by: yminer update isNydus judgement && define annotation var Signed-off-by: yminer whitespace lint Signed-off-by: yminer --- icons/nydus.png | Bin 0 -> 23342 bytes src/controller/icon/controller.go | 4 + src/core/main.go | 1 + src/lib/icon/const.go | 1 + src/pkg/accessory/manager.go | 4 +- src/pkg/accessory/manager_test.go | 4 +- src/pkg/accessory/model/accessory.go | 6 +- src/pkg/accessory/model/nydus/nydus.go | 46 +++++ src/pkg/accessory/model/nydus/nydus_test.go | 70 +++++++ src/server/middleware/nydus/nydus.go | 149 ++++++++++++++ src/server/middleware/nydus/nydus_test.go | 207 ++++++++++++++++++++ src/server/registry/route.go | 2 + 12 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 icons/nydus.png create mode 100644 src/pkg/accessory/model/nydus/nydus.go create mode 100644 src/pkg/accessory/model/nydus/nydus_test.go create mode 100644 src/server/middleware/nydus/nydus.go create mode 100644 src/server/middleware/nydus/nydus_test.go diff --git a/icons/nydus.png b/icons/nydus.png new file mode 100644 index 0000000000000000000000000000000000000000..9404942465b57d5ea319270b8986b7133b676f31 GIT binary patch literal 23342 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 eYo*U+oBs!iRf_gzL%*N^0000WQ( literal 0 HcmV?d00001 diff --git a/src/controller/icon/controller.go b/src/controller/icon/controller.go index c06c2b111..34ac9eea8 100644 --- a/src/controller/icon/controller.go +++ b/src/controller/icon/controller.go @@ -56,6 +56,10 @@ var ( path: "./icons/cosign.png", resize: false, }, + icon.DigestOfIconAccNydus: { + path: "./icons/nydus.png", + resize: false, + }, icon.DigestOfIconDefault: { path: "./icons/default.png", resize: true, diff --git a/src/core/main.go b/src/core/main.go index 70ffafde5..bcd2e5d7a 100755 --- a/src/core/main.go +++ b/src/core/main.go @@ -55,6 +55,7 @@ import ( "github.com/goharbor/harbor/src/migration" _ "github.com/goharbor/harbor/src/pkg/accessory/model/base" _ "github.com/goharbor/harbor/src/pkg/accessory/model/cosign" + _ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus" "github.com/goharbor/harbor/src/pkg/audit" dbCfg "github.com/goharbor/harbor/src/pkg/config/db" _ "github.com/goharbor/harbor/src/pkg/config/inmemory" diff --git a/src/lib/icon/const.go b/src/lib/icon/const.go index 0c24b632a..0c3f1c525 100644 --- a/src/lib/icon/const.go +++ b/src/lib/icon/const.go @@ -10,4 +10,5 @@ const ( // ToDo add the accessories images DigestOfIconAccDefault = "" DigestOfIconAccCosign = "sha256:20401d5b3a0f6dbc607c8d732eb08471af4ae6b19811a4efce8c6a724aed2882" + DigestOfIconAccNydus = "sha256:dfcb6617cd9c144358dc1b305b87bbe34f0b619f1e329116e6aee2e41f2e34cf" ) diff --git a/src/pkg/accessory/manager.go b/src/pkg/accessory/manager.go index a9952bf17..c0f22a916 100644 --- a/src/pkg/accessory/manager.go +++ b/src/pkg/accessory/manager.go @@ -16,6 +16,7 @@ package accessory import ( "context" + "github.com/goharbor/harbor/src/lib/errors" "github.com/goharbor/harbor/src/lib/icon" "github.com/goharbor/harbor/src/lib/q" @@ -29,7 +30,8 @@ var ( // icon digests for each known type defaultIcons = map[string]string{ - model.TypeCosignSignature: icon.DigestOfIconAccCosign, + model.TypeCosignSignature: icon.DigestOfIconAccCosign, + model.TypeNydusAccelerator: icon.DigestOfIconAccNydus, } ) diff --git a/src/pkg/accessory/manager_test.go b/src/pkg/accessory/manager_test.go index 1151d0c0d..67b0971e7 100644 --- a/src/pkg/accessory/manager_test.go +++ b/src/pkg/accessory/manager_test.go @@ -15,15 +15,17 @@ package accessory import ( + "testing" + "github.com/goharbor/harbor/src/lib/q" "github.com/goharbor/harbor/src/pkg/accessory/dao" "github.com/goharbor/harbor/src/pkg/accessory/model" _ "github.com/goharbor/harbor/src/pkg/accessory/model/base" _ "github.com/goharbor/harbor/src/pkg/accessory/model/cosign" + _ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus" "github.com/goharbor/harbor/src/testing/mock" testingdao "github.com/goharbor/harbor/src/testing/pkg/accessory/dao" "github.com/stretchr/testify/suite" - "testing" ) type managerTestSuite struct { diff --git a/src/pkg/accessory/model/accessory.go b/src/pkg/accessory/model/accessory.go index 033d93157..f560774ab 100644 --- a/src/pkg/accessory/model/accessory.go +++ b/src/pkg/accessory/model/accessory.go @@ -17,9 +17,10 @@ package model import ( "encoding/json" "fmt" - "github.com/goharbor/harbor/src/lib/errors" "sync" "time" + + "github.com/goharbor/harbor/src/lib/errors" ) const ( @@ -63,6 +64,9 @@ const ( TypeNone = "base" // TypeCosignSignature ... TypeCosignSignature = "signature.cosign" + + // TypeNydusAccelerator ... + TypeNydusAccelerator = "accelerator.nydus" ) // AccessoryData ... diff --git a/src/pkg/accessory/model/nydus/nydus.go b/src/pkg/accessory/model/nydus/nydus.go new file mode 100644 index 000000000..48507e3f1 --- /dev/null +++ b/src/pkg/accessory/model/nydus/nydus.go @@ -0,0 +1,46 @@ +// 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 nydus + +import ( + "github.com/goharbor/harbor/src/pkg/accessory/model" + "github.com/goharbor/harbor/src/pkg/accessory/model/base" +) + +// Nydus accelerator model +type Nydus struct { + base.Default +} + +// Kind gives the reference type of nydus accelerator. +func (ny *Nydus) Kind() string { + return model.RefHard +} + +// IsHard ... +func (ny *Nydus) IsHard() bool { + return true +} + +// New returns nydus accelerator +func New(data model.AccessoryData) model.Accessory { + return &Nydus{base.Default{ + Data: data, + }} +} + +func init() { + model.Register(model.TypeNydusAccelerator, New) +} diff --git a/src/pkg/accessory/model/nydus/nydus_test.go b/src/pkg/accessory/model/nydus/nydus_test.go new file mode 100644 index 000000000..8397241c9 --- /dev/null +++ b/src/pkg/accessory/model/nydus/nydus_test.go @@ -0,0 +1,70 @@ +package nydus + +import ( + "testing" + + "github.com/goharbor/harbor/src/pkg/accessory/model" + htesting "github.com/goharbor/harbor/src/testing" + "github.com/stretchr/testify/suite" +) + +type NydusTestSuite struct { + htesting.Suite + accessory model.Accessory + digest string +} + +func (suite *NydusTestSuite) SetupSuite() { + suite.digest = suite.DigestString() + suite.accessory, _ = model.New(model.TypeNydusAccelerator, + model.AccessoryData{ + ArtifactID: 1, + SubArtifactID: 2, + Size: 4321, + Digest: suite.digest, + }) +} + +func (suite *NydusTestSuite) TestGetID() { + suite.Equal(int64(0), suite.accessory.GetData().ID) +} + +func (suite *NydusTestSuite) TestGetArtID() { + suite.Equal(int64(1), suite.accessory.GetData().ArtifactID) +} + +func (suite *NydusTestSuite) TestSubGetArtID() { + suite.Equal(int64(2), suite.accessory.GetData().SubArtifactID) +} + +func (suite *NydusTestSuite) TestSubGetSize() { + suite.Equal(int64(4321), suite.accessory.GetData().Size) +} + +func (suite *NydusTestSuite) TestSubGetDigest() { + suite.Equal(suite.digest, suite.accessory.GetData().Digest) +} + +func (suite *NydusTestSuite) TestSubGetType() { + suite.Equal(model.TypeNydusAccelerator, suite.accessory.GetData().Type) +} + +func (suite *NydusTestSuite) TestSubGetRefType() { + suite.Equal(model.RefHard, suite.accessory.Kind()) +} + +func (suite *NydusTestSuite) TestIsSoft() { + suite.False(suite.accessory.IsSoft()) +} + +func (suite *NydusTestSuite) TestIsHard() { + suite.True(suite.accessory.IsHard()) +} + +func (suite *NydusTestSuite) TestDisplay() { + suite.False(suite.accessory.Display()) +} + +func TestCacheTestSuite(t *testing.T) { + suite.Run(t, new(NydusTestSuite)) +} diff --git a/src/server/middleware/nydus/nydus.go b/src/server/middleware/nydus/nydus.go new file mode 100644 index 000000000..9f0b00463 --- /dev/null +++ b/src/server/middleware/nydus/nydus.go @@ -0,0 +1,149 @@ +package nydus + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + + "github.com/goharbor/harbor/src/controller/artifact" + "github.com/goharbor/harbor/src/lib" + "github.com/goharbor/harbor/src/lib/errors" + "github.com/goharbor/harbor/src/lib/log" + "github.com/goharbor/harbor/src/lib/orm" + "github.com/goharbor/harbor/src/pkg/accessory" + "github.com/goharbor/harbor/src/pkg/accessory/model" + "github.com/goharbor/harbor/src/pkg/distribution" + "github.com/goharbor/harbor/src/server/middleware" + v1 "github.com/opencontainers/image-spec/specs-go/v1" +) + +var ( + // nydus boostrap layer annotation + nydusBoostrapAnnotation = "containerd.io/snapshot/nydus-bootstrap" + + // source artifact digest annotation + sourceDigestAnnotation = "io.goharbor.artifact.v1alpha1.acceleration.source.digest" +) + +// NydusAcceleratorMiddleware middleware to record the linkeage of artifact and its accessory +/* +/v2/library/hello-world/manifests/sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 +{ + "schemaVersion": 2, + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "digest": "sha256:f7d0778a3c468a5203e95a9efd4d67ecef0d2a04866bb3320f0d5d637812aaee", + "size": 466 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.nydus.blob.v1", + "digest": "sha256:fd9923a8e2bdc53747dbba3311be876a1deff4658785830e6030c5a8287acf74 ", + "size": 3011, + "annotations": { + "containerd.io/snapshot/nydus-blob": "true" + } + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:d49bf6d7db9dac935b99d4c2c846b0d280f550aae62012f888d5a6e3ca59a589", + "size": 459, + "annotations": { + "containerd.io/snapshot/nydus-blob-ids": "[\"fd9923a8e2bdc53747dbba3311be876a1deff4658785830e6030c5a8287acf74\"]", + "containerd.io/snapshot/nydus-bootstrap": "true", + "containerd.io/snapshot/nydus-rafs-version": "5" + } + } + ], + "annotations": { + "io.goharbor.artifact.v1alpha1.acceleration.driver.name":"nydus", + "io.goharbor.artifact.v1alpha1.acceleration.driver.version":"5", + "io.goharbor.artifact.v1alpha1.acceleration.source.digest":"sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4" + } +} + +*/ +func AcceleratorMiddleware() func(http.Handler) http.Handler { + return middleware.AfterResponse(func(w http.ResponseWriter, r *http.Request, statusCode int) error { + if statusCode != http.StatusCreated { + return nil + } + + log.Debug("Start NydusAccelerator Middleware") + ctx := r.Context() + logger := log.G(ctx).WithFields(log.Fields{"middleware": "nydus"}) + + none := lib.ArtifactInfo{} + info := lib.GetArtifactInfo(ctx) + if info == none { + return errors.New("artifactinfo middleware required before this middleware").WithCode(errors.NotFoundCode) + } + if info.Tag == "" { + return nil + } + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + return err + } + + contentType := r.Header.Get("Content-Type") + manifest, desc, err := distribution.UnmarshalManifest(contentType, body) + if err != nil { + logger.Errorf("unmarshal manifest failed, error: %v", err) + return err + } + + var isNydus bool + for _, descriptor := range manifest.References() { + annotationMap := descriptor.Annotations + if _, ok := annotationMap[nydusBoostrapAnnotation]; ok { + isNydus = true + break + } + } + log.Debug("isNydus: ", isNydus) + + _, payload, err := manifest.Payload() + if err != nil { + return err + } + mf := &v1.Manifest{} + if err := json.Unmarshal(payload, mf); err != nil { + return err + } + + if isNydus { + subjectArt, err := artifact.Ctl.GetByReference(ctx, info.Repository, mf.Annotations[sourceDigestAnnotation], nil) + if err != nil { + logger.Errorf("failed to get subject artifact: %s, error: %v", info.Tag, err) + return err + } + art, err := artifact.Ctl.GetByReference(ctx, info.Repository, desc.Digest.String(), nil) + if err != nil { + logger.Errorf("failed to get nydus accel accelerator: %s, error: %v", desc.Digest.String(), err) + return err + } + + if err := orm.WithTransaction(func(ctx context.Context) error { + id, err := accessory.Mgr.Create(ctx, model.AccessoryData{ + ArtifactID: art.ID, + SubArtifactID: subjectArt.ID, + Size: desc.Size, + Digest: desc.Digest.String(), + Type: model.TypeNydusAccelerator, + }) + log.Debug("accessory id:", id) + return err + })(orm.SetTransactionOpNameToContext(ctx, "tx-create-nydus-accessory")); err != nil { + if !errors.IsConflictErr(err) { + logger.Errorf("failed to create nydus accelerator artifact: %s, error: %v", desc.Digest.String(), err) + return err + } + } + } + + return nil + }) +} diff --git a/src/server/middleware/nydus/nydus_test.go b/src/server/middleware/nydus/nydus_test.go new file mode 100644 index 000000000..07a02bda9 --- /dev/null +++ b/src/server/middleware/nydus/nydus_test.go @@ -0,0 +1,207 @@ +package nydus + +import ( + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/goharbor/harbor/src/controller/repository" + "github.com/goharbor/harbor/src/lib" + "github.com/goharbor/harbor/src/lib/q" + "github.com/goharbor/harbor/src/pkg" + "github.com/goharbor/harbor/src/pkg/accessory" + "github.com/goharbor/harbor/src/pkg/accessory/model" + accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model" + _ "github.com/goharbor/harbor/src/pkg/accessory/model/base" + _ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus" + "github.com/goharbor/harbor/src/pkg/artifact" + "github.com/goharbor/harbor/src/pkg/distribution" + htesting "github.com/goharbor/harbor/src/testing" + "github.com/stretchr/testify/suite" +) + +type MiddlewareTestSuite struct { + htesting.Suite +} + +func (suite *MiddlewareTestSuite) SetupTest() { + suite.Suite.SetupSuite() +} + +func (suite *MiddlewareTestSuite) TearDownTest() { +} + +func (suite *MiddlewareTestSuite) prepare(name, ref string) (distribution.Manifest, distribution.Descriptor, *http.Request) { + body := fmt.Sprintf(` + { + "schemaVersion": 2, + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "digest": "sha256:f7d0778a3c468a5203e95a9efd4d67ecef0d2a04866bb3320f0d5d637812aaee", + "size": 466 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.nydus.blob.v1", + "digest": "sha256:fd9923a8e2bdc53747dbba3311be876a1deff4658785830e6030c5a8287acf74 ", + "size": 3011, + "annotations": { + "containerd.io/snapshot/nydus-blob": "true" + } + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:d49bf6d7db9dac935b99d4c2c846b0d280f550aae62012f888d5a6e3ca59a589", + "size": 459, + "annotations": { + "containerd.io/snapshot/nydus-blob-ids": "[\"fd9923a8e2bdc53747dbba3311be876a1deff4658785830e6030c5a8287acf74\"]", + "containerd.io/snapshot/nydus-bootstrap": "true", + "containerd.io/snapshot/nydus-rafs-version": "5" + } + } + ], + "annotations": { + "io.goharbor.artifact.v1alpha1.acceleration.driver.name":"nydus", + "io.goharbor.artifact.v1alpha1.acceleration.driver.version":"5", + "io.goharbor.artifact.v1alpha1.acceleration.source.digest":"sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4" + } + } + `) + + manifest, descriptor, err := distribution.UnmarshalManifest("application/vnd.oci.image.manifest.v1+json", []byte(body)) + suite.Nil(err) + + req := suite.NewRequest(http.MethodPut, fmt.Sprintf("/v2/%s/manifests/%s", name, ref), strings.NewReader(body)) + req.Header.Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + info := lib.ArtifactInfo{ + Repository: name, + Reference: ref, + Tag: "latest-nydus", + Digest: descriptor.Digest.String(), + } + + return manifest, descriptor, req.WithContext(lib.WithArtifactInfo(req.Context(), info)) +} + +func (suite *MiddlewareTestSuite) addArt(pid, repositoryID int64, repositoryName, dgt string) int64 { + af := &artifact.Artifact{ + Type: "Docker-Image", + ProjectID: pid, + RepositoryID: repositoryID, + RepositoryName: repositoryName, + Digest: dgt, + Size: 1024, + PushTime: time.Now(), + PullTime: time.Now(), + } + afid, err := pkg.ArtifactMgr.Create(suite.Context(), af) + suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) + return afid +} + +func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryName, dgt, accdgt string) int64 { + subaf := &artifact.Artifact{ + Type: "Docker-Image", + ProjectID: pid, + RepositoryID: repositoryID, + RepositoryName: repositoryName, + Digest: dgt, + Size: 1024, + PushTime: time.Now(), + PullTime: time.Now(), + } + subafid, err := pkg.ArtifactMgr.Create(suite.Context(), subaf) + suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) + + af := &artifact.Artifact{ + Type: "Nydus", + ProjectID: pid, + RepositoryID: repositoryID, + RepositoryName: repositoryName, + Digest: accdgt, + Size: 1024, + PushTime: time.Now(), + PullTime: time.Now(), + } + afid, err := pkg.ArtifactMgr.Create(suite.Context(), af) + suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) + + accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{ + ID: 1, + ArtifactID: afid, + SubArtifactID: subafid, + Digest: accdgt, + Type: accessorymodel.TypeNydusAccelerator, + }) + suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID)) + return accid +} + +func (suite *MiddlewareTestSuite) TestNydusAccelerator() { + suite.WithProject(func(projectID int64, projectName string) { + name := fmt.Sprintf("%s/hello-world", projectName) + subArtDigest := "sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4" + _, descriptor, req := suite.prepare(name, subArtDigest) + + // create sunjectArtifact repository + _, repoId, err := repository.Ctl.Ensure(suite.Context(), name) + suite.Nil(err) + + // add subject artifact + subjectArtID := suite.addArt(projectID, repoId, name, subArtDigest) + + // add nydus artifact + artID := suite.addArt(projectID, repoId, name, descriptor.Digest.String()) + suite.Nil(err) + + res := httptest.NewRecorder() + next := suite.NextHandler(http.StatusCreated, map[string]string{"Docker-Content-Digest": descriptor.Digest.String()}) + AcceleratorMiddleware()(next).ServeHTTP(res, req) + suite.Equal(http.StatusCreated, res.Code) + + accs, _ := accessory.Mgr.List(suite.Context(), &q.Query{ + Keywords: map[string]interface{}{ + "SubjectArtifactID": subjectArtID, + }, + }) + suite.Equal(1, len(accs)) + suite.Equal(subjectArtID, accs[0].GetData().SubArtifactID) + suite.Equal(artID, accs[0].GetData().ArtifactID) + suite.True(accs[0].IsHard()) + suite.Equal(model.TypeNydusAccelerator, accs[0].GetData().Type) + }) +} + +func (suite *MiddlewareTestSuite) TestNydusAcceleratorDup() { + suite.WithProject(func(projectID int64, projectName string) { + name := fmt.Sprintf("%s/hello-world", projectName) + subArtDigest := "sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4" + _, descriptor, req := suite.prepare(name, subArtDigest) + + _, repoId, err := repository.Ctl.Ensure(suite.Context(), name) + suite.Nil(err) + accID := suite.addArtAcc(projectID, repoId, name, subArtDigest, descriptor.Digest.String()) + + res := httptest.NewRecorder() + next := suite.NextHandler(http.StatusCreated, map[string]string{"Docker-Content-Digest": descriptor.Digest.String()}) + AcceleratorMiddleware()(next).ServeHTTP(res, req) + suite.Equal(http.StatusCreated, res.Code) + + accs, _ := accessory.Mgr.List(suite.Context(), &q.Query{ + Keywords: map[string]interface{}{ + "ID": accID, + }, + }) + suite.Equal(1, len(accs)) + suite.Equal(descriptor.Digest.String(), accs[0].GetData().Digest) + suite.True(accs[0].IsHard()) + suite.Equal(model.TypeNydusAccelerator, accs[0].GetData().Type) + }) +} + +func TestMiddlewareTestSuite(t *testing.T) { + suite.Run(t, &MiddlewareTestSuite{}) +} diff --git a/src/server/registry/route.go b/src/server/registry/route.go index 44fd02fba..3da9fec0b 100644 --- a/src/server/registry/route.go +++ b/src/server/registry/route.go @@ -22,6 +22,7 @@ import ( "github.com/goharbor/harbor/src/server/middleware/cosign" "github.com/goharbor/harbor/src/server/middleware/immutable" "github.com/goharbor/harbor/src/server/middleware/metric" + "github.com/goharbor/harbor/src/server/middleware/nydus" "github.com/goharbor/harbor/src/server/middleware/quota" "github.com/goharbor/harbor/src/server/middleware/repoproxy" "github.com/goharbor/harbor/src/server/middleware/v2auth" @@ -80,6 +81,7 @@ func RegisterRoutes() { Middleware(immutable.Middleware()). Middleware(quota.PutManifestMiddleware()). Middleware(cosign.SignatureMiddleware()). + Middleware(nydus.AcceleratorMiddleware()). Middleware(blob.PutManifestMiddleware()). HandlerFunc(putManifest) // blob head