Last active
September 30, 2019 21:59
-
-
Save akutz/e393502b093ed8485861ede6b0799df7 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 ( | |
"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/v1alpha2" | |
) | |
const ( | |
namespace = "default" | |
) | |
type runtimeObject interface { | |
runtime.Object | |
GetName() string | |
GetNamespace() string | |
GetOwnerReferences() []metav1.OwnerReference | |
} | |
// 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 := func() { | |
EventuallyWithOffset(1, func() bool { | |
if err := k8sClient.Get(ctx, *key, obj); err != nil { | |
return false | |
} | |
return true | |
}, time.Second*30).Should(BeTrue()) | |
} | |
JustBeforeEach(func() { | |
Expect(k8sClient.Create(ctx, obj)).ToNot(HaveOccurred()) | |
key = &client.ObjectKey{ | |
Namespace: obj.GetNamespace(), | |
Name: obj.GetName(), | |
} | |
}) | |
JustAfterEach(func() { | |
Expect(k8sClient.Delete(ctx, obj)).ShouldNot(HaveOccurred()) | |
}) | |
AfterEach(func() { | |
obj = nil | |
key = nil | |
}) | |
Context("VSphereCluster", func() { | |
BeforeEach(func() { | |
obj = &infrav1.VSphereCluster{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
}, | |
Spec: infrav1.VSphereClusterSpec{}, | |
} | |
}) | |
It("Will be created and wait on an OwnerRef", func() { | |
assertObjEventuallyExists() | |
}) | |
}) | |
Context("VSphereMachine", func() { | |
BeforeEach(func() { | |
obj = &infrav1.VSphereMachine{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
}, | |
Spec: infrav1.VSphereMachineSpec{}, | |
} | |
}) | |
It("Will be created and wait on an OwnerRef", func() { | |
assertObjEventuallyExists() | |
}) | |
}) | |
}) | |
type canDeleteAndWait interface { | |
runtime.Object | |
SetFinalizers(finalizers []string) | |
} | |
// 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() { | |
// 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)).ShouldNot(HaveOccurred()) | |
clusterKey := client.ObjectKey{Namespace: cluster.Namespace, Name: cluster.Name} | |
Eventually(func() error { | |
return k8sClient.Get(ctx, clusterKey, cluster) | |
}, time.Second*30).ShouldNot(HaveOccurred()) | |
// Create the infrastructure cluster and wait for it to have a | |
// finalizer. | |
infraCluster := &infrav1.VSphereCluster{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
OwnerReferences: []metav1.OwnerReference{ | |
metav1.OwnerReference{ | |
APIVersion: cluster.APIVersion, | |
Kind: cluster.Kind, | |
Name: cluster.Name, | |
UID: cluster.UID, | |
}, | |
}, | |
}, | |
Spec: infrav1.VSphereClusterSpec{}, | |
} | |
Expect(k8sClient.Create(ctx, infraCluster)).ToNot(HaveOccurred()) | |
// Assert that eventually the infrastructure cluster will have a | |
// finalizer. | |
infraClusterKey := client.ObjectKey{Namespace: infraCluster.Namespace, Name: infraCluster.Name} | |
Eventually(func() bool { | |
if err := k8sClient.Get(ctx, infraClusterKey, infraCluster); err != nil { | |
return false | |
} | |
return len(infraCluster.Finalizers) > 0 | |
}, time.Second*30).Should(BeTrue()) | |
// Update the corresponding CAPI Cluster's InfrastructureRef | |
cluster.Spec.InfrastructureRef = &corev1.ObjectReference{ | |
APIVersion: infraCluster.APIVersion, | |
Kind: "VSphereCluster", //reflect.TypeOf(infraCluster).Elem().Name(), | |
Name: infraCluster.Name, | |
} | |
Expect(k8sClient.Update(ctx, cluster)).ShouldNot(HaveOccurred()) | |
// 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)).ShouldNot(HaveOccurred()) | |
machineKey := client.ObjectKey{Namespace: machine.Namespace, Name: machine.Name} | |
Eventually(func() error { | |
return k8sClient.Get(ctx, machineKey, machine) | |
}, time.Second*30).ShouldNot(HaveOccurred()) | |
// Create the infrastructure machine and wait for it to have a | |
// finalizer. | |
infraMachine := &infrav1.VSphereMachine{ | |
ObjectMeta: metav1.ObjectMeta{ | |
GenerateName: "test-", | |
Namespace: namespace, | |
OwnerReferences: []metav1.OwnerReference{ | |
metav1.OwnerReference{ | |
APIVersion: machine.APIVersion, | |
Kind: machine.Kind, | |
Name: machine.Name, | |
UID: machine.UID, | |
}, | |
}, | |
}, | |
Spec: infrav1.VSphereMachineSpec{}, | |
} | |
Expect(k8sClient.Create(ctx, infraMachine)).ToNot(HaveOccurred()) | |
infraMachineKey := client.ObjectKey{Namespace: infraMachine.Namespace, Name: infraMachine.Name} | |
Eventually(func() bool { | |
if err := k8sClient.Get(ctx, infraMachineKey, infraMachine); err != nil { | |
return false | |
} | |
return len(infraMachine.Finalizers) > 0 | |
}, time.Second*30).Should(BeTrue()) | |
deleteAndWait := func(key client.ObjectKey, obj canDeleteAndWait) { | |
// Delete the object. | |
Expect(k8sClient.Delete(ctx, obj)).ToNot(HaveOccurred()) | |
// Issues updates until the patch to remove the finalizers is | |
// successful. | |
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).ShouldNot(HaveOccurred()) | |
// Wait for the object to no longer be available. | |
EventuallyWithOffset(1, func() error { | |
return k8sClient.Get(ctx, key, obj) | |
}, time.Second*30).Should(HaveOccurred()) | |
} | |
// Delete the CAPI Cluster. To simulate the CAPI components we must: | |
// | |
// 1. Delete a resource. | |
// 2. Remove its finalizers. | |
// 3. Update the resource. | |
// 4. Wait for the resource to be deleted. | |
deleteAndWait(infraMachineKey, infraMachine) | |
deleteAndWait(machineKey, machine) | |
deleteAndWait(infraClusterKey, infraCluster) | |
deleteAndWait(clusterKey, cluster) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment