Skip to content

Commit 8b180df

Browse files
committed
feat: make talosconfig and talosconfigtemplate immutable
This change is made to conform CAPI practices for resource updates: instead of modifying the templates/configs, it is necessary to create a new one. If the resource is always recreated, rolling update strategy will be able to pick up the change and redeploy machines. Signed-off-by: Artem Chernyshev <[email protected]>
1 parent e66b203 commit 8b180df

File tree

5 files changed

+104
-3
lines changed

5 files changed

+104
-3
lines changed

api/v1alpha3/talosconfig_webhook.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package v1alpha3
77
import (
88
"fmt"
99

10+
"github.com/google/go-cmp/cmp"
1011
apierrors "k8s.io/apimachinery/pkg/api/errors"
1112
runtime "k8s.io/apimachinery/pkg/runtime"
1213
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -21,7 +22,7 @@ func (r *TalosConfig) SetupWebhookWithManager(mgr ctrl.Manager) error {
2122
Complete()
2223
}
2324

24-
//+kubebuilder:webhook:verbs=create;update;delete,path=/validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfig,mutating=false,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=talosconfigs,versions=v1alpha3,name=vtalosconfig.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1
25+
//+kubebuilder:webhook:verbs=create;update,path=/validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfig,mutating=false,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=talosconfigs,versions=v1alpha3,name=vtalosconfig.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1
2526

2627
var _ webhook.Validator = &TalosConfig{}
2728

@@ -31,7 +32,13 @@ func (r *TalosConfig) ValidateCreate() error {
3132
}
3233

3334
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
34-
func (r *TalosConfig) ValidateUpdate(old runtime.Object) error {
35+
func (r *TalosConfig) ValidateUpdate(oldRaw runtime.Object) error {
36+
old := oldRaw.(*TalosConfig)
37+
38+
if !cmp.Equal(r.Spec, old.Spec) {
39+
return apierrors.NewBadRequest("TalosConfig.Spec is immutable")
40+
}
41+
3542
return r.validate()
3643
}
3744

api/v1alpha3/talosconfigtemplate_webhook.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,40 @@
55
package v1alpha3
66

77
import (
8+
"github.com/google/go-cmp/cmp"
9+
apierrors "k8s.io/apimachinery/pkg/api/errors"
10+
runtime "k8s.io/apimachinery/pkg/runtime"
811
ctrl "sigs.k8s.io/controller-runtime"
12+
"sigs.k8s.io/controller-runtime/pkg/webhook"
913
)
1014

1115
func (r *TalosConfigTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
1216
return ctrl.NewWebhookManagedBy(mgr).
1317
For(r).
1418
Complete()
1519
}
20+
21+
//+kubebuilder:webhook:verbs=update,path=/validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfigtemplate,mutating=false,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=talosconfigtemplates,versions=v1alpha3,name=vtalosconfigtemplate.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1
22+
23+
var _ webhook.Validator = &TalosConfigTemplate{}
24+
25+
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
26+
func (r *TalosConfigTemplate) ValidateCreate() error {
27+
return nil
28+
}
29+
30+
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
31+
func (r *TalosConfigTemplate) ValidateUpdate(oldRaw runtime.Object) error {
32+
old := oldRaw.(*TalosConfigTemplate)
33+
34+
if !cmp.Equal(r.Spec, old.Spec) {
35+
return apierrors.NewBadRequest("TalosConfigTemplate.Spec is immutable")
36+
}
37+
38+
return nil
39+
}
40+
41+
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
42+
func (r *TalosConfigTemplate) ValidateDelete() error {
43+
return nil
44+
}

config/webhook/manifests.yaml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,25 @@ webhooks:
2222
operations:
2323
- CREATE
2424
- UPDATE
25-
- DELETE
2625
resources:
2726
- talosconfigs
2827
sideEffects: None
28+
- admissionReviewVersions:
29+
- v1
30+
clientConfig:
31+
service:
32+
name: webhook-service
33+
namespace: system
34+
path: /validate-bootstrap-cluster-x-k8s-io-v1alpha3-talosconfigtemplate
35+
failurePolicy: Fail
36+
name: vtalosconfigtemplate.cluster.x-k8s.io
37+
rules:
38+
- apiGroups:
39+
- bootstrap.cluster.x-k8s.io
40+
apiVersions:
41+
- v1alpha3
42+
operations:
43+
- UPDATE
44+
resources:
45+
- talosconfigtemplates
46+
sideEffects: None

internal/integration/integration_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,50 @@ func TestIntegration(t *testing.T) {
483483
err := c.Create(ctx, talosConfig)
484484
require.Error(t, err)
485485
assert.True(t, apierrors.IsInvalid(err))
486+
487+
talosConfig.Spec.Hostname.Source = ""
488+
489+
err = c.Create(ctx, talosConfig)
490+
require.NoError(t, err)
491+
492+
patchHelper, err := patch.NewHelper(talosConfig, c)
493+
require.NoError(t, err)
494+
talosConfig.Spec.TalosVersion = "v0.7.0"
495+
496+
err = patchHelper.Patch(ctx, talosConfig)
497+
require.Error(t, err)
498+
assert.True(t, strings.Contains(err.Error(), "is immutable"))
499+
})
500+
t.Run("TalosConfigTemplateValidate", func(t *testing.T) {
501+
t.Parallel()
502+
503+
namespaceName := setupTest(ctx, t, c)
504+
505+
talosConfigTemplateName := generateName(t, "talosconfigtemplate")
506+
talosConfigTemplate := &bootstrapv1alpha3.TalosConfigTemplate{
507+
ObjectMeta: metav1.ObjectMeta{
508+
Namespace: namespaceName,
509+
Name: talosConfigTemplateName,
510+
},
511+
Spec: bootstrapv1alpha3.TalosConfigTemplateSpec{
512+
Template: bootstrapv1alpha3.TalosConfigTemplateResource{
513+
Spec: bootstrapv1alpha3.TalosConfigSpec{
514+
TalosVersion: "v0.1.0",
515+
},
516+
},
517+
},
518+
}
519+
520+
err := c.Create(ctx, talosConfigTemplate)
521+
require.NoError(t, err)
522+
523+
patchHelper, err := patch.NewHelper(talosConfigTemplate, c)
524+
require.NoError(t, err)
525+
talosConfigTemplate.Spec.Template.Spec.TalosVersion = "v1.0.0"
526+
527+
err = patchHelper.Patch(ctx, talosConfigTemplate)
528+
require.Error(t, err)
529+
assert.True(t, strings.Contains(err.Error(), "is immutable"))
486530
})
487531
}
488532

internal/integration/setup_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ func setupSuite(t *testing.T) (context.Context, client.Client) {
9595
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 10})
9696
require.NoError(t, err)
9797

98+
err = (&bootstrapv1alpha3.TalosConfigTemplate{}).SetupWebhookWithManager(mgr)
99+
require.NoError(t, err)
100+
98101
err = (&bootstrapv1alpha3.TalosConfig{}).SetupWebhookWithManager(mgr)
99102
require.NoError(t, err)
100103

0 commit comments

Comments
 (0)