Skip to content

Commit

Permalink
test: Move Bookinfo Demo to a separate test suite
Browse files Browse the repository at this point in the history
Same motivation as in the previous commit.

Signed-off-by: Martynas Pumputis <m@lambda.lt>
  • Loading branch information
brb authored and jibi committed Jun 21, 2021
1 parent 412e299 commit d3dd7e8
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 165 deletions.
165 changes: 0 additions & 165 deletions test/k8sT/Services.go
Original file line number Diff line number Diff line change
Expand Up @@ -1708,169 +1708,4 @@ Secondary Interface %s :: IPv4: (%s, %s), IPv6: (%s, %s)`, helpers.DualStackSupp
validateEgressAfterDeletion(kubectl)
})
})

SkipContextIf(func() bool { return helpers.IsIntegration(helpers.CIIntegrationEKS) }, "Bookinfo Demo", func() {

var (
bookinfoV1YAML, bookinfoV2YAML string
resourceYAMLs []string
policyPath string
)

BeforeAll(func() {
DeployCiliumAndDNS(kubectl, ciliumFilename)

bookinfoV1YAML = helpers.ManifestGet(kubectl.BasePath(), "bookinfo-v1.yaml")
bookinfoV2YAML = helpers.ManifestGet(kubectl.BasePath(), "bookinfo-v2.yaml")
policyPath = helpers.ManifestGet(kubectl.BasePath(), "cnp-specs.yaml")

resourceYAMLs = []string{bookinfoV1YAML, bookinfoV2YAML}

for _, resourcePath := range resourceYAMLs {
By("Creating objects in file %q", resourcePath)
res := kubectl.Create(resourcePath)
res.ExpectSuccess("unable to create resource %q", resourcePath)
}

By("Waiting for pods to be ready")
err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=bookinfo", helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Pods are not ready after timeout")
})

AfterAll(func() {

// Explicitly do not check result to avoid having assertions in AfterAll.
_ = kubectl.Delete(policyPath)

for _, resourcePath := range resourceYAMLs {
By("Deleting resource %s", resourcePath)
// Explicitly do not check result to avoid having assertions in AfterAll.
_ = kubectl.Delete(resourcePath)
}
})

It("Tests bookinfo demo", func() {

// We use wget in this test because the Istio apps do not provide curl.
wgetCommand := fmt.Sprintf("wget --tries=2 --connect-timeout %d", helpers.CurlConnectTimeout)

version := "version"
v1 := "v1"

productPage := "productpage"
reviews := "reviews"
ratings := "ratings"
details := "details"
dnsChecks := []string{productPage, reviews, ratings, details}
app := "app"
health := "health"
ratingsPath := "ratings/0"

apiPort := "9080"

podNameFilter := "{.items[*].metadata.name}"

// shouldConnect asserts that srcPod can connect to dst.
shouldConnect := func(srcPod, dst string) {
By("Checking that %q can connect to %q", srcPod, dst)
res := kubectl.ExecPodCmd(
helpers.DefaultNamespace, srcPod, fmt.Sprintf("%s %s", wgetCommand, dst))
res.ExpectSuccess("Unable to connect from %q to %q", srcPod, dst)
}

// shouldNotConnect asserts that srcPod cannot connect to dst.
shouldNotConnect := func(srcPod, dst string) {
By("Checking that %q cannot connect to %q", srcPod, dst)
res := kubectl.ExecPodCmd(
helpers.DefaultNamespace, srcPod, fmt.Sprintf("%s %s", wgetCommand, dst))
res.ExpectFail("Was able to connect from %q to %q, but expected no connection: %s", srcPod, dst, res.CombineOutput())
}

// formatLabelArgument formats the provided key-value pairs as labels for use in
// querying Kubernetes.
formatLabelArgument := func(firstKey, firstValue string, nextLabels ...string) string {
baseString := fmt.Sprintf("-l %s=%s", firstKey, firstValue)
if nextLabels == nil {
return baseString
} else if len(nextLabels)%2 != 0 {
Fail("must provide even number of arguments for label key-value pairings")
} else {
for i := 0; i < len(nextLabels); i += 2 {
baseString = fmt.Sprintf("%s,%s=%s", baseString, nextLabels[i], nextLabels[i+1])
}
}
return baseString
}

// formatAPI is a helper function which formats a URI to access.
formatAPI := func(service, port, resource string) string {
target := fmt.Sprintf(
"%s.%s.svc.cluster.local:%s",
service, helpers.DefaultNamespace, port)
if resource != "" {
return fmt.Sprintf("%s/%s", target, resource)
}
return target
}

err := kubectl.CiliumEndpointWaitReady()
ExpectWithOffset(1, err).To(BeNil(), "Endpoints are not ready after timeout")

By("Waiting for services to be ready")
for _, service := range []string{details, ratings, reviews, productPage} {
err = kubectl.WaitForServiceEndpoints(
helpers.DefaultNamespace, "", service,
helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Service %q is not ready after timeout", service)
}
By("Validating DNS without Policy")
for _, name := range dnsChecks {
err = kubectl.WaitForKubeDNSEntry(name, helpers.DefaultNamespace)
Expect(err).To(BeNil(), "DNS entry is not ready after timeout")
}

By("All pods should be able to connect without policy")

reviewsPodV1, err := kubectl.GetPods(helpers.DefaultNamespace, formatLabelArgument(app, reviews, version, v1)).Filter(podNameFilter)
Expect(err).Should(BeNil(), "cannot get reviewsV1 pods")
productpagePodV1, err := kubectl.GetPods(helpers.DefaultNamespace, formatLabelArgument(app, productPage, version, v1)).Filter(podNameFilter)
Expect(err).Should(BeNil(), "cannot get productpageV1 pods")

shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, health))
shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

shouldConnect(productpagePodV1.String(), formatAPI(details, apiPort, health))
shouldConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, health))
shouldConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

policyCmd := "cilium policy get io.cilium.k8s.policy.name=cnp-specs"

By("Importing policy")

_, err = kubectl.CiliumPolicyAction(helpers.DefaultNamespace, policyPath, helpers.KubectlCreate, helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Error creating policy %q", policyPath)

By("Checking that policies were correctly imported into Cilium")

ciliumPodK8s1, err := kubectl.GetCiliumPodOnNode(helpers.K8s1)
Expect(err).Should(BeNil(), "Cannot get cilium pod on k8s1")
res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPodK8s1, policyCmd)
res.ExpectSuccess("Policy %s is not imported", policyCmd)

By("Validating DNS with Policy loaded")
for _, name := range dnsChecks {
err = kubectl.WaitForKubeDNSEntry(name, helpers.DefaultNamespace)
Expect(err).To(BeNil(), "DNS entry is not ready after timeout")
}

By("After policy import")
shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, health))
shouldNotConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

shouldConnect(productpagePodV1.String(), formatAPI(details, apiPort, health))

shouldNotConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, health))
shouldNotConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, ratingsPath))
})
})
})
216 changes: 216 additions & 0 deletions test/k8sT/bookinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// Copyright 2017-2021 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
"fmt"

. "github.com/cilium/cilium/test/ginkgo-ext"
"github.com/cilium/cilium/test/helpers"

. "github.com/onsi/gomega"
)

// The 5.4 CI job is intended to catch BPF complexity regressions and as such
// doesn't need to execute this test suite.
var _ = SkipDescribeIf(helpers.RunsOn54Kernel, "K8sBookInfoDemoTest", func() {
var (
kubectl *helpers.Kubectl
ciliumFilename string
)

BeforeAll(func() {
kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
ciliumFilename = helpers.TimestampFilename("cilium.yaml")
})

JustAfterEach(func() {
kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration)
})

AfterEach(func() {
ExpectAllPodsTerminated(kubectl)
})

AfterAll(func() {
UninstallCiliumFromManifest(kubectl, ciliumFilename)
kubectl.CloseSSHClient()
})

SkipContextIf(func() bool { return helpers.IsIntegration(helpers.CIIntegrationEKS) }, "Bookinfo Demo", func() {
var (
bookinfoV1YAML, bookinfoV2YAML string
resourceYAMLs []string
policyPath string
)

BeforeAll(func() {
DeployCiliumAndDNS(kubectl, ciliumFilename)

bookinfoV1YAML = helpers.ManifestGet(kubectl.BasePath(), "bookinfo-v1.yaml")
bookinfoV2YAML = helpers.ManifestGet(kubectl.BasePath(), "bookinfo-v2.yaml")
policyPath = helpers.ManifestGet(kubectl.BasePath(), "cnp-specs.yaml")

resourceYAMLs = []string{bookinfoV1YAML, bookinfoV2YAML}

for _, resourcePath := range resourceYAMLs {
By("Creating objects in file %q", resourcePath)
res := kubectl.Create(resourcePath)
res.ExpectSuccess("unable to create resource %q", resourcePath)
}

By("Waiting for pods to be ready")
err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=bookinfo", helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Pods are not ready after timeout")
})

AfterAll(func() {

// Explicitly do not check result to avoid having assertions in AfterAll.
_ = kubectl.Delete(policyPath)

for _, resourcePath := range resourceYAMLs {
By("Deleting resource %s", resourcePath)
// Explicitly do not check result to avoid having assertions in AfterAll.
_ = kubectl.Delete(resourcePath)
}
})

It("Tests bookinfo demo", func() {

// We use wget in this test because the Istio apps do not provide curl.
wgetCommand := fmt.Sprintf("wget --tries=2 --connect-timeout %d", helpers.CurlConnectTimeout)

version := "version"
v1 := "v1"

productPage := "productpage"
reviews := "reviews"
ratings := "ratings"
details := "details"
dnsChecks := []string{productPage, reviews, ratings, details}
app := "app"
health := "health"
ratingsPath := "ratings/0"

apiPort := "9080"

podNameFilter := "{.items[*].metadata.name}"

// shouldConnect asserts that srcPod can connect to dst.
shouldConnect := func(srcPod, dst string) {
By("Checking that %q can connect to %q", srcPod, dst)
res := kubectl.ExecPodCmd(
helpers.DefaultNamespace, srcPod, fmt.Sprintf("%s %s", wgetCommand, dst))
res.ExpectSuccess("Unable to connect from %q to %q", srcPod, dst)
}

// shouldNotConnect asserts that srcPod cannot connect to dst.
shouldNotConnect := func(srcPod, dst string) {
By("Checking that %q cannot connect to %q", srcPod, dst)
res := kubectl.ExecPodCmd(
helpers.DefaultNamespace, srcPod, fmt.Sprintf("%s %s", wgetCommand, dst))
res.ExpectFail("Was able to connect from %q to %q, but expected no connection: %s", srcPod, dst, res.CombineOutput())
}

// formatLabelArgument formats the provided key-value pairs as labels for use in
// querying Kubernetes.
formatLabelArgument := func(firstKey, firstValue string, nextLabels ...string) string {
baseString := fmt.Sprintf("-l %s=%s", firstKey, firstValue)
if nextLabels == nil {
return baseString
} else if len(nextLabels)%2 != 0 {
Fail("must provide even number of arguments for label key-value pairings")
} else {
for i := 0; i < len(nextLabels); i += 2 {
baseString = fmt.Sprintf("%s,%s=%s", baseString, nextLabels[i], nextLabels[i+1])
}
}
return baseString
}

// formatAPI is a helper function which formats a URI to access.
formatAPI := func(service, port, resource string) string {
target := fmt.Sprintf(
"%s.%s.svc.cluster.local:%s",
service, helpers.DefaultNamespace, port)
if resource != "" {
return fmt.Sprintf("%s/%s", target, resource)
}
return target
}

err := kubectl.CiliumEndpointWaitReady()
ExpectWithOffset(1, err).To(BeNil(), "Endpoints are not ready after timeout")

By("Waiting for services to be ready")
for _, service := range []string{details, ratings, reviews, productPage} {
err = kubectl.WaitForServiceEndpoints(
helpers.DefaultNamespace, "", service,
helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Service %q is not ready after timeout", service)
}
By("Validating DNS without Policy")
for _, name := range dnsChecks {
err = kubectl.WaitForKubeDNSEntry(name, helpers.DefaultNamespace)
Expect(err).To(BeNil(), "DNS entry is not ready after timeout")
}

By("All pods should be able to connect without policy")

reviewsPodV1, err := kubectl.GetPods(helpers.DefaultNamespace, formatLabelArgument(app, reviews, version, v1)).Filter(podNameFilter)
Expect(err).Should(BeNil(), "cannot get reviewsV1 pods")
productpagePodV1, err := kubectl.GetPods(helpers.DefaultNamespace, formatLabelArgument(app, productPage, version, v1)).Filter(podNameFilter)
Expect(err).Should(BeNil(), "cannot get productpageV1 pods")

shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, health))
shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

shouldConnect(productpagePodV1.String(), formatAPI(details, apiPort, health))
shouldConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, health))
shouldConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

policyCmd := "cilium policy get io.cilium.k8s.policy.name=cnp-specs"

By("Importing policy")

_, err = kubectl.CiliumPolicyAction(helpers.DefaultNamespace, policyPath, helpers.KubectlCreate, helpers.HelperTimeout)
Expect(err).Should(BeNil(), "Error creating policy %q", policyPath)

By("Checking that policies were correctly imported into Cilium")

ciliumPodK8s1, err := kubectl.GetCiliumPodOnNode(helpers.K8s1)
Expect(err).Should(BeNil(), "Cannot get cilium pod on k8s1")
res := kubectl.ExecPodCmd(helpers.CiliumNamespace, ciliumPodK8s1, policyCmd)
res.ExpectSuccess("Policy %s is not imported", policyCmd)

By("Validating DNS with Policy loaded")
for _, name := range dnsChecks {
err = kubectl.WaitForKubeDNSEntry(name, helpers.DefaultNamespace)
Expect(err).To(BeNil(), "DNS entry is not ready after timeout")
}

By("After policy import")
shouldConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, health))
shouldNotConnect(reviewsPodV1.String(), formatAPI(ratings, apiPort, ratingsPath))

shouldConnect(productpagePodV1.String(), formatAPI(details, apiPort, health))

shouldNotConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, health))
shouldNotConnect(productpagePodV1.String(), formatAPI(ratings, apiPort, ratingsPath))
})
})

})

0 comments on commit d3dd7e8

Please sign in to comment.