/controllers_test.go Secret
Created
October 1, 2019 16:30
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers_test | |
import ( | |
"reflect" | |
"time" | |
. "github.com/onsi/ginkgo" | |
. "github.com/onsi/gomega" | |
corev1 "k8s.io/api/core/v1" | |
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
"k8s.io/apimachinery/pkg/runtime" | |
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha2" | |
"sigs.k8s.io/controller-runtime/pkg/client" | |
infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha2" | |
) | |
const ( | |
namespace = "default" | |
) | |
type runtimeObject interface { | |
runtime.Object | |
GetName() string | |
GetNamespace() string | |
SetFinalizers([]string) | |
GetFinalizers() []string | |
GetOwnerReferences() []metav1.OwnerReference | |
SetOwnerReferences([]metav1.OwnerReference) | |
} | |
// newInfraCluster should return a new instance of the infrastructure cluster. | |
func newInfraCluster() runtimeObject { | |
return &infrav1.VSphereCluster{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
}, | |
} | |
} | |
// newInfraMachine should return a new instance of the infrastructure machine. | |
func newInfraMachine() runtimeObject { | |
return &infrav1.VSphereMachine{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
}, | |
} | |
} | |
// Cache the type names of the infrastructure cluster and machine. | |
var ( | |
infraClusterTypeName = reflect.TypeOf(newInfraCluster()).Elem().Name() | |
infraMachineTypeName = reflect.TypeOf(newInfraMachine()).Elem().Name() | |
) | |
// The spec conformance tests assert that the infrastructure types | |
// can be submitted to the API server without any errors. | |
var _ = Describe("Spec conformance tests", func() { | |
var ( | |
obj runtimeObject | |
key *client.ObjectKey | |
) | |
// assertObjEventuallyExists is used to assert that eventually obj can be | |
// retrieved from the API server. | |
assertObjEventuallyExists := func() { | |
EventuallyWithOffset(1, func() error { | |
return k8sClient.Get(ctx, *key, obj) | |
}, time.Second*30).Should(Succeed()) | |
} | |
JustBeforeEach(func() { | |
Expect(k8sClient.Create(ctx, obj)).To(Succeed()) | |
key = &client.ObjectKey{ | |
Namespace: obj.GetNamespace(), | |
Name: obj.GetName(), | |
} | |
}) | |
JustAfterEach(func() { | |
Expect(k8sClient.Delete(ctx, obj)).To(Succeed()) | |
}) | |
AfterEach(func() { | |
obj = nil | |
key = nil | |
}) | |
Context(infraClusterTypeName, func() { | |
BeforeEach(func() { | |
obj = newInfraCluster() | |
}) | |
It("Will be created and wait on an OwnerRef", func() { | |
assertObjEventuallyExists() | |
}) | |
}) | |
Context(infraMachineTypeName, func() { | |
BeforeEach(func() { | |
obj = newInfraMachine() | |
}) | |
It("Will be created and wait on an OwnerRef", func() { | |
assertObjEventuallyExists() | |
}) | |
}) | |
}) | |
// Verifies that the infrastructure types have finalizers set when an OwnerRef | |
// is set that points to the corresponding CAPI resource. | |
var _ = Describe("Reconciler tests", func() { | |
Specify("Infrastructure resources should have finalizers after reconciliation", func() { | |
// assertEventuallyFinalizers is used to assert an object eventually has one or more | |
// finalizers. | |
assertEventuallyFinalizers := func(key client.ObjectKey, obj runtimeObject) { | |
EventuallyWithOffset(1, func() (int, error) { | |
if err := k8sClient.Get(ctx, key, obj); err != nil { | |
return 0, err | |
} | |
return len(obj.GetFinalizers()), nil | |
}, time.Second*30).Should(BeNumerically(">", 0)) | |
} | |
By("Create the CAPI Cluster and wait for it to exist") | |
// A finalizer is added to prevent it from being deleted until its | |
// dependents are removed. | |
cluster := &clusterv1.Cluster{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
Finalizers: []string{"test"}, | |
}, | |
Spec: clusterv1.ClusterSpec{}, | |
} | |
Expect(k8sClient.Create(ctx, cluster)).To(Succeed()) | |
clusterKey := client.ObjectKey{Namespace: cluster.Namespace, Name: cluster.Name} | |
Eventually(func() error { | |
return k8sClient.Get(ctx, clusterKey, cluster) | |
}, time.Second*30).Should(Succeed()) | |
By("Create the infrastructure cluster and wait for it to have a finalizer") | |
infraCluster := newInfraCluster() | |
infraCluster.SetOwnerReferences([]metav1.OwnerReference{ | |
metav1.OwnerReference{ | |
APIVersion: cluster.APIVersion, | |
Kind: cluster.Kind, | |
Name: cluster.Name, | |
UID: cluster.UID, | |
}, | |
}) | |
Expect(k8sClient.Create(ctx, infraCluster)).To(Succeed()) | |
// Assert that eventually the infrastructure cluster will have a | |
// finalizer. | |
infraClusterKey := client.ObjectKey{Namespace: infraCluster.GetNamespace(), Name: infraCluster.GetName()} | |
assertEventuallyFinalizers(infraClusterKey, infraCluster) | |
By("Update the CAPI Cluster's InfrastructureRef") | |
cluster.Spec.InfrastructureRef = &corev1.ObjectReference{ | |
APIVersion: infraCluster.GetObjectKind().GroupVersionKind().GroupVersion().String(), | |
Kind: infraCluster.GetObjectKind().GroupVersionKind().Kind, | |
Name: infraCluster.GetName(), | |
} | |
Expect(k8sClient.Update(ctx, cluster)).To(Succeed()) | |
By("Create the CAPI Machine and wait for it to exist") | |
// A finalizer is added to prevent it from being deleted until its | |
// dependents are removed. | |
machine := &clusterv1.Machine{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
Finalizers: []string{"test"}, | |
Labels: map[string]string{ | |
clusterv1.MachineClusterLabelName: cluster.Name, | |
}, | |
OwnerReferences: []metav1.OwnerReference{ | |
metav1.OwnerReference{ | |
APIVersion: cluster.APIVersion, | |
Kind: cluster.Kind, | |
Name: cluster.Name, | |
UID: cluster.UID, | |
}, | |
}, | |
}, | |
Spec: clusterv1.MachineSpec{}, | |
} | |
Expect(k8sClient.Create(ctx, machine)).To(Succeed()) | |
machineKey := client.ObjectKey{Namespace: machine.Namespace, Name: machine.Name} | |
Eventually(func() error { | |
return k8sClient.Get(ctx, machineKey, machine) | |
}, time.Second*30).Should(Succeed()) | |
By("Create the infrastructure machine and wait for it to have a finalizer") | |
infraMachine := newInfraMachine() | |
infraMachine.SetOwnerReferences([]metav1.OwnerReference{ | |
metav1.OwnerReference{ | |
APIVersion: machine.APIVersion, | |
Kind: machine.Kind, | |
Name: machine.Name, | |
UID: machine.UID, | |
}, | |
}) | |
Expect(k8sClient.Create(ctx, infraMachine)).To(Succeed()) | |
infraMachineKey := client.ObjectKey{Namespace: infraMachine.GetNamespace(), Name: infraMachine.GetName()} | |
assertEventuallyFinalizers(infraMachineKey, infraMachine) | |
deleteAndWait := func(key client.ObjectKey, obj runtimeObject, removeFinalizers bool) { | |
// Delete the object. | |
Expect(k8sClient.Delete(ctx, obj)).To(Succeed()) | |
// Issues updates until the patch to remove the finalizers is | |
// successful. | |
if removeFinalizers { | |
EventuallyWithOffset(1, func() error { | |
if err := k8sClient.Get(ctx, key, obj); err != nil { | |
return err | |
} | |
obj.SetFinalizers([]string{}) | |
return k8sClient.Update(ctx, obj) | |
}, time.Second*30).Should(Succeed()) | |
} | |
// Wait for the object to no longer be available. | |
EventuallyWithOffset(1, func() error { | |
return k8sClient.Get(ctx, key, obj) | |
}, time.Second*30).ShouldNot(Succeed()) | |
} | |
// Delete the CAPI Cluster. To simulate the CAPI components we must: | |
// | |
// 1. Delete a resource. | |
// 2. Remove its finalizers (if its a CAPI object). | |
// 3. Update the resource. | |
// 4. Wait for the resource to be deleted. | |
By("Delete the infrastructure machine and wait for it to be removed") | |
deleteAndWait(infraMachineKey, infraMachine, false) | |
By("Delete the CAPI machine and wait for it to be removed") | |
deleteAndWait(machineKey, machine, true) | |
By("Delete the infrastructure cluster and wait for it to be removed") | |
deleteAndWait(infraClusterKey, infraCluster, false) | |
By("Delete the CAPI cluster and wait for it to be removed") | |
deleteAndWait(clusterKey, cluster, true) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment