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
46 changes: 44 additions & 2 deletions api/v1/clusterextensionrevision_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,14 +392,29 @@ type ClusterExtensionRevisionPhase struct {

// ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
// of a phase, along with its collision protection settings.
//
// Exactly one of object or ref must be set.
//
// +kubebuilder:validation:XValidation:rule="has(self.object) != has(self.ref)",message="exactly one of object or ref must be set"
type ClusterExtensionRevisionObject struct {
// object is a required embedded Kubernetes object to be applied.
// object is an optional embedded Kubernetes object to be applied.
//
// Exactly one of object or ref must be set.
//
// This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
//
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
Object unstructured.Unstructured `json:"object"`
// +optional
Object unstructured.Unstructured `json:"object,omitzero"`

// ref is an optional reference to a Secret that holds the serialized
// object manifest.
//
// Exactly one of object or ref must be set.
//
// +optional
Ref ObjectSourceRef `json:"ref,omitzero"`

// collisionProtection controls whether the operator can adopt and modify objects
// that already exist on the cluster.
Expand All @@ -425,6 +440,33 @@ type ClusterExtensionRevisionObject struct {
CollisionProtection CollisionProtection `json:"collisionProtection,omitempty"`
}

// ObjectSourceRef references content within a Secret that contains a
// serialized object manifest.
type ObjectSourceRef struct {
// name is the name of the referenced Secret.
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
Name string `json:"name"`

// namespace is the namespace of the referenced Secret.
// When empty, defaults to the OLM system namespace during ref resolution.
//
// +optional
// +kubebuilder:validation:MaxLength=63
Namespace string `json:"namespace,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Does omission of namespace imply OLM system namespace? If so could we add a comment here for that?


// key is the data key within the referenced Secret containing the
// object manifest content. The value at this key must be a
// JSON-serialized Kubernetes object manifest.
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
Key string `json:"key"`
}

// CollisionProtection specifies if and how ownership collisions are prevented.
type CollisionProtection string

Expand Down
71 changes: 71 additions & 0 deletions api/v1/clusterextensionrevision_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,77 @@ func TestClusterExtensionRevisionValidity(t *testing.T) {
},
valid: true,
},
"object with inline object is valid": {
spec: ClusterExtensionRevisionSpec{
LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
Phases: []ClusterExtensionRevisionPhase{
{
Name: "deploy",
Objects: []ClusterExtensionRevisionObject{
{
Object: configMap(),
},
},
},
},
},
valid: true,
},
"object with ref is valid": {
spec: ClusterExtensionRevisionSpec{
LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
Phases: []ClusterExtensionRevisionPhase{
{
Name: "deploy",
Objects: []ClusterExtensionRevisionObject{
{
Ref: ObjectSourceRef{Name: "my-secret", Key: "my-key"},
},
},
},
},
},
valid: true,
},
"object with both object and ref is invalid": {
spec: ClusterExtensionRevisionSpec{
LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
Phases: []ClusterExtensionRevisionPhase{
{
Name: "deploy",
Objects: []ClusterExtensionRevisionObject{
{
Object: configMap(),
Ref: ObjectSourceRef{Name: "my-secret", Key: "my-key"},
},
},
},
},
},
valid: false,
},
"object with neither object nor ref is invalid": {
spec: ClusterExtensionRevisionSpec{
LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
Phases: []ClusterExtensionRevisionPhase{
{
Name: "deploy",
Objects: []ClusterExtensionRevisionObject{
{},
},
},
},
},
valid: false,
},
} {
t.Run(name, func(t *testing.T) {
cer := &ClusterExtensionRevision{
Expand Down
16 changes: 16 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion applyconfigurations/api/v1/clusterextensionrevisionobject.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions applyconfigurations/api/v1/objectsourceref.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions applyconfigurations/utils.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
Preflights: c.preflights,
PreAuthorizer: preAuth,
FieldOwner: fieldOwner,
SystemNamespace: cfg.systemNamespace,
}
revisionStatesGetter := &controllers.BoxcutterRevisionStatesGetter{Reader: c.mgr.GetClient()}
storageMigrator := &applier.BoxcutterStorageMigrator{
Expand Down
2 changes: 2 additions & 0 deletions docs/api-reference/olmv1-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,8 @@ _Appears in:_
| `label` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#labelselector-v1-meta)_ | label is the label selector definition.<br />Required when type is "Label".<br />A probe using a Label selector will be executed against every object matching the labels or expressions; you must use care<br />when using this type of selector. For example, if multiple Kind objects are selected via labels then the probe is<br />likely to fail because the values of different Kind objects rarely share the same schema.<br />The LabelSelector field uses the following Kubernetes format:<br />https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#LabelSelector<br />Requires exactly one of matchLabels or matchExpressions.<br /><opcon:experimental> | | Optional: \{\} <br /> |




#### PreflightConfig


Expand Down
Loading
Loading