Skip to content

Commit 1989253

Browse files
committed
refactoring and tests
1 parent e2e3285 commit 1989253

File tree

9 files changed

+280
-63
lines changed

9 files changed

+280
-63
lines changed

cmd/ocmTransfer.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ import (
88

99
// ocmTransferCmd represents the "ocm transfer componentversion" command
1010
var ocmTransferCmd = &cobra.Command{
11-
Use: "ocmTransfer source destination",
12-
Short: "Transfer an OCM component from a source to a destination",
13-
Long: `Transfers the specified OCM component version from the source location to the destination location.`,
11+
Use: "ocmTransfer source target",
12+
Short: "Transfer an OCM component from a source to a target location",
13+
Long: `Transfers the specified OCM component version from the source location to the target location.`,
1414
Aliases: []string{
1515
"transfer",
1616
},
1717
Args: cobra.ExactArgs(2),
1818
ArgAliases: []string{
1919
"source",
20-
"destination",
20+
"target",
2121
},
2222
RunE: func(cmd *cobra.Command, args []string) error {
2323
transferCommands := []string{
@@ -30,7 +30,7 @@ var ocmTransferCmd = &cobra.Command{
3030
"--copy-resources",
3131
"--copy-sources",
3232
args[0], // source
33-
args[1], // destination
33+
args[1], // target
3434
}
3535

3636
return ocmcli.Execute(cmd.Context(), transferCommands, transferArgs, cmd.Flag("config").Value.String())

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ go 1.24.5
55
require (
66
github.com/spf13/cobra v1.9.1
77
github.com/stretchr/testify v1.10.0
8-
gopkg.in/yaml.v3 v3.0.1
8+
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
9+
sigs.k8s.io/yaml v1.6.0
910
)
1011

1112
require (
1213
github.com/davecgh/go-spew v1.1.1 // indirect
1314
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1415
github.com/pmezard/go-difflib v1.0.0 // indirect
1516
github.com/spf13/pflag v1.0.7 // indirect
17+
go.yaml.in/yaml/v2 v2.4.2 // indirect
18+
gopkg.in/yaml.v3 v3.0.1 // indirect
1619
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
22
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
33
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
5+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
46
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
57
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
68
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -13,7 +15,15 @@ github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
1315
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
1416
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
1517
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
18+
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
19+
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
20+
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
21+
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
1622
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1723
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1824
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1925
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
26+
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
27+
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
28+
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
29+
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

internal/ocm-cli/ocm.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package ocm_cli
33
import (
44
"context"
55
"fmt"
6-
"gopkg.in/yaml.v3"
76
"os"
87
"os/exec"
8+
"sigs.k8s.io/yaml"
99
)
1010

1111
const (
@@ -19,16 +19,16 @@ const (
1919
// The `args` parameter is a slice of strings representing the arguments to the command.
2020
// The `ocmConfig` parameter is a string representing the path to the OCM configuration file. Passing `NoOcmConfig` indicates that no configuration file should be used.
2121
func Execute(ctx context.Context, commands []string, args []string, ocmConfig string) error {
22-
var flags []string
23-
24-
flags = append(flags, commands...)
25-
flags = append(flags, args...)
22+
var ocmArgs []string
2623

2724
if ocmConfig != NoOcmConfig {
28-
flags = append(flags, "--config", ocmConfig)
25+
ocmArgs = append(ocmArgs, "--config", ocmConfig)
2926
}
3027

31-
cmd := exec.CommandContext(ctx, "ocm", flags...)
28+
ocmArgs = append(ocmArgs, commands...)
29+
ocmArgs = append(ocmArgs, args...)
30+
31+
cmd := exec.CommandContext(ctx, "ocm", ocmArgs...)
3232
cmd.Stdout = os.Stdout
3333
cmd.Stderr = os.Stderr
3434

@@ -52,43 +52,47 @@ type ComponentVersion struct {
5252
// Component represents an OCM component with its name, version, references to other components, and resources.
5353
type Component struct {
5454
// Name is the name of the component.
55-
Name string `yaml:"name"`
55+
Name string `json:"name"`
5656
// Version is the version of the component.
57-
Version string `yaml:"version"`
57+
Version string `json:"version"`
5858
// ComponentReferences is a list of references to other components that this component depends on.
5959
ComponentReferences []ComponentReference `yaml:"componentReferences"`
6060
// Resources is a list of resources associated with this component, including their names, versions, types, and access information.
61-
Resources []Resource `yaml:"resources"`
61+
Resources []Resource `json:"resources"`
6262
}
6363

6464
// ComponentReference represents a reference to another component, including its name, version, and the name of the component it refers to.
6565
type ComponentReference struct {
6666
// Name is the name of the component reference.
67-
Name string `yaml:"name"`
67+
Name string `json:"name"`
6868
// Version is the version of the component reference.
69-
Version string `yaml:"version"`
69+
Version string `json:"version"`
7070
// ComponentName is the name of the component that this reference points to.
71-
ComponentName string `yaml:"componentName"`
71+
ComponentName string `json:"componentName"`
7272
}
7373

7474
// Resource represents a resource associated with a component, including its name, version, type, and access information.
7575
type Resource struct {
7676
// Name is the name of the resource.
77-
Name string `yaml:"name"`
77+
Name string `json:"name"`
7878
// Version is the version of the resource.
79-
Version string `yaml:"version"`
79+
Version string `json:"version"`
8080
// Type is the content type of the resource.
81-
Type string `yaml:"type"`
81+
Type string `json:"type"`
8282
// Access contains the information on how to access the resource.
83-
Access Access `yaml:"access"`
83+
Access Access `json:"access"`
8484
}
8585

8686
// Access represents the access information for a resource, including the type of access.
8787
type Access struct {
88-
// Type is the content type of access to the resource.
89-
Type string `yaml:"type"`
88+
// Type specifies the access type of the resource.
89+
Type string `json:"type"`
9090
// ImageReference is the reference to the image if the Type is "ociArtifact".
91-
ImageReference string `yaml:"imageReference"`
91+
ImageReference *string `json:"imageReference"`
92+
// LocalReference specifies a component local access
93+
LocalReference *string `json:"localReference"`
94+
// MediaType is the media type of the resource
95+
MediaType *string `json:"mediaType"`
9296
}
9397

9498
// GetResource retrieves a resource by its name from the component version.
@@ -113,21 +117,18 @@ func (cv *ComponentVersion) GetComponentReference(name string) (*ComponentRefere
113117

114118
// GetComponentVersion retrieves a component version by its reference using the OCM CLI.
115119
func GetComponentVersion(ctx context.Context, componentReference string, ocmConfig string) (*ComponentVersion, error) {
116-
flags := []string{
117-
"get",
118-
"componentversion",
119-
"--output", "yaml",
120-
componentReference,
121-
}
120+
var ocmArgs []string
122121

123122
if ocmConfig != NoOcmConfig {
124-
flags = append(flags, "--config", ocmConfig)
123+
ocmArgs = append(ocmArgs, "--config", ocmConfig)
125124
}
126125

127-
cmd := exec.CommandContext(ctx, "ocm", flags...)
126+
ocmArgs = append(ocmArgs, "get", "componentversion", "--output", "yaml", componentReference)
127+
128+
cmd := exec.CommandContext(ctx, "ocm", ocmArgs...)
128129
out, err := cmd.CombinedOutput()
129130
if err != nil {
130-
return nil, fmt.Errorf("error executing ocm command: %w", err)
131+
return nil, fmt.Errorf("error executing ocm command: %w, %q", err, out)
131132
}
132133

133134
var cv ComponentVersion

internal/ocm-cli/ocm_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package ocm_cli_test
2+
3+
import (
4+
"errors"
5+
ocmcli "github.com/openmcp-project/bootstrapper/internal/ocm-cli"
6+
"k8s.io/utils/ptr"
7+
8+
testutil "github.com/openmcp-project/bootstrapper/test/utils"
9+
"github.com/stretchr/testify/assert"
10+
"testing"
11+
)
12+
13+
func TestExecute(t *testing.T) {
14+
expectError := errors.New("expected error")
15+
16+
testutil.DownloadOCMAndAddToPath(t)
17+
18+
ctfIn := testutil.BuildComponent("./testdata/component-constructor.yaml", t)
19+
20+
testCases := []struct {
21+
desc string
22+
commands []string
23+
arguments []string
24+
ocmConfig string
25+
expectedError error
26+
}{
27+
{
28+
desc: "get componentversion",
29+
commands: []string{"get", "componentversion"},
30+
arguments: []string{"--output", "yaml", ctfIn},
31+
ocmConfig: ocmcli.NoOcmConfig,
32+
expectedError: nil,
33+
},
34+
{
35+
desc: "get componentversion with invalid argument",
36+
commands: []string{"get", "componentversion"},
37+
arguments: []string{"--output", "yaml", "invalid-argument"},
38+
ocmConfig: ocmcli.NoOcmConfig,
39+
expectedError: expectError,
40+
},
41+
{
42+
desc: "get componentversion with ocm config",
43+
commands: []string{"get", "componentversion"},
44+
arguments: []string{"--output", "yaml", ctfIn},
45+
ocmConfig: "./testdata/ocm-config.yaml",
46+
expectedError: nil,
47+
},
48+
}
49+
50+
for _, tc := range testCases {
51+
t.Run(tc.desc, func(t *testing.T) {
52+
err := ocmcli.Execute(t.Context(), tc.commands, tc.arguments, tc.ocmConfig)
53+
54+
if tc.expectedError != nil {
55+
assert.Error(t, err)
56+
} else {
57+
assert.NoError(t, err)
58+
}
59+
})
60+
}
61+
}
62+
63+
func TestGetComponentVersion(t *testing.T) {
64+
expectError := errors.New("expected error")
65+
testutil.DownloadOCMAndAddToPath(t)
66+
67+
ctfIn := testutil.BuildComponent("./testdata/component-constructor.yaml", t)
68+
69+
testCases := []struct {
70+
desc string
71+
componentRef string
72+
ocmConfig string
73+
expectedError error
74+
verify func(cv *ocmcli.ComponentVersion)
75+
}{
76+
{
77+
desc: "get component version",
78+
componentRef: ctfIn,
79+
ocmConfig: ocmcli.NoOcmConfig,
80+
expectedError: nil,
81+
verify: func(cv *ocmcli.ComponentVersion) {
82+
assert.Equal(t, cv.Component.Name, "github.com/openmcp-project/bootstrapper/test")
83+
assert.Equal(t, cv.Component.Version, "v0.0.1")
84+
assert.Len(t, cv.Component.ComponentReferences, 2)
85+
assert.Len(t, cv.Component.Resources, 1)
86+
87+
assert.Contains(t, cv.Component.ComponentReferences, ocmcli.ComponentReference{
88+
Name: "bootstrapper-dependency-a",
89+
Version: "v0.2.0",
90+
ComponentName: "github.com/openmcp-project/bootstrapper-dependency-a",
91+
})
92+
assert.Contains(t, cv.Component.ComponentReferences, ocmcli.ComponentReference{
93+
Name: "bootstrapper-dependency-b",
94+
Version: "v0.3.0",
95+
ComponentName: "github.com/openmcp-project/bootstrapper-dependency-b",
96+
})
97+
98+
assert.Contains(t, cv.Component.Resources, ocmcli.Resource{
99+
Name: "test-resource",
100+
Version: "v0.0.1",
101+
Type: "blob",
102+
Access: ocmcli.Access{
103+
Type: "localBlob",
104+
LocalReference: cv.Component.Resources[0].Access.LocalReference,
105+
MediaType: ptr.To("application/octet-stream"),
106+
},
107+
})
108+
},
109+
},
110+
{
111+
desc: "get component version with ocm config",
112+
componentRef: ctfIn,
113+
ocmConfig: "./testdata/ocm-config.yaml",
114+
expectedError: nil,
115+
},
116+
{
117+
desc: "get component version with invalid reference",
118+
componentRef: "invalid-component-ref",
119+
ocmConfig: ocmcli.NoOcmConfig,
120+
expectedError: expectError,
121+
},
122+
}
123+
124+
for _, tc := range testCases {
125+
t.Run(tc.desc, func(t *testing.T) {
126+
cv, err := ocmcli.GetComponentVersion(t.Context(), tc.componentRef, tc.ocmConfig)
127+
128+
if tc.expectedError != nil {
129+
assert.Error(t, err)
130+
} else {
131+
assert.NoError(t, err)
132+
}
133+
134+
if tc.verify != nil {
135+
tc.verify(cv)
136+
}
137+
})
138+
}
139+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
components:
2+
- name: github.com/openmcp-project/bootstrapper/test
3+
version: v0.0.1
4+
provider:
5+
name: openmcp-project
6+
7+
componentReferences:
8+
- componentName: github.com/openmcp-project/bootstrapper-dependency-a
9+
name: bootstrapper-dependency-a
10+
version: v0.2.0
11+
12+
- componentName: github.com/openmcp-project/bootstrapper-dependency-b
13+
name: bootstrapper-dependency-b
14+
version: v0.3.0
15+
16+
resources:
17+
- name: test-resource
18+
type: blob
19+
input:
20+
type: file
21+
path: ./test-resource.yaml
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
type: generic.config.ocm.software/v1
2+
configurations:
3+
- type: credentials.config.ocm.software
4+
repositories:
5+
- repository:
6+
type: DockerConfig/v1
7+
dockerConfigFile: "~/.docker/config.json"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
config:
2+
vars:
3+
- a: "a"
4+
- b: "b"

0 commit comments

Comments
 (0)