Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Centralize the way the sample apps yaml are being set to be deployed #483

Merged
merged 4 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/e2e/controlplane/control_plane_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var (
istioCniName = env.Get("ISTIOCNI_NAME", "default")
skipDeploy = env.GetBool("SKIP_DEPLOY", false)
expectedRegistry = env.Get("EXPECTED_REGISTRY", "^docker\\.io|^gcr\\.io")
bookinfoNamespace = env.Get("BOOKINFO_NAMESPACE", "bookinfo")
sampleNamespace = env.Get("SAMPLE_NAMESPACE", "sample")
multicluster = env.GetBool("MULTICLUSTER", false)
ipFamily = env.Get("IP_FAMILY", "ipv4")

Expand Down
63 changes: 25 additions & 38 deletions tests/e2e/controlplane/control_plane_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,41 +221,49 @@ spec:
})
})

When("bookinfo is deployed", func() {
When("sample pod is deployed", func() {
BeforeAll(func() {
Expect(k.CreateNamespace(bookinfoNamespace)).To(Succeed(), "Bookinfo namespace failed to be created")
Expect(k.Patch("namespace", bookinfoNamespace, "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching bookinfo namespace")
Expect(deployBookinfo(version)).To(Succeed(), "Error deploying bookinfo")
Success("Bookinfo deployed")
Expect(k.CreateNamespace(sampleNamespace)).To(Succeed(), "Sample namespace failed to be created")
Expect(k.Patch("namespace", sampleNamespace, "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")
Expect(k.WithNamespace(sampleNamespace).
ApplyWithLabels(common.GetYAMLPodURL(version, sampleNamespace), "version=v1")).
To(Succeed(), "Error deploying sample")
Success("sample deployed")
})

bookinfoPods := &corev1.PodList{}
samplePods := &corev1.PodList{}

It("updates the pods status to Running", func(ctx SpecContext) {
Expect(cl.List(ctx, bookinfoPods, client.InNamespace(bookinfoNamespace))).To(Succeed())
Expect(bookinfoPods.Items).ToNot(BeEmpty(), "No pods found in bookinfo namespace")
Eventually(func() bool {
// Wait until the sample pod exists. Is wraped inside a function to avoid failure on the first iteration
Expect(cl.List(ctx, samplePods, client.InNamespace(sampleNamespace))).To(Succeed())
return len(samplePods.Items) > 0
}).Should(BeTrue(), "No sample pods found")

for _, pod := range bookinfoPods.Items {
Eventually(common.GetObject).WithArguments(ctx, cl, kube.Key(pod.Name, bookinfoNamespace), &corev1.Pod{}).
Expect(cl.List(ctx, samplePods, client.InNamespace(sampleNamespace))).To(Succeed())
Expect(samplePods.Items).ToNot(BeEmpty(), "No pods found in sample namespace")

for _, pod := range samplePods.Items {
Eventually(common.GetObject).WithArguments(ctx, cl, kube.Key(pod.Name, sampleNamespace), &corev1.Pod{}).
Should(HaveCondition(corev1.PodReady, metav1.ConditionTrue), "Pod is not Ready")
}
Success("Bookinfo pods are ready")
Success("sample pods are ready")
})

It("has sidecars with the correct istio version", func(ctx SpecContext) {
for _, pod := range bookinfoPods.Items {
sidecarVersion, err := getProxyVersion(pod.Name, bookinfoNamespace)
for _, pod := range samplePods.Items {
sidecarVersion, err := getProxyVersion(pod.Name, sampleNamespace)
Expect(err).NotTo(HaveOccurred(), "Error getting sidecar version")
Expect(sidecarVersion).To(Equal(version.Version), "Sidecar Istio version does not match the expected version")
}
Success("Istio sidecar version matches the expected Istio version")
})

AfterAll(func(ctx SpecContext) {
By("Deleting bookinfo")
Expect(k.DeleteNamespace(bookinfoNamespace)).To(Succeed(), "Bookinfo namespace failed to be deleted")
Success("Bookinfo deleted")
By("Deleting sample")
Expect(k.DeleteNamespace(sampleNamespace)).To(Succeed(), "sample namespace failed to be deleted")
Success("sample deleted")
})
})

Expand Down Expand Up @@ -368,27 +376,6 @@ func forceDeleteIstioResources() error {
return nil
}

func getBookinfoURL(version supportedversion.VersionInfo) string {
// Bookinfo YAML for the current version can be found from istio/istio repository
// If the version is latest, we need to get the latest version from the master branch
bookinfoURL := fmt.Sprintf("https://raw.githubusercontent.com/istio/istio/%s/samples/bookinfo/platform/kube/bookinfo.yaml", version.Version)
if version.Name == "latest" {
bookinfoURL = "https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml"
}

return bookinfoURL
}

func deployBookinfo(version supportedversion.VersionInfo) error {
bookinfoURL := getBookinfoURL(version)
err := k.WithNamespace(bookinfoNamespace).Apply(bookinfoURL)
if err != nil {
return fmt.Errorf("error deploying bookinfo: %w", err)
}

return nil
}

func getProxyVersion(podName, namespace string) (*semver.Version, error) {
output, err := k.WithNamespace(namespace).Exec(
podName,
Expand Down
31 changes: 4 additions & 27 deletions tests/e2e/dualstack/dualstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ spec:
Expect(k.Patch("namespace", SleepNamespace, "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sleep namespace")

Expect(k.WithNamespace(DualStackNamespace).Apply(getYAMLPodURL(version, DualStackNamespace))).To(Succeed(), "error deploying tcpDualStack pod")
Expect(k.WithNamespace(IPv4Namespace).Apply(getYAMLPodURL(version, IPv4Namespace))).To(Succeed(), "error deploying ipv4 pod")
Expect(k.WithNamespace(IPv6Namespace).Apply(getYAMLPodURL(version, IPv6Namespace))).To(Succeed(), "error deploying ipv6 pod")
Expect(k.WithNamespace(SleepNamespace).Apply(getYAMLPodURL(version, SleepNamespace))).To(Succeed(), "error deploying sleep pod")
Expect(k.WithNamespace(DualStackNamespace).Apply(common.GetYAMLPodURL(version, "tcp-echo-dual-stack"))).To(Succeed(), "error deploying tcpDualStack pod")
Expect(k.WithNamespace(IPv4Namespace).Apply(common.GetYAMLPodURL(version, "tcp-echo-ipv4"))).To(Succeed(), "error deploying ipv4 pod")
Expect(k.WithNamespace(IPv6Namespace).Apply(common.GetYAMLPodURL(version, "tcp-echo-ipv6"))).To(Succeed(), "error deploying ipv6 pod")
Expect(k.WithNamespace(SleepNamespace).Apply(common.GetYAMLPodURL(version, "sleep"))).To(Succeed(), "error deploying sleep pod")

Success("dualStack validation pods deployed")
})
Expand Down Expand Up @@ -323,29 +323,6 @@ func getEnvVars(container corev1.Container) []corev1.EnvVar {
return container.Env
}

func getYAMLPodURL(version supportedversion.VersionInfo, namespace string) string {
var url string

switch namespace {
case DualStackNamespace:
url = "samples/tcp-echo/tcp-echo-dual-stack.yaml"
case IPv4Namespace:
url = "samples/tcp-echo/tcp-echo-ipv4.yaml"
case IPv6Namespace:
url = "samples/tcp-echo/tcp-echo-ipv6.yaml"
case SleepNamespace:
url = "samples/sleep/sleep.yaml"
default:
return ""
}

if version.Name == "latest" {
return fmt.Sprintf("https://raw.githubusercontent.com/istio/istio/master/%s", url)
}

return fmt.Sprintf("https://raw.githubusercontent.com/istio/istio/%s/%s", version.Version, url)
}

func checkPodConnectivity(podName, namespace, echoStr string) {
command := fmt.Sprintf(`sh -c 'echo %s | nc tcp-echo.%s 9000'`, echoStr, echoStr)
response, err := k.WithNamespace(namespace).Exec(podName, "sleep", command)
Expand Down
56 changes: 24 additions & 32 deletions tests/e2e/multicluster/multicluster_multiprimary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,37 @@ spec:

When("sample apps are deployed in both clusters", func() {
BeforeAll(func(ctx SpecContext) {
// Create the namespace
Expect(k1.CreateNamespace("sample")).To(Succeed(), "Namespace failed to be created")
Expect(k2.CreateNamespace("sample")).To(Succeed(), "Namespace failed to be created")

// Label the sample namespace
Expect(k1.Patch("namespace", "sample", "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")
Expect(k2.Patch("namespace", "sample", "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")

// Deploy the sample app in both clusters
deploySampleApp("sample", version)
helloWorldURL := common.GetYAMLPodURL(version, "helloworld")
sleepURL := common.GetYAMLPodURL(version, "sleep")

// On Cluster 0, create a service for the helloworld app v1
Expect(k1.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k1.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "version=v1")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k1.WithNamespace("sample").Apply(sleepURL)).To(Succeed(), "Failed to deploy sleep service")

// On Cluster 1, create a service for the helloworld app v2
Expect(k2.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k2.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "version=v2")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k2.WithNamespace("sample").Apply(sleepURL)).To(Succeed(), "Failed to deploy sleep service")
Success("Sample app is deployed in both clusters")
})

It("updates the pods status to Ready", func(ctx SpecContext) {
samplePodsCluster1 := &corev1.PodList{}

Expect(clPrimary.List(ctx, samplePodsCluster1, client.InNamespace("sample"))).To(Succeed())
Expect(samplePodsCluster1.Items).ToNot(BeEmpty(), "No pods found in bookinfo namespace")
Expect(samplePodsCluster1.Items).ToNot(BeEmpty(), "No pods found in sample namespace")

for _, pod := range samplePodsCluster1.Items {
Eventually(common.GetObject).
Expand All @@ -217,7 +238,7 @@ spec:

samplePodsCluster2 := &corev1.PodList{}
Expect(clRemote.List(ctx, samplePodsCluster2, client.InNamespace("sample"))).To(Succeed())
Expect(samplePodsCluster2.Items).ToNot(BeEmpty(), "No pods found in bookinfo namespace")
Expect(samplePodsCluster2.Items).ToNot(BeEmpty(), "No pods found in sample namespace")

for _, pod := range samplePodsCluster2.Items {
Eventually(common.GetObject).
Expand Down Expand Up @@ -290,32 +311,3 @@ spec:
Expect(k2.WaitNamespaceDeleted(namespace)).To(Succeed())
})
})

// deploySampleApp deploys the sample app in the given cluster
func deploySampleApp(ns string, istioVersion supportedversion.VersionInfo) {
// Create the namespace
Expect(k1.CreateNamespace(ns)).To(Succeed(), "Namespace failed to be created")
Expect(k2.CreateNamespace(ns)).To(Succeed(), "Namespace failed to be created")

// Label the namespace
Expect(k1.Patch("namespace", ns, "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")
Expect(k2.Patch("namespace", ns, "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")

version := istioVersion.Version.String()
// Deploy the sample app from upstream URL in both clusters
if istioVersion.Name == "latest" {
version = "master"
}
helloWorldURL := fmt.Sprintf("https://raw.githubusercontent.com/istio/istio/%s/samples/helloworld/helloworld.yaml", version)
Expect(k1.WithNamespace(ns).ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Sample service deploy failed on Cluster #1")
Expect(k2.WithNamespace(ns).ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Sample service deploy failed on Cluster #2")

Expect(k1.WithNamespace(ns).ApplyWithLabels(helloWorldURL, "version=v1")).To(Succeed(), "Sample service deploy failed on Cluster #1")
Expect(k2.WithNamespace(ns).ApplyWithLabels(helloWorldURL, "version=v2")).To(Succeed(), "Sample service deploy failed on Cluster #2")

sleepURL := fmt.Sprintf("https://raw.githubusercontent.com/istio/istio/%s/samples/sleep/sleep.yaml", version)
Expect(k1.WithNamespace(ns).Apply(sleepURL)).To(Succeed(), "Sample sleep deploy failed on Cluster #1")
Expect(k2.WithNamespace(ns).Apply(sleepURL)).To(Succeed(), "Sample sleep deploy failed on Cluster #2")
}
27 changes: 24 additions & 3 deletions tests/e2e/multicluster/multicluster_primaryremote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,37 @@ spec:

When("sample apps are deployed in both clusters", func() {
BeforeAll(func(ctx SpecContext) {
// Create the namespace
Expect(k1.CreateNamespace("sample")).To(Succeed(), "Namespace failed to be created")
Expect(k2.CreateNamespace("sample")).To(Succeed(), "Namespace failed to be created")

// Label the sample namespace
Expect(k1.Patch("namespace", "sample", "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")
Expect(k2.Patch("namespace", "sample", "merge", `{"metadata":{"labels":{"istio-injection":"enabled"}}}`)).
To(Succeed(), "Error patching sample namespace")

// Deploy the sample app in both clusters
deploySampleApp("sample", v)
helloWorldURL := common.GetYAMLPodURL(v, "helloworld")
sleepURL := common.GetYAMLPodURL(v, "sleep")

// On Cluster 0, create a service for the helloworld app v1
Expect(k1.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k1.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "version=v1")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k1.WithNamespace("sample").Apply(sleepURL)).To(Succeed(), "Failed to deploy sleep service")

// On Cluster 1, create a service for the helloworld app v2
Expect(k2.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "service=helloworld")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k2.WithNamespace("sample").ApplyWithLabels(helloWorldURL, "version=v2")).To(Succeed(), "Failed to deploy helloworld service")
Expect(k2.WithNamespace("sample").Apply(sleepURL)).To(Succeed(), "Failed to deploy sleep service")
Success("Sample app is deployed in both clusters")
})

It("updates the pods status to Ready", func(ctx SpecContext) {
samplePodsPrimary := &corev1.PodList{}

Expect(clPrimary.List(ctx, samplePodsPrimary, client.InNamespace("sample"))).To(Succeed())
Expect(samplePodsPrimary.Items).ToNot(BeEmpty(), "No pods found in bookinfo namespace")
Expect(samplePodsPrimary.Items).ToNot(BeEmpty(), "No pods found in sample namespace")

for _, pod := range samplePodsPrimary.Items {
Eventually(common.GetObject).
Expand All @@ -264,7 +285,7 @@ spec:

samplePodsRemote := &corev1.PodList{}
Expect(clRemote.List(ctx, samplePodsRemote, client.InNamespace("sample"))).To(Succeed())
Expect(samplePodsRemote.Items).ToNot(BeEmpty(), "No pods found in bookinfo namespace")
Expect(samplePodsRemote.Items).ToNot(BeEmpty(), "No pods found in sample namespace")

for _, pod := range samplePodsRemote.Items {
Eventually(common.GetObject).
Expand Down
59 changes: 59 additions & 0 deletions tests/e2e/util/common/e2e_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package common
import (
"context"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
Expand All @@ -27,6 +28,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/istio-ecosystem/sail-operator/pkg/kube"
"github.com/istio-ecosystem/sail-operator/pkg/test/project"
"github.com/istio-ecosystem/sail-operator/pkg/test/util/supportedversion"
"github.com/istio-ecosystem/sail-operator/tests/e2e/util/env"
. "github.com/istio-ecosystem/sail-operator/tests/e2e/util/gomega"
"github.com/istio-ecosystem/sail-operator/tests/e2e/util/helm"
Expand Down Expand Up @@ -261,3 +263,60 @@ func InstallOperatorViaHelm(extraArgs ...string) error {
func UninstallOperator() error {
return helm.Uninstall("sail-operator", "--namespace", OperatorNamespace)
}

// GetYAMLPodURL returns the URL of the yaml file for the testing app.
// args:
// version: the version of the Istio to get the yaml file from.
// appName: the name of the testing app. Example: helloworld, sleep, tcp-echo.
func GetYAMLPodURL(version supportedversion.VersionInfo, appName string) string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it was called that before, but GetYAMLPodURL is a strange name for this func. Isn't GetSampleYAML more adequate? Not sure what the pod has to do with this?

// This func will be used to get URLs for the yaml files of the testing apps. Example: helloworld, sleep, tcp-echo.
// Default values points to upstream Istio sample yaml files. Custom paths can be provided using environment variables.

// Define environment variables for specific apps
envVarMap := map[string]string{
"tcp-echo-dual-stack": "TCP_ECHO_DUAL_STACK_YAML_PATH",
"tcp-echo-ipv4": "TCP_ECHO_IPV4_YAML_PATH",
"tcp-echo": "TCP_ECHO_IPV4_YAML_PATH",
"tcp-echo-ipv6": "TCP_ECHO_IPV6_YAML_PATH",
"sleep": "SLEEP_YAML_PATH",
"helloworld": "HELLOWORLD_YAML_PATH",
"sample": "HELLOWORLD_YAML_PATH",
}

// Check if there's a custom path for the given appName
if envVar, exists := envVarMap[appName]; exists {
customPath := os.Getenv(envVar)
if customPath != "" {
return customPath
}
}

// Default paths if no custom path is provided
var url string
switch appName {
case "tcp-echo-dual-stack":
url = "samples/tcp-echo/tcp-echo-dual-stack.yaml"
case "tcp-echo-ipv4", "tcp-echo":
url = "samples/tcp-echo/tcp-echo-ipv4.yaml"
case "tcp-echo-ipv6":
url = "samples/tcp-echo/tcp-echo-ipv6.yaml"
case "sleep":
url = "samples/sleep/sleep.yaml"
case "helloworld", "sample":
url = "samples/helloworld/helloworld.yaml"
default:
return ""
}

// Base URL logic
baseURL := os.Getenv("POD_SAMPLE_YAML_BASE_URL")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean, that if I'm setting a custom "baseURL" based on the env var, the path for the yaml files should be identical to the mentioned in lines 279-290?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll improve this to be able to set the full path

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaxBab take a look, I think the best way is to set each yaml individually. With this, wdyt?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fjglira

Cool!
I like this approach.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the POD prefix?

if baseURL == "" {
baseURL = "https://raw.githubusercontent.com/istio/istio"
}

if version.Name == "latest" {
return fmt.Sprintf("%s/master/%s", baseURL, url)
}

return fmt.Sprintf("%s/%s/%s", baseURL, version.Version, url)
}