Skip to content

Commit 0548a0a

Browse files
fabianburthmatthiasbrunsSkarlso
authored
feat(cli): resolver integration (#1053)
<!-- markdownlint-disable MD041 --> #### What this PR does / why we need it This PR integrates the following repository changes - use the new patchmatcher repo - use legacy fallback if no pathmatcher config is available #### Which issue(s) this PR fixes Contributes open-component-model/ocm-project#575 --------- Signed-off-by: Matthias Bruns <git@matthiasbruns.com> Signed-off-by: Fabian Burth <fabian.burth@sap.com> Signed-off-by: Gergely Brautigam <gergely.brautigam@sap.com> Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Co-authored-by: Matthias Bruns <git@matthiasbruns.com> Co-authored-by: Matthias Bruns <github@matthiasbruns.com> Co-authored-by: Gergely Brautigam <gergely.brautigam@sap.com> Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
1 parent c475a84 commit 0548a0a

22 files changed

Lines changed: 924 additions & 396 deletions

File tree

.github/config/wordlist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ replicationset
375375
repo
376376
repocpi
377377
repositoryimpl
378+
repositoryProvider
378379
repositoryspec
379380
repositoryurl
380381
reproducibility

cli/cmd/add/component-version/cmd.go

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"sigs.k8s.io/yaml"
1616

1717
"ocm.software/open-component-model/bindings/go/blob"
18-
resolverruntime "ocm.software/open-component-model/bindings/go/configuration/ocm/v1/runtime"
1918
"ocm.software/open-component-model/bindings/go/constructor"
2019
constructorruntime "ocm.software/open-component-model/bindings/go/constructor/runtime"
2120
constructorv1 "ocm.software/open-component-model/bindings/go/constructor/spec/v1"
@@ -26,8 +25,6 @@ import (
2625
"ocm.software/open-component-model/bindings/go/plugin/manager"
2726
"ocm.software/open-component-model/bindings/go/plugin/manager/registries/resource"
2827
"ocm.software/open-component-model/bindings/go/repository"
29-
//nolint:staticcheck // no replacement for resolvers available yet https://github.com/open-component-model/ocm-project/issues/575
30-
v1 "ocm.software/open-component-model/bindings/go/repository/component/fallback/v1"
3128
"ocm.software/open-component-model/bindings/go/runtime"
3229
"ocm.software/open-component-model/cli/cmd/setup/hooks"
3330
ocmctx "ocm.software/open-component-model/cli/internal/context"
@@ -201,11 +198,17 @@ func persistentPreRunE(cmd *cobra.Command, _ []string) error {
201198
}
202199

203200
func AddComponentVersion(cmd *cobra.Command, _ []string) error {
201+
ctx := cmd.Context()
204202
pluginManager := ocmctx.FromContext(cmd.Context()).PluginManager()
205203
if pluginManager == nil {
206204
return fmt.Errorf("could not retrieve plugin manager from context")
207205
}
208206

207+
ocmContext := ocmctx.FromContext(ctx)
208+
if ocmContext == nil {
209+
return fmt.Errorf("no OCM context found")
210+
}
211+
209212
credentialGraph := ocmctx.FromContext(cmd.Context()).CredentialGraph()
210213
if credentialGraph == nil {
211214
return fmt.Errorf("could not retrieve credential graph from context")
@@ -253,27 +256,17 @@ func AddComponentVersion(cmd *cobra.Command, _ []string) error {
253256

254257
config := ocmctx.FromContext(cmd.Context()).Configuration()
255258

256-
//nolint:staticcheck // no replacement for resolvers available yet https://github.com/open-component-model/ocm-project/issues/575
257-
var resolvers []*resolverruntime.Resolver
258-
if config != nil {
259-
resolvers, err = ocm.ResolversFromConfig(config)
260-
if err != nil {
261-
return fmt.Errorf("getting resolvers from configuration failed: %w", err)
262-
}
263-
}
264-
265-
//nolint:staticcheck // no replacement for resolvers available yet https://github.com/open-component-model/ocm-project/issues/575
266-
fallback, err := v1.NewFallbackRepository(cmd.Context(), pluginManager.ComponentVersionRepositoryRegistry, credentialGraph, resolvers)
259+
repoProvider, err := ocm.NewComponentVersionRepositoryForComponentProvider(cmd.Context(), pluginManager.ComponentVersionRepositoryRegistry, credentialGraph, config, nil)
267260
if err != nil {
268-
return fmt.Errorf("creating fallback repository failed: %w", err)
261+
return fmt.Errorf("could not initialize ocm repository: %w", err)
269262
}
270263

271264
instance := &constructorProvider{
272-
cache: cacheDir,
273-
targetRepoSpec: repoSpec,
274-
fallbackRepo: fallback,
275-
pluginManager: pluginManager,
276-
graph: credentialGraph,
265+
cache: cacheDir,
266+
targetRepoSpec: repoSpec,
267+
repositoryProvider: repoProvider,
268+
pluginManager: pluginManager,
269+
graph: credentialGraph,
277270
}
278271

279272
opts := constructor.Options{
@@ -369,16 +362,18 @@ var (
369362
)
370363

371364
type constructorProvider struct {
372-
cache string
373-
targetRepoSpec runtime.Typed
374-
//nolint:staticcheck // no replacement for resolvers available yet https://github.com/open-component-model/ocm-project/issues/575
375-
fallbackRepo *v1.FallbackRepository
376-
pluginManager *manager.PluginManager
377-
graph credentials.GraphResolver
365+
cache string
366+
targetRepoSpec runtime.Typed
367+
repositoryProvider ocm.ComponentVersionRepositoryForComponentProvider
368+
pluginManager *manager.PluginManager
369+
graph credentials.GraphResolver
378370
}
379371

380372
func (prov *constructorProvider) GetExternalRepository(ctx context.Context, name, version string) (repository.ComponentVersionRepository, error) {
381-
return prov.fallbackRepo, nil
373+
if prov.repositoryProvider == nil {
374+
return nil, fmt.Errorf("cannot fetch external component version %s:%s repository provider configured", name, version)
375+
}
376+
return prov.repositoryProvider.GetComponentVersionRepositoryForComponent(ctx, name, version)
382377
}
383378

384379
func (prov *constructorProvider) GetDigestProcessor(ctx context.Context, resource *descriptor.Resource) (constructor.ResourceDigestProcessor, error) {

cli/cmd/cmd_test.go

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,8 @@ resources:
873873
})
874874
})
875875

876-
t.Run("construction with references", func(t *testing.T) {
876+
t.Run("construction with references targeting fallback resolvers", func(t *testing.T) {
877+
tmp := t.TempDir()
877878
externalConstructorYAML := fmt.Sprintf(`
878879
name: ocm.software/external
879880
version: 1.0.0
@@ -985,6 +986,121 @@ components:
985986
}
986987

987988
})
989+
990+
t.Run("construction with references targeting resolvers", func(t *testing.T) {
991+
tmp := t.TempDir()
992+
externalConstructorYAML := fmt.Sprintf(`
993+
name: ocm.software/external
994+
version: 1.0.0
995+
provider:
996+
name: ocm.software
997+
resources:
998+
- name: my-resource
999+
type: blob
1000+
input:
1001+
type: utf8/v1
1002+
text: "I come from external!"
1003+
`)
1004+
externalConstructorYAMLFilePath := filepath.Join(tmp, "component-constructor-external.yaml")
1005+
r.NoError(os.WriteFile(externalConstructorYAMLFilePath, []byte(externalConstructorYAML), 0o600))
1006+
externalArchiveFilePath := filepath.Join(tmp, "transport-archive-external")
1007+
1008+
_, err := test.OCM(t, test.WithArgs("add", "cv",
1009+
"--constructor", externalConstructorYAMLFilePath,
1010+
"--repository", externalArchiveFilePath,
1011+
"--working-directory", tmp,
1012+
), test.WithErrorOutput(logs))
1013+
r.NoError(err, "could not construct component version with working directory")
1014+
1015+
resolverConfigYAML := fmt.Sprintf(`
1016+
type: generic.config.ocm.software/v1
1017+
configurations:
1018+
- type: resolvers.config.ocm.software
1019+
resolvers:
1020+
- repository:
1021+
type: CommonTransportFormat/v1
1022+
path: %[1]s
1023+
componentNamePattern: ocm.software/*
1024+
`, externalArchiveFilePath)
1025+
1026+
resolverConfigYAMLFilePath := filepath.Join(tmp, "config-with-resolver.yaml")
1027+
r.NoError(os.WriteFile(resolverConfigYAMLFilePath, []byte(resolverConfigYAML), 0o600))
1028+
1029+
constructorYAML = fmt.Sprintf(`
1030+
components:
1031+
- name: ocm.software/a
1032+
version: 1.0.0
1033+
provider:
1034+
name: ocm.software
1035+
resources:
1036+
- name: my-resource
1037+
type: blob
1038+
input:
1039+
type: utf8/v1
1040+
text: "I come from A"
1041+
- name: ocm.software/b
1042+
version: 1.0.0
1043+
provider:
1044+
name: ocm.software
1045+
componentReferences:
1046+
- name: b-to-a # internal reference
1047+
version: 1.0.0
1048+
componentName: ocm.software/a
1049+
- name: external
1050+
version: 1.0.0
1051+
componentName: ocm.software/external # from external repository
1052+
resources:
1053+
- name: my-resource
1054+
type: blob
1055+
input:
1056+
type: utf8/v1
1057+
text: "I come from B"
1058+
`)
1059+
1060+
// Create a replacement test file to be added to the component version
1061+
constructorYAMLFilePath := filepath.Join(tmp, "component-constructor-external-reference.yaml")
1062+
r.NoError(os.WriteFile(constructorYAMLFilePath, []byte(constructorYAML), 0o600))
1063+
1064+
cmd, err := test.OCM(t, test.WithArgs("add", "cv",
1065+
"--constructor", constructorYAMLFilePath,
1066+
"--repository", archiveFilePath,
1067+
"--working-directory", tmp,
1068+
"--config", resolverConfigYAMLFilePath,
1069+
"--component-version-conflict-policy", string(componentversion.ComponentVersionConflictPolicyReplace),
1070+
"--external-component-version-copy-policy", string(componentversion.ExternalComponentVersionCopyPolicyCopyOrFail),
1071+
), test.WithErrorOutput(logs))
1072+
1073+
r.Equal(ocmctx.FromContext(cmd.Context()).FilesystemConfig().WorkingDirectory, tmp, "expected working directory to be set in ocm context automatically")
1074+
1075+
r.NoError(err, "could not construct component version with working directory")
1076+
1077+
fs, err := filesystem.NewFS(archiveFilePath, os.O_RDONLY)
1078+
r.NoError(err, "could not create test filesystem")
1079+
archive := ctf.NewFileSystemCTF(fs)
1080+
helperRepo, err := oci.NewRepository(ocictf.WithCTF(ocictf.NewFromCTF(archive)))
1081+
r.NoError(err, "could not create helper test repository")
1082+
1083+
for _, identity := range []runtime.Identity{{
1084+
descriptor.IdentityAttributeName: "ocm.software/a",
1085+
descriptor.IdentityAttributeVersion: "1.0.0",
1086+
}, {
1087+
descriptor.IdentityAttributeName: "ocm.software/b",
1088+
descriptor.IdentityAttributeVersion: "1.0.0",
1089+
}, {
1090+
descriptor.IdentityAttributeName: "ocm.software/external",
1091+
descriptor.IdentityAttributeVersion: "1.0.0",
1092+
}} {
1093+
t.Run(identity.String(), func(t *testing.T) {
1094+
r := require.New(t)
1095+
_, err := helperRepo.GetComponentVersion(t.Context(),
1096+
identity[descriptor.IdentityAttributeName],
1097+
identity[descriptor.IdentityAttributeVersion],
1098+
)
1099+
r.NoError(err, "could not retrieve component version from test repository")
1100+
})
1101+
}
1102+
1103+
})
9881104
}
9891105

9901106
func Test_Version(t *testing.T) {

cli/cmd/download/plugin/cmd.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"ocm.software/open-component-model/bindings/go/plugin/manager/types"
2222
ocmruntime "ocm.software/open-component-model/bindings/go/runtime"
2323
"ocm.software/open-component-model/cli/cmd/download/shared"
24+
ocmctx "ocm.software/open-component-model/cli/internal/context"
2425
"ocm.software/open-component-model/cli/internal/flags/enum"
26+
"ocm.software/open-component-model/cli/internal/reference/compref"
2527
"ocm.software/open-component-model/cli/internal/repository/ocm"
2628
)
2729

@@ -73,10 +75,15 @@ Resources can be accessed either locally or via a plugin that supports remote fe
7375
}
7476

7577
func DownloadPlugin(cmd *cobra.Command, args []string) error {
78+
ctx := cmd.Context()
7679
pluginManager, credentialGraph, logger, err := shared.GetContextItems(cmd)
7780
if err != nil {
7881
return err
7982
}
83+
ocmContext := ocmctx.FromContext(ctx)
84+
if ocmContext == nil {
85+
return fmt.Errorf("no OCM context found")
86+
}
8087

8188
resourceName, err := cmd.Flags().GetString(FlagResourceName)
8289
if err != nil {
@@ -114,12 +121,25 @@ func DownloadPlugin(cmd *cobra.Command, args []string) error {
114121
}
115122

116123
reference := args[0]
117-
repo, err := ocm.NewFromRef(cmd.Context(), pluginManager, credentialGraph, reference)
124+
// we have a reference and parse it
125+
ref, err := compref.Parse(reference)
126+
if err != nil {
127+
return fmt.Errorf("parsing component reference %q failed: %w", reference, err)
128+
}
129+
config := ocmContext.Configuration()
130+
slog.DebugContext(ctx, "parsed component reference", "reference", reference, "parsed", ref)
131+
132+
repoProvider, err := ocm.NewComponentVersionRepositoryForComponentProvider(cmd.Context(), pluginManager.ComponentVersionRepositoryRegistry, credentialGraph, config, ref)
118133
if err != nil {
119134
return fmt.Errorf("could not initialize ocm repository: %w", err)
120135
}
121136

122-
desc, err := repo.GetComponentVersion(cmd.Context())
137+
repo, err := repoProvider.GetComponentVersionRepositoryForComponent(cmd.Context(), ref.Component, ref.Version)
138+
if err != nil {
139+
return fmt.Errorf("could not access ocm repository: %w", err)
140+
}
141+
142+
desc, err := repo.GetComponentVersion(cmd.Context(), ref.Component, ref.Version)
123143
if err != nil {
124144
return fmt.Errorf("getting component version failed: %w", err)
125145
}
@@ -172,7 +192,7 @@ func DownloadPlugin(cmd *cobra.Command, args []string) error {
172192
slog.String("type", res.Type),
173193
slog.Any("identity", res.ToIdentity()))
174194

175-
data, err := shared.DownloadResourceData(cmd.Context(), pluginManager, credentialGraph, repo, res, resourceIdentity)
195+
data, err := shared.DownloadResourceData(ctx, pluginManager, credentialGraph, ref.Component, ref.Version, repo, res, resourceIdentity)
176196
if err != nil {
177197
return fmt.Errorf("downloading plugin resource for identity %q failed: %w", resourceIdentity, err)
178198
}

cli/cmd/download/resource/cmd.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"ocm.software/open-component-model/bindings/go/runtime"
2323
"ocm.software/open-component-model/cli/cmd/download/shared"
2424
"ocm.software/open-component-model/cli/internal/flags/enum"
25+
"ocm.software/open-component-model/cli/internal/reference/compref"
2526
"ocm.software/open-component-model/cli/internal/repository/ocm"
2627
"ocm.software/open-component-model/cli/internal/transformers"
2728
)
@@ -122,12 +123,21 @@ func DownloadResource(cmd *cobra.Command, args []string) error {
122123
}
123124

124125
reference := args[0]
125-
repo, err := ocm.NewFromRef(cmd.Context(), pluginManager, credentialGraph, reference)
126+
ref, err := compref.Parse(reference)
127+
if err != nil {
128+
return fmt.Errorf("parsing component reference %q failed: %w", reference, err)
129+
}
130+
repoProvider, err := ocm.NewComponentVersionRepositoryForComponentProvider(cmd.Context(), pluginManager.ComponentVersionRepositoryRegistry, credentialGraph, nil, ref)
126131
if err != nil {
127132
return fmt.Errorf("could not initialize ocm repository: %w", err)
128133
}
129134

130-
desc, err := repo.GetComponentVersion(cmd.Context())
135+
repo, err := repoProvider.GetComponentVersionRepositoryForComponent(cmd.Context(), ref.Component, ref.Version)
136+
if err != nil {
137+
return fmt.Errorf("could not access ocm repository: %w", err)
138+
}
139+
140+
desc, err := repo.GetComponentVersion(cmd.Context(), ref.Component, ref.Version)
131141
if err != nil {
132142
return fmt.Errorf("getting component version failed: %w", err)
133143
}
@@ -146,7 +156,7 @@ func DownloadResource(cmd *cobra.Command, args []string) error {
146156
}
147157
res := &toDownload[0]
148158

149-
data, err := shared.DownloadResourceData(cmd.Context(), pluginManager, credentialGraph, repo, res, requestedIdentity)
159+
data, err := shared.DownloadResourceData(cmd.Context(), pluginManager, credentialGraph, ref.Component, ref.Version, repo, res, requestedIdentity)
150160
if err != nil {
151161
return fmt.Errorf("downloading resource for identity %q failed: %w", requestedIdentity, err)
152162
}

cli/cmd/download/shared/common.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import (
1616
v2 "ocm.software/open-component-model/bindings/go/descriptor/v2"
1717
"ocm.software/open-component-model/bindings/go/plugin/manager"
1818
"ocm.software/open-component-model/bindings/go/plugin/manager/registries/resource"
19+
"ocm.software/open-component-model/bindings/go/repository"
1920
"ocm.software/open-component-model/bindings/go/runtime"
2021
ocmctx "ocm.software/open-component-model/cli/internal/context"
2122
"ocm.software/open-component-model/cli/internal/flags/log"
22-
"ocm.software/open-component-model/cli/internal/repository/ocm"
2323
)
2424

2525
// GetContextItems extracts common dependencies from cobra command
@@ -43,13 +43,13 @@ func GetContextItems(cmd *cobra.Command) (*manager.PluginManager, credentials.Gr
4343
}
4444

4545
// DownloadResourceData handles the actual data download from repository
46-
func DownloadResourceData(ctx context.Context, pluginManager *manager.PluginManager, credentialGraph credentials.GraphResolver, repo *ocm.ComponentRepository, res *descriptor.Resource, identity runtime.Identity) (blob.ReadOnlyBlob, error) {
46+
func DownloadResourceData(ctx context.Context, pluginManager *manager.PluginManager, credentialGraph credentials.GraphResolver, component, version string, repo repository.ComponentVersionRepository, res *descriptor.Resource, identity runtime.Identity) (blob.ReadOnlyBlob, error) {
4747
access := res.GetAccess()
4848
var data blob.ReadOnlyBlob
4949
var err error
5050

5151
if IsLocal(access) {
52-
data, _, err = repo.GetLocalResource(ctx, identity)
52+
data, _, err = repo.GetLocalResource(ctx, component, version, identity)
5353
} else {
5454
var plugin resource.Repository
5555
plugin, err = pluginManager.ResourcePluginRegistry.GetResourcePlugin(ctx, access)

0 commit comments

Comments
 (0)