...
1
2 package resources
3
4 import (
5 "context"
6 "time"
7
8 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9 "k8s.io/apimachinery/pkg/types"
10 "sigs.k8s.io/controller-runtime/pkg/client"
11
12 "edge-infra.dev/pkg/k8s/runtime/conditions"
13 "edge-infra.dev/pkg/k8s/runtime/patch"
14 v1etcd "edge-infra.dev/pkg/sds/etcd/operator/apis/etcdmember/v1"
15
16 etcdretryclient "edge-infra.dev/pkg/sds/lib/etcd/client/retry"
17 kubeclienttypes "edge-infra.dev/pkg/sds/lib/k8s/retryclient/types"
18 )
19
20 type EtcdMemberHandler struct {
21 *v1etcd.EtcdMember
22
23 Client kubeclienttypes.Retrier
24 Key types.NamespacedName
25 Found bool
26 IsMember bool
27 IsLearner bool
28 }
29
30
31 func (h *EtcdMemberHandler) Validate(ctx context.Context) error {
32 opts := &client.CreateOptions{}
33 client.DryRunAll.ApplyToCreate(opts)
34 return client.IgnoreAlreadyExists(h.Client.SafeCreate(ctx, h.EtcdMember, opts))
35 }
36
37 func (h *EtcdMemberHandler) ReconcileMembershipStatus(ctx context.Context, client etcdretryclient.Retrier) error {
38 resp, err := client.SafeMemberList(ctx)
39 if err != nil {
40 return err
41 }
42 for _, member := range resp.Members {
43 if member.PeerURLs[0] == h.PeerURL() {
44 h.IsMember = true
45 h.IsLearner = member.IsLearner
46 }
47 }
48 return nil
49 }
50
51
52
53 func (h *EtcdMemberHandler) ReconcileLocal(ctx context.Context) error {
54 return h.Client.SafeGet(ctx, h.Key, h.EtcdMember)
55 }
56
57
58 func (h *EtcdMemberHandler) CreateRemote(ctx context.Context) error {
59 return h.Client.SafeCreate(ctx, h.EtcdMember)
60 }
61
62
63 func (h *EtcdMemberHandler) DeleteRemote(ctx context.Context) error {
64 return h.Client.SafeDelete(ctx, h.EtcdMember)
65 }
66
67
68
69 func (h *EtcdMemberHandler) WithReconcileRemote(ctx context.Context, fn func(e *v1etcd.EtcdMember)) error {
70 patcher := patch.NewSerialPatcher(h.EtcdMember, h.Client.Client())
71 fn(h.EtcdMember)
72
73 return patcher.Patch(ctx, h.EtcdMember)
74 }
75
76
77
78 func (h *EtcdMemberHandler) DeepCopyFrom(from *v1etcd.EtcdMember) {
79 from.DeepCopyInto(h.EtcdMember)
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 func (h *EtcdMemberHandler) ReconfigurationRequired() bool {
95 healthCondition := conditions.Get(h.EtcdMember, v1etcd.Health)
96 if healthCondition == nil {
97 return false
98 }
99 installedCondition := conditions.Get(h.EtcdMember, v1etcd.Installed)
100 switch installedCondition {
101 case nil:
102 return healthCondition.Status != metav1.ConditionTrue &&
103 healthCondition.LastTransitionTime.Add(60*time.Minute).Before(time.Now())
104 default:
105 return healthCondition.Status != metav1.ConditionTrue &&
106 healthCondition.LastTransitionTime.Add(h.Spec.BackoffPeriod()).Before(time.Now())
107 }
108 }
109
110
111
112 func (h *EtcdMemberHandler) DeletionRequired(currentIENVersion string) bool {
113 if !h.InstalledForLatestIEN(currentIENVersion) {
114 return true
115 }
116 if !h.DeletionTimestamp.IsZero() {
117 return true
118 }
119 return h.ReconfigurationRequired()
120 }
121
122
123 func (h *EtcdMemberHandler) IsProvisioned() bool {
124 return conditions.IsTrue(h.EtcdMember, v1etcd.Provisioned)
125 }
126
127
128 func (h *EtcdMemberHandler) IsInstalled() bool {
129 return conditions.IsTrue(h.EtcdMember, v1etcd.Installed)
130 }
131
132
133 func (h *EtcdMemberHandler) IsSuspended() bool {
134 return h.Spec.Suspend
135 }
136
137
138
139 func (h *EtcdMemberHandler) InstallationAttempted() bool {
140 condition := conditions.Get(h, v1etcd.Installed)
141 return condition != nil
142 }
143
144
145
146 func (h *EtcdMemberHandler) InstalledForLatestIEN(currentVersion string) bool {
147 installedVersion := h.EtcdMember.GetLabels()[v1etcd.IENVersionLabel]
148 return installedVersion == currentVersion
149 }
150
View as plain text