Skip to content

Commit 3385406

Browse files
committed
feat: read kube-vip template from KCPTemplate
To correctly support kube-vip version upgrades without an unplanned control-plane rollout, read the kube-vip template directly from the KCPTemplate that will be released along with the ClusterClasses.
1 parent 84ca8d6 commit 3385406

File tree

10 files changed

+475
-282
lines changed

10 files changed

+475
-282
lines changed

common/pkg/testutils/capitest/request/items.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,19 @@ func NewKubeadmConfigTemplateRequest(
8383
)
8484
}
8585

86-
func NewKubeadmControlPlaneTemplateRequest(
86+
type KubeadmControlPlaneTemplateRequestItemBuilder struct {
87+
files []bootstrapv1.File
88+
}
89+
90+
func (b *KubeadmControlPlaneTemplateRequestItemBuilder) WithFiles(
91+
files ...bootstrapv1.File,
92+
) *KubeadmControlPlaneTemplateRequestItemBuilder {
93+
b.files = files
94+
return b
95+
}
96+
97+
func (b *KubeadmControlPlaneTemplateRequestItemBuilder) NewRequest(
8798
uid types.UID,
88-
name string,
8999
) runtimehooksv1.GeneratePatchesRequestItem {
90100
return NewRequestItem(
91101
&controlplanev1.KubeadmControlPlaneTemplate{
@@ -94,7 +104,7 @@ func NewKubeadmControlPlaneTemplateRequest(
94104
Kind: "KubeadmControlPlaneTemplate",
95105
},
96106
ObjectMeta: metav1.ObjectMeta{
97-
Name: name,
107+
Name: kubeadmControlPlaneTemplateRequestObjectName,
98108
Namespace: Namespace,
99109
},
100110
Spec: controlplanev1.KubeadmControlPlaneTemplateSpec{
@@ -107,6 +117,7 @@ func NewKubeadmControlPlaneTemplateRequest(
107117
JoinConfiguration: &bootstrapv1.JoinConfiguration{
108118
NodeRegistration: bootstrapv1.NodeRegistrationOptions{},
109119
},
120+
Files: b.files,
110121
},
111122
},
112123
},
@@ -126,7 +137,8 @@ func NewKubeadmControlPlaneTemplateRequest(
126137
func NewKubeadmControlPlaneTemplateRequestItem(
127138
uid types.UID,
128139
) runtimehooksv1.GeneratePatchesRequestItem {
129-
return NewKubeadmControlPlaneTemplateRequest(uid, kubeadmControlPlaneTemplateRequestObjectName)
140+
builder := &KubeadmControlPlaneTemplateRequestItemBuilder{}
141+
return builder.NewRequest(uid)
130142
}
131143

132144
func NewCPDockerMachineTemplateRequestItem(

pkg/handlers/generic/mutation/controlplanevirtualip/inject.go

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ package controlplanevirtualip
66
import (
77
"context"
88
"fmt"
9+
"slices"
910

10-
"github.com/spf13/pflag"
1111
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1212
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
13+
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
1314
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
1415
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
1516
ctrl "sigs.k8s.io/controller-runtime"
@@ -31,23 +32,9 @@ const (
3132

3233
type Config struct {
3334
*options.GlobalOptions
34-
35-
defaultKubeVIPConfigMapName string
36-
}
37-
38-
func (c *Config) AddFlags(prefix string, flags *pflag.FlagSet) {
39-
flags.StringVar(
40-
&c.defaultKubeVIPConfigMapName,
41-
prefix+".default-kube-vip-template-configmap-name",
42-
"default-kube-vip-template",
43-
"default ConfigMap name that holds the kube-vip template used for the control-plane virtual IP",
44-
)
4535
}
4636

4737
type ControlPlaneVirtualIP struct {
48-
client client.Reader
49-
config *Config
50-
5138
variableName string
5239
variableFieldPath []string
5340
}
@@ -56,14 +43,10 @@ type ControlPlaneVirtualIP struct {
5643
// It requires variableName and variableFieldPath to be passed from another provider specific handler.
5744
// The code is here to be shared across different providers.
5845
func NewControlPlaneVirtualIP(
59-
cl client.Reader,
60-
config *Config,
6146
variableName string,
6247
variableFieldPath ...string,
6348
) *ControlPlaneVirtualIP {
6449
return &ControlPlaneVirtualIP{
65-
client: cl,
66-
config: config,
6750
variableName: variableName,
6851
variableFieldPath: variableFieldPath,
6952
}
@@ -103,11 +86,6 @@ func (h *ControlPlaneVirtualIP) Mutate(
10386
controlPlaneEndpointVar,
10487
)
10588

106-
if controlPlaneEndpointVar.VirtualIPSpec == nil {
107-
log.V(5).Info("ControlPlane VirtualIP not set")
108-
return nil
109-
}
110-
11189
cluster, err := clusterGetter(ctx)
11290
if err != nil {
11391
log.Error(
@@ -117,23 +95,27 @@ func (h *ControlPlaneVirtualIP) Mutate(
11795
return err
11896
}
11997

120-
var virtualIPProvider providers.Provider
121-
// only kube-vip is supported, but more providers can be added in the future
122-
if controlPlaneEndpointVar.VirtualIPSpec.Provider == v1alpha1.VirtualIPProviderKubeVIP {
123-
virtualIPProvider = providers.NewKubeVIPFromConfigMapProvider(
124-
h.client,
125-
h.config.defaultKubeVIPConfigMapName,
126-
h.config.DefaultsNamespace(),
127-
)
128-
}
129-
13098
return patches.MutateIfApplicable(
13199
obj,
132100
vars,
133101
&holderRef,
134102
selectors.ControlPlane(),
135103
log,
136104
func(obj *controlplanev1.KubeadmControlPlaneTemplate) error {
105+
if controlPlaneEndpointVar.VirtualIPSpec == nil {
106+
log.V(5).Info("ControlPlane VirtualIP not set")
107+
// if VirtualIPSpec is not set, delete all template files
108+
// as we do not want them to end up in the generated KCP
109+
deleteFiles(obj, providers.TemplateFileNames...)
110+
return nil
111+
}
112+
113+
var virtualIPProvider providers.Provider
114+
// only kube-vip is supported, but more providers can be added in the future
115+
if controlPlaneEndpointVar.VirtualIPSpec.Provider == v1alpha1.VirtualIPProviderKubeVIP {
116+
virtualIPProvider = providers.NewKubeVIPFromKCPTemplateProvider(obj)
117+
}
118+
137119
files, preKubeadmCommands, postKubeadmCommands, generateErr := virtualIPProvider.GenerateFilesAndCommands(
138120
ctx,
139121
controlPlaneEndpointVar,
@@ -150,10 +132,8 @@ func (h *ControlPlaneVirtualIP) Mutate(
150132
"adding %s static Pod file to control plane kubeadm config spec",
151133
virtualIPProvider.Name(),
152134
))
153-
obj.Spec.Template.Spec.KubeadmConfigSpec.Files = append(
154-
obj.Spec.Template.Spec.KubeadmConfigSpec.Files,
155-
files...,
156-
)
135+
136+
mergeFiles(obj, files...)
157137

158138
if len(preKubeadmCommands) > 0 {
159139
log.WithValues(
@@ -187,3 +167,36 @@ func (h *ControlPlaneVirtualIP) Mutate(
187167
},
188168
)
189169
}
170+
171+
func deleteFiles(obj *controlplanev1.KubeadmControlPlaneTemplate, filePathsToDelete ...string) {
172+
for i := len(obj.Spec.Template.Spec.KubeadmConfigSpec.Files) - 1; i >= 0; i-- {
173+
for _, path := range filePathsToDelete {
174+
if obj.Spec.Template.Spec.KubeadmConfigSpec.Files[i].Path == path {
175+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files = slices.Delete(
176+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files, i, i+1,
177+
)
178+
break
179+
}
180+
}
181+
}
182+
}
183+
184+
// mergeFiles will merge the files into the KubeadmControlPlaneTemplate,
185+
// overriding any file with the same path and appending the rest.
186+
func mergeFiles(obj *controlplanev1.KubeadmControlPlaneTemplate, filesToMerge ...bootstrapv1.File) {
187+
// replace any existing files with the same path
188+
for i := len(filesToMerge) - 1; i >= 0; i-- {
189+
for j := range obj.Spec.Template.Spec.KubeadmConfigSpec.Files {
190+
if obj.Spec.Template.Spec.KubeadmConfigSpec.Files[j].Path == filesToMerge[i].Path {
191+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files[j] = filesToMerge[i]
192+
filesToMerge = slices.Delete(filesToMerge, i, i+1)
193+
break
194+
}
195+
}
196+
}
197+
// append the remaining files
198+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files = append(
199+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files,
200+
filesToMerge...,
201+
)
202+
}

0 commit comments

Comments
 (0)