mirror of
https://github.com/goharbor/harbor.git
synced 2024-09-12 05:58:23 +02:00
Merge pull request #7275 from ywk253100/190402_delete_image
Call Harbor API to delete the images in Harbor adapter
This commit is contained in:
commit
382558167c
@ -37,10 +37,10 @@ import (
|
||||
"github.com/goharbor/harbor/src/common/utils/notary"
|
||||
"github.com/goharbor/harbor/src/common/utils/registry"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
"github.com/goharbor/harbor/src/core/notifier"
|
||||
coreutils "github.com/goharbor/harbor/src/core/utils"
|
||||
"github.com/goharbor/harbor/src/replication/event/notification"
|
||||
"github.com/goharbor/harbor/src/replication/event/topic"
|
||||
"github.com/goharbor/harbor/src/replication/ng"
|
||||
"github.com/goharbor/harbor/src/replication/ng/event"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
)
|
||||
|
||||
// RepositoryAPI handles request to /api/repositories /api/repositories/tags /api/repositories/manifests, the parm has to be put
|
||||
@ -328,15 +328,21 @@ func (ra *RepositoryAPI) Delete() {
|
||||
log.Infof("delete tag: %s:%s", repoName, t)
|
||||
|
||||
go func(tag string) {
|
||||
image := repoName + ":" + tag
|
||||
err := notifier.Publish(topic.ReplicationEventTopicOnDeletion, notification.OnDeletionNotification{
|
||||
Image: image,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("failed to publish on deletion topic for resource %s: %v", image, err)
|
||||
return
|
||||
e := &event.Event{
|
||||
Type: event.EventTypeImagePush,
|
||||
Resource: &model.Resource{
|
||||
Type: model.ResourceTypeRepository,
|
||||
Metadata: &model.ResourceMetadata{
|
||||
Name: repoName,
|
||||
Namespace: projectName,
|
||||
Vtags: []string{tag},
|
||||
},
|
||||
Deleted: true,
|
||||
},
|
||||
}
|
||||
if err := ng.EventHandler.Handle(e); err != nil {
|
||||
log.Errorf("failed to handle event: %v", err)
|
||||
}
|
||||
log.Debugf("the on deletion topic for resource %s published", image)
|
||||
}(t)
|
||||
|
||||
go func(tag string) {
|
||||
|
@ -66,3 +66,10 @@ func (a *adapter) FetchImages(namespaces []string, filters []*model.Filter) ([]*
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// override the default implementation from the default image registry
|
||||
// by calling Harbor API directly
|
||||
func (a *adapter) DeleteManifest(repository, reference string) error {
|
||||
url := fmt.Sprintf("%s/api/repositories/%s/tags/%s", a.coreServiceURL, repository, reference)
|
||||
return a.client.Delete(url)
|
||||
}
|
||||
|
@ -22,15 +22,15 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/goharbor/harbor/src/replication/ng/util"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/goharbor/harbor/src/common/http/modifier"
|
||||
common_http_auth "github.com/goharbor/harbor/src/common/http/modifier/auth"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
registry_pkg "github.com/goharbor/harbor/src/common/utils/registry"
|
||||
"github.com/goharbor/harbor/src/common/utils/registry/auth"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
"github.com/goharbor/harbor/src/replication/ng/util"
|
||||
)
|
||||
|
||||
// const definition
|
||||
@ -45,7 +45,8 @@ type ImageRegistry interface {
|
||||
ManifestExist(repository, reference string) (exist bool, digest string, err error)
|
||||
PullManifest(repository, reference string, accepttedMediaTypes []string) (manifest distribution.Manifest, digest string, err error)
|
||||
PushManifest(repository, reference, mediaType string, payload []byte) error
|
||||
DeleteManifest(repository, digest string) error
|
||||
// the "reference" can be "tag" or "digest", the function needs to handle both
|
||||
DeleteManifest(repository, reference string) error
|
||||
BlobExist(repository, digest string) (exist bool, err error)
|
||||
PullBlob(repository, digest string) (size int64, blob io.ReadCloser, err error)
|
||||
PushBlob(repository, digest string, size int64, blob io.Reader) error
|
||||
@ -179,15 +180,24 @@ func (d *DefaultImageRegistry) PushManifest(repository, reference, mediaType str
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO monitor the registry API request in core directly rather than using
|
||||
// the web hook
|
||||
|
||||
// DeleteManifest ...
|
||||
func (d *DefaultImageRegistry) DeleteManifest(repository, digest string) error {
|
||||
func (d *DefaultImageRegistry) DeleteManifest(repository, reference string) error {
|
||||
client, err := d.getClient(repository)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
digest := reference
|
||||
if !isDigest(digest) {
|
||||
dgt, exist, err := client.ManifestExist(reference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
log.Debugf("the manifest of %s:%s doesn't exist", repository, reference)
|
||||
return nil
|
||||
}
|
||||
digest = dgt
|
||||
}
|
||||
return client.DeleteManifest(digest)
|
||||
}
|
||||
|
||||
@ -217,3 +227,7 @@ func (d *DefaultImageRegistry) PushBlob(repository, digest string, size int64, b
|
||||
}
|
||||
return client.PushBlob(digest, size, blob)
|
||||
}
|
||||
|
||||
func isDigest(str string) bool {
|
||||
return strings.Contains(str, ":")
|
||||
}
|
||||
|
46
src/replication/ng/adapter/image_registry_test.go
Normal file
46
src/replication/ng/adapter/image_registry_test.go
Normal file
@ -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 adapter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TODO add UT
|
||||
|
||||
func TestIsDigest(t *testing.T) {
|
||||
cases := []struct {
|
||||
str string
|
||||
isDigest bool
|
||||
}{
|
||||
{
|
||||
str: "",
|
||||
isDigest: false,
|
||||
},
|
||||
{
|
||||
str: "latest",
|
||||
isDigest: false,
|
||||
},
|
||||
{
|
||||
str: "sha256:fea8895f450959fa676bcc1df0611ea93823a735a01205fd8622846041d0c7cf",
|
||||
isDigest: true,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.isDigest, isDigest(c.str))
|
||||
}
|
||||
}
|
@ -278,10 +278,9 @@ func (t *transfer) delete(repo *repository) error {
|
||||
return jobStoppedErr
|
||||
}
|
||||
|
||||
digests := map[string]struct{}{}
|
||||
repository := repo.repository
|
||||
for _, tag := range repo.tags {
|
||||
exist, digest, err := t.dst.ManifestExist(repository, tag)
|
||||
exist, _, err := t.dst.ManifestExist(repository, tag)
|
||||
if err != nil {
|
||||
t.logger.Errorf("failed to check the existence of the manifest of image %s:%s on the destination registry: %v",
|
||||
repository, tag, err)
|
||||
@ -292,18 +291,12 @@ func (t *transfer) delete(repo *repository) error {
|
||||
repository, tag)
|
||||
continue
|
||||
}
|
||||
t.logger.Infof("the digest of image %s:%s is %s", repository, tag, digest)
|
||||
if _, exist := digests[digest]; !exist {
|
||||
digests[digest] = struct{}{}
|
||||
}
|
||||
}
|
||||
for digest := range digests {
|
||||
if err := t.dst.DeleteManifest(repository, digest); err != nil {
|
||||
if err := t.dst.DeleteManifest(repository, tag); err != nil {
|
||||
t.logger.Errorf("failed to delete the manifest of image %s:%s on the destination registry: %v",
|
||||
repository, digest, err)
|
||||
repository, tag, err)
|
||||
return err
|
||||
}
|
||||
t.logger.Infof("the manifest of image %s:%s is deleted", repository, digest)
|
||||
t.logger.Infof("the manifest of image %s:%s is deleted", repository, tag)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user