Skip to content

Commit b0797a6

Browse files
committed
Add logic to detect minimum spec version on save
Signed-off-by: Evan Lezar <[email protected]>
1 parent 7c6a5ea commit b0797a6

File tree

5 files changed

+97
-5
lines changed

5 files changed

+97
-5
lines changed

api/producer/options.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,18 @@ import (
2525
type Option func(*options) error
2626

2727
type options struct {
28-
specFormat SpecFormat
29-
overwrite bool
30-
permissions fs.FileMode
28+
specFormat SpecFormat
29+
overwrite bool
30+
permissions fs.FileMode
31+
detectMinimumVersion bool
32+
}
33+
34+
// WithDetectMinimumVersion toggles whether a minimum version should be detected for a CDI specification.
35+
func WithDetectMinimumVersion(detectMinimumVersion bool) Option {
36+
return func(o *options) error {
37+
o.detectMinimumVersion = detectMinimumVersion
38+
return nil
39+
}
3140
}
3241

3342
// WithSpecFormat sets the output format of a CDI specification.

api/producer/set-minimum-version.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright © 2025 The CDI Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package producer
18+
19+
import (
20+
"fmt"
21+
22+
cdi "tags.cncf.io/container-device-interface/specs-go"
23+
)
24+
25+
type setMinimumRequiredVersion struct{}
26+
27+
// transform detects the minimum required version required for the specified
28+
// spec and sets the version field accordingly.
29+
func (d setMinimumRequiredVersion) transform(spec *cdi.Spec) error {
30+
minVersion, err := cdi.MinimumRequiredVersion(spec)
31+
if err != nil {
32+
return fmt.Errorf("failed to get minimum required CDI spec version: %w", err)
33+
}
34+
spec.Version = minVersion
35+
return nil
36+
}

api/producer/spec-format.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,22 @@ func (p *formattedSpec) validate() error {
8585
return nil
8686
}
8787

88+
// transform applies a transform to the spec associated with the CDI spec formatter.
89+
// This is currently limited to detecting (and updating) the spec so that the minimum
90+
// CDI spec version is used, but could be extended to apply other transformations.
91+
func (p *formattedSpec) transform() error {
92+
if !p.detectMinimumVersion {
93+
return nil
94+
}
95+
return (&setMinimumRequiredVersion{}).transform(p.Spec)
96+
}
97+
8898
// contents returns the raw contents of a CDI specification.
8999
// Validation is performed before marshalling the contentent based on the spec format.
90100
func (p *formattedSpec) contents() ([]byte, error) {
101+
if err := p.transform(); err != nil {
102+
return nil, fmt.Errorf("spec transform failed: %w", err)
103+
}
91104
if err := p.validate(); err != nil {
92105
return nil, fmt.Errorf("spec validation failed: %w", err)
93106
}

api/producer/writer.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ func NewSpecWriter(opts ...Option) (*SpecWriter, error) {
3636
options: options{
3737
overwrite: true,
3838
// TODO: This could be updated to 0644 to be world-readable.
39-
permissions: 0600,
40-
specFormat: DefaultSpecFormat,
39+
permissions: 0600,
40+
specFormat: DefaultSpecFormat,
41+
detectMinimumVersion: false,
4142
},
4243
}
4344
for _, opt := range opts {

api/producer/writer_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,39 @@ devices:
148148
- path: /dev/foo
149149
name: dev1
150150
kind: example.com/class
151+
`,
152+
},
153+
{
154+
description: "minimum version is detected",
155+
spec: cdi.Spec{
156+
Version: cdi.CurrentVersion,
157+
Kind: "example.com/class",
158+
Devices: []cdi.Device{
159+
{
160+
Name: "dev1",
161+
ContainerEdits: cdi.ContainerEdits{
162+
DeviceNodes: []*cdi.DeviceNode{
163+
{
164+
Path: "/dev/foo",
165+
},
166+
},
167+
},
168+
},
169+
},
170+
},
171+
options: []Option{WithDetectMinimumVersion(true)},
172+
filename: "foo",
173+
expectedFilename: "foo.yaml",
174+
expectedPermissions: 0600,
175+
expectedOutput: `---
176+
cdiVersion: 0.3.0
177+
containerEdits: {}
178+
devices:
179+
- containerEdits:
180+
deviceNodes:
181+
- path: /dev/foo
182+
name: dev1
183+
kind: example.com/class
151184
`,
152185
},
153186
}

0 commit comments

Comments
 (0)