diff --git a/src/jobservice/job/impl/replication/replication.go b/src/jobservice/job/impl/replication/replication.go index 3bfd42625c3..20844d2932a 100644 --- a/src/jobservice/job/impl/replication/replication.go +++ b/src/jobservice/job/impl/replication/replication.go @@ -53,8 +53,8 @@ import ( _ "github.com/goharbor/harbor/src/pkg/reg/adapter/tencentcr" // register the VolcEngine CR Registry adapter _ "github.com/goharbor/harbor/src/pkg/reg/adapter/volcenginecr" - // register sftp adapter - _ "github.com/goharbor/harbor/src/pkg/reg/adapter/sftp" + // register storage adapter + _ "github.com/goharbor/harbor/src/pkg/reg/adapter/storage" "github.com/goharbor/harbor/src/pkg/reg/model" ) diff --git a/src/pkg/reg/adapter/sftp/adapter.go b/src/pkg/reg/adapter/storage/adapter.go similarity index 61% rename from src/pkg/reg/adapter/sftp/adapter.go rename to src/pkg/reg/adapter/storage/adapter.go index 0f976beca50..106f7e77206 100644 --- a/src/pkg/reg/adapter/sftp/adapter.go +++ b/src/pkg/reg/adapter/storage/adapter.go @@ -1,110 +1,125 @@ -package sftp +package storage import ( "context" "errors" "fmt" + "github.com/davecgh/go-spew/spew" "github.com/docker/distribution" "github.com/docker/distribution/reference" - "github.com/docker/distribution/registry/storage" storagedriver "github.com/docker/distribution/registry/storage/driver" - "github.com/goharbor/harbor/src/lib/log" - "github.com/goharbor/harbor/src/pkg/reg/adapter" - sftpdriver "github.com/goharbor/harbor/src/pkg/reg/adapter/sftp/driver" + "github.com/goharbor/harbor/src/common/utils" + regadapter "github.com/goharbor/harbor/src/pkg/reg/adapter" + "github.com/goharbor/harbor/src/pkg/reg/adapter/storage/health" + "github.com/goharbor/harbor/src/pkg/reg/filter" "github.com/goharbor/harbor/src/pkg/reg/model" "github.com/opencontainers/go-digest" "io" "strings" ) -func init() { - err := adapter.RegisterFactory(model.RegistryTypeSFTP, &factory{}) - if err != nil { - log.Errorf("failed to register factory for dtr: %v", err) - return - } - log.Infof("the factory of SFTP sftpAdapter was registered") -} - -type factory struct { -} - -// Create ... -func (f *factory) Create(r *model.Registry) (adapter.Adapter, error) { - driver := sftpdriver.NewDriver(r) - ns, err := storage.NewRegistry(context.TODO(), driver) - if err != nil { - return nil, err - } - return &sftpAdapter{ - regModel: r, - registry: ns, - }, nil -} - -// AdapterPattern ... -func (f *factory) AdapterPattern() *model.AdapterPattern { - return nil -} - var ( - _ adapter.Adapter = (*sftpAdapter)(nil) - _ adapter.ArtifactRegistry = (*sftpAdapter)(nil) + _ regadapter.Adapter = (*adapter)(nil) + _ regadapter.ArtifactRegistry = (*adapter)(nil) ) -type sftpAdapter struct { +type adapter struct { regModel *model.Registry driver storagedriver.StorageDriver registry distribution.Namespace } -func (a *sftpAdapter) FetchArtifacts(_ []*model.Filter) ([]*model.Resource, error) { +func (a *adapter) FetchArtifacts(filters []*model.Filter) ([]*model.Resource, error) { + fmt.Println("Fetch artifacts") + + spew.Dump("filters", filters) ctx := context.Background() - var repos = make([]string, 1000) + var repoNames = make([]string, 1000) - _, err := a.registry.Repositories(ctx, repos, "") + _, err := a.registry.Repositories(ctx, repoNames, "") if err != nil && !errors.Is(err, io.EOF) { return nil, fmt.Errorf("unable to get repositories: %v", err) } - var resources []*model.Resource - for _, r := range repos { - if r == "" { - continue - } + if len(repoNames) == 0 { + return nil, nil + } - named, err := reference.WithName(r) - if err != nil { - return nil, fmt.Errorf("ref %s error: %v", r, err) - } - repo, err := a.registry.Repository(ctx, named) - if err != nil { - return nil, fmt.Errorf("unable to get repo %s: %v", r, err) - } - tags, err := repo.Tags(ctx).All(ctx) - if err != nil { - return nil, fmt.Errorf("unable to get all tags for repo %s: %v", r, err) - } + var repositories []*model.Repository + for _, repoName := range repoNames { + repositories = append(repositories, &model.Repository{ + Name: repoName, + }) + } + + repositories, err = filter.DoFilterRepositories(repositories, filters) + if err != nil { + return nil, err + } + + runner := utils.NewLimitedConcurrentRunner(10) + + var rawResources = make([]*model.Resource, len(repositories)) + for i, r := range repositories { + repo := r + index := i - resources = append(resources, &model.Resource{ - Type: model.ResourceTypeImage, - Registry: a.regModel, - Metadata: &model.ResourceMetadata{ - Repository: &model.Repository{ - Name: r, + runner.AddTask(func() error { + named, err := reference.WithName(repo.Name) + if err != nil { + return fmt.Errorf("ref %s error: %v", repo.Name, err) + } + repository, err := a.registry.Repository(ctx, named) + if err != nil { + return fmt.Errorf("unable to get repo %s: %v", repo.Name, err) + } + + tags, err := repository.Tags(ctx).All(ctx) + if err != nil { + return fmt.Errorf("unable to get all tags for repo %s: %v", r, err) + } + + artifacts := []*model.Artifact{ + { + Tags: tags, }, - Artifacts: []*model.Artifact{ - { - Tags: tags, + } + + artifacts, err = filter.DoFilterArtifacts(artifacts, filters) + if err != nil { + return fmt.Errorf("failed to list artifacts of repository %s: %v", repo, err) + } + + if len(artifacts) == 0 { + return nil + } + + rawResources[index] = &model.Resource{ + Type: model.ResourceTypeImage, + Registry: a.regModel, + Metadata: &model.ResourceMetadata{ + Repository: &model.Repository{ + Name: r.Name, }, + Artifacts: artifacts, }, - }, + } + return nil }) } + + var resources []*model.Resource + + for _, r := range rawResources { + if r == nil { + continue + } + resources = append(resources, r) + } return resources, nil } -func (a *sftpAdapter) ManifestExist(repository, ref string) (exist bool, desc *distribution.Descriptor, err error) { +func (a *adapter) ManifestExist(repository, ref string) (exist bool, desc *distribution.Descriptor, err error) { ctx := context.Background() repo, err := a.getRepo(ctx, repository, ref) @@ -145,7 +160,7 @@ func (a *sftpAdapter) ManifestExist(repository, ref string) (exist bool, desc *d return true, &descriptor, nil } -func (a *sftpAdapter) PullManifest(repository, ref string, _ ...string) (distribution.Manifest, string, error) { +func (a *adapter) PullManifest(repository, ref string, _ ...string) (distribution.Manifest, string, error) { ctx := context.Background() repo, err := a.getRepo(ctx, repository, ref) @@ -184,7 +199,7 @@ func (a *sftpAdapter) PullManifest(repository, ref string, _ ...string) (distrib } // PushManifest manifests are blobs actually -func (a *sftpAdapter) PushManifest(repository, ref, mediaType string, payload []byte) (string, error) { +func (a *adapter) PushManifest(repository, ref, mediaType string, payload []byte) (string, error) { ctx := context.Background() repo, err := a.getRepo(ctx, repository, ref) @@ -207,7 +222,7 @@ func (a *sftpAdapter) PushManifest(repository, ref, mediaType string, payload [] return descriptor.Digest.String(), nil } -func (a *sftpAdapter) DeleteManifest(repository, ref string) error { +func (a *adapter) DeleteManifest(repository, ref string) error { ctx := context.Background() named, err := reference.WithName(repository) @@ -223,11 +238,10 @@ func (a *sftpAdapter) DeleteManifest(repository, ref string) error { if err != nil { return err } - return manifests.Delete(ctx, digest.Digest(ref)) } -func (a *sftpAdapter) BlobExist(repository, d string) (exist bool, err error) { +func (a *adapter) BlobExist(repository, d string) (exist bool, err error) { ctx := context.Background() repo, err := a.getRepo(ctx, repository, d) @@ -246,7 +260,7 @@ func (a *sftpAdapter) BlobExist(repository, d string) (exist bool, err error) { return true, nil } -func (a *sftpAdapter) PullBlob(repository, d string) (int64, io.ReadCloser, error) { +func (a *adapter) PullBlob(repository, d string) (int64, io.ReadCloser, error) { ctx := context.Background() repo, err := a.getRepo(ctx, repository, d) @@ -268,17 +282,15 @@ func (a *sftpAdapter) PullBlob(repository, d string) (int64, io.ReadCloser, erro return descriptor.Size, readSeeker, nil } -func (a *sftpAdapter) PullBlobChunk(_, _ string, _, _, _ int64) (size int64, blob io.ReadCloser, err error) { +func (a *adapter) PullBlobChunk(_, _ string, _, _, _ int64) (size int64, blob io.ReadCloser, err error) { return 0, nil, fmt.Errorf("PullBlobChunk is not implemented") } -func (a *sftpAdapter) PushBlobChunk(_, _ string, _ int64, _ io.Reader, _, _ int64, _ string) (nextUploadLocation string, endRange int64, err error) { +func (a *adapter) PushBlobChunk(_, _ string, _ int64, _ io.Reader, _, _ int64, _ string) (nextUploadLocation string, endRange int64, err error) { return "", 0, fmt.Errorf("PushBlobChunk is not implemented") } -func (a *sftpAdapter) PushBlob(repository, d string, size int64, r io.Reader) error { - fmt.Printf("push blob %s %d", d, size) - +func (a *adapter) PushBlob(repository, d string, size int64, r io.Reader) error { ctx := context.Background() repo, err := a.getRepo(ctx, repository, d) @@ -311,15 +323,15 @@ func (a *sftpAdapter) PushBlob(repository, d string, size int64, r io.Reader) er return nil } -func (a *sftpAdapter) MountBlob(_, _, _ string) (err error) { +func (a *adapter) MountBlob(_, _, _ string) (err error) { return fmt.Errorf("MountBlob is not implemented") } -func (a *sftpAdapter) CanBeMount(_ string) (mount bool, repository string, err error) { +func (a *adapter) CanBeMount(_ string) (mount bool, repository string, err error) { return false, "", nil } -func (a *sftpAdapter) DeleteTag(r, tag string) error { +func (a *adapter) DeleteTag(r, tag string) error { ctx := context.Background() named, err := reference.WithName(r) if err != nil { @@ -332,7 +344,7 @@ func (a *sftpAdapter) DeleteTag(r, tag string) error { return repo.Tags(ctx).Untag(ctx, tag) } -func (a *sftpAdapter) ListTags(r string) ([]string, error) { +func (a *adapter) ListTags(r string) ([]string, error) { ctx := context.Background() named, err := reference.WithName(r) @@ -350,15 +362,22 @@ func (a *sftpAdapter) ListTags(r string) ([]string, error) { return tags, nil } -func (a *sftpAdapter) PrepareForPush(_ []*model.Resource) error { +func (a *adapter) PrepareForPush(_ []*model.Resource) error { return nil } -func (a *sftpAdapter) HealthCheck() (string, error) { +func (a *adapter) HealthCheck() (string, error) { + checker, ok := a.driver.(health.Checker) + if !ok { + return model.Healthy, nil + } + if err := checker.Health(context.Background()); err != nil { + return model.Unhealthy, err + } return model.Healthy, nil } -func (a *sftpAdapter) getRepo(ctx context.Context, repository, ref string) (distribution.Repository, error) { +func (a *adapter) getRepo(ctx context.Context, repository, ref string) (distribution.Repository, error) { named, err := reference.WithName(repository) if err != nil { return nil, err @@ -375,13 +394,22 @@ func (a *sftpAdapter) getRepo(ctx context.Context, repository, ref string) (dist return a.registry.Repository(ctx, named) } -func (a *sftpAdapter) Info() (*model.RegistryInfo, error) { +func (a *adapter) Info() (*model.RegistryInfo, error) { return &model.RegistryInfo{ Type: model.RegistryTypeSFTP, SupportedResourceTypes: []string{ model.ResourceTypeImage, }, - SupportedResourceFilters: []*model.FilterStyle{}, + SupportedResourceFilters: []*model.FilterStyle{ + { + Type: model.FilterTypeName, + Style: model.FilterStyleTypeText, + }, + { + Type: model.FilterTypeTag, + Style: model.FilterStyleTypeText, + }, + }, SupportedTriggers: []string{ model.TriggerTypeManual, model.TriggerTypeScheduled, diff --git a/src/pkg/reg/adapter/sftp/driver/driver.go b/src/pkg/reg/adapter/storage/drivers/sftp/driver.go similarity index 55% rename from src/pkg/reg/adapter/sftp/driver/driver.go rename to src/pkg/reg/adapter/storage/drivers/sftp/driver.go index 65761e53cd6..0c12758cb5a 100644 --- a/src/pkg/reg/adapter/sftp/driver/driver.go +++ b/src/pkg/reg/adapter/storage/drivers/sftp/driver.go @@ -1,9 +1,12 @@ -package driver +package sftp import ( "context" "fmt" - "github.com/docker/distribution/registry/storage/driver" + "github.com/davecgh/go-spew/spew" + storagedriver "github.com/docker/distribution/registry/storage/driver" + "github.com/docker/distribution/registry/storage/driver/base" + "github.com/goharbor/harbor/src/pkg/reg/adapter/storage/health" "github.com/goharbor/harbor/src/pkg/reg/model" sftppkg "github.com/pkg/sftp" "golang.org/x/crypto/ssh" @@ -11,18 +14,32 @@ import ( "net/url" "os" "path" - "strings" "sync" ) -type Driver struct { +const ( + DriverName = "sftp" + defaultConcurrency = 10 +) + +type driver struct { regModel *model.Registry client *clientWrapper clientLock *sync.Mutex } -func (d *Driver) Name() string { - return "sftp" +func (d *driver) Name() string { + return DriverName +} + +type baseEmbed struct { + base.Base +} + +// Driver is a storagedriver.StorageDriver implementation backed by a local +// filesystem. All provided paths will be subpaths of the RootDirectory. +type Driver struct { + baseEmbed } type clientWrapper struct { @@ -30,16 +47,12 @@ type clientWrapper struct { basePath string } -func (c clientWrapper) normaliseBasePath(path string) string { - return normalisePath(c.basePath, path) -} - -func normalisePath(base, path string) string { - return fmt.Sprintf("%s/%s", strings.TrimRight(base, "/"), strings.TrimLeft(path, "/")) +func (c clientWrapper) normaliseBasePath(p string) string { + return path.Join(c.basePath, p) } -func (d *Driver) GetContent(_ context.Context, path string) ([]byte, error) { - client, err := d.getClient(d.regModel) +func (d *driver) GetContent(_ context.Context, path string) ([]byte, error) { + client, err := d.getClient() if err != nil { return nil, err } @@ -47,20 +60,21 @@ func (d *Driver) GetContent(_ context.Context, path string) ([]byte, error) { file, err := client.Open(client.normaliseBasePath(path)) if err != nil { if os.IsNotExist(err) { - return nil, driver.PathNotFoundError{} + return nil, storagedriver.PathNotFoundError{} } return nil, fmt.Errorf("unable to open file: %v", err) } return io.ReadAll(file) } -func (d *Driver) PutContent(_ context.Context, p string, content []byte) error { +func (d *driver) PutContent(_ context.Context, p string, content []byte) error { - client, err := d.getClient(d.regModel) + client, err := d.getClient() if err != nil { return err } - client.normaliseBasePath(p) + + p = client.normaliseBasePath(p) if err := client.MkdirAll(path.Dir(p)); err != nil { return fmt.Errorf("unable to create directory: %v", err) @@ -78,11 +92,12 @@ func (d *Driver) PutContent(_ context.Context, p string, content []byte) error { return err } -func (d *Driver) Reader(_ context.Context, path string, offset int64) (io.ReadCloser, error) { +func (d *driver) Reader(_ context.Context, path string, offset int64) (io.ReadCloser, error) { + if offset > 0 { return nil, fmt.Errorf("offset is not supported") } - client, err := d.getClient(d.regModel) + client, err := d.getClient() if err != nil { return nil, err } @@ -90,7 +105,7 @@ func (d *Driver) Reader(_ context.Context, path string, offset int64) (io.ReadCl file, err := client.Open(client.normaliseBasePath(path)) if err != nil { if os.IsNotExist(err) { - return nil, driver.PathNotFoundError{} + return nil, storagedriver.PathNotFoundError{} } return nil, err } @@ -101,17 +116,18 @@ func (d *Driver) Reader(_ context.Context, path string, offset int64) (io.ReadCl return nil, err } else if seekPos < offset { file.Close() - return nil, driver.InvalidOffsetError{Path: path, Offset: offset} + return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset} } return file, nil } -func (d *Driver) Writer(_ context.Context, path string, append bool) (driver.FileWriter, error) { +func (d *driver) Writer(_ context.Context, path string, append bool) (storagedriver.FileWriter, error) { + if append { return nil, fmt.Errorf("append is not supported") } - client, err := d.getClient(d.regModel) + client, err := d.getClient() if err != nil { return nil, err } @@ -142,51 +158,56 @@ func (d *Driver) Writer(_ context.Context, path string, append bool) (driver.Fil return newFileWriter(file, client, offset), nil } -func (d *Driver) Stat(_ context.Context, path string) (driver.FileInfo, error) { - client, err := d.getClient(d.regModel) +func (d *driver) Stat(_ context.Context, p string) (storagedriver.FileInfo, error) { + + client, err := d.getClient() if err != nil { return nil, err } - path = client.normaliseBasePath(path) - stat, err := client.Stat(path) + p = client.normaliseBasePath(p) + stat, err := client.Stat(p) if err != nil { if os.IsNotExist(err) { - return nil, driver.PathNotFoundError{Path: path} + return nil, storagedriver.PathNotFoundError{Path: p} } return nil, err } return fileInfo{ FileInfo: stat, - path: path, + path: p, }, nil } -func (d *Driver) List(_ context.Context, path string) ([]string, error) { - client, err := d.getClient(d.regModel) +func (d *driver) List(_ context.Context, p string) ([]string, error) { + + client, err := d.getClient() if err != nil { return nil, fmt.Errorf("list error: %v", err) } - path = client.normaliseBasePath(path) + p = client.normaliseBasePath(p) - files, err := client.ReadDir(path) + files, err := client.ReadDir(p) if err != nil { if os.IsNotExist(err) { - return nil, driver.PathNotFoundError{Path: path} + return nil, storagedriver.PathNotFoundError{Path: p} } return nil, fmt.Errorf("read dir error: %v", err) } var result []string for _, file := range files { - result = append(result, normalisePath(path, file.Name())) + result = append(result, path.Join(p, file.Name())) } + + spew.Dump(result) + return result, nil } -func (d *Driver) Move(_ context.Context, sourcePath string, destPath string) error { - client, err := d.getClient(d.regModel) +func (d *driver) Move(_ context.Context, sourcePath string, destPath string) error { + client, err := d.getClient() if err != nil { return err } @@ -201,8 +222,8 @@ func (d *Driver) Move(_ context.Context, sourcePath string, destPath string) err return client.Rename(sourcePath, destPath) } -func (d *Driver) Delete(_ context.Context, path string) error { - client, err := d.getClient(d.regModel) +func (d *driver) Delete(_ context.Context, path string) error { + client, err := d.getClient() if err != nil { return err } @@ -218,33 +239,21 @@ func (d *Driver) Delete(_ context.Context, path string) error { return nil } -func (d *Driver) URLFor(_ context.Context, _ string, _ map[string]interface{}) (string, error) { +func (d *driver) URLFor(_ context.Context, _ string, _ map[string]interface{}) (string, error) { return "", fmt.Errorf("URLFor is not implemented") } -func (d *Driver) Walk(_ context.Context, path string, f driver.WalkFn) error { - client, err := d.getClient(d.regModel) - if err != nil { - return err - } - path = client.normaliseBasePath(path) - walker := client.Walk(path) +func (d *driver) Walk(ctx context.Context, path string, f storagedriver.WalkFn) error { + return storagedriver.WalkFallback(ctx, d, path, f) +} - for walker.Step() { - if walker.Err() != nil { - continue - } - if err = f(&fileInfo{ - FileInfo: walker.Stat(), - path: normalisePath(path, walker.Path()), - }); err != nil { - return err - } - } - return nil +func (d *driver) resetClient() { + d.clientLock.Lock() + defer d.clientLock.Unlock() + d.client = nil } -func (d *Driver) getClient(registry *model.Registry) (*clientWrapper, error) { +func (d *driver) getClient() (*clientWrapper, error) { d.clientLock.Lock() defer d.clientLock.Unlock() @@ -252,7 +261,9 @@ func (d *Driver) getClient(registry *model.Registry) (*clientWrapper, error) { return d.client, nil } - u, err := url.Parse(registry.URL) + fmt.Println("################# CONNECT!!!!! ##################") + + u, err := url.Parse(d.regModel.URL) if err != nil { return nil, fmt.Errorf("unable to parse registry URL: %v", err) } @@ -263,13 +274,13 @@ func (d *Driver) getClient(registry *model.Registry) (*clientWrapper, error) { } conf := &ssh.ClientConfig{} - if registry.Insecure { + if d.regModel.Insecure { conf.HostKeyCallback = ssh.InsecureIgnoreHostKey() } - if registry.Credential != nil { - conf.User = registry.Credential.AccessKey - conf.Auth = append(conf.Auth, ssh.Password(registry.Credential.AccessSecret)) + if d.regModel.Credential != nil { + conf.User = d.regModel.Credential.AccessKey + conf.Auth = append(conf.Auth, ssh.Password(d.regModel.Credential.AccessSecret)) } hostname := fmt.Sprintf("%s:%s", u.Hostname(), port) @@ -277,7 +288,6 @@ func (d *Driver) getClient(registry *model.Registry) (*clientWrapper, error) { if err != nil { return nil, fmt.Errorf("dial %s error: %v", hostname, err) } - c, err := sftppkg.NewClient(conn) if err != nil { return nil, err @@ -289,7 +299,26 @@ func (d *Driver) getClient(registry *model.Registry) (*clientWrapper, error) { } return d.client, nil } +func (d *driver) Health(_ context.Context) error { + fmt.Println("--------------- HEALTH CHECK ----------------") + d.resetClient() + client, err := d.getClient() + if err != nil { + return err + } + defer client.Close() + return err +} + +func New(regModel *model.Registry) storagedriver.StorageDriver { -func NewDriver(regModel *model.Registry) *Driver { - return &Driver{regModel: regModel, clientLock: &sync.Mutex{}} + return &Driver{ + baseEmbed: baseEmbed{ + Base: base.Base{ + StorageDriver: base.NewRegulator(&driver{regModel: regModel, clientLock: &sync.Mutex{}}, defaultConcurrency), + }, + }, + } } + +var _ health.Checker = (*driver)(nil) diff --git a/src/pkg/reg/adapter/sftp/driver/fileinfo.go b/src/pkg/reg/adapter/storage/drivers/sftp/fileinfo.go similarity index 98% rename from src/pkg/reg/adapter/sftp/driver/fileinfo.go rename to src/pkg/reg/adapter/storage/drivers/sftp/fileinfo.go index 284bba28b44..1f2bdb411d8 100644 --- a/src/pkg/reg/adapter/sftp/driver/fileinfo.go +++ b/src/pkg/reg/adapter/storage/drivers/sftp/fileinfo.go @@ -1,4 +1,4 @@ -package driver +package sftp import ( storagedriver "github.com/docker/distribution/registry/storage/driver" diff --git a/src/pkg/reg/adapter/sftp/driver/filewriter.go b/src/pkg/reg/adapter/storage/drivers/sftp/filewriter.go similarity index 99% rename from src/pkg/reg/adapter/sftp/driver/filewriter.go rename to src/pkg/reg/adapter/storage/drivers/sftp/filewriter.go index f4c08641d75..1ba109712a1 100644 --- a/src/pkg/reg/adapter/sftp/driver/filewriter.go +++ b/src/pkg/reg/adapter/storage/drivers/sftp/filewriter.go @@ -1,4 +1,4 @@ -package driver +package sftp import ( "bufio" diff --git a/src/pkg/reg/adapter/storage/health/health.go b/src/pkg/reg/adapter/storage/health/health.go new file mode 100644 index 00000000000..19565f22590 --- /dev/null +++ b/src/pkg/reg/adapter/storage/health/health.go @@ -0,0 +1,7 @@ +package health + +import "context" + +type Checker interface { + Health(ctx context.Context) error +} diff --git a/src/pkg/reg/adapter/storage/s3_factory.go b/src/pkg/reg/adapter/storage/s3_factory.go new file mode 100644 index 00000000000..0beb2ff2beb --- /dev/null +++ b/src/pkg/reg/adapter/storage/s3_factory.go @@ -0,0 +1,52 @@ +package storage + +import ( + "context" + "fmt" + "github.com/docker/distribution/registry/storage" + "github.com/docker/distribution/registry/storage/driver/s3-aws" + "github.com/goharbor/harbor/src/lib/log" + regadapter "github.com/goharbor/harbor/src/pkg/reg/adapter" + "github.com/goharbor/harbor/src/pkg/reg/model" +) + +func init() { + err := regadapter.RegisterFactory(model.RegistryTypeS3, &s3Factory{}) + if err != nil { + log.Errorf("failed to register s3 for dtr: %v", err) + return + } + log.Infof("sftpFactory of SFTP adapter was registered") +} + +type s3Factory struct { +} + +// Create ... +func (f *s3Factory) Create(r *model.Registry) (regadapter.Adapter, error) { + + fmt.Println("1!!!!!!!!!!!!! S3 FACTORY CREATE !!!!!!!!!!!!!!!") + driverParams := s3.DriverParameters{} + + if r.Credential != nil { + driverParams.AccessKey = r.Credential.AccessKey + driverParams.SecretKey = r.Credential.AccessSecret + } + + driver, err := s3.New(driverParams) + + ns, err := storage.NewRegistry(context.TODO(), driver) + if err != nil { + return nil, err + } + return &adapter{ + regModel: r, + driver: driver, + registry: ns, + }, nil +} + +// AdapterPattern ... +func (f *s3Factory) AdapterPattern() *model.AdapterPattern { + return nil +} diff --git a/src/pkg/reg/adapter/storage/sftp_factory.go b/src/pkg/reg/adapter/storage/sftp_factory.go new file mode 100644 index 00000000000..078daa64781 --- /dev/null +++ b/src/pkg/reg/adapter/storage/sftp_factory.go @@ -0,0 +1,44 @@ +package storage + +import ( + "context" + "fmt" + "github.com/docker/distribution/registry/storage" + "github.com/goharbor/harbor/src/lib/log" + regadapter "github.com/goharbor/harbor/src/pkg/reg/adapter" + sftpdriver "github.com/goharbor/harbor/src/pkg/reg/adapter/storage/drivers/sftp" + "github.com/goharbor/harbor/src/pkg/reg/model" +) + +func init() { + err := regadapter.RegisterFactory(model.RegistryTypeSFTP, &sftpFactory{}) + if err != nil { + log.Errorf("failed to register sftpFactory for dtr: %v", err) + return + } + log.Infof("sftpFactory of SFTP adapter was registered") +} + +type sftpFactory struct { +} + +// Create ... +func (f *sftpFactory) Create(r *model.Registry) (regadapter.Adapter, error) { + + fmt.Println("1!!!!!!!!!!!!! SFTP FACTORY CREATE !!!!!!!!!!!!!!!") + driver := sftpdriver.New(r) + ns, err := storage.NewRegistry(context.TODO(), driver) + if err != nil { + return nil, err + } + return &adapter{ + regModel: r, + driver: driver, + registry: ns, + }, nil +} + +// AdapterPattern ... +func (f *sftpFactory) AdapterPattern() *model.AdapterPattern { + return nil +} diff --git a/src/pkg/reg/model/registry.go b/src/pkg/reg/model/registry.go index 59e49c6a05f..9a5a5053fee 100644 --- a/src/pkg/reg/model/registry.go +++ b/src/pkg/reg/model/registry.go @@ -36,9 +36,9 @@ const ( RegistryTypeGithubCR = "github-ghcr" RegistryTypeVolcCR = "volcengine-cr" RegistryTypeSFTP = "sftp" - - RegistryTypeHelmHub = "helm-hub" - RegistryTypeArtifactHub = "artifact-hub" + RegistryTypeS3 = "s3" + RegistryTypeHelmHub = "helm-hub" + RegistryTypeArtifactHub = "artifact-hub" FilterStyleTypeText = "input" FilterStyleTypeRadio = "radio"