From beab57c81c5487f3e0debdfd2656871f8b34efde Mon Sep 17 00:00:00 2001 From: liamfallon Date: Wed, 15 Jan 2025 09:41:37 +0000 Subject: [PATCH] Updated to introduce cache factory --- api/generated/openapi/zz_generated.openapi.go | 2 +- pkg/apiserver/apiserver.go | 28 +++++----- pkg/cache/cache.go | 18 ++++-- pkg/cache/memory/cache.go | 35 ++++++++---- pkg/cache/memory/cache_test.go | 8 +-- pkg/cache/memory/memorycachefactory.go | 34 +++++++++++ pkg/cache/memory/package.go | 2 +- pkg/cache/memory/packagerevision.go | 2 +- pkg/cache/memory/repository.go | 13 ++--- pkg/cache/memory/util.go | 2 +- pkg/cache/types/cachetypes.go | 34 +++++++++++ pkg/engine/engine.go | 4 +- pkg/engine/options.go | 4 +- pkg/registry/porch/background.go | 6 +- pkg/repoimpl/git/git.go | 26 --------- pkg/repoimpl/git/gitrepofactory.go | 56 +++++++++++++++++++ pkg/repoimpl/oci/oci.go | 25 --------- pkg/repoimpl/oci/ocirepofactory.go | 52 +++++++++++++++++ pkg/repoimpl/repoimpl.go | 10 +++- pkg/repoimpl/types/repoimpltypes.go | 12 +++- 20 files changed, 264 insertions(+), 109 deletions(-) create mode 100644 pkg/cache/memory/memorycachefactory.go create mode 100644 pkg/cache/types/cachetypes.go create mode 100644 pkg/repoimpl/git/gitrepofactory.go create mode 100644 pkg/repoimpl/oci/ocirepofactory.go diff --git a/api/generated/openapi/zz_generated.openapi.go b/api/generated/openapi/zz_generated.openapi.go index 44daf27f..eb9a6477 100644 --- a/api/generated/openapi/zz_generated.openapi.go +++ b/api/generated/openapi/zz_generated.openapi.go @@ -377,7 +377,7 @@ func schema_porch_api_porch_v1alpha1_FunctionEvalTaskSpec(ref common.ReferenceCa }, "image": { SchemaProps: spec.SchemaProps{ - Description: "`Image` specifies the function image, such as `gcr.io/kpt-fn/gatekeeper:v0.2`. Use of `Image` is mutually exclusive with `FunctionRef`.", + Description: "`Image` specifies the function image, such as `gcr.io/kpt-fn/gatekeeper:v0.2`.", Type: []string{"string"}, Format: "", }, diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index e95c79ef..0d53f29c 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -27,7 +27,7 @@ import ( internalapi "github.com/nephio-project/porch/internal/api/porchinternal/v1alpha1" "github.com/nephio-project/porch/internal/kpt/fnruntime" "github.com/nephio-project/porch/pkg/cache" - memorycache "github.com/nephio-project/porch/pkg/cache/memory" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" "github.com/nephio-project/porch/pkg/engine" "github.com/nephio-project/porch/pkg/meta" "github.com/nephio-project/porch/pkg/registry/porch" @@ -95,7 +95,7 @@ type Config struct { type PorchServer struct { GenericAPIServer *genericapiserver.GenericAPIServer coreClient client.WithWatch - cache cache.Cache + cache cachetypes.Cache PeriodicRepoSyncFrequency time.Duration } @@ -229,15 +229,17 @@ func (c completedConfig) New() (*PorchServer, error) { watcherMgr := engine.NewWatcherManager() - memoryCache := memorycache.NewCache(repoimpltypes.RepoImplOptions{ - LocalDirectory: c.ExtraConfig.CacheDirectory, - RepoSyncFrequency: c.ExtraConfig.RepoSyncFrequency, - UseUserDefinedCaBundle: c.ExtraConfig.UseUserDefinedCaBundle, - CredentialResolver: credentialResolver, - UserInfoProvider: userInfoProvider, - MetadataStore: metadataStore, - ObjectNotifier: watcherMgr, - }) + cache, err := cache.CreateCacheImpl( + context.TODO(), + repoimpltypes.RepoImplOptions{ + LocalDirectory: c.ExtraConfig.CacheDirectory, + RepoSyncFrequency: c.ExtraConfig.RepoSyncFrequency, + UseUserDefinedCaBundle: c.ExtraConfig.UseUserDefinedCaBundle, + CredentialResolver: credentialResolver, + UserInfoProvider: userInfoProvider, + MetadataStore: metadataStore, + RepoPRNotifier: watcherMgr, + }) runnerOptionsResolver := func(namespace string) fnruntime.RunnerOptions { runnerOptions := fnruntime.RunnerOptions{} @@ -247,7 +249,7 @@ func (c completedConfig) New() (*PorchServer, error) { } cad, err := engine.NewCaDEngine( - engine.WithCache(memoryCache), + engine.WithCache(cache), // The order of registering the function runtimes matters here. When // evaluating a function, the runtimes will be tried in the same // order as they are registered. @@ -272,7 +274,7 @@ func (c completedConfig) New() (*PorchServer, error) { s := &PorchServer{ GenericAPIServer: genericServer, coreClient: coreClient, - cache: memoryCache, + cache: cache, // Set background job periodic frequency the same as repo sync frequency. PeriodicRepoSyncFrequency: c.ExtraConfig.RepoSyncFrequency, } diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index e68933fb..2b730f64 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -17,11 +17,19 @@ package cache import ( "context" - configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" - "github.com/nephio-project/porch/pkg/repository" + memorycache "github.com/nephio-project/porch/pkg/cache/memory" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" + repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" ) -type Cache interface { - OpenRepository(ctx context.Context, repositorySpec *configapi.Repository) (repository.Repository, error) - CloseRepository(ctx context.Context, repositorySpec *configapi.Repository, allRepos []configapi.Repository) error +var tracer = otel.Tracer("cache") + +func CreateCacheImpl(ctx context.Context, options repoimpltypes.RepoImplOptions) (cachetypes.Cache, error) { + ctx, span := tracer.Start(ctx, "Repository::RepositoryFactory", trace.WithAttributes()) + defer span.End() + + var cacheFactory = new(memorycache.MemoryCacheFactory) + return cacheFactory.NewCache(ctx, options) } diff --git a/pkg/cache/memory/cache.go b/pkg/cache/memory/cache.go index 8c1aa336..f5c5e00c 100644 --- a/pkg/cache/memory/cache.go +++ b/pkg/cache/memory/cache.go @@ -12,20 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "context" "sync" configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" - "github.com/nephio-project/porch/pkg/cache" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" "github.com/nephio-project/porch/pkg/repoimpl" repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" "github.com/nephio-project/porch/pkg/repository" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) +var tracer = otel.Tracer("memorycache") + // Cache allows us to keep state for repositories, rather than querying them every time. // // Cache Structure: @@ -42,14 +45,7 @@ type Cache struct { options repoimpltypes.RepoImplOptions } -var _ cache.Cache = &Cache{} - -func NewCache(options repoimpltypes.RepoImplOptions) *Cache { - return &Cache{ - repositories: make(map[string]*cachedRepository), - options: options, - } -} +var _ cachetypes.Cache = &Cache{} func (c *Cache) OpenRepository(ctx context.Context, repositorySpec *configapi.Repository) (repository.Repository, error) { ctx, span := tracer.Start(ctx, "Cache::OpenRepository", trace.WithAttributes()) @@ -72,7 +68,7 @@ func (c *Cache) OpenRepository(ctx context.Context, repositorySpec *configapi.Re } } - repoImpl, err := repoimpl.RepositoryFactory(ctx, repositorySpec, c.options) + repoImpl, err := repoimpl.CreateRepositoryImpl(ctx, repositorySpec, c.options) if err != nil { return nil, err } @@ -123,3 +119,20 @@ func (c *Cache) CloseRepository(ctx context.Context, repositorySpec *configapi.R return nil } } + +func (c *Cache) GetRepositories(ctx context.Context) []configapi.Repository { + repoSlice := []configapi.Repository{} + + for _, repo := range c.repositories { + repoSlice = append(repoSlice, *repo.repoSpec) + } + return repoSlice +} + +func (c *Cache) GetRepository(ctx context.Context, repositoryName string) *configapi.Repository { + if repo := c.repositories[repositoryName]; repo != nil { + return repo.repoSpec + } else { + return nil + } +} diff --git a/pkg/cache/memory/cache_test.go b/pkg/cache/memory/cache_test.go index 4df2dd64..23dbaab6 100644 --- a/pkg/cache/memory/cache_test.go +++ b/pkg/cache/memory/cache_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "context" @@ -224,12 +224,12 @@ func openRepositoryFromArchive(t *testing.T, ctx context.Context, testPath, name _, address := git.ServeGitRepository(t, tarfile, tempdir) metadataStore := createMetadataStoreFromArchive(t, fmt.Sprintf("%s-metadata.yaml", name), name) - cache := NewCache(repoimpltypes.RepoImplOptions{ + cache, _ := new(MemoryCacheFactory).NewCache(ctx, repoimpltypes.RepoImplOptions{ LocalDirectory: t.TempDir(), RepoSyncFrequency: 60 * time.Second, UseUserDefinedCaBundle: true, MetadataStore: metadataStore, - ObjectNotifier: &fakecache.ObjectNotifier{}, + RepoPRNotifier: &fakecache.ObjectNotifier{}, CredentialResolver: &fakecache.CredentialResolver{}, }) apiRepo := &v1alpha1.Repository{ @@ -259,7 +259,7 @@ func openRepositoryFromArchive(t *testing.T, ctx context.Context, testPath, name if err != nil { t.Errorf("CloseRepository(%q) failed: %v", address, err) } - if len(cache.repositories) != 0 { + if len(cache.GetRepositories(ctx)) != 0 { t.Errorf("CloseRepository hasn't deleted repository from cache") } }) diff --git a/pkg/cache/memory/memorycachefactory.go b/pkg/cache/memory/memorycachefactory.go new file mode 100644 index 00000000..72a5ac8d --- /dev/null +++ b/pkg/cache/memory/memorycachefactory.go @@ -0,0 +1,34 @@ +// Copyright 2025 The kpt and Nephio 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 memorycache + +import ( + "context" + + cachetypes "github.com/nephio-project/porch/pkg/cache/types" + repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" +) + +var _ cachetypes.CacheFactory = &MemoryCacheFactory{} + +type MemoryCacheFactory struct { +} + +func (f *MemoryCacheFactory) NewCache(_ context.Context, options repoimpltypes.RepoImplOptions) (cachetypes.Cache, error) { + return &Cache{ + repositories: make(map[string]*cachedRepository), + options: options, + }, nil +} diff --git a/pkg/cache/memory/package.go b/pkg/cache/memory/package.go index d02093f2..929937da 100644 --- a/pkg/cache/memory/package.go +++ b/pkg/cache/memory/package.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "github.com/nephio-project/porch/pkg/repository" diff --git a/pkg/cache/memory/packagerevision.go b/pkg/cache/memory/packagerevision.go index f12f8d62..79371bf2 100644 --- a/pkg/cache/memory/packagerevision.go +++ b/pkg/cache/memory/packagerevision.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "context" diff --git a/pkg/cache/memory/repository.go b/pkg/cache/memory/repository.go index d9ff91ae..ee7f91da 100644 --- a/pkg/cache/memory/repository.go +++ b/pkg/cache/memory/repository.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "context" @@ -24,7 +24,6 @@ import ( configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" "github.com/nephio-project/porch/pkg/repository" - "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,8 +32,6 @@ import ( "k8s.io/klog/v2" ) -var tracer = otel.Tracer("cache") - // We take advantage of the cache having a global view of all the packages // in a repository and compute the latest package revision in the cache // rather than add another level of caching in the repositories themselves. @@ -375,7 +372,7 @@ func (r *cachedRepository) Close() error { klog.Warningf("repo %s: error deleting packagerev for %s: %v", r.id, nn.Name, err) } klog.Infof("repo %s: successfully deleted packagerev %s/%s", r.id, nn.Namespace, nn.Name) - sent += r.options.ObjectNotifier.NotifyPackageRevisionChange(watch.Deleted, pr) + sent += r.options.RepoPRNotifier.NotifyPackageRevisionChange(watch.Deleted, pr) } klog.Infof("repo %s: sent %d notifications for %d package revisions during close", r.id, sent, len(r.cachedPackageRevisions)) return r.repo.Close() @@ -508,10 +505,10 @@ func (r *cachedRepository) refreshAllCachedPackages(ctx context.Context) (map[re for kname, newPackage := range newPackageRevisionNames { oldPackage := oldPackageRevisionNames[kname] if oldPackage == nil { - addSent += r.options.ObjectNotifier.NotifyPackageRevisionChange(watch.Added, newPackage) + addSent += r.options.RepoPRNotifier.NotifyPackageRevisionChange(watch.Added, newPackage) } else { if oldPackage.ResourceVersion() != newPackage.ResourceVersion() { - modSent += r.options.ObjectNotifier.NotifyPackageRevisionChange(watch.Modified, newPackage) + modSent += r.options.RepoPRNotifier.NotifyPackageRevisionChange(watch.Modified, newPackage) } } } @@ -544,7 +541,7 @@ func (r *cachedRepository) refreshAllCachedPackages(ctx context.Context) (map[re } klog.Infof("repo %s: deleting PackageRev %s/%s because PackageRevision was removed from SoT", r.id, nn.Namespace, nn.Name) - delSent += r.options.ObjectNotifier.NotifyPackageRevisionChange(watch.Deleted, oldPackage) + delSent += r.options.RepoPRNotifier.NotifyPackageRevisionChange(watch.Deleted, oldPackage) } } klog.Infof("repo %s: addSent %d, modSent %d, delSent for %d old and %d new repo packages", r.id, addSent, modSent, len(oldPackageRevisionNames), len(newPackageRevisionNames)) diff --git a/pkg/cache/memory/util.go b/pkg/cache/memory/util.go index c69d402b..8d9e6acb 100644 --- a/pkg/cache/memory/util.go +++ b/pkg/cache/memory/util.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package memory +package memorycache import ( "sort" diff --git a/pkg/cache/types/cachetypes.go b/pkg/cache/types/cachetypes.go new file mode 100644 index 00000000..678e0c15 --- /dev/null +++ b/pkg/cache/types/cachetypes.go @@ -0,0 +1,34 @@ +// Copyright 2025 The kpt and Nephio 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 cachetypes + +import ( + "context" + + configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" + repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" + "github.com/nephio-project/porch/pkg/repository" +) + +type Cache interface { + OpenRepository(ctx context.Context, repositorySpec *configapi.Repository) (repository.Repository, error) + CloseRepository(ctx context.Context, repositorySpec *configapi.Repository, allRepos []configapi.Repository) error + GetRepositories(ctx context.Context) []configapi.Repository + GetRepository(ctx context.Context, repositoryName string) *configapi.Repository +} + +type CacheFactory interface { + NewCache(ctx context.Context, options repoimpltypes.RepoImplOptions) (Cache, error) +} diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index c80eb5e6..07e62d96 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -23,7 +23,7 @@ import ( api "github.com/nephio-project/porch/api/porch/v1alpha1" configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" - cache "github.com/nephio-project/porch/pkg/cache" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" "github.com/nephio-project/porch/pkg/meta" "github.com/nephio-project/porch/pkg/repository" "github.com/nephio-project/porch/pkg/task" @@ -73,7 +73,7 @@ func NewCaDEngine(opts ...EngineOption) (CaDEngine, error) { } type cadEngine struct { - cache cache.Cache + cache cachetypes.Cache userInfoProvider repository.UserInfoProvider metadataStore meta.MetadataStore diff --git a/pkg/engine/options.go b/pkg/engine/options.go index 21388edb..d5406924 100644 --- a/pkg/engine/options.go +++ b/pkg/engine/options.go @@ -18,7 +18,7 @@ import ( "fmt" "github.com/nephio-project/porch/internal/kpt/fnruntime" - "github.com/nephio-project/porch/pkg/cache" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" "github.com/nephio-project/porch/pkg/kpt" "github.com/nephio-project/porch/pkg/kpt/fn" "github.com/nephio-project/porch/pkg/meta" @@ -38,7 +38,7 @@ func (f EngineOptionFunc) apply(engine *cadEngine) error { return f(engine) } -func WithCache(cache cache.Cache) EngineOption { +func WithCache(cache cachetypes.Cache) EngineOption { return EngineOptionFunc(func(engine *cadEngine) error { engine.cache = cache return nil diff --git a/pkg/registry/porch/background.go b/pkg/registry/porch/background.go index b4202651..a43ffbc0 100644 --- a/pkg/registry/porch/background.go +++ b/pkg/registry/porch/background.go @@ -20,7 +20,7 @@ import ( "time" configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" - "github.com/nephio-project/porch/pkg/cache" + cachetypes "github.com/nephio-project/porch/pkg/cache/types" "k8s.io/apimachinery/pkg/api/meta" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" @@ -28,7 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RunBackground(ctx context.Context, coreClient client.WithWatch, cache cache.Cache, PeriodicRepoSyncFrequency time.Duration) { +func RunBackground(ctx context.Context, coreClient client.WithWatch, cache cachetypes.Cache, PeriodicRepoSyncFrequency time.Duration) { b := background{ coreClient: coreClient, cache: cache, @@ -40,7 +40,7 @@ func RunBackground(ctx context.Context, coreClient client.WithWatch, cache cache // background manages background tasks type background struct { coreClient client.WithWatch - cache cache.Cache + cache cachetypes.Cache PeriodicRepoSyncFrequency time.Duration } diff --git a/pkg/repoimpl/git/git.go b/pkg/repoimpl/git/git.go index 8a62fd86..2cbe499b 100644 --- a/pkg/repoimpl/git/git.go +++ b/pkg/repoimpl/git/git.go @@ -73,32 +73,6 @@ type GitRepositoryOptions struct { MainBranchStrategy MainBranchStrategy } -func GetRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { - if repositorySpec.Spec.Git == nil { - return nil, errors.New("git property is required") - } - if repositorySpec.Spec.Git.Repo == "" { - return nil, errors.New("git.repo property is required") - } - - var mbs MainBranchStrategy - if repositorySpec.Spec.Git.CreateBranch { - mbs = CreateIfMissing - } else { - mbs = ErrorIfMissing - } - - repo, err := OpenRepository(ctx, repositorySpec.Name, repositorySpec.Namespace, repositorySpec.Spec.Git, repositorySpec.Spec.Deployment, filepath.Join(options.LocalDirectory, "git"), GitRepositoryOptions{ - RepoImplOptions: options, - MainBranchStrategy: mbs, - }) - if err != nil { - return nil, err - } - - return repo, nil -} - func OpenRepository(ctx context.Context, name, namespace string, spec *configapi.GitRepository, deployment bool, root string, opts GitRepositoryOptions) (GitRepository, error) { ctx, span := tracer.Start(ctx, "OpenRepository", trace.WithAttributes()) defer span.End() diff --git a/pkg/repoimpl/git/gitrepofactory.go b/pkg/repoimpl/git/gitrepofactory.go new file mode 100644 index 00000000..7aecf0ca --- /dev/null +++ b/pkg/repoimpl/git/gitrepofactory.go @@ -0,0 +1,56 @@ +// Copyright 2025 The kpt and Nephio 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 git + +import ( + "context" + "errors" + "path/filepath" + + configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" + repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" + "github.com/nephio-project/porch/pkg/repository" +) + +var _ repoimpltypes.RepoImplFactory = &GitRepoFactory{} + +type GitRepoFactory struct { +} + +func (f *GitRepoFactory) NewRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { + if repositorySpec.Spec.Git == nil { + return nil, errors.New("git property is required") + } + if repositorySpec.Spec.Git.Repo == "" { + return nil, errors.New("git.repo property is required") + } + + var mbs MainBranchStrategy + if repositorySpec.Spec.Git.CreateBranch { + mbs = CreateIfMissing + } else { + mbs = ErrorIfMissing + } + + repo, err := OpenRepository(ctx, repositorySpec.Name, repositorySpec.Namespace, repositorySpec.Spec.Git, repositorySpec.Spec.Deployment, filepath.Join(options.LocalDirectory, "git"), GitRepositoryOptions{ + RepoImplOptions: options, + MainBranchStrategy: mbs, + }) + if err != nil { + return nil, err + } + + return repo, nil +} diff --git a/pkg/repoimpl/oci/oci.go b/pkg/repoimpl/oci/oci.go index 2df50ae5..6abcba3e 100644 --- a/pkg/repoimpl/oci/oci.go +++ b/pkg/repoimpl/oci/oci.go @@ -21,47 +21,22 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "path/filepath" "strings" "time" "github.com/GoogleContainerTools/kpt/pkg/oci" - kptoci "github.com/GoogleContainerTools/kpt/pkg/oci" "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/google" "github.com/nephio-project/porch/api/porch/v1alpha1" configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" "github.com/nephio-project/porch/internal/kpt/pkg" kptfile "github.com/nephio-project/porch/pkg/kpt/api/kptfile/v1" - repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" "github.com/nephio-project/porch/pkg/repository" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/klog/v2" ) -func GetRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { - if repositorySpec.Spec.Oci == nil { - return nil, fmt.Errorf("oci not configured") - } - - ociSpec := repositorySpec.Spec.Oci - localDir := filepath.Join(options.LocalDirectory, "oci") - storage, err := kptoci.NewStorage(localDir) - if err != nil { - return nil, err - } - - return &ociRepository{ - name: repositorySpec.Name, - namespace: repositorySpec.Namespace, - spec: *ociSpec.DeepCopy(), - deployment: repositorySpec.Spec.Deployment, - storage: storage, - }, nil - -} - type ociRepository struct { name string namespace string diff --git a/pkg/repoimpl/oci/ocirepofactory.go b/pkg/repoimpl/oci/ocirepofactory.go new file mode 100644 index 00000000..4f52d7e7 --- /dev/null +++ b/pkg/repoimpl/oci/ocirepofactory.go @@ -0,0 +1,52 @@ +// Copyright 2025 The kpt and Nephio 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 oci + +import ( + "context" + "fmt" + "path/filepath" + + kptoci "github.com/GoogleContainerTools/kpt/pkg/oci" + configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" + repoimpltypes "github.com/nephio-project/porch/pkg/repoimpl/types" + "github.com/nephio-project/porch/pkg/repository" +) + +var _ repoimpltypes.RepoImplFactory = &OciRepoFactory{} + +type OciRepoFactory struct { +} + +func (f *OciRepoFactory) NewRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { + if repositorySpec.Spec.Oci == nil { + return nil, fmt.Errorf("oci not configured") + } + + ociSpec := repositorySpec.Spec.Oci + localDir := filepath.Join(options.LocalDirectory, "oci") + storage, err := kptoci.NewStorage(localDir) + if err != nil { + return nil, err + } + + return &ociRepository{ + name: repositorySpec.Name, + namespace: repositorySpec.Namespace, + spec: *ociSpec.DeepCopy(), + deployment: repositorySpec.Spec.Deployment, + storage: storage, + }, nil +} diff --git a/pkg/repoimpl/repoimpl.go b/pkg/repoimpl/repoimpl.go index 6e3770fd..cbddc988 100644 --- a/pkg/repoimpl/repoimpl.go +++ b/pkg/repoimpl/repoimpl.go @@ -30,20 +30,24 @@ import ( var tracer = otel.Tracer("repoimpl") -func RepositoryFactory(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { +func CreateRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options repoimpltypes.RepoImplOptions) (repository.Repository, error) { ctx, span := tracer.Start(ctx, "Repository::RepositoryFactory", trace.WithAttributes()) defer span.End() + var repoFactory repoimpltypes.RepoImplFactory + switch repositoryType := repositorySpec.Spec.Type; repositoryType { case configapi.RepositoryTypeOCI: - return oci.GetRepositoryImpl(ctx, repositorySpec, options) + repoFactory = new(oci.OciRepoFactory) case configapi.RepositoryTypeGit: - return git.GetRepositoryImpl(ctx, repositorySpec, options) + repoFactory = new(git.GitRepoFactory) default: return nil, fmt.Errorf("type %q not supported", repositoryType) } + + return repoFactory.NewRepositoryImpl(ctx, repositorySpec, options) } func RepositoryKey(repositorySpec *configapi.Repository) (string, error) { diff --git a/pkg/repoimpl/types/repoimpltypes.go b/pkg/repoimpl/types/repoimpltypes.go index 66094fdc..8af947f2 100644 --- a/pkg/repoimpl/types/repoimpltypes.go +++ b/pkg/repoimpl/types/repoimpltypes.go @@ -15,15 +15,17 @@ package repoimpltypes import ( + "context" "time" + configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1" "github.com/nephio-project/porch/pkg/meta" "github.com/nephio-project/porch/pkg/repository" "k8s.io/apimachinery/pkg/watch" ) -type objectNotifier interface { - NotifyPackageRevisionChange(eventType watch.EventType, obj repository.PackageRevision) int +type RepoImplFactory interface { + NewRepositoryImpl(ctx context.Context, repositorySpec *configapi.Repository, options RepoImplOptions) (repository.Repository, error) } type RepoImplOptions struct { @@ -33,5 +35,9 @@ type RepoImplOptions struct { CredentialResolver repository.CredentialResolver UserInfoProvider repository.UserInfoProvider MetadataStore meta.MetadataStore - ObjectNotifier objectNotifier + RepoPRNotifier RepoPRNotifier +} + +type RepoPRNotifier interface { + NotifyPackageRevisionChange(eventType watch.EventType, obj repository.PackageRevision) int }