From e7697bcce459c9b30b1e41ab8f0a658dc2ad7381 Mon Sep 17 00:00:00 2001 From: Ellis Tarn Date: Tue, 29 Jun 2021 15:10:33 -0700 Subject: [PATCH] =?UTF-8?q?Finally=20decided=20to=20prevent=20tests=20from?= =?UTF-8?q?=20flaking=20=F0=9F=A4=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 2 +- pkg/cloudprovider/aws/suite_test.go | 135 ++++++++++----------- pkg/controllers/allocation/suite_test.go | 49 +++----- pkg/controllers/controller.go | 11 -- pkg/controllers/manager.go | 14 --- pkg/controllers/reallocation/suite_test.go | 23 ++-- pkg/controllers/termination/suite_test.go | 22 ++-- pkg/test/environment.go | 37 +++--- pkg/test/expectations/expectations.go | 72 +++++------ 9 files changed, 156 insertions(+), 209 deletions(-) diff --git a/docs/README.md b/docs/README.md index b96a3536c90b..f01b96f5556d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -424,5 +424,5 @@ its target, and indicates whether or not those conditions are met.


Generated with gen-crd-api-reference-docs -on git commit aa1e430. +on git commit 350646c.

diff --git a/pkg/cloudprovider/aws/suite_test.go b/pkg/cloudprovider/aws/suite_test.go index 035de6254a72..f98c9ab79f5b 100644 --- a/pkg/cloudprovider/aws/suite_test.go +++ b/pkg/cloudprovider/aws/suite_test.go @@ -23,6 +23,7 @@ import ( "github.com/awslabs/karpenter/pkg/apis/provisioning/v1alpha2" "github.com/awslabs/karpenter/pkg/cloudprovider/aws/fake" "github.com/awslabs/karpenter/pkg/cloudprovider/registry" + "github.com/awslabs/karpenter/pkg/controllers" "github.com/awslabs/karpenter/pkg/controllers/allocation" "github.com/awslabs/karpenter/pkg/test" . "github.com/awslabs/karpenter/pkg/test/expectations" @@ -47,8 +48,10 @@ func TestAPIs(t *testing.T) { var launchTemplateCache = cache.New(CacheTTL, CacheCleanupInterval) var fakeEC2API *fake.EC2API +var controller controllers.Controller + var env = test.NewEnvironment(func(e *test.Environment) { - clientSet := kubernetes.NewForConfigOrDie(e.Manager.GetConfig()) + clientSet := kubernetes.NewForConfigOrDie(e.Config) fakeEC2API = &fake.EC2API{} cloudProvider := &CloudProvider{ nodeAPI: &NodeFactory{fakeEC2API}, @@ -63,13 +66,7 @@ var env = test.NewEnvironment(func(e *test.Environment) { instanceProvider: &InstanceProvider{fakeEC2API}, } registry.RegisterOrDie(cloudProvider) - e.Manager.RegisterControllers( - allocation.NewController( - e.Manager.GetClient(), - clientSet.CoreV1(), - cloudProvider, - ), - ) + controller = allocation.NewController(e.Client, clientSet.CoreV1(), cloudProvider) }) var _ = BeforeSuite(func() { @@ -110,11 +107,11 @@ var _ = Describe("Allocation", func() { Context("Reconciliation", func() { Context("Reserved Labels", func() { It("should not schedule a pod with cloud provider reserved labels", func() { - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{AWSLabelPrefix + "unknown": randomdata.SillyName()}}), ) // Assertions - Expect(pod.Spec.NodeName).To(BeEmpty()) + Expect(pods[0].Spec.NodeName).To(BeEmpty()) }) }) Context("Specialized Hardware", func() { @@ -141,8 +138,7 @@ var _ = Describe("Allocation", func() { }, }) ExpectCreatedWithStatus(env.Client, pod1, pod2, pod3) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) // Assertions scheduled1 := ExpectPodExists(env.Client, pod1.GetName(), pod1.GetNamespace()) scheduled2 := ExpectPodExists(env.Client, pod2.GetName(), pod2.GetNamespace()) @@ -191,8 +187,7 @@ var _ = Describe("Allocation", func() { }, }) ExpectCreatedWithStatus(env.Client, pod1, pod2, pod3) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) // Assertions scheduled1 := ExpectPodExists(env.Client, pod1.GetName(), pod1.GetNamespace()) scheduled2 := ExpectPodExists(env.Client, pod2.GetName(), pod2.GetNamespace()) @@ -222,9 +217,9 @@ var _ = Describe("Allocation", func() { Context("CapacityType", func() { It("should default to on demand", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(aws.StringValue(fakeEC2API.CalledWithCreateFleetInput[0].TargetCapacitySpecification.DefaultTargetCapacityType)).To(Equal(CapacityTypeOnDemand)) @@ -233,9 +228,9 @@ var _ = Describe("Allocation", func() { It("should default to a provisioner's specified capacity type", func() { // Setup provisioner.Spec.Labels = map[string]string{CapacityTypeLabel: CapacityTypeSpot} - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(aws.StringValue(fakeEC2API.CalledWithCreateFleetInput[0].TargetCapacitySpecification.DefaultTargetCapacityType)).To(Equal(CapacityTypeSpot)) @@ -243,11 +238,11 @@ var _ = Describe("Allocation", func() { }) It("should allow a pod to override the capacity type", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{CapacityTypeLabel: CapacityTypeSpot}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(aws.StringValue(fakeEC2API.CalledWithCreateFleetInput[0].TargetCapacitySpecification.DefaultTargetCapacityType)).To(Equal(CapacityTypeSpot)) @@ -255,19 +250,19 @@ var _ = Describe("Allocation", func() { }) It("should not schedule a pod with an invalid capacityType", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{CapacityTypeLabel: "unknown"}}), ) // Assertions - Expect(pod.Spec.NodeName).To(BeEmpty()) + Expect(pods[0].Spec.NodeName).To(BeEmpty()) }) }) Context("LaunchTemplates", func() { It("should default to a generated launch template", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification @@ -282,9 +277,9 @@ var _ = Describe("Allocation", func() { LaunchTemplateIdLabel: randomdata.SillyName(), LaunchTemplateVersionLabel: randomdata.SillyName(), } - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification @@ -296,9 +291,9 @@ var _ = Describe("Allocation", func() { It("should default to a provisioner's launch template and the default launch template version", func() { // Setup provisioner.Spec.Labels = map[string]string{LaunchTemplateIdLabel: randomdata.SillyName()} - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification @@ -313,36 +308,36 @@ var _ = Describe("Allocation", func() { LaunchTemplateIdLabel: randomdata.SillyName(), LaunchTemplateVersionLabel: randomdata.SillyName(), } - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{ LaunchTemplateIdLabel: randomdata.SillyName(), LaunchTemplateVersionLabel: randomdata.SillyName(), }}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification - Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pod.Spec.NodeSelector[LaunchTemplateIdLabel])) - Expect(aws.StringValue(launchTemplate.Version)).To(Equal(pod.Spec.NodeSelector[LaunchTemplateVersionLabel])) - Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pod.Spec.NodeSelector[LaunchTemplateIdLabel])) - Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateVersionLabel, pod.Spec.NodeSelector[LaunchTemplateVersionLabel])) + Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(aws.StringValue(launchTemplate.Version)).To(Equal(pods[0].Spec.NodeSelector[LaunchTemplateVersionLabel])) + Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateVersionLabel, pods[0].Spec.NodeSelector[LaunchTemplateVersionLabel])) }) It("should allow a pod to override the launch template id and use the default launch template version", func() { // Setup provisioner.Spec.Labels = map[string]string{LaunchTemplateIdLabel: randomdata.SillyName()} - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{LaunchTemplateIdLabel: randomdata.SillyName()}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification - Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pod.Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) Expect(aws.StringValue(launchTemplate.Version)).To(Equal(DefaultLaunchTemplateVersion)) - Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pod.Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) Expect(node.Labels).ToNot(HaveKey(LaunchTemplateVersionLabel)) }) It("should allow a pod to override the launch template id and use the provisioner's launch template version", func() { @@ -351,17 +346,17 @@ var _ = Describe("Allocation", func() { LaunchTemplateIdLabel: randomdata.SillyName(), LaunchTemplateVersionLabel: randomdata.SillyName(), } - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{LaunchTemplateIdLabel: randomdata.SillyName()}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) launchTemplate := fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification - Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pod.Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(aws.StringValue(launchTemplate.LaunchTemplateId)).To(Equal(pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) Expect(aws.StringValue(launchTemplate.Version)).To(Equal(provisioner.Spec.Labels[LaunchTemplateVersionLabel])) - Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pod.Spec.NodeSelector[LaunchTemplateIdLabel])) + Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateIdLabel, pods[0].Spec.NodeSelector[LaunchTemplateIdLabel])) Expect(node.Labels).To(HaveKeyWithValue(LaunchTemplateVersionLabel, provisioner.Spec.Labels[LaunchTemplateVersionLabel])) }) }) @@ -369,9 +364,9 @@ var _ = Describe("Allocation", func() { It("should default to the clusters subnets", func() { // Setup provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].Overrides).To(ConsistOf( @@ -386,9 +381,9 @@ var _ = Describe("Allocation", func() { // Setup provisioner.Spec.Labels = map[string]string{SubnetNameLabel: "test-subnet-2"} provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].Overrides).To(ConsistOf( @@ -400,9 +395,9 @@ var _ = Describe("Allocation", func() { It("should default to a provisioner's specified subnet tag key", func() { provisioner.Spec.Labels = map[string]string{SubnetTagKeyLabel: "TestTag"} provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].Overrides).To(ConsistOf( @@ -414,49 +409,49 @@ var _ = Describe("Allocation", func() { It("should allow a pod to override the subnet name", func() { // Setup provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SubnetNameLabel: "test-subnet-2"}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].Overrides).To(ConsistOf( &ec2.FleetLaunchTemplateOverridesRequest{SubnetId: aws.String("test-subnet-2"), InstanceType: aws.String("m5.large")}, )) - Expect(node.Labels).To(HaveKeyWithValue(SubnetNameLabel, pod.Spec.NodeSelector[SubnetNameLabel])) + Expect(node.Labels).To(HaveKeyWithValue(SubnetNameLabel, pods[0].Spec.NodeSelector[SubnetNameLabel])) Expect(node.Labels).ToNot(HaveKey(SubnetTagKeyLabel)) }) It("should allow a pod to override the subnet tags", func() { provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SubnetTagKeyLabel: "TestTag"}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs[0].Overrides).To(ConsistOf( &ec2.FleetLaunchTemplateOverridesRequest{SubnetId: aws.String("test-subnet-3"), InstanceType: aws.String("m5.large")}, )) Expect(node.Labels).ToNot(HaveKey(SubnetNameLabel)) - Expect(node.Labels).To(HaveKeyWithValue(SubnetTagKeyLabel, pod.Spec.NodeSelector[SubnetTagKeyLabel])) + Expect(node.Labels).To(HaveKeyWithValue(SubnetTagKeyLabel, pods[0].Spec.NodeSelector[SubnetTagKeyLabel])) }) It("should not schedule a pod with an invalid subnet", func() { provisioner.Spec.InstanceTypes = []string{"m5.large"} // limit instance type to simplify ConsistOf checks - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningFailed(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SubnetTagKeyLabel: "Invalid"}}), ) // Assertions - Expect(pod.Spec.NodeName).To(BeEmpty()) + Expect(pods[0].Spec.NodeName).To(BeEmpty()) }) }) Context("Security Groups", func() { It("should default to the clusters security groups", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput[0].LaunchTemplateData.SecurityGroupIds).To(ConsistOf( aws.String("test-security-group-1"), @@ -469,9 +464,9 @@ var _ = Describe("Allocation", func() { It("should default to a provisioner's specified security groups name", func() { // Setup provisioner.Spec.Labels = map[string]string{SecurityGroupNameLabel: "test-security-group-2"} - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput[0].LaunchTemplateData.SecurityGroupIds).To(ConsistOf( aws.String("test-security-group-2"), @@ -481,9 +476,9 @@ var _ = Describe("Allocation", func() { }) It("should default to a provisioner's specified security groups tag key", func() { provisioner.Spec.Labels = map[string]string{SecurityGroupTagKeyLabel: "TestTag"} - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput[0].LaunchTemplateData.SecurityGroupIds).To(ConsistOf( aws.String("test-security-group-3"), @@ -493,24 +488,24 @@ var _ = Describe("Allocation", func() { }) It("should allow a pod to override the security groups name", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SecurityGroupNameLabel: "test-security-group-2"}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput[0].LaunchTemplateData.SecurityGroupIds).To(ConsistOf( aws.String("test-security-group-2"), )) - Expect(node.Labels).To(HaveKeyWithValue(SecurityGroupNameLabel, pod.Spec.NodeSelector[SecurityGroupNameLabel])) + Expect(node.Labels).To(HaveKeyWithValue(SecurityGroupNameLabel, pods[0].Spec.NodeSelector[SecurityGroupNameLabel])) Expect(node.Labels).ToNot(HaveKey(SecurityGroupTagKeyLabel)) }) It("should allow a pod to override the security groups tags", func() { - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SecurityGroupTagKeyLabel: "TestTag"}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(fakeEC2API.CalledWithCreateFleetInput).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateFleetInput[0].LaunchTemplateConfigs).To(HaveLen(1)) Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput).To(HaveLen(1)) @@ -518,14 +513,14 @@ var _ = Describe("Allocation", func() { aws.String("test-security-group-3"), )) Expect(node.Labels).ToNot(HaveKey(SecurityGroupNameLabel)) - Expect(node.Labels).To(HaveKeyWithValue(SecurityGroupTagKeyLabel, pod.Spec.NodeSelector[SecurityGroupTagKeyLabel])) + Expect(node.Labels).To(HaveKeyWithValue(SecurityGroupTagKeyLabel, pods[0].Spec.NodeSelector[SecurityGroupTagKeyLabel])) }) It("should not schedule a pod with an invalid security group", func() { - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningFailed(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{SecurityGroupTagKeyLabel: "Invalid"}}), ) // Assertions - Expect(pod.Spec.NodeName).To(BeEmpty()) + Expect(pods[0].Spec.NodeName).To(BeEmpty()) }) }) }) diff --git a/pkg/controllers/allocation/suite_test.go b/pkg/controllers/allocation/suite_test.go index 12eac9da532c..3b750a9bb213 100644 --- a/pkg/controllers/allocation/suite_test.go +++ b/pkg/controllers/allocation/suite_test.go @@ -47,11 +47,10 @@ var env = test.NewEnvironment(func(e *test.Environment) { cloudProvider := &fake.CloudProvider{} registry.RegisterOrDie(cloudProvider) controller = NewController( - e.Manager.GetClient(), - corev1.NewForConfigOrDie(e.Manager.GetConfig()), + e.Client, + corev1.NewForConfigOrDie(e.Config), cloudProvider, ) - e.Manager.RegisterControllers(controller) }) var _ = BeforeSuite(func() { @@ -86,43 +85,38 @@ var _ = Describe("Allocation", func() { Context("Zones", func() { It("should default to a cluster zone", func() { // Setup - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(node.Spec.ProviderID).To(ContainSubstring("test-zone-1")) }) It("should default to a provisioner's zone", func() { // Setup provisioner.Spec.Zones = []string{"test-zone-2"} - pod := AttemptProvisioning(env.Client, provisioner, test.PendingPod()) + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod()) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(node.Spec.ProviderID).To(ContainSubstring("test-zone-2")) }) It("should allow a pod to override the zone", func() { // Setup provisioner.Spec.Zones = []string{"test-zone-1"} - pod := AttemptProvisioning(env.Client, provisioner, + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{NodeSelector: map[string]string{v1alpha2.ZoneLabelKey: "test-zone-2"}}), ) // Assertions - node := ExpectNodeExists(env.Client, pod.Spec.NodeName) + node := ExpectNodeExists(env.Client, pods[0].Spec.NodeName) Expect(node.Spec.ProviderID).To(ContainSubstring("test-zone-2")) }) }) It("should provision nodes for unconstrained pods", func() { - pods := []*v1.Pod{test.PendingPod(), test.PendingPod()} - for _, pod := range pods { - ExpectCreatedWithStatus(env.Client, pod) - } - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) - + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, + test.PendingPod(), test.PendingPod(), + ) nodes := &v1.NodeList{} Expect(env.Client.List(ctx, nodes)).To(Succeed()) Expect(len(nodes.Items)).To(Equal(1)) - for _, object := range pods { - pod := ExpectPodExists(env.Client, object.GetName(), object.GetNamespace()) + for _, pod := range pods { Expect(pod.Spec.NodeName).To(Equal(nodes.Items[0].Name)) } }) @@ -162,8 +156,7 @@ var _ = Describe("Allocation", func() { ExpectCreatedWithStatus(env.Client, schedulable...) ExpectCreatedWithStatus(env.Client, coschedulable...) ExpectCreatedWithStatus(env.Client, unschedulable...) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) nodes := &v1.NodeList{} Expect(env.Client.List(ctx, nodes)).To(Succeed()) @@ -210,8 +203,7 @@ var _ = Describe("Allocation", func() { } ExpectCreatedWithStatus(env.Client, schedulable...) ExpectCreatedWithStatus(env.Client, unschedulable...) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) nodes := &v1.NodeList{} Expect(env.Client.List(ctx, nodes)).To(Succeed()) @@ -226,7 +218,7 @@ var _ = Describe("Allocation", func() { } }) It("should provision nodes for accelerators", func() { - schedulable := []client.Object{ + pods := ExpectProvisioningSucceeded(env.Client, controller, provisioner, test.PendingPod(test.PodOptions{ ResourceRequirements: v1.ResourceRequirements{Limits: v1.ResourceList{resources.NvidiaGPU: resource.MustParse("1")}}, }), @@ -236,15 +228,11 @@ var _ = Describe("Allocation", func() { test.PendingPod(test.PodOptions{ ResourceRequirements: v1.ResourceRequirements{Limits: v1.ResourceList{resources.AWSNeuron: resource.MustParse("1")}}, }), - } - ExpectCreatedWithStatus(env.Client, schedulable...) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) - + ) nodes := &v1.NodeList{} Expect(env.Client.List(ctx, nodes)).To(Succeed()) Expect(len(nodes.Items)).To(Equal(3)) - for _, pod := range schedulable { + for _, pod := range pods { scheduled := ExpectPodExists(env.Client, pod.GetName(), pod.GetNamespace()) ExpectNodeExists(env.Client, scheduled.Spec.NodeName) } @@ -276,8 +264,7 @@ var _ = Describe("Allocation", func() { } ExpectCreatedWithStatus(env.Client, daemonsets...) ExpectCreatedWithStatus(env.Client, schedulable...) - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) nodes := &v1.NodeList{} Expect(env.Client.List(ctx, nodes)).To(Succeed()) diff --git a/pkg/controllers/controller.go b/pkg/controllers/controller.go index cc14d2dd40d6..d26def47cbe9 100644 --- a/pkg/controllers/controller.go +++ b/pkg/controllers/controller.go @@ -18,11 +18,9 @@ import ( "context" "fmt" - "github.com/awslabs/karpenter/pkg/utils/conditions" "go.uber.org/zap" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - "knative.dev/pkg/apis" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -51,15 +49,6 @@ func (c *GenericController) Reconcile(ctx context.Context, req reconcile.Request if err != nil { zap.S().Errorf("Controller failed to reconcile kind %s, %s", resource.GetObjectKind().GroupVersionKind().Kind, err.Error()) } - // 4. Set status based on results of reconcile - if conditionsAccessor, ok := resource.(apis.ConditionsAccessor); ok { - m := apis.NewLivingConditionSet(conditions.Active).Manage(conditionsAccessor) - if err != nil { - m.MarkFalse(conditions.Active, err.Error(), "") - } else { - m.MarkTrue(conditions.Active) - } - } // 5. Update Status using a merge patch // If the controller is reconciling nodes, don't patch if _, ok := resource.(*v1.Node); !ok { diff --git a/pkg/controllers/manager.go b/pkg/controllers/manager.go index e97759d54eb9..b1bbd21e52d3 100644 --- a/pkg/controllers/manager.go +++ b/pkg/controllers/manager.go @@ -19,12 +19,8 @@ import ( "fmt" "time" - "github.com/awslabs/karpenter/pkg/apis" - "golang.org/x/time/rate" v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/client-go/util/workqueue" controllerruntime "sigs.k8s.io/controller-runtime" @@ -34,22 +30,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" ) -var ( - scheme = runtime.NewScheme() -) - -func init() { - _ = clientgoscheme.AddToScheme(scheme) - _ = apis.AddToScheme(scheme) -} - type GenericControllerManager struct { manager.Manager } // NewManagerOrDie instantiates a controller manager or panics func NewManagerOrDie(config *rest.Config, options controllerruntime.Options) Manager { - options.Scheme = scheme manager, err := controllerruntime.NewManager(config, options) if err != nil { panic(fmt.Sprintf("Failed to create controller manager, %s", err.Error())) diff --git a/pkg/controllers/reallocation/suite_test.go b/pkg/controllers/reallocation/suite_test.go index 877a74002c08..d79365bfe382 100644 --- a/pkg/controllers/reallocation/suite_test.go +++ b/pkg/controllers/reallocation/suite_test.go @@ -46,11 +46,10 @@ var env = test.NewEnvironment(func(e *test.Environment) { cloudProvider := &fake.CloudProvider{} registry.RegisterOrDie(cloudProvider) controller = NewController( - e.Manager.GetClient(), - corev1.NewForConfigOrDie(e.Manager.GetConfig()), + e.Client, + corev1.NewForConfigOrDie(e.Config), cloudProvider, ) - e.Manager.RegisterControllers(controller) }) var _ = BeforeSuite(func() { @@ -79,7 +78,7 @@ var _ = Describe("Reallocation", func() { }) AfterEach(func() { - ExpectCleanedUp(env.Manager.GetClient()) + ExpectCleanedUp(env.Client) }) Context("Reconciliation", func() { @@ -91,9 +90,7 @@ var _ = Describe("Reallocation", func() { }, }) ExpectCreatedWithStatus(env.Client, node) - - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + ExpectReconcileSucceeded(controller, provisioner) updatedNode := &v1.Node{} Expect(env.Client.Get(ctx, client.ObjectKey{Name: node.Name}, updatedNode)).To(Succeed()) @@ -111,18 +108,14 @@ var _ = Describe("Reallocation", func() { v1alpha2.ProvisionerTTLKey: time.Now().Add(time.Duration(100) * time.Second).Format(time.RFC3339), }, }) - pod := test.Pod(test.PodOptions{ + ExpectCreatedWithStatus(env.Client, node) + ExpectCreatedWithStatus(env.Client, test.Pod(test.PodOptions{ Name: strings.ToLower(randomdata.SillyName()), Namespace: provisioner.Namespace, NodeName: node.Name, Conditions: []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue}}, - }) - - ExpectCreatedWithStatus(env.Client, node) - ExpectCreatedWithStatus(env.Client, pod) - - ExpectCreated(env.Client, provisioner) - ExpectEventuallyReconciled(env.Client, provisioner) + })) + ExpectReconcileSucceeded(controller, provisioner) updatedNode := &v1.Node{} Expect(env.Client.Get(ctx, client.ObjectKey{Name: node.Name}, updatedNode)).To(Succeed()) diff --git a/pkg/controllers/termination/suite_test.go b/pkg/controllers/termination/suite_test.go index b3642f1dd9b6..35368c1cbb8f 100644 --- a/pkg/controllers/termination/suite_test.go +++ b/pkg/controllers/termination/suite_test.go @@ -41,11 +41,10 @@ var env = test.NewEnvironment(func(e *test.Environment) { cloudProvider := &fake.CloudProvider{} registry.RegisterOrDie(cloudProvider) controller = NewController( - e.Manager.GetClient(), - corev1.NewForConfigOrDie(e.Manager.GetConfig()), + e.Client, + corev1.NewForConfigOrDie(e.Config), cloudProvider, ) - e.Manager.RegisterControllers(controller) }) var _ = BeforeSuite(func() { @@ -64,7 +63,7 @@ var _ = Describe("Termination", func() { }) AfterEach(func() { - ExpectCleanedUp(env.Manager.GetClient()) + ExpectCleanedUp(env.Client) }) Context("Reconciliation", func() { @@ -76,8 +75,10 @@ var _ = Describe("Termination", func() { v1alpha2.ProvisionerNamespaceLabelKey: "default", }, }) - ExpectCreatedWithStatus(env.Client, node) + ExpectCreated(env.Client, node) Expect(env.Client.Delete(ctx, node)).To(Succeed()) + node = ExpectNodeExists(env.Client, node.Name) + ExpectReconcileSucceeded(controller, node) ExpectNotFound(env.Client, node) }) It("should not evict pods that tolerate unschedulable taint", func() { @@ -88,15 +89,16 @@ var _ = Describe("Termination", func() { v1alpha2.ProvisionerNamespaceLabelKey: "default", }, }) - pod := test.Pod(test.PodOptions{ + ExpectCreated(env.Client, node) + ExpectCreated(env.Client, test.Pod(test.PodOptions{ NodeName: node.Name, Tolerations: []v1.Toleration{{Key: v1.TaintNodeUnschedulable, Operator: v1.TolerationOpExists, Effect: v1.TaintEffectNoSchedule}}, - }) - ExpectCreatedWithStatus(env.Client, node) - ExpectCreatedWithStatus(env.Client, pod) + })) - pods := &v1.PodList{} Expect(env.Client.Delete(ctx, node)).To(Succeed()) + node = ExpectNodeExists(env.Client, node.Name) + ExpectReconcileSucceeded(controller, node) + pods := &v1.PodList{} Expect(env.Client.List(ctx, pods, client.MatchingFields{"spec.nodeName": node.Name})).To(Succeed()) Expect(pods.Items).To(HaveLen(1)) ExpectNotFound(env.Client, node) diff --git a/pkg/test/environment.go b/pkg/test/environment.go index 40c962413655..d0861ce9247b 100644 --- a/pkg/test/environment.go +++ b/pkg/test/environment.go @@ -17,17 +17,27 @@ import ( "fmt" "sync" - "github.com/awslabs/karpenter/pkg/controllers" + "github.com/awslabs/karpenter/pkg/apis" "github.com/awslabs/karpenter/pkg/utils/log" "github.com/awslabs/karpenter/pkg/utils/project" - "go.uber.org/zap" "go.uber.org/zap/zapcore" + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" controllerruntime "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" controllerruntimezap "sigs.k8s.io/controller-runtime/pkg/log/zap" ) +var ( + scheme = runtime.NewScheme() +) + +func init() { + _ = clientgoscheme.AddToScheme(scheme) + _ = apis.AddToScheme(scheme) +} + /* Environment is for e2e local testing. It stands up an API Server, ETCD, and a controller-runtime manager. It's possible to run multiple environments @@ -45,8 +55,7 @@ AfterSuite(func() { env.Stop() }) */ type Environment struct { envtest.Environment - Manager controllers.Manager - Client client.Client + Client client.Client options []EnvironmentOption ctx context.Context @@ -75,36 +84,20 @@ func NewEnvironment(options ...EnvironmentOption) *Environment { func (e *Environment) Start() (err error) { // Environment - if _, err := e.Environment.Start(); err != nil { + if _, err = e.Environment.Start(); err != nil { return fmt.Errorf("starting environment, %w", err) } - // Manager - e.Manager = controllers.NewManagerOrDie(e.Config, controllerruntime.Options{ - MetricsBindAddress: "0", // Skip the metrics server to avoid port conflicts for parallel testing - }) - // Client - kubeClient, err := client.New(e.Manager.GetConfig(), client.Options{ - Scheme: e.Manager.GetScheme(), - Mapper: e.Manager.GetRESTMapper(), - }) + e.Client, err = client.New(e.Config, client.Options{Scheme: scheme}) if err != nil { return err } - e.Client = kubeClient // options for _, option := range e.options { option(e) } - - // Start manager - go func() { - if err := e.Manager.Start(e.ctx); err != nil { - zap.S().Panic(err) - } - }() return nil } diff --git a/pkg/test/expectations/expectations.go b/pkg/test/expectations/expectations.go index b5b70beb1626..d2ac2c793315 100644 --- a/pkg/test/expectations/expectations.go +++ b/pkg/test/expectations/expectations.go @@ -20,8 +20,7 @@ import ( "time" "github.com/awslabs/karpenter/pkg/apis/provisioning/v1alpha2" - "github.com/awslabs/karpenter/pkg/utils/conditions" - "github.com/awslabs/karpenter/pkg/utils/log" + "github.com/awslabs/karpenter/pkg/controllers" . "github.com/onsi/gomega" v1 "k8s.io/api/core/v1" @@ -74,15 +73,11 @@ func ExpectCreatedWithStatus(c client.Client, objects ...client.Object) { } } -func ExpectDeletedNode(c client.Client, n *v1.Node) { - persisted := n.DeepCopy() - n.Finalizers = []string{} - Expect(c.Patch(context.Background(), n, client.MergeFrom(persisted))).To(Succeed()) - ExpectDeleted(c, n) -} - func ExpectDeleted(c client.Client, objects ...client.Object) { for _, object := range objects { + persisted := object.DeepCopyObject() + object.SetFinalizers([]string{}) + Expect(c.Patch(context.Background(), object, client.MergeFrom(persisted))).To(Succeed()) Expect(c.Delete(context.Background(), object, &client.DeleteOptions{GracePeriodSeconds: ptr.Int64(0)})).To(Succeed()) } for _, object := range objects { @@ -90,26 +85,6 @@ func ExpectDeleted(c client.Client, objects ...client.Object) { } } -func ExpectEventuallyHappy(c client.Client, provisioner *v1alpha2.Provisioner) { - nn := types.NamespacedName{Name: provisioner.GetName(), Namespace: provisioner.GetNamespace()} - Eventually(func() bool { - Expect(c.Get(context.Background(), nn, provisioner)).To(Succeed()) - return provisioner.StatusConditions().IsHappy() - }, ReconcilerPropagationTime, RequestInterval).Should(BeTrue(), func() string { - return fmt.Sprintf("resource never became happy\n%s", log.Pretty(provisioner)) - }) -} - -func ExpectEventuallyReconciled(c client.Client, provisioner *v1alpha2.Provisioner) { - nn := types.NamespacedName{Name: provisioner.GetName(), Namespace: provisioner.GetNamespace()} - Eventually(func() bool { - Expect(c.Get(context.Background(), nn, provisioner)).To(Succeed()) - return !provisioner.StatusConditions().GetCondition(conditions.Active).IsUnknown() - }, ReconcilerPropagationTime, RequestInterval).Should(BeTrue(), func() string { - return fmt.Sprintf("resources active condition was never updated\n%s", log.Pretty(provisioner)) - }) -} - func ExpectCleanedUp(c client.Client) { ctx := context.Background() pods := v1.PodList{} @@ -120,7 +95,7 @@ func ExpectCleanedUp(c client.Client) { nodes := v1.NodeList{} Expect(c.List(ctx, &nodes)).To(Succeed()) for _, node := range nodes.Items { - ExpectDeletedNode(c, &node) + ExpectDeleted(c, &node) } provisioners := v1alpha2.ProvisionerList{} Expect(c.List(ctx, &provisioners)).To(Succeed()) @@ -129,9 +104,36 @@ func ExpectCleanedUp(c client.Client) { } } -func AttemptProvisioning(c client.Client, provisioner *v1alpha2.Provisioner, pod *v1.Pod) *v1.Pod { - ExpectCreatedWithStatus(c, pod) - ExpectCreated(c, provisioner) - ExpectEventuallyReconciled(c, provisioner) - return ExpectPodExists(c, pod.GetName(), pod.GetNamespace()) +func ExpectProvisioningSucceeded(c client.Client, controller controllers.Controller, provisioner *v1alpha2.Provisioner, pods ...*v1.Pod) []*v1.Pod { + for _, pod := range pods { + ExpectCreatedWithStatus(c, pod) + } + ExpectReconcileSucceeded(controller, provisioner) + result := []*v1.Pod{} + for _, pod := range pods { + result = append(result, ExpectPodExists(c, pod.GetName(), pod.GetNamespace())) + } + return result +} + +func ExpectProvisioningFailed(c client.Client, controller controllers.Controller, provisioner *v1alpha2.Provisioner, pods ...*v1.Pod) []*v1.Pod { + for _, pod := range pods { + ExpectCreatedWithStatus(c, pod) + } + ExpectReconcileFailed(controller, provisioner) + result := []*v1.Pod{} + for _, pod := range pods { + result = append(result, ExpectPodExists(c, pod.GetName(), pod.GetNamespace())) + } + return result +} + +func ExpectReconcileFailed(controller controllers.Controller, object client.Object) { + _, err := controller.Reconcile(context.Background(), object) + Expect(err).To(HaveOccurred()) +} + +func ExpectReconcileSucceeded(controller controllers.Controller, object client.Object) { + _, err := controller.Reconcile(context.Background(), object) + Expect(err).ToNot(HaveOccurred()) }