@@ -6,10 +6,11 @@ package controlplanevirtualip
66import (
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
3233type 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
4737type 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.
5845func 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,35 @@ 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 =
176+ slices .Delete (obj .Spec .Template .Spec .KubeadmConfigSpec .Files , i , i + 1 )
177+ break
178+ }
179+ }
180+ }
181+ }
182+
183+ // mergeFiles will merge the files into the KubeadmControlPlaneTemplate,
184+ // overriding any file with the same path and appending the rest.
185+ func mergeFiles (obj * controlplanev1.KubeadmControlPlaneTemplate , filesToMerge ... bootstrapv1.File ) {
186+ // replace any existing files with the same path
187+ for i := len (filesToMerge ) - 1 ; i >= 0 ; i -- {
188+ for j := range obj .Spec .Template .Spec .KubeadmConfigSpec .Files {
189+ if obj .Spec .Template .Spec .KubeadmConfigSpec .Files [j ].Path == filesToMerge [i ].Path {
190+ obj .Spec .Template .Spec .KubeadmConfigSpec .Files [j ] = filesToMerge [i ]
191+ filesToMerge = slices .Delete (filesToMerge , i , i + 1 )
192+ break
193+ }
194+ }
195+ }
196+ // append the remaining files
197+ obj .Spec .Template .Spec .KubeadmConfigSpec .Files = append (
198+ obj .Spec .Template .Spec .KubeadmConfigSpec .Files ,
199+ filesToMerge ... ,
200+ )
201+ }
0 commit comments