Skip to content

Commit

Permalink
Update integrationtests
Browse files Browse the repository at this point in the history
  • Loading branch information
Mario Manno committed Nov 27, 2023
1 parent db7bff2 commit 11b7007
Show file tree
Hide file tree
Showing 3 changed files with 393 additions and 177 deletions.
270 changes: 225 additions & 45 deletions integrationtests/agent/bundle_deployment_status_test.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
package agent

import (
"context"
"os"

"github.com/rancher/fleet/integrationtests/utils"
"github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func orphanBundeResources() map[string][]v1alpha1.BundleResource {
v1, err := os.ReadFile(assetsPath + "/deployment-v1.yaml")
Expect(err).NotTo(HaveOccurred())
v2, err := os.ReadFile(assetsPath + "/deployment-v2.yaml")
Expect(err).NotTo(HaveOccurred())

return map[string][]v1alpha1.BundleResource{
"v1": {
{
Name: "deployment-v1.yaml",
Content: string(v1),
Encoding: "",
},
}, "v2": {
{
Name: "deployment-v2.yaml",
Content: string(v2),
Encoding: "",
},
func init() {
v1, _ := os.ReadFile(assetsPath + "/deployment-v1.yaml")
v2, _ := os.ReadFile(assetsPath + "/deployment-v2.yaml")

resources["v1"] = []v1alpha1.BundleResource{
{
Name: "deployment-v1.yaml",
Content: string(v1),
Encoding: "",
},
}
resources["v2"] = []v1alpha1.BundleResource{
{
Name: "deployment-v2.yaml",
Content: string(v2),
Encoding: "",
},
}
}
Expand All @@ -45,48 +45,216 @@ var _ = Describe("BundleDeployment status", Ordered, func() {
)

var (
env *specEnv
namespace string
name string
env *specEnv
)

createBundleDeploymentV1 := func(name string) {
bundled := v1alpha1.BundleDeployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Namespace: clusterNS,
},
Spec: v1alpha1.BundleDeploymentSpec{
DeploymentID: "v1",
Options: v1alpha1.BundleDeploymentOptions{
DefaultNamespace: namespace,
},
},
}

b, err := env.controller.Create(&bundled)
err := k8sClient.Create(context.TODO(), &bundled)
Expect(err).To(BeNil())
Expect(b).To(Not(BeNil()))
Expect(bundled).To(Not(BeNil()))
}

BeforeAll(func() {
env = specEnvs["orphanbundle"]
name = "orphanbundle"
namespace = env.namespace
DeferCleanup(func() {
Expect(k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}})).ToNot(HaveOccurred())
})
})
createNamespace := func() string {
namespace, err := utils.NewNamespaceName()
Expect(err).ToNot(HaveOccurred())

ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
Expect(k8sClient.Create(context.Background(), ns)).ToNot(HaveOccurred())

return namespace
}

When("New bundle deployment is created", func() {
BeforeAll(func() {
name = "orphanbundletest1"
namespace = createNamespace()
DeferCleanup(func() {
Expect(k8sClient.Delete(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: namespace}})).ToNot(HaveOccurred())
})
env = &specEnv{namespace: namespace}

// this BundleDeployment will create a deployment with the resources from assets/deployment-v1.yaml
createBundleDeploymentV1(name)
DeferCleanup(func() {
Expect(k8sClient.Delete(context.TODO(), &v1alpha1.BundleDeployment{
ObjectMeta: metav1.ObjectMeta{Namespace: clusterNS, Name: name},
})).ToNot(HaveOccurred())
})
})

It("BundleDeployment is not ready", func() {
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).NotTo(HaveOccurred())
Expect(bd.Status.Ready).To(BeFalse())
})

It("BundleDeployment will eventually be ready and non modified", func() {
Eventually(env.isBundleDeploymentReadyAndNotModified).WithArguments(name).Should(BeTrue())
})

It("Resources from BundleDeployment are present in the cluster", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
Expect(svc.Name).NotTo(BeEmpty())
})

It("Lists deployed resources in the status", func() {
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).NotTo(HaveOccurred())
Expect(bd.Status.Resources).To(HaveLen(3))
ts := bd.Status.Resources[0].CreatedAt
Expect(ts.Time).ToNot(BeZero())
Expect(bd.Status.Resources).To(ContainElement(v1alpha1.BundleDeploymentResource{
Kind: "Service",
APIVersion: "v1",
Namespace: namespace,
Name: "svc-test",
CreatedAt: ts,
}))
})

Context("A release resource is modified", func() {
It("Modify service", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
patch := svc.DeepCopy()
patch.Spec.Selector = map[string]string{"foo": "bar"}
Expect(k8sClient.Patch(ctx, patch, client.MergeFrom(&svc))).NotTo(HaveOccurred())
})

It("BundleDeployment status will not be Ready, and will contain the error message", func() {
Eventually(func() bool {
modifiedStatus := v1alpha1.ModifiedStatus{
Kind: "Service",
APIVersion: "v1",
Namespace: namespace,
Name: "svc-test",
Create: false,
Delete: false,
Patch: "{\"spec\":{\"selector\":{\"app.kubernetes.io/name\":\"MyApp\"}}}",
}
return env.isNotReadyAndModified(name, modifiedStatus, "service.v1 "+namespace+"/svc-test modified {\"spec\":{\"selector\":{\"app.kubernetes.io/name\":\"MyApp\"}}}")
}).Should(BeTrue(), "BundleDeployment status does not contain modified message")
})

It("Modify service to have its original value", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
patch := svc.DeepCopy()
patch.Spec.Selector = map[string]string{"app.kubernetes.io/name": "MyApp"}
Expect(k8sClient.Patch(ctx, patch, client.MergeFrom(&svc))).To(BeNil())
})

It("BundleDeployment will eventually be ready and non modified", func() {
Eventually(env.isBundleDeploymentReadyAndNotModified).WithArguments(name).Should(BeTrue())
})
})

AfterAll(func() {
Expect(env.controller.Delete(namespace, name, nil)).NotTo(HaveOccurred())
Context("Upgrading to a release that will leave an orphan resource", func() {
It("Upgrade BundleDeployment to a release that deletes the svc with a finalizer", func() {
Eventually(func() bool {
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).To(BeNil())
bd.Spec.DeploymentID = "v2"
err = k8sClient.Update(ctx, bd)
return err == nil && bd != nil
}).Should(BeTrue())

})

It("BundleDeployment status will eventually be extra", func() {
Eventually(func() bool {
modifiedStatus := v1alpha1.ModifiedStatus{
Kind: "Service",
APIVersion: "v1",
Namespace: namespace,
Name: "svc-finalizer",
Create: false,
Delete: true,
Patch: "",
}
return env.isNotReadyAndModified(name, modifiedStatus, "service.v1 "+namespace+"/svc-finalizer extra")
}).Should(BeTrue())
})

It("Remove finalizer", func() {
svc, err := env.getService(svcFinalizerName)
Expect(err).NotTo(HaveOccurred())
patch := svc.DeepCopy()
patch.Finalizers = nil
Expect(k8sClient.Patch(ctx, patch, client.MergeFrom(&svc))).To(BeNil())
})

It("BundleDeployment will eventually be ready and non modified", func() {
Eventually(env.isBundleDeploymentReadyAndNotModified).WithArguments(name).Should(BeTrue())
})
})

Context("Delete a resource in the release", func() {
It("Delete service", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
err = k8sClient.Delete(ctx, &svc)
Expect(err).NotTo(HaveOccurred())
})

It("BundleDeployment status will eventually be missing", func() {
Eventually(func() bool {
modifiedStatus := v1alpha1.ModifiedStatus{
Kind: "Service",
APIVersion: "v1",
Namespace: namespace,
Name: "svc-test",
Create: true,
Delete: false,
Patch: "",
}
return env.isNotReadyAndModified(name, modifiedStatus, "service.v1 "+namespace+"/svc-test missing")
}).Should(BeTrue())
})
})
})

