Skip to content

Commit 9b22cca

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

File tree

5 files changed

+83
-5
lines changed

5 files changed

+83
-5
lines changed

api/producer/options.go

+12-3
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

+36
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

+13
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,22 @@ func (p *specFormatter) validate() error {
8383
return nil
8484
}
8585

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

api/producer/writer.go

+3-2
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

+19
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,25 @@ devices: null
126126
kind: example.com/class
127127
`,
128128
},
129+
{
130+
description: "minimum version is detected",
131+
spec: cdi.Spec{
132+
Version: cdi.CurrentVersion,
133+
Kind: "example.com/class",
134+
ContainerEdits: cdi.ContainerEdits{
135+
DeviceNodes: []*cdi.DeviceNode{
136+
{
137+
Path: "/dev/foo",
138+
},
139+
},
140+
},
141+
},
142+
options: []Option{WithDetectMinimumVersion(true)},
143+
filename: "foo",
144+
expectedFilename: "foo.yaml",
145+
expectedPermissions: 0600,
146+
expectedOutput: `---
147+
cdiVersion: 0.3.0
129148
containerEdits:
130149
deviceNodes:
131150
- path: /dev/foo

0 commit comments

Comments
 (0)