Skip to content
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
1 change: 1 addition & 0 deletions features.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| AWSDedicatedHosts| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AWSDualStackInstall| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AWSServiceLBNetworkSecurityGroup| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AdditionalStorageConfig| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AutomatedEtcdBackup| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AzureClusterHostedDNSInstall| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
| AzureDedicatedHosts| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> |
Expand Down
8 changes: 8 additions & 0 deletions features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ var (
enableIn(configv1.Default, configv1.OKD, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()

FeatureGateAdditionalStorageConfig = newFeatureGate("AdditionalStorageConfig").
reportProblemsToJiraComponent("MachineConfigOperator").
contactPerson("saschagrunert").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1934").
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()

FeatureGateUpgradeStatus = newFeatureGate("UpgradeStatus").
reportProblemsToJiraComponent("Cluster Version Operator").
contactPerson("pmuller").
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
name: "ContainerRuntimeConfig"
crdName: containerruntimeconfigs.machineconfiguration.openshift.io
featureGates:
- AdditionalStorageConfig
tests:
onCreate:
# AdditionalLayerStores - comprehensive validation tests
- name: Should be able to create ContainerRuntimeConfig with multiple additionalLayerStores
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/stargz-store
- path: /mnt/nydus-store
- path: /opt/layer_store-v1.0
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/stargz-store
- path: /mnt/nydus-store
- path: /opt/layer_store-v1.0

- name: Should fail if additionalLayerStores path is empty
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: ""
expectedError: "path in body should be at least 1 chars long"

- name: Should fail if additionalLayerStores path is not absolute
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: var/lib/stargz-store
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"

- name: Should fail if additionalLayerStores path contains spaces
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/stargz store
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"

- name: Should fail if additionalLayerStores path contains invalid characters
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/stargz@store
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"

- name: Should fail if additionalLayerStores path is too long
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
expectedError: "Too long: may not be more than 256 bytes"

- name: Should fail if additionalLayerStores exceeds maximum of 5 items
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/store1
- path: /var/lib/store2
- path: /var/lib/store3
- path: /var/lib/store4
- path: /var/lib/store5
- path: /var/lib/store6
expectedError: "Too many: 6: must have at most 5 items"

- name: Should fail if additionalLayerStores item has no path field
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- {}
expectedError: "path: Required value"

- name: Should fail if additionalLayerStores contains duplicate paths
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalLayerStores:
- path: /var/lib/stargz-store
- path: /var/lib/stargz-store
expectedError: "additionalLayerStores must not contain duplicate paths"

# AdditionalImageStores - test max items validation (different from layer stores)
- name: Should fail if additionalImageStores exceeds maximum of 10 items
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalImageStores:
- path: /var/lib/store1
- path: /var/lib/store2
- path: /var/lib/store3
- path: /var/lib/store4
- path: /var/lib/store5
- path: /var/lib/store6
- path: /var/lib/store7
- path: /var/lib/store8
- path: /var/lib/store9
- path: /var/lib/store10
- path: /var/lib/store11
expectedError: "Too many: 11: must have at most 10 items"

- name: Should fail if additionalImageStores path is not absolute
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalImageStores:
- path: var/lib/images
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"

- name: Should fail if additionalImageStores item has no path field
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalImageStores:
- {}
expectedError: "path: Required value"

- name: Should fail if additionalImageStores contains duplicate paths
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalImageStores:
- path: /mnt/nfs-images
- path: /mnt/nfs-images
expectedError: "additionalImageStores must not contain duplicate paths"

# AdditionalArtifactStores - test max items validation (different from layer stores)
- name: Should fail if additionalArtifactStores exceeds maximum of 10 items
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalArtifactStores:
- path: /var/lib/store1
- path: /var/lib/store2
- path: /var/lib/store3
- path: /var/lib/store4
- path: /var/lib/store5
- path: /var/lib/store6
- path: /var/lib/store7
- path: /var/lib/store8
- path: /var/lib/store9
- path: /var/lib/store10
- path: /var/lib/store11
expectedError: "Too many: 11: must have at most 10 items"

- name: Should fail if additionalArtifactStores path is not absolute
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalArtifactStores:
- path: var/lib/artifacts
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"

- name: Should fail if additionalArtifactStores item has no path field
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalArtifactStores:
- {}
expectedError: "path: Required value"

- name: Should fail if additionalArtifactStores contains duplicate paths
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
additionalArtifactStores:
- path: /mnt/ssd-artifacts
- path: /mnt/ssd-artifacts
expectedError: "additionalArtifactStores must not contain duplicate paths"

# Combined test - all storage types together with other fields
- name: Should be able to create ContainerRuntimeConfig with all storage types and existing fields
initial: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
defaultRuntime: crun
logLevel: info
additionalLayerStores:
- path: /var/lib/stargz-store
additionalImageStores:
- path: /mnt/nfs-images
- path: /mnt/ssd-images
additionalArtifactStores:
- path: /mnt/ssd-artifacts
expected: |
apiVersion: machineconfiguration.openshift.io/v1
kind: ContainerRuntimeConfig
spec:
containerRuntimeConfig:
defaultRuntime: crun
logLevel: info
additionalLayerStores:
- path: /var/lib/stargz-store
additionalImageStores:
- path: /mnt/nfs-images
- path: /mnt/ssd-images
additionalArtifactStores:
- path: /mnt/ssd-artifacts
114 changes: 114 additions & 0 deletions machineconfiguration/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,60 @@ type ContainerRuntimeConfiguration struct {
// +kubebuilder:validation:Enum=crun;runc
// +optional
DefaultRuntime ContainerRuntimeDefaultRuntime `json:"defaultRuntime,omitempty"`

// additionalLayerStores configures additional read-only container image layer store locations for Open Container Initiative (OCI) images.
//
// Layers are checked in order: additional stores first, then the default location.
// Stores are read-only.
// Maximum of 5 stores allowed.
// Each path must be unique.
//
// When omitted, only the default layer location is used.
// When specified, at least one store must be provided.
//
// +openshift:enable:FeatureGate=AdditionalStorageConfig
// +optional
// +listType=atomic
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=5
// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalLayerStores must not contain duplicate paths"
AdditionalLayerStores []AdditionalLayerStore `json:"additionalLayerStores,omitempty"`

// additionalImageStores configures additional read-only container image store locations for Open Container Initiative (OCI) images.
//
// Images are checked in order: additional stores first, then the default location.
// Stores are read-only.
// Maximum of 10 stores allowed.
// Each path must be unique.
//
// When omitted, only the default image location is used.
// When specified, at least one store must be provided.
//
// +openshift:enable:FeatureGate=AdditionalStorageConfig
// +optional
// +listType=atomic
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=10
// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalImageStores must not contain duplicate paths"
AdditionalImageStores []AdditionalImageStore `json:"additionalImageStores,omitempty"`

// additionalArtifactStores configures additional read-only artifact storage locations for Open Container Initiative (OCI) artifacts.
//
// Artifacts are checked in order: additional stores first, then the default location (/var/lib/containers/storage/artifacts).
// Stores are read-only.
// Maximum of 10 stores allowed.
// Each path must be unique.
//
// When omitted, only the default artifact location is used.
// When specified, at least one store must be provided.
//
// +openshift:enable:FeatureGate=AdditionalStorageConfig
// +optional
// +listType=atomic
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=10
// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalArtifactStores must not contain duplicate paths"
AdditionalArtifactStores []AdditionalArtifactStore `json:"additionalArtifactStores,omitempty"`
}

type ContainerRuntimeDefaultRuntime string
Expand All @@ -904,6 +958,66 @@ const (
ContainerRuntimeDefaultRuntimeDefault = ContainerRuntimeDefaultRuntimeCrun
)

// AdditionalLayerStore defines a read-only storage location for Open Container Initiative (OCI) container image layers.
type AdditionalLayerStore struct {
// path specifies the absolute location of the additional layer store.
//
// The path must exist on the node before configuration is applied.
// When a container image is requested, layers found at this location will be used instead of
// retrieving from the registry.
//
// This field is required and must:
// - Have length between 1 and 256 characters
// - Start with '/' (absolute path)
// - Contain only: a-z, A-Z, 0-9, '/', '.', '_', '-' (no spaces or special characters)
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/._-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"
Path string `json:"path,omitempty"`
}

// AdditionalImageStore defines an additional read-only storage location for Open Container Initiative (OCI) images.
type AdditionalImageStore struct {
// path specifies the absolute location of the additional image store.
//
// The path must exist on the node before configuration is applied.
// When a container image is requested, images found at this location will be used instead of
// retrieving from the registry.
//
// This field is required and must:
// - Have length between 1 and 256 characters
// - Start with '/' (absolute path)
// - Contain only: a-z, A-Z, 0-9, '/', '.', '_', '-' (no spaces or special characters)
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/._-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"
Path string `json:"path,omitempty"`
}

// AdditionalArtifactStore defines an additional read-only storage location for Open Container Initiative (OCI) artifacts.
type AdditionalArtifactStore struct {
// path specifies the absolute location of the additional artifact store.
//
// The path must exist on the node before configuration is applied.
// When an artifact is requested, artifacts found at this location will be used instead of
// retrieving from the registry.
//
// This field is required and must:
// - Have length between 1 and 256 characters
// - Start with '/' (absolute path)
// - Contain only: a-z, A-Z, 0-9, '/', '.', '_', '-' (no spaces or special characters)
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/._-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"
Path string `json:"path,omitempty"`
}

// ContainerRuntimeConfigStatus defines the observed state of a ContainerRuntimeConfig
type ContainerRuntimeConfigStatus struct {
// observedGeneration represents the generation observed by the controller.
Expand Down
Loading