When("Simulating how another operator creates a dynamic resource", func() {
BeforeAll(func() {
namespace = createNamespace()
DeferCleanup(func() {
Expect(k8sClient.Delete(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: namespace}})).ToNot(HaveOccurred())
})
env = &specEnv{namespace: namespace}

name = "orphanbundletest2"
createBundleDeploymentV1(name)
DeferCleanup(func() {
Expect(k8sClient.Delete(context.TODO(), &v1alpha1.BundleDeployment{
ObjectMeta: metav1.ObjectMeta{Namespace: clusterNS, Name: name},
})).ToNot(HaveOccurred())
})
})

It("BundleDeployment is not ready", func() {
bd, err := env.controller.Get(namespace, name, metav1.GetOptions{})
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).NotTo(HaveOccurred())
Expect(bd.Status.Ready).To(BeFalse())
})
Expand All @@ -98,11 +266,12 @@ var _ = Describe("BundleDeployment status", Ordered, func() {
It("Resources from BundleDeployment are present in the cluster", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
Expect(svc).To(Not(BeNil()))
Expect(svc.Name).NotTo(BeEmpty())
})

It("Lists deployed resources in the status", func() {
bd, err := env.controller.Get(namespace, name, metav1.GetOptions{})
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).NotTo(HaveOccurred())
Expect(bd.Status.Resources).To(HaveLen(3))
ts := bd.Status.Resources[0].CreatedAt
Expand Down Expand Up @@ -137,7 +306,7 @@ var _ = Describe("BundleDeployment status", Ordered, func() {
Patch: "{\"spec\":{\"selector\":{\"app.kubernetes.io/name\":\"MyApp\"}}}",
}
return env.isNotReadyAndModified(name, modifiedStatus, "service.v1 "+namespace+"/svc-test modified {\"spec\":{\"selector\":{\"app.kubernetes.io/name\":\"MyApp\"}}}")
}).Should(BeTrue())
}).Should(BeTrue(), "BundleDeployment status does not contain modified message")
})

It("Modify service to have its original value", func() {
Expand All @@ -156,11 +325,12 @@ var _ = Describe("BundleDeployment status", Ordered, func() {
Context("Upgrading to a release that will leave an orphan resource", func() {
It("Upgrade BundleDeployment to a release that deletes the svc with a finalizer", func() {
Eventually(func() bool {
bd, err := env.controller.Get(namespace, name, metav1.GetOptions{})
bd := &v1alpha1.BundleDeployment{}
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: clusterNS, Name: name}, bd)
Expect(err).To(BeNil())
bd.Spec.DeploymentID = "v2"
b, err := env.controller.Update(bd)
return err == nil && b != nil
err = k8sClient.Update(ctx, bd)
return err == nil && bd != nil
}).Should(BeTrue())

})
Expand Down Expand Up @@ -220,7 +390,21 @@ var _ = Describe("BundleDeployment status", Ordered, func() {

When("Simulating how another operator creates a dynamic resource", func() {
BeforeAll(func() {
namespace = createNamespace()
DeferCleanup(func() {
Expect(k8sClient.Delete(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: namespace}})).ToNot(HaveOccurred())
})
env = &specEnv{namespace: namespace}

name = "orphanbundletest2"
createBundleDeploymentV1(name)
DeferCleanup(func() {
Expect(k8sClient.Delete(context.TODO(), &v1alpha1.BundleDeployment{
ObjectMeta: metav1.ObjectMeta{Namespace: clusterNS, Name: name},
})).ToNot(HaveOccurred())
})

// It is possible that some operators copy the objectset.rio.cattle.io/hash label into a dynamically created objects.
// https://github.com/rancher/fleet/issues/1141
By("Simulating orphan resource creation", func() {
Expand All @@ -242,18 +426,14 @@ var _ = Describe("BundleDeployment status", Ordered, func() {
})
})

AfterAll(func() {
Expect(env.controller.Delete(namespace, name, nil)).NotTo(HaveOccurred())
})

It("BundleDeployment will eventually be ready and non modified", func() {
Eventually(env.isBundleDeploymentReadyAndNotModified).WithArguments(name).Should(BeTrue())
})

It("Resources from BundleDeployment are present in the cluster", func() {
svc, err := env.getService(svcName)
Expect(err).NotTo(HaveOccurred())
Expect(svc).To(Not(BeNil()))
Expect(svc.Name).NotTo(BeEmpty())
})
})
})
Loading

0 comments on commit 11b7007

Please sign in to comment.