Skip to content

Commit f2fdcc0

Browse files
committed
TOFIX: Use producer API
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent 080dbf8 commit f2fdcc0

11 files changed

Lines changed: 434 additions & 171 deletions

File tree

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,5 @@ require (
4848
gopkg.in/yaml.v3 v3.0.1 // indirect
4949
sigs.k8s.io/yaml v1.4.0 // indirect
5050
)
51+
52+
replace tags.cncf.io/container-device-interface => ../container-device-interface

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
116116
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
117117
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
118118
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
119-
tags.cncf.io/container-device-interface v1.1.0 h1:RnxNhxF1JOu6CJUVpetTYvrXHdxw9j9jFYgZpI+anSY=
120-
tags.cncf.io/container-device-interface v1.1.0/go.mod h1:76Oj0Yqp9FwTx/pySDc8Bxjpg+VqXfDb50cKAXVJ34Q=
121119
tags.cncf.io/container-device-interface/specs-go v1.1.0 h1:QRZVeAceQM+zTZe12eyfuJuuzp524EKYwhmvLd+h+yQ=
122120
tags.cncf.io/container-device-interface/specs-go v1.1.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ=

pkg/nvcdi/spec/spec.go

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import (
2121
"io"
2222
"os"
2323
"path/filepath"
24+
"strings"
2425

2526
"tags.cncf.io/container-device-interface/pkg/cdi"
27+
producer "tags.cncf.io/container-device-interface/pkg/cdi-producer"
2628
"tags.cncf.io/container-device-interface/specs-go"
2729

2830
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform"
@@ -42,104 +44,95 @@ func New(opts ...Option) (Interface, error) {
4244
return newBuilder(opts...).Build()
4345
}
4446

45-
// Save writes the spec to the specified path and overwrites the file if it exists.
46-
func (s *spec) Save(path string) error {
47-
if s.transformOnSave != nil {
48-
err := s.transformOnSave.Transform(s.Raw())
47+
type Validator interface {
48+
Validate(*specs.Spec) error
49+
}
50+
51+
type Validators []Validator
52+
53+
func (v Validators) Validate(s *specs.Spec) error {
54+
for _, vv := range v {
55+
if vv == nil {
56+
continue
57+
}
58+
err := vv.Validate(s)
4959
if err != nil {
50-
return fmt.Errorf("error applying transform: %w", err)
60+
return err
5161
}
5262
}
53-
path, err := s.normalizePath(path)
54-
if err != nil {
55-
return fmt.Errorf("failed to normalize path: %w", err)
56-
}
63+
return nil
64+
}
5765

58-
specDir, filename := filepath.Split(path)
59-
cache, _ := cdi.NewCache(
60-
cdi.WithAutoRefresh(false),
61-
cdi.WithSpecDirs(specDir),
62-
)
63-
if err := cache.WriteSpec(s.Raw(), filename); err != nil {
64-
return fmt.Errorf("failed to write spec: %w", err)
65-
}
66+
type transfromAsValidator struct {
67+
transform.Transformer
68+
}
6669

67-
specDirAsRoot, err := os.OpenRoot(specDir)
68-
if err != nil {
69-
return fmt.Errorf("failed to open root: %w", err)
70+
func fromTransform(t transform.Transformer) Validator {
71+
if t == nil {
72+
return nil
7073
}
71-
defer specDirAsRoot.Close()
74+
return &transfromAsValidator{t}
75+
}
7276

73-
if err := specDirAsRoot.Chmod(filename, s.permissions); err != nil {
74-
return fmt.Errorf("failed to set permissions on spec file: %w", err)
77+
func (t *transfromAsValidator) Validate(s *specs.Spec) error {
78+
if t == nil || t.Transformer == nil {
79+
return nil
80+
}
81+
if err := t.Transform(s); err != nil {
82+
return fmt.Errorf("error applying transform: %w", err)
7583
}
76-
7784
return nil
7885
}
7986

80-
// WriteTo writes the spec to the specified writer.
81-
func (s *spec) WriteTo(w io.Writer) (int64, error) {
82-
tmpFile, err := os.CreateTemp("", "nvcdi-spec-*"+s.extension())
83-
if err != nil {
84-
return 0, err
85-
}
86-
tmpDir, tmpFileName := filepath.Split(tmpFile.Name())
87-
88-
tmpDirRoot, err := os.OpenRoot(tmpDir)
89-
if err != nil {
90-
return 0, err
87+
// Save writes the spec to the specified path and overwrites the file if it exists.
88+
func (s *spec) Save(path string) error {
89+
if pathWithExtension := s.ensureExtension(path); pathWithExtension != "" {
90+
return producer.Save(s.Raw(), pathWithExtension,
91+
s.producerOptions()...,
92+
)
9193
}
92-
defer tmpDirRoot.Close()
93-
defer func() {
94-
_ = tmpDirRoot.Remove(tmpFileName)
95-
}()
94+
_, err := s.WriteTo(os.Stdout)
95+
return err
96+
}
9697

97-
if err := s.Save(tmpFile.Name()); err != nil {
98-
return 0, err
99-
}
98+
// WriteTo writes the spec to the specified writer.
99+
func (s *spec) WriteTo(w io.Writer) (int64, error) {
100+
return producer.WriteTo(s.Raw(), w,
101+
s.producerOptions()...,
102+
)
103+
}
100104

101-
if err := tmpFile.Close(); err != nil {
102-
return 0, fmt.Errorf("failed to close temporary file: %w", err)
105+
func (s *spec) producerOptions() []producer.Option {
106+
var validators Validators
107+
if s.transformOnSave != nil {
108+
validators = append(validators, fromTransform(s.transformOnSave))
103109
}
110+
validators = append(validators, cdi.SpecContentValidator)
104111

105-
savedFile, err := tmpDirRoot.Open(tmpFileName)
106-
if err != nil {
107-
return 0, fmt.Errorf("failed to open temporary file: %w", err)
112+
return []producer.Option{
113+
producer.WithOutputFormat(s.format),
114+
producer.WithOverwrite(true),
115+
producer.WithPermissions(s.permissions),
116+
producer.WithValidator(validators),
108117
}
109-
defer savedFile.Close()
110-
111-
return savedFile.WriteTo(w)
112118
}
113119

114120
// Raw returns a pointer to the raw spec.
115121
func (s *spec) Raw() *specs.Spec {
116122
return s.Spec
117123
}
118124

119-
// normalizePath ensures that the specified path has a supported extension
120-
func (s *spec) normalizePath(path string) (string, error) {
121-
if ext := filepath.Ext(path); ext != ".yaml" && ext != ".json" {
122-
path += s.extension()
125+
func (s *spec) ensureExtension(filename string) string {
126+
if filename == "" {
127+
return ""
123128
}
124-
125-
if filepath.Clean(filepath.Dir(path)) == "." {
126-
pwd, err := os.Getwd()
127-
if err != nil {
128-
return path, fmt.Errorf("failed to get current working directory: %v", err)
129-
}
130-
path = filepath.Join(pwd, path)
129+
ext := filepath.Ext(filename)
130+
switch ext {
131+
case ".yaml", ".json":
132+
return filename
133+
case ".yml":
134+
return strings.TrimSuffix(filename, ".yml") + ".yaml"
135+
default:
136+
return filename + "." + s.format
131137
}
132-
133-
return path, nil
134-
}
135-
136-
func (s *spec) extension() string {
137-
switch s.format {
138-
case FormatJSON:
139-
return ".json"
140-
case FormatYAML:
141-
return ".yaml"
142-
}
143-
144-
return ".yaml"
145138
}

vendor/modules.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,14 @@ gopkg.in/yaml.v3
234234
## explicit; go 1.12
235235
sigs.k8s.io/yaml
236236
sigs.k8s.io/yaml/goyaml.v2
237-
# tags.cncf.io/container-device-interface v1.1.0
237+
# tags.cncf.io/container-device-interface v1.1.0 => ../container-device-interface
238238
## explicit; go 1.21
239239
tags.cncf.io/container-device-interface/internal/validation
240240
tags.cncf.io/container-device-interface/internal/validation/k8s
241241
tags.cncf.io/container-device-interface/pkg/cdi
242+
tags.cncf.io/container-device-interface/pkg/cdi-producer
242243
tags.cncf.io/container-device-interface/pkg/parser
243244
# tags.cncf.io/container-device-interface/specs-go v1.1.0
244245
## explicit; go 1.19
245246
tags.cncf.io/container-device-interface/specs-go
247+
# tags.cncf.io/container-device-interface => ../container-device-interface

vendor/tags.cncf.io/container-device-interface/pkg/cdi/spec_linux.go renamed to vendor/tags.cncf.io/container-device-interface/pkg/cdi-producer/renamein_linux.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/tags.cncf.io/container-device-interface/pkg/cdi/spec_other.go renamed to vendor/tags.cncf.io/container-device-interface/pkg/cdi-producer/renamein_other.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)