Skip to content

Commit 012a496

Browse files
authored
K8SPSMDB-1365: delete services after disabling expose (#1906)
* K8SPSMDB-1365: delete services after disabling expose https://perconadev.atlassian.net/browse/K8SPSMDB-1365 * delete unused lines * fix * update go ver for tests * this will fix the test * fix init-deploy
1 parent be033fb commit 012a496

File tree

11 files changed

+587
-21
lines changed

11 files changed

+587
-21
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
steps:
88
- uses: actions/setup-go@v5
99
with:
10-
go-version: '^1.23'
10+
go-version: '^1.24'
1111
- uses: actions/checkout@v4.1.1
1212
- name: run tests
1313
run: make test

e2e-tests/init-deploy/compare/backup-80.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@
133133
"update"
134134
]
135135
},
136+
{
137+
"resource": {
138+
"db": "",
139+
"collection": "system.views"
140+
},
141+
"actions": [
142+
"dropCollection"
143+
]
144+
},
136145
{
137146
"resource": {
138147
"db": "admin",
@@ -243,15 +252,6 @@
243252
"updateSearchIndex"
244253
]
245254
},
246-
{
247-
"resource": {
248-
"db": "admin",
249-
"collection": "system.views"
250-
},
251-
"actions": [
252-
"dropCollection"
253-
]
254-
},
255255
{
256256
"resource": {
257257
"db": "admin",

e2e-tests/init-deploy/run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ test_dir=$(realpath $(dirname $0))
66
. ${test_dir}/../functions
77
set_debug
88

9-
max_conn=16
9+
max_conn=17
1010

1111
create_infra $namespace
1212

pkg/controller/perconaservermongodb/connections_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ func TestConnectionLeaks(t *testing.T) {
118118

119119
obj := []client.Object{}
120120
obj = append(obj, cr,
121-
fakeStatefulset(cr, cr.Spec.Replsets[0], cr.Spec.Replsets[0].Size, updatedRevision),
122-
fakeStatefulset(cr, &api.ReplsetSpec{Name: "deleted-sts"}, 0, ""),
121+
fakeStatefulset(cr, cr.Spec.Replsets[0], cr.Spec.Replsets[0].Size, updatedRevision, ""),
122+
fakeStatefulset(cr, &api.ReplsetSpec{Name: "deleted-sts"}, 0, "", ""),
123123
)
124124

125125
rsPods := fakePodsForRS(cr, cr.Spec.Replsets[0])
@@ -136,7 +136,7 @@ func TestConnectionLeaks(t *testing.T) {
136136
if err := cr.CheckNSetDefaults(ctx, version.PlatformKubernetes); err != nil {
137137
t.Fatal(err)
138138
}
139-
obj = append(obj, fakeStatefulset(cr, cr.Spec.Sharding.ConfigsvrReplSet, cr.Spec.Sharding.ConfigsvrReplSet.Size, updatedRevision))
139+
obj = append(obj, fakeStatefulset(cr, cr.Spec.Sharding.ConfigsvrReplSet, cr.Spec.Sharding.ConfigsvrReplSet.Size, updatedRevision, ""))
140140
allPods = append(allPods, fakePodsForRS(cr, cr.Spec.Sharding.ConfigsvrReplSet)...)
141141
}
142142

@@ -344,12 +344,14 @@ func fakePod(name, namespace string, ls map[string]string, containerName string)
344344
}
345345
}
346346

347-
func fakeStatefulset(cr *api.PerconaServerMongoDB, rs *api.ReplsetSpec, size int32, updateRevision string) client.Object {
347+
func fakeStatefulset(cr *api.PerconaServerMongoDB, rs *api.ReplsetSpec, size int32, updateRevision string, component string) client.Object {
348+
ls := naming.RSLabels(cr, rs)
349+
ls[naming.LabelKubernetesComponent] = component
348350
return &appsv1.StatefulSet{
349351
ObjectMeta: metav1.ObjectMeta{
350352
Name: fmt.Sprintf("%s-%s", cr.Name, rs.Name),
351353
Namespace: cr.Namespace,
352-
Labels: naming.RSLabels(cr, rs),
354+
Labels: ls,
353355
},
354356
Spec: appsv1.StatefulSetSpec{
355357
Replicas: &size,

pkg/controller/perconaservermongodb/finalizers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestCheckFinalizers(t *testing.T) {
2424

2525
obj := append(
2626
fakePodsForRS(defaultCR, defaultCR.Spec.Replsets[0]),
27-
fakeStatefulset(defaultCR, defaultCR.Spec.Replsets[0], defaultCR.Spec.Replsets[0].Size, ""),
27+
fakeStatefulset(defaultCR, defaultCR.Spec.Replsets[0], defaultCR.Spec.Replsets[0].Size, "", ""),
2828
)
2929

3030
tests := []struct {

pkg/controller/perconaservermongodb/service.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func (r *ReconcilePerconaServerMongoDB) reconcileReplsetServices(ctx context.Con
3737
if err := r.createOrUpdateSvc(ctx, cr, service, true); err != nil {
3838
return errors.Wrapf(err, "create or update service for replset %s", rs.Name)
3939
}
40+
if err := r.removeOutdatedServices(ctx, cr, rs); err != nil {
41+
return errors.Wrapf(err, "failed to remove old services of replset %s", rs.Name)
42+
}
4043
if !rs.Expose.Enabled {
4144
continue
4245
}
@@ -48,10 +51,6 @@ func (r *ReconcilePerconaServerMongoDB) reconcileReplsetServices(ctx context.Con
4851
if err := r.ensureExternalServices(ctx, cr, rs, &pods); err != nil {
4952
return errors.Wrap(err, "ensure external services")
5053
}
51-
52-
if err := r.removeOutdatedServices(ctx, cr, rs); err != nil {
53-
return errors.Wrapf(err, "failed to remove old services of replset %s", rs.Name)
54-
}
5554
}
5655
return nil
5756
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package perconaservermongodb
2+
3+
import (
4+
"bytes"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
corev1 "k8s.io/api/core/v1"
10+
"sigs.k8s.io/controller-runtime/pkg/client"
11+
"sigs.k8s.io/yaml"
12+
13+
api "github.com/percona/percona-server-mongodb-operator/pkg/apis/psmdb/v1"
14+
"github.com/percona/percona-server-mongodb-operator/pkg/naming"
15+
)
16+
17+
func TestReconcileReplsetServices(t *testing.T) {
18+
ctx := t.Context()
19+
const ns = "rs-svc"
20+
const crName = ns
21+
22+
getReplsets := func(t *testing.T, cr *api.PerconaServerMongoDB) []*api.ReplsetSpec {
23+
t.Helper()
24+
25+
cr = cr.DeepCopy()
26+
repls := cr.Spec.Replsets
27+
if cr.Spec.Sharding.Enabled && cr.Spec.Sharding.ConfigsvrReplSet != nil {
28+
repls = append([]*api.ReplsetSpec{cr.Spec.Sharding.ConfigsvrReplSet}, repls...)
29+
}
30+
return repls
31+
}
32+
33+
compareSvcList := func(t *testing.T, cl client.Client, cr *api.PerconaServerMongoDB, filename string) {
34+
t.Helper()
35+
36+
svcList := new(corev1.ServiceList)
37+
if err := cl.List(ctx, svcList, client.InNamespace(cr.Namespace)); err != nil {
38+
t.Fatal(err)
39+
}
40+
41+
yamlCompare(t, ns, filename, svcList)
42+
}
43+
44+
prepareObjects := func(t *testing.T, cr *api.PerconaServerMongoDB) []client.Object {
45+
t.Helper()
46+
47+
repls := getReplsets(t, cr)
48+
49+
objs := []client.Object{cr}
50+
for _, rs := range repls {
51+
component := naming.ComponentMongod
52+
if rs.ClusterRole == api.ClusterRoleConfigSvr {
53+
component = api.ConfigReplSetName
54+
}
55+
objs = append(objs, fakeStatefulset(cr, rs, rs.Size, "", component))
56+
objs = append(objs, fakePodsForRS(cr, rs)...)
57+
}
58+
return objs
59+
}
60+
61+
t.Run("expose toggle: not sharded cluster", func(t *testing.T) {
62+
cr, err := readDefaultCR(crName, ns)
63+
if err != nil {
64+
t.Fatal(err)
65+
}
66+
cr.Spec.Replsets[0].Expose.Enabled = false
67+
cr.Spec.Sharding.Enabled = false
68+
if err := cr.CheckNSetDefaults(ctx, ""); err != nil {
69+
t.Fatal(err)
70+
}
71+
r := buildFakeClient(prepareObjects(t, cr)...)
72+
73+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
74+
t.Fatal(err)
75+
}
76+
compareSvcList(t, r.client, cr, "svc_list_expose_off.yaml")
77+
78+
cr.Spec.Replsets[0].Expose.Enabled = true
79+
if err := r.client.Update(ctx, cr); err != nil {
80+
t.Fatal(err)
81+
}
82+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
83+
t.Fatal(err)
84+
}
85+
compareSvcList(t, r.client, cr, "svc_list_expose_on.yaml")
86+
87+
cr.Spec.Replsets[0].Expose.Enabled = false
88+
if err := r.client.Update(ctx, cr); err != nil {
89+
t.Fatal(err)
90+
}
91+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
92+
t.Fatal(err)
93+
}
94+
compareSvcList(t, r.client, cr, "svc_list_expose_off.yaml")
95+
})
96+
97+
t.Run("expose toggle: sharded cluster", func(t *testing.T) {
98+
cr, err := readDefaultCR(crName, ns)
99+
if err != nil {
100+
t.Fatal(err)
101+
}
102+
cr.Spec.Replsets[0].Expose.Enabled = false
103+
cr.Spec.Sharding.Enabled = true
104+
if err := cr.CheckNSetDefaults(ctx, ""); err != nil {
105+
t.Fatal(err)
106+
}
107+
108+
r := buildFakeClient(prepareObjects(t, cr)...)
109+
110+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
111+
t.Fatal(err)
112+
}
113+
compareSvcList(t, r.client, cr, "svc_list_sharded_expose_off.yaml")
114+
115+
cr.Spec.Replsets[0].Expose.Enabled = true
116+
if err := r.client.Update(ctx, cr); err != nil {
117+
t.Fatal(err)
118+
}
119+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
120+
t.Fatal(err)
121+
}
122+
compareSvcList(t, r.client, cr, "svc_list_sharded_expose_on.yaml")
123+
124+
cr.Spec.Replsets[0].Expose.Enabled = false
125+
if err := r.client.Update(ctx, cr); err != nil {
126+
t.Fatal(err)
127+
}
128+
if err := r.reconcileReplsetServices(ctx, cr, getReplsets(t, cr)); err != nil {
129+
t.Fatal(err)
130+
}
131+
compareSvcList(t, r.client, cr, "svc_list_sharded_expose_off.yaml")
132+
})
133+
}
134+
135+
func yamlCompare(t *testing.T, ns string, filename string, compare any) {
136+
t.Helper()
137+
138+
data, err := yaml.Marshal(compare)
139+
if err != nil {
140+
t.Fatal(err)
141+
}
142+
expected, err := os.ReadFile(filepath.Join("testdata", ns, filename))
143+
if err != nil {
144+
t.Fatal(err)
145+
}
146+
if !bytes.Equal(bytes.TrimSpace(data), bytes.TrimSpace(expected)) {
147+
t.Fatalf("yaml resources doesn't match:\nexpected:\n%s\ngot:\n%s", string(expected), string(data))
148+
}
149+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
items:
2+
- apiVersion: v1
3+
kind: Service
4+
metadata:
5+
annotations:
6+
percona.com/last-config-hash: eyJwb3J0cyI6W3sibmFtZSI6Im1vbmdvZGIiLCJwb3J0IjoyNzAxNywidGFyZ2V0UG9ydCI6MjcwMTd9XSwic2VsZWN0b3IiOnsiYXBwLmt1YmVybmV0ZXMuaW8vaW5zdGFuY2UiOiJycy1zdmMiLCJhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5IjoicGVyY29uYS1zZXJ2ZXItbW9uZ29kYi1vcGVyYXRvciIsImFwcC5rdWJlcm5ldGVzLmlvL25hbWUiOiJwZXJjb25hLXNlcnZlci1tb25nb2RiIiwiYXBwLmt1YmVybmV0ZXMuaW8vcGFydC1vZiI6InBlcmNvbmEtc2VydmVyLW1vbmdvZGIiLCJhcHAua3ViZXJuZXRlcy5pby9yZXBsc2V0IjoicnMwIn0sImNsdXN0ZXJJUCI6Ik5vbmUifQ==
7+
creationTimestamp: null
8+
labels:
9+
app.kubernetes.io/instance: rs-svc
10+
app.kubernetes.io/managed-by: percona-server-mongodb-operator
11+
app.kubernetes.io/name: percona-server-mongodb
12+
app.kubernetes.io/part-of: percona-server-mongodb
13+
app.kubernetes.io/replset: rs0
14+
name: rs-svc-rs0
15+
namespace: rs-svc
16+
ownerReferences:
17+
- apiVersion: psmdb.percona.com/v1
18+
controller: true
19+
kind: PerconaServerMongoDB
20+
name: rs-svc
21+
uid: ""
22+
resourceVersion: "1"
23+
spec:
24+
clusterIP: None
25+
ports:
26+
- name: mongodb
27+
port: 27017
28+
targetPort: 27017
29+
selector:
30+
app.kubernetes.io/instance: rs-svc
31+
app.kubernetes.io/managed-by: percona-server-mongodb-operator
32+
app.kubernetes.io/name: percona-server-mongodb
33+
app.kubernetes.io/part-of: percona-server-mongodb
34+
app.kubernetes.io/replset: rs0
35+
status:
36+
loadBalancer: {}
37+
metadata: {}

0 commit comments

Comments
 (0)