diff --git a/test/e2e/shared/aws.go b/test/e2e/shared/aws.go index ae5723b6f7..df2c89746b 100644 --- a/test/e2e/shared/aws.go +++ b/test/e2e/shared/aws.go @@ -2405,63 +2405,3 @@ func GetMountTargetState(ctx context.Context, e2eCtx *E2EContext, mountTargetID state := string(result.LifeCycleState) return &state, nil } - -func getAvailabilityZone(e2eCtx *E2EContext) string { - az := e2eCtx.E2EConfig.MustGetVariable(AwsAvailabilityZone1) - return az -} - -func getInstanceFamily(e2eCtx *E2EContext) string { - machineType := e2eCtx.E2EConfig.MustGetVariable(AwsNodeMachineType) - // from instance type get instace family behind the dot - // for example: t3a.medium -> t3 - machineTypeSplit := strings.Split(machineType, ".") - if len(machineTypeSplit) > 0 { - return machineTypeSplit[0] - } - return "t3" -} - -func AllocateHost(ctx context.Context, e2eCtx *E2EContext) (string, error) { - ec2Svc := ec2.NewFromConfig(*e2eCtx.AWSSession) - input := &ec2.AllocateHostsInput{ - AvailabilityZone: aws.String(getAvailabilityZone(e2eCtx)), - InstanceFamily: aws.String(getInstanceFamily(e2eCtx)), - Quantity: aws.Int32(1), - } - output, err := ec2Svc.AllocateHosts(ctx, input) - Expect(err).ToNot(HaveOccurred(), "Failed to allocate host") - Expect(len(output.HostIds)).To(BeNumerically(">", 0), "No dedicated host ID returned") - fmt.Println("Allocated Host ID: ", output.HostIds[0]) - hostID := output.HostIds[0] - return hostID, nil -} - -func ReleaseHost(ctx context.Context, e2eCtx *E2EContext, hostID string) { - ec2Svc := ec2.NewFromConfig(*e2eCtx.AWSSession) - - input := &ec2.ReleaseHostsInput{ - HostIds: []string{hostID}, - } - - _, err := ec2Svc.ReleaseHosts(ctx, input) - Expect(err).ToNot(HaveOccurred(), "Failed to release host %s", hostID) - fmt.Println("Released Host ID: ", hostID) -} - -func GetHostID(ctx context.Context, e2eCtx *E2EContext, instanceID string) string { - ec2Svc := ec2.NewFromConfig(*e2eCtx.AWSSession) - - input := &ec2.DescribeInstancesInput{ - InstanceIds: []string{instanceID}, - } - - result, err := ec2Svc.DescribeInstances(ctx, input) - Expect(err).ToNot(HaveOccurred(), "Failed to get host ID for instance %s", instanceID) - Expect(len(result.Reservations)).To(BeNumerically(">", 0), "No reservation returned") - Expect(len(result.Reservations[0].Instances)).To(BeNumerically(">", 0), "No instance returned") - placement := *result.Reservations[0].Instances[0].Placement - hostID := *placement.HostId - fmt.Println("Host ID: ", hostID) - return hostID -} diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go index 4c6643f686..bc65e84829 100644 --- a/test/e2e/shared/defaults.go +++ b/test/e2e/shared/defaults.go @@ -77,8 +77,6 @@ const ( ClassicElbTestKubernetesFrom = "CLASSICELB_TEST_KUBERNETES_VERSION_FROM" ClassicElbTestKubernetesTo = "CLASSICELB_TEST_KUBERNETES_VERSION_TO" - - DedicatedHostFlavor = "dedicated-host" ) // ResourceQuotaFilePath is the path to the file that contains the resource usage. diff --git a/test/e2e/suites/unmanaged/unmanaged_functional_test.go b/test/e2e/suites/unmanaged/unmanaged_functional_test.go index e873a7ff35..1bd31fab25 100644 --- a/test/e2e/suites/unmanaged/unmanaged_functional_test.go +++ b/test/e2e/suites/unmanaged/unmanaged_functional_test.go @@ -27,7 +27,6 @@ import ( "strings" "time" - "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/blang/semver" "github.com/gofrs/flock" "github.com/onsi/ginkgo/v2" @@ -634,266 +633,6 @@ var _ = ginkgo.Context("[unmanaged] [functional]", func() { }) }) - // This test builds a management cluster using an externally managed VPC and subnets. CAPA is still handling security group - // creation for the management cluster. The workload cluster is created in a peered VPC with a single externally managed security group. - // A private and public subnet is created in this VPC to allow for egress traffic but the workload AWSCluster is configured with - // an internal load balancer and only the private subnet. All applicable resources are restricted to us-west-2a for simplicity. - ginkgo.PDescribe("External infrastructure, external security groups, VPC peering, internal ELB and private subnet use only", func() { - var namespace *corev1.Namespace - var requiredResources *shared.TestResource - specName := "functional-test-extinfra" - mgmtClusterName := fmt.Sprintf("%s-%s", specName, util.RandomString(6)) - mgmtClusterInfra := new(shared.AWSInfrastructure) - shared.SetEnvVar("MGMT_CLUSTER_NAME", mgmtClusterName, false) - - wlClusterName := fmt.Sprintf("%s-%s", specName, util.RandomString(6)) - wlClusterInfra := new(shared.AWSInfrastructure) - - var cPeering *types.VpcPeeringConnection - - // Some infrastructure creation was moved to a setup node to better organize the test. - ginkgo.JustBeforeEach(func() { - if !e2eCtx.Settings.SkipQuotas { - requiredResources = &shared.TestResource{EC2Normal: 2 * e2eCtx.Settings.InstanceVCPU, IGW: 2, NGW: 2, VPC: 2, ClassicLB: 2, EIP: 5, EventBridgeRules: 50} - requiredResources.WriteRequestedResources(e2eCtx, specName) - Expect(shared.AcquireResources(requiredResources, ginkgo.GinkgoParallelProcess(), flock.New(shared.ResourceQuotaFilePath))).To(Succeed()) - } - namespace = shared.SetupSpecNamespace(ctx, specName, e2eCtx) - ginkgo.By("Creating the management cluster infrastructure") - mgmtClusterInfra.New(shared.AWSInfrastructureSpec{ - ClusterName: mgmtClusterName, - VpcCidr: "10.0.0.0/23", - PublicSubnetCidr: "10.0.0.0/24", - PrivateSubnetCidr: "10.0.1.0/24", - AvailabilityZone: "us-west-2a", - }, e2eCtx) - mgmtClusterInfra.CreateInfrastructure() - - ginkgo.By("Creating the workload cluster infrastructure") - wlClusterInfra.New(shared.AWSInfrastructureSpec{ - ClusterName: wlClusterName, - VpcCidr: "10.0.2.0/23", - PublicSubnetCidr: "10.0.2.0/24", - PrivateSubnetCidr: "10.0.3.0/24", - AvailabilityZone: "us-west-2a", - }, e2eCtx) - wlClusterInfra.CreateInfrastructure() - - ginkgo.By("Creating VPC peerings") - cPeering, _ = shared.CreatePeering(e2eCtx, mgmtClusterName+"-"+wlClusterName, *mgmtClusterInfra.VPC.VpcId, *wlClusterInfra.VPC.VpcId) - }) - - // Infrastructure cleanup is done in setup node so it is not bypassed if there is a test failure in the subject node. - ginkgo.JustAfterEach(func() { - if !e2eCtx.Settings.SkipQuotas { - shared.ReleaseResources(requiredResources, ginkgo.GinkgoParallelProcess(), flock.New(shared.ResourceQuotaFilePath)) - } - shared.DumpSpecResourcesAndCleanup(ctx, "", namespace, e2eCtx) - if !e2eCtx.Settings.SkipCleanup { - ginkgo.By("Deleting peering connection") - if cPeering != nil && cPeering.VpcPeeringConnectionId != nil { - shared.DeletePeering(e2eCtx, *cPeering.VpcPeeringConnectionId) - } - ginkgo.By("Deleting the workload cluster infrastructure") - wlClusterInfra.DeleteInfrastructure(ctx) - ginkgo.By("Deleting the management cluster infrastructure") - mgmtClusterInfra.DeleteInfrastructure(ctx) - } - }) - - ginkgo.It("should create external clusters in peered VPC and with an internal ELB and only utilize a private subnet", func() { - ginkgo.By("Validating management infrastructure") - Expect(mgmtClusterInfra.VPC).NotTo(BeNil()) - Expect(*mgmtClusterInfra.State.VpcState).To(Equal("available")) - Expect(len(mgmtClusterInfra.Subnets)).To(Equal(2)) - Expect(mgmtClusterInfra.InternetGateway).NotTo(BeNil()) - Expect(mgmtClusterInfra.ElasticIP).NotTo(BeNil()) - Expect(mgmtClusterInfra.NatGateway).NotTo(BeNil()) - Expect(len(mgmtClusterInfra.RouteTables)).To(Equal(2)) - - ginkgo.By("Validating workload infrastructure") - Expect(wlClusterInfra.VPC).NotTo(BeNil()) - Expect(*wlClusterInfra.State.VpcState).To(Equal("available")) - Expect(len(wlClusterInfra.Subnets)).To(Equal(2)) - Expect(wlClusterInfra.InternetGateway).NotTo(BeNil()) - Expect(wlClusterInfra.ElasticIP).NotTo(BeNil()) - Expect(wlClusterInfra.NatGateway).NotTo(BeNil()) - Expect(len(wlClusterInfra.RouteTables)).To(Equal(2)) - - ginkgo.By("Validate and accept peering") - Expect(cPeering).NotTo(BeNil()) - Eventually(func() bool { - aPeering, err := shared.AcceptPeering(e2eCtx, *cPeering.VpcPeeringConnectionId) - if err != nil { - return false - } - wlClusterInfra.Peering = aPeering - return aPeering != nil - }, 60*time.Second).Should(BeTrue(), "Eventually failed waiting for peering to be accepted") - - ginkgo.By("Creating security groups") - mgmtSG, _ := shared.CreateSecurityGroup(e2eCtx, mgmtClusterName+"-all", mgmtClusterName+"-all", *mgmtClusterInfra.VPC.VpcId) - Expect(mgmtSG).NotTo(BeNil()) - shared.CreateSecurityGroupIngressRule(e2eCtx, *mgmtSG.GroupId, "all default", "0.0.0.0/0", "-1", -1, -1) - shared.SetEnvVar("SG_ID", *mgmtSG.GroupId, false) - - shared.SetEnvVar("MGMT_VPC_ID", *mgmtClusterInfra.VPC.VpcId, false) - shared.SetEnvVar("WL_VPC_ID", *wlClusterInfra.VPC.VpcId, false) - shared.SetEnvVar("MGMT_PUBLIC_SUBNET_ID", *mgmtClusterInfra.State.PublicSubnetID, false) - shared.SetEnvVar("MGMT_PRIVATE_SUBNET_ID", *mgmtClusterInfra.State.PrivateSubnetID, false) - shared.SetEnvVar("WL_PRIVATE_SUBNET_ID", *wlClusterInfra.State.PrivateSubnetID, false) - - ginkgo.By("Creating routes for peerings") - shared.CreateRoute(e2eCtx, *mgmtClusterInfra.State.PublicRouteTableID, "10.0.2.0/23", nil, nil, cPeering.VpcPeeringConnectionId) - shared.CreateRoute(e2eCtx, *mgmtClusterInfra.State.PrivateRouteTableID, "10.0.2.0/23", nil, nil, cPeering.VpcPeeringConnectionId) - shared.CreateRoute(e2eCtx, *wlClusterInfra.State.PublicRouteTableID, "10.0.0.0/23", nil, nil, cPeering.VpcPeeringConnectionId) - shared.CreateRoute(e2eCtx, *wlClusterInfra.State.PrivateRouteTableID, "10.0.0.0/23", nil, nil, cPeering.VpcPeeringConnectionId) - - ginkgo.By("Creating a management cluster in a peered VPC") - mgmtConfigCluster := defaultConfigCluster(mgmtClusterName, namespace.Name) - mgmtConfigCluster.WorkerMachineCount = ptr.To[int64](1) - mgmtConfigCluster.Flavor = "peered-remote" - mgmtCluster, mgmtMD, _ := createCluster(ctx, mgmtConfigCluster, result) - - mgmtWM := framework.GetMachinesByMachineDeployments(ctx, framework.GetMachinesByMachineDeploymentsInput{ - Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), - ClusterName: mgmtClusterName, - Namespace: namespace.Name, - MachineDeployment: *mgmtMD[0], - }) - mgmtCPM := framework.GetControlPlaneMachinesByCluster(ctx, framework.GetControlPlaneMachinesByClusterInput{ - Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), - ClusterName: mgmtClusterName, - Namespace: namespace.Name, - }) - Expect(len(mgmtWM)).To(Equal(1)) - Expect(len(mgmtCPM)).To(Equal(1)) - - mgmtClusterProxy := e2eCtx.Environment.BootstrapClusterProxy.GetWorkloadCluster(ctx, mgmtCluster.Namespace, mgmtCluster.Name) - - ginkgo.By(fmt.Sprintf("Creating a namespace for hosting the %s test spec", specName)) - mgmtNamespace := framework.CreateNamespace(ctx, framework.CreateNamespaceInput{ - Creator: mgmtClusterProxy.GetClient(), - Name: namespace.Name, - }) - - ginkgo.By("Initializing the management cluster") - clusterctl.InitManagementClusterAndWatchControllerLogs(ctx, clusterctl.InitManagementClusterAndWatchControllerLogsInput{ - ClusterProxy: mgmtClusterProxy, - ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, - InfrastructureProviders: e2eCtx.E2EConfig.InfrastructureProviders(), - LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", mgmtCluster.Name), - }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-controllers")...) - - ginkgo.By("Ensure API servers are stable before doing the move") - Consistently(func() error { - kubeSystem := &corev1.Namespace{} - return e2eCtx.Environment.BootstrapClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem) - }, "5s", "100ms").Should(BeNil(), "Failed to assert bootstrap API server stability") - Consistently(func() error { - kubeSystem := &corev1.Namespace{} - return mgmtClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem) - }, "5s", "100ms").Should(BeNil(), "Failed to assert management API server stability") - - ginkgo.By("Moving the management cluster to be self hosted") - clusterctl.Move(ctx, clusterctl.MoveInput{ - LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", "bootstrap"), - ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, - FromKubeconfigPath: e2eCtx.Environment.BootstrapClusterProxy.GetKubeconfigPath(), - ToKubeconfigPath: mgmtClusterProxy.GetKubeconfigPath(), - Namespace: namespace.Name, - }) - - mgmtCluster = framework.DiscoveryAndWaitForCluster(ctx, framework.DiscoveryAndWaitForClusterInput{ - Getter: mgmtClusterProxy.GetClient(), - Namespace: mgmtNamespace.Name, - Name: mgmtCluster.Name, - }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-cluster")...) - - mgmtControlPlane := framework.GetKubeadmControlPlaneByCluster(ctx, framework.GetKubeadmControlPlaneByClusterInput{ - Lister: mgmtClusterProxy.GetClient(), - ClusterName: mgmtCluster.Name, - Namespace: mgmtCluster.Namespace, - }) - Expect(mgmtControlPlane).ToNot(BeNil()) - - ginkgo.By("Creating a namespace to host the internal-elb spec") - wlNamespace := framework.CreateNamespace(ctx, framework.CreateNamespaceInput{ - Creator: mgmtClusterProxy.GetClient(), - Name: wlClusterName, - }) - - ginkgo.By("Creating workload cluster with internal ELB") - wlConfigCluster := defaultConfigCluster(wlClusterName, wlNamespace.Name) - wlConfigCluster.WorkerMachineCount = ptr.To[int64](1) - wlConfigCluster.Flavor = "internal-elb" - wlResult := &clusterctl.ApplyClusterTemplateAndWaitResult{} - clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{ - ClusterProxy: mgmtClusterProxy, - ConfigCluster: wlConfigCluster, - WaitForClusterIntervals: e2eCtx.E2EConfig.GetIntervals("", "wait-cluster"), - WaitForControlPlaneIntervals: e2eCtx.E2EConfig.GetIntervals("", "wait-control-plane"), - WaitForMachineDeployments: e2eCtx.E2EConfig.GetIntervals("", "wait-worker-nodes"), - }, wlResult) - - wlWM := framework.GetMachinesByMachineDeployments(ctx, framework.GetMachinesByMachineDeploymentsInput{ - Lister: mgmtClusterProxy.GetClient(), - ClusterName: mgmtClusterName, - Namespace: wlNamespace.Name, - MachineDeployment: *wlResult.MachineDeployments[0], - }) - wlCPM := framework.GetControlPlaneMachinesByCluster(ctx, framework.GetControlPlaneMachinesByClusterInput{ - Lister: mgmtClusterProxy.GetClient(), - ClusterName: wlClusterName, - Namespace: wlNamespace.Name, - }) - Expect(len(wlWM)).To(Equal(1)) - Expect(len(wlCPM)).To(Equal(1)) - - ginkgo.By("Deleting the workload cluster") - shared.DumpSpecResourcesFromProxy(ctx, e2eCtx, wlNamespace, mgmtClusterProxy) - shared.DumpMachinesFromProxy(ctx, e2eCtx, wlNamespace, mgmtClusterProxy) - if !e2eCtx.Settings.SkipCleanup { - framework.DeleteCluster(ctx, framework.DeleteClusterInput{ - Deleter: mgmtClusterProxy.GetClient(), - Cluster: wlResult.Cluster, - }) - - framework.WaitForClusterDeleted(ctx, framework.WaitForClusterDeletedInput{ - ClusterProxy: mgmtClusterProxy, - Cluster: wlResult.Cluster, - ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, - ArtifactFolder: e2eCtx.Settings.ArtifactFolder, - }, e2eCtx.E2EConfig.GetIntervals("", "wait-delete-cluster")...) - - ginkgo.By("Moving the management cluster back to bootstrap") - clusterctl.Move(ctx, clusterctl.MoveInput{ - LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", mgmtCluster.Name), - ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, - FromKubeconfigPath: mgmtClusterProxy.GetKubeconfigPath(), - ToKubeconfigPath: e2eCtx.Environment.BootstrapClusterProxy.GetKubeconfigPath(), - Namespace: namespace.Name, - }) - - mgmtCluster = framework.DiscoveryAndWaitForCluster(ctx, framework.DiscoveryAndWaitForClusterInput{ - Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), - Namespace: mgmtNamespace.Name, - Name: mgmtCluster.Name, - }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-cluster")...) - - mgmtControlPlane = framework.GetKubeadmControlPlaneByCluster(ctx, framework.GetKubeadmControlPlaneByClusterInput{ - Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), - ClusterName: mgmtCluster.Name, - Namespace: mgmtCluster.Namespace, - }) - Expect(mgmtControlPlane).ToNot(BeNil()) - - ginkgo.By("Deleting the management cluster") - deleteCluster(ctx, mgmtCluster) - } - }) - }) - ginkgo.Describe("Workload cluster with AWS S3 and Ignition parameter", func() { ginkgo.It("It should be creatable and deletable", func() { specName := "functional-test-ignition" @@ -993,73 +732,4 @@ var _ = ginkgo.Context("[unmanaged] [functional]", func() { }) }) - // NOTE: disabled whilst discussions happen on the costs. - ginkgo.PDescribe("Dedicated hosts cluster test", func() { - ginkgo.It("should create cluster with dedicated hosts", func() { - specName := "dedicated-host" - if !e2eCtx.Settings.SkipQuotas { - requiredResources = &shared.TestResource{EC2Normal: 1 * e2eCtx.Settings.InstanceVCPU, IGW: 1, NGW: 1, VPC: 1, ClassicLB: 1, EIP: 1, EventBridgeRules: 50} - requiredResources.WriteRequestedResources(e2eCtx, specName) - Expect(shared.AcquireResources(requiredResources, ginkgo.GinkgoParallelProcess(), flock.New(shared.ResourceQuotaFilePath))).To(Succeed()) - defer shared.ReleaseResources(requiredResources, ginkgo.GinkgoParallelProcess(), flock.New(shared.ResourceQuotaFilePath)) - } - namespace := shared.SetupSpecNamespace(ctx, specName, e2eCtx) - defer shared.DumpSpecResourcesAndCleanup(ctx, specName, namespace, e2eCtx) - - ginkgo.By("Allocating a dedicated host") - hostID, err := shared.AllocateHost(ctx, e2eCtx) - Expect(err).To(BeNil()) - Expect(hostID).NotTo(BeEmpty()) - ginkgo.By(fmt.Sprintf("Allocated dedicated host: %s", hostID)) - defer func() { - ginkgo.By(fmt.Sprintf("Releasing the dedicated host: %s", hostID)) - shared.ReleaseHost(ctx, e2eCtx, hostID) - }() - - ginkgo.By("Creating cluster") - clusterName := fmt.Sprintf("%s-%s", specName, util.RandomString(6)) - - // Create a cluster with a dedicated host - clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{ - ClusterProxy: e2eCtx.Environment.BootstrapClusterProxy, - ConfigCluster: clusterctl.ConfigClusterInput{ - LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName()), - ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, - KubeconfigPath: e2eCtx.Environment.BootstrapClusterProxy.GetKubeconfigPath(), - InfrastructureProvider: clusterctl.DefaultInfrastructureProvider, - Flavor: shared.DedicatedHostFlavor, - Namespace: namespace.Name, - ClusterName: clusterName, - KubernetesVersion: e2eCtx.E2EConfig.MustGetVariable(shared.KubernetesVersion), - ControlPlaneMachineCount: ptr.To[int64](1), - WorkerMachineCount: ptr.To[int64](0), - ClusterctlVariables: map[string]string{ - "HOST_ID": hostID, - "HOST_AFFINITY": "host", - }, - }, - WaitForClusterIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-cluster"), - WaitForControlPlaneIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-control-plane"), - }, result) - - workerMachines := result.MachineDeployments - mdName := fmt.Sprintf("%s-md-dh", clusterName) - var found *clusterv1.MachineDeployment - for _, md := range workerMachines { - if md.Name == mdName { - found = md - } - } - Expect(found).NotTo(BeNil(), fmt.Sprintf("Expected MachineDeployment %s to be found", mdName)) - machineList := getAWSMachinesForDeployment(namespace.Name, *found) - Expect(len(machineList.Items)).To(Equal(1), fmt.Sprintf("Expected one machine in MachineDeployment %s, but got %d", mdName, len(machineList.Items))) - machine := machineList.Items[0] - instanceID := *(machine.Spec.InstanceID) - ginkgo.By(fmt.Sprintf("Worker instance ID: %s", instanceID)) - instanceHostID := shared.GetHostID(ctx, e2eCtx, instanceID) - ginkgo.By(fmt.Sprintf("Worker instance host ID: %s", instanceHostID)) - Expect(instanceHostID).To(Equal(hostID), fmt.Sprintf("Expected instance to be on host %s, but got %s", hostID, instanceHostID)) - ginkgo.By("PASSED!") - }) - }) })