Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CDI devices to device flag #2280

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ jobs:
run: |
sudo apt-get install -y expect
go install -v gotest.tools/gotestsum@v1
- name: Enable CDI in the Docker daemon.
run: |
sudo mkdir -p /etc/docker
echo '{ "features": {"cdi": true} }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
- name: "Ensure that the integration test suite is compatible with Docker"
run: WITH_SUDO=true ./hack/test-integration.sh -test.target=docker
- name: "Ensure that the IPv6 integration test suite is compatible with Docker"
Expand Down
14 changes: 13 additions & 1 deletion cmd/nerdctl/container/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"runtime"

"github.com/spf13/cobra"
cdi "tags.cncf.io/container-device-interface/pkg/parser"

"github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers"
"github.com/containerd/nerdctl/v2/pkg/api/types"
Expand Down Expand Up @@ -211,10 +212,18 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt
if err != nil {
return opt, err
}
opt.Device, err = cmd.Flags().GetStringSlice("device")

allDevices, err := cmd.Flags().GetStringSlice("device")
if err != nil {
return opt, err
}
for _, device := range allDevices {
if cdi.IsQualifiedName(device) {
opt.CDIDevices = append(opt.CDIDevices, device)
continue
}
opt.Device = append(opt.Device, device)
}
// #endregion

// #region for intel RDT flags
Expand Down Expand Up @@ -431,6 +440,9 @@ func createAction(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
if len(createOpt.CDIDevices) > 0 && !createOpt.GOptions.Experimental {
return fmt.Errorf("specifying CDI devices in the device flag requires experimental mode to be enabled")
}

if (createOpt.Platform == "windows" || createOpt.Platform == "freebsd") && !createOpt.GOptions.Experimental {
return fmt.Errorf("%s requires experimental mode to be enabled", createOpt.Platform)
Expand Down
17 changes: 17 additions & 0 deletions cmd/nerdctl/container/container_run_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,20 @@ func TestPortBindingWithCustomHost(t *testing.T) {

testCase.Run(t)
}

func TestRunDeviceCDI(t *testing.T) {
// Although CDI injection is supported by Docker, specifying the --cdi-spec-dirs on the command line is not.
testutil.DockerIncompatible(t)
cwd, err := os.Getwd()
assert.NilError(t, err)
cdiSpecDir := filepath.Join(cwd, "testdata", "cdi")

base := testutil.NewBase(t)
containerName := testutil.Identifier(t)
defer base.Cmd("rm", "-f", containerName).AssertOK()
base.Cmd("--cdi-spec-dirs", cdiSpecDir, "run",
"--rm",
"--device", "vendor1.com/device=foo",
testutil.AlpineImage, "env",
).AssertOutContains("FOO=injected")
}
6 changes: 6 additions & 0 deletions cmd/nerdctl/helpers/flagutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error)
if err != nil {
return types.GlobalCommandOptions{}, err
}
cdiSpecDirs, err := cmd.Flags().GetStringSlice("cdi-spec-dirs")
if err != nil {
return types.GlobalCommandOptions{}, err
}

return types.GlobalCommandOptions{
Debug: debug,
DebugFull: debugFull,
Expand All @@ -123,6 +128,7 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error)
HostGatewayIP: hostGatewayIP,
BridgeIP: bridgeIP,
KubeHideDupe: kubeHideDupe,
CDISpecDirs: cdiSpecDirs,
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions cmd/nerdctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet,
helpers.AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host")
helpers.AddPersistentStringFlag(rootCmd, "bridge-ip", nil, nil, nil, aliasToBeInherited, cfg.BridgeIP, "NERDCTL_BRIDGE_IP", "IP address for the default nerdctl bridge network")
rootCmd.PersistentFlags().Bool("kube-hide-dupe", cfg.KubeHideDupe, "Deduplicate images for Kubernetes with namespace k8s.io")
rootCmd.PersistentFlags().StringSlice("cdi-spec-dirs", cfg.CDISpecDirs, "The directories to search for CDI spec files. Defaults to /etc/cdi,/var/run/cdi")
return aliasToBeInherited, nil
}

Expand Down
7 changes: 7 additions & 0 deletions cmd/nerdctl/testdata/cdi/vendor1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cdiVersion: "0.3.0"
kind: "vendor1.com/device"
devices:
- name: foo
containerEdits:
env:
- FOO=injected
1 change: 1 addition & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ experimental = true
| `host_gateway_ip` | `--host-gateway-ip` | `NERDCTL_HOST_GATEWAY_IP` | IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host | Since 1.3.0 |
| `bridge_ip` | `--bridge-ip` | `NERDCTL_BRIDGE_IP` | IP address for the default nerdctl bridge network, e.g., 10.1.100.1/24 | Since 2.0.1 |
| `kube_hide_dupe` | `--kube-hide-dupe` | | Deduplicate images for Kubernetes with namespace k8s.io, no more redundant <none> ones are displayed | Since 2.0.3 |
| `cdi_spec_dirs` | `--cdi-spec-dirs` | | The folders to use when searching for CDI specifications.| experimental |

