Skip to content

Commit 769a730

Browse files
stttsopenshift-cherrypick-robot
authored and
openshift-cherrypick-robot
committed
syncer: readd compatibility for v0.6.0 ns locators
1 parent a4992de commit 769a730

File tree

4 files changed

+209
-11
lines changed

4 files changed

+209
-11
lines changed

pkg/syncer/shared/namespace.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ type NamespaceLocator struct {
4141
}
4242

4343
type SyncTargetLocator struct {
44-
Workspace logicalcluster.Name `json:"workspace"`
45-
Name string `json:"name"`
46-
UID types.UID `json:"uid"`
44+
Workspace string `json:"workspace,omitempty"`
45+
DeprecatedPath string `json:"path,omitempty"`
46+
Name string `json:"name"`
47+
UID types.UID `json:"uid"`
4748
}
4849

4950
func NewNamespaceLocator(workspace, syncTargetWorkspace logicalcluster.Name, syncTargetUID types.UID, workloadLogicalClusterName, upstreamNamespace string) NamespaceLocator {
5051
return NamespaceLocator{
5152
SyncTarget: SyncTargetLocator{
52-
Workspace: syncTargetWorkspace,
53+
Workspace: syncTargetWorkspace.String(),
5354
Name: workloadLogicalClusterName,
5455
UID: syncTargetUID,
5556
},
@@ -58,6 +59,18 @@ func NewNamespaceLocator(workspace, syncTargetWorkspace logicalcluster.Name, syn
5859
}
5960
}
6061

62+
func NewNamespaceLocatorV060(workspace, syncTargetWorkspace logicalcluster.Name, syncTargetUID types.UID, workloadLogicalClusterName, upstreamNamespace string) NamespaceLocator {
63+
return NamespaceLocator{
64+
SyncTarget: SyncTargetLocator{
65+
DeprecatedPath: syncTargetWorkspace.String(),
66+
Name: workloadLogicalClusterName,
67+
UID: syncTargetUID,
68+
},
69+
Workspace: workspace,
70+
Namespace: upstreamNamespace,
71+
}
72+
}
73+
6174
func LocatorFromAnnotations(annotations map[string]string) (*NamespaceLocator, bool, error) {
6275
annotation, ok := annotations[NamespaceLocatorAnnotation]
6376
if !ok {
@@ -67,6 +80,13 @@ func LocatorFromAnnotations(annotations map[string]string) (*NamespaceLocator, b
6780
if err := json.Unmarshal([]byte(annotation), &locator); err != nil {
6881
return nil, false, err
6982
}
83+
84+
// get us from v0.6.0 locators (using syncTarget.path) to v0.6.1+ (using syncTarget.workspace)
85+
if locator.SyncTarget.Workspace == "" {
86+
locator.SyncTarget.Workspace = locator.SyncTarget.DeprecatedPath
87+
}
88+
locator.SyncTarget.DeprecatedPath = ""
89+
7090
return &locator, true, nil
7191
}
7292

pkg/syncer/shared/namespace_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
Copyright 2022 The KCP Authors.
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+
17+
package shared
18+
19+
import (
20+
"reflect"
21+
"strings"
22+
"testing"
23+
24+
"github.com/kcp-dev/logicalcluster"
25+
)
26+
27+
func TestLocatorFromAnnotations(t *testing.T) {
28+
tests := []struct {
29+
name string
30+
annotations map[string]string
31+
want *NamespaceLocator
32+
wantFound bool
33+
wantErrs []string
34+
}{
35+
{
36+
name: "no annotation",
37+
wantFound: false,
38+
},
39+
{
40+
name: "garbage",
41+
annotations: map[string]string{
42+
NamespaceLocatorAnnotation: "garbage",
43+
},
44+
wantErrs: []string{"invalid character"},
45+
},
46+
{
47+
name: "happy case",
48+
annotations: map[string]string{
49+
NamespaceLocatorAnnotation: `{"syncTarget":{"workspace":"test-workspace","name":"test-name","uid":"test-uid"},"workspace":"test-workspace","namespace":"test-namespace"}`,
50+
},
51+
want: &NamespaceLocator{
52+
SyncTarget: SyncTargetLocator{
53+
Workspace: "test-workspace",
54+
Name: "test-name",
55+
UID: "test-uid",
56+
},
57+
Workspace: logicalcluster.New("test-workspace"),
58+
Namespace: "test-namespace",
59+
},
60+
wantFound: true,
61+
},
62+
{
63+
name: "format up to v0.6.0",
64+
annotations: map[string]string{
65+
NamespaceLocatorAnnotation: `{"syncTarget":{"path":"test-workspace","name":"test-name","uid":"test-uid"},"workspace":"test-workspace","namespace":"test-namespace"}`,
66+
},
67+
want: &NamespaceLocator{
68+
SyncTarget: SyncTargetLocator{
69+
Workspace: "test-workspace",
70+
Name: "test-name",
71+
UID: "test-uid",
72+
},
73+
Workspace: logicalcluster.New("test-workspace"),
74+
Namespace: "test-namespace",
75+
},
76+
wantFound: true,
77+
},
78+
}
79+
for _, tt := range tests {
80+
t.Run(tt.name, func(t *testing.T) {
81+
got, gotFound, err := LocatorFromAnnotations(tt.annotations)
82+
if (err != nil) != (len(tt.wantErrs) > 0) {
83+
t.Errorf("LocatorFromAnnotations() error = %q, wantErrs %v", err.Error(), tt.wantErrs)
84+
return
85+
} else if err != nil {
86+
for _, wantErr := range tt.wantErrs {
87+
if !strings.Contains(err.Error(), wantErr) {
88+
t.Errorf("LocatorFromAnnotations() error = %q, wantErrs %q", err.Error(), wantErr)
89+
return
90+
}
91+
}
92+
}
93+
if !reflect.DeepEqual(got, tt.want) {
94+
t.Errorf("LocatorFromAnnotations() got = %v, want %v", got, tt.want)
95+
}
96+
if gotFound != tt.wantFound {
97+
t.Errorf("LocatorFromAnnotations() gotFound = %v, want %v", gotFound, tt.wantFound)
98+
}
99+
})
100+
}
101+
}

pkg/syncer/spec/spec_process.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,30 @@ func (c *Controller) process(ctx context.Context, gvr schema.GroupVersionResourc
114114
}
115115
clusterName, name := clusters.SplitClusterAwareKey(clusterAwareName)
116116

117+
namespaceGvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}
118+
117119
desiredNSLocator := shared.NewNamespaceLocator(clusterName, c.syncTargetClusterName, c.syncTargetUID, c.syncTargetName, upstreamNamespace)
118120
jsonNSLocator, err := json.Marshal(desiredNSLocator)
119121
if err != nil {
120122
return err
121123
}
122-
123-
namespaceGvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}
124124
downstreamNamespaces, err := c.downstreamInformers.ForResource(namespaceGvr).Informer().GetIndexer().ByIndex(byNamespaceLocatorIndexName, string(jsonNSLocator))
125125
if err != nil {
126126
return err
127127
}
128+
if len(downstreamNamespaces) == 0 {
129+
// case for up to v0.6.0 where we used syncTarget.path in namespace locators
130+
desiredNSLocator := shared.NewNamespaceLocatorV060(clusterName, c.syncTargetClusterName, c.syncTargetUID, c.syncTargetName, upstreamNamespace)
131+
jsonNSLocator, err := json.Marshal(desiredNSLocator)
132+
if err != nil {
133+
return err
134+
}
135+
downstreamNamespaces, err = c.downstreamInformers.ForResource(namespaceGvr).Informer().GetIndexer().ByIndex(byNamespaceLocatorIndexName, string(jsonNSLocator))
136+
if err != nil {
137+
return err
138+
}
139+
}
140+
128141
var downstreamNamespace string
129142

130143
if len(downstreamNamespaces) == 1 {

pkg/syncer/spec/spec_process_test.go

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,51 @@ func TestSyncerProcess(t *testing.T) {
926926
expectActionsOnFrom: []clienttesting.Action{},
927927
expectActionsOnTo: []clienttesting.Action{},
928928
},
929+
"old v0.6.0 namespace locator exists downstream": {
930+
upstreamLogicalCluster: "root:org:ws",
931+
fromNamespace: namespace("test", "root:org:ws", map[string]string{
932+
"state.workload.kcp.dev/us-west1": "Sync",
933+
}, nil),
934+
gvr: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"},
935+
toResources: []runtime.Object{
936+
namespace("kcp-0123456789", "", map[string]string{
937+
"state.workload.kcp.dev/us-west1": "Sync",
938+
},
939+
map[string]string{
940+
"kcp.dev/namespace-locator": `{"syncTarget":{"path":"root:org:ws","name":"us-west1","uid":"syncTargetUID"},"workspace":"root:org:ws","namespace":"test"}`,
941+
}),
942+
secret("foo", "test", "root:org:ws",
943+
map[string]string{"state.workload.kcp.dev/us-west1": "Sync"},
944+
nil,
945+
map[string][]byte{
946+
"a": []byte("b"),
947+
}),
948+
},
949+
fromResources: []runtime.Object{
950+
secretWithFinalizers("foo", "test", "root:org:ws",
951+
map[string]string{
952+
"state.workload.kcp.dev/us-west1": "Sync",
953+
"something": "else"},
954+
nil,
955+
[]string{"workload.kcp.dev/syncer-us-west1"},
956+
map[string][]byte{
957+
"a": []byte("b"),
958+
}),
959+
},
960+
resourceToProcessLogicalClusterName: "root:org:ws",
961+
resourceToProcessName: "foo",
962+
syncTargetName: "us-west1",
963+
964+
expectActionsOnFrom: []clienttesting.Action{},
965+
expectActionsOnTo: []clienttesting.Action{
966+
patchSecretAction(
967+
"foo",
968+
"kcp-0123456789",
969+
types.ApplyPatchType,
970+
[]byte(`{"apiVersion":"v1","data":{"a":"Yg=="},"kind":"Secret","metadata":{"creationTimestamp":null,"labels":{"internal.workload.kcp.dev/cluster":"us-west1","something":"else"},"name":"foo","namespace":"kcp-0123456789"},"type":"kubernetes.io/service-account-token"}`),
971+
),
972+
},
973+
},
929974
}
930975

931976
for name, tc := range tests {
@@ -987,11 +1032,7 @@ func TestSyncerProcess(t *testing.T) {
9871032

9881033
key := tc.fromNamespace.Name + "/" + clusters.ToClusterAwareKey(logicalcluster.New(tc.resourceToProcessLogicalClusterName), tc.resourceToProcessName)
9891034
err = controller.process(context.Background(),
990-
schema.GroupVersionResource{
991-
Group: "apps",
992-
Version: "v1",
993-
Resource: "deployments",
994-
},
1035+
tc.gvr,
9951036
key,
9961037
)
9971038
if tc.expectError {
@@ -1055,13 +1096,18 @@ func deployment(name, namespace, clusterName string, labels, annotations map[str
10551096
}
10561097

10571098
func secret(name, namespace, clusterName string, labels, annotations map[string]string, data map[string][]byte) *corev1.Secret {
1099+
return secretWithFinalizers(name, namespace, clusterName, labels, annotations, nil, data)
1100+
}
1101+
1102+
func secretWithFinalizers(name, namespace, clusterName string, labels, annotations map[string]string, finalizers []string, data map[string][]byte) *corev1.Secret {
10581103
return &corev1.Secret{
10591104
ObjectMeta: metav1.ObjectMeta{
10601105
Name: name,
10611106
Namespace: namespace,
10621107
ClusterName: clusterName,
10631108
Labels: labels,
10641109
Annotations: annotations,
1110+
Finalizers: finalizers,
10651111
},
10661112
Data: data,
10671113
StringData: nil,
@@ -1196,3 +1242,21 @@ func deleteDeploymentAction(name, namespace string, subresources ...string) clie
11961242
DeleteOptions: metav1.DeleteOptions{},
11971243
}
11981244
}
1245+
1246+
func secretAction(verb, namespace string, subresources ...string) clienttesting.ActionImpl {
1247+
return clienttesting.ActionImpl{
1248+
Namespace: namespace,
1249+
Verb: verb,
1250+
Resource: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"},
1251+
Subresource: strings.Join(subresources, "/"),
1252+
}
1253+
}
1254+
1255+
func patchSecretAction(name, namespace string, patchType types.PatchType, patch []byte, subresources ...string) clienttesting.PatchActionImpl {
1256+
return clienttesting.PatchActionImpl{
1257+
ActionImpl: secretAction("patch", namespace, subresources...),
1258+
Name: name,
1259+
PatchType: patchType,
1260+
Patch: patch,
1261+
}
1262+
}

0 commit comments

Comments
 (0)