diff --git a/apptests/appscenarios/externaldns.go b/apptests/appscenarios/externaldns.go new file mode 100644 index 000000000..f75c9e9ea --- /dev/null +++ b/apptests/appscenarios/externaldns.go @@ -0,0 +1,81 @@ +package appscenarios + +import ( + "context" + "path/filepath" + + "github.com/mesosphere/kommander-applications/apptests/constants" + "github.com/mesosphere/kommander-applications/apptests/environment" +) + +type externalDns struct{} + +func (r externalDns) Name() string { + return constants.ExternalDns +} + +var _ AppScenario = (*reloader)(nil) + +func (r externalDns) Install(ctx context.Context, env *environment.Env) error { + appPath, err := absolutePathTo(r.Name()) + if err != nil { + return err + } + + err = r.install(ctx, env, appPath) + if err != nil { + return err + } + + return err +} + +func (r externalDns) InstallPreviousVersion(ctx context.Context, env *environment.Env) error { + appPath, err := getkAppsUpgradePath(r.Name()) + if err != nil { + return err + } + + err = r.install(ctx, env, appPath) + if err != nil { + return err + } + + return nil +} + +func (r externalDns) Upgrade(ctx context.Context, env *environment.Env) error { + appPath, err := absolutePathTo(r.Name()) + if err != nil { + return err + } + + err = r.install(ctx, env, appPath) + if err != nil { + return err + } + + return err +} + +func (r externalDns) install(ctx context.Context, env *environment.Env, appPath string) error { + // apply defaults configmaps first + defaultKustomization := filepath.Join(appPath, "/defaults") + err := env.ApplyKustomizations(ctx, defaultKustomization, map[string]string{ + "releaseNamespace": kommanderNamespace, + }) + if err != nil { + return err + } + + // apply the kustomization for the helmrelease + releasePath := filepath.Join(appPath, "/") + err = env.ApplyKustomizations(ctx, releasePath, map[string]string{ + "releaseNamespace": kommanderNamespace, + }) + if err != nil { + return err + } + + return err +} diff --git a/apptests/appscenarios/externaldns_test.go b/apptests/appscenarios/externaldns_test.go new file mode 100644 index 000000000..35c33e45f --- /dev/null +++ b/apptests/appscenarios/externaldns_test.go @@ -0,0 +1,252 @@ +package appscenarios + +import ( + "fmt" + corev1 "k8s.io/api/core/v1" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + fluxhelmv2beta2 "github.com/fluxcd/helm-controller/api/v2beta2" + apimeta "github.com/fluxcd/pkg/apis/meta" + appsv1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrlClient "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("External DNS Tests", Label("external-dns"), func() { + BeforeEach(OncePerOrdered, func() { + err := SetupKindCluster() + Expect(err).To(BeNil()) + + err = env.InstallLatestFlux(ctx) + Expect(err).To(BeNil()) + + err = env.ApplyKommanderBaseKustomizations(ctx) + Expect(err).To(BeNil()) + }) + + AfterEach(OncePerOrdered, func() { + err := env.Destroy(ctx) + Expect(err).ToNot(HaveOccurred()) + }) + + Describe("Installing external-dns", Ordered, Label("install"), func() { + + var ( + ed externalDns + hr *fluxhelmv2beta2.HelmRelease + deploymentList *appsv1.DeploymentList + ) + + It("should install successfully with default config", func() { + ed = externalDns{} + err := ed.Install(ctx, env) + Expect(err).To(BeNil()) + + hr = &fluxhelmv2beta2.HelmRelease{ + TypeMeta: metav1.TypeMeta{ + Kind: fluxhelmv2beta2.HelmReleaseKind, + APIVersion: fluxhelmv2beta2.GroupVersion.Version, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: ed.Name(), + Namespace: kommanderNamespace, + }, + } + + // Check the status of the HelmReleases + Eventually(func() error { + err = k8sClient.Get(ctx, ctrlClient.ObjectKeyFromObject(hr), hr) + if err != nil { + return err + } + + for _, cond := range hr.Status.Conditions { + if cond.Status == metav1.ConditionTrue && + cond.Type == apimeta.ReadyCondition { + return nil + } + } + return fmt.Errorf("helm release not ready yet") + }).WithPolling(pollInterval).WithTimeout(5 * time.Minute).Should(Succeed()) + }) + + It("should have a PriorityClass configured", func() { + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/instance": ed.Name(), + }, + }) + Expect(err).To(BeNil()) + listOptions := &ctrlClient.ListOptions{ + LabelSelector: selector, + } + deploymentList = &appsv1.DeploymentList{} + err = k8sClient.List(ctx, deploymentList, listOptions) + Expect(err).To(BeNil()) + Expect(deploymentList.Items).To(HaveLen(1)) + Expect(err).To(BeNil()) + + for _, deployment := range deploymentList.Items { + Expect(deployment.Spec.Template.Spec.PriorityClassName).To(Equal(dkpHighPriority)) + } + }) + + // Check that metrics server on port 7979 on the external DNS pod is responding + It("should emit metrics", func() { + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": "external-dns", + }, + }) + Expect(err).To(BeNil()) + listOptions := &ctrlClient.ListOptions{ + LabelSelector: selector, + } + podList := &corev1.PodList{} + err = k8sClient.List(ctx, podList, listOptions) + Expect(err).To(BeNil()) + Expect(podList.Items).To(HaveLen(1)) + + res := restClientV1Pods.Get().Resource("pods").Namespace(podList.Items[0].Namespace).Name(podList.Items[0].Name + ":7979").SubResource("proxy").Suffix("metrics").Do(ctx) + Expect(res.Error()).To(BeNil()) + + var statusCode int + res.StatusCode(&statusCode) + Expect(statusCode).To(Equal(200)) + + body, err := res.Raw() + Expect(err).To(BeNil()) + Expect(string(body)).To(ContainSubstring("external_dns")) + }) + }) + + Describe("Upgrading external-dns", Ordered, Label("upgrade"), func() { + var ( + ed externalDns + hr *fluxhelmv2beta2.HelmRelease + ) + + It("should install the previous version successfully", func() { + ed = externalDns{} + err := ed.InstallPreviousVersion(ctx, env) + Expect(err).To(BeNil()) + + hr = &fluxhelmv2beta2.HelmRelease{ + TypeMeta: metav1.TypeMeta{ + Kind: fluxhelmv2beta2.HelmReleaseKind, + APIVersion: fluxhelmv2beta2.GroupVersion.Version, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: ed.Name(), + Namespace: kommanderNamespace, + }, + } + + // Check the status of the HelmReleases + Eventually(func() error { + err = k8sClient.Get(ctx, ctrlClient.ObjectKeyFromObject(hr), hr) + if err != nil { + return err + } + + for _, cond := range hr.Status.Conditions { + if cond.Status == metav1.ConditionTrue && + cond.Type == apimeta.ReadyCondition { + return nil + } + } + return fmt.Errorf("helm release not ready yet") + }).WithPolling(pollInterval).WithTimeout(5 * time.Minute).Should(Succeed()) + }) + + It("should emit metrics", func() { + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": "external-dns", + }, + }) + Expect(err).To(BeNil()) + listOptions := &ctrlClient.ListOptions{ + LabelSelector: selector, + } + podList := &corev1.PodList{} + err = k8sClient.List(ctx, podList, listOptions) + Expect(err).To(BeNil()) + Expect(podList.Items).To(HaveLen(1)) + + res := restClientV1Pods.Get().Resource("pods").Namespace(podList.Items[0].Namespace).Name(podList.Items[0].Name + ":7979").SubResource("proxy").Suffix("metrics").Do(ctx) + Expect(res.Error()).To(BeNil()) + + var statusCode int + res.StatusCode(&statusCode) + Expect(statusCode).To(Equal(200)) + + body, err := res.Raw() + Expect(err).To(BeNil()) + Expect(string(body)).To(ContainSubstring("external_dns")) + }) + + It("should upgrade external-dns successfully", func() { + err := ed.Upgrade(ctx, env) + Expect(err).To(BeNil()) + + hr = &fluxhelmv2beta2.HelmRelease{ + TypeMeta: metav1.TypeMeta{ + Kind: fluxhelmv2beta2.HelmReleaseKind, + APIVersion: fluxhelmv2beta2.GroupVersion.Version, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: ed.Name(), + Namespace: kommanderNamespace, + }, + } + + // Check the status of the HelmReleases + Eventually(func() error { + err = k8sClient.Get(ctx, ctrlClient.ObjectKeyFromObject(hr), hr) + if err != nil { + return err + } + + for _, cond := range hr.Status.Conditions { + if cond.Status == metav1.ConditionTrue && + cond.Type == apimeta.ReadyCondition { + return nil + } + } + return fmt.Errorf("helm release not ready yet") + }).WithPolling(pollInterval).WithTimeout(5 * time.Minute).Should(Succeed()) + }) + + It("should emit metrics", func() { + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": "external-dns", + }, + }) + Expect(err).To(BeNil()) + listOptions := &ctrlClient.ListOptions{ + LabelSelector: selector, + } + podList := &corev1.PodList{} + err = k8sClient.List(ctx, podList, listOptions) + Expect(err).To(BeNil()) + Expect(podList.Items).To(HaveLen(1)) + + res := restClientV1Pods.Get().Resource("pods").Namespace(podList.Items[0].Namespace).Name(podList.Items[0].Name + ":7979").SubResource("proxy").Suffix("metrics").Do(ctx) + Expect(res.Error()).To(BeNil()) + + var statusCode int + res.StatusCode(&statusCode) + Expect(statusCode).To(Equal(200)) + + body, err := res.Raw() + Expect(err).To(BeNil()) + Expect(string(body)).To(ContainSubstring("external_dns")) + }) + + }) +}) diff --git a/apptests/constants/apps.go b/apptests/constants/apps.go index e2c24ab7b..826dda3ce 100644 --- a/apptests/constants/apps.go +++ b/apptests/constants/apps.go @@ -8,4 +8,5 @@ const ( Traefik = "traefik" KarmaTraefik = "karma-traefik" Flux = "kommander-flux" + ExternalDns = "external-dns" )