Skip to content

Commit 75dbdcf

Browse files
committed
add the new tests
On-behalf-of: @SAP [email protected]
1 parent 8513c2a commit 75dbdcf

File tree

2 files changed

+372
-0
lines changed

2 files changed

+372
-0
lines changed

test/crds/backup.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# sourced from https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
name: backups.eksempel.no
6+
spec:
7+
group: eksempel.no
8+
scope: Namespaced
9+
names:
10+
plural: backups
11+
singular: backup
12+
kind: Backup
13+
versions:
14+
- name: v1
15+
served: true
16+
storage: true
17+
schema:
18+
openAPIV3Schema:
19+
type: object
20+
properties:
21+
spec:
22+
type: object
23+
properties:
24+
source:
25+
type: string
26+
destination:
27+
type: string
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
//go:build e2e
2+
3+
/*
4+
Copyright 2025 The KCP Authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package apiexport
20+
21+
import (
22+
"context"
23+
"testing"
24+
"time"
25+
26+
"github.com/go-logr/logr"
27+
28+
syncagentv1alpha1 "github.com/kcp-dev/api-syncagent/sdk/apis/syncagent/v1alpha1"
29+
"github.com/kcp-dev/api-syncagent/test/utils"
30+
31+
kcpapisv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha1"
32+
33+
"k8s.io/apimachinery/pkg/api/equality"
34+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35+
"k8s.io/apimachinery/pkg/types"
36+
"k8s.io/apimachinery/pkg/util/wait"
37+
ctrlruntime "sigs.k8s.io/controller-runtime"
38+
ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
39+
)
40+
41+
func TestPermissionsClaims(t *testing.T) {
42+
const (
43+
apiExportName = "kcp.example.com"
44+
)
45+
46+
ctx := context.Background()
47+
ctrlruntime.SetLogger(logr.Discard())
48+
49+
// setup a test environment in kcp
50+
orgKubconfig := utils.CreateOrganization(t, ctx, "apiexport-no-pclaims-by-default", apiExportName)
51+
52+
// start a service cluster
53+
envtestKubeconfig, envtestClient, _ := utils.RunEnvtest(t, []string{
54+
"test/crds/crontab.yaml",
55+
"test/crds/backup.yaml",
56+
})
57+
58+
// publish Crontabs and Backups
59+
t.Logf("Publishing CRDs…")
60+
prCrontabs := &syncagentv1alpha1.PublishedResource{
61+
ObjectMeta: metav1.ObjectMeta{
62+
Name: "publish-crontabs",
63+
},
64+
Spec: syncagentv1alpha1.PublishedResourceSpec{
65+
Resource: syncagentv1alpha1.SourceResourceDescriptor{
66+
APIGroup: "example.com",
67+
Version: "v1",
68+
Kind: "CronTab",
69+
},
70+
},
71+
}
72+
73+
if err := envtestClient.Create(ctx, prCrontabs); err != nil {
74+
t.Fatalf("Failed to create PublishedResource: %v", err)
75+
}
76+
77+
prBackups := &syncagentv1alpha1.PublishedResource{
78+
ObjectMeta: metav1.ObjectMeta{
79+
Name: "publish-backups",
80+
},
81+
Spec: syncagentv1alpha1.PublishedResourceSpec{
82+
Resource: syncagentv1alpha1.SourceResourceDescriptor{
83+
APIGroup: "eksempel.no",
84+
Version: "v1",
85+
Kind: "Backup",
86+
},
87+
},
88+
}
89+
90+
if err := envtestClient.Create(ctx, prBackups); err != nil {
91+
t.Fatalf("Failed to create PublishedResource: %v", err)
92+
}
93+
94+
// let the agent do its thing
95+
utils.RunAgent(ctx, t, "bob", orgKubconfig, envtestKubeconfig, apiExportName)
96+
97+
// wait for the APIExport to be updated
98+
t.Logf("Waiting for APIExport to be updated…")
99+
orgClient := utils.GetClient(t, orgKubconfig)
100+
apiExportKey := types.NamespacedName{Name: apiExportName}
101+
102+
apiExport := &kcpapisv1alpha1.APIExport{}
103+
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (done bool, err error) {
104+
err = orgClient.Get(ctx, apiExportKey, apiExport)
105+
if err != nil {
106+
return false, err
107+
}
108+
109+
return len(apiExport.Spec.LatestResourceSchemas) == 2, nil
110+
})
111+
if err != nil {
112+
t.Fatalf("Failed to wait for APIExport to be updated: %v", err)
113+
}
114+
115+
if claims := apiExport.Spec.PermissionClaims; len(claims) > 0 {
116+
t.Fatalf("APIExport should have no permissions claims, but has %v", claims)
117+
}
118+
119+
// let's configure some related resources
120+
121+
// refresh the objects
122+
if err := envtestClient.Get(ctx, ctrlruntimeclient.ObjectKeyFromObject(prCrontabs), prCrontabs); err != nil {
123+
t.Fatalf("Failed to get PublishedResource: %v", err)
124+
}
125+
126+
if err := envtestClient.Get(ctx, ctrlruntimeclient.ObjectKeyFromObject(prBackups), prBackups); err != nil {
127+
t.Fatalf("Failed to get PublishedResource: %v", err)
128+
}
129+
130+
t.Logf("Configuring related resources…")
131+
prBackups.Spec.Related = []syncagentv1alpha1.RelatedResourceSpec{
132+
{
133+
Identifier: "super-secret",
134+
Origin: "kcp",
135+
Kind: "Secret",
136+
Reference: syncagentv1alpha1.RelatedResourceReference{
137+
Name: syncagentv1alpha1.ResourceLocator{
138+
Path: "spec.test.name",
139+
},
140+
Namespace: &syncagentv1alpha1.ResourceLocator{
141+
Path: "spec.test.namespace",
142+
},
143+
},
144+
},
145+
{
146+
Identifier: "other-super-secret",
147+
Origin: "service",
148+
Kind: "Secret",
149+
Reference: syncagentv1alpha1.RelatedResourceReference{
150+
Name: syncagentv1alpha1.ResourceLocator{
151+
Path: "spec.otherTest.name",
152+
},
153+
Namespace: &syncagentv1alpha1.ResourceLocator{
154+
Path: "spec.otherTest.namespace",
155+
},
156+
},
157+
},
158+
}
159+
160+
prCrontabs.Spec.Related = []syncagentv1alpha1.RelatedResourceSpec{
161+
{
162+
Identifier: "config",
163+
Origin: "kcp",
164+
Kind: "ConfigMap",
165+
Reference: syncagentv1alpha1.RelatedResourceReference{
166+
Name: syncagentv1alpha1.ResourceLocator{
167+
Path: "spec.secretTest.name",
168+
},
169+
Namespace: &syncagentv1alpha1.ResourceLocator{
170+
Path: "spec.secretTest.namespace",
171+
},
172+
},
173+
},
174+
}
175+
176+
if err := envtestClient.Update(ctx, prCrontabs); err != nil {
177+
t.Fatalf("Failed to update PublishedResource: %v", err)
178+
}
179+
180+
if err := envtestClient.Update(ctx, prBackups); err != nil {
181+
t.Fatalf("Failed to update PublishedResource: %v", err)
182+
}
183+
184+
// wait for the permission claims to be updated; note that since we have related resources at all,
185+
// the agent will also claim namespaces (since both ConfigMaps and Secrets are always namespaced).
186+
187+
t.Logf("Wait for the claims to be updated…")
188+
apiExport = &kcpapisv1alpha1.APIExport{}
189+
err = wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (done bool, err error) {
190+
err = orgClient.Get(ctx, apiExportKey, apiExport)
191+
if err != nil {
192+
return false, err
193+
}
194+
195+
return len(apiExport.Spec.PermissionClaims) == 3, nil
196+
})
197+
if err != nil {
198+
t.Fatalf("Failed to wait for APIExport to be updated: %v", err)
199+
}
200+
201+
expectedClaims := []kcpapisv1alpha1.PermissionClaim{
202+
{
203+
GroupResource: kcpapisv1alpha1.GroupResource{
204+
Group: "",
205+
Resource: "configmaps",
206+
},
207+
All: true,
208+
},
209+
{
210+
GroupResource: kcpapisv1alpha1.GroupResource{
211+
Group: "",
212+
Resource: "namespaces",
213+
},
214+
All: true,
215+
},
216+
{
217+
GroupResource: kcpapisv1alpha1.GroupResource{
218+
Group: "",
219+
Resource: "secrets",
220+
},
221+
All: true,
222+
},
223+
}
224+
225+
// Do not use cmp.Equal() because the Equal() func on PermissionClaims does not check all fields.
226+
if !equality.Semantic.DeepEqual(expectedClaims, apiExport.Spec.PermissionClaims) {
227+
t.Fatalf("Expected permission claims %+v, but got %+v.", expectedClaims, apiExport.Spec.PermissionClaims)
228+
}
229+
}
230+
231+
func TestExistingPermissionsClaimsAreKept(t *testing.T) {
232+
const (
233+
apiExportName = "kcp.example.com"
234+
)
235+
236+
ctx := context.Background()
237+
ctrlruntime.SetLogger(logr.Discard())
238+
239+
// setup a test environment in kcp
240+
orgKubconfig := utils.CreateOrganization(t, ctx, "apiexport-pclaims-are-kept", apiExportName)
241+
242+
// start a service cluster
243+
envtestKubeconfig, envtestClient, _ := utils.RunEnvtest(t, []string{
244+
"test/crds/crontab.yaml",
245+
})
246+
247+
// set a random claim that is supposed to survive
248+
orgClient := utils.GetClient(t, orgKubconfig)
249+
apiExportKey := types.NamespacedName{Name: apiExportName}
250+
251+
apiExport := &kcpapisv1alpha1.APIExport{}
252+
if err := orgClient.Get(ctx, apiExportKey, apiExport); err != nil {
253+
t.Fatalf("Failed to get APIExport: %v", err)
254+
}
255+
256+
apiExport.Spec.PermissionClaims = []kcpapisv1alpha1.PermissionClaim{
257+
{
258+
GroupResource: kcpapisv1alpha1.GroupResource{
259+
Group: "",
260+
Resource: "configmaps",
261+
},
262+
All: true,
263+
},
264+
}
265+
266+
if err := orgClient.Update(ctx, apiExport); err != nil {
267+
t.Fatalf("Failed to update APIExport: %v", err)
268+
}
269+
270+
// publish Crontabs
271+
t.Logf("Publishing CRD…")
272+
prCrontabs := &syncagentv1alpha1.PublishedResource{
273+
ObjectMeta: metav1.ObjectMeta{
274+
Name: "publish-crontabs",
275+
},
276+
Spec: syncagentv1alpha1.PublishedResourceSpec{
277+
Resource: syncagentv1alpha1.SourceResourceDescriptor{
278+
APIGroup: "example.com",
279+
Version: "v1",
280+
Kind: "CronTab",
281+
},
282+
Related: []syncagentv1alpha1.RelatedResourceSpec{
283+
{
284+
Identifier: "super-secret",
285+
Origin: "kcp",
286+
Kind: "Secret",
287+
Reference: syncagentv1alpha1.RelatedResourceReference{
288+
Name: syncagentv1alpha1.ResourceLocator{
289+
Path: "spec.test.name",
290+
},
291+
Namespace: &syncagentv1alpha1.ResourceLocator{
292+
Path: "spec.test.namespace",
293+
},
294+
},
295+
},
296+
},
297+
},
298+
}
299+
300+
if err := envtestClient.Create(ctx, prCrontabs); err != nil {
301+
t.Fatalf("Failed to create PublishedResource: %v", err)
302+
}
303+
304+
// let the agent do its thing
305+
utils.RunAgent(ctx, t, "bob", orgKubconfig, envtestKubeconfig, apiExportName)
306+
307+
// wait for the APIExport to be updated
308+
expectedClaims := []kcpapisv1alpha1.PermissionClaim{
309+
{
310+
GroupResource: kcpapisv1alpha1.GroupResource{
311+
Group: "",
312+
Resource: "configmaps",
313+
},
314+
All: true,
315+
},
316+
{
317+
GroupResource: kcpapisv1alpha1.GroupResource{
318+
Group: "",
319+
Resource: "namespaces",
320+
},
321+
All: true,
322+
},
323+
{
324+
GroupResource: kcpapisv1alpha1.GroupResource{
325+
Group: "",
326+
Resource: "secrets",
327+
},
328+
All: true,
329+
},
330+
}
331+
332+
t.Logf("Waiting for APIExport to be updated…")
333+
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (done bool, err error) {
334+
err = orgClient.Get(ctx, apiExportKey, apiExport)
335+
if err != nil {
336+
return false, err
337+
}
338+
339+
// Do not use cmp.Equal() because the Equal() func on PermissionClaims does not check all fields.
340+
return equality.Semantic.DeepEqual(expectedClaims, apiExport.Spec.PermissionClaims), nil
341+
})
342+
if err != nil {
343+
t.Fatalf("Failed to wait for APIExport to be updated: %v", err)
344+
}
345+
}

0 commit comments

Comments
 (0)