280 lines
9.1 KiB
Go
280 lines
9.1 KiB
Go
/*
|
|
Copyright © 2022 SUSE LLC
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package controllers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
elementalv1 "github.com/rancher/elemental-operator/api/v1beta1"
|
|
"github.com/rancher/elemental-operator/pkg/test"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/utils/pointer"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
)
|
|
|
|
var _ = Describe("reconcile machine inventory", func() {
|
|
var r *MachineInventoryReconciler
|
|
var mInventory *elementalv1.MachineInventory
|
|
var planSecret *corev1.Secret
|
|
|
|
BeforeEach(func() {
|
|
r = &MachineInventoryReconciler{
|
|
Client: cl,
|
|
}
|
|
|
|
mInventory = &elementalv1.MachineInventory{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "machine-inventory-suite",
|
|
Namespace: "default",
|
|
},
|
|
}
|
|
|
|
planSecret = &corev1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: mInventory.Namespace,
|
|
Name: mInventory.Name,
|
|
},
|
|
Data: map[string][]byte{
|
|
"applied-checksum": []byte("appliedchecksum"),
|
|
},
|
|
}
|
|
|
|
Expect(cl.Create(ctx, mInventory)).To(Succeed())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
Expect(test.CleanupAndWait(ctx, cl, mInventory, planSecret)).To(Succeed())
|
|
})
|
|
|
|
It("should reconcile machine inventory object when plan secret doesn't exist", func() {
|
|
_, err := r.Reconcile(ctx, reconcile.Request{
|
|
NamespacedName: types.NamespacedName{
|
|
Namespace: mInventory.Namespace,
|
|
Name: mInventory.Name,
|
|
},
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(cl.Get(ctx, client.ObjectKey{
|
|
Name: mInventory.Name,
|
|
Namespace: mInventory.Namespace,
|
|
}, mInventory)).To(Succeed())
|
|
|
|
Expect(mInventory.Finalizers).To(HaveLen(1))
|
|
Expect(mInventory.Finalizers[0]).To(Equal(elementalv1.MachineInventoryFinalizer))
|
|
|
|
Expect(mInventory.Status.Conditions).To(HaveLen(1))
|
|
|
|
Expect(mInventory.Status.Conditions[0].Type).To(Equal(elementalv1.ReadyCondition))
|
|
Expect(mInventory.Status.Conditions[0].Reason).To(Equal(elementalv1.WaitingForPlanReason))
|
|
Expect(mInventory.Status.Conditions[0].Status).To(Equal(metav1.ConditionFalse))
|
|
Expect(mInventory.Status.Conditions[0].Message).To(Equal("waiting for plan to be applied"))
|
|
})
|
|
|
|
It("should reconcile machine inventory object when plan secret already exists", func() {
|
|
Expect(cl.Create(ctx, planSecret)).To(Succeed())
|
|
|
|
_, err := r.Reconcile(ctx, reconcile.Request{
|
|
NamespacedName: types.NamespacedName{
|
|
Namespace: mInventory.Namespace,
|
|
Name: mInventory.Name,
|
|
},
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(cl.Get(ctx, client.ObjectKey{
|
|
Name: mInventory.Name,
|
|
Namespace: mInventory.Namespace,
|
|
}, mInventory)).To(Succeed())
|
|
|
|
Expect(mInventory.Finalizers).To(HaveLen(1))
|
|
Expect(mInventory.Finalizers[0]).To(Equal(elementalv1.MachineInventoryFinalizer))
|
|
|
|
Expect(mInventory.Status.Plan.Checksum).To(Equal(string(planSecret.Data["applied-checksum"])))
|
|
Expect(mInventory.Status.Plan.State).To(Equal(elementalv1.PlanApplied))
|
|
|
|
Expect(mInventory.Status.Conditions).To(HaveLen(1))
|
|
|
|
Expect(mInventory.Status.Conditions[0].Type).To(Equal(elementalv1.ReadyCondition))
|
|
Expect(mInventory.Status.Conditions[0].Reason).To(Equal(elementalv1.PlanSuccefullyAppliedReason))
|
|
Expect(mInventory.Status.Conditions[0].Status).To(Equal(metav1.ConditionTrue))
|
|
Expect(mInventory.Status.Conditions[0].Message).To(Equal("plan succefully applied"))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("createPlanSecret", func() {
|
|
var r *MachineInventoryReconciler
|
|
var mInventory *elementalv1.MachineInventory
|
|
var planSecret *corev1.Secret
|
|
|
|
BeforeEach(func() {
|
|
r = &MachineInventoryReconciler{
|
|
Client: cl,
|
|
}
|
|
|
|
mInventory = &elementalv1.MachineInventory{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "machine-inventory-suite",
|
|
Namespace: "default",
|
|
},
|
|
}
|
|
|
|
planSecret = &corev1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: mInventory.Namespace,
|
|
Name: mInventory.Name,
|
|
},
|
|
}
|
|
|
|
Expect(cl.Create(ctx, mInventory)).To(Succeed())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
Expect(test.CleanupAndWait(ctx, cl, mInventory, planSecret)).To(Succeed())
|
|
})
|
|
|
|
It("should succesfully create plan secret", func() {
|
|
Expect(r.createPlanSecret(ctx, mInventory)).To(Succeed())
|
|
|
|
Expect(r.Get(ctx, types.NamespacedName{Namespace: mInventory.Namespace, Name: mInventory.Name}, planSecret)).To(Succeed())
|
|
|
|
Expect(planSecret.OwnerReferences).To(HaveLen(1))
|
|
Expect(planSecret.OwnerReferences[0].APIVersion).To(Equal(elementalv1.GroupVersion.String()))
|
|
Expect(planSecret.OwnerReferences[0].Kind).To(Equal("MachineInventory"))
|
|
Expect(planSecret.OwnerReferences[0].Name).To(Equal(mInventory.Name))
|
|
Expect(planSecret.OwnerReferences[0].UID).To(Equal(mInventory.UID))
|
|
Expect(planSecret.OwnerReferences[0].Controller).To(Equal(pointer.Bool(true)))
|
|
Expect(planSecret.Labels).To(HaveKey(elementalv1.ElementalManagedLabel))
|
|
Expect(planSecret.Type).To(Equal(elementalv1.PlanSecretType))
|
|
Expect(planSecret.Data).To(HaveKey("plan"))
|
|
|
|
Expect(mInventory.Status.Plan.PlanSecretRef.Name).To(Equal(mInventory.Name))
|
|
Expect(mInventory.Status.Plan.PlanSecretRef.Namespace).To(Equal(mInventory.Namespace))
|
|
|
|
Expect(mInventory.Status.Conditions).To(HaveLen(1))
|
|
|
|
Expect(mInventory.Status.Conditions[0].Type).To(Equal(elementalv1.ReadyCondition))
|
|
Expect(mInventory.Status.Conditions[0].Reason).To(Equal(elementalv1.WaitingForPlanReason))
|
|
Expect(mInventory.Status.Conditions[0].Status).To(Equal(metav1.ConditionFalse))
|
|
Expect(mInventory.Status.Conditions[0].Message).To(Equal("waiting for plan to be applied"))
|
|
})
|
|
|
|
It("shouldn't return error is secret already exists", func() {
|
|
Expect(r.createPlanSecret(ctx, mInventory)).To(Succeed())
|
|
Expect(r.createPlanSecret(ctx, mInventory)).To(Succeed())
|
|
})
|
|
|
|
It("should return error is secret fails to be created", func() {
|
|
r.Client = machineInventoryFailingClient{}
|
|
err := r.createPlanSecret(ctx, mInventory)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("failed to create"))
|
|
})
|
|
|
|
It("should do nothing if ready condition is present", func() {
|
|
meta.SetStatusCondition(&mInventory.Status.Conditions, metav1.Condition{
|
|
Type: elementalv1.ReadyCondition,
|
|
Reason: elementalv1.PlanSuccefullyAppliedReason,
|
|
Status: metav1.ConditionTrue,
|
|
Message: "plan succefully applied",
|
|
})
|
|
Expect(r.createPlanSecret(ctx, mInventory)).To(Succeed())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("updateInventoryWithPlanStatus", func() {
|
|
var r *MachineInventoryReconciler
|
|
var mInventory *elementalv1.MachineInventory
|
|
var planSecret *corev1.Secret
|
|
|
|
BeforeEach(func() {
|
|
r = &MachineInventoryReconciler{
|
|
Client: cl,
|
|
}
|
|
|
|
mInventory = &elementalv1.MachineInventory{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "machine-inventory-suite",
|
|
Namespace: "default",
|
|
},
|
|
}
|
|
|
|
planSecret = &corev1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: mInventory.Namespace,
|
|
Name: mInventory.Name,
|
|
},
|
|
}
|
|
|
|
Expect(cl.Create(ctx, mInventory)).To(Succeed())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
Expect(test.CleanupAndWait(ctx, cl, mInventory, planSecret)).To(Succeed())
|
|
})
|
|
|
|
It("should succesfully update when plan is applied", func() {
|
|
planSecret.Data = map[string][]byte{
|
|
"applied-checksum": []byte("applied-checksum"),
|
|
}
|
|
Expect(cl.Create(ctx, planSecret)).To(Succeed())
|
|
|
|
mInventory.Status.Plan = &elementalv1.PlanStatus{}
|
|
Expect(r.updateInventoryWithPlanStatus(ctx, mInventory)).To(Succeed())
|
|
|
|
Expect(mInventory.Status.Plan.State).To(Equal(elementalv1.PlanApplied))
|
|
|
|
Expect(mInventory.Status.Conditions).To(HaveLen(1))
|
|
Expect(mInventory.Status.Conditions[0].Type).To(Equal(elementalv1.ReadyCondition))
|
|
Expect(mInventory.Status.Conditions[0].Reason).To(Equal(elementalv1.PlanSuccefullyAppliedReason))
|
|
Expect(mInventory.Status.Conditions[0].Status).To(Equal(metav1.ConditionTrue))
|
|
Expect(mInventory.Status.Conditions[0].Message).To(Equal("plan succefully applied"))
|
|
})
|
|
|
|
It("should return error when plan failed to be applied", func() {
|
|
planSecret.Data = map[string][]byte{
|
|
"failed-checksum": []byte("failed-checksum"),
|
|
}
|
|
Expect(cl.Create(ctx, planSecret)).To(Succeed())
|
|
|
|
mInventory.Status.Plan = &elementalv1.PlanStatus{}
|
|
err := r.updateInventoryWithPlanStatus(ctx, mInventory)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("failed to apply plan"))
|
|
})
|
|
|
|
AfterEach(func() {
|
|
Expect(test.CleanupAndWait(ctx, cl, mInventory, planSecret)).To(Succeed())
|
|
})
|
|
|
|
})
|
|
|
|
type machineInventoryFailingClient struct {
|
|
client.Client
|
|
}
|
|
|
|
func (cl machineInventoryFailingClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
|
|
return errors.New("failed to create")
|
|
}
|