diff --git a/api/v1alpha/runtimeclass_types.go b/api/v1alpha/runtimeclass_types.go
index 76d34ddb..868b796e 100644
--- a/api/v1alpha/runtimeclass_types.go
+++ b/api/v1alpha/runtimeclass_types.go
@@ -30,7 +30,7 @@ type RuntimeClassControllerName string
// decline. Enumerating the features keeps a class from declaring one that no
// provider can interpret.
//
-// +kubebuilder:validation:Enum=sandboxRuntime;virtualMachineRuntime;configMapVolumes;secretVolumes;diskVolumes;deviceVolumeAttachments;envFrom;imagePullSecrets;containerCapabilities;sandboxSysctls;exec;gracefulTermination
+// +kubebuilder:validation:Enum=sandboxRuntime;virtualMachineRuntime;configMapVolumes;secretVolumes;diskVolumes;deviceVolumeAttachments;envFrom;imagePullSecrets;containerCapabilities;sandboxSysctls;exec;execTerminal;gracefulTermination
type RuntimeClassFeature string
const (
@@ -80,10 +80,13 @@ const (
RuntimeClassFeatureSandboxSysctls RuntimeClassFeature = "sandboxSysctls"
// RuntimeClassFeatureExec is the ability to run a command in a running
- // instance's container through an InstanceConsoleSession, such as an
- // interactive shell.
+ // instance's container through an InstanceConsoleSession.
RuntimeClassFeatureExec RuntimeClassFeature = "exec"
+ // RuntimeClassFeatureExecTerminal is the ability to give a shell session's
+ // command an interactive terminal. A class declaring it also declares exec.
+ RuntimeClassFeatureExecTerminal RuntimeClassFeature = "execTerminal"
+
// RuntimeClassFeatureGracefulTermination is the ability to signal an
// instance's processes when it stops and wait up to the instance's
// termination grace period for them to exit.
@@ -105,6 +108,7 @@ var runtimeClassFeatureDescriptions = map[RuntimeClassFeature]string{
RuntimeClassFeatureContainerCapabilities: "container capability requests",
RuntimeClassFeatureSandboxSysctls: "sandbox sysctls",
RuntimeClassFeatureExec: "shell sessions into running instances",
+ RuntimeClassFeatureExecTerminal: "interactive terminals in shell sessions",
RuntimeClassFeatureGracefulTermination: "termination grace periods",
}
@@ -195,6 +199,7 @@ type RuntimeClassIsolation struct {
// +kubebuilder:validation:XValidation:message="supportedSysctls requires the sandboxSysctls feature",rule="!has(self.supportedSysctls) || size(self.supportedSysctls) == 0 || (has(self.features) && 'sandboxSysctls' in self.features)"
// +kubebuilder:validation:XValidation:message="the sandboxSysctls feature requires a non-empty supportedSysctls",rule="!has(self.features) || !('sandboxSysctls' in self.features) || (has(self.supportedSysctls) && size(self.supportedSysctls) > 0)"
// +kubebuilder:validation:XValidation:message="the sandboxSysctls feature requires the sandboxRuntime feature",rule="!has(self.features) || !('sandboxSysctls' in self.features) || 'sandboxRuntime' in self.features"
+// +kubebuilder:validation:XValidation:message="the execTerminal feature requires the exec feature",rule="!has(self.features) || !('execTerminal' in self.features) || 'exec' in self.features"
type RuntimeClassCapabilities struct {
// The optional parts of the instance API this class serves. Anything absent
// is unsupported, so a class that omits a feature rejects requests for it
diff --git a/config/base/crd/bases/compute.datumapis.com_runtimeclasses.yaml b/config/base/crd/bases/compute.datumapis.com_runtimeclasses.yaml
index 4010e168..ebcf6a93 100644
--- a/config/base/crd/bases/compute.datumapis.com_runtimeclasses.yaml
+++ b/config/base/crd/bases/compute.datumapis.com_runtimeclasses.yaml
@@ -116,6 +116,7 @@ spec:
- containerCapabilities
- sandboxSysctls
- exec
+ - execTerminal
- gracefulTermination
type: string
maxItems: 32
@@ -221,6 +222,9 @@ spec:
feature
rule: '!has(self.features) || !(''sandboxSysctls'' in self.features)
|| ''sandboxRuntime'' in self.features'
+ - message: the execTerminal feature requires the exec feature
+ rule: '!has(self.features) || !(''execTerminal'' in self.features)
+ || ''exec'' in self.features'
controllerName:
description: |-
The controller that implements this class. A provider watches for classes
diff --git a/docs/api/runtimeclasses.md b/docs/api/runtimeclasses.md
index 5d85a3c6..d8ec7564 100644
--- a/docs/api/runtimeclasses.md
+++ b/docs/api/runtimeclasses.md
@@ -104,7 +104,7 @@ Spec is the published contract for this execution tier.
What this class can serve, and what it cannot.
- Validations:!has(self.grantableCapabilities) || size(self.grantableCapabilities) == 0 || (has(self.features) && 'containerCapabilities' in self.features): grantableCapabilities requires the containerCapabilities feature!has(self.features) || !('containerCapabilities' in self.features) || (has(self.grantableCapabilities) && size(self.grantableCapabilities) > 0): the containerCapabilities feature requires a non-empty grantableCapabilities!has(self.supportedSysctls) || size(self.supportedSysctls) == 0 || (has(self.features) && 'sandboxSysctls' in self.features): supportedSysctls requires the sandboxSysctls feature!has(self.features) || !('sandboxSysctls' in self.features) || (has(self.supportedSysctls) && size(self.supportedSysctls) > 0): the sandboxSysctls feature requires a non-empty supportedSysctls!has(self.features) || !('sandboxSysctls' in self.features) || 'sandboxRuntime' in self.features: the sandboxSysctls feature requires the sandboxRuntime feature
+ Validations:!has(self.grantableCapabilities) || size(self.grantableCapabilities) == 0 || (has(self.features) && 'containerCapabilities' in self.features): grantableCapabilities requires the containerCapabilities feature!has(self.features) || !('containerCapabilities' in self.features) || (has(self.grantableCapabilities) && size(self.grantableCapabilities) > 0): the containerCapabilities feature requires a non-empty grantableCapabilities!has(self.supportedSysctls) || size(self.supportedSysctls) == 0 || (has(self.features) && 'sandboxSysctls' in self.features): supportedSysctls requires the sandboxSysctls feature!has(self.features) || !('sandboxSysctls' in self.features) || (has(self.supportedSysctls) && size(self.supportedSysctls) > 0): the sandboxSysctls feature requires a non-empty supportedSysctls!has(self.features) || !('sandboxSysctls' in self.features) || 'sandboxRuntime' in self.features: the sandboxSysctls feature requires the sandboxRuntime feature!has(self.features) || !('execTerminal' in self.features) || 'exec' in self.features: the execTerminal feature requires the exec feature
|
true |
@@ -249,7 +249,7 @@ statement before committing an image to the tier.
is unsupported, so a class that omits a feature rejects requests for it
rather than serving it by accident.
- Enum: sandboxRuntime, virtualMachineRuntime, configMapVolumes, secretVolumes, diskVolumes, deviceVolumeAttachments, envFrom, imagePullSecrets, containerCapabilities, sandboxSysctls, exec, gracefulTermination
+ Enum: sandboxRuntime, virtualMachineRuntime, configMapVolumes, secretVolumes, diskVolumes, deviceVolumeAttachments, envFrom, imagePullSecrets, containerCapabilities, sandboxSysctls, exec, execTerminal, gracefulTermination
false |
diff --git a/internal/validation/runtimeclass_crd_test.go b/internal/validation/runtimeclass_crd_test.go
index 8a262744..e61f6a2d 100644
--- a/internal/validation/runtimeclass_crd_test.go
+++ b/internal/validation/runtimeclass_crd_test.go
@@ -196,6 +196,21 @@ func TestRuntimeClassCRD(t *testing.T) {
"the sandboxSysctls feature requires the sandboxRuntime feature")
})
+ t.Run("the terminal feature requires exec", func(t *testing.T) {
+ class := newCatalogEntry("terminal-without-exec")
+ class.Spec.Capabilities.Features = append(class.Spec.Capabilities.Features,
+ computev1alpha.RuntimeClassFeatureExecTerminal)
+ require.ErrorContains(t, c.Create(ctx, class),
+ "the execTerminal feature requires the exec feature")
+ })
+
+ t.Run("a class may declare terminals with exec", func(t *testing.T) {
+ class := newCatalogEntry("terminal-with-exec")
+ class.Spec.Capabilities.Features = append(class.Spec.Capabilities.Features,
+ computev1alpha.RuntimeClassFeatureExec, computev1alpha.RuntimeClassFeatureExecTerminal)
+ require.NoError(t, c.Create(ctx, class))
+ })
+
for i, invalid := range []string{
"net..ipv4.forwarding",
"net.ipv4.forwarding.",
diff --git a/pkg/runtimeclass/capabilities.go b/pkg/runtimeclass/capabilities.go
index 2f3ade9e..82b5b5f9 100644
--- a/pkg/runtimeclass/capabilities.go
+++ b/pkg/runtimeclass/capabilities.go
@@ -42,6 +42,7 @@ const (
FeatureContainerCapabilities = computev1alpha.RuntimeClassFeatureContainerCapabilities
FeatureSandboxSysctls = computev1alpha.RuntimeClassFeatureSandboxSysctls
FeatureExec = computev1alpha.RuntimeClassFeatureExec
+ FeatureExecTerminal = computev1alpha.RuntimeClassFeatureExecTerminal
FeatureGracefulTermination = computev1alpha.RuntimeClassFeatureGracefulTermination
)
diff --git a/pkg/runtimeclass/capabilities_test.go b/pkg/runtimeclass/capabilities_test.go
index 966e0e26..d8318d56 100644
--- a/pkg/runtimeclass/capabilities_test.go
+++ b/pkg/runtimeclass/capabilities_test.go
@@ -69,6 +69,7 @@ func TestFeatureDescriptions(t *testing.T) {
FeatureContainerCapabilities,
FeatureSandboxSysctls,
FeatureExec,
+ FeatureExecTerminal,
FeatureGracefulTermination,
}