Skip to content

Commit a366c54

Browse files
authored
Render TiProxy labels into configmap (#6937) (#6943)
1 parent a0ed9f0 commit a366c54

9 files changed

Lines changed: 137 additions & 21 deletions

File tree

api/core/v1alpha1/tiproxy_types.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,8 @@ type TiProxyServer struct {
193193
Ports TiProxyPorts `json:"ports,omitempty"`
194194

195195
// Labels defines the server labels of the TiProxy server.
196-
// Operator will set these `labels` by API.
196+
// Operator will render these `labels` into the TiProxy config file.
197197
// If a label in this field is conflict with the config file, this field takes precedence.
198-
// NOTE: If a label is removed, operator will not delete it automatically.
199198
// NOTE: these label keys are managed by TiDB Operator, it will be set automatically and you can not modify them:
200199
// - host
201200
// - region

manifests/crd/core.pingcap.com_tiproxies.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8518,9 +8518,8 @@ spec:
85188518
type: string
85198519
description: |-
85208520
Labels defines the server labels of the TiProxy server.
8521-
Operator will set these `labels` by API.
8521+
Operator will render these `labels` into the TiProxy config file.
85228522
If a label in this field is conflict with the config file, this field takes precedence.
8523-
NOTE: If a label is removed, operator will not delete it automatically.
85248523
NOTE: these label keys are managed by TiDB Operator, it will be set automatically and you can not modify them:
85258524
- host
85268525
- region

manifests/crd/core.pingcap.com_tiproxygroups.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8806,9 +8806,8 @@ spec:
88068806
type: string
88078807
description: |-
88088808
Labels defines the server labels of the TiProxy server.
8809-
Operator will set these `labels` by API.
8809+
Operator will render these `labels` into the TiProxy config file.
88108810
If a label in this field is conflict with the config file, this field takes precedence.
8811-
NOTE: If a label is removed, operator will not delete it automatically.
88128811
NOTE: these label keys are managed by TiDB Operator, it will be set automatically and you can not modify them:
88138812
- host
88148813
- region

pkg/configs/tiproxy/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
2424
coreutil "github.com/pingcap/tidb-operator/v2/pkg/apiutil/core/v1alpha1"
2525
"github.com/pingcap/tidb-operator/v2/pkg/runtime/scope"
26+
maputil "github.com/pingcap/tidb-operator/v2/pkg/utils/map"
2627
stringutil "github.com/pingcap/tidb-operator/v2/pkg/utils/string"
2728
)
2829

@@ -74,6 +75,9 @@ func (c *Config) Overlay(cluster *v1alpha1.Cluster, tiproxy *v1alpha1.TiProxy) e
7475
c.Proxy.AdvertiseAddress = getAdvertiseAddress(cluster, tiproxy)
7576
c.Proxy.PDAddress = stringutil.RemoveHTTPPrefix(cluster.Status.PD)
7677
c.API.Address = coreutil.ListenAddress(coreutil.TiProxyAPIPort(tiproxy))
78+
if len(tiproxy.Spec.Server.Labels) > 0 {
79+
c.Labels = maputil.Merge(c.Labels, tiproxy.Spec.Server.Labels)
80+
}
7781

7882
if coreutil.IsTLSClusterEnabled(cluster) {
7983
c.Security.ClusterTLS.CA = path.Join(v1alpha1.DirPathClusterTLSTiProxy, corev1.ServiceAccountRootCAKey)

pkg/configs/tiproxy/config_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,46 @@ func TestOverlay(t *testing.T) {
284284
})
285285
}
286286
}
287+
288+
func TestOverlayLabels(t *testing.T) {
289+
cluster := &v1alpha1.Cluster{
290+
ObjectMeta: metav1.ObjectMeta{
291+
Namespace: "ns1",
292+
Name: "db",
293+
},
294+
Status: v1alpha1.ClusterStatus{
295+
PD: "http://db-pd.ns1:2379",
296+
},
297+
}
298+
tiproxy := &v1alpha1.TiProxy{
299+
ObjectMeta: metav1.ObjectMeta{
300+
Namespace: "ns1",
301+
Name: "db-foo",
302+
},
303+
Spec: v1alpha1.TiProxySpec{
304+
Subdomain: "db-tiproxy-peer",
305+
TiProxyTemplateSpec: v1alpha1.TiProxyTemplateSpec{
306+
Server: v1alpha1.TiProxyServer{
307+
Labels: map[string]string{
308+
"zone": "from-server-labels",
309+
"env": "prod",
310+
},
311+
},
312+
},
313+
},
314+
}
315+
316+
got := &Config{
317+
Labels: map[string]string{
318+
"rack": "rack-1",
319+
"zone": "from-config",
320+
},
321+
}
322+
err := got.Overlay(cluster, tiproxy)
323+
require.NoError(t, err)
324+
assert.Equal(t, map[string]string{
325+
"rack": "rack-1",
326+
"zone": "from-server-labels",
327+
"env": "prod",
328+
}, got.Labels)
329+
}

pkg/controllers/tiproxy/builder.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
package tiproxy
1616

1717
import (
18-
"context"
19-
2018
"github.com/pingcap/tidb-operator/v2/pkg/controllers/common"
2119
"github.com/pingcap/tidb-operator/v2/pkg/controllers/tiproxy/tasks"
2220
"github.com/pingcap/tidb-operator/v2/pkg/runtime/scope"
@@ -73,10 +71,6 @@ func (r *Reconciler) NewRunner(state *tasks.ReconcileContext, reporter task.Task
7371
tasks.TaskConfigMap(state, r.Client),
7472
common.TaskPVC[scope.TiProxy](state, r.Client, r.VolumeModifierFactory, tasks.PVCNewer()),
7573
tasks.TaskPod(state, r.Client),
76-
common.TaskServerLabels[scope.TiProxy](state, r.Client, r.PDClientManager, func(ctx context.Context, labels map[string]string) error {
77-
// TODO(liubo02): compare before setting
78-
return state.TiProxyClient.SetLabels(ctx, labels)
79-
}),
8074
common.TaskInstanceConditionSynced[scope.TiProxy](state),
8175
common.TaskInstanceConditionReady[scope.TiProxy](state),
8276
common.TaskInstanceConditionRunning[scope.TiProxy](state),

pkg/controllers/tiproxy/tasks/cm_test.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,22 @@ import (
2727

2828
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
2929
"github.com/pingcap/tidb-operator/v2/pkg/client"
30+
tiproxycfg "github.com/pingcap/tidb-operator/v2/pkg/configs/tiproxy"
3031
"github.com/pingcap/tidb-operator/v2/pkg/utils/fake"
3132
"github.com/pingcap/tidb-operator/v2/pkg/utils/task/v3"
33+
"github.com/pingcap/tidb-operator/v2/pkg/utils/toml"
3234
)
3335

3436
const fakePDAddr = "any string, useless in test"
3537

3638
func TestTaskConfigMap(t *testing.T) {
3739
cases := []struct {
38-
desc string
39-
state *ReconcileContext
40-
objs []client.Object
41-
unexpectedErr bool
42-
invalidConfig bool
40+
desc string
41+
state *ReconcileContext
42+
objs []client.Object
43+
unexpectedErr bool
44+
invalidConfig bool
45+
expectedLabels map[string]string
4346

4447
expectedStatus task.Status
4548
}{
@@ -88,6 +91,29 @@ func TestTaskConfigMap(t *testing.T) {
8891
},
8992
expectedStatus: task.SFail,
9093
},
94+
{
95+
desc: "server labels are rendered into config",
96+
state: &ReconcileContext{
97+
State: &state{
98+
tiproxy: fake.FakeObj("aaa-xxx", func(obj *v1alpha1.TiProxy) *v1alpha1.TiProxy {
99+
obj.Spec.Server.Labels = map[string]string{
100+
"env": "prod",
101+
"rack": "rack-1",
102+
}
103+
return obj
104+
}),
105+
cluster: fake.FakeObj("cluster", func(obj *v1alpha1.Cluster) *v1alpha1.Cluster {
106+
obj.Status.PD = fakePDAddr
107+
return obj
108+
}),
109+
},
110+
},
111+
expectedLabels: map[string]string{
112+
"env": "prod",
113+
"rack": "rack-1",
114+
},
115+
expectedStatus: task.SComplete,
116+
},
91117
{
92118
desc: "has config map",
93119
state: &ReconcileContext{
@@ -166,6 +192,12 @@ func TestTaskConfigMap(t *testing.T) {
166192
}
167193
require.NoError(tt, fc.Get(ctx, client.ObjectKeyFromObject(&cm), &cm), c.desc)
168194
assert.NotEmpty(tt, cm.Data, c.desc)
195+
if c.expectedLabels != nil {
196+
cfg := tiproxycfg.Config{}
197+
decoder, _ := toml.Codec[tiproxycfg.Config]()
198+
require.NoError(tt, decoder.Decode([]byte(cm.Data[v1alpha1.FileNameConfig]), &cfg), c.desc)
199+
assert.Equal(tt, c.expectedLabels, cfg.Labels, c.desc)
200+
}
169201
}
170202
})
171203
}

pkg/reloadable/tiproxy.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ func convertTiProxyTemplate(tmpl *v1alpha1.TiProxyTemplate) *v1alpha1.TiProxyTem
9999
newTmpl.Labels = convertLabels(newTmpl.Labels)
100100
newTmpl.Annotations = convertAnnotations(newTmpl.Annotations)
101101

102-
// server labels can be updated dynamically
103-
newTmpl.Spec.Server.Labels = nil
104-
105102
newTmpl.Spec.Volumes = convertVolumes(newTmpl.Spec.Volumes)
106103
newTmpl.Spec.Overlay = convertOverlay(newTmpl.Spec.Overlay)
107104

@@ -111,14 +108,17 @@ func convertTiProxyTemplate(tmpl *v1alpha1.TiProxyTemplate) *v1alpha1.TiProxyTem
111108
func equalTiProxyTemplate(c, p *v1alpha1.TiProxyTemplate) bool {
112109
p = convertTiProxyTemplate(p)
113110
c = convertTiProxyTemplate(c)
111+
serverLabelsChanged := !apiequality.Semantic.DeepEqual(p.Spec.Server.Labels, c.Spec.Server.Labels)
114112
// not equal only when current strategy is Restart and config is changed
115-
if c.Spec.UpdateStrategy.Config == v1alpha1.ConfigUpdateStrategyRestart && p.Spec.Config != c.Spec.Config {
113+
if c.Spec.UpdateStrategy.Config == v1alpha1.ConfigUpdateStrategyRestart && (p.Spec.Config != c.Spec.Config || serverLabelsChanged) {
116114
return false
117115
}
118116

119117
// ignore these fields
120118
p.Spec.Config = ""
121119
c.Spec.Config = ""
120+
p.Spec.Server.Labels = nil
121+
c.Spec.Server.Labels = nil
122122
p.Spec.UpdateStrategy.Config = ""
123123
c.Spec.UpdateStrategy.Config = ""
124124

pkg/reloadable/tiproxy_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"testing"
1919

2020
"github.com/stretchr/testify/assert"
21+
corev1 "k8s.io/api/core/v1"
2122
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2223

2324
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
@@ -62,3 +63,48 @@ func TestCheckTiProxy(t *testing.T) {
6263
})
6364
}
6465
}
66+
67+
func TestCheckTiProxyPodWhenServerLabelsChange(t *testing.T) {
68+
tests := []struct {
69+
name string
70+
strategy v1alpha1.ConfigUpdateStrategy
71+
wantCheck bool
72+
}{
73+
{
74+
name: "restart strategy",
75+
strategy: v1alpha1.ConfigUpdateStrategyRestart,
76+
wantCheck: false,
77+
},
78+
{
79+
name: "hot reload strategy",
80+
strategy: v1alpha1.ConfigUpdateStrategyHotReload,
81+
wantCheck: true,
82+
},
83+
}
84+
85+
for _, tt := range tests {
86+
t.Run(tt.name, func(t *testing.T) {
87+
previous := tiproxyWithServerLabels(tt.strategy, map[string]string{"zone": "z1"})
88+
current := tiproxyWithServerLabels(tt.strategy, map[string]string{"zone": "z2"})
89+
pod := &corev1.Pod{}
90+
MustEncodeLastTiProxyTemplate(previous, pod)
91+
92+
assert.Equal(t, tt.wantCheck, CheckTiProxyPod(current, pod))
93+
})
94+
}
95+
}
96+
97+
func tiproxyWithServerLabels(strategy v1alpha1.ConfigUpdateStrategy, labels map[string]string) *v1alpha1.TiProxy {
98+
return &v1alpha1.TiProxy{
99+
Spec: v1alpha1.TiProxySpec{
100+
TiProxyTemplateSpec: v1alpha1.TiProxyTemplateSpec{
101+
Server: v1alpha1.TiProxyServer{
102+
Labels: labels,
103+
},
104+
UpdateStrategy: v1alpha1.UpdateStrategy{
105+
Config: strategy,
106+
},
107+
},
108+
},
109+
}
110+
}

0 commit comments

Comments
 (0)