Skip to content

Commit

Permalink
Create test for ingress for custom default backend.
Browse files Browse the repository at this point in the history
  • Loading branch information
sawsa307 committed Aug 8, 2023
1 parent e365740 commit 5d5e174
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 2 deletions.
115 changes: 115 additions & 0 deletions test/ingress_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
Copyright 2023 The Kubernetes Authors.
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 test

import (
"context"
"os"
"path"
"testing"

"github.com/GoogleCloudPlatform/gke-networking-recipes/test/utils"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
)

const (
testInstanceName = "allow-ssh-rcp-instance"
proxyOnlyFirewallName = "allow-proxy-connection-rcp"
proxyOnlySubnetName = "proxy-only-subnet-rcp"
allowSSHFirewallName = "fw-allow-ssh-rcp"
)

func TestIngressCustomDefaultBackendSingleCluster(t *testing.T) {
klog.Info("Running TestIngressCustomDefaultBackendSingleCluster.")

testNamespace := "ing-custom-default-be"
if err := utils.SetupTestNamespace(testNamespace); err != nil {
t.Fatalf("Fail to set up test namespace %s: %v", testNamespace, err)
}

ctx := context.Background()
client := Framework.Client
goPath := os.Getenv("GOPATH")
yamlPath := "ingress/single-cluster/ingress-custom-default-backend/ingress-custom-default-backend.yaml"

// Set up proxy-only subnet and firewall for internal Ingress.
region := flags.zone[:len(flags.zone)-2] // Drop the zone
if err := utils.SetupProxyOnlySubnet(proxyOnlySubnetName, flags.testNetworkName, region); err != nil {
t.Fatalf("Failed to set up proxy-only subnet: %v", err)
}
if err := utils.SetupAllowProxyConnectionFirewall(proxyOnlyFirewallName, flags.testNetworkName); err != nil {
t.Fatalf("Failed to set up proxy-only-connection firewall: %v", err)
}

// Create k8s resources from recipe yaml.
objects, err := utils.ParseK8sYaml(ctx, path.Join(goPath, flags.pkgDir, yamlPath), testNamespace)
if err != nil {
t.Fatalf("Failed to parse yaml: %v", err)
}
objectKeys, err := utils.CreateK8sResources(ctx, objects, client, testNamespace)
if err != nil {
t.Fatalf("Failed to create resources from yaml: %v", err)
}
t.Cleanup(func() {
t.Log("Start cleanup.")
err = utils.DeleteK8sResources(ctx, objects, client)
if err != nil {
t.Fatalf("Error during clean up: %v", err)
}
})

// Fetch ingress and validate its IP is ready.
ingressGVK := schema.GroupVersionKind{Group: "networking.k8s.io", Version: "v1", Kind: "Ingress"}
ingressObjectKeys := objectKeys[ingressGVK.String()]
if len(ingressObjectKeys) != 1 {
t.Fatalf("Expect 1 ingress, got %d", len(ingressObjectKeys))
}
ingressIP, err := utils.WaitForIngress(ctx, client, ingressObjectKeys[0])
if err != nil {
t.Fatalf("Fail to get IP for ingress %s/%s: %v", ingressObjectKeys[0].Namespace, ingressObjectKeys[0].Name, err)
}
klog.Infof("Ingress IP: %s", ingressIP)

// Create a test instance that in the same znoe and network as the cluster.
if err := utils.SetupTestInstance(testInstanceName, flags.zone, flags.testNetworkName, flags.testSubnetName); err != nil {
t.Fatalf("Failed to set up test instance: %v", err)
}
if err := utils.SetupAllowSSHFirewall(allowSSHFirewallName, flags.testNetworkName); err != nil {
t.Fatalf("Failed to set up allow-ssh firewall: %v", err)
}

// Send traffic to /foo. Should receive response from foo containers.
addr := ingressIP + "/foo"
response, err := sendTrafficToIngress(addr, testInstanceName, flags.zone, nil)
if err != nil {
t.Fatalf("Fail to send traffic to address %s: %v", addr, err)
}
if err := validateResponse(response, "foo"); err != nil {
t.Fatalf("Fail to validate response: %v", err)
}

// Send traffic to any non-defined path. Should receive response from default-be containers.
addr = ingressIP + "/bar"
response, err = sendTrafficToIngress(addr, testInstanceName, flags.zone, nil)
if err != nil {
t.Fatalf("Fail to send traffic to address %s: %v", addr, err)
}
if err := validateResponse(response, "default-be"); err != nil {
t.Fatalf("Fail to validate response: %v", err)
}
}
14 changes: 13 additions & 1 deletion test/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"math/rand"
"os"
"os/exec"
"strings"
"time"

"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud"
Expand Down Expand Up @@ -61,7 +62,7 @@ func getBoskosProject(resourceType string) *common.Resource {
},
)
if err != nil {
klog.Fatalf("timed out trying to acquire boskos project")
klog.Fatalf("timed out trying to acquire boskos project: %v", err)
}
return project
}
Expand Down Expand Up @@ -167,3 +168,14 @@ func sendTrafficToIngress(address, instanceName, zone string, curlArgs []string)
}
return jsonMap, nil
}

func validateResponse(response map[string]string, expectPodName string) error {
gotPodName, ok := response["pod_name"]
if !ok {
return fmt.Errorf("cannot extract pod name from response")
}
if !strings.Contains(gotPodName, expectPodName) {
return fmt.Errorf("Expect response from %s, got %s", expectPodName, gotPodName)
}
return nil
}
56 changes: 56 additions & 0 deletions test/utils/address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2023 The Kubernetes Authors.
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
https://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 utils

import (
"fmt"
"os/exec"

"k8s.io/klog/v2"
)

func SetupStaticIP(staticIPName string) error {
klog.Infof("Setting up static IP %s.", staticIPName)
params := []string{
"compute",
"addresses",
"describe",
"--global",
staticIPName,
}
if _, err := exec.Command("gcloud", params...).CombinedOutput(); err != nil {
klog.Infof("Static IP %s does not exist, creating.", staticIPName)
return createStaticIP(staticIPName)
}
klog.Infof("Use existing static IP %s.", staticIPName)
return nil
}

func createStaticIP(staticIPName string) error {
klog.Infof("Creating static IP %s.", staticIPName)
params := []string{
"compute",
"addresses",
"create",
"--global",
staticIPName,
}
if out, err := exec.Command("gcloud", params...).CombinedOutput(); err != nil {
return fmt.Errorf("failed creating static IP %s: %s, err: %v", staticIPName, out, err)
}
return nil
}
2 changes: 1 addition & 1 deletion test/utils/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ func DeleteK8sResources(ctx context.Context, objects []ctrlClient.Object, cli ct
for _, obj := range objects {
gvk := obj.GetObjectKind().GroupVersionKind().String()
err := cli.Delete(ctx, obj, &ctrlClient.DeleteOptions{})
klog.Infof("Deleting %s %s/%s", gvk, obj.GetNamespace(), obj.GetName())
if err != nil {
klog.Infof("Failed to delete %s %s/%s: %v", gvk, obj.GetNamespace(), obj.GetName(), err)
return err
}
klog.Infof("Deleting %s %s/%s", gvk, obj.GetNamespace(), obj.GetName())

}
return nil
}
Expand Down
56 changes: 56 additions & 0 deletions test/utils/sslPolicy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2023 The Kubernetes Authors.
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
https://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 utils

import (
"fmt"
"os/exec"

"k8s.io/klog/v2"
)

func SetupSslPolicy(sslPolicyName string) error {
klog.Infof("Setting up SSL Policy %s.", sslPolicyName)
params := []string{
"compute",
"ssl-policies",
"describe",
sslPolicyName,
}
if _, err := exec.Command("gcloud", params...).CombinedOutput(); err != nil {
klog.Infof("SSL Policy %s does not exist, creating.", sslPolicyName)
return createSslPolicy(sslPolicyName)
}
klog.Infof("Use existing SSL policy %s.", sslPolicyName)
return nil
}

func createSslPolicy(sslPolicyName string) error {
klog.Infof("Creating SSL Policy %s.", sslPolicyName)
params := []string{
"compute",
"ssl-policies",
"create",
sslPolicyName,
"--profile", "MODERN",
"--min-tls-version", "1.2",
}
if out, err := exec.Command("gcloud", params...).CombinedOutput(); err != nil {
return fmt.Errorf("failed creating SSL policy %s: %s, err: %v", sslPolicyName, out, err)
}
return nil
}

0 comments on commit 5d5e174

Please sign in to comment.