Skip to content

Commit 76818c9

Browse files
committed
move namespace and serviceAccount fields to spec root
Signed-off-by: everettraven <[email protected]>
1 parent 22ef06f commit 76818c9

File tree

12 files changed

+262
-266
lines changed

12 files changed

+262
-266
lines changed

api/v1alpha1/clusterextension_types.go

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,34 @@ const (
4343

4444
// ClusterExtensionSpec defines the desired state of ClusterExtension
4545
type ClusterExtensionSpec struct {
46+
// namespace is a reference to a Kubernetes namespace.
47+
// This is the namespace the provided ServiceAccount must exist.
48+
// It also designates the default namespace where namespace-scoped resources
49+
// for the extension are applied to the cluster.
50+
// Some extensions may contain namespace-scoped resources to be applied in other namespaces.
51+
// This namespace must exist.
52+
//
53+
// namespace is required, immutable, and follows the DNS label standard
54+
// as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
55+
// start and end with an alphanumeric character, and be no longer than 63 characters
56+
//
57+
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
58+
//
59+
// +kubebuilder:validation:MaxLength:=63
60+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="namespace is immutable"
61+
// +kubebuilder:validation:XValidation:rule="self.matches(\"^[a-z0-9]([-a-z0-9]*[a-z0-9])?$\")",message="namespace must be a valid DNS1123 label"
62+
// +kubebuilder:validation:Required
63+
Namespace string `json:"namespace"`
64+
65+
// serviceAccount is a reference to a ServiceAccount used to perform all interactions
66+
// with the cluster that are required to manage the extension.
67+
// The ServiceAccount must be configured with the necessary permissions to perform these interactions.
68+
// The ServiceAccount must exist in the namespace referenced in the spec.
69+
// serviceAccount is required.
70+
//
71+
// +kubebuilder:validation:Required
72+
ServiceAccount ServiceAccountReference `json:"serviceAccount"`
73+
4674
// source is a required field which selects the installation source of content
4775
// for this ClusterExtension. Selection is performed by setting the sourceType.
4876
//
@@ -59,18 +87,11 @@ type ClusterExtensionSpec struct {
5987
// +kubebuilder:validation:Required
6088
Source SourceConfig `json:"source"`
6189

62-
// install is a required field used to configure the installation options
63-
// for the ClusterExtension such as the installation namespace,
64-
// the service account and the pre-flight check configuration.
90+
// install is an optional field used to configure the installation options
91+
// for the ClusterExtension such as the pre-flight check configuration.
6592
//
66-
// Below is a minimal example of an installation definition (in yaml):
67-
// install:
68-
// namespace: example-namespace
69-
// serviceAccount:
70-
// name: example-sa
71-
//
72-
// +kubebuilder:validation:Required
73-
Install ClusterExtensionInstallConfig `json:"install"`
93+
// +optional
94+
Install *ClusterExtensionInstallConfig `json:"install,omitempty"`
7495
}
7596

7697
const SourceTypeCatalog = "Catalog"
@@ -104,38 +125,9 @@ type SourceConfig struct {
104125
// ClusterExtensionInstallConfig is a union which selects the clusterExtension installation config.
105126
// ClusterExtensionInstallConfig requires the namespace and serviceAccount which should be used for the installation of packages.
106127
//
128+
// +kubebuilder:validation:XValidation:rule="has(self.preflight)",message="at least one of [preflight] are required when install is specified"
107129
// +union
108130
type ClusterExtensionInstallConfig struct {
109-
// namespace designates the kubernetes Namespace where bundle content
110-
// for the package, referenced in the 'packageName' field, will be applied and the necessary
111-
// service account can be found.
112-
// The bundle may contain cluster-scoped resources or resources that are
113-
// applied to other Namespaces. This Namespace is expected to exist.
114-
//
115-
// namespace is required, immutable, and follows the DNS label standard
116-
// as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
117-
// start and end with an alphanumeric character, and be no longer than 63 characters
118-
//
119-
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
120-
//
121-
// +kubebuilder:validation:MaxLength:=63
122-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="namespace is immutable"
123-
// +kubebuilder:validation:XValidation:rule="self.matches(\"^[a-z0-9]([-a-z0-9]*[a-z0-9])?$\")",message="namespace must be a valid DNS1123 label"
124-
// +kubebuilder:validation:Required
125-
Namespace string `json:"namespace"`
126-
127-
// serviceAccount is a required reference to a ServiceAccount that exists
128-
// in the installNamespace which is used to install and
129-
// manage the content for the package specified in the packageName field.
130-
//
131-
// In order to successfully install and manage the content for the package,
132-
// the ServiceAccount provided via this field should be configured with the
133-
// appropriate permissions to perform the necessary operations on all the
134-
// resources that are included in the bundle of content being applied.
135-
//
136-
// +kubebuilder:validation:Required
137-
ServiceAccount ServiceAccountReference `json:"serviceAccount"`
138-
139131
// preflight is an optional field that can be used to configure the checks that are
140132
// run before installation or upgrade of the content for the package specified in the packageName field.
141133
//

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/manager/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func main() {
197197
helmclient.StorageDriverMapper(action.ChunkedStorageDriverMapper(coreClient, mgr.GetAPIReader(), systemNamespace)),
198198
helmclient.ClientNamespaceMapper(func(obj client.Object) (string, error) {
199199
ext := obj.(*ocv1alpha1.ClusterExtension)
200-
return ext.Spec.Install.Namespace, nil
200+
return ext.Spec.Namespace, nil
201201
}),
202202
helmclient.ClientRestConfigMapper(clientRestConfigMapper),
203203
)

config/base/crd/bases/olm.operatorframework.io_clusterextensions.yaml

Lines changed: 65 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -58,36 +58,9 @@ spec:
5858
properties:
5959
install:
6060
description: |-
61-
install is a required field used to configure the installation options
62-
for the ClusterExtension such as the installation namespace,
63-
the service account and the pre-flight check configuration.
64-
65-
Below is a minimal example of an installation definition (in yaml):
66-
install:
67-
namespace: example-namespace
68-
serviceAccount:
69-
name: example-sa
61+
install is an optional field used to configure the installation options
62+
for the ClusterExtension such as the pre-flight check configuration.
7063
properties:
71-
namespace:
72-
description: |-
73-
namespace designates the kubernetes Namespace where bundle content
74-
for the package, referenced in the 'packageName' field, will be applied and the necessary
75-
service account can be found.
76-
The bundle may contain cluster-scoped resources or resources that are
77-
applied to other Namespaces. This Namespace is expected to exist.
78-
79-
namespace is required, immutable, and follows the DNS label standard
80-
as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
81-
start and end with an alphanumeric character, and be no longer than 63 characters
82-
83-
[RFC 1123]: https://tools.ietf.org/html/rfc1123
84-
maxLength: 63
85-
type: string
86-
x-kubernetes-validations:
87-
- message: namespace is immutable
88-
rule: self == oldSelf
89-
- message: namespace must be a valid DNS1123 label
90-
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
9164
preflight:
9265
description: |-
9366
preflight is an optional field that can be used to configure the checks that are
@@ -130,55 +103,74 @@ spec:
130103
- message: at least one of [crdUpgradeSafety] are required when
131104
preflight is specified
132105
rule: has(self.crdUpgradeSafety)
133-
serviceAccount:
106+
type: object
107+
x-kubernetes-validations:
108+
- message: at least one of [preflight] are required when install is
109+
specified
110+
rule: has(self.preflight)
111+
namespace:
112+
description: |-
113+
namespace is a reference to a Kubernetes namespace.
114+
This is the namespace the provided ServiceAccount must exist.
115+
It also designates the default namespace where namespace-scoped resources
116+
for the extension are applied to the cluster.
117+
Some extensions may contain namespace-scoped resources to be applied in other namespaces.
118+
This namespace must exist.
119+
120+
namespace is required, immutable, and follows the DNS label standard
121+
as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
122+
start and end with an alphanumeric character, and be no longer than 63 characters
123+
124+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
125+
maxLength: 63
126+
type: string
127+
x-kubernetes-validations:
128+
- message: namespace is immutable
129+
rule: self == oldSelf
130+
- message: namespace must be a valid DNS1123 label
131+
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
132+
serviceAccount:
133+
description: |-
134+
serviceAccount is a reference to a ServiceAccount used to perform all interactions
135+
with the cluster that are required to manage the extension.
136+
The ServiceAccount must be configured with the necessary permissions to perform these interactions.
137+
The ServiceAccount must exist in the namespace referenced in the spec.
138+
serviceAccount is required.
139+
properties:
140+
name:
134141
description: |-
135-
serviceAccount is a required reference to a ServiceAccount that exists
136-
in the installNamespace which is used to install and
137-
manage the content for the package specified in the packageName field.
138-
139-
In order to successfully install and manage the content for the package,
140-
the ServiceAccount provided via this field should be configured with the
141-
appropriate permissions to perform the necessary operations on all the
142-
resources that are included in the bundle of content being applied.
143-
properties:
144-
name:
145-
description: |-
146-
name is a required, immutable reference to the name of the ServiceAccount
147-
to be used for installation and management of the content for the package
148-
specified in the packageName field.
142+
name is a required, immutable reference to the name of the ServiceAccount
143+
to be used for installation and management of the content for the package
144+
specified in the packageName field.
149145
150-
This ServiceAccount must exist in the installNamespace.
146+
This ServiceAccount must exist in the installNamespace.
151147
152-
name follows the DNS subdomain standard as defined in [RFC 1123].
153-
It must contain only lowercase alphanumeric characters,
154-
hyphens (-) or periods (.), start and end with an alphanumeric character,
155-
and be no longer than 253 characters.
148+
name follows the DNS subdomain standard as defined in [RFC 1123].
149+
It must contain only lowercase alphanumeric characters,
150+
hyphens (-) or periods (.), start and end with an alphanumeric character,
151+
and be no longer than 253 characters.
156152
157-
Some examples of valid values are:
158-
- some-serviceaccount
159-
- 123-serviceaccount
160-
- 1-serviceaccount-2
161-
- someserviceaccount
162-
- some.serviceaccount
153+
Some examples of valid values are:
154+
- some-serviceaccount
155+
- 123-serviceaccount
156+
- 1-serviceaccount-2
157+
- someserviceaccount
158+
- some.serviceaccount
163159
164-
Some examples of invalid values are:
165-
- -some-serviceaccount
166-
- some-serviceaccount-
160+
Some examples of invalid values are:
161+
- -some-serviceaccount
162+
- some-serviceaccount-
167163
168-
[RFC 1123]: https://tools.ietf.org/html/rfc1123
169-
maxLength: 253
170-
type: string
171-
x-kubernetes-validations:
172-
- message: name is immutable
173-
rule: self == oldSelf
174-
- message: name must be a valid DNS1123 subdomain
175-
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
176-
required:
177-
- name
178-
type: object
164+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
165+
maxLength: 253
166+
type: string
167+
x-kubernetes-validations:
168+
- message: name is immutable
169+
rule: self == oldSelf
170+
- message: name must be a valid DNS1123 subdomain
171+
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
179172
required:
180-
- namespace
181-
- serviceAccount
173+
- name
182174
type: object
183175
source:
184176
description: |-
@@ -459,7 +451,8 @@ spec:
459451
rule: 'has(self.sourceType) && self.sourceType == ''Catalog'' ?
460452
has(self.catalog) : !has(self.catalog)'
461453
required:
462-
- install
454+
- namespace
455+
- serviceAccount
463456
- source
464457
type: object
465458
status:

config/samples/olm_v1alpha1_clusterextension.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,11 @@ kind: ClusterExtension
272272
metadata:
273273
name: argocd
274274
spec:
275+
namespace: argocd
276+
serviceAccount:
277+
name: argocd-installer
275278
source:
276279
sourceType: Catalog
277280
catalog:
278281
packageName: argocd-operator
279282
version: 0.6.0
280-
install:
281-
namespace: argocd
282-
serviceAccount:
283-
name: argocd-installer

internal/action/restconfig.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ func ServiceAccountRestConfigMapper(tokenGetter *authentication.TokenGetter) fun
1616
return func(ctx context.Context, o client.Object, c *rest.Config) (*rest.Config, error) {
1717
cExt := o.(*ocv1alpha1.ClusterExtension)
1818
saKey := types.NamespacedName{
19-
Name: cExt.Spec.Install.ServiceAccount.Name,
20-
Namespace: cExt.Spec.Install.Namespace,
19+
Name: cExt.Spec.ServiceAccount.Name,
20+
Namespace: cExt.Spec.Namespace,
2121
}
2222
saConfig := rest.AnonymousClientConfig(c)
2323
saConfig.Wrap(func(rt http.RoundTripper) http.RoundTripper {

internal/applier/helm.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func shouldSkipPreflight(ctx context.Context, preflight Preflight, ext *ocv1alph
7878
}
7979

8080
func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.ClusterExtension, objectLabels map[string]string, storageLabels map[string]string) ([]client.Object, string, error) {
81-
chrt, err := convert.RegistryV1ToHelmChart(ctx, contentFS, ext.Spec.Install.Namespace, []string{corev1.NamespaceAll})
81+
chrt, err := convert.RegistryV1ToHelmChart(ctx, contentFS, ext.Spec.Namespace, []string{corev1.NamespaceAll})
8282
if err != nil {
8383
return nil, "", err
8484
}
@@ -118,7 +118,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
118118

119119
switch state {
120120
case StateNeedsInstall:
121-
rel, err = ac.Install(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(install *action.Install) error {
121+
rel, err = ac.Install(ext.GetName(), ext.Spec.Namespace, chrt, values, func(install *action.Install) error {
122122
install.CreateNamespace = false
123123
install.Labels = storageLabels
124124
return nil
@@ -127,7 +127,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
127127
return nil, state, err
128128
}
129129
case StateNeedsUpgrade:
130-
rel, err = ac.Upgrade(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(upgrade *action.Upgrade) error {
130+
rel, err = ac.Upgrade(ext.GetName(), ext.Spec.Namespace, chrt, values, func(upgrade *action.Upgrade) error {
131131
upgrade.MaxHistory = maxHelmReleaseHistory
132132
upgrade.Labels = storageLabels
133133
return nil
@@ -161,7 +161,7 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
161161
}
162162

163163
if errors.Is(err, driver.ErrReleaseNotFound) {
164-
desiredRelease, err := cl.Install(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(i *action.Install) error {
164+
desiredRelease, err := cl.Install(ext.GetName(), ext.Spec.Namespace, chrt, values, func(i *action.Install) error {
165165
i.DryRun = true
166166
i.DryRunOption = "server"
167167
return nil
@@ -171,7 +171,7 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
171171
}
172172
return nil, desiredRelease, StateNeedsInstall, nil
173173
}
174-
desiredRelease, err := cl.Upgrade(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(upgrade *action.Upgrade) error {
174+
desiredRelease, err := cl.Upgrade(ext.GetName(), ext.Spec.Namespace, chrt, values, func(upgrade *action.Upgrade) error {
175175
upgrade.MaxHistory = maxHelmReleaseHistory
176176
upgrade.DryRun = true
177177
upgrade.DryRunOption = "server"

0 commit comments

Comments
 (0)