Skip to content

Commit b203030

Browse files
Add ability to specify a namespace for provider secret
1 parent 996d5d4 commit b203030

File tree

11 files changed

+191
-14
lines changed

11 files changed

+191
-14
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests for the operator e.g
294294
$(CONTROLLER_GEN) \
295295
paths=./api/... \
296296
paths=./internal/controller/... \
297+
paths=./internal/webhook/... \
297298
crd:crdVersions=v1 \
298299
rbac:roleName=manager-role \
299300
output:crd:dir=./config/crd/bases \

api/v1alpha1/provider_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ type ProviderSpec struct {
5151
// +optional
5252
SecretName string `json:"secretName,omitempty"`
5353

54+
// SecretNamespace is the namespace of the Secret providing the configuration variables. If not specified,
55+
// the namespace of the provider will be used.
56+
SecretNamespace string `json:"secretNamespace,omitempty"`
57+
5458
// FetchConfig determines how the operator will fetch the components and metadata for the provider.
5559
// If nil, the operator will try to fetch components according to default
5660
// embedded fetch configuration for the given kind and `ObjectMeta.Name`.

internal/controller/phases.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (p *phaseReconciler) secretReader(ctx context.Context) (configclient.Reader
195195
// Fetch configuration variables from the secret. See API field docs for more info.
196196
if p.provider.GetSpec().SecretName != "" {
197197
secret := &corev1.Secret{}
198-
key := types.NamespacedName{Namespace: p.provider.GetNamespace(), Name: p.provider.GetSpec().SecretName}
198+
key := types.NamespacedName{Namespace: p.provider.GetSpec().SecretNamespace, Name: p.provider.GetSpec().SecretName}
199199

200200
if err := p.ctrlClient.Get(ctx, key, secret); err != nil {
201201
return nil, err

internal/controller/phases_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func TestSecretReader(t *testing.T) {
3838
fakeclient := fake.NewClientBuilder().WithObjects().Build()
3939

4040
secretName := "test-secret"
41+
secretNamespace := "test-secret-namespace"
4142
namespace := "test-namespace"
4243

4344
p := &phaseReconciler{
@@ -54,7 +55,8 @@ func TestSecretReader(t *testing.T) {
5455
},
5556
Spec: operatorv1.CoreProviderSpec{
5657
ProviderSpec: operatorv1.ProviderSpec{
57-
SecretName: secretName,
58+
SecretName: secretName,
59+
SecretNamespace: secretNamespace,
5860
FetchConfig: &operatorv1.FetchConfiguration{
5961
URL: "https://example.com",
6062
},
@@ -72,7 +74,7 @@ func TestSecretReader(t *testing.T) {
7274
g.Expect(fakeclient.Create(ctx, &corev1.Secret{
7375
ObjectMeta: metav1.ObjectMeta{
7476
Name: secretName,
75-
Namespace: namespace,
77+
Namespace: secretNamespace,
7678
},
7779
Data: map[string][]byte{
7880
testKey1: []byte(testValue1),

internal/controller/preflight_checks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func preflightChecks(ctx context.Context, c client.Client, provider genericprovi
117117
// Validate that provided github token works and has repository access.
118118
if spec.SecretName != "" {
119119
secret := &corev1.Secret{}
120-
key := types.NamespacedName{Namespace: provider.GetNamespace(), Name: provider.GetSpec().SecretName}
120+
key := types.NamespacedName{Namespace: provider.GetSpec().SecretNamespace, Name: provider.GetSpec().SecretName}
121121

122122
if err := c.Get(ctx, key, secret); err != nil {
123123
return ctrl.Result{}, fmt.Errorf("failed to get providers secret: %w", err)

internal/webhook/bootstrapprovider_webhook.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package webhook
1818

1919
import (
2020
"context"
21+
"fmt"
2122

23+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2224
"k8s.io/apimachinery/pkg/runtime"
2325
ctrl "sigs.k8s.io/controller-runtime"
2426
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -32,12 +34,17 @@ func (r *BootstrapProviderWebhook) SetupWebhookWithManager(mgr ctrl.Manager) err
3234
return ctrl.NewWebhookManagedBy(mgr).
3335
For(&operatorv1.BootstrapProvider{}).
3436
WithValidator(r).
37+
WithDefaulter(r).
3538
Complete()
3639
}
3740

38-
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-bootstrapprovider,mutating=false,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=bootstrapproviders,versions=v1alpha1,name=vbootstrapprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1alpha1
41+
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-bootstrapprovider,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=bootstrapproviders,versions=v1alpha1,name=vbootstrapprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
42+
//+kubebuilder:webhook:verbs=create;update,path=/mutate-operator-cluster-x-k8s-io-v1alpha1-bootstrapprovider,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=bootstrapproviders,versions=v1alpha1,name=vbootstrapprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
3943

40-
var _ webhook.CustomValidator = &BootstrapProviderWebhook{}
44+
var (
45+
_ webhook.CustomValidator = &BootstrapProviderWebhook{}
46+
_ webhook.CustomDefaulter = &BootstrapProviderWebhook{}
47+
)
4148

4249
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
4350
func (r *BootstrapProviderWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) error {
@@ -53,3 +60,15 @@ func (r *BootstrapProviderWebhook) ValidateUpdate(ctx context.Context, oldObj, n
5360
func (r *BootstrapProviderWebhook) ValidateDelete(_ context.Context, obj runtime.Object) error {
5461
return nil
5562
}
63+
64+
// Default implements webhook.Default so a webhook will be registered for the type.
65+
func (r *BootstrapProviderWebhook) Default(ctx context.Context, obj runtime.Object) error {
66+
bootstrapProvider, ok := obj.(*operatorv1.BootstrapProvider)
67+
if !ok {
68+
return apierrors.NewBadRequest(fmt.Sprintf("expected a BootstrapProvider but got a %T", obj))
69+
}
70+
71+
setDefaultProviderSpec(&bootstrapProvider.Spec.ProviderSpec, bootstrapProvider.Namespace)
72+
73+
return nil
74+
}

internal/webhook/controlplaneprovider_webhook.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package webhook
1818

1919
import (
2020
"context"
21+
"fmt"
2122

23+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2224
"k8s.io/apimachinery/pkg/runtime"
2325
ctrl "sigs.k8s.io/controller-runtime"
2426
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -32,12 +34,17 @@ func (r *ControlPlaneProviderWebhook) SetupWebhookWithManager(mgr ctrl.Manager)
3234
return ctrl.NewWebhookManagedBy(mgr).
3335
For(&operatorv1.ControlPlaneProvider{}).
3436
WithValidator(r).
37+
WithDefaulter(r).
3538
Complete()
3639
}
3740

38-
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-controlplaneprovider,mutating=false,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=controlplaneproviders,versions=v1alpha1,name=vcontrolplaneprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1alpha1
41+
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-controlplaneprovider,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=controlplaneproviders,versions=v1alpha1,name=vcontrolplaneprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
42+
//+kubebuilder:webhook:verbs=create;update,path=/mutate-operator-cluster-x-k8s-io-v1alpha1-controlplaneprovider,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=controlplaneproviders,versions=v1alpha1,name=vcontrolplaneprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
3943

40-
var _ webhook.CustomValidator = &ControlPlaneProviderWebhook{}
44+
var (
45+
_ webhook.CustomValidator = &ControlPlaneProviderWebhook{}
46+
_ webhook.CustomDefaulter = &ControlPlaneProviderWebhook{}
47+
)
4148

4249
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
4350
func (r *ControlPlaneProviderWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) error {
@@ -53,3 +60,15 @@ func (r *ControlPlaneProviderWebhook) ValidateUpdate(ctx context.Context, oldObj
5360
func (r *ControlPlaneProviderWebhook) ValidateDelete(_ context.Context, obj runtime.Object) error {
5461
return nil
5562
}
63+
64+
// Default implements webhook.Default so a webhook will be registered for the type.
65+
func (r *ControlPlaneProviderWebhook) Default(ctx context.Context, obj runtime.Object) error {
66+
controlPlaneProvider, ok := obj.(*operatorv1.ControlPlaneProvider)
67+
if !ok {
68+
return apierrors.NewBadRequest(fmt.Sprintf("expected a ControlPlaneProvider but got a %T", obj))
69+
}
70+
71+
setDefaultProviderSpec(&controlPlaneProvider.Spec.ProviderSpec, controlPlaneProvider.Namespace)
72+
73+
return nil
74+
}

internal/webhook/coreprovider_webhook.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,32 @@ package webhook
1818

1919
import (
2020
"context"
21+
"fmt"
2122

23+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2224
"k8s.io/apimachinery/pkg/runtime"
25+
operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha1"
2326
ctrl "sigs.k8s.io/controller-runtime"
2427
"sigs.k8s.io/controller-runtime/pkg/webhook"
25-
26-
operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha1"
2728
)
2829

2930
type CoreProviderWebhook struct{}
3031

3132
func (r *CoreProviderWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
3233
return ctrl.NewWebhookManagedBy(mgr).
3334
WithValidator(r).
35+
WithDefaulter(r).
3436
For(&operatorv1.CoreProvider{}).
3537
Complete()
3638
}
3739

38-
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-coreprovider,mutating=false,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=coreproviders,versions=v1alpha1,name=vcoreprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1alpha1
40+
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-coreprovider,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=coreproviders,versions=v1alpha1,name=vcoreprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
41+
//+kubebuilder:webhook:verbs=create;update,path=/mutate-operator-cluster-x-k8s-io-v1alpha1-coreprovider,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=coreproviders,versions=v1alpha1,name=vcoreprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
3942

40-
var _ webhook.CustomValidator = &CoreProviderWebhook{}
43+
var (
44+
_ webhook.CustomValidator = &CoreProviderWebhook{}
45+
_ webhook.CustomDefaulter = &CoreProviderWebhook{}
46+
)
4147

4248
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
4349
func (r *CoreProviderWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) error {
@@ -53,3 +59,15 @@ func (r *CoreProviderWebhook) ValidateUpdate(ctx context.Context, oldObj, newObj
5359
func (r *CoreProviderWebhook) ValidateDelete(_ context.Context, obj runtime.Object) error {
5460
return nil
5561
}
62+
63+
// Default implements webhook.Default so a webhook will be registered for the type.
64+
func (r *CoreProviderWebhook) Default(ctx context.Context, obj runtime.Object) error {
65+
coreProvider, ok := obj.(*operatorv1.CoreProvider)
66+
if !ok {
67+
return apierrors.NewBadRequest(fmt.Sprintf("expected a CoreProvider but got a %T", obj))
68+
}
69+
70+
setDefaultProviderSpec(&coreProvider.Spec.ProviderSpec, coreProvider.Namespace)
71+
72+
return nil
73+
}

internal/webhook/infrastructureprovider_webhook.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package webhook
1818

1919
import (
2020
"context"
21+
"fmt"
2122

23+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2224
"k8s.io/apimachinery/pkg/runtime"
2325
ctrl "sigs.k8s.io/controller-runtime"
2426
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -31,13 +33,18 @@ type InfrastructureProviderWebhook struct{}
3133
func (r *InfrastructureProviderWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
3234
return ctrl.NewWebhookManagedBy(mgr).
3335
WithValidator(r).
36+
WithDefaulter(r).
3437
For(&operatorv1.InfrastructureProvider{}).
3538
Complete()
3639
}
3740

38-
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-infrastructureprovider,mutating=false,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=infrastructureproviders,versions=v1alpha1,name=vinfrastructureprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1alpha1
41+
//+kubebuilder:webhook:verbs=create;update,path=/validate-operator-cluster-x-k8s-io-v1alpha1-infrastructureprovider,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=operator.cluster.x-k8s.io,resources=infrastructureproviders,versions=v1alpha1,name=vinfrastructureprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
42+
//+kubebuilder:webhook:verbs=create;update,path=/mutate-operator-cluster-x-k8s-io-v1alpha1-infrastructureprovider,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,failurePolicy=fail,groups=operator.cluster.x-k8s.io,resources=infrastructureproviders,versions=v1alpha1,name=vinfrastructureprovider.kb.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
3943

40-
var _ webhook.CustomValidator = &InfrastructureProviderWebhook{}
44+
var (
45+
_ webhook.CustomValidator = &InfrastructureProviderWebhook{}
46+
_ webhook.CustomDefaulter = &InfrastructureProviderWebhook{}
47+
)
4148

4249
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
4350
func (r *InfrastructureProviderWebhook) ValidateCreate(ctx context.Context, obj runtime.Object) error {
@@ -53,3 +60,15 @@ func (r *InfrastructureProviderWebhook) ValidateUpdate(ctx context.Context, oldO
5360
func (r *InfrastructureProviderWebhook) ValidateDelete(_ context.Context, obj runtime.Object) error {
5461
return nil
5562
}
63+
64+
// Default implements webhook.Default so a webhook will be registered for the type.
65+
func (r *InfrastructureProviderWebhook) Default(ctx context.Context, obj runtime.Object) error {
66+
infrastructureProvider, ok := obj.(*operatorv1.InfrastructureProvider)
67+
if !ok {
68+
return apierrors.NewBadRequest(fmt.Sprintf("expected a InfrastructureProvider but got a %T", obj))
69+
}
70+
71+
setDefaultProviderSpec(&infrastructureProvider.Spec.ProviderSpec, infrastructureProvider.Namespace)
72+
73+
return nil
74+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package webhook
18+
19+
import (
20+
operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha1"
21+
)
22+
23+
// setDefaultProviderSpec sets the default values for the provider spec.
24+
func setDefaultProviderSpec(providerSpec *operatorv1.ProviderSpec, providerNamespace string) {
25+
if providerSpec.SecretName != "" && providerSpec.SecretNamespace == "" {
26+
providerSpec.SecretNamespace = providerNamespace
27+
}
28+
}

0 commit comments

Comments
 (0)