Skip to content

Commit

Permalink
feat: MicrovmDeployment Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Callisto13 committed Dec 7, 2022
1 parent 8515d6b commit 83a21e6
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
6 changes: 6 additions & 0 deletions api/v1alpha1/condition_consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,10 @@ const (

// MicrovmDeploymentProvisionFailedReason indicates that the microvm deployment failed to provision.
MicrovmDeploymentProvisionFailedReason = "MicrovmDeploymentProvisionFailed"

// MicrovmDeploymentUpdatingReason indicates the microvm deployment is in a pending state.
MicrovmDeploymentUpdatingReason = "MicrovmDeploymentUpdating"

// MicrovmDeploymentUpdateFailed indicates the microvm deployment is in a pending state.
MicrovmDeploymentUpdateFailedReason = "MicrovmDeploymentUpdateFailed"
)
12 changes: 12 additions & 0 deletions controllers/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ func reconcileMicrovmDeployment(client client.Client) (ctrl.Result, error) {
return mvmDepController.Reconcile(context.TODO(), request)
}

func reconcileMicrovmDeploymentNTimes(g *WithT, client client.Client, count int, r, rr int32) error {
for count > 0 {
ensureMicrovmReplicaSetState(g, client, r, rr)
if _, err := reconcileMicrovmDeployment(client); err != nil {
return err
}
count--
}

return nil
}

func getMicrovm(c client.Client, name, namespace string) (*infrav1.Microvm, error) {
key := client.ObjectKey{
Name: name,
Expand Down
19 changes: 19 additions & 0 deletions controllers/microvmdeployment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ func (r *MicrovmDeploymentReconciler) reconcileNormal(
}

mvmDeploymentScope.SetNotReady(infrav1.MicrovmDeploymentIncompleteReason, "Info", "")
// if we are here then a scale down has been requested.
// we delete the first found until the numbers balance out.
// TODO the way this works is very naive and often ends up deleting everything
// if the timing is wrong/right, find a better way https://github.com/weaveworks-liquidmetal/microvm-operator/issues/17
case createdSets > mvmDeploymentScope.RequiredSets():
mvmDeploymentScope.Info("MicrovmDeployment updating: delete microvmreplicaset")
mvmDeploymentScope.SetNotReady(infrav1.MicrovmDeploymentUpdatingReason, "Info", "")

rs := rsList[0]
if !rs.DeletionTimestamp.IsZero() {
return ctrl.Result{}, nil
}

if err := r.Delete(ctx, &rs); err != nil {
mvmDeploymentScope.Error(err, "failed deleting microvmreplicaset")
mvmDeploymentScope.SetNotReady(infrav1.MicrovmDeploymentUpdateFailedReason, "Error", "")

return ctrl.Result{}, err
}
// if all desired objects have been created, but are not quite ready yet,
// set the condition and requeue
default:
Expand Down
63 changes: 63 additions & 0 deletions controllers/microvmdeployment_controller_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package controllers_test

import (
"context"
"testing"

. "github.com/onsi/gomega"
"github.com/weaveworks-liquidmetal/controller-pkg/types/microvm"
infrav1 "github.com/weaveworks-liquidmetal/microvm-operator/api/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
)
Expand Down Expand Up @@ -79,3 +81,64 @@ func TestMicrovmDep_ReconcileNormal_CreateSucceeds(t *testing.T) {
g.Expect(microvmReplicaSetsCreated(g, client)).To(Equal(expectedReplicaSets), "Expected all Microvms to have been created after two reconciliations")
assertOneSetPerHost(g, reconciled, client)
}

func TestMicrovmDep_ReconcileNormal_UpdateSucceeds(t *testing.T) {
g := NewWithT(t)

// updating a replicaset with 2 replicas
var (
initialReplicaSetCount int = 2
scaledReplicaSetCount int32 = 1
expectedReplicas int32 = 2
initialReplicaCount int32 = 4
scaledReplicaCount int32 = 2
)

mvmD := createMicrovmDeployment(expectedReplicas, initialReplicaSetCount)
objects := []runtime.Object{mvmD}
client := createFakeClient(g, objects)

// create
g.Expect(reconcileMicrovmDeploymentNTimes(g, client, initialReplicaSetCount+4, expectedReplicas, expectedReplicas)).To(Succeed())

reconciled, err := getMicrovmDeployment(client, testMicrovmDeploymentName, testNamespace)
g.Expect(err).NotTo(HaveOccurred(), "Getting microvm should not fail")

assertMDFinalizer(g, reconciled)
assertConditionTrue(g, reconciled, infrav1.MicrovmDeploymentReadyCondition)
g.Expect(reconciled.Status.Ready).To(BeTrue(), "MicrovmDeployment should be ready now")
g.Expect(reconciled.Status.Replicas).To(Equal(initialReplicaCount), "Expected the record to contain 4 replicas")
g.Expect(reconciled.Status.ReadyReplicas).To(Equal(initialReplicaCount), "Expected all replicas to be ready")
g.Expect(microvmReplicaSetsCreated(g, client)).To(Equal(initialReplicaSetCount), "Expected 2 replicasets to exist")

// update, scale down to 1
reconciled.Spec.Hosts = []microvm.Host{{Endpoint: "1.2.3.4:9090"}}
g.Expect(client.Update(context.TODO(), reconciled)).To(Succeed())

// first reconciliation
result, err := reconcileMicrovmDeployment(client)
g.Expect(err).NotTo(HaveOccurred(), "Reconciling microvmdeployment the first time should not error")
g.Expect(result.IsZero()).To(BeFalse(), "Expect requeue to be requested after update")

reconciled, err = getMicrovmDeployment(client, testMicrovmDeploymentName, testNamespace)
g.Expect(err).NotTo(HaveOccurred(), "Getting microvmdeployment should not fail")

assertConditionFalse(g, reconciled, infrav1.MicrovmDeploymentReadyCondition, infrav1.MicrovmDeploymentUpdatingReason)
g.Expect(reconciled.Status.Ready).To(BeFalse(), "MicrovmDeployment should not be ready")
g.Expect(reconciled.Status.Replicas).To(Equal(initialReplicaCount), "Expected the record to contain 4 replicas")
g.Expect(reconciled.Status.ReadyReplicas).To(Equal(initialReplicaCount), "Expected all replicas to be ready")

// second reconciliation
result, err = reconcileMicrovmDeployment(client)
g.Expect(err).NotTo(HaveOccurred(), "Reconciling microvmdeployment the second time should not error")
g.Expect(result.IsZero()).To(BeTrue(), "Expect requeue to not be requested after reconcile")

reconciled, err = getMicrovmDeployment(client, testMicrovmDeploymentName, testNamespace)
g.Expect(err).NotTo(HaveOccurred(), "Getting microvmdeployment should not fail")

assertConditionTrue(g, reconciled, infrav1.MicrovmDeploymentReadyCondition)
g.Expect(reconciled.Status.Ready).To(BeTrue(), "MicrovmDeployment should be ready again")
g.Expect(reconciled.Status.Replicas).To(Equal(scaledReplicaCount), "Expected the record to contain 2 replicas")
g.Expect(reconciled.Status.ReadyReplicas).To(Equal(scaledReplicaCount), "Expected all replicas to be ready")
g.Expect(microvmReplicaSetsCreated(g, client)).To(Equal(int(scaledReplicaSetCount)), "Expected replicasets to have been scaled down after two reconciliations")
}

0 comments on commit 83a21e6

Please sign in to comment.