Skip to content

Commit

Permalink
extend CRD annotations test
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz-Smelcerz-SAP committed Nov 7, 2024
1 parent 5cb3779 commit 9b43572
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 21 deletions.
13 changes: 12 additions & 1 deletion internal/util/collections/filter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package collections

// filterInPlace is a function that filters a slice by a predicate function.
// FilterInPlace modifies a slice using provided predicate function.
// It returns a sub-slice of the input list that only contains the elements for which the predicate function returns true.
// Warning: This function modifies the input list!
func FilterInPlace[E any](list []*E, predicate func(*E) bool) []*E {
Expand All @@ -14,6 +14,17 @@ func FilterInPlace[E any](list []*E, predicate func(*E) bool) []*E {
return list[:last]
}

// Filter returns a new slice which results from applying the provided predicate to the input slice.
func Filter[E any](input []E, predicate func(E) bool) []E {
output := []E{}
for _, val := range input {
if predicate(val) {
output = append(output, val)
}
}
return output
}

// Dereference is a function that dereferences elements of a provided slice of pointers.
func Dereference[E any](list []*E) []E {
res := make([]E, len(list))
Expand Down
6 changes: 6 additions & 0 deletions pkg/testutils/builder/modulereleasemeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func (m ModuleReleaseMetaBuilder) WithName(name string) ModuleReleaseMetaBuilder
return m
}

func (m ModuleReleaseMetaBuilder) WithSingleModuleChannelAndVersions(channel, version string) ModuleReleaseMetaBuilder {
chanVer := v1beta2.ChannelVersionAssignment{Channel: channel, Version: version}
m.moduleReleaseMeta.Spec.Channels = append(m.moduleReleaseMeta.Spec.Channels, chanVer)
return m
}

func (m ModuleReleaseMetaBuilder) WithModuleChannelAndVersions(channelVersions []v1beta2.ChannelVersionAssignment) ModuleReleaseMetaBuilder {
m.moduleReleaseMeta.Spec.Channels = append(m.moduleReleaseMeta.Spec.Channels, channelVersions...)
return m
Expand Down
24 changes: 16 additions & 8 deletions tests/integration/controller/kcp/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,24 @@ func containsModuleTemplateCondition(clnt client.Client, kymaName, kymaNamespace
}

func updateKymaCRD(clnt client.Client) (*apiextensionsv1.CustomResourceDefinition, error) {
crd, err := fetchCrd(clnt, shared.KymaKind)
return updateCRDPropertyDescription(clnt, shared.KymaKind, "channel", "test change")
}

func updateModuleReleaseMetaCRD(clnt client.Client) (*apiextensionsv1.CustomResourceDefinition, error) {
return updateCRDPropertyDescription(clnt, shared.ModuleReleaseMetaKind, "channels", "test change")
}

func updateCRDPropertyDescription(clnt client.Client, crdKind shared.Kind, propertyName, newValue string) (*apiextensionsv1.CustomResourceDefinition, error) {
crd, err := fetchCrd(clnt, crdKind)
if err != nil {
return nil, err
}

crd.SetManagedFields(nil)
crdSpecVersions := crd.Spec.Versions
channelProperty := getCrdSpec(crd).Properties["channel"]
channelProperty.Description = "test change"
getCrdSpec(crd).Properties["channel"] = channelProperty
channelProperty := getCrdSpec(crd).Properties[propertyName]
channelProperty.Description = newValue
getCrdSpec(crd).Properties[propertyName] = channelProperty
crd.Spec = apiextensionsv1.CustomResourceDefinitionSpec{
Versions: crdSpecVersions,
Names: crd.Spec.Names,
Expand All @@ -199,13 +207,13 @@ func updateKymaCRD(clnt client.Client) (*apiextensionsv1.CustomResourceDefinitio
client.FieldOwner(shared.OperatorName)); err != nil {
return nil, err
}
crd, err = fetchCrd(clnt, shared.KymaKind)
kymaCrdName := fmt.Sprintf("%s.%s", shared.KymaKind.Plural(), v1beta2.GroupVersion.Group)
crd, err = fetchCrd(clnt, crdKind)
crdName := fmt.Sprintf("%s.%s", crdKind.Plural(), v1beta2.GroupVersion.Group)

// Replace the cached CRD after updating the KCP CRD to validate that
// the Generation values are updated correctly
if _, ok := crdCache.Get(kymaCrdName); ok {
crdCache.Add(kymaCrdName, *crd)
if _, ok := crdCache.Get(crdName); ok {
crdCache.Add(crdName, *crd)
}
if err != nil {
return nil, err
Expand Down
108 changes: 96 additions & 12 deletions tests/integration/controller/kcp/remote_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package kcp_test

import (
"errors"
"fmt"
"maps"
"slices"
"strconv"
"strings"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -13,6 +17,7 @@ import (
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/descriptor/cache"
"github.com/kyma-project/lifecycle-manager/internal/pkg/flags"
"github.com/kyma-project/lifecycle-manager/internal/util/collections"
"github.com/kyma-project/lifecycle-manager/pkg/testutils/builder"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -301,7 +306,12 @@ var _ = Describe("Kyma sync default module list into Remote Cluster", Ordered, f

var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered, func() {
kyma := NewTestKyma("kyma-test-crd-update")
moduleInKCP := NewTestModule("in-kcp", v1beta2.DefaultChannel)
moduleInKCP := NewTestModule("module-inkcp", v1beta2.DefaultChannel)
moduleReleaseMetaInKCP := builder.NewModuleReleaseMetaBuilder().
WithName("modulereleasemeta-inkcp").
WithModuleName("module-inkcp").
WithSingleModuleChannelAndVersions(v1beta2.DefaultChannel, "0.1.0").
Build()
kyma.Spec.Modules = []v1beta2.Module{{Name: moduleInKCP.Name, Channel: moduleInKCP.Channel}}
skrKyma := buildSkrKyma()
var skrClient client.Client
Expand All @@ -312,9 +322,15 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
skrClient, err = testSkrContextFactory.Get(kyma.GetNamespacedName())
return err
}, Timeout, Interval).Should(Succeed())

Eventually(CreateCR, Timeout, Interval).
WithContext(ctx).
WithArguments(kcpClient, moduleReleaseMetaInKCP).Should(Succeed())
})

annotations := []string{
injectedAnnotations := []string{
"modulereleasemeta-skr-crd-generation",
"modulereleasemeta-kcp-crd-generation",
"moduletemplate-skr-crd-generation",
"moduletemplate-kcp-crd-generation",
"kyma-skr-crd-generation",
Expand All @@ -328,9 +344,15 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
return err
}

for _, annotation := range annotations {
if _, ok := kcpKyma.Annotations[annotation]; !ok {
return ErrNotContainsExpectedAnnotation
relevantKymaAnnotations := collections.Filter(slices.Collect(maps.Keys(kcpKyma.Annotations)), func(val string) bool {
return strings.HasSuffix(val, "crd-generation")
})
if len(relevantKymaAnnotations) < len(injectedAnnotations) {
return fmt.Errorf("%w: expected: %d, actual: %d", ErrNotContainsExpectedAnnotation, len(injectedAnnotations), len(relevantKymaAnnotations))
}
for _, expectedAnnotation := range injectedAnnotations {
if _, ok := kcpKyma.Annotations[expectedAnnotation]; !ok {
return fmt.Errorf("%w: %s is missing", ErrNotContainsExpectedAnnotation, expectedAnnotation)
}
}

Expand All @@ -345,9 +367,9 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
return err
}

for _, annotation := range annotations {
if _, ok := skrKyma.Annotations[annotation]; ok {
return ErrContainsUnexpectedAnnotation
for _, unwantedAnnotation := range injectedAnnotations {
if _, ok := skrKyma.Annotations[unwantedAnnotation]; ok {
return fmt.Errorf("%w: %s is present but it should not", ErrContainsUnexpectedAnnotation, unwantedAnnotation)
}
}

Expand All @@ -358,6 +380,11 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
It("Kyma CRD should sync to SKR and annotations get updated", func() {
var kcpKymaCrd *apiextensionsv1.CustomResourceDefinition
var skrKymaCrd *apiextensionsv1.CustomResourceDefinition
var skrModuleTemplateCrd *apiextensionsv1.CustomResourceDefinition
var kcpModuleTemplateCrd *apiextensionsv1.CustomResourceDefinition
var skrModuleReleaseMetaCrd *apiextensionsv1.CustomResourceDefinition
var kcpModuleReleaseMetaCrd *apiextensionsv1.CustomResourceDefinition

By("Update KCP Kyma CRD")
Eventually(func() string {
var err error
Expand All @@ -380,18 +407,66 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
return skrKymaCrd.Spec.Versions[0].Schema
}, Timeout, Interval).Should(Equal(kcpKymaCrd.Spec.Versions[0].Schema))

By("Update ModuleReleaseMeta CRD")
Eventually(func() string {
var err error
kcpModuleReleaseMetaCrd, err = updateModuleReleaseMetaCRD(kcpClient)
if err != nil {
return ""
}

return getCrdSpec(kcpModuleReleaseMetaCrd).Properties["channels"].Description
}, Timeout, Interval).Should(Equal("test change"))

By("SKR ModuleReleaseMeta CRD should be updated")
Eventually(func() *apiextensionsv1.CustomResourceValidation {
var err error
skrModuleReleaseMetaCrd, err = fetchCrd(skrClient, shared.ModuleReleaseMetaKind)
if err != nil {
return nil
}

return skrModuleReleaseMetaCrd.Spec.Versions[0].Schema
}, Timeout, Interval).Should(Equal(kcpModuleReleaseMetaCrd.Spec.Versions[0].Schema))

By("Read ModuleTemplate CRDs")
Eventually(func() error {
var err error
skrModuleTemplateCrd, err = fetchCrd(skrClient, shared.ModuleTemplateKind)
if err != nil {
return err
}
kcpModuleTemplateCrd, err = fetchCrd(kcpClient, shared.ModuleTemplateKind)
if err != nil {
return err
}
return nil
}, Timeout, Interval).Should(Succeed())

By("Kyma CR generation annotations should be updated")
Eventually(func() error {
kcpKyma, err := GetKyma(ctx, kcpClient, kyma.GetName(), kyma.GetNamespace())
if err != nil {
return err
}

if kcpKyma.Annotations["kyma-skr-crd-generation"] != strconv.FormatInt(skrKymaCrd.Generation, 10) {
return ErrAnnotationNotUpdated
if err = assertCrdGenerationAnnotations(kcpKyma, "kyma-skr-crd-generation", skrKymaCrd); err != nil {
return err
}
if err = assertCrdGenerationAnnotations(kcpKyma, "kyma-kcp-crd-generation", kcpKymaCrd); err != nil {
return err
}
if err = assertCrdGenerationAnnotations(kcpKyma, "moduletemplate-skr-crd-generation", skrModuleTemplateCrd); err != nil {
return err
}
if kcpKyma.Annotations["kyma-kcp-crd-generation"] != strconv.FormatInt(kcpKymaCrd.Generation, 10) {
return ErrAnnotationNotUpdated
if err = assertCrdGenerationAnnotations(kcpKyma, "moduletemplate-kcp-crd-generation", kcpModuleTemplateCrd); err != nil {
return err
}
if err = assertCrdGenerationAnnotations(kcpKyma, "modulereleasemeta-skr-crd-generation", skrModuleReleaseMetaCrd); err != nil {
return err
}
if err = assertCrdGenerationAnnotations(kcpKyma, "modulereleasemeta-kcp-crd-generation", kcpModuleReleaseMetaCrd); err != nil {
return err
}

return nil
Expand Down Expand Up @@ -426,3 +501,12 @@ var _ = Describe("CRDs sync to SKR and annotations updated in KCP kyma", Ordered
}, Timeout, Interval).WithContext(ctx).Should(Not(HaveOccurred()))
})
})

func assertCrdGenerationAnnotations(kcpKyma *v1beta2.Kyma, annotationName string, targetCrd *apiextensionsv1.CustomResourceDefinition) error {
annotationValue := kcpKyma.Annotations[annotationName]
targetCrdGeneration := strconv.FormatInt(targetCrd.Generation, 10)
if annotationValue != targetCrdGeneration {
return fmt.Errorf("%w: expected: %s, actual: %s", ErrAnnotationNotUpdated, targetCrdGeneration, annotationValue)
}
return nil
}

0 comments on commit 9b43572

Please sign in to comment.