mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
cliconfig/containersconfig: Container runtime auto-detection
Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
36
internal/command/cliconfig/containersconfig/automatic.go
Normal file
36
internal/command/cliconfig/containersconfig/automatic.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package containersconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"iter"
|
||||
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/opentofu/opentofu/internal/containers"
|
||||
)
|
||||
|
||||
func FindTypicalContainerRuntimes(ctx context.Context, env RuntimeDiscoveryEnvironment) iter.Seq2[ociv1.Platform, containers.Runtime] {
|
||||
// we'll delegate directly to OS-specific implementations in other
|
||||
// conditionally-compiled files.
|
||||
return findTypicalContainerRuntimes(ctx, env)
|
||||
}
|
||||
|
||||
type RuntimeDiscoveryEnvironment interface {
|
||||
// FindCommandExe attempts to find the path to an executable that matches
|
||||
// the given command name. It returns an empty string if no such executable
|
||||
// file is available.
|
||||
//
|
||||
// [FindTypicalContainerRuntimes] uses this to try to automatically discover
|
||||
// various different OCI-compatible language runtimes by testing whether
|
||||
// their usual command names correspond to programs installed on the system.
|
||||
FindCommandExe(ctx context.Context, name string) string
|
||||
|
||||
// ContainerIDBase returns a string to use as part of a container ID for
|
||||
// a container built from an image obtained from the given location and
|
||||
// with the given manifest.
|
||||
ContainerIDBase(registryName, repositoryName string, manifest *ociv1.Manifest) string
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build linux
|
||||
|
||||
package containersconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"iter"
|
||||
"runtime"
|
||||
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/opentofu/opentofu/internal/containers"
|
||||
)
|
||||
|
||||
func findTypicalContainerRuntimes(ctx context.Context, env RuntimeDiscoveryEnvironment) iter.Seq2[ociv1.Platform, containers.Runtime] {
|
||||
platform := ociv1.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
|
||||
return func(yield func(ociv1.Platform, containers.Runtime) bool) {
|
||||
if exePath := env.FindCommandExe(ctx, "runc"); exePath != "" {
|
||||
yield(platform, makeExecRuntime(env, exePath, func(containerID, bundleDir string) []string {
|
||||
// no bundleDir included because runc uses the current working directory
|
||||
return []string{"create", containerID}
|
||||
}))
|
||||
return
|
||||
}
|
||||
if exePath := env.FindCommandExe(ctx, "systemd-nspawn"); exePath != "" {
|
||||
yield(platform, makeExecRuntime(env, exePath, func(containerID, bundleDir string) []string {
|
||||
return []string{"--machine=" + containerID, "--oci-layout=" + bundleDir, "--no-pager", "--no-ask-password"}
|
||||
}))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeExecRuntime(env RuntimeDiscoveryEnvironment, exePath string, argsFunc func(containerID, bundleDir string) []string) containers.Runtime {
|
||||
return &containers.ExecRuntime{
|
||||
ContainerIDBaseFunc: env.ContainerIDBase,
|
||||
RunCommandFunc: func(containerID, bundleDir string) (string, []string) {
|
||||
args := argsFunc(containerID, bundleDir)
|
||||
return exePath, args
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build !linux && !windows
|
||||
|
||||
package containersconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"iter"
|
||||
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/opentofu/opentofu/internal/containers"
|
||||
)
|
||||
|
||||
func findTypicalContainerRuntimes(_ context.Context, _ RuntimeDiscoveryEnvironment) iter.Seq2[ociv1.Platform, containers.Runtime] {
|
||||
// On unsupported platforms we just return nothing at all. Container
|
||||
// runtimes must be explicitly configured.
|
||||
return func(yield func(ociv1.Platform, containers.Runtime) bool) {}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build windows
|
||||
|
||||
package containersconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"iter"
|
||||
"runtime"
|
||||
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/opentofu/opentofu/internal/containers"
|
||||
)
|
||||
|
||||
func findTypicalContainerRuntimes(ctx context.Context, env RuntimeDiscoveryEnvironment) iter.Seq2[ociv1.Platform, containers.Runtime] {
|
||||
// Windows has support for both Windows-native containers and for
|
||||
// Linux-based containers run in a Hyper-V based virtual machine.
|
||||
//
|
||||
// We'll therefore report runtimes for both of these.
|
||||
// This means that when we find an index manifest that has both a
|
||||
// Windows and a Linux descriptor we'll prefer the Windows one,
|
||||
// but we can still use Linux-only images when that's all we have.
|
||||
windowsPlatform := ociv1.Platform{
|
||||
OS: "windows",
|
||||
Architecture: runtime.GOARCH,
|
||||
|
||||
// OpenTofu only suppports hosts that have the "win32k" feature,
|
||||
// which is the Windows API subsystem, so we'll include that so we
|
||||
// can match descriptors which require it.
|
||||
// (Only very cut-down environments, such as Windows Nano Server
|
||||
// used as a base image for Windows-native containers, leave out
|
||||
// this subsystem. But this feature is talking about the capabilities
|
||||
// of the host, rather than what's installed in the container, so
|
||||
// that would be relevant only if OpenTofu were run inside such a
|
||||
// container, which we don't support.)
|
||||
OSFeatures: []string{"win32k"},
|
||||
}
|
||||
linuxPlatform := ociv1.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
|
||||
return func(yield func(ociv1.Platform, containers.Runtime) bool) {
|
||||
if exePath := env.FindCommandExe(ctx, "runhcs"); exePath != "" {
|
||||
// "runhcs" was forked from "runc", so its command line usage
|
||||
// patterns are similar.
|
||||
runtime := makeExecRuntime(env, exePath, func(containerID, bundleDir string) []string {
|
||||
// no bundleDir included because runc uses the current working directory
|
||||
return []string{"create", containerID}
|
||||
})
|
||||
if !yield(windowsPlatform, runtime) {
|
||||
return
|
||||
}
|
||||
if !yield(linuxPlatform, runtime) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeExecRuntime(env RuntimeDiscoveryEnvironment, exePath string, argsFunc func(containerID, bundleDir string) []string) containers.Runtime {
|
||||
return &containers.ExecRuntime{
|
||||
ContainerIDBaseFunc: env.ContainerIDBase,
|
||||
RunCommandFunc: func(containerID, bundleDir string) (string, []string) {
|
||||
args := argsFunc(containerID, bundleDir)
|
||||
return exePath, args
|
||||
},
|
||||
}
|
||||
}
|
||||
11
internal/command/cliconfig/containersconfig/doc.go
Normal file
11
internal/command/cliconfig/containersconfig/doc.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
// Package containersconfig contains types used for describing (or automatically
|
||||
// discovering) container-execution-related settings.
|
||||
//
|
||||
// The rest of OpenTofu should make use of this package only indirectly through
|
||||
// package cliconfig, which is responsible for making the policy decisions.
|
||||
package containersconfig
|
||||
Reference in New Issue
Block a user