The properties are parsed in the following precedence:
1. CLI flag
Expand Down
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ require (
github.com/containerd/accelerated-container-image v1.3.0
github.com/containerd/cgroups/v3 v3.0.5
github.com/containerd/console v1.0.4
github.com/containerd/containerd v1.7.23
github.com/containerd/containerd/api v1.8.0
github.com/containerd/containerd/v2 v2.0.2
github.com/containerd/continuity v0.4.5
github.com/containerd/containerd/v2 v2.0.0
github.com/containerd/continuity v0.4.4
github.com/containerd/errdefs v1.0.0
github.com/containerd/fifo v1.1.0
github.com/containerd/go-cni v1.1.12
Expand Down Expand Up @@ -68,6 +69,7 @@ require (
golang.org/x/text v0.22.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.2
tags.cncf.io/container-device-interface v0.8.1
)

require (
Expand Down Expand Up @@ -140,7 +142,6 @@ require (
google.golang.org/protobuf v1.36.2 // indirect
lukechampine.com/blake3 v1.3.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface v0.8.0 // indirect
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect
)

Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJ
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/containerd/v2 v2.0.2 h1:GmH/tRBlTvrXOLwSpWE2vNAm8+MqI6nmxKpKBNKY8Wc=
github.com/containerd/containerd/v2 v2.0.2/go.mod h1:wIqEvQ/6cyPFUGJ5yMFanspPabMLor+bF865OHvNTTI=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM=
github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
Expand Down Expand Up @@ -510,7 +512,7 @@ lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
tags.cncf.io/container-device-interface v0.8.1 h1:c0jN4Mt6781jD67NdPajmZlD1qrqQyov/Xfoab37lj0=
tags.cncf.io/container-device-interface v0.8.1/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=
2 changes: 2 additions & 0 deletions pkg/api/types/container_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ type ContainerCreateOptions struct {
CgroupParent string
// Device specifies add a host device to the container
Device []string
// CDIDevices specifies the CDI devices to add to the container
CDIDevices []string
// #endregion

// #region for intel RDT flags
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
}
opts = append(opts, platformOpts...)

opts = append(opts, withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...))

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / build | 1.23.x

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / build | 1.24.x

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | freebsd |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | freebsd |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | freebsd |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | freebsd |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | freebsd |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | windows |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | windows |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | windows |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | windows |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | windows |

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / unit | linux

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux | go-canary

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux | go-canary

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux | go-canary

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux | go-canary

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / go | linux | go-canary

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append) (typecheck)

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / windows

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / windows

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

Check failure on line 127 in pkg/cmd/container/create.go

View workflow job for this annotation

GitHub Actions / unit | windows

cannot use withCDIDevices(options.GOptions.CDISpecDirs, options.CDIDevices...) (value of func type "github.com/containerd/containerd/oci".SpecOpts) as "github.com/containerd/containerd/v2/pkg/oci".SpecOpts value in argument to append

if _, err := referenceutil.Parse(args[0]); errors.Is(err, referenceutil.ErrLoadOCIArchiveRequired) {
imageRef := args[0]

Expand Down
64 changes: 64 additions & 0 deletions pkg/cmd/container/run_cdi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright The containerd Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package container

import (
"context"
"fmt"

"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/oci"
"github.com/containerd/log"
"tags.cncf.io/container-device-interface/pkg/cdi"
)

// withCDIDevices creates the OCI runtime spec options for injecting CDI devices.
// Two options are returned: The first ensures that the CDI registry is initialized with
// refresh disabled, and the second injects the devices into the container.
func withCDIDevices(cdiSpecDirs []string, devices ...string) oci.SpecOpts {
return func(ctx context.Context, _ oci.Client, c *containers.Container, s *oci.Spec) error {
if len(devices) == 0 {
return nil
}

// We configure the CDI registry with the configured spec dirs and disable refresh.
cdi.Configure(
cdi.WithSpecDirs(cdiSpecDirs...),
cdi.WithAutoRefresh(false),
)

// TODO: Call oci.WithCDIDevices(devices...) here once the dependencies have been updated.
if err := cdi.Refresh(); err != nil {
// We don't consider registry refresh failure a fatal error.
// For instance, a dynamically generated invalid CDI Spec file for
// any particular vendor shouldn't prevent injection of devices of
// different vendors. CDI itself knows better and it will fail the
// injection if necessary.
log.G(ctx).Warnf("CDI registry refresh failed: %v", err)
}

if _, err := cdi.InjectDevices(s, devices...); err != nil {
return fmt.Errorf("CDI device injection failed: %w", err)
}

// One crucial thing to keep in mind is that CDI device injection
// might add OCI Spec environment variables, hooks, and mounts as
// well. Therefore it is important that none of the corresponding
// OCI Spec fields are reset up in the call stack once we return.
return nil
}
}
3 changes: 3 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type Config struct {
HostGatewayIP string `toml:"host_gateway_ip"`
BridgeIP string `toml:"bridge_ip, omitempty"`
KubeHideDupe bool `toml:"kube_hide_dupe"`
// CDISpecDirs is a list of directories in which CDI specifications can be found.
CDISpecDirs []string `toml:"cdi_spec_dirs,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bike shedding: "Dirs" vs "Path"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"CDIPath" might be more consistent with the existing "CNIPath"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that these are specifically directories and not files. Furthermore, the naming is consistent with this setting in other projects: containerd, cri-o, docker, singularity.

I'm happy to change if you feel strongly about it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the naming is consistent with this setting in other projects: containerd, cri-o, docker, singularity.

👍

}

// New creates a default Config object statically,
Expand All @@ -61,5 +63,6 @@ func New() *Config {
Experimental: true,
HostGatewayIP: ncdefaults.HostGatewayIP(),
KubeHideDupe: false,
CDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
Loading