Skip to content

Commit efc4a4c

Browse files
authored
Merge pull request #813 from makhov/fix-808
Initiate update on machine template ref change
2 parents bc69797 + 9510b68 commit efc4a4c

File tree

6 files changed

+660
-83
lines changed

6 files changed

+660
-83
lines changed

internal/controller/controlplane/helper.go

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2023.
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+
117
package controlplane
218

319
import (
@@ -16,6 +32,7 @@ import (
1632
"k8s.io/apimachinery/pkg/types"
1733
"k8s.io/client-go/kubernetes"
1834
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
35+
"sigs.k8s.io/cluster-api/controllers/external"
1936
"sigs.k8s.io/cluster-api/util/collections"
2037
ctrl "sigs.k8s.io/controller-runtime"
2138
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -24,6 +41,10 @@ import (
2441
cpv1beta1 "github.com/k0sproject/k0smotron/api/controlplane/v1beta1"
2542
)
2643

44+
const (
45+
etcdMemberConditionTypeJoined = "Joined"
46+
)
47+
2748
func (c *K0sController) createMachine(ctx context.Context, name string, cluster *clusterv1.Cluster, kcp *cpv1beta1.K0sControlPlane, infraRef corev1.ObjectReference, failureDomain *string) (*clusterv1.Machine, error) {
2849
machine, err := c.generateMachine(ctx, name, cluster, kcp, infraRef, failureDomain)
2950
if err != nil {
@@ -100,6 +121,21 @@ func (c *K0sController) generateMachine(_ context.Context, name string, cluster
100121
return machine, nil
101122
}
102123

124+
func (c *K0sController) getInfraMachines(ctx context.Context, machines collections.Machines) (map[string]*unstructured.Unstructured, error) {
125+
result := map[string]*unstructured.Unstructured{}
126+
for _, m := range machines {
127+
infraMachine, err := external.Get(ctx, c.Client, &m.Spec.InfrastructureRef, m.Namespace)
128+
if err != nil {
129+
if apierrors.IsNotFound(err) {
130+
continue
131+
}
132+
return nil, fmt.Errorf("failed to retrieve infra machine for machine object %s: %w", m.Name, err)
133+
}
134+
result[m.Name] = infraMachine
135+
}
136+
return result, nil
137+
}
138+
103139
func (c *K0sController) createMachineFromTemplate(ctx context.Context, name string, cluster *clusterv1.Cluster, kcp *cpv1beta1.K0sControlPlane) (*unstructured.Unstructured, error) {
104140
machineFromTemplate, err := c.generateMachineFromTemplate(ctx, name, cluster, kcp)
105141
if err != nil {
@@ -211,15 +247,62 @@ func (c *K0sController) generateMachineFromTemplate(ctx context.Context, name st
211247
return machine, nil
212248
}
213249

250+
func matchesTemplateClonedFrom(infraMachines map[string]*unstructured.Unstructured, kcp *cpv1beta1.K0sControlPlane, machine *clusterv1.Machine) bool {
251+
if machine == nil {
252+
return false
253+
}
254+
infraMachine, found := infraMachines[machine.Name]
255+
if !found {
256+
return false
257+
}
258+
259+
clonedFromName := infraMachine.GetAnnotations()[clusterv1.TemplateClonedFromNameAnnotation]
260+
clonedFromGroupKind := infraMachine.GetAnnotations()[clusterv1.TemplateClonedFromGroupKindAnnotation]
261+
262+
return clonedFromName == kcp.Spec.MachineTemplate.InfrastructureRef.Name &&
263+
clonedFromGroupKind == kcp.Spec.MachineTemplate.InfrastructureRef.GroupVersionKind().GroupKind().String()
264+
}
265+
266+
func (c *K0sController) checkMachineLeft(ctx context.Context, name string, clientset *kubernetes.Clientset) (bool, error) {
267+
var etcdMember unstructured.Unstructured
268+
err := clientset.RESTClient().
269+
Get().
270+
AbsPath("/apis/etcd.k0sproject.io/v1beta1/etcdmembers/" + name).
271+
Do(ctx).
272+
Into(&etcdMember)
273+
274+
if err != nil {
275+
if apierrors.IsNotFound(err) {
276+
return true, nil
277+
}
278+
return false, fmt.Errorf("error getting etcd member: %w", err)
279+
}
280+
281+
conditions, _, err := unstructured.NestedSlice(etcdMember.Object, "status", "conditions")
282+
if err != nil {
283+
return false, fmt.Errorf("error getting etcd member conditions: %w", err)
284+
}
285+
286+
for _, condition := range conditions {
287+
conditionMap := condition.(map[string]interface{})
288+
if conditionMap["type"] == etcdMemberConditionTypeJoined && conditionMap["status"] == "False" {
289+
return true, nil
290+
}
291+
}
292+
return false, nil
293+
}
294+
214295
func (c *K0sController) markChildControlNodeToLeave(ctx context.Context, name string, clientset *kubernetes.Clientset) error {
215296
if clientset == nil {
216297
return nil
217298
}
299+
218300
logger := log.FromContext(ctx).WithValues("controlNode", name)
301+
219302
err := clientset.RESTClient().
220303
Patch(types.MergePatchType).
221304
AbsPath("/apis/etcd.k0sproject.io/v1beta1/etcdmembers/" + name).
222-
Body([]byte(`{"spec":{"leave":true}}`)).
305+
Body([]byte(`{"spec":{"leave":true}, "metadata": {"annotations": {"k0smotron.io/marked-to-leave-at": "` + time.Now().String() + `"}}}`)).
223306
Do(ctx).
224307
Error()
225308
if err != nil {

0 commit comments

Comments
 (0)