mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	Use nvcdi.spec package to write and validate spec
Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
		
							parent
							
								
									89321edae6
								
							
						
					
					
						commit
						890a519121
					
				| @ -18,7 +18,6 @@ package generate | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
| @ -26,13 +25,13 @@ import ( | |||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/discover" | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/discover" | ||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/edits" | 	"github.com/NVIDIA/nvidia-container-toolkit/internal/edits" | ||||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi" | 	"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi" | ||||||
|  | 	"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/spec" | ||||||
| 	"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" | 	"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" | ||||||
| 	specs "github.com/container-orchestrated-devices/container-device-interface/specs-go" | 	specs "github.com/container-orchestrated-devices/container-device-interface/specs-go" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/urfave/cli/v2" | 	"github.com/urfave/cli/v2" | ||||||
| 	"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device" | 	"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device" | ||||||
| 	"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml" | 	"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml" | ||||||
| 	"sigs.k8s.io/yaml" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| @ -118,7 +117,8 @@ func (m command) build() *cli.Command { | |||||||
| 	return &c | 	return &c | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m command) validateFlags(r *cli.Context, cfg *config) error { | func (m command) validateFlags(c *cli.Context, cfg *config) error { | ||||||
|  | 
 | ||||||
| 	cfg.format = strings.ToLower(cfg.format) | 	cfg.format = strings.ToLower(cfg.format) | ||||||
| 	switch cfg.format { | 	switch cfg.format { | ||||||
| 	case formatJSON: | 	case formatJSON: | ||||||
| @ -143,31 +143,6 @@ func (m command) validateFlags(r *cli.Context, cfg *config) error { | |||||||
| 
 | 
 | ||||||
| 	cfg.nvidiaCTKPath = discover.FindNvidiaCTK(m.logger, cfg.nvidiaCTKPath) | 	cfg.nvidiaCTKPath = discover.FindNvidiaCTK(m.logger, cfg.nvidiaCTKPath) | ||||||
| 
 | 
 | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (m command) run(c *cli.Context, cfg *config) error { |  | ||||||
| 	spec, err := m.generateSpec(cfg) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("failed to generate CDI spec: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	var outputTo io.Writer |  | ||||||
| 	if cfg.output == "" { |  | ||||||
| 		outputTo = os.Stdout |  | ||||||
| 	} else { |  | ||||||
| 		err := createParentDirsIfRequired(cfg.output) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("failed to create parent folders for output file: %v", err) |  | ||||||
| 		} |  | ||||||
| 		outputFile, err := os.Create(cfg.output) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("failed to create output file: %v", err) |  | ||||||
| 		} |  | ||||||
| 		defer outputFile.Close() |  | ||||||
| 		outputTo = outputFile |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if outputFileFormat := formatFromFilename(cfg.output); outputFileFormat != "" { | 	if outputFileFormat := formatFromFilename(cfg.output); outputFileFormat != "" { | ||||||
| 		m.logger.Debugf("Inferred output format as %q from output file name", outputFileFormat) | 		m.logger.Debugf("Inferred output format as %q from output file name", outputFileFormat) | ||||||
| 		if !c.IsSet("format") { | 		if !c.IsSet("format") { | ||||||
| @ -177,25 +152,29 @@ func (m command) run(c *cli.Context, cfg *config) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	data, err := yaml.Marshal(spec) | 	return nil | ||||||
| 	if err != nil { | } | ||||||
| 		return fmt.Errorf("failed to marshal CDI spec: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	if strings.ToLower(cfg.format) == formatJSON { | func (m command) run(c *cli.Context, cfg *config) error { | ||||||
| 		data, err = yaml.YAMLToJSONStrict(data) | 	spec, err := m.generateSpec(cfg) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to generate CDI spec: %v", err) | ||||||
|  | 	} | ||||||
|  | 	m.logger.Infof("Generated CDI spec with version", spec.Raw().Version) | ||||||
|  | 
 | ||||||
|  | 	if cfg.output == "" { | ||||||
|  | 		_, err := spec.WriteTo(os.Stdout) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("failed to convert CDI spec from YAML to JSON: %v", err) | 			return fmt.Errorf("failed to write CDI spec to STDOUT: %v", err) | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = writeToOutput(cfg.format, data, outputTo) | 	err = createParentDirsIfRequired(cfg.output) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("failed to write output: %v", err) | 		return fmt.Errorf("failed to create parent folders for output file: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 	return spec.Save(cfg.output) | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func formatFromFilename(filename string) string { | func formatFromFilename(filename string) string { | ||||||
| @ -212,22 +191,7 @@ func formatFromFilename(filename string) string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func writeToOutput(format string, data []byte, output io.Writer) error { | func (m command) generateSpec(cfg *config) (spec.Interface, error) { | ||||||
| 	if format == formatYAML { |  | ||||||
| 		_, err := output.Write([]byte("---\n")) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("failed to write YAML separator: %v", err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	_, err := output.Write(data) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("failed to write data: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (m command) generateSpec(cfg *config) (*specs.Spec, error) { |  | ||||||
| 	deviceNamer, err := nvcdi.NewDeviceNamer(cfg.deviceNameStrategy) | 	deviceNamer, err := nvcdi.NewDeviceNamer(cfg.deviceNameStrategy) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("failed to create device namer: %v", err) | 		return nil, fmt.Errorf("failed to create device namer: %v", err) | ||||||
| @ -275,23 +239,13 @@ func (m command) generateSpec(cfg *config) (*specs.Spec, error) { | |||||||
| 		return nil, fmt.Errorf("failed to create edits common for entities: %v", err) | 		return nil, fmt.Errorf("failed to create edits common for entities: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// We construct the spec and determine the minimum required version based on the specification.
 | 	return spec.New( | ||||||
| 	spec := specs.Spec{ | 		spec.WithVendor("nvidia.com"), | ||||||
| 		Version:        "NOT_SET", | 		spec.WithClass("gpu"), | ||||||
| 		Kind:           "nvidia.com/gpu", | 		spec.WithDeviceSpecs(deviceSpecs), | ||||||
| 		Devices:        deviceSpecs, | 		spec.WithEdits(*commonEdits.ContainerEdits), | ||||||
| 		ContainerEdits: *commonEdits.ContainerEdits, | 		spec.WithFormat(cfg.format), | ||||||
| 	} | 	) | ||||||
| 
 |  | ||||||
| 	minVersion, err := cdi.MinimumRequiredVersion(&spec) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, fmt.Errorf("failed to get minumum required CDI spec version: %v", err) |  | ||||||
| 	} |  | ||||||
| 	m.logger.Infof("Using minimum required CDI spec version: %s", minVersion) |  | ||||||
| 
 |  | ||||||
| 	spec.Version = minVersion |  | ||||||
| 
 |  | ||||||
| 	return &spec, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // MergeDeviceSpecs creates a device with the specified name which combines the edits from the previous devices.
 | // MergeDeviceSpecs creates a device with the specified name which combines the edits from the previous devices.
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user