mirror of
https://github.com/goharbor/harbor
synced 2025-04-28 02:08:52 +00:00

This commit implements the delete function for image transfer Signed-off-by: Wenkai Yin <yinw@vmware.com>
198 lines
5.8 KiB
Go
198 lines
5.8 KiB
Go
// 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 (
|
|
"errors"
|
|
|
|
"github.com/goharbor/harbor/src/replication/ng/adapter"
|
|
|
|
"github.com/goharbor/harbor/src/common/utils/log"
|
|
"github.com/goharbor/harbor/src/jobservice/errs"
|
|
"github.com/goharbor/harbor/src/replication/ng/model"
|
|
trans "github.com/goharbor/harbor/src/replication/ng/transfer"
|
|
)
|
|
|
|
var (
|
|
jobStoppedErr = errs.JobStoppedError()
|
|
)
|
|
|
|
func init() {
|
|
if err := trans.RegisterFactory(model.ResourceTypeChart, factory); err != nil {
|
|
log.Errorf("failed to register transfer factory: %v", err)
|
|
}
|
|
}
|
|
|
|
func factory(logger trans.Logger, stopFunc trans.StopFunc) (trans.Transfer, error) {
|
|
return &transfer{
|
|
logger: logger,
|
|
isStopped: stopFunc,
|
|
}, nil
|
|
}
|
|
|
|
type chart struct {
|
|
name string
|
|
version string
|
|
}
|
|
|
|
type transfer struct {
|
|
logger trans.Logger
|
|
isStopped trans.StopFunc
|
|
src adapter.ChartRegistry
|
|
dst adapter.ChartRegistry
|
|
}
|
|
|
|
func (t *transfer) Transfer(src *model.Resource, dst *model.Resource) error {
|
|
// initialize
|
|
if err := t.initialize(src, dst); err != nil {
|
|
return err
|
|
}
|
|
|
|
// delete the chart on destination registry
|
|
if dst.Deleted {
|
|
return t.delete(&chart{
|
|
name: dst.Metadata.Name,
|
|
version: dst.Metadata.Vtags[0],
|
|
})
|
|
}
|
|
|
|
srcChart := &chart{
|
|
name: src.Metadata.Name,
|
|
version: src.Metadata.Vtags[0],
|
|
}
|
|
dstChart := &chart{
|
|
name: dst.Metadata.Name,
|
|
version: dst.Metadata.Vtags[0],
|
|
}
|
|
// copy the chart from source registry to the destination
|
|
return t.copy(srcChart, dstChart, dst.Override)
|
|
}
|
|
|
|
func (t *transfer) initialize(src, dst *model.Resource) error {
|
|
if t.shouldStop() {
|
|
return jobStoppedErr
|
|
}
|
|
// create client for source registry
|
|
srcReg, err := createRegistry(src.Registry)
|
|
if err != nil {
|
|
t.logger.Errorf("failed to create client for source registry: %v", err)
|
|
return err
|
|
}
|
|
t.src = srcReg
|
|
t.logger.Infof("client for source registry [type: %s, URL: %s, insecure: %v] created",
|
|
src.Registry.Type, src.Registry.URL, src.Registry.Insecure)
|
|
|
|
// create client for destination registry
|
|
dstReg, err := createRegistry(dst.Registry)
|
|
if err != nil {
|
|
t.logger.Errorf("failed to create client for destination registry: %v", err)
|
|
return err
|
|
}
|
|
t.dst = dstReg
|
|
t.logger.Infof("client for destination registry [type: %s, URL: %s, insecure: %v] created",
|
|
dst.Registry.Type, dst.Registry.URL, dst.Registry.Insecure)
|
|
|
|
return nil
|
|
}
|
|
|
|
func createRegistry(reg *model.Registry) (adapter.ChartRegistry, error) {
|
|
factory, err := adapter.GetFactory(reg.Type)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ad, err := factory(reg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
registry, ok := ad.(adapter.ChartRegistry)
|
|
if !ok {
|
|
return nil, errors.New("the adapter doesn't implement the \"ChartRegistry\" interface")
|
|
}
|
|
return registry, nil
|
|
}
|
|
|
|
func (t *transfer) shouldStop() bool {
|
|
isStopped := t.isStopped()
|
|
if isStopped {
|
|
t.logger.Info("the job is stopped")
|
|
}
|
|
return isStopped
|
|
}
|
|
|
|
func (t *transfer) copy(src, dst *chart, override bool) error {
|
|
if t.shouldStop() {
|
|
return jobStoppedErr
|
|
}
|
|
t.logger.Infof("copying %s:%s(source registry) to %s:%s(destination registry)...",
|
|
src.name, src.version, dst.name, dst.version)
|
|
|
|
// check the existence of the chart on the destination registry
|
|
exist, err := t.dst.ChartExist(dst.name, dst.version)
|
|
if err != nil {
|
|
t.logger.Errorf("failed to check the existence of chart %s:%s on the destination registry: %v", dst.name, dst.version, err)
|
|
return err
|
|
}
|
|
if exist {
|
|
// the same name chart exists, but not allowed to override
|
|
if !override {
|
|
t.logger.Warningf("the same name chart %s:%s exists on the destination registry, but the \"override\" is set to false, skip",
|
|
dst.name, dst.version)
|
|
return nil
|
|
}
|
|
// the same name chart exists, but allowed to override
|
|
t.logger.Warningf("the same name chart %s:%s exists on the destination registry and the \"override\" is set to true, continue...",
|
|
dst.name, dst.version)
|
|
}
|
|
|
|
// copy the chart between the source and destination registries
|
|
chart, err := t.src.DownloadChart(src.name, src.version)
|
|
if err != nil {
|
|
t.logger.Errorf("failed to download the chart %s:%s: %v", src.name, src.version, err)
|
|
return err
|
|
}
|
|
defer chart.Close()
|
|
|
|
if err = t.dst.UploadChart(dst.name, dst.version, chart); err != nil {
|
|
t.logger.Errorf("failed to upload the chart %s:%s: %v", dst.name, dst.version, err)
|
|
return err
|
|
}
|
|
|
|
t.logger.Infof("copy %s:%s(source registry) to %s:%s(destination registry) completed",
|
|
src.name, src.version, dst.name, dst.version)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *transfer) delete(chart *chart) error {
|
|
exist, err := t.dst.ChartExist(chart.name, chart.version)
|
|
if err != nil {
|
|
t.logger.Errorf("failed to check the existence of chart %s:%s on the destination registry: %v", chart.name, chart.version, err)
|
|
return err
|
|
}
|
|
if !exist {
|
|
t.logger.Infof("the chart %s:%s doesn't exist on the destination registry, skip",
|
|
chart.name, chart.version)
|
|
return nil
|
|
}
|
|
|
|
t.logger.Infof("deleting the chart %s:%s on the destination registry...", chart.name, chart.version)
|
|
if err := t.dst.DeleteChart(chart.name, chart.version); err != nil {
|
|
t.logger.Errorf("failed to delete the chart %s:%s on the destination registry: %v", chart.name, chart.version, err)
|
|
return err
|
|
}
|
|
t.logger.Infof("delete the chart %s:%s on the destination registry completed", chart.name, chart.version)
|
|
return nil
|
|
}
|