forked from Altinity/clickhouse-operator
/
labeler.go
233 lines (206 loc) · 7.35 KB
/
labeler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Copyright 2019 Altinity Ltd and/or its affiliates. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package chi
import (
"context"
"errors"
"fmt"
v13 "k8s.io/api/apps/v1"
v12 "k8s.io/api/core/v1"
log "github.com/squids-io/clickhouse-operator/pkg/announcer"
chiv1 "github.com/squids-io/clickhouse-operator/pkg/apis/clickhouse.altinity.com/v1"
"github.com/squids-io/clickhouse-operator/pkg/chop"
"github.com/squids-io/clickhouse-operator/pkg/model"
"github.com/squids-io/clickhouse-operator/pkg/util"
)
func (c *Controller) labelMyObjectsTree(ctx context.Context) error {
// Operator is running in the Pod. We need to label this Pod
// Pod is owned by ReplicaSet. We need to label this ReplicaSet also.
// ReplicaSet is owned by Deployment. We need to label this Deployment also.
// Deployment is not owned by any entity so far.
//
// Excerpt from Pod's yaml
// metadata:
// ownerReferences:
// - apiVersion: apps/v1
// blockOwnerDeletion: true
// controller: true
// kind: ReplicaSet
// name: clickhouse-operator-79bf98f9b8
// uid: a276f30c-83ae-11e9-b92d-0208b778ea1a
//
// Excerpt from ReplicaSet's yaml
// metadata:
// ownerReferences:
// - apiVersion: apps/v1
// blockOwnerDeletion: true
// controller: true
// kind: Deployment
// name: clickhouse-operator
// uid: a275a8a0-83ae-11e9-b92d-0208b778ea1a
if util.IsContextDone(ctx) {
log.V(2).Info("ctx is done")
return nil
}
// What pod does operator run in?
name, ok1 := chop.Get().ConfigManager.GetRuntimeParam(chiv1.OPERATOR_POD_NAME)
namespace, ok2 := chop.Get().ConfigManager.GetRuntimeParam(chiv1.OPERATOR_POD_NAMESPACE)
if !ok1 || !ok2 {
str := fmt.Sprintf("ERROR read env vars: %s/%s ", chiv1.OPERATOR_POD_NAME, chiv1.OPERATOR_POD_NAMESPACE)
log.V(1).M(namespace, name).A().Error(str)
return errors.New(str)
}
// Put labels on the pod
pod, err := c.labelPod(ctx, namespace, name)
if err != nil {
return err
}
if pod == nil {
return fmt.Errorf("ERROR label pod %s/%s", namespace, name)
}
// Put labels on the ReplicaSet
replicaSet, err := c.labelReplicaSet(ctx, pod)
if err != nil {
return err
}
if replicaSet == nil {
return fmt.Errorf("ERROR label ReplicaSet for pod %s/%s", pod.Namespace, pod.Name)
}
// Put labels on the Deployment
err = c.labelDeployment(ctx, replicaSet)
if err != nil {
return err
}
return nil
}
func (c *Controller) labelPod(ctx context.Context, namespace, name string) (*v12.Pod, error) {
pod, err := c.kubeClient.CoreV1().Pods(namespace).Get(ctx, name, newGetOptions())
if err != nil {
log.V(1).M(namespace, name).A().Error("ERROR get Pod %s/%s %v", namespace, name, err)
return nil, err
}
if pod == nil {
str := fmt.Sprintf("ERROR get Pod is nil %s/%s ", namespace, name)
log.V(1).M(namespace, name).A().Error(str)
return nil, errors.New(str)
}
// Put label on the Pod
pod.Labels = c.addLabels(pod.Labels)
pod, err = c.kubeClient.CoreV1().Pods(namespace).Update(ctx, pod, newUpdateOptions())
if err != nil {
log.V(1).M(namespace, name).A().Error("ERROR put label on Pod %s/%s %v", namespace, name, err)
return nil, err
}
if pod == nil {
str := fmt.Sprintf("ERROR update Pod is nil %s/%s ", namespace, name)
log.V(1).M(namespace, name).A().Error(str)
return nil, errors.New(str)
}
return pod, nil
}
func (c *Controller) labelReplicaSet(ctx context.Context, pod *v12.Pod) (*v13.ReplicaSet, error) {
// Find parent ReplicaSet
replicaSetName := ""
for i := range pod.OwnerReferences {
owner := &pod.OwnerReferences[i]
if owner.Kind == "ReplicaSet" {
// ReplicaSet found
replicaSetName = owner.Name
break
}
}
if replicaSetName == "" {
// ReplicaSet not found
str := fmt.Sprintf("ERROR ReplicaSet for Pod %s/%s not found", pod.Namespace, pod.Name)
log.V(1).M(pod.Namespace, pod.Name).A().Error(str)
return nil, errors.New(str)
}
// ReplicaSet namespaced name found, fetch the ReplicaSet
replicaSet, err := c.kubeClient.AppsV1().ReplicaSets(pod.Namespace).Get(ctx, replicaSetName, newGetOptions())
if err != nil {
log.V(1).M(pod.Namespace, replicaSetName).A().Error("ERROR get ReplicaSet %s/%s %v", pod.Namespace, replicaSetName, err)
return nil, err
}
if replicaSet == nil {
str := fmt.Sprintf("ERROR get ReplicaSet is nil %s/%s ", pod.Namespace, replicaSetName)
log.V(1).M(pod.Namespace, replicaSetName).A().Error(str)
return nil, errors.New(str)
}
// Put label on the ReplicaSet
replicaSet.Labels = c.addLabels(replicaSet.Labels)
replicaSet, err = c.kubeClient.AppsV1().ReplicaSets(pod.Namespace).Update(ctx, replicaSet, newUpdateOptions())
if err != nil {
log.V(1).M(pod.Namespace, replicaSetName).A().Error("ERROR put label on ReplicaSet %s/%s %v", pod.Namespace, replicaSetName, err)
return nil, err
}
if replicaSet == nil {
str := fmt.Sprintf("ERROR update ReplicaSet is nil %s/%s ", pod.Namespace, replicaSetName)
log.V(1).M(pod.Namespace, replicaSetName).A().Error(str)
return nil, errors.New(str)
}
return replicaSet, nil
}
func (c *Controller) labelDeployment(ctx context.Context, rs *v13.ReplicaSet) error {
// Find parent Deployment
deploymentName := ""
for i := range rs.OwnerReferences {
owner := &rs.OwnerReferences[i]
if owner.Kind == "Deployment" {
// Deployment found
deploymentName = owner.Name
break
}
}
if deploymentName == "" {
// Deployment not found
str := fmt.Sprintf("ERROR find Deployment for ReplicaSet %s/%s not found", rs.Namespace, rs.Name)
log.V(1).M(rs.Namespace, rs.Name).A().Error(str)
return errors.New(str)
}
// Deployment namespaced name found, fetch the Deployment
deployment, err := c.kubeClient.AppsV1().Deployments(rs.Namespace).Get(ctx, deploymentName, newGetOptions())
if err != nil {
log.V(1).M(rs.Namespace, deploymentName).A().Error("ERROR get Deployment %s/%s", rs.Namespace, deploymentName)
return err
}
if deployment == nil {
str := fmt.Sprintf("ERROR get Deployment is nil %s/%s ", rs.Namespace, deploymentName)
log.V(1).M(rs.Namespace, deploymentName).A().Error(str)
return errors.New(str)
}
// Put label on the Deployment
deployment.Labels = c.addLabels(deployment.Labels)
deployment, err = c.kubeClient.AppsV1().Deployments(rs.Namespace).Update(ctx, deployment, newUpdateOptions())
if err != nil {
log.V(1).M(rs.Namespace, deploymentName).A().Error("ERROR put label on Deployment %s/%s %v", rs.Namespace, deploymentName, err)
return err
}
if deployment == nil {
str := fmt.Sprintf("ERROR update Deployment is nil %s/%s ", rs.Namespace, deploymentName)
log.V(1).M(rs.Namespace, deploymentName).A().Error(str)
return errors.New(str)
}
return nil
}
// addLabels adds app and version labels
func (c *Controller) addLabels(labels map[string]string) map[string]string {
return util.MergeStringMapsOverwrite(
labels,
// Add the following labels
map[string]string{
model.LabelAppName: model.LabelAppValue,
model.LabelCHOP: chop.Get().Version,
},
)
}