Skip to content

Commit b6f2abb

Browse files
committed
add new tests for the apiresourceschema controller
On-behalf-of: @SAP [email protected]
1 parent 242e2e6 commit b6f2abb

File tree

3 files changed

+211
-0
lines changed

3 files changed

+211
-0
lines changed

Diff for: test/e2e/apiresourceschema/apiresourceschema_test.go

+166
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,169 @@ func TestARSAreCreated(t *testing.T) {
106106
t.Fatalf("APIResourceSchema does not exist: %v", err)
107107
}
108108
}
109+
110+
func TestARSAreNotUpdated(t *testing.T) {
111+
const (
112+
apiExportName = "example.com"
113+
)
114+
115+
ctx := context.Background()
116+
ctrlruntime.SetLogger(logr.Discard())
117+
118+
// setup a test environment in kcp
119+
orgKubconfig := utils.CreateOrganization(t, ctx, "ars-are-not-updated", apiExportName)
120+
121+
// start a service cluster
122+
envtestKubeconfig, envtestClient, _ := utils.RunEnvtest(t, []string{
123+
"test/crds/crontab.yaml",
124+
})
125+
126+
// publish Crontabs
127+
t.Logf("Publishing CronTabs…")
128+
pr := &syncagentv1alpha1.PublishedResource{
129+
ObjectMeta: metav1.ObjectMeta{
130+
Name: "publish-crontabs",
131+
},
132+
Spec: syncagentv1alpha1.PublishedResourceSpec{
133+
Resource: syncagentv1alpha1.SourceResourceDescriptor{
134+
APIGroup: "example.com",
135+
Version: "v1",
136+
Kind: "CronTab",
137+
},
138+
},
139+
}
140+
141+
if err := envtestClient.Create(ctx, pr); err != nil {
142+
t.Fatalf("Failed to create PublishedResource: %v", err)
143+
}
144+
145+
// let the agent do its thing
146+
utils.RunAgent(ctx, t, "bob", orgKubconfig, envtestKubeconfig, apiExportName)
147+
148+
// wait for the APIExport to be updated
149+
t.Logf("Waiting for APIExport to be updated…")
150+
orgClient := utils.GetClient(t, orgKubconfig)
151+
apiExportKey := types.NamespacedName{Name: apiExportName}
152+
153+
var arsName string
154+
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (done bool, err error) {
155+
apiExport := &kcpapisv1alpha1.APIExport{}
156+
err = orgClient.Get(ctx, apiExportKey, apiExport)
157+
if err != nil {
158+
return false, err
159+
}
160+
161+
if len(apiExport.Spec.LatestResourceSchemas) == 0 {
162+
return false, nil
163+
}
164+
165+
arsName = apiExport.Spec.LatestResourceSchemas[0]
166+
167+
return true, nil
168+
})
169+
if err != nil {
170+
t.Fatalf("Failed to wait for APIExport to be updated: %v", err)
171+
}
172+
173+
// update the CRD
174+
t.Logf("Updating CRD (same version, but new schema)…")
175+
utils.ApplyCRD(t, ctx, envtestClient, "test/crds/crontab-improved.yaml")
176+
177+
// give the agent some time to do nothing
178+
time.Sleep(3 * time.Second)
179+
180+
// validate that the APIExport has *not* changed
181+
apiExport := &kcpapisv1alpha1.APIExport{}
182+
err = orgClient.Get(ctx, apiExportKey, apiExport)
183+
if err != nil {
184+
t.Fatalf("APIExport disappeared: %v", err)
185+
}
186+
187+
if l := len(apiExport.Spec.LatestResourceSchemas); l != 1 {
188+
t.Fatalf("APIExport should still have 1 resource schema, but has %d.", l)
189+
}
190+
191+
if currentName := apiExport.Spec.LatestResourceSchemas[0]; currentName != arsName {
192+
t.Fatalf("APIExport should still refer to the original ARS %q, but now contains %q.", arsName, currentName)
193+
}
194+
}
195+
196+
func TestARSDropsAllVersionsExceptTheSelectedOne(t *testing.T) {
197+
const (
198+
apiExportName = "example.com"
199+
theVersion = "v1"
200+
)
201+
202+
ctx := context.Background()
203+
ctrlruntime.SetLogger(logr.Discard())
204+
205+
// setup a test environment in kcp
206+
orgKubconfig := utils.CreateOrganization(t, ctx, "ars-drops-crd-versions", apiExportName)
207+
208+
// start a service cluster
209+
envtestKubeconfig, envtestClient, _ := utils.RunEnvtest(t, []string{
210+
"test/crds/crontab-multi-versions.yaml",
211+
})
212+
213+
// publish Crontabs
214+
t.Logf("Publishing CronTabs…")
215+
pr := &syncagentv1alpha1.PublishedResource{
216+
ObjectMeta: metav1.ObjectMeta{
217+
Name: "publish-crontabs",
218+
},
219+
Spec: syncagentv1alpha1.PublishedResourceSpec{
220+
Resource: syncagentv1alpha1.SourceResourceDescriptor{
221+
APIGroup: "example.com",
222+
Version: theVersion,
223+
Kind: "CronTab",
224+
},
225+
},
226+
}
227+
228+
if err := envtestClient.Create(ctx, pr); err != nil {
229+
t.Fatalf("Failed to create PublishedResource: %v", err)
230+
}
231+
232+
// let the agent do its thing
233+
utils.RunAgent(ctx, t, "bob", orgKubconfig, envtestKubeconfig, apiExportName)
234+
235+
// wait for the APIExport to be updated
236+
t.Logf("Waiting for APIExport to be updated…")
237+
orgClient := utils.GetClient(t, orgKubconfig)
238+
apiExportKey := types.NamespacedName{Name: apiExportName}
239+
240+
var arsName string
241+
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (done bool, err error) {
242+
apiExport := &kcpapisv1alpha1.APIExport{}
243+
err = orgClient.Get(ctx, apiExportKey, apiExport)
244+
if err != nil {
245+
return false, err
246+
}
247+
248+
if len(apiExport.Spec.LatestResourceSchemas) == 0 {
249+
return false, nil
250+
}
251+
252+
arsName = apiExport.Spec.LatestResourceSchemas[0]
253+
254+
return true, nil
255+
})
256+
if err != nil {
257+
t.Fatalf("Failed to wait for APIExport to be updated: %v", err)
258+
}
259+
260+
// check the APIResourceSchema
261+
ars := &kcpapisv1alpha1.APIResourceSchema{}
262+
err = orgClient.Get(ctx, types.NamespacedName{Name: arsName}, ars)
263+
if err != nil {
264+
t.Fatalf("APIResourceSchema does not exist: %v", err)
265+
}
266+
267+
if len(ars.Spec.Versions) != 1 {
268+
t.Fatalf("Expected only one version to remain in ARS, but found %d.", len(ars.Spec.Versions))
269+
}
270+
271+
if name := ars.Spec.Versions[0].Name; name != theVersion {
272+
t.Fatalf("Expected ARS to contain %q, but contains %q.", theVersion, name)
273+
}
274+
}

