Skip to content

Commit 43fe7c4

Browse files
committed
Switch to CDI producer API
This change switces to the CDI producer API to write CDI specifications. Signed-off-by: Evan Lezar <[email protected]>
1 parent 5ef7a39 commit 43fe7c4

File tree

26 files changed

+547
-885
lines changed

26 files changed

+547
-885
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
golang.org/x/mod v0.22.0
1515
golang.org/x/sys v0.29.0
1616
tags.cncf.io/container-device-interface v0.8.0
17+
tags.cncf.io/container-device-interface/api/producer v0.0.0
1718
tags.cncf.io/container-device-interface/specs-go v0.8.0
1819
)
1920

@@ -39,6 +40,6 @@ require (
3940

4041
replace (
4142
tags.cncf.io/container-device-interface => ../container-device-interface
42-
tags.cncf.io/container-device-interface/specs-go => ../container-device-interface/specs-go
4343
tags.cncf.io/container-device-interface/api/producer => ../container-device-interface/api/producer
44+
tags.cncf.io/container-device-interface/specs-go => ../container-device-interface/specs-go
4445
)

go.sum

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,3 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
8888
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8989
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
9090
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
91-
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
92-
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
93-
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
94-
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=

pkg/nvcdi/spec/builder.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,28 @@ import (
2020
"fmt"
2121
"os"
2222

23-
"tags.cncf.io/container-device-interface/pkg/cdi"
23+
"tags.cncf.io/container-device-interface/api/producer"
2424
"tags.cncf.io/container-device-interface/pkg/parser"
25-
"tags.cncf.io/container-device-interface/specs-go"
25+
cdi "tags.cncf.io/container-device-interface/specs-go"
2626

2727
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform"
2828
)
2929

3030
type builder struct {
31-
raw *specs.Spec
31+
raw *cdi.Spec
3232
version string
3333
vendor string
3434
class string
35-
deviceSpecs []specs.Device
36-
edits specs.ContainerEdits
35+
deviceSpecs []cdi.Device
36+
edits cdi.ContainerEdits
3737
format string
3838

3939
mergedDeviceOptions []transform.MergedDeviceOption
4040
noSimplify bool
4141
permissions os.FileMode
4242

43-
transformOnSave transform.Transformer
43+
detectMinimumVersion bool
44+
transformOnSave transform.Transformer
4445
}
4546

4647
// newBuilder creates a new spec builder with the supplied options
@@ -64,7 +65,7 @@ func newBuilder(opts ...Option) *builder {
6465
}
6566
}
6667
if s.version == "" || s.version == DetectMinimumVersion {
67-
s.transformOnSave = &setMinimumRequiredVersion{}
68+
s.detectMinimumVersion = true
6869
s.version = cdi.CurrentVersion
6970
}
7071
if s.vendor == "" {
@@ -86,7 +87,7 @@ func newBuilder(opts ...Option) *builder {
8687
func (o *builder) Build() (*spec, error) {
8788
raw := o.raw
8889
if raw == nil {
89-
raw = &specs.Spec{
90+
raw = &cdi.Spec{
9091
Version: o.version,
9192
Kind: fmt.Sprintf("%s/%s", o.vendor, o.class),
9293
Devices: o.deviceSpecs,
@@ -114,11 +115,26 @@ func (o *builder) Build() (*spec, error) {
114115
}
115116
}
116117

118+
options := []producer.Option{
119+
producer.WithDetectMinimumVersion(o.detectMinimumVersion),
120+
producer.WithPermissions(o.permissions),
121+
}
122+
switch o.format {
123+
case FormatJSON:
124+
options = append(options, producer.WithSpecFormat(producer.SpecFormatJSON))
125+
case FormatYAML:
126+
options = append(options, producer.WithSpecFormat(producer.SpecFormatYAML))
127+
}
128+
129+
producer, err := producer.NewSpecWriter(options...)
130+
if err != nil {
131+
return nil, err
132+
}
133+
117134
s := spec{
118-
Spec: raw,
119-
format: o.format,
120-
permissions: o.permissions,
135+
raw: raw,
121136
transformOnSave: o.transformOnSave,
137+
SpecWriter: producer,
122138
}
123139
return &s, nil
124140
}
@@ -127,14 +143,14 @@ func (o *builder) Build() (*spec, error) {
127143
type Option func(*builder)
128144

129145
// WithDeviceSpecs sets the device specs for the spec builder
130-
func WithDeviceSpecs(deviceSpecs []specs.Device) Option {
146+
func WithDeviceSpecs(deviceSpecs []cdi.Device) Option {
131147
return func(o *builder) {
132148
o.deviceSpecs = deviceSpecs
133149
}
134150
}
135151

136152
// WithEdits sets the container edits for the spec builder
137-
func WithEdits(edits specs.ContainerEdits) Option {
153+
func WithEdits(edits cdi.ContainerEdits) Option {
138154
return func(o *builder) {
139155
o.edits = edits
140156
}
@@ -176,7 +192,7 @@ func WithNoSimplify(noSimplify bool) Option {
176192
}
177193

178194
// WithRawSpec sets the raw spec for the spec builder
179-
func WithRawSpec(raw *specs.Spec) Option {
195+
func WithRawSpec(raw *cdi.Spec) Option {
180196
return func(o *builder) {
181197
o.raw = raw
182198
}

pkg/nvcdi/spec/set-minimum-version.go

Lines changed: 0 additions & 35 deletions
This file was deleted.

pkg/nvcdi/spec/spec.go

Lines changed: 20 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,18 @@
1717
package spec
1818

1919
import (
20-
"fmt"
2120
"io"
22-
"os"
23-
"path/filepath"
2421

25-
"tags.cncf.io/container-device-interface/pkg/cdi"
26-
"tags.cncf.io/container-device-interface/specs-go"
22+
"tags.cncf.io/container-device-interface/api/producer"
23+
cdi "tags.cncf.io/container-device-interface/specs-go"
2724

2825
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform"
2926
)
3027

3128
type spec struct {
32-
*specs.Spec
33-
format string
34-
permissions os.FileMode
29+
raw *cdi.Spec
3530
transformOnSave transform.Transformer
31+
*producer.SpecWriter
3632
}
3733

3834
var _ Interface = (*spec)(nil)
@@ -42,96 +38,32 @@ func New(opts ...Option) (Interface, error) {
4238
return newBuilder(opts...).Build()
4339
}
4440

41+
// Raw returns a pointer to the raw spec.
42+
func (s *spec) Raw() *cdi.Spec {
43+
return s.raw
44+
}
45+
4546
// Save writes the spec to the specified path and overwrites the file if it exists.
4647
func (s *spec) Save(path string) error {
4748
if s.transformOnSave != nil {
48-
err := s.transformOnSave.Transform(s.Raw())
49+
err := s.transformOnSave.Transform(s.raw)
4950
if err != nil {
50-
return fmt.Errorf("error applying transform: %w", err)
51+
return err
5152
}
5253
}
53-
path, err := s.normalizePath(path)
54-
if err != nil {
55-
return fmt.Errorf("failed to normalize path: %w", err)
56-
}
57-
58-
specDir := filepath.Dir(path)
59-
cache, _ := cdi.NewCache(
60-
cdi.WithAutoRefresh(false),
61-
cdi.WithSpecDirs(specDir),
62-
)
63-
if err := cache.WriteSpec(s.Raw(), filepath.Base(path)); err != nil {
64-
return fmt.Errorf("failed to write spec: %w", err)
65-
}
66-
67-
if err := os.Chmod(path, s.permissions); err != nil {
68-
return fmt.Errorf("failed to set permissions on spec file: %w", err)
69-
}
70-
71-
return nil
54+
// TODO: We should add validation here.
55+
_, err := s.SpecWriter.Save(s.raw, path)
56+
return err
7257
}
7358

74-
// WriteTo writes the spec to the specified writer.
59+
// WriteTo writes the configured spec to the specified writer.
7560
func (s *spec) WriteTo(w io.Writer) (int64, error) {
76-
name, err := cdi.GenerateNameForSpec(s.Raw())
77-
if err != nil {
78-
return 0, err
79-
}
80-
81-
path, _ := s.normalizePath(name)
82-
tmpFile, err := os.CreateTemp("", "*"+filepath.Base(path))
83-
if err != nil {
84-
return 0, err
85-
}
86-
defer os.Remove(tmpFile.Name())
87-
88-
if err := s.Save(tmpFile.Name()); err != nil {
89-
return 0, err
90-
}
91-
92-
err = tmpFile.Close()
93-
if err != nil {
94-
return 0, fmt.Errorf("failed to close temporary file: %w", err)
95-
}
96-
97-
r, err := os.Open(tmpFile.Name())
98-
if err != nil {
99-
return 0, fmt.Errorf("failed to open temporary file: %w", err)
100-
}
101-
defer r.Close()
102-
103-
return io.Copy(w, r)
104-
}
105-
106-
// Raw returns a pointer to the raw spec.
107-
func (s *spec) Raw() *specs.Spec {
108-
return s.Spec
109-
}
110-
111-
// normalizePath ensures that the specified path has a supported extension
112-
func (s *spec) normalizePath(path string) (string, error) {
113-
if ext := filepath.Ext(path); ext != ".yaml" && ext != ".json" {
114-
path += s.extension()
115-
}
116-
117-
if filepath.Clean(filepath.Dir(path)) == "." {
118-
pwd, err := os.Getwd()
61+
if s.transformOnSave != nil {
62+
err := s.transformOnSave.Transform(s.raw)
11963
if err != nil {
120-
return path, fmt.Errorf("failed to get current working directory: %v", err)
64+
return 0, err
12165
}
122-
path = filepath.Join(pwd, path)
123-
}
124-
125-
return path, nil
126-
}
127-
128-
func (s *spec) extension() string {
129-
switch s.format {
130-
case FormatJSON:
131-
return ".json"
132-
case FormatYAML:
133-
return ".yaml"
13466
}
135-
136-
return ".yaml"
67+
// TODO: We should add validation here.
68+
return s.SpecWriter.WriteSpecTo(s.raw, w)
13769
}

vendor/modules.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,18 @@ gopkg.in/yaml.v3
8787
# sigs.k8s.io/yaml v1.3.0
8888
## explicit; go 1.12
8989
sigs.k8s.io/yaml
90-
# tags.cncf.io/container-device-interface v0.8.0
90+
# tags.cncf.io/container-device-interface v0.8.0 => ../container-device-interface
9191
## explicit; go 1.20
9292
tags.cncf.io/container-device-interface/internal/validation
9393
tags.cncf.io/container-device-interface/internal/validation/k8s
9494
tags.cncf.io/container-device-interface/pkg/cdi
9595
tags.cncf.io/container-device-interface/pkg/parser
96-
# tags.cncf.io/container-device-interface/specs-go v0.8.0
96+
# tags.cncf.io/container-device-interface/api/producer v0.0.0 => ../container-device-interface/api/producer
97+
## explicit; go 1.20
98+
tags.cncf.io/container-device-interface/api/producer
99+
# tags.cncf.io/container-device-interface/specs-go v0.8.0 => ../container-device-interface/specs-go
97100
## explicit; go 1.19
98101
tags.cncf.io/container-device-interface/specs-go
102+
# tags.cncf.io/container-device-interface => ../container-device-interface
103+
# tags.cncf.io/container-device-interface/api/producer => ../container-device-interface/api/producer
104+
# tags.cncf.io/container-device-interface/specs-go => ../container-device-interface/specs-go

vendor/tags.cncf.io/container-device-interface/api/producer/api.go

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)