Skip to content

Remove dependency on github.com/opencontainers/runtime-tools#316

Closed
tianon-sso wants to merge 3 commits into
cncf-tags:mainfrom
tianon-sso:runtime-tools
Closed

Remove dependency on github.com/opencontainers/runtime-tools#316
tianon-sso wants to merge 3 commits into
cncf-tags:mainfrom
tianon-sso:runtime-tools

Conversation

@tianon-sso

Copy link
Copy Markdown

The generate package was used in two places purely as a convenience wrapper over *oci.Spec field mutations -- none of its logic was load-bearing. Replace it with direct spec manipulation throughout.

In pkg/cdi/container-edits.go, drop the ocigen.Generator value and operate on *oci.Spec directly in Apply. Extract small private helpers for the operations that have non-trivial logic: addMultipleProcessEnv (deduplicates by key), removeDevice and removeMount (find-and-splice), and addProcessAdditionalGid (append-if-absent).

In cmd/cdi/cmd/cdi-api.go, replace the three-step gen.NewFromSpec / ClearLinuxDevices / AddDevice sequence in collectCDIDevicesFromOCISpec with a single partition loop over spec.Linux.Devices.

Assisted-By: "claude my eyes right out"

The `generate` package was used in two places purely as a convenience wrapper over `*oci.Spec` field mutations -- none of its logic was load-bearing. Replace it with direct spec manipulation throughout.

In `pkg/cdi/container-edits.go`, drop the `ocigen.Generator` value and operate on `*oci.Spec` directly in `Apply`. Extract small private helpers for the operations that have non-trivial logic: `addMultipleProcessEnv` (deduplicates by key), `removeDevice` and `removeMount` (find-and-splice), and `addProcessAdditionalGid` (append-if-absent).

In `cmd/cdi/cmd/cdi-api.go`, replace the three-step `gen.NewFromSpec` / `ClearLinuxDevices` / `AddDevice` sequence in `collectCDIDevicesFromOCISpec` with a single partition loop over `spec.Linux.Devices`.

Assisted-By: "claude my eyes right out"
Signed-off-by: Tianon Gravi <tianon.gravi@docker.com>
@tianon-sso

Copy link
Copy Markdown
Author

Friendly ping - runtime-tools has historically been a problematic dependency across the ecosystem, and the lift to remove it is pretty small here 🙇

@elezar elezar self-requested a review June 9, 2026 22:14
@elezar

elezar commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Sorry for the delay here. I'll have a look tomorrow.

@elezar elezar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A first pass of this looks good. One question I would have is whether we wanted to add a local type that wrapps *oci.Spec like runtime-tools does to reduce the diff further, but I assume that it probably isn't worth the effort for the reduced feature set we have here.

@klihub what do you think?

@elezar elezar requested review from bart0sh, kad and klihub June 10, 2026 08:02
Signed-off-by: Evan Lezar <elezar@nvidia.com>
if specgen == nil || netDev == nil {
// addMultipleProcessEnv adds or replaces environment variables on the process,
// deduplicating by key.
func addMultipleProcessEnv(process *oci.Process, envs []string) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One thing that I want to call out (thanks Codex). There is a subtle difference between the new code and the original runtime-tools implementation. In the previous implemenation, the entries in envCache were constucted using ENV=value strings when loading an OCI spec. This means that when updating envs by name from the CDI spec, we would not overwrite the initial envvar, but always append. (Subsequent CDI updates would append). This was likely a bug in runtime-tools.

Note that there is also a slight mismatch to the wording of the CDI specification which states that envvars are appended to the environment.

I do, however, think that the new behaviour is correct and should also remove ambiguity around dealing with multiple envvars. We may want to update the wording around evvars for the spec though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

}
prefix := parts[0] + "="
replaced := false
for i, e := range process.Env {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Implementing a simplified generator type locally will allow us to cache the envvars to improve performance for containers with many envvars. (Using envvars in CDI is not common, so it may not be worth it though).

Comment thread pkg/cdi/container-edits.go Outdated
spec.Linux = &oci.Linux{}
}
removeDevice(spec, dev.Path)
spec.Linux.Devices = append(spec.Linux.Devices, dev)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Another inconsistency is that specgen.AddDevice(dev) would skip the addition if the spec had multiple matching devices to start with.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Is that something you'd like me to update the PR for/with, or just something you want to note? 🙇

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It was initially just a note from my side, but what about adding an ensureDevice(*oci.Spec, *Device) function that handles all of this internally?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(similarly for ensureMount where we follow the same pattern). Not blockers from my side though.

Signed-off-by: Tianon Gravi <tianon.gravi@docker.com>
@klihub

klihub commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

A first pass of this looks good. One question I would have is whether we wanted to add a local type that wrapps *oci.Spec like runtime-tools does to reduce the diff further, but I assume that it probably isn't worth the effort for the reduced feature set we have here.

@klihub what do you think?

@elezar I think that would be cleaner.

specgen := ocigen.NewFromSpec(spec)
if len(e.Env) > 0 {
specgen.AddMultipleProcessEnv(e.Env)
if spec.Process == nil {

@klihub klihub Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe this could be an ensureProcess() for consistency.

specgenAddLinuxNetDevice(&specgen, dev.HostInterfaceName, (&LinuxNetDevice{dev}).toOCI())
}
for _, dev := range e.NetDevices {
ensureLinuxNetDevices(spec)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we kept the length check it would be more consistent and we could call ensureLinuxNetDevices() once in the if branch outside the for loop.

@klihub klihub left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have a few minor nits.

@elezar I am fine with this if you and others consider eliminating our dependency on runtime-tools that important. I am not sure and I tend to think that a properly maintained runtime-tools/generate would be more useful than re-implementing the same, in this case arguably small, functionality multiple times wherever runtime-tools/generate could be used, but this is just my subjective opinion.

@elezar

elezar commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

A first pass of this looks good. One question I would have is whether we wanted to add a local type that wrapps *oci.Spec like runtime-tools does to reduce the diff further, but I assume that it probably isn't worth the effort for the reduced feature set we have here.

I agree that a well-maintained runtime-tools would be better for the community as a whole, but I don't know whether that is something that we have control over.

One thing to note is that at least for moby/moby the dependency on runtime-tools was introduced with the addition of CDI in moby/moby#45134. Even for containerd, it was re-added in containerd/containerd#6654 (after being added and then removed in containerd/containerd#2097 and containerd/containerd#3169, respectively).

Both Podman and Cri-o have been using the dependency from the beginning.

@elezar

elezar commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

@tianon-sso thanks again for this change. We decided to go with #317 instead as it more clearly leaves open the option to switch back to runtime-tools/generate at a later stage.

@elezar elezar closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants