Skip to content

Commit

Permalink
tests, network, services: Refactor connectivity job calls
Browse files Browse the repository at this point in the history
Reduce the complexity of the connectivity job helpers and their usage.

Signed-off-by: Edward Haas <[email protected]>
  • Loading branch information
EdDev committed Feb 19, 2024
1 parent 1e75a49 commit 0cac943
Showing 1 changed file with 69 additions and 86 deletions.
155 changes: 69 additions & 86 deletions tests/network/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,16 @@ import (

const (
cleaningK8sv1ServiceShouldSucceed = "cleaning up the k8sv1.Service entity should have succeeded."
cleaningK8sv1JobFuncShouldExist = "a k8sv1.Job cleaning up function should exist"
cleaningK8sv1JobShouldSucceed = "cleaning up the k8sv1.Job entity should have succeeded."
expectConnectivityToExposedService = "connectivity is expected to the exposed service"

jobSuccessRetry = 3
jobFailureRetry = 0
)

var _ = SIGDescribe("Services", func() {
var virtClient kubecli.KubevirtClient

runTCPClientExpectingHelloWorldFromServer := func(host, port, namespace string, retries int32) *batchv1.Job {
job := job.NewHelloWorldJobTCP(host, port)
job.Spec.BackoffLimit = &retries
var err error
job, err = virtClient.BatchV1().Jobs(namespace).Create(context.Background(), job, k8smetav1.CreateOptions{})
ExpectWithOffset(1, err).ToNot(HaveOccurred())
return job
}

exposeExistingVMISpec := func(vmi *v1.VirtualMachineInstance, subdomain string, hostname string, selectorLabelKey string, selectorLabelValue string) *v1.VirtualMachineInstance {
vmi.Labels = map[string]string{selectorLabelKey: selectorLabelValue}
vmi.Spec.Subdomain = subdomain
Expand Down Expand Up @@ -98,39 +91,12 @@ var _ = SIGDescribe("Services", func() {
return virtClient.CoreV1().Services(namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})
}

assertConnectivityToService := func(serviceName, namespace string, servicePort int) (func() error, error) {
serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
tcpJob := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, 3)

By(fmt.Sprintf("waiting for the job to report a SUCCESSFUL connection attempt to service %s on port %d", serviceFQDN, servicePort))
err := job.WaitForJobToSucceed(tcpJob, 90*time.Second)
return func() error {
return virtClient.BatchV1().Jobs(util.NamespaceTestDefault).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})
}, err
}

assertNoConnectivityToService := func(serviceName, namespace string, servicePort int) (func() error, error) {
serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s", serviceFQDN))
tcpJob := runTCPClientExpectingHelloWorldFromServer(serviceFQDN, strconv.Itoa(servicePort), namespace, 0)

By(fmt.Sprintf("waiting for the job to report a FAILED connection attempt to service %s on port %d", serviceFQDN, servicePort))
err := job.WaitForJobToFail(tcpJob, 90*time.Second)
return func() error {
return virtClient.BatchV1().Jobs(util.NamespaceTestDefault).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})
}, err
}

BeforeEach(func() {
virtClient = kubevirt.Client()
})

Context("bridge interface binding", func() {
var inboundVMI *v1.VirtualMachineInstance
var serviceName string

const (
selectorLabelKey = "expose"
Expand Down Expand Up @@ -166,44 +132,49 @@ var _ = SIGDescribe("Services", func() {
})

Context("with a service matching the vmi exposed", func() {
var jobCleanup func() error
const serviceName = "myservice"

BeforeEach(func() {
serviceName = "myservice"

service := netservice.BuildSpec(serviceName, servicePort, servicePort, selectorLabelKey, selectorLabelValue)
_, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
serv, err := virtClient.CoreV1().Services(inboundVMI.Namespace).Create(context.Background(), service, k8smetav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
})

AfterEach(func() {
Expect(cleanupService(inboundVMI.GetNamespace(), serviceName)).To(Succeed(), cleaningK8sv1ServiceShouldSucceed)
})

AfterEach(func() {
Expect(jobCleanup).NotTo(BeNil(), cleaningK8sv1JobFuncShouldExist)
Expect(jobCleanup()).To(Succeed(), cleaningK8sv1JobShouldSucceed)
jobCleanup = nil
DeferCleanup(func() {
err := virtClient.CoreV1().Services(serv.Namespace).Delete(context.Background(), serv.Name, k8smetav1.DeleteOptions{})
Expect(err).To(SatisfyAny(
Not(HaveOccurred()),
MatchError(errors.IsNotFound, "does not exist"),
), cleaningK8sv1ServiceShouldSucceed)
})
})

It("[test_id:1547] should be able to reach the vmi based on labels specified on the vmi", func() {
var err error
tcpJob, err := createServiceConnectivityJob(serviceName, inboundVMI.Namespace, servicePort, jobSuccessRetry)
Expect(err).NotTo(HaveOccurred())
DeferCleanup(func() {
Expect(virtClient.BatchV1().Jobs(tcpJob.Namespace).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})).To(Succeed())
})

jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort)
Expect(err).NotTo(HaveOccurred(), expectConnectivityToExposedService)
Expect(job.WaitForJobToSucceed(tcpJob, 90*time.Second)).To(Succeed(), expectConnectivityToExposedService)
})

It("[test_id:1548] should fail to reach the vmi if an invalid servicename is used", func() {
var err error
tcpJob, err := createServiceConnectivityJob("wrongservice", inboundVMI.Namespace, servicePort, jobFailureRetry)
Expect(err).NotTo(HaveOccurred())
DeferCleanup(func() {
err := virtClient.BatchV1().Jobs(tcpJob.Namespace).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})
Expect(err).To(SatisfyAny(
Not(HaveOccurred()),
MatchError(errors.IsNotFound, "does not exist"),
))
})

jobCleanup, err = assertNoConnectivityToService("wrongservice", inboundVMI.Namespace, servicePort)
err = job.WaitForJobToFail(tcpJob, 90*time.Second)
Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
})
})

Context("with a subdomain and a headless service given", func() {
var jobCleanup func() error

var serviceName string
BeforeEach(func() {
serviceName = inboundVMI.Spec.Subdomain

Expand All @@ -216,16 +187,20 @@ var _ = SIGDescribe("Services", func() {
Expect(virtClient.CoreV1().Services(inboundVMI.Namespace).Delete(context.Background(), serviceName, k8smetav1.DeleteOptions{})).To(Succeed())
})

AfterEach(func() {
Expect(jobCleanup()).To(Succeed(), cleaningK8sv1ServiceShouldSucceed)
})

It("[test_id:1549]should be able to reach the vmi via its unique fully qualified domain name", func() {
var err error
serviceHostnameWithSubdomain := fmt.Sprintf("%s.%s", inboundVMI.Spec.Hostname, inboundVMI.Spec.Subdomain)

jobCleanup, err = assertConnectivityToService(serviceHostnameWithSubdomain, inboundVMI.Namespace, servicePort)
Expect(err).NotTo(HaveOccurred(), expectConnectivityToExposedService)
tcpJob, err := createServiceConnectivityJob(serviceHostnameWithSubdomain, inboundVMI.Namespace, servicePort, jobSuccessRetry)
Expect(err).NotTo(HaveOccurred())
DeferCleanup(func() {
Expect(virtClient.BatchV1().Jobs(tcpJob.Namespace).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})).To(
Succeed(),
cleaningK8sv1JobShouldSucceed,
)
})

Expect(job.WaitForJobToSucceed(tcpJob, 90*time.Second)).To(Succeed(), expectConnectivityToExposedService)
})
})
})
Expand Down Expand Up @@ -262,15 +237,8 @@ var _ = SIGDescribe("Services", func() {
})

Context("with a service matching the vmi exposed", func() {
var jobCleanup func() error
var service *k8sv1.Service

AfterEach(func() {
Expect(jobCleanup).NotTo(BeNil(), cleaningK8sv1JobFuncShouldExist)
Expect(jobCleanup()).To(Succeed(), cleaningK8sv1JobShouldSucceed)
jobCleanup = nil
})

AfterEach(func() {
Expect(cleanupService(inboundVMI.GetNamespace(), service.Name)).To(Succeed(), cleaningK8sv1ServiceShouldSucceed)
})
Expand All @@ -291,33 +259,48 @@ var _ = SIGDescribe("Services", func() {
})

By("checking connectivity the exposed service")
var err error
tcpJob, err := createServiceConnectivityJob(serviceName, inboundVMI.Namespace, servicePort, jobSuccessRetry)
Expect(err).NotTo(HaveOccurred())
DeferCleanup(func() {
err := virtClient.BatchV1().Jobs(tcpJob.Namespace).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})
Expect(err).To(SatisfyAny(
Not(HaveOccurred()),
MatchError(errors.IsNotFound, "does not exist"),
), cleaningK8sv1JobShouldSucceed)
})

jobCleanup, err = assertConnectivityToService(serviceName, inboundVMI.Namespace, servicePort)
Expect(err).NotTo(HaveOccurred(), expectConnectivityToExposedService)
Expect(job.WaitForJobToSucceed(tcpJob, 90*time.Second)).To(Succeed(), expectConnectivityToExposedService)
},
Entry("when the service is exposed by an IPv4 address.", k8sv1.IPv4Protocol),
Entry("when the service is exposed by an IPv6 address.", k8sv1.IPv6Protocol),
)
})

Context("*without* a service matching the vmi exposed", func() {
var jobCleanup func() error
var serviceName string

AfterEach(func() {
Expect(jobCleanup).NotTo(BeNil(), cleaningK8sv1JobFuncShouldExist)
Expect(jobCleanup()).To(Succeed(), cleaningK8sv1JobShouldSucceed)
jobCleanup = nil
})

It("should fail to reach the vmi", func() {
var err error
serviceName = "missingservice"
tcpJob, err := createServiceConnectivityJob("missingservice", inboundVMI.Namespace, servicePort, jobFailureRetry)
Expect(err).NotTo(HaveOccurred())

DeferCleanup(func() {
err := virtClient.BatchV1().Jobs(tcpJob.Namespace).Delete(context.Background(), tcpJob.Name, k8smetav1.DeleteOptions{})
Expect(err).To(SatisfyAny(
Not(HaveOccurred()),
MatchError(errors.IsNotFound, "does not exist"),
))
})

jobCleanup, err = assertNoConnectivityToService(serviceName, inboundVMI.Namespace, servicePort)
err = job.WaitForJobToFail(tcpJob, 90*time.Second)
Expect(err).NotTo(HaveOccurred(), "connectivity is *not* expected, since there isn't an exposed service")
})
})
})
})

func createServiceConnectivityJob(serviceName, namespace string, servicePort int, retries int32) (*batchv1.Job, error) {
serviceFQDN := fmt.Sprintf("%s.%s", serviceName, namespace)

By(fmt.Sprintf("starting a job which tries to reach the vmi via service %s, on port %d", serviceFQDN, servicePort))
tcpJob := job.NewHelloWorldJobTCP(serviceFQDN, strconv.Itoa(servicePort))
tcpJob.Spec.BackoffLimit = &retries
return kubevirt.Client().BatchV1().Jobs(namespace).Create(context.Background(), tcpJob, k8smetav1.CreateOptions{})
}

0 comments on commit 0cac943

Please sign in to comment.