diff --git a/api/v1/clusterobjectdeployment_types_test.go b/api/v1/clusterobjectdeployment_types_test.go index da4e06c02b..7965010bd6 100644 --- a/api/v1/clusterobjectdeployment_types_test.go +++ b/api/v1/clusterobjectdeployment_types_test.go @@ -57,19 +57,19 @@ func TestClusterObjectDeploymentValidity(t *testing.T) { cod.Spec.Template.Spec.Phases[0].Objects[0].CollisionProtection = "Invalid" }}, {name: "object reference", mutate: func(cod *ClusterObjectDeployment) { - cod.Spec.Template.Spec.Phases[0].Objects[0] = ClusterObjectSetObject{Ref: ObjectSourceRef{Name: "objects", Key: "configmap"}} + cod.Spec.Template.Spec.Phases[0].Objects[0] = ClusterObjectSetObject{Type: ObjectTypeObjectReference, ObjectReference: ObjectSourceRef{Name: "objects", Key: "configmap"}} }, valid: true}, {name: "both inline object and reference", mutate: func(cod *ClusterObjectDeployment) { - cod.Spec.Template.Spec.Phases[0].Objects[0].Ref = ObjectSourceRef{Name: "objects", Key: "configmap"} + cod.Spec.Template.Spec.Phases[0].Objects[0].ObjectReference = ObjectSourceRef{Name: "objects", Key: "configmap"} }}, {name: "neither inline object nor reference", mutate: func(cod *ClusterObjectDeployment) { cod.Spec.Template.Spec.Phases[0].Objects[0] = ClusterObjectSetObject{} }}, {name: "reference key missing", mutate: func(cod *ClusterObjectDeployment) { - cod.Spec.Template.Spec.Phases[0].Objects[0] = ClusterObjectSetObject{Ref: ObjectSourceRef{Name: "objects"}} + cod.Spec.Template.Spec.Phases[0].Objects[0] = ClusterObjectSetObject{Type: ObjectTypeObjectReference, ObjectReference: ObjectSourceRef{Name: "objects"}} }}, {name: "inline object kind missing", mutate: func(cod *ClusterObjectDeployment) { - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.SetKind("") + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.SetKind("") }}, {name: "progression probe", mutate: func(cod *ClusterObjectDeployment) { cod.Spec.Template.Spec.ProgressionProbes = []ProgressionProbe{codProbe("ready")} @@ -138,7 +138,7 @@ func TestClusterObjectDeploymentTemplateIsMutable(t *testing.T) { secondObject := configMap() secondObject.SetName("second-cm") cod.Spec.Template.Spec.Phases = append(cod.Spec.Template.Spec.Phases, ClusterObjectSetPhase{ - Name: "second", Objects: []ClusterObjectSetObject{{Object: secondObject}}, + Name: "second", Objects: []ClusterObjectSetObject{{Type: ObjectTypeInlineManifest, InlineManifest: secondObject}}, }) cod.Spec.Template.Spec.CollisionProtection = CollisionProtectionIfNoController cod.Spec.Template.Spec.ProgressionProbes = []ProgressionProbe{codProbe("first"), codProbe("second")} @@ -148,7 +148,7 @@ func TestClusterObjectDeploymentTemplateIsMutable(t *testing.T) { // COS immutability rules must not apply to the mutable deployment template. cod.Spec.Template.Spec.Phases[0], cod.Spec.Template.Spec.Phases[1] = cod.Spec.Template.Spec.Phases[1], cod.Spec.Template.Spec.Phases[0] cod.Spec.Template.Spec.Phases[0].Name = "renamed" - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"mode": "updated"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"mode": "updated"} cod.Spec.Template.Spec.CollisionProtection = CollisionProtectionNone cod.Spec.Template.Spec.ProgressionProbes[0], cod.Spec.Template.Spec.ProgressionProbes[1] = cod.Spec.Template.Spec.ProgressionProbes[1], cod.Spec.Template.Spec.ProgressionProbes[0] cod.Spec.Template.Spec.ProgressionProbes[0].Assertions[0].FieldValue.Value = "updated" @@ -346,7 +346,7 @@ func newTestClusterObjectDeployment(name string) *ClusterObjectDeployment { Template: ClusterObjectDeploymentTemplate{ Spec: ClusterObjectDeploymentTemplateSpec{ CollisionProtection: CollisionProtectionPrevent, - Phases: []ClusterObjectSetPhase{{Name: "deploy", Objects: []ClusterObjectSetObject{{Object: configMap()}}}}, + Phases: []ClusterObjectSetPhase{{Name: "deploy", Objects: []ClusterObjectSetObject{{Type: ObjectTypeInlineManifest, InlineManifest: configMap()}}}}, }, }, }, @@ -366,7 +366,7 @@ func codPhases(count int) func(*ClusterObjectDeployment) { cod.Spec.Template.Spec.Phases = make([]ClusterObjectSetPhase, count) for i := range cod.Spec.Template.Spec.Phases { cod.Spec.Template.Spec.Phases[i] = ClusterObjectSetPhase{ - Name: fmt.Sprintf("phase-%d", i), Objects: []ClusterObjectSetObject{{Object: configMap()}}, + Name: fmt.Sprintf("phase-%d", i), Objects: []ClusterObjectSetObject{{Type: ObjectTypeInlineManifest, InlineManifest: configMap()}}, } } } @@ -378,7 +378,7 @@ func codPhaseObjects(count int) func(*ClusterObjectDeployment) { for i := range objects { obj := configMap() obj.SetName(fmt.Sprintf("configmap-%d", i)) - objects[i] = ClusterObjectSetObject{Object: obj} + objects[i] = ClusterObjectSetObject{Type: ObjectTypeInlineManifest, InlineManifest: obj} } cod.Spec.Template.Spec.Phases[0].Objects = objects } diff --git a/api/v1/clusterobjectset_types.go b/api/v1/clusterobjectset_types.go index c4044012d0..16f7c2654b 100644 --- a/api/v1/clusterobjectset_types.go +++ b/api/v1/clusterobjectset_types.go @@ -401,31 +401,56 @@ type ClusterObjectSetPhase struct { CollisionProtection CollisionProtection `json:"collisionProtection,omitempty"` } +// ObjectType defines the type of objects provided in the Objects set. +// +kubebuilder:validation:Enum=InlineManifest;ObjectReference +type ObjectType string + +const ( + ObjectTypeInlineManifest ObjectType = "InlineManifest" + ObjectTypeObjectReference ObjectType = "ObjectReference" +) + // ClusterObjectSetObject 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. +// Exactly one of inlineManifest or objectReference must be set. // -// +kubebuilder:validation:ExactlyOneOf={object,ref} +// +union +// +kubebuilder:validation:XValidation:rule="self.type == 'InlineManifest' ?has(self.inlineManifest) : !has(self.inlineManifest)",message="inlineManifest is required when type is InlineManifest, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="self.type == 'ObjectReference' ?has(self.objectReference) : !has(self.objectReference)",message="objectReference is required when type is ObjectReference, and forbidden otherwise" type ClusterObjectSetObject struct { - // object is an optional embedded Kubernetes object to be applied. + // type is a required field which specifies the type of object to use. + // + // The allowed selector types are "InlineManifest" and "ObjectReference". + // + // When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + // When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. // - // Exactly one of object or ref must be set. + // +unionDiscriminator + // +required + // + Type ObjectType `json:"type,omitempty"` + + // inlineManifest is an optional embedded Kubernetes object to be applied. + // + // Exactly one of inlineManifest or objectReference must be set. // // This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. // // +kubebuilder:validation:EmbeddedResource // +kubebuilder:pruning:PreserveUnknownFields + // +unionMember // +optional - Object unstructured.Unstructured `json:"object,omitzero"` + InlineManifest unstructured.Unstructured `json:"inlineManifest,omitempty,omitzero"` - // ref is an optional reference to a Secret that holds the serialized + // objectReference is an optional reference to a Secret that holds the serialized // object manifest. // - // Exactly one of object or ref must be set. + // Exactly one of inlineManifest or objectReference must be set. // + // +unionMember // +optional - Ref ObjectSourceRef `json:"ref,omitzero"` + ObjectReference ObjectSourceRef `json:"objectReference,omitzero"` // collisionProtection controls whether the operator can adopt and modify objects // that already exist on the cluster. diff --git a/api/v1/clusterobjectset_types_test.go b/api/v1/clusterobjectset_types_test.go index bae5e1f08b..206bcb353d 100644 --- a/api/v1/clusterobjectset_types_test.go +++ b/api/v1/clusterobjectset_types_test.go @@ -273,7 +273,7 @@ func TestClusterObjectSetValidity(t *testing.T) { Objects: func() []ClusterObjectSetObject { objects := make([]ClusterObjectSetObject, 51) for i := range objects { - objects[i] = ClusterObjectSetObject{Object: configMap()} + objects[i] = ClusterObjectSetObject{InlineManifest: configMap()} } return objects }(), @@ -423,7 +423,8 @@ func TestClusterObjectSetValidity(t *testing.T) { Name: "deploy", Objects: []ClusterObjectSetObject{ { - Object: configMap(), + Type: ObjectTypeInlineManifest, + InlineManifest: configMap(), }, }, }, @@ -431,7 +432,7 @@ func TestClusterObjectSetValidity(t *testing.T) { }, valid: true, }, - "object with inline object is valid": { + "object with inlineObject is valid": { spec: ClusterObjectSetSpec{ Group: "validity-inline-object", LifecycleState: ClusterObjectSetLifecycleStateActive, @@ -442,7 +443,8 @@ func TestClusterObjectSetValidity(t *testing.T) { Name: "deploy", Objects: []ClusterObjectSetObject{ { - Object: configMap(), + Type: ObjectTypeInlineManifest, + InlineManifest: configMap(), }, }, }, @@ -450,7 +452,7 @@ func TestClusterObjectSetValidity(t *testing.T) { }, valid: true, }, - "object with ref is valid": { + "object with objectReference is valid": { spec: ClusterObjectSetSpec{ Group: "validity-ref-object", LifecycleState: ClusterObjectSetLifecycleStateActive, @@ -461,7 +463,8 @@ func TestClusterObjectSetValidity(t *testing.T) { Name: "deploy", Objects: []ClusterObjectSetObject{ { - Ref: ObjectSourceRef{Name: "my-secret", Key: "my-key"}, + Type: ObjectTypeObjectReference, + ObjectReference: ObjectSourceRef{Name: "my-secret", Key: "my-key"}, }, }, }, @@ -469,27 +472,27 @@ func TestClusterObjectSetValidity(t *testing.T) { }, valid: true, }, - "object ref requires a name": { + "objectReference requires a name": { spec: refSpec("validity-case-21", ObjectSourceRef{Key: "my-key"}), valid: false, - expectedError: "ref.name: Required value", + expectedError: "objectReference.name: Required value", }, - "object ref requires a key": { + "objectReference requires a key": { spec: refSpec("validity-case-22", ObjectSourceRef{Name: "my-secret"}), valid: false, - expectedError: "ref.key: Required value", + expectedError: "objectReference.key: Required value", }, - "object ref name cannot exceed 253 characters": { + "objectReference name cannot exceed 253 characters": { spec: refSpec("validity-case-23", ObjectSourceRef{Name: strings.Repeat("a", 254), Key: "my-key"}), valid: false, - expectedError: "ref.name: Too long", + expectedError: "objectReference.name: Too long", }, - "object ref namespace cannot exceed 63 characters": { + "objectReference namespace cannot exceed 63 characters": { spec: refSpec("validity-case-24", ObjectSourceRef{Name: "my-secret", Key: "my-key", Namespace: strings.Repeat("a", 64)}), valid: false, - expectedError: "ref.namespace: Too long", + expectedError: "objectReference.namespace: Too long", }, - "object with both object and ref is invalid": { + "object with type InlineManifest but objectReference also set is invalid": { spec: ClusterObjectSetSpec{ Group: "validity-object-and-ref", LifecycleState: ClusterObjectSetLifecycleStateActive, @@ -500,17 +503,18 @@ func TestClusterObjectSetValidity(t *testing.T) { Name: "deploy", Objects: []ClusterObjectSetObject{ { - Object: configMap(), - Ref: ObjectSourceRef{Name: "my-secret", Key: "my-key"}, + Type: ObjectTypeInlineManifest, + InlineManifest: configMap(), + ObjectReference: ObjectSourceRef{Name: "my-secret", Key: "my-key"}, }, }, }, }, }, valid: false, - expectedError: "exactly one of the fields in [object ref] must be set", + expectedError: "objectReference is required when type is ObjectReference, and forbidden otherwise", }, - "object with neither object nor ref is invalid": { + "object without a type is invalid": { spec: ClusterObjectSetSpec{ Group: "validity-object-and-ref-missing", LifecycleState: ClusterObjectSetLifecycleStateActive, @@ -526,7 +530,25 @@ func TestClusterObjectSetValidity(t *testing.T) { }, }, valid: false, - expectedError: "exactly one of the fields in [object ref] must be set", + expectedError: "spec.phases[0].objects[0].type: Required value", + }, + "object with type InlineManifest but no object is invalid": { + spec: ClusterObjectSetSpec{ + Group: "validity-object-type-no-object", + LifecycleState: ClusterObjectSetLifecycleStateActive, + Revision: 1, + CollisionProtection: CollisionProtectionPrevent, + Phases: []ClusterObjectSetPhase{ + { + Name: "deploy", + Objects: []ClusterObjectSetObject{ + {Type: ObjectTypeInlineManifest}, + }, + }, + }, + }, + valid: false, + expectedError: "inlineManifest is required when type is InlineManifest, and forbidden otherwise", }, "progressionProbe with GroupKind selector and ConditionEqual assertion is valid": { spec: probeSpec("validity-case-27", ProgressionProbe{ @@ -937,7 +959,7 @@ func refSpec(group string, ref ObjectSourceRef) ClusterObjectSetSpec { Phases: []ClusterObjectSetPhase{ { Name: "deploy", - Objects: []ClusterObjectSetObject{{Ref: ref}}, + Objects: []ClusterObjectSetObject{{Type: ObjectTypeObjectReference, ObjectReference: ref}}, }, }, } diff --git a/api/v1/validation_test.go b/api/v1/validation_test.go index 35446c4a16..24c45055eb 100644 --- a/api/v1/validation_test.go +++ b/api/v1/validation_test.go @@ -41,7 +41,7 @@ func TestValidate(t *testing.T) { defaultDeploymentSpec := func(s *ClusterObjectDeploymentSpec) *ClusterObjectDeploymentSpec { s.Template.Spec.CollisionProtection = CollisionProtectionPrevent s.Template.Spec.Phases = []ClusterObjectSetPhase{ - {Name: "deploy", Objects: []ClusterObjectSetObject{{Object: configMap()}}}, + {Name: "deploy", Objects: []ClusterObjectSetObject{{Type: ObjectTypeInlineManifest, InlineManifest: configMap()}}}, } return s } @@ -235,7 +235,7 @@ func newRevisionHistoryLimitCOD(name string, limit *int32) *ClusterObjectDeploym Spec: ClusterObjectDeploymentTemplateSpec{ CollisionProtection: CollisionProtectionPrevent, Phases: []ClusterObjectSetPhase{ - {Name: "deploy", Objects: []ClusterObjectSetObject{{Object: configMap()}}}, + {Name: "deploy", Objects: []ClusterObjectSetObject{{Type: ObjectTypeInlineManifest, InlineManifest: configMap()}}}, }, }, }, diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index aa81f0136f..635a4e8f44 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -655,8 +655,8 @@ func (in *ClusterObjectSetList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterObjectSetObject) DeepCopyInto(out *ClusterObjectSetObject) { *out = *in - in.Object.DeepCopyInto(&out.Object) - out.Ref = in.Ref + in.InlineManifest.DeepCopyInto(&out.InlineManifest) + out.ObjectReference = in.ObjectReference } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterObjectSetObject. diff --git a/applyconfigurations/api/v1/clusterobjectsetobject.go b/applyconfigurations/api/v1/clusterobjectsetobject.go index b6bee6784e..a51a88b512 100644 --- a/applyconfigurations/api/v1/clusterobjectsetobject.go +++ b/applyconfigurations/api/v1/clusterobjectsetobject.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by controller-gen-v0.21. DO NOT EDIT. +// Code generated by controller-gen. DO NOT EDIT. package v1 @@ -29,19 +29,28 @@ import ( // ClusterObjectSetObject 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. +// Exactly one of inlineManifest or objectReference must be set. type ClusterObjectSetObjectApplyConfiguration struct { - // object is an optional embedded Kubernetes object to be applied. + // type is a required field which specifies the type of object to use. // - // Exactly one of object or ref must be set. + // The allowed selector types are "InlineManifest" and "ObjectReference". + // + // When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + // When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + // + // + Type *apiv1.ObjectType `json:"type,omitempty"` + // inlineManifest is an optional embedded Kubernetes object to be applied. + // + // Exactly one of inlineManifest or objectReference must be set. // // This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. - Object *unstructured.Unstructured `json:"object,omitempty"` - // ref is an optional reference to a Secret that holds the serialized + InlineManifest *unstructured.Unstructured `json:"inlineManifest,omitempty"` + // objectReference is an optional reference to a Secret that holds the serialized // object manifest. // - // Exactly one of object or ref must be set. - Ref *ObjectSourceRefApplyConfiguration `json:"ref,omitempty"` + // Exactly one of inlineManifest or objectReference must be set. + ObjectReference *ObjectSourceRefApplyConfiguration `json:"objectReference,omitempty"` // collisionProtection controls whether the operator can adopt and modify objects // that already exist on the cluster. // @@ -69,19 +78,27 @@ func ClusterObjectSetObject() *ClusterObjectSetObjectApplyConfiguration { return &ClusterObjectSetObjectApplyConfiguration{} } -// WithObject sets the Object field in the declarative configuration to the given value +// WithType sets the Type field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Type field is set to the value of the last call. +func (b *ClusterObjectSetObjectApplyConfiguration) WithType(value apiv1.ObjectType) *ClusterObjectSetObjectApplyConfiguration { + b.Type = &value + return b +} + +// WithInlineManifest sets the InlineManifest field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the Object field is set to the value of the last call. -func (b *ClusterObjectSetObjectApplyConfiguration) WithObject(value unstructured.Unstructured) *ClusterObjectSetObjectApplyConfiguration { - b.Object = &value +// If called multiple times, the InlineManifest field is set to the value of the last call. +func (b *ClusterObjectSetObjectApplyConfiguration) WithInlineManifest(value unstructured.Unstructured) *ClusterObjectSetObjectApplyConfiguration { + b.InlineManifest = &value return b } -// WithRef sets the Ref field in the declarative configuration to the given value +// WithObjectReference sets the ObjectReference field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the Ref field is set to the value of the last call. -func (b *ClusterObjectSetObjectApplyConfiguration) WithRef(value *ObjectSourceRefApplyConfiguration) *ClusterObjectSetObjectApplyConfiguration { - b.Ref = value +// If called multiple times, the ObjectReference field is set to the value of the last call. +func (b *ClusterObjectSetObjectApplyConfiguration) WithObjectReference(value *ObjectSourceRefApplyConfiguration) *ClusterObjectSetObjectApplyConfiguration { + b.ObjectReference = value return b } diff --git a/applyconfigurations/internal/internal.go b/applyconfigurations/internal/internal.go index 8f564a4eda..8a155ac7d3 100644 --- a/applyconfigurations/internal/internal.go +++ b/applyconfigurations/internal/internal.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by controller-gen-v0.21. DO NOT EDIT. +// Code generated by controller-gen. DO NOT EDIT. package internal @@ -351,12 +351,15 @@ var schemaYAML = typed.YAMLObject(`types: - name: collisionProtection type: namedType: com.github.operator-framework.operator-controller.api.v1.CollisionProtection - - name: object + - name: inlineManifest type: namedType: io.k8s.apimachinery.pkg.apis.meta.v1.unstructured.Unstructured - - name: ref + - name: objectReference type: namedType: com.github.operator-framework.operator-controller.api.v1.ObjectSourceRef + - name: type + type: + namedType: com.github.operator-framework.operator-controller.api.v1.ObjectType - name: com.github.operator-framework.operator-controller.api.v1.ClusterObjectSetPhase map: fields: @@ -527,6 +530,8 @@ var schemaYAML = typed.YAMLObject(`types: - name: version type: scalar: string +- name: com.github.operator-framework.operator-controller.api.v1.ObjectType + scalar: string - name: com.github.operator-framework.operator-controller.api.v1.ObservedPhase map: fields: diff --git a/cmd/object-controller/main_test.go b/cmd/object-controller/main_test.go index 6fea75f96b..fe9499814e 100644 --- a/cmd/object-controller/main_test.go +++ b/cmd/object-controller/main_test.go @@ -102,7 +102,7 @@ func TestStandaloneController(t *testing.T) { "metadata": map[string]any{"name": name, "namespace": ns.Name}, "data": map[string]any{"hello": "world"}, }} - obj := ocv1.ClusterObjectSetObject{Object: manifest} + obj := ocv1.ClusterObjectSetObject{Type: ocv1.ObjectTypeInlineManifest, InlineManifest: manifest} if name == "secret-ref" { data, err := json.Marshal(manifest.Object) require.NoError(t, err) @@ -111,7 +111,7 @@ func TestStandaloneController(t *testing.T) { Immutable: ptr.To(true), Data: map[string][]byte{"object": data}, } require.NoError(t, cl.Create(ctx, secret)) - obj = ocv1.ClusterObjectSetObject{Ref: ocv1.ObjectSourceRef{Name: secret.Name, Namespace: secret.Namespace, Key: "object"}} + obj = ocv1.ClusterObjectSetObject{Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: secret.Name, Namespace: secret.Namespace, Key: "object"}} } cos := &ocv1.ClusterObjectSet{ ObjectMeta: metav1.ObjectMeta{Name: name + "-1"}, diff --git a/docs/api-reference/olmv1-api-reference.md b/docs/api-reference/olmv1-api-reference.md index 1e18b26772..219afc9041 100644 --- a/docs/api-reference/olmv1-api-reference.md +++ b/docs/api-reference/olmv1-api-reference.md @@ -524,18 +524,18 @@ _Appears in:_ ClusterObjectSetObject 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. +Exactly one of inlineManifest or objectReference must be set. + -_Validation:_ -- ExactlyOneOf: [object ref] _Appears in:_ - [ClusterObjectSetPhase](#clusterobjectsetphase) | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `object` _[Unstructured](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#unstructured-unstructured-v1)_ | 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. | | EmbeddedResource: \{\}
Optional: \{\}
| -| `ref` _[ObjectSourceRef](#objectsourceref)_ | ref is an optional reference to a Secret that holds the serialized
object manifest.
Exactly one of object or ref must be set. | | Optional: \{\}
| +| `type` _[ObjectType](#objecttype)_ | type is a required field which specifies the type of object to use.
The allowed selector types are "InlineManifest" and "ObjectReference".
When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields.
When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest.
**Experimental channel:** | | Enum: [InlineManifest ObjectReference]
Required: \{\}
| +| `inlineManifest` _[Unstructured](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#unstructured-unstructured-v1)_ | inlineManifest is an optional embedded Kubernetes object to be applied.
Exactly one of inlineManifest or objectReference must be set.
This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. | | EmbeddedResource: \{\}
Optional: \{\}
| +| `objectReference` _[ObjectSourceRef](#objectsourceref)_ | objectReference is an optional reference to a Secret that holds the serialized
object manifest.
Exactly one of inlineManifest or objectReference must be set. | | Optional: \{\}
| | `collisionProtection` _[CollisionProtection](#collisionprotection)_ | collisionProtection controls whether the operator can adopt and modify objects
that already exist on the cluster.
Allowed values are: "Prevent", "IfNoController", and "None".
When set to "Prevent", the operator only manages objects it created itself.
This prevents ownership collisions.
When set to "IfNoController", the operator can adopt and modify pre-existing objects
that are not owned by another controller.
This is useful for taking over management of manually-created resources.
When set to "None", the operator can adopt and modify any pre-existing object, even if
owned by another controller.
Use this setting with extreme caution as it may cause multiple controllers to fight over
the same resource, resulting in increased load on the API server and etcd.
When omitted, the value is inherited from the phase, then spec. | | Enum: [Prevent IfNoController None]
Optional: \{\}
| @@ -554,7 +554,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `name` _string_ | name is a required identifier for this phase.
phase names must follow the DNS label standard as defined in [RFC 1123].
They must contain only lowercase alphanumeric characters or hyphens (-),
start and end with an alphanumeric character, and be no longer than 63 characters.
Common phase names include: namespaces, policies, rbac, crds, storage, deploy, publish.
[RFC 1123]: https://tools.ietf.org/html/rfc1123 | | MaxLength: 63
MinLength: 1
Required: \{\}
| -| `objects` _[ClusterObjectSetObject](#clusterobjectsetobject) array_ | objects is a required list of all Kubernetes objects that belong to this phase.
All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50. | | ExactlyOneOf: [object ref]
MaxItems: 50
Required: \{\}
| +| `objects` _[ClusterObjectSetObject](#clusterobjectsetobject) array_ | objects is a required list of all Kubernetes objects that belong to this phase.
All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50. | | MaxItems: 50
Required: \{\}
| | `collisionProtection` _[CollisionProtection](#collisionprotection)_ | collisionProtection specifies the default collision protection strategy for all objects
in this phase. Individual objects can override this value.
When set, this value is used as the default for any object in this phase that does not
explicitly specify its own collisionProtection.
When omitted, we use .spec.collistionProtection as the default for any object in this phase that does not
explicitly specify its own collisionProtection. | | Enum: [Prevent IfNoController None]
Optional: \{\}
| @@ -690,6 +690,24 @@ _Appears in:_ +#### ObjectType + +_Underlying type:_ _string_ + +ObjectType defines the type of objects provided in the Objects set. + +_Validation:_ +- Enum: [InlineManifest ObjectReference] + +_Appears in:_ +- [ClusterObjectSetObject](#clusterobjectsetobject) + +| Field | Description | +| --- | --- | +| `InlineManifest` | | +| `ObjectReference` | | + + #### PreflightConfig diff --git a/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectdeployments.yaml b/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectdeployments.yaml index 4505b49d9f..5407f2508f 100644 --- a/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectdeployments.yaml +++ b/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectdeployments.yaml @@ -169,7 +169,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -196,22 +196,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -237,12 +237,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] - must be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) - == 1 + - message: inlineManifest is required when type is + InlineManifest, and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is + ObjectReference, and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic diff --git a/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectsets.yaml b/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectsets.yaml index 3e7fc64e85..347b13ce27 100644 --- a/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectsets.yaml +++ b/helm/olmv1/base/object-controller/crd/experimental/olm.operatorframework.io_clusterobjectsets.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.22.0 + controller-gen.kubebuilder.io/version: v0.23.0 olm.operatorframework.io/generator: experimental name: clusterobjectsets.olm.operatorframework.io spec: @@ -198,7 +198,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -225,22 +225,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -265,11 +265,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] must - be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) == 1 + - message: inlineManifest is required when type is InlineManifest, + and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is ObjectReference, + and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic diff --git a/internal/object-controller/controllers/clusterobjectdeployment_controller_internal_test.go b/internal/object-controller/controllers/clusterobjectdeployment_controller_internal_test.go index a47a384b9f..75d432cb9d 100644 --- a/internal/object-controller/controllers/clusterobjectdeployment_controller_internal_test.go +++ b/internal/object-controller/controllers/clusterobjectdeployment_controller_internal_test.go @@ -27,7 +27,7 @@ func testTemplate() ocv1.ClusterObjectDeploymentTemplate { { Name: "resources", Objects: []ocv1.ClusterObjectSetObject{ - {Object: unstructured.Unstructured{Object: map[string]interface{}{ + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: unstructured.Unstructured{Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", "metadata": map[string]interface{}{"name": "cm", "namespace": "ns"}, @@ -52,7 +52,7 @@ func Test_templateHash_isStableAndSensitive(t *testing.T) { // A change to a phase object changes the hash. changed := testTemplate() - changed.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"k": "v"} + changed.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"k": "v"} require.NotEqual(t, h1, templateHash(changed)) // A change to ONLY progressionProbes (a mutable COS field) still changes the hash. diff --git a/internal/object-controller/controllers/clusterobjectdeployment_controller_test.go b/internal/object-controller/controllers/clusterobjectdeployment_controller_test.go index e4da78cacc..ddc4f1de7e 100644 --- a/internal/object-controller/controllers/clusterobjectdeployment_controller_test.go +++ b/internal/object-controller/controllers/clusterobjectdeployment_controller_test.go @@ -44,7 +44,8 @@ func codFixture() *ocv1.ClusterObjectDeployment { Phases: []ocv1.ClusterObjectSetPhase{{ Name: "resources", Objects: []ocv1.ClusterObjectSetObject{{ - Object: unstructured.Unstructured{Object: map[string]interface{}{ + Type: ocv1.ObjectTypeInlineManifest, + InlineManifest: unstructured.Unstructured{Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", "metadata": map[string]interface{}{"name": "cm", "namespace": "ns"}, @@ -194,7 +195,7 @@ func Test_ClusterObjectDeploymentReconciler_Available(t *testing.T) { // Change the template so a new revision is created while revision 1 stays Ready. cod := &ocv1.ClusterObjectDeployment{} require.NoError(t, c.Get(t.Context(), types.NamespacedName{Name: clusterObjectDeploymentName}, cod)) - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"k": "v"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"k": "v"} require.NoError(t, c.Update(t.Context(), cod)) _, err = reconcileCOD(t, c) // creates revision 2; revision 1 is still active and Ready @@ -217,7 +218,7 @@ func Test_ClusterObjectDeploymentReconciler_Available(t *testing.T) { // Change the template so a new revision is created while revision 1 stays Ready. cod := &ocv1.ClusterObjectDeployment{} require.NoError(t, c.Get(t.Context(), types.NamespacedName{Name: clusterObjectDeploymentName}, cod)) - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"k": "v"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"k": "v"} require.NoError(t, c.Update(t.Context(), cod)) _, err = reconcileCOD(t, c) // creates revision 2 @@ -533,7 +534,7 @@ func Test_ClusterObjectDeploymentReconciler_CreatesNewRevisionOnTemplateChange(t // Change the template. cod := &ocv1.ClusterObjectDeployment{} require.NoError(t, c.Get(t.Context(), types.NamespacedName{Name: clusterObjectDeploymentName}, cod)) - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"k": "v"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"k": "v"} require.NoError(t, c.Update(t.Context(), cod)) _, err = reconcileCOD(t, c) @@ -1151,7 +1152,7 @@ func Test_ClusterObjectDeploymentReconciler_OwnerConflict(t *testing.T) { if tc.owner != nil { foreign.OwnerReferences = []metav1.OwnerReference{*tc.owner} } - foreign.Spec.Phases[0].Objects[0].Object.SetName("foreign-cm") + foreign.Spec.Phases[0].Objects[0].InlineManifest.SetName("foreign-cm") setCOSReady(foreign, metav1.ConditionTrue, ocv1.ClusterObjectSetReasonAllObjectsReady) objects := []client.Object{cod, foreign} if tc.owned { diff --git a/internal/object-controller/controllers/clusterobjectdeployment_deadline_test.go b/internal/object-controller/controllers/clusterobjectdeployment_deadline_test.go index 99eb387737..a01db30b05 100644 --- a/internal/object-controller/controllers/clusterobjectdeployment_deadline_test.go +++ b/internal/object-controller/controllers/clusterobjectdeployment_deadline_test.go @@ -69,7 +69,7 @@ func TestClusterObjectDeploymentReconcilerDeadlineCoversEntireRevision(t *testin for i := range 5 { phase := phaseTemplate.DeepCopy() phase.Name = fmt.Sprintf("phase-%d", i+1) - phase.Objects[0].Object.SetName(phase.Name) + phase.Objects[0].InlineManifest.SetName(phase.Name) cod.Spec.Template.Spec.Phases = append(cod.Spec.Template.Spec.Phases, *phase) } @@ -102,7 +102,7 @@ func TestClusterObjectDeploymentReconcilerDeadlineCoversEntireRevision(t *testin isComplete: i < completedPhases, objects: []machinery.ObjectResult{newMockObjectResult(mockCtrl, objectResultConfig{ action: machinery.ActionCreated, - object: phase.Objects[0].Object.DeepCopy(), + object: phase.Objects[0].InlineManifest.DeepCopy(), complete: i < completedPhases, paused: i > completedPhases, probes: machinerytypes.ProbeResultContainer{ @@ -192,7 +192,7 @@ func TestClusterObjectDeploymentReconcilerDeadlineCoversEntireRevision(t *testin // A later revision receives a fresh budget despite the deployment's age and // the previous revision's earlier timeout. require.NoError(t, c.Get(t.Context(), client.ObjectKeyFromObject(cod), cod)) - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"version": "second"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"version": "second"} require.NoError(t, c.Update(t.Context(), cod)) _, err = reconcileDeadlineDeployment(t, c, clk) require.NoError(t, err) @@ -398,7 +398,7 @@ func TestClusterObjectDeploymentReconcilerDeadlineRetainsAvailability(t *testing clk.Step(time.Hour) require.NoError(t, c.Get(t.Context(), client.ObjectKeyFromObject(cod), cod)) - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.Object["data"] = map[string]interface{}{"version": "second"} + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.Object["data"] = map[string]interface{}{"version": "second"} require.NoError(t, c.Update(t.Context(), cod)) result, err := reconcileDeadlineDeployment(t, c, clk) require.NoError(t, err) diff --git a/internal/object-controller/controllers/clusterobjectdeployment_ownership_test.go b/internal/object-controller/controllers/clusterobjectdeployment_ownership_test.go index 0c0c41872a..c67871f4fd 100644 --- a/internal/object-controller/controllers/clusterobjectdeployment_ownership_test.go +++ b/internal/object-controller/controllers/clusterobjectdeployment_ownership_test.go @@ -36,7 +36,7 @@ func TestClusterObjectDeploymentGroupEvents(t *testing.T) { cod := codFixture() cod.Name = "cod-group-events-" + resolution cod.UID = "" - cod.Spec.Template.Spec.Phases[0].Objects[0].Object.SetName("owned-" + resolution) + cod.Spec.Template.Spec.Phases[0].Objects[0].InlineManifest.SetName("owned-" + resolution) require.NoError(t, cl.Create(t.Context(), cod)) t.Cleanup(func() { ctx := context.Background() @@ -67,7 +67,7 @@ func TestClusterObjectDeploymentGroupEvents(t *testing.T) { OwnerReferences: []metav1.OwnerReference{foreignControllerReference()}, } foreign.Spec.Revision = 3 - foreign.Spec.Phases[0].Objects[0].Object.SetName("foreign-" + resolution) + foreign.Spec.Phases[0].Objects[0].InlineManifest.SetName("foreign-" + resolution) foreign.Status = ocv1.ClusterObjectSetStatus{} require.NoError(t, cl.Create(t.Context(), foreign)) waitForCODCondition(t, cl, cod.Name, ocv1.ClusterObjectDeploymentTypeProgressing, diff --git a/internal/object-controller/controllers/clusterobjectset_controller.go b/internal/object-controller/controllers/clusterobjectset_controller.go index c2612e0947..6e96398c19 100644 --- a/internal/object-controller/controllers/clusterobjectset_controller.go +++ b/internal/object-controller/controllers/clusterobjectset_controller.go @@ -599,11 +599,11 @@ func (c *ClusterObjectSetReconciler) buildBoxcutterPhases(ctx context.Context, c objs := make([]client.Object, 0, len(specPhase.Objects)) for _, specObj := range specPhase.Objects { var obj *unstructured.Unstructured - switch { - case specObj.Object.Object != nil: - obj = specObj.Object.DeepCopy() - case specObj.Ref.Name != "": - resolved, err := c.resolveObjectRef(ctx, specObj.Ref) + switch specObj.Type { + case ocv1.ObjectTypeInlineManifest: + obj = specObj.InlineManifest.DeepCopy() + case ocv1.ObjectTypeObjectReference: + resolved, err := c.resolveObjectRef(ctx, specObj.ObjectReference) if err != nil { return nil, nil, nil, fmt.Errorf("resolving ref in phase %q: %w", specPhase.Name, err) } @@ -865,10 +865,10 @@ func (c *ClusterObjectSetReconciler) verifyReferencedSecretsImmutable(ctx contex for _, phase := range cos.Spec.Phases { for _, obj := range phase.Objects { - if obj.Ref.Name == "" { + if obj.Type != ocv1.ObjectTypeObjectReference { continue } - sr := secretRef{name: obj.Ref.Name, namespace: obj.Ref.Namespace} + sr := secretRef{name: obj.ObjectReference.Name, namespace: obj.ObjectReference.Namespace} if _, ok := seen[sr]; !ok { seen[sr] = struct{}{} refs = append(refs, sr) diff --git a/internal/object-controller/controllers/clusterobjectset_controller_internal_test.go b/internal/object-controller/controllers/clusterobjectset_controller_internal_test.go index 61e2d097c7..0ac18be227 100644 --- a/internal/object-controller/controllers/clusterobjectset_controller_internal_test.go +++ b/internal/object-controller/controllers/clusterobjectset_controller_internal_test.go @@ -467,7 +467,8 @@ func TestVerifyReferencedSecretsImmutable(t *testing.T) { Phases: []ocv1.ClusterObjectSetPhase{{ Name: "phase1", Objects: []ocv1.ClusterObjectSetObject{{ - Ref: ocv1.ObjectSourceRef{ + Type: ocv1.ObjectTypeObjectReference, + ObjectReference: ocv1.ObjectSourceRef{ Name: "test-secret", Namespace: "test-ns", Key: "obj", @@ -497,7 +498,8 @@ func TestVerifyReferencedSecretsImmutable(t *testing.T) { Phases: []ocv1.ClusterObjectSetPhase{{ Name: "phase1", Objects: []ocv1.ClusterObjectSetObject{{ - Ref: ocv1.ObjectSourceRef{ + Type: ocv1.ObjectTypeObjectReference, + ObjectReference: ocv1.ObjectSourceRef{ Name: "test-secret", Namespace: "test-ns", Key: "obj", @@ -522,8 +524,9 @@ func TestVerifyReferencedSecretsImmutable(t *testing.T) { cos := &ocv1.ClusterObjectSet{ Spec: ocv1.ClusterObjectSetSpec{ Phases: []ocv1.ClusterObjectSetPhase{{ - Name: "phase1", + Name: "phase1", Objects: []ocv1.ClusterObjectSetObject{{ + Type: ocv1.ObjectTypeInlineManifest, // Inline object, no ref }}, }}, @@ -557,8 +560,8 @@ func TestVerifyReferencedSecretsImmutable(t *testing.T) { Phases: []ocv1.ClusterObjectSetPhase{{ Name: "phase1", Objects: []ocv1.ClusterObjectSetObject{ - {Ref: ocv1.ObjectSourceRef{Name: "test-secret", Namespace: "test-ns", Key: "obj"}}, - {Ref: ocv1.ObjectSourceRef{Name: "test-secret", Namespace: "test-ns", Key: "obj2"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "test-secret", Namespace: "test-ns", Key: "obj"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "test-secret", Namespace: "test-ns", Key: "obj2"}}, }, }}, }, diff --git a/internal/object-controller/controllers/clusterobjectset_controller_test.go b/internal/object-controller/controllers/clusterobjectset_controller_test.go index b2bf86c141..46cd056f20 100644 --- a/internal/object-controller/controllers/clusterobjectset_controller_test.go +++ b/internal/object-controller/controllers/clusterobjectset_controller_test.go @@ -942,8 +942,8 @@ func Test_ClusterObjectSetReconciler_Reconcile_VerifyReferencedSecrets(t *testin rev1.Spec.Phases = []ocv1.ClusterObjectSetPhase{{ Name: "everything", Objects: []ocv1.ClusterObjectSetObject{ - {Ref: ocv1.ObjectSourceRef{Name: "secret-a", Namespace: "ns", Key: "configmap"}}, - {Ref: ocv1.ObjectSourceRef{Name: "secret-b", Namespace: "ns", Key: "configmap"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "secret-a", Namespace: "ns", Key: "configmap"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "secret-b", Namespace: "ns", Key: "configmap"}}, }, }} @@ -1007,7 +1007,7 @@ func Test_ClusterObjectSetReconciler_Reconcile_ReferencedContentValidationRecove rev1.Spec.Phases = []ocv1.ClusterObjectSetPhase{{ Name: "everything", Objects: []ocv1.ClusterObjectSetObject{ - {Ref: ocv1.ObjectSourceRef{Name: "manifest", Namespace: "ns", Key: "configmap"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "manifest", Namespace: "ns", Key: "configmap"}}, }, }} @@ -1558,7 +1558,8 @@ func newTestClusterObjectSet(t *testing.T, revisionName string, ext *ocv1.Cluste Name: "everything", Objects: []ocv1.ClusterObjectSetObject{ { - Object: unstructured.Unstructured{ + Type: ocv1.ObjectTypeInlineManifest, + InlineManifest: unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", diff --git a/internal/object-controller/controllers/resolve_ref_test.go b/internal/object-controller/controllers/resolve_ref_test.go index ddaf2cc218..2394ab0fa6 100644 --- a/internal/object-controller/controllers/resolve_ref_test.go +++ b/internal/object-controller/controllers/resolve_ref_test.go @@ -300,7 +300,8 @@ func newRefTestCOS(name string, ref ocv1.ObjectSourceRef) *ocv1.ClusterObjectSet Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ { - Ref: ref, + Type: ocv1.ObjectTypeObjectReference, + ObjectReference: ref, }, }, }, diff --git a/internal/operator-controller/applier/boxcutter.go b/internal/operator-controller/applier/boxcutter.go index 78e9d78d89..52b834266f 100644 --- a/internal/operator-controller/applier/boxcutter.go +++ b/internal/operator-controller/applier/boxcutter.go @@ -105,7 +105,8 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease( } objs = append(objs, *ocv1ac.ClusterObjectSetObject(). - WithObject(obj)) + WithType(ocv1.ObjectTypeInlineManifest). + WithInlineManifest(obj)) } revisionAnnotations := map[string]string{ @@ -158,7 +159,8 @@ func (r *SimpleRevisionGenerator) renderObjects( } objs = append(objs, *ocv1ac.ClusterObjectSetObject(). - WithObject(unstr)) + WithType(ocv1.ObjectTypeInlineManifest). + WithInlineManifest(unstr)) } return objs, nil } @@ -750,8 +752,11 @@ func extractPhasesForPacking(phases []ocv1ac.ClusterObjectSetPhaseApplyConfigura phase.Objects = make([]ocv1.ClusterObjectSetObject, 0, len(p.Objects)) for _, o := range p.Objects { obj := ocv1.ClusterObjectSetObject{} - if o.Object != nil { - obj.Object = *o.Object + if o.Type != nil { + obj.Type = *o.Type + } + if o.InlineManifest != nil { + obj.InlineManifest = *o.InlineManifest } if o.CollisionProtection != nil { obj.CollisionProtection = *o.CollisionProtection @@ -774,11 +779,12 @@ func replaceInlineWithRefs(rev *ocv1ac.ClusterObjectSetApplyConfiguration, pack if !ok { continue } - rev.Spec.Phases[phaseIdx].Objects[objIdx].Object = nil - rev.Spec.Phases[phaseIdx].Objects[objIdx].Ref = ocv1ac.ObjectSourceRef(). - WithName(ref.Name). - WithNamespace(ref.Namespace). - WithKey(ref.Key) + rev.Spec.Phases[phaseIdx].Objects[objIdx] = *ocv1ac.ClusterObjectSetObject(). + WithType(ocv1.ObjectTypeObjectReference). + WithObjectReference(ocv1ac.ObjectSourceRef(). + WithName(ref.Name). + WithNamespace(ref.Namespace). + WithKey(ref.Key)) } } } diff --git a/internal/operator-controller/applier/boxcutter_test.go b/internal/operator-controller/applier/boxcutter_test.go index 7f51e4feb9..3ab014e7a3 100644 --- a/internal/operator-controller/applier/boxcutter_test.go +++ b/internal/operator-controller/applier/boxcutter_test.go @@ -111,7 +111,8 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T) WithName("configuration"). WithObjects( ocv1ac.ClusterObjectSetObject(). - WithObject(unstructured.Unstructured{ + WithType(ocv1.ObjectTypeInlineManifest). + WithInlineManifest(unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -127,7 +128,8 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T) }, }), ocv1ac.ClusterObjectSetObject(). - WithObject(unstructured.Unstructured{ + WithType(ocv1.ObjectTypeInlineManifest). + WithInlineManifest(unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -818,9 +820,9 @@ func TestBoxcutterApply_WritesClusterObjectDeployment(t *testing.T) { sawRef := false for _, ph := range cod.Spec.Template.Spec.Phases { for _, o := range ph.Objects { - require.Nil(t, o.Object.Object, "object should be externalized to a Secret ref") - require.NotNil(t, o.Ref) - refNames[o.Ref.Name] = struct{}{} + require.Nil(t, o.InlineManifest.Object, "object should be externalized to a Secret ref") + require.NotNil(t, o.ObjectReference) + refNames[o.ObjectReference.Name] = struct{}{} sawRef = true } } diff --git a/internal/operator-controller/applier/clusterobjectdeployment.go b/internal/operator-controller/applier/clusterobjectdeployment.go index da2305ada6..ffa7f7693f 100644 --- a/internal/operator-controller/applier/clusterobjectdeployment.go +++ b/internal/operator-controller/applier/clusterobjectdeployment.go @@ -146,11 +146,12 @@ func replaceInlineWithRefsInCOD(cod *ocv1ac.ClusterObjectDeploymentApplyConfigur if !ok { continue } - cod.Spec.Template.Spec.Phases[phaseIdx].Objects[objIdx].Object = nil - cod.Spec.Template.Spec.Phases[phaseIdx].Objects[objIdx].Ref = ocv1ac.ObjectSourceRef(). - WithName(ref.Name). - WithNamespace(ref.Namespace). - WithKey(ref.Key) + cod.Spec.Template.Spec.Phases[phaseIdx].Objects[objIdx] = *ocv1ac.ClusterObjectSetObject(). + WithType(ocv1.ObjectTypeObjectReference). + WithObjectReference(ocv1ac.ObjectSourceRef(). + WithName(ref.Name). + WithNamespace(ref.Namespace). + WithKey(ref.Key)) } } } diff --git a/internal/operator-controller/applier/clusterobjectdeployment_test.go b/internal/operator-controller/applier/clusterobjectdeployment_test.go index fd8f17cb82..4f32514511 100644 --- a/internal/operator-controller/applier/clusterobjectdeployment_test.go +++ b/internal/operator-controller/applier/clusterobjectdeployment_test.go @@ -56,7 +56,7 @@ func TestBuildClusterObjectDeployment(t *testing.T) { obj.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ConfigMap")) objects := []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ - *ocv1ac.ClusterObjectSetObject().WithObject(*obj), + *ocv1ac.ClusterObjectSetObject().WithType(ocv1.ObjectTypeInlineManifest).WithInlineManifest(*obj), } annotations := map[string]string{ @@ -184,8 +184,8 @@ func TestGenerateClusterObjectDeployment_PacksAndRefs(t *testing.T) { require.NotNil(t, cod.Spec.Template.Spec.Phases) for _, phase := range cod.Spec.Template.Spec.Phases { for _, obj := range phase.Objects { - assert.Nil(t, obj.Object, "phase %s should have no inline objects", *phase.Name) - assert.NotNil(t, obj.Ref, "phase %s should have refs", *phase.Name) + assert.Nil(t, obj.InlineManifest, "phase %s should have no inline objects", *phase.Name) + assert.NotNil(t, obj.ObjectReference, "phase %s should have refs", *phase.Name) } } diff --git a/internal/operator-controller/applier/externalize_test.go b/internal/operator-controller/applier/externalize_test.go index 98f165ba11..7ccb806c06 100644 --- a/internal/operator-controller/applier/externalize_test.go +++ b/internal/operator-controller/applier/externalize_test.go @@ -21,7 +21,7 @@ func TestExtractPhasesForPacking(t *testing.T) { cp := ocv1.CollisionProtectionPrevent acPhases := []ocv1ac.ClusterObjectSetPhaseApplyConfiguration{ *ocv1ac.ClusterObjectSetPhase().WithName("deploy").WithObjects( - ocv1ac.ClusterObjectSetObject().WithObject(obj).WithCollisionProtection(cp), + ocv1ac.ClusterObjectSetObject().WithType(ocv1.ObjectTypeInlineManifest).WithInlineManifest(obj).WithCollisionProtection(cp), ), } @@ -30,7 +30,7 @@ func TestExtractPhasesForPacking(t *testing.T) { require.Len(t, result, 1) assert.Equal(t, "deploy", result[0].Name) require.Len(t, result[0].Objects, 1) - assert.Equal(t, "ConfigMap", result[0].Objects[0].Object.GetKind()) + assert.Equal(t, "ConfigMap", result[0].Objects[0].InlineManifest.GetKind()) assert.Equal(t, ocv1.CollisionProtectionPrevent, result[0].Objects[0].CollisionProtection) } @@ -50,8 +50,8 @@ func TestReplaceInlineWithRefs(t *testing.T) { WithSpec(ocv1ac.ClusterObjectSetSpec(). WithPhases( ocv1ac.ClusterObjectSetPhase().WithName("deploy").WithObjects( - ocv1ac.ClusterObjectSetObject().WithObject(obj1), - ocv1ac.ClusterObjectSetObject().WithObject(obj2), + ocv1ac.ClusterObjectSetObject().WithType(ocv1.ObjectTypeInlineManifest).WithInlineManifest(obj1), + ocv1ac.ClusterObjectSetObject().WithType(ocv1.ObjectTypeInlineManifest).WithInlineManifest(obj2), ), ), ) @@ -69,16 +69,16 @@ func TestReplaceInlineWithRefs(t *testing.T) { require.Len(t, rev.Spec.Phases[0].Objects, 2) // Object should be nil, Ref should be set - assert.Nil(t, rev.Spec.Phases[0].Objects[0].Object) - require.NotNil(t, rev.Spec.Phases[0].Objects[0].Ref) - assert.Equal(t, "secret-1", *rev.Spec.Phases[0].Objects[0].Ref.Name) - assert.Equal(t, "olmv1-system", *rev.Spec.Phases[0].Objects[0].Ref.Namespace) - assert.Equal(t, "key-a", *rev.Spec.Phases[0].Objects[0].Ref.Key) + assert.Nil(t, rev.Spec.Phases[0].Objects[0].InlineManifest) + require.NotNil(t, rev.Spec.Phases[0].Objects[0].ObjectReference) + assert.Equal(t, "secret-1", *rev.Spec.Phases[0].Objects[0].ObjectReference.Name) + assert.Equal(t, "olmv1-system", *rev.Spec.Phases[0].Objects[0].ObjectReference.Namespace) + assert.Equal(t, "key-a", *rev.Spec.Phases[0].Objects[0].ObjectReference.Key) - assert.Nil(t, rev.Spec.Phases[0].Objects[1].Object) - require.NotNil(t, rev.Spec.Phases[0].Objects[1].Ref) - assert.Equal(t, "secret-1", *rev.Spec.Phases[0].Objects[1].Ref.Name) - assert.Equal(t, "key-b", *rev.Spec.Phases[0].Objects[1].Ref.Key) + assert.Nil(t, rev.Spec.Phases[0].Objects[1].InlineManifest) + require.NotNil(t, rev.Spec.Phases[0].Objects[1].ObjectReference) + assert.Equal(t, "secret-1", *rev.Spec.Phases[0].Objects[1].ObjectReference.Name) + assert.Equal(t, "key-b", *rev.Spec.Phases[0].Objects[1].ObjectReference.Key) } func TestReplaceInlineWithRefs_NilSpec(t *testing.T) { diff --git a/internal/operator-controller/applier/phase.go b/internal/operator-controller/applier/phase.go index dd5d688879..6d8d4fb5c9 100644 --- a/internal/operator-controller/applier/phase.go +++ b/internal/operator-controller/applier/phase.go @@ -156,15 +156,15 @@ func init() { // Helm-to-Boxcutter migration where the same resources may come from different sources // (Helm release manifest vs bundle manifest) and need to produce identical phases. func compareClusterObjectSetObjectApplyConfigurations(a, b ocv1ac.ClusterObjectSetObjectApplyConfiguration) int { - aGVK := a.Object.GroupVersionKind() - bGVK := b.Object.GroupVersionKind() + aGVK := a.InlineManifest.GroupVersionKind() + bGVK := b.InlineManifest.GroupVersionKind() return cmp.Or( cmp.Compare(aGVK.Group, bGVK.Group), cmp.Compare(aGVK.Version, bGVK.Version), cmp.Compare(aGVK.Kind, bGVK.Kind), - cmp.Compare(a.Object.GetNamespace(), b.Object.GetNamespace()), - cmp.Compare(a.Object.GetName(), b.Object.GetName()), + cmp.Compare(a.InlineManifest.GetNamespace(), b.InlineManifest.GetNamespace()), + cmp.Compare(a.InlineManifest.GetName(), b.InlineManifest.GetName()), ) } @@ -176,7 +176,7 @@ func PhaseSort(unsortedObjs []ocv1ac.ClusterObjectSetObjectApplyConfiguration) [ phaseMap := make(map[Phase][]ocv1ac.ClusterObjectSetObjectApplyConfiguration) for _, obj := range unsortedObjs { - phase := determinePhase(obj.Object.GroupVersionKind().GroupKind()) + phase := determinePhase(obj.InlineManifest.GroupVersionKind().GroupKind()) phaseMap[phase] = append(phaseMap[phase], obj) } diff --git a/internal/operator-controller/applier/phase_test.go b/internal/operator-controller/applier/phase_test.go index aba36d12fd..ab11f66309 100644 --- a/internal/operator-controller/applier/phase_test.go +++ b/internal/operator-controller/applier/phase_test.go @@ -21,7 +21,7 @@ func Test_PhaseSort(t *testing.T) { name: "single deploy obj", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -34,7 +34,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -49,7 +49,7 @@ func Test_PhaseSort(t *testing.T) { name: "all phases", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "admissionregistration.k8s.io/v1", "kind": "ValidatingWebhookConfiguration", @@ -57,7 +57,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -65,7 +65,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -73,7 +73,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "some.api/v1", "kind": "SomeCustomResource", @@ -81,7 +81,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -89,7 +89,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -97,7 +97,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "RoleBinding", @@ -105,7 +105,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", @@ -113,7 +113,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "PersistentVolume", @@ -121,7 +121,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", @@ -129,7 +129,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1", "kind": "CustomResourceDefinition", @@ -137,7 +137,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -145,7 +145,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -153,7 +153,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -161,7 +161,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", @@ -172,7 +172,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "autoscaling.k8s.io/v1", "kind": "VerticalPodAutoscaler", @@ -180,7 +180,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "monitoring.coreos.com/v1", "kind": "PrometheusRule", @@ -193,7 +193,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseNamespaces)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -206,7 +206,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhasePolicies)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "networking.k8s.io/v1", "kind": "NetworkPolicy", @@ -219,7 +219,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseIdentity)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -232,7 +232,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -245,7 +245,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseStorage)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "PersistentVolume", @@ -258,7 +258,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseCRDs)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1", "kind": "CustomResourceDefinition", @@ -271,7 +271,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseRoles)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -279,7 +279,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", @@ -292,7 +292,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseBindings)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -300,7 +300,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "RoleBinding", @@ -313,7 +313,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseInfrastructure)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -321,7 +321,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", @@ -337,7 +337,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -345,7 +345,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "some.api/v1", "kind": "SomeCustomResource", @@ -358,7 +358,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseScaling)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "autoscaling.k8s.io/v1", "kind": "VerticalPodAutoscaler", @@ -371,7 +371,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhasePublish)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "monitoring.coreos.com/v1", "kind": "PrometheusRule", @@ -384,7 +384,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseAdmission)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "admissionregistration.k8s.io/v1", "kind": "ValidatingWebhookConfiguration", @@ -399,7 +399,7 @@ func Test_PhaseSort(t *testing.T) { name: "sorted and batched", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -407,7 +407,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -415,7 +415,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -428,7 +428,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseIdentity)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -441,7 +441,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -454,7 +454,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -474,7 +474,7 @@ func Test_PhaseSort(t *testing.T) { name: "sort by group across infrastructure and deploy phases", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -485,7 +485,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", @@ -501,7 +501,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseInfrastructure)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", @@ -517,7 +517,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -535,7 +535,7 @@ func Test_PhaseSort(t *testing.T) { name: "sort by version within same group and phase", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -546,7 +546,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -562,7 +562,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -573,7 +573,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -591,7 +591,7 @@ func Test_PhaseSort(t *testing.T) { name: "sort by kind within same group, version, and phase", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -602,7 +602,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -618,7 +618,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -629,7 +629,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -647,7 +647,7 @@ func Test_PhaseSort(t *testing.T) { name: "sort by namespace within same GVK and phase", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -659,7 +659,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -671,7 +671,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -688,7 +688,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -700,7 +700,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -712,7 +712,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -731,7 +731,7 @@ func Test_PhaseSort(t *testing.T) { name: "sort by name within same GVK, namespace, and phase", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -743,7 +743,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -755,7 +755,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -772,7 +772,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -784,7 +784,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -796,7 +796,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -815,7 +815,7 @@ func Test_PhaseSort(t *testing.T) { name: "comprehensive sorting - all dimensions", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -827,7 +827,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -839,7 +839,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -851,7 +851,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -863,7 +863,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -875,7 +875,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -892,7 +892,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseConfiguration)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -904,7 +904,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -916,7 +916,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -928,7 +928,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -945,7 +945,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseDeploy)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -957,7 +957,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -976,7 +976,7 @@ func Test_PhaseSort(t *testing.T) { name: "cluster-scoped vs namespaced resources - empty namespace sorts first", objs: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -987,7 +987,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -998,7 +998,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", @@ -1015,7 +1015,7 @@ func Test_PhaseSort(t *testing.T) { Name: ptr.To(string(applier.PhaseRoles)), Objects: []ocv1ac.ClusterObjectSetObjectApplyConfiguration{ { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -1026,7 +1026,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRole", @@ -1037,7 +1037,7 @@ func Test_PhaseSort(t *testing.T) { }, }, { - Object: &unstructured.Unstructured{ + InlineManifest: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "Role", diff --git a/internal/operator-controller/applier/secretpacker.go b/internal/operator-controller/applier/secretpacker.go index 7f371bf5c8..8fe1471bc8 100644 --- a/internal/operator-controller/applier/secretpacker.go +++ b/internal/operator-controller/applier/secretpacker.go @@ -90,11 +90,11 @@ func (p *SecretPacker) Pack(phases []ocv1.ClusterObjectSetPhase) (*PackResult, e for phaseIdx, phase := range phases { for objIdx, obj := range phase.Objects { - if obj.Object.Object == nil { + if obj.Type == ocv1.ObjectTypeObjectReference { continue // skip ref-only entries } - data, err := json.Marshal(obj.Object.Object) + data, err := json.Marshal(obj.InlineManifest.Object) if err != nil { return nil, fmt.Errorf("serializing object in phase %d index %d: %w", phaseIdx, objIdx, err) } diff --git a/internal/operator-controller/applier/secretpacker_test.go b/internal/operator-controller/applier/secretpacker_test.go index a32bc5d2b6..b7468fc782 100644 --- a/internal/operator-controller/applier/secretpacker_test.go +++ b/internal/operator-controller/applier/secretpacker_test.go @@ -34,7 +34,8 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{{ - Object: testConfigMap("test-cm", "default"), + Type: ocv1.ObjectTypeInlineManifest, + InlineManifest: testConfigMap("test-cm", "default"), }}, }} @@ -68,8 +69,8 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ - {Object: testConfigMap("cm-1", "default")}, - {Object: testConfigMap("cm-2", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("cm-1", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("cm-2", "default")}, }, }} @@ -84,11 +85,11 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{ { Name: "crds", - Objects: []ocv1.ClusterObjectSetObject{{Object: testConfigMap("crd-1", "")}}, + Objects: []ocv1.ClusterObjectSetObject{{Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("crd-1", "")}}, }, { Name: "deploy", - Objects: []ocv1.ClusterObjectSetObject{{Object: testConfigMap("deploy-1", "ns")}}, + Objects: []ocv1.ClusterObjectSetObject{{Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("deploy-1", "ns")}}, }, } @@ -111,7 +112,7 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ - {Object: testConfigMap("cm-1", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("cm-1", "default")}, }, }} @@ -129,7 +130,7 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ - {Ref: ocv1.ObjectSourceRef{Name: "existing-secret", Namespace: "ns", Key: "somekey"}}, + {Type: ocv1.ObjectTypeObjectReference, ObjectReference: ocv1.ObjectSourceRef{Name: "existing-secret", Namespace: "ns", Key: "somekey"}}, }, }} @@ -149,7 +150,7 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", - Objects: []ocv1.ClusterObjectSetObject{{Object: largeObj}}, + Objects: []ocv1.ClusterObjectSetObject{{Type: ocv1.ObjectTypeInlineManifest, InlineManifest: largeObj}}, }} result, err := packer.Pack(phases) @@ -176,8 +177,8 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ - {Object: testConfigMap("same-cm", "default")}, - {Object: testConfigMap("same-cm", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("same-cm", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("same-cm", "default")}, }, }} @@ -202,7 +203,7 @@ func TestSecretPacker_Pack(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", - Objects: []ocv1.ClusterObjectSetObject{{Object: obj}}, + Objects: []ocv1.ClusterObjectSetObject{{Type: ocv1.ObjectTypeInlineManifest, InlineManifest: obj}}, }} result, err := packer.Pack(phases) require.NoError(t, err) @@ -216,7 +217,7 @@ func TestSecretPacker_NameIsRevisionIndependent(t *testing.T) { phases := []ocv1.ClusterObjectSetPhase{{ Name: "deploy", Objects: []ocv1.ClusterObjectSetObject{ - {Object: testConfigMap("test-cm", "default")}, + {Type: ocv1.ObjectTypeInlineManifest, InlineManifest: testConfigMap("test-cm", "default")}, }, }} diff --git a/manifests/experimental-e2e.yaml b/manifests/experimental-e2e.yaml index 02a58c730c..f55286bd10 100644 --- a/manifests/experimental-e2e.yaml +++ b/manifests/experimental-e2e.yaml @@ -1498,7 +1498,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -1525,22 +1525,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -1566,12 +1566,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] - must be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) - == 1 + - message: inlineManifest is required when type is + InlineManifest, and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is + ObjectReference, and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic @@ -1995,7 +2013,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.22.0 + controller-gen.kubebuilder.io/version: v0.23.0 olm.operatorframework.io/generator: experimental name: clusterobjectsets.olm.operatorframework.io spec: @@ -2190,7 +2208,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -2217,22 +2235,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -2257,11 +2275,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] must - be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) == 1 + - message: inlineManifest is required when type is InlineManifest, + and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is ObjectReference, + and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic diff --git a/manifests/experimental.yaml b/manifests/experimental.yaml index 72b24b71b6..b381c95616 100644 --- a/manifests/experimental.yaml +++ b/manifests/experimental.yaml @@ -1459,7 +1459,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -1486,22 +1486,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -1527,12 +1527,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] - must be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) - == 1 + - message: inlineManifest is required when type is + InlineManifest, and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is + ObjectReference, and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic @@ -1956,7 +1974,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.22.0 + controller-gen.kubebuilder.io/version: v0.23.0 olm.operatorframework.io/generator: experimental name: clusterobjectsets.olm.operatorframework.io spec: @@ -2151,7 +2169,7 @@ spec: ClusterObjectSetObject 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. + Exactly one of inlineManifest or objectReference must be set. properties: collisionProtection: description: |- @@ -2178,22 +2196,22 @@ spec: - IfNoController - None type: string - object: + inlineManifest: description: |- - object is an optional embedded Kubernetes object to be applied. + inlineManifest is an optional embedded Kubernetes object to be applied. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields. type: object x-kubernetes-embedded-resource: true x-kubernetes-preserve-unknown-fields: true - ref: + objectReference: description: |- - ref is an optional reference to a Secret that holds the serialized + objectReference is an optional reference to a Secret that holds the serialized object manifest. - Exactly one of object or ref must be set. + Exactly one of inlineManifest or objectReference must be set. properties: key: description: |- @@ -2218,11 +2236,30 @@ spec: - key - name type: object + type: + description: |- + type is a required field which specifies the type of object to use. + + The allowed selector types are "InlineManifest" and "ObjectReference". + + When set to "InlineManifest", object manifests are supplied inline, as valid Kubernetes resources with apiVersion, kind, and metadata fields. + When set to "ObjectReference", objects are supplied as references to a Secret that holds the serialized object manifest. + enum: + - InlineManifest + - ObjectReference + type: string + required: + - type type: object x-kubernetes-validations: - - message: exactly one of the fields in [object ref] must - be set - rule: (has(self.object)?1:0)+(has(self.ref)?1:0) == 1 + - message: inlineManifest is required when type is InlineManifest, + and forbidden otherwise + rule: 'self.type == ''InlineManifest'' ?has(self.inlineManifest) + : !has(self.inlineManifest)' + - message: objectReference is required when type is ObjectReference, + and forbidden otherwise + rule: 'self.type == ''ObjectReference'' ?has(self.objectReference) + : !has(self.objectReference)' maxItems: 50 type: array x-kubernetes-list-type: atomic diff --git a/test/e2e/features/cod_progressing_reasons.feature b/test/e2e/features/cod_progressing_reasons.feature index 8c9420d6aa..71674ee805 100644 --- a/test/e2e/features/cod_progressing_reasons.feature +++ b/test/e2e/features/cod_progressing_reasons.feature @@ -38,7 +38,8 @@ Feature: ClusterObjectDeployment impeded-rollout Progressing reasons phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -99,7 +100,8 @@ Feature: ClusterObjectDeployment impeded-rollout Progressing reasons phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${NAME}-mutable-secret namespace: ${TEST_NAMESPACE} key: configmap @@ -170,7 +172,8 @@ Feature: ClusterObjectDeployment impeded-rollout Progressing reasons phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: apps/v1 kind: Deployment metadata: @@ -227,7 +230,8 @@ Feature: ClusterObjectDeployment impeded-rollout Progressing reasons phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cod_revision_history.feature b/test/e2e/features/cod_revision_history.feature index 0466bb6c4e..a7dd31b596 100644 --- a/test/e2e/features/cod_revision_history.feature +++ b/test/e2e/features/cod_revision_history.feature @@ -25,7 +25,8 @@ Feature: ClusterObjectDeployment revision history limit phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -50,7 +51,8 @@ Feature: ClusterObjectDeployment revision history limit phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -78,7 +80,8 @@ Feature: ClusterObjectDeployment revision history limit phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cod_rollout.feature b/test/e2e/features/cod_rollout.feature index 24757a0468..ba3c8f6aba 100644 --- a/test/e2e/features/cod_rollout.feature +++ b/test/e2e/features/cod_rollout.feature @@ -24,7 +24,8 @@ Feature: ClusterObjectDeployment revision rollout phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -53,7 +54,8 @@ Feature: ClusterObjectDeployment revision rollout phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -76,7 +78,8 @@ Feature: ClusterObjectDeployment revision rollout phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -84,7 +87,8 @@ Feature: ClusterObjectDeployment revision rollout namespace: ${TEST_NAMESPACE} data: k: v - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cod_template_metadata.feature b/test/e2e/features/cod_template_metadata.feature index 984b399f4f..e68b774fc4 100644 --- a/test/e2e/features/cod_template_metadata.feature +++ b/test/e2e/features/cod_template_metadata.feature @@ -29,7 +29,8 @@ Feature: ClusterObjectDeployment template metadata propagation phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -66,7 +67,8 @@ Feature: ClusterObjectDeployment template metadata propagation phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cos_object_collision_and_adoption.feature b/test/e2e/features/cos_object_collision_and_adoption.feature index 25c13de2aa..215d6bf26c 100644 --- a/test/e2e/features/cos_object_collision_and_adoption.feature +++ b/test/e2e/features/cos_object_collision_and_adoption.feature @@ -38,7 +38,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -73,7 +74,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -97,7 +99,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -127,7 +130,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -151,7 +155,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -195,7 +200,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -237,7 +243,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -269,7 +276,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -293,7 +301,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -339,7 +348,8 @@ Feature: ClusterObjectSet object collision and adoption phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cos_preflight.feature b/test/e2e/features/cos_preflight.feature index 064f85f857..1786de7737 100644 --- a/test/e2e/features/cos_preflight.feature +++ b/test/e2e/features/cos_preflight.feature @@ -24,7 +24,8 @@ Feature: ClusterObjectSet preflight dry-run validation phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -54,7 +55,8 @@ Feature: ClusterObjectSet preflight dry-run validation phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: Pod metadata: @@ -83,7 +85,8 @@ Feature: ClusterObjectSet preflight dry-run validation phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/cos_static_validation.feature b/test/e2e/features/cos_static_validation.feature index 42e332ed27..ae6caafd30 100644 --- a/test/e2e/features/cos_static_validation.feature +++ b/test/e2e/features/cos_static_validation.feature @@ -24,7 +24,8 @@ Feature: ClusterObjectSet static preflight validation phases: - name: phase-a objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -34,7 +35,8 @@ Feature: ClusterObjectSet static preflight validation k: v - name: phase-b objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -64,7 +66,8 @@ Feature: ClusterObjectSet static preflight validation phases: - name: phase-a objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/group.feature b/test/e2e/features/group.feature index 143cb33eb9..c17f8624ad 100644 --- a/test/e2e/features/group.feature +++ b/test/e2e/features/group.feature @@ -43,7 +43,8 @@ Feature: Track ClusterObjectSet revisions by group phases: - name: config objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -69,7 +70,8 @@ Feature: Track ClusterObjectSet revisions by group phases: - name: config objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -112,7 +114,8 @@ Feature: Track ClusterObjectSet revisions by group phases: - name: config objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -137,7 +140,8 @@ Feature: Track ClusterObjectSet revisions by group phases: - name: config objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/install.feature b/test/e2e/features/install.feature index da346e1d09..e3830d725d 100644 --- a/test/e2e/features/install.feature +++ b/test/e2e/features/install.feature @@ -466,7 +466,8 @@ Feature: Install ClusterExtension phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/revision.feature b/test/e2e/features/revision.feature index 86861c044d..209262087c 100644 --- a/test/e2e/features/revision.feature +++ b/test/e2e/features/revision.feature @@ -32,7 +32,8 @@ Feature: Install ClusterObjectSet phases: - name: pvc objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -48,7 +49,8 @@ Feature: Install ClusterObjectSet storage: 1Mi - name: configmap objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -93,7 +95,8 @@ Feature: Install ClusterObjectSet phases: - name: pvc objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -107,7 +110,8 @@ Feature: Install ClusterObjectSet resources: requests: storage: 1Mi - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: PersistentVolume metadata: @@ -137,7 +141,8 @@ Feature: Install ClusterObjectSet - a-node-name-that-should-not-exist - name: configmap objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -180,7 +185,8 @@ Feature: Install ClusterObjectSet phases: - name: cm-1 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -192,7 +198,8 @@ Feature: Install ClusterObjectSet foo: foo - name: cm-2 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -259,7 +266,8 @@ Feature: Install ClusterObjectSet phases: - name: phase1 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -271,7 +279,8 @@ Feature: Install ClusterObjectSet foo: bar - name: phase2 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ServiceAccount metadata: @@ -282,7 +291,8 @@ Feature: Install ClusterObjectSet bar: exercise-fieldsEqual-probe - name: phase3 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: Pod metadata: @@ -308,7 +318,8 @@ Feature: Install ClusterObjectSet type: RuntimeDefault - name: phase4 objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: @@ -413,11 +424,13 @@ Feature: Install ClusterObjectSet phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-ref-secret namespace: ${TEST_NAMESPACE} key: configmap - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-ref-secret namespace: ${TEST_NAMESPACE} key: deployment @@ -465,7 +478,8 @@ Feature: Install ClusterObjectSet phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-mutable-secret namespace: ${TEST_NAMESPACE} key: configmap @@ -514,7 +528,8 @@ Feature: Install ClusterObjectSet phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-change-secret namespace: ${TEST_NAMESPACE} key: configmap @@ -618,7 +633,8 @@ Feature: Install ClusterObjectSet phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-missing-key-secret namespace: ${TEST_NAMESPACE} key: does-not-exist @@ -656,7 +672,8 @@ Feature: Install ClusterObjectSet phases: - name: resources objects: - - ref: + - type: ObjectReference + objectReference: name: ${COS_NAME}-malformed-secret namespace: ${TEST_NAMESPACE} key: configmap @@ -694,7 +711,8 @@ Feature: Install ClusterObjectSet phases: - name: workload objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: apps/v1 kind: Deployment metadata: @@ -728,7 +746,8 @@ Feature: Install ClusterObjectSet type: RuntimeDefault - name: config objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/features/update.feature b/test/e2e/features/update.feature index b69b31e69d..70f900378e 100644 --- a/test/e2e/features/update.feature +++ b/test/e2e/features/update.feature @@ -79,7 +79,8 @@ Feature: Update ClusterExtension phases: - name: resources objects: - - object: + - type: InlineManifest + inlineManifest: apiVersion: v1 kind: ConfigMap metadata: diff --git a/test/e2e/steps/group_steps.go b/test/e2e/steps/group_steps.go index 8451d3b59f..11bec3950b 100644 --- a/test/e2e/steps/group_steps.go +++ b/test/e2e/steps/group_steps.go @@ -130,9 +130,9 @@ func ClusterObjectSetObjectsUseSSAManager(ctx context.Context, revisionName, man count := 0 for _, phase := range cos.Spec.Phases { for _, phaseObj := range phase.Objects { - desired := &phaseObj.Object - if phaseObj.Ref.Name != "" { - desired, err = resolveObjectRef(phaseObj.Ref) + desired := &phaseObj.InlineManifest + if phaseObj.Type == ocv1.ObjectTypeObjectReference { + desired, err = resolveObjectRef(phaseObj.ObjectReference) if err != nil { return false } diff --git a/test/e2e/steps/steps.go b/test/e2e/steps/steps.go index 21eee259f3..5cb6cca34d 100644 --- a/test/e2e/steps/steps.go +++ b/test/e2e/steps/steps.go @@ -1316,17 +1316,17 @@ func ClusterObjectSetObjectsNotFoundOrNotOwned(ctx context.Context, revisionName for i, phase := range rev.Spec.Phases { for j, phaseObj := range phase.Objects { var obj *unstructured.Unstructured - switch { - case phaseObj.Ref.Name != "": - resolved, err := resolveObjectRef(phaseObj.Ref) + switch phaseObj.Type { + case ocv1.ObjectTypeObjectReference: + resolved, err := resolveObjectRef(phaseObj.ObjectReference) if err != nil { return fmt.Errorf("resolving ref in phase %q object %d: %w", phase.Name, j, err) } obj = resolved - case len(phaseObj.Object.Object) > 0: - obj = &phaseObj.Object + case ocv1.ObjectTypeInlineManifest: + obj = &phaseObj.InlineManifest default: - return fmt.Errorf("clusterobjectset %q phase %d object %d has neither ref nor inline object", revisionName, i, j) + return fmt.Errorf("clusterobjectset %q phase %d object %d has unknown type %q", revisionName, i, j, phaseObj.Type) } kind := obj.GetKind() name := obj.GetName() @@ -1402,9 +1402,9 @@ func ClusterObjectSetPhaseObjectsManagedInSecrets(ctx context.Context, revisionN if !ok { return false } - ref, refOK, _ := unstructured.NestedMap(obj, "ref") + ref, refOK, _ := unstructured.NestedMap(obj, "objectReference") if !refOK || len(ref) == 0 { - logger.V(1).Info("object does not use ref", "revision", revisionName) + logger.V(1).Info("object does not use objectReference", "revision", revisionName) return false } name, _, _ := unstructured.NestedString(ref, "name") @@ -1610,7 +1610,7 @@ func collectReferredSecretNames(ctx context.Context, revisionName string) ([]str if !ok { continue } - name, _, _ := unstructured.NestedString(phaseObj, "ref", "name") + name, _, _ := unstructured.NestedString(phaseObj, "objectReference", "name") if name != "" && !seen.Has(name) { seen.Insert(name) names = append(names, name) @@ -1653,11 +1653,11 @@ func collectReferredSecretRefs(ctx context.Context, revisionName string) ([]refe if !ok { continue } - name, _, _ := unstructured.NestedString(phaseObj, "ref", "name") + name, _, _ := unstructured.NestedString(phaseObj, "objectReference", "name") if name == "" { continue } - ns, _, _ := unstructured.NestedString(phaseObj, "ref", "namespace") + ns, _, _ := unstructured.NestedString(phaseObj, "objectReference", "namespace") if ns == "" { ns = olmNamespace } @@ -2611,17 +2611,17 @@ func listExtensionRevisionResources(extName string) ([]client.Object, error) { phase := &rev.Spec.Phases[i] for j := range phase.Objects { specObj := &phase.Objects[j] - switch { - case specObj.Ref.Name != "": - resolved, err := resolveObjectRef(specObj.Ref) + switch specObj.Type { + case ocv1.ObjectTypeObjectReference: + resolved, err := resolveObjectRef(specObj.ObjectReference) if err != nil { return nil, fmt.Errorf("resolving ref in phase %q object %d: %w", phase.Name, j, err) } objs = append(objs, resolved) - case len(specObj.Object.Object) > 0: - objs = append(objs, &specObj.Object) + case ocv1.ObjectTypeInlineManifest: + objs = append(objs, &specObj.InlineManifest) default: - return nil, fmt.Errorf("object %d in phase %q has neither object nor ref", j, phase.Name) + return nil, fmt.Errorf("object %d in phase %q has unknown type %q", j, phase.Name, specObj.Type) } } }