Diff for: test/utils/fixtures.go

+43
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package utils
1919
import (
2020
"context"
2121
"fmt"
22+
"os"
23+
"path/filepath"
2224
"strings"
2325
"testing"
2426
"time"
@@ -32,8 +34,10 @@ import (
3234
"github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions"
3335

3436
rbacv1 "k8s.io/api/rbac/v1"
37+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3538
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3639
"k8s.io/apimachinery/pkg/util/wait"
40+
"k8s.io/apimachinery/pkg/util/yaml"
3741
ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
3842
"sigs.k8s.io/controller-runtime/pkg/kontext"
3943
)
@@ -301,3 +305,42 @@ func BindToAPIExport(t *testing.T, ctx context.Context, client ctrlruntimeclient
301305

302306
return apiBinding
303307
}
308+
309+
func ApplyCRD(t *testing.T, ctx context.Context, client ctrlruntimeclient.Client, filename string) {
310+
t.Helper()
311+
312+
crd := loadCRD(t, filename)
313+
314+
existingCRD := &apiextensionsv1.CustomResourceDefinition{}
315+
if err := client.Get(ctx, ctrlruntimeclient.ObjectKeyFromObject(crd), existingCRD); err != nil {
316+
if err := client.Create(ctx, crd); err != nil {
317+
t.Fatalf("Failed to create CRD: %v", err)
318+
}
319+
} else {
320+
existingCRD.Spec = crd.Spec
321+
322+
if err := client.Update(ctx, existingCRD); err != nil {
323+
t.Fatalf("Failed to update CRD: %v", err)
324+
}
325+
}
326+
}
327+
328+
func loadCRD(t *testing.T, filename string) *apiextensionsv1.CustomResourceDefinition {
329+
t.Helper()
330+
331+
rootDirectory := requiredEnv(t, "ROOT_DIRECTORY")
332+
333+
f, err := os.Open(filepath.Join(rootDirectory, filename))
334+
if err != nil {
335+
t.Fatalf("Failed to read CRD: %v", err)
336+
}
337+
defer f.Close()
338+
339+
crd := &apiextensionsv1.CustomResourceDefinition{}
340+
dec := yaml.NewYAMLOrJSONDecoder(f, 1024)
341+
if err := dec.Decode(crd); err != nil {
342+
t.Fatalf("Failed to decode CRD: %v", err)
343+
}
344+
345+
return crd
346+
}

Diff for: test/utils/utils.go

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
corev1 "k8s.io/api/core/v1"
3232
rbacv1 "k8s.io/api/rbac/v1"
33+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3334
"k8s.io/apimachinery/pkg/runtime"
3435
"k8s.io/client-go/scale/scheme"
3536
"k8s.io/client-go/tools/clientcmd"
@@ -60,6 +61,7 @@ func newScheme(t *testing.T) *runtime.Scheme {
6061
must(t, kcptenancyv1alpha1.AddToScheme(sc))
6162
must(t, kcpapisv1alpha1.AddToScheme(sc))
6263
must(t, syncagentv1alpha1.AddToScheme(sc))
64+
must(t, apiextensionsv1.AddToScheme(sc))
6365

6466
return sc
6567
}

0 commit comments

Comments
 (0)