Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ushitora-anqou committed Sep 8, 2024
1 parent 8e1e880 commit efd6560
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 72 deletions.
22 changes: 10 additions & 12 deletions internal/controller/mastodonserver_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,14 @@ func buildJobName(kind jobType, mastodonServerName string) string {
}

func encodeDeploymentImage(image string) string {
return base64.StdEncoding.EncodeToString([]byte(image))
return base64.RawURLEncoding.EncodeToString([]byte(image))
}

func getDeploymentImage(
ctx context.Context, client client.Client, name, namespace string,
) (string, error) {
var deploy appsv1.Deployment
if err := client.Get(
ctx, types.NamespacedName{
Name: buildDeploymentName(componentWeb, name), Namespace: namespace,
}, &deploy,
); err != nil {
if err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, &deploy); err != nil {
return "", err
}

Expand Down Expand Up @@ -180,6 +176,10 @@ func (r *MastodonServerReconciler) Reconcile(ctx context.Context, req ctrl.Reque
"name", server.GetName(),
"namespace", server.GetNamespace(),
"whattodo", whattodo.String(),
"deploymentStatus", k8sStatus.deploymentsStatus,
"preMigrationJobStatus", k8sStatus.preMigrationJobStatus,
"postMigrationJobStatus", k8sStatus.postMigrationJobStatus,
"migratingImageMap", k8sStatus.migratingImageMap != nil,
)

switch whattodo {
Expand Down Expand Up @@ -476,6 +476,7 @@ func (r *MastodonServerReconciler) createOrUpdateDeployment(

result, err := ctrl.CreateOrUpdate(ctx, r.Client, &deploy, func() error {
deploy.SetAnnotations(deployAnnotations)
deploy.SetLabels(deployLabels)

selector := map[string]string{
"app.kubernetes.io/name": appName,
Expand All @@ -486,17 +487,14 @@ func (r *MastodonServerReconciler) createOrUpdateDeployment(
MatchLabels: selector,
}

labels := map[string]string{
podLabels := map[string]string{
labelMastodonServer: server.GetName(),
labelDeployImage: encodeDeploymentImage(image),
}
for k, v := range selector {
labels[k] = v
}
for k, v := range deployLabels {
labels[k] = v
podLabels[k] = v
}
deploy.SetLabels(labels)
deploy.Spec.Template.SetLabels(podLabels)

deploy.Spec.Replicas = &replicas
deploy.Spec.Template.Spec.Containers = []corev1.Container{
Expand Down
231 changes: 172 additions & 59 deletions internal/controller/mastodonserver_controller_test.go
Original file line number Diff line number Diff line change
@@ -1,59 +1,172 @@
package controller

// import (
// . "github.com/onsi/ginkgo/v2"
// . "github.com/onsi/gomega"
// )

// var _ = Describe("MastodonServer Controller", func() {
// Context("When reconciling a resource", func() {
// const resourceName = "test-resource"
//
// ctx := context.Background()
//
// typeNamespacedName := types.NamespacedName{
// Name: resourceName,
// Namespace: "default", // TODO(user):Modify as needed
// }
// mastodonserver := &magoutv1.MastodonServer{}
//
// BeforeEach(func() {
// By("creating the custom resource for the Kind MastodonServer")
// err := k8sClient.Get(ctx, typeNamespacedName, mastodonserver)
// if err != nil && errors.IsNotFound(err) {
// resource := &magoutv1.MastodonServer{
// ObjectMeta: metav1.ObjectMeta{
// Name: resourceName,
// Namespace: "default",
// },
// // TODO(user): Specify other spec details if needed.
// }
// Expect(k8sClient.Create(ctx, resource)).To(Succeed())
// }
// })
//
// AfterEach(func() {
// // TODO(user): Cleanup logic after each test, like removing the resource instance.
// resource := &magoutv1.MastodonServer{}
// err := k8sClient.Get(ctx, typeNamespacedName, resource)
// Expect(err).NotTo(HaveOccurred())
//
// By("Cleanup the specific resource instance MastodonServer")
// Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
// })
// It("should successfully reconcile the resource", func() {
// By("Reconciling the created resource")
// controllerReconciler := &MastodonServerReconciler{
// Client: k8sClient,
// Scheme: k8sClient.Scheme(),
// }
//
// _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
// NamespacedName: typeNamespacedName,
// })
// Expect(err).NotTo(HaveOccurred())
// // TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
// // Example: If you expect a certain status condition after reconciliation, verify it here.
// })
// })
// })
package controller_test

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
magoutv1 "github.com/ushitora-anqou/magout/api/v1"
"github.com/ushitora-anqou/magout/internal/controller"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

var _ = Describe("MastodonServer Controller", func() {
Context("When reconciling a resource", func() {
ctx := context.Background()

It("should create post-migration job if nothing is found", func() {
mastodonServerName := "test"
namespace := "default"
namespacedName := types.NamespacedName{Name: mastodonServerName, Namespace: namespace}
webImage := "web-image"
webImageBase64 := "d2ViLWltYWdl"
sidekiqImage := "sidekiq-image"
sidekiqImageBase64 := "c2lkZWtpcS1pbWFnZQ"
streamingImage := "streaming-image"
streamingImageBase64 := "c3RyZWFtaW5nLWltYWdl"

controllerReconciler := &controller.MastodonServerReconciler{
Client: k8sClient,
Scheme: k8sClient.Scheme(),
}

By("Creating a MastodonServer resource")
var err error
server := &magoutv1.MastodonServer{}
server.SetName(mastodonServerName)
server.SetNamespace(namespace)
server.Spec.Web.Image = webImage
server.Spec.Sidekiq.Image = sidekiqImage
server.Spec.Streaming.Image = streamingImage
err = k8sClient.Create(ctx, server)
Expect(err).NotTo(HaveOccurred())

By("Reconciling the created resource")
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: namespacedName,
})
Expect(err).NotTo(HaveOccurred())

By("Checking that the MantleServer resource has migrating field")
err = k8sClient.Get(ctx, namespacedName, server)
Expect(err).NotTo(HaveOccurred())
Expect(server.Status.Migrating.Web).To(Equal(webImage))
Expect(server.Status.Migrating.Sidekiq).To(Equal(sidekiqImage))
Expect(server.Status.Migrating.Streaming).To(Equal(streamingImage))

By("Reconciling the created resource")
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: namespacedName,
})
Expect(err).NotTo(HaveOccurred())

By("Checking that a post migration job was created")
var job batchv1.Job
err = k8sClient.Get(ctx, types.NamespacedName{
Name: mastodonServerName + "-post-migration",
Namespace: namespace,
}, &job)
Expect(err).NotTo(HaveOccurred())
Expect(job.Spec.Template.Spec.Containers[0].Image).To(Equal(webImage))
Expect(job.Spec.Template.Spec.Containers[0].Env[0].Name).To(Equal("SKIP_POST_DEPLOYMENT_MIGRATIONS"))
Expect(job.Spec.Template.Spec.Containers[0].Env[0].Value).To(Equal("true"))

By("Making the post migration job completed")
job.Status.Succeeded = 1
err = k8sClient.Status().Update(ctx, &job)
Expect(err).NotTo(HaveOccurred())

By("Reconciling the created resource")
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: namespacedName,
})
Expect(err).NotTo(HaveOccurred())

By("Checking deployments are created")
var deployWeb appsv1.Deployment
err = k8sClient.Get(ctx, types.NamespacedName{Name: mastodonServerName + "-web", Namespace: namespace}, &deployWeb)
Expect(err).NotTo(HaveOccurred())
Expect(deployWeb.Spec.Template.GetLabels()[labelMagoutAnqouNetMastodonServer]).To(Equal(mastodonServerName))
Expect(deployWeb.Spec.Template.GetLabels()[labelMagoutAnqouNetDeployImage]).To(Equal(webImageBase64))

var deploySidekiq appsv1.Deployment
err = k8sClient.Get(ctx, types.NamespacedName{Name: mastodonServerName + "-sidekiq", Namespace: namespace}, &deploySidekiq)
Expect(err).NotTo(HaveOccurred())
Expect(deploySidekiq.Spec.Template.GetLabels()[labelMagoutAnqouNetMastodonServer]).To(Equal(mastodonServerName))
Expect(deploySidekiq.Spec.Template.GetLabels()[labelMagoutAnqouNetDeployImage]).To(Equal(sidekiqImageBase64))

var deployStreaming appsv1.Deployment
err = k8sClient.Get(ctx, types.NamespacedName{Name: mastodonServerName + "-streaming", Namespace: namespace}, &deployStreaming)
Expect(err).NotTo(HaveOccurred())
Expect(deployStreaming.Spec.Template.GetLabels()[labelMagoutAnqouNetMastodonServer]).To(Equal(mastodonServerName))
Expect(deployStreaming.Spec.Template.GetLabels()[labelMagoutAnqouNetDeployImage]).To(Equal(streamingImageBase64))

By("Creating pods to emulate the situation where all the deployments are ready")
var podWeb corev1.Pod
podWeb.SetName(mastodonServerName + "-web-ffffff")
podWeb.SetNamespace(namespace)
podWeb.SetLabels(map[string]string{
labelMagoutAnqouNetMastodonServer: mastodonServerName,
labelMagoutAnqouNetDeployImage: webImageBase64,
})
podWeb.Spec.Containers = []corev1.Container{
{Name: "container", Image: webImage},
}
podWeb.Status.Phase = corev1.PodRunning
err = k8sClient.Create(ctx, &podWeb)
Expect(err).NotTo(HaveOccurred())

var podSidekiq corev1.Pod
podSidekiq.SetName(mastodonServerName + "-sidekiq-ffffff")
podSidekiq.SetNamespace(namespace)
podSidekiq.SetLabels(map[string]string{
labelMagoutAnqouNetMastodonServer: mastodonServerName,
labelMagoutAnqouNetDeployImage: sidekiqImageBase64,
})
podSidekiq.Spec.Containers = []corev1.Container{
{Name: "container", Image: sidekiqImage},
}
podSidekiq.Status.Phase = corev1.PodRunning
err = k8sClient.Create(ctx, &podSidekiq)
Expect(err).NotTo(HaveOccurred())

var podStreming corev1.Pod
podStreming.SetName(mastodonServerName + "-streaming-ffffff")
podStreming.SetNamespace(namespace)
podStreming.SetLabels(map[string]string{
labelMagoutAnqouNetMastodonServer: mastodonServerName,
labelMagoutAnqouNetDeployImage: streamingImageBase64,
})
podStreming.Spec.Containers = []corev1.Container{
{Name: "container", Image: streamingImage},
}
podStreming.Status.Phase = corev1.PodRunning
err = k8sClient.Create(ctx, &podStreming)
Expect(err).NotTo(HaveOccurred())

By("Reconciling the created resource")
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: namespacedName,
})
Expect(err).NotTo(HaveOccurred())

By("Checking that the post migration job was removed")
err = k8sClient.Get(ctx, types.NamespacedName{
Name: mastodonServerName + "-post-migration",
Namespace: namespace,
}, &job)
Expect(k8serrors.IsNotFound(err)).To(BeTrue())

By("Reconciling the created resource")
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: namespacedName,
})
Expect(err).NotTo(HaveOccurred())
})
})
})
10 changes: 9 additions & 1 deletion internal/controller/suite_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package controller
package controller_test

import (
"context"
"fmt"
"path/filepath"
"runtime"
"testing"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -70,6 +71,8 @@ var _ = BeforeSuite(func() {
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())

SetDefaultEventuallyTimeout(3 * time.Second)
SetDefaultEventuallyPollingInterval(1 * time.Second)
})

var _ = AfterSuite(func() {
Expand All @@ -78,3 +81,8 @@ var _ = AfterSuite(func() {
err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred())
})

const (
labelMagoutAnqouNetMastodonServer = "magout.anqou.net/mastodon-server"
labelMagoutAnqouNetDeployImage = "magout.anqou.net/deploy-image"
)

0 comments on commit efd6560

Please sign in to comment.