2017-10-17 22:50:27 +00:00
|
|
|
/*
|
|
|
|
Copyright 2017 Jetstack Ltd.
|
|
|
|
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 framework
|
|
|
|
|
|
|
|
import (
|
2020-03-24 13:44:13 +00:00
|
|
|
"context"
|
2020-02-19 03:08:14 +00:00
|
|
|
"crypto/tls"
|
2017-10-17 22:50:27 +00:00
|
|
|
"fmt"
|
2020-07-01 21:19:51 +00:00
|
|
|
"net"
|
2020-02-19 03:08:14 +00:00
|
|
|
"net/http"
|
2017-10-17 22:50:27 +00:00
|
|
|
"strings"
|
2017-11-10 02:00:38 +00:00
|
|
|
"time"
|
2017-10-17 22:50:27 +00:00
|
|
|
|
2020-06-24 17:52:05 +00:00
|
|
|
"github.com/gavv/httpexpect/v2"
|
2022-07-31 16:16:28 +00:00
|
|
|
"github.com/onsi/ginkgo/v2"
|
2020-02-19 03:08:14 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-05-08 00:21:13 +00:00
|
|
|
appsv1 "k8s.io/api/apps/v1"
|
2020-09-26 23:27:19 +00:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2019-01-09 19:13:17 +00:00
|
|
|
v1 "k8s.io/api/core/v1"
|
2021-08-21 20:42:00 +00:00
|
|
|
networking "k8s.io/api/networking/v1"
|
2017-10-17 22:50:27 +00:00
|
|
|
apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
2020-07-29 15:53:35 +00:00
|
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
2017-11-10 02:00:38 +00:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2018-04-01 20:09:27 +00:00
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
2017-11-12 16:52:55 +00:00
|
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
2017-10-17 22:50:27 +00:00
|
|
|
"k8s.io/client-go/kubernetes"
|
2020-09-26 23:27:19 +00:00
|
|
|
"k8s.io/client-go/kubernetes/scheme"
|
2020-10-23 15:58:10 +00:00
|
|
|
"k8s.io/client-go/rest"
|
2017-11-12 16:52:55 +00:00
|
|
|
restclient "k8s.io/client-go/rest"
|
2020-08-08 23:31:02 +00:00
|
|
|
"k8s.io/klog/v2"
|
2017-10-17 22:50:27 +00:00
|
|
|
)
|
|
|
|
|
2018-03-07 16:37:30 +00:00
|
|
|
// RequestScheme define a scheme used in a test request.
|
2017-10-17 22:50:27 +00:00
|
|
|
type RequestScheme string
|
|
|
|
|
|
|
|
// These are valid test request schemes.
|
|
|
|
const (
|
|
|
|
HTTP RequestScheme = "http"
|
|
|
|
HTTPS RequestScheme = "https"
|
|
|
|
)
|
|
|
|
|
2018-10-29 16:01:41 +00:00
|
|
|
var (
|
|
|
|
// KubectlPath defines the full path of the kubectl binary
|
|
|
|
KubectlPath = "/usr/local/bin/kubectl"
|
|
|
|
)
|
|
|
|
|
2017-10-17 22:50:27 +00:00
|
|
|
// Framework supports common operations used by e2e tests; it will keep a client & a namespace for you.
|
|
|
|
type Framework struct {
|
|
|
|
BaseName string
|
|
|
|
|
|
|
|
// A Kubernetes and Service Catalog client
|
|
|
|
KubeClientSet kubernetes.Interface
|
2017-11-12 16:52:55 +00:00
|
|
|
KubeConfig *restclient.Config
|
2017-10-17 22:50:27 +00:00
|
|
|
APIExtensionsClientSet apiextcs.Interface
|
|
|
|
|
2021-08-21 20:42:00 +00:00
|
|
|
Namespace string
|
|
|
|
IngressClass string
|
2020-09-26 23:27:19 +00:00
|
|
|
|
|
|
|
pod *corev1.Pod
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 02:00:38 +00:00
|
|
|
// NewDefaultFramework makes a new framework and sets up a BeforeEach/AfterEach for
|
2017-10-17 22:50:27 +00:00
|
|
|
// you (you can write additional before/after each functions).
|
|
|
|
func NewDefaultFramework(baseName string) *Framework {
|
2020-02-19 03:08:14 +00:00
|
|
|
defer ginkgo.GinkgoRecover()
|
|
|
|
|
2017-10-17 22:50:27 +00:00
|
|
|
f := &Framework{
|
2020-06-27 15:57:00 +00:00
|
|
|
BaseName: baseName,
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 22:52:01 +00:00
|
|
|
ginkgo.BeforeEach(f.BeforeEach)
|
|
|
|
ginkgo.AfterEach(f.AfterEach)
|
2017-10-17 22:50:27 +00:00
|
|
|
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
2022-05-26 13:23:24 +00:00
|
|
|
// NewSimpleFramework makes a new framework that allows the usage of a namespace
|
|
|
|
// for arbitraty tests.
|
|
|
|
func NewSimpleFramework(baseName string) *Framework {
|
|
|
|
defer ginkgo.GinkgoRecover()
|
|
|
|
|
|
|
|
f := &Framework{
|
|
|
|
BaseName: baseName,
|
|
|
|
}
|
|
|
|
|
|
|
|
ginkgo.BeforeEach(f.CreateEnvironment)
|
|
|
|
ginkgo.AfterEach(f.DestroyEnvironment)
|
|
|
|
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Framework) CreateEnvironment() {
|
2020-06-27 15:57:00 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
if f.KubeClientSet == nil {
|
2020-10-26 14:24:55 +00:00
|
|
|
f.KubeConfig, err = loadConfig()
|
2020-06-27 15:57:00 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "loading a kubernetes client configuration")
|
2020-10-23 15:58:10 +00:00
|
|
|
|
|
|
|
// TODO: remove after k8s v1.22
|
|
|
|
f.KubeConfig.WarningHandler = rest.NoWarnings{}
|
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
f.KubeClientSet, err = kubernetes.NewForConfig(f.KubeConfig)
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "creating a kubernetes client")
|
|
|
|
|
|
|
|
}
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
f.Namespace, err = CreateKubeNamespace(f.BaseName, f.KubeClientSet)
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "creating namespace")
|
2022-05-26 13:23:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Framework) DestroyEnvironment() {
|
|
|
|
go func() {
|
|
|
|
defer ginkgo.GinkgoRecover()
|
|
|
|
err := DeleteKubeNamespace(f.KubeClientSet, f.Namespace)
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "deleting namespace %v", f.Namespace)
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
// BeforeEach gets a client and makes a namespace.
|
|
|
|
func (f *Framework) BeforeEach() {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
f.CreateEnvironment()
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2021-08-21 20:42:00 +00:00
|
|
|
f.IngressClass, err = CreateIngressClass(f.Namespace, f.KubeClientSet)
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "creating IngressClass")
|
|
|
|
|
2020-02-14 00:19:07 +00:00
|
|
|
err = f.newIngressController(f.Namespace, f.BaseName)
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "deploying the ingress controller")
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
err = f.updateIngressNGINXPod()
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller pod information")
|
|
|
|
|
2020-07-01 21:19:51 +00:00
|
|
|
f.WaitForNginxListening(80)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AfterEach deletes the namespace, after reading its events.
|
|
|
|
func (f *Framework) AfterEach() {
|
2022-05-26 13:23:24 +00:00
|
|
|
defer f.DestroyEnvironment()
|
2019-06-24 02:34:07 +00:00
|
|
|
|
2021-08-21 20:42:00 +00:00
|
|
|
defer func(kubeClient kubernetes.Interface, ingressclass string) {
|
|
|
|
go func() {
|
|
|
|
defer ginkgo.GinkgoRecover()
|
|
|
|
err := deleteIngressClass(kubeClient, ingressclass)
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "deleting IngressClass")
|
|
|
|
}()
|
|
|
|
}(f.KubeClientSet, f.IngressClass)
|
|
|
|
|
2022-07-31 16:16:28 +00:00
|
|
|
if !ginkgo.CurrentSpecReport().Failed() {
|
2020-06-27 15:57:00 +00:00
|
|
|
return
|
|
|
|
}
|
2020-02-14 00:19:07 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
cmd := fmt.Sprintf("cat /etc/nginx/nginx.conf")
|
2020-09-26 23:27:19 +00:00
|
|
|
o, err := f.ExecCommand(f.pod, cmd)
|
2020-06-27 15:57:00 +00:00
|
|
|
if err != nil {
|
|
|
|
Logf("Unexpected error obtaining nginx.conf file: %v", err)
|
|
|
|
return
|
|
|
|
}
|
2019-06-24 02:34:07 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
ginkgo.By("Dumping NGINX configuration after failure")
|
|
|
|
Logf("%v", o)
|
2020-02-14 00:19:07 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
log, err := f.NginxLogs()
|
|
|
|
if err != nil {
|
|
|
|
Logf("Unexpected error obtaining NGINX logs: %v", err)
|
|
|
|
return
|
|
|
|
}
|
2020-02-14 00:19:07 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
ginkgo.By("Dumping NGINX logs")
|
|
|
|
Logf("%v", log)
|
|
|
|
|
|
|
|
o, err = f.NamespaceContent()
|
|
|
|
if err != nil {
|
|
|
|
Logf("Unexpected error obtaining namespace information: %v", err)
|
|
|
|
return
|
2018-08-03 13:50:53 +00:00
|
|
|
}
|
2020-02-14 00:19:07 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
ginkgo.By("Dumping namespace content")
|
|
|
|
Logf("%v", o)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
// IngressNginxDescribe wrapper function for ginkgo describe. Adds namespacing.
|
2017-10-17 22:50:27 +00:00
|
|
|
func IngressNginxDescribe(text string, body func()) bool {
|
2020-02-16 14:58:37 +00:00
|
|
|
return ginkgo.Describe(text, body)
|
2019-06-27 14:03:20 +00:00
|
|
|
}
|
|
|
|
|
2020-02-16 18:27:58 +00:00
|
|
|
// DescribeAnnotation wrapper function for ginkgo describe. Adds namespacing.
|
|
|
|
func DescribeAnnotation(text string, body func()) bool {
|
|
|
|
return ginkgo.Describe("[Annotations] "+text, body)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DescribeSetting wrapper function for ginkgo describe. Adds namespacing.
|
|
|
|
func DescribeSetting(text string, body func()) bool {
|
|
|
|
return ginkgo.Describe("[Setting] "+text, body)
|
|
|
|
}
|
|
|
|
|
2019-06-27 14:03:20 +00:00
|
|
|
// MemoryLeakIt is wrapper function for ginkgo It. Adds "[MemoryLeak]" tag and makes static analysis easier.
|
2022-07-31 16:16:28 +00:00
|
|
|
func MemoryLeakIt(text string, body interface{}) bool {
|
|
|
|
return ginkgo.It(text+" [MemoryLeak]", body)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 14:03:42 +00:00
|
|
|
// GetNginxIP returns the number of TCP port where NGINX is running
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) GetNginxIP() string {
|
2018-04-18 19:15:08 +00:00
|
|
|
s, err := f.KubeClientSet.
|
|
|
|
CoreV1().
|
2019-02-22 14:03:42 +00:00
|
|
|
Services(f.Namespace).
|
2020-03-24 13:44:13 +00:00
|
|
|
Get(context.TODO(), "nginx-ingress-controller", metav1.GetOptions{})
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "obtaining NGINX IP address")
|
2019-02-22 14:03:42 +00:00
|
|
|
return s.Spec.ClusterIP
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
2020-01-25 08:03:18 +00:00
|
|
|
// GetNginxPodIP returns the IP addresses of the running pods
|
2020-06-27 15:57:00 +00:00
|
|
|
func (f *Framework) GetNginxPodIP() string {
|
2020-09-26 23:27:19 +00:00
|
|
|
return f.pod.Status.PodIP
|
2019-08-13 21:14:55 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 14:03:42 +00:00
|
|
|
// GetURL returns the URL should be used to make a request to NGINX
|
|
|
|
func (f *Framework) GetURL(scheme RequestScheme) string {
|
2018-10-29 21:39:04 +00:00
|
|
|
ip := f.GetNginxIP()
|
2019-02-22 14:03:42 +00:00
|
|
|
return fmt.Sprintf("%v://%v", scheme, ip)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
2017-11-10 02:00:38 +00:00
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
// GetIngressNGINXPod returns the ingress controller running pod
|
|
|
|
func (f *Framework) GetIngressNGINXPod() *corev1.Pod {
|
|
|
|
return f.pod
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateIngressNGINXPod search and updates the ingress controller running pod
|
|
|
|
func (f *Framework) updateIngressNGINXPod() error {
|
|
|
|
var err error
|
|
|
|
f.pod, err = getIngressNGINXPod(f.Namespace, f.KubeClientSet)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-24 16:39:12 +00:00
|
|
|
// WaitForNginxServer waits until the nginx configuration contains a particular server section.
|
|
|
|
// `cfg` passed to matcher is normalized by replacing all tabs and spaces with single space.
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) bool) {
|
2020-08-21 00:12:31 +00:00
|
|
|
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxConditions(name, matcher))
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
|
2020-07-01 21:19:51 +00:00
|
|
|
Sleep(1 * time.Second)
|
2017-11-12 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 12:26:53 +00:00
|
|
|
// WaitForNginxConfiguration waits until the nginx configuration contains a particular configuration
|
2020-12-24 16:39:12 +00:00
|
|
|
// `cfg` passed to matcher is normalized by replacing all tabs and spaces with single space.
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) WaitForNginxConfiguration(matcher func(cfg string) bool) {
|
2020-08-21 00:12:31 +00:00
|
|
|
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxConditions("", matcher))
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
|
2020-08-09 12:13:24 +00:00
|
|
|
Sleep(1 * time.Second)
|
2018-01-17 12:26:53 +00:00
|
|
|
}
|
|
|
|
|
2020-03-26 09:25:11 +00:00
|
|
|
// WaitForNginxCustomConfiguration waits until the nginx configuration given part (from, to) contains a particular configuration
|
|
|
|
func (f *Framework) WaitForNginxCustomConfiguration(from string, to string, matcher func(cfg string) bool) {
|
2020-08-21 00:12:31 +00:00
|
|
|
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxCustomConditions(from, to, matcher))
|
2020-03-26 09:25:11 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
|
|
|
|
}
|
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
// NginxLogs returns the logs of the nginx ingress controller pod running
|
|
|
|
func (f *Framework) NginxLogs() (string, error) {
|
|
|
|
if isRunning, err := podRunningReady(f.pod); err == nil && isRunning {
|
|
|
|
return Logs(f.KubeClientSet, f.Namespace, f.pod.Name)
|
2017-11-14 20:50:08 +00:00
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
return "", fmt.Errorf("no nginx ingress controller pod is running (logs)")
|
2017-11-14 20:50:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-12 16:52:55 +00:00
|
|
|
func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) bool) wait.ConditionFunc {
|
|
|
|
return func() (bool, error) {
|
2018-01-17 12:26:53 +00:00
|
|
|
var cmd string
|
|
|
|
if name == "" {
|
|
|
|
cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf")
|
|
|
|
} else {
|
|
|
|
cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf | awk '/## start server %v/,/## end server %v/'", name, name)
|
|
|
|
}
|
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
o, err := f.ExecCommand(f.pod, cmd)
|
2017-11-12 16:52:55 +00:00
|
|
|
if err != nil {
|
2019-02-22 14:03:42 +00:00
|
|
|
return false, nil
|
2017-11-12 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
2020-08-08 23:31:02 +00:00
|
|
|
if klog.V(10).Enabled() && len(o) > 0 {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.InfoS("NGINX", "configuration", o)
|
2017-11-12 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
2020-02-19 03:08:14 +00:00
|
|
|
// passes the nginx config to the passed function
|
|
|
|
if matcher(strings.Join(strings.Fields(o), " ")) {
|
|
|
|
return true, nil
|
2018-04-18 19:15:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-12 16:52:55 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
2017-11-10 02:00:38 +00:00
|
|
|
}
|
2018-04-01 20:09:27 +00:00
|
|
|
|
2020-03-26 09:25:11 +00:00
|
|
|
func (f *Framework) matchNginxCustomConditions(from string, to string, matcher func(cfg string) bool) wait.ConditionFunc {
|
|
|
|
return func() (bool, error) {
|
|
|
|
cmd := fmt.Sprintf("cat /etc/nginx/nginx.conf| awk '/%v/,/%v/'", from, to)
|
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
o, err := f.ExecCommand(f.pod, cmd)
|
2020-03-26 09:25:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2020-08-08 23:31:02 +00:00
|
|
|
if klog.V(10).Enabled() && len(o) > 0 {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.InfoS("NGINX", "configuration", o)
|
2020-03-26 09:25:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// passes the nginx config to the passed function
|
|
|
|
if matcher(strings.Join(strings.Fields(o), " ")) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-24 14:53:23 +00:00
|
|
|
func (f *Framework) getConfigMap(name string) (*v1.ConfigMap, error) {
|
2018-04-10 18:14:36 +00:00
|
|
|
if f.KubeClientSet == nil {
|
|
|
|
return nil, fmt.Errorf("KubeClientSet not initialized")
|
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
config, err := f.KubeClientSet.
|
|
|
|
CoreV1().
|
2019-02-22 14:03:42 +00:00
|
|
|
ConfigMaps(f.Namespace).
|
2020-03-24 13:44:13 +00:00
|
|
|
Get(context.TODO(), name, metav1.GetOptions{})
|
2018-04-10 18:14:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return config, err
|
|
|
|
}
|
|
|
|
|
2020-02-16 14:58:37 +00:00
|
|
|
// SetNginxConfigMapData sets ingress-nginx's nginx-ingress-controller configMap data
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) SetNginxConfigMapData(cmData map[string]string) {
|
2020-02-16 14:58:37 +00:00
|
|
|
cfgMap, err := f.getConfigMap("nginx-ingress-controller")
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err)
|
|
|
|
assert.NotNil(ginkgo.GinkgoT(), cfgMap, "expected a configmap but none returned")
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2020-02-16 14:58:37 +00:00
|
|
|
cfgMap.Data = cmData
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
fn := func() {
|
|
|
|
_, err = f.KubeClientSet.
|
|
|
|
CoreV1().
|
|
|
|
ConfigMaps(f.Namespace).
|
|
|
|
Update(context.TODO(), cfgMap, metav1.UpdateOptions{})
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "updating configuration configmap")
|
|
|
|
}
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2020-12-24 16:39:12 +00:00
|
|
|
f.WaitForReload(fn)
|
2018-04-10 18:14:36 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 00:43:14 +00:00
|
|
|
// CreateConfigMap creates a new configmap in the current namespace
|
2019-09-24 14:53:23 +00:00
|
|
|
func (f *Framework) CreateConfigMap(name string, data map[string]string) {
|
2020-03-24 13:44:13 +00:00
|
|
|
_, err := f.KubeClientSet.CoreV1().ConfigMaps(f.Namespace).Create(context.TODO(), &v1.ConfigMap{
|
2019-09-24 14:53:23 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: name,
|
|
|
|
Namespace: f.Namespace,
|
|
|
|
},
|
|
|
|
Data: data,
|
2020-03-24 13:44:13 +00:00
|
|
|
}, metav1.CreateOptions{})
|
2020-02-19 03:08:56 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "creating configMap")
|
2019-09-24 14:53:23 +00:00
|
|
|
}
|
|
|
|
|
2020-02-16 14:58:37 +00:00
|
|
|
// UpdateNginxConfigMapData updates single field in ingress-nginx's nginx-ingress-controller map data
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) UpdateNginxConfigMapData(key string, value string) {
|
2020-02-16 14:58:37 +00:00
|
|
|
config, err := f.getConfigMap("nginx-ingress-controller")
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err)
|
|
|
|
assert.NotNil(ginkgo.GinkgoT(), config, "expected a configmap but none returned")
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2020-02-16 14:58:37 +00:00
|
|
|
config.Data[key] = value
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
fn := func() {
|
|
|
|
_, err = f.KubeClientSet.
|
|
|
|
CoreV1().
|
|
|
|
ConfigMaps(f.Namespace).
|
|
|
|
Update(context.TODO(), config, metav1.UpdateOptions{})
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "updating configuration configmap")
|
|
|
|
}
|
|
|
|
|
2020-12-24 16:39:12 +00:00
|
|
|
f.WaitForReload(fn)
|
2020-06-27 15:57:00 +00:00
|
|
|
}
|
|
|
|
|
2020-12-24 16:39:12 +00:00
|
|
|
// WaitForReload calls the passed function and
|
|
|
|
// asser it has caused at least 1 reload.
|
|
|
|
func (f *Framework) WaitForReload(fn func()) {
|
2020-09-30 14:24:51 +00:00
|
|
|
initialReloadCount := getReloadCount(f.pod, f.Namespace, f.KubeClientSet)
|
2020-06-27 15:57:00 +00:00
|
|
|
|
|
|
|
fn()
|
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
count := 0
|
2020-09-30 14:24:51 +00:00
|
|
|
err := wait.Poll(1*time.Second, DefaultTimeout, func() (bool, error) {
|
|
|
|
reloads := getReloadCount(f.pod, f.Namespace, f.KubeClientSet)
|
2020-06-27 15:57:00 +00:00
|
|
|
// most of the cases reload the ingress controller
|
|
|
|
// in cases where the value is not modified we could wait forever
|
2020-09-30 14:24:51 +00:00
|
|
|
if count > 5 && reloads == initialReloadCount {
|
2020-06-27 15:57:00 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
count++
|
|
|
|
|
2020-09-30 14:24:51 +00:00
|
|
|
return (reloads > initialReloadCount), nil
|
2020-06-27 15:57:00 +00:00
|
|
|
})
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "while waiting for ingress controller reload")
|
|
|
|
}
|
2020-02-19 03:08:14 +00:00
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
func getReloadCount(pod *corev1.Pod, namespace string, client kubernetes.Interface) int {
|
2020-11-27 17:26:53 +00:00
|
|
|
events, err := client.CoreV1().Events(namespace).Search(scheme.Scheme, pod)
|
2020-09-26 23:27:19 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "obtaining NGINX Pod")
|
2020-06-29 22:28:52 +00:00
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
reloadCount := 0
|
2020-11-27 17:26:53 +00:00
|
|
|
for _, e := range events.Items {
|
2020-10-26 14:24:55 +00:00
|
|
|
if e.Reason == "RELOAD" && e.Type == corev1.EventTypeNormal {
|
2020-09-26 23:27:19 +00:00
|
|
|
reloadCount++
|
|
|
|
}
|
2020-06-29 22:28:52 +00:00
|
|
|
}
|
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
return reloadCount
|
2020-06-27 15:57:00 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 10:37:19 +00:00
|
|
|
// DeleteNGINXPod deletes the currently running pod. It waits for the replacement pod to be up.
|
|
|
|
// Grace period to wait for pod shutdown is in seconds.
|
|
|
|
func (f *Framework) DeleteNGINXPod(grace int64) {
|
2019-02-22 14:03:42 +00:00
|
|
|
ns := f.Namespace
|
2018-12-11 10:37:19 +00:00
|
|
|
|
2020-09-26 23:27:19 +00:00
|
|
|
err := f.KubeClientSet.CoreV1().Pods(ns).Delete(context.TODO(), f.pod.GetName(), *metav1.NewDeleteOptions(grace))
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "deleting ingress nginx pod")
|
2018-12-11 10:37:19 +00:00
|
|
|
|
2020-08-21 00:12:31 +00:00
|
|
|
err = wait.Poll(Poll, DefaultTimeout, func() (bool, error) {
|
2020-09-26 23:27:19 +00:00
|
|
|
err := f.updateIngressNGINXPod()
|
|
|
|
if err != nil || f.pod == nil {
|
2018-12-11 10:37:19 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
2020-09-26 23:27:19 +00:00
|
|
|
return f.pod.GetName() != "", nil
|
2018-12-11 10:37:19 +00:00
|
|
|
})
|
2020-02-19 03:08:14 +00:00
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "while waiting for ingress nginx pod to come up again")
|
|
|
|
}
|
|
|
|
|
2022-05-26 13:23:24 +00:00
|
|
|
// HTTPDumbTestClient returns a new httpexpect client without BaseURL.
|
|
|
|
func (f *Framework) HTTPDumbTestClient() *httpexpect.Expect {
|
|
|
|
return f.newTestClient(nil, false)
|
|
|
|
}
|
|
|
|
|
2020-02-20 00:43:14 +00:00
|
|
|
// HTTPTestClient returns a new httpexpect client for end-to-end HTTP testing.
|
2020-02-19 03:08:14 +00:00
|
|
|
func (f *Framework) HTTPTestClient() *httpexpect.Expect {
|
2022-05-26 13:23:24 +00:00
|
|
|
return f.newTestClient(nil, true)
|
2020-02-19 03:08:14 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 00:43:14 +00:00
|
|
|
// HTTPTestClientWithTLSConfig returns a new httpexpect client for end-to-end
|
|
|
|
// HTTP testing with a custom TLS configuration.
|
2020-02-19 03:08:14 +00:00
|
|
|
func (f *Framework) HTTPTestClientWithTLSConfig(config *tls.Config) *httpexpect.Expect {
|
2022-05-26 13:23:24 +00:00
|
|
|
return f.newTestClient(config, true)
|
2020-02-19 03:08:14 +00:00
|
|
|
}
|
|
|
|
|
2022-05-26 13:23:24 +00:00
|
|
|
func (f *Framework) newTestClient(config *tls.Config, setIngressURL bool) *httpexpect.Expect {
|
2020-02-19 03:08:14 +00:00
|
|
|
if config == nil {
|
|
|
|
config = &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
}
|
|
|
|
}
|
2022-05-26 13:23:24 +00:00
|
|
|
var baseURL string
|
|
|
|
if setIngressURL {
|
|
|
|
baseURL = f.GetURL(HTTP)
|
|
|
|
}
|
2020-02-19 03:08:14 +00:00
|
|
|
|
|
|
|
return httpexpect.WithConfig(httpexpect.Config{
|
2022-05-26 13:23:24 +00:00
|
|
|
BaseURL: baseURL,
|
2020-02-19 03:08:14 +00:00
|
|
|
Client: &http.Client{
|
|
|
|
Transport: &http.Transport{
|
|
|
|
TLSClientConfig: config,
|
|
|
|
},
|
|
|
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
|
|
|
return http.ErrUseLastResponse
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Reporter: httpexpect.NewAssertReporter(
|
|
|
|
httpexpect.NewAssertReporter(ginkgo.GinkgoT()),
|
|
|
|
),
|
|
|
|
Printers: []httpexpect.Printer{
|
|
|
|
// TODO: enable conditionally?
|
|
|
|
// httpexpect.NewDebugPrinter(ginkgo.GinkgoT(), false),
|
|
|
|
},
|
|
|
|
})
|
2018-12-11 10:37:19 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 21:19:51 +00:00
|
|
|
// WaitForNginxListening waits until NGINX starts accepting connections on a port
|
|
|
|
func (f *Framework) WaitForNginxListening(port int) {
|
|
|
|
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, metav1.ListOptions{
|
|
|
|
LabelSelector: "app.kubernetes.io/name=ingress-nginx",
|
|
|
|
})
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for ingress pods to be ready")
|
|
|
|
|
|
|
|
podIP := f.GetNginxIP()
|
|
|
|
err = wait.Poll(500*time.Millisecond, DefaultTimeout, func() (bool, error) {
|
2020-09-03 02:01:13 +00:00
|
|
|
hostPort := net.JoinHostPort(podIP, fmt.Sprintf("%v", port))
|
|
|
|
conn, err := net.Dial("tcp", hostPort)
|
2020-07-01 21:19:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
})
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for ingress controller pod listening on port 80")
|
|
|
|
}
|
|
|
|
|
2022-05-26 13:23:24 +00:00
|
|
|
// WaitForPod waits for a specific Pod to be ready, using a label selector
|
|
|
|
func (f *Framework) WaitForPod(selector string, timeout time.Duration, shouldFail bool) {
|
|
|
|
err := waitForPodsReady(f.KubeClientSet, timeout, 1, f.Namespace, metav1.ListOptions{
|
|
|
|
LabelSelector: selector,
|
|
|
|
})
|
|
|
|
|
|
|
|
if shouldFail {
|
|
|
|
assert.NotNil(ginkgo.GinkgoT(), err, "waiting for pods to be ready")
|
|
|
|
} else {
|
|
|
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for pods to be ready")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-01 20:09:27 +00:00
|
|
|
// UpdateDeployment runs the given updateFunc on the deployment and waits for it to be updated
|
2019-05-08 00:21:13 +00:00
|
|
|
func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name string, replicas int, updateFunc func(d *appsv1.Deployment) error) error {
|
2020-03-24 13:44:13 +00:00
|
|
|
deployment, err := kubeClientSet.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
2018-04-01 20:09:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
if updateFunc != nil {
|
|
|
|
if err := updateFunc(deployment); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-07-01 21:19:51 +00:00
|
|
|
|
2020-07-29 15:53:35 +00:00
|
|
|
err = waitForDeploymentRollout(kubeClientSet, deployment)
|
2020-07-01 21:19:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-04-18 19:15:08 +00:00
|
|
|
}
|
|
|
|
|
2020-02-19 03:08:56 +00:00
|
|
|
if *deployment.Spec.Replicas != int32(replicas) {
|
|
|
|
deployment.Spec.Replicas = NewInt32(int32(replicas))
|
2020-03-24 13:44:13 +00:00
|
|
|
_, err = kubeClientSet.AppsV1().Deployments(namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
|
2020-02-19 03:08:56 +00:00
|
|
|
if err != nil {
|
2022-01-10 00:29:12 +00:00
|
|
|
return fmt.Errorf("scaling the number of replicas to %d: %w", replicas, err)
|
2020-02-19 03:08:56 +00:00
|
|
|
}
|
2020-07-01 21:19:51 +00:00
|
|
|
|
2020-07-29 15:53:35 +00:00
|
|
|
err = waitForDeploymentRollout(kubeClientSet, deployment)
|
2020-07-01 21:19:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-02-19 03:08:56 +00:00
|
|
|
}
|
|
|
|
|
2020-06-27 15:57:00 +00:00
|
|
|
err = waitForPodsReady(kubeClientSet, DefaultTimeout, replicas, namespace, metav1.ListOptions{
|
2018-04-01 20:09:27 +00:00
|
|
|
LabelSelector: fields.SelectorFromSet(fields.Set(deployment.Spec.Template.ObjectMeta.Labels)).String(),
|
|
|
|
})
|
|
|
|
if err != nil {
|
2022-01-10 00:29:12 +00:00
|
|
|
return fmt.Errorf("waiting for nginx-ingress-controller replica count to be %d: %w", replicas, err)
|
2018-04-01 20:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2020-07-29 15:53:35 +00:00
|
|
|
func waitForDeploymentRollout(kubeClientSet kubernetes.Interface, resource *appsv1.Deployment) error {
|
|
|
|
return wait.Poll(Poll, 5*time.Minute, func() (bool, error) {
|
|
|
|
d, err := kubeClientSet.AppsV1().Deployments(resource.Namespace).Get(context.TODO(), resource.Name, metav1.GetOptions{})
|
|
|
|
if apierrors.IsNotFound(err) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.DeletionTimestamp != nil {
|
|
|
|
return false, fmt.Errorf("deployment %q is being deleted", resource.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.Generation <= d.Status.ObservedGeneration && d.Status.UpdatedReplicas == d.Status.Replicas && d.Status.UnavailableReplicas == 0 {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-12-11 21:57:46 +00:00
|
|
|
// UpdateIngress runs the given updateFunc on the ingress
|
2019-12-12 23:12:12 +00:00
|
|
|
func UpdateIngress(kubeClientSet kubernetes.Interface, namespace string, name string, updateFunc func(d *networking.Ingress) error) error {
|
2021-08-21 20:42:00 +00:00
|
|
|
ingress, err := kubeClientSet.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
2018-12-11 21:57:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-02-19 03:08:56 +00:00
|
|
|
if ingress == nil {
|
|
|
|
return fmt.Errorf("there is no ingress with name %v in namespace %v", name, namespace)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ingress.ObjectMeta.Annotations == nil {
|
|
|
|
ingress.ObjectMeta.Annotations = map[string]string{}
|
|
|
|
}
|
|
|
|
|
2018-12-11 21:57:46 +00:00
|
|
|
if err := updateFunc(ingress); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-08-21 20:42:00 +00:00
|
|
|
_, err = kubeClientSet.NetworkingV1().Ingresses(namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
|
2020-02-19 03:08:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-07-01 21:19:51 +00:00
|
|
|
Sleep(1 * time.Second)
|
2020-02-19 03:08:56 +00:00
|
|
|
return nil
|
2018-12-11 21:57:46 +00:00
|
|
|
}
|
|
|
|
|
2018-08-23 00:25:21 +00:00
|
|
|
// NewSingleIngressWithTLS creates a simple ingress rule with TLS spec included
|
2019-12-13 05:47:11 +00:00
|
|
|
func NewSingleIngressWithTLS(name, path, host string, tlsHosts []string, ns, service string, port int, annotations map[string]string) *networking.Ingress {
|
2019-01-09 19:13:17 +00:00
|
|
|
return newSingleIngressWithRules(name, path, host, ns, service, port, annotations, tlsHosts)
|
2018-08-23 00:25:21 +00:00
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
// NewSingleIngress creates a simple ingress rule
|
2019-12-13 05:47:11 +00:00
|
|
|
func NewSingleIngress(name, path, host, ns, service string, port int, annotations map[string]string) *networking.Ingress {
|
2019-01-09 19:13:17 +00:00
|
|
|
return newSingleIngressWithRules(name, path, host, ns, service, port, annotations, nil)
|
2018-08-23 00:25:21 +00:00
|
|
|
}
|
|
|
|
|
2021-11-12 19:46:28 +00:00
|
|
|
func NewSingleIngressWithIngressClass(name, path, host, ns, service, ingressClass string, port int, annotations map[string]string) *networking.Ingress {
|
|
|
|
ing := newSingleIngressWithRules(name, path, host, ns, service, port, annotations, nil)
|
|
|
|
ing.Spec.IngressClassName = &ingressClass
|
|
|
|
return ing
|
|
|
|
}
|
|
|
|
|
2019-03-04 11:20:54 +00:00
|
|
|
// NewSingleIngressWithMultiplePaths creates a simple ingress rule with multiple paths
|
2019-12-13 05:47:11 +00:00
|
|
|
func NewSingleIngressWithMultiplePaths(name string, paths []string, host, ns, service string, port int, annotations map[string]string) *networking.Ingress {
|
2021-08-21 20:42:00 +00:00
|
|
|
pathtype := networking.PathTypePrefix
|
2019-12-12 23:12:12 +00:00
|
|
|
spec := networking.IngressSpec{
|
2021-08-21 20:42:00 +00:00
|
|
|
IngressClassName: GetIngressClassName(ns),
|
2019-12-12 23:12:12 +00:00
|
|
|
Rules: []networking.IngressRule{
|
2019-03-04 11:20:54 +00:00
|
|
|
{
|
|
|
|
Host: host,
|
2019-12-12 23:12:12 +00:00
|
|
|
IngressRuleValue: networking.IngressRuleValue{
|
|
|
|
HTTP: &networking.HTTPIngressRuleValue{},
|
2019-03-04 11:20:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, path := range paths {
|
2019-12-12 23:12:12 +00:00
|
|
|
spec.Rules[0].IngressRuleValue.HTTP.Paths = append(spec.Rules[0].IngressRuleValue.HTTP.Paths, networking.HTTPIngressPath{
|
2021-08-21 20:42:00 +00:00
|
|
|
Path: path,
|
|
|
|
PathType: &pathtype,
|
2019-12-12 23:12:12 +00:00
|
|
|
Backend: networking.IngressBackend{
|
2021-08-21 20:42:00 +00:00
|
|
|
Service: &networking.IngressServiceBackend{
|
|
|
|
Name: service,
|
|
|
|
Port: networking.ServiceBackendPort{
|
|
|
|
Number: int32(port),
|
|
|
|
},
|
|
|
|
},
|
2019-03-04 11:20:54 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return newSingleIngress(name, ns, annotations, spec)
|
|
|
|
}
|
|
|
|
|
2019-12-13 05:47:11 +00:00
|
|
|
func newSingleIngressWithRules(name, path, host, ns, service string, port int, annotations map[string]string, tlsHosts []string) *networking.Ingress {
|
2021-08-21 20:42:00 +00:00
|
|
|
pathtype := networking.PathTypePrefix
|
2019-12-12 23:12:12 +00:00
|
|
|
spec := networking.IngressSpec{
|
2021-08-21 20:42:00 +00:00
|
|
|
IngressClassName: GetIngressClassName(ns),
|
2019-12-12 23:12:12 +00:00
|
|
|
Rules: []networking.IngressRule{
|
2018-12-05 14:39:19 +00:00
|
|
|
{
|
2019-12-12 23:12:12 +00:00
|
|
|
IngressRuleValue: networking.IngressRuleValue{
|
|
|
|
HTTP: &networking.HTTPIngressRuleValue{
|
|
|
|
Paths: []networking.HTTPIngressPath{
|
2018-12-05 14:39:19 +00:00
|
|
|
{
|
2021-08-21 20:42:00 +00:00
|
|
|
Path: path,
|
|
|
|
PathType: &pathtype,
|
2019-12-12 23:12:12 +00:00
|
|
|
Backend: networking.IngressBackend{
|
2021-08-21 20:42:00 +00:00
|
|
|
Service: &networking.IngressServiceBackend{
|
|
|
|
Name: service,
|
|
|
|
Port: networking.ServiceBackendPort{
|
|
|
|
Number: int32(port),
|
|
|
|
},
|
|
|
|
},
|
2018-04-18 19:15:08 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-10-29 21:39:04 +00:00
|
|
|
|
2019-12-28 22:56:13 +00:00
|
|
|
// allow ingresses without host field
|
|
|
|
if host != "" {
|
|
|
|
spec.Rules[0].Host = host
|
|
|
|
}
|
|
|
|
|
2019-01-09 19:13:17 +00:00
|
|
|
if len(tlsHosts) > 0 {
|
2019-12-12 23:12:12 +00:00
|
|
|
spec.TLS = []networking.IngressTLS{
|
2018-08-23 00:25:21 +00:00
|
|
|
{
|
2019-01-09 19:13:17 +00:00
|
|
|
Hosts: tlsHosts,
|
2018-08-23 00:25:21 +00:00
|
|
|
SecretName: host,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2018-12-05 14:39:19 +00:00
|
|
|
return newSingleIngress(name, ns, annotations, spec)
|
|
|
|
}
|
|
|
|
|
2019-01-25 19:53:55 +00:00
|
|
|
// NewSingleIngressWithBackendAndRules creates an ingress with both a default backend and a rule
|
2019-12-13 05:47:11 +00:00
|
|
|
func NewSingleIngressWithBackendAndRules(name, path, host, ns, defaultService string, defaultPort int, service string, port int, annotations map[string]string) *networking.Ingress {
|
2021-08-21 20:42:00 +00:00
|
|
|
pathtype := networking.PathTypePrefix
|
2019-12-12 23:12:12 +00:00
|
|
|
spec := networking.IngressSpec{
|
2021-08-21 20:42:00 +00:00
|
|
|
IngressClassName: GetIngressClassName(ns),
|
|
|
|
DefaultBackend: &networking.IngressBackend{
|
|
|
|
Service: &networking.IngressServiceBackend{
|
|
|
|
Name: defaultService,
|
|
|
|
Port: networking.ServiceBackendPort{
|
|
|
|
Number: int32(defaultPort),
|
|
|
|
},
|
|
|
|
},
|
2019-01-25 19:53:55 +00:00
|
|
|
},
|
2019-12-12 23:12:12 +00:00
|
|
|
Rules: []networking.IngressRule{
|
2019-01-25 19:53:55 +00:00
|
|
|
{
|
|
|
|
Host: host,
|
2019-12-12 23:12:12 +00:00
|
|
|
IngressRuleValue: networking.IngressRuleValue{
|
|
|
|
HTTP: &networking.HTTPIngressRuleValue{
|
|
|
|
Paths: []networking.HTTPIngressPath{
|
2019-01-25 19:53:55 +00:00
|
|
|
{
|
2021-08-21 20:42:00 +00:00
|
|
|
Path: path,
|
|
|
|
PathType: &pathtype,
|
2019-12-12 23:12:12 +00:00
|
|
|
Backend: networking.IngressBackend{
|
2021-08-21 20:42:00 +00:00
|
|
|
Service: &networking.IngressServiceBackend{
|
|
|
|
Name: service,
|
|
|
|
Port: networking.ServiceBackendPort{
|
|
|
|
Number: int32(port),
|
|
|
|
},
|
|
|
|
},
|
2019-01-25 19:53:55 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return newSingleIngress(name, ns, annotations, spec)
|
|
|
|
}
|
|
|
|
|
2018-12-05 14:39:19 +00:00
|
|
|
// NewSingleCatchAllIngress creates a simple ingress with a catch-all backend
|
2019-12-13 05:47:11 +00:00
|
|
|
func NewSingleCatchAllIngress(name, ns, service string, port int, annotations map[string]string) *networking.Ingress {
|
2019-12-12 23:12:12 +00:00
|
|
|
spec := networking.IngressSpec{
|
2021-08-21 20:42:00 +00:00
|
|
|
IngressClassName: GetIngressClassName(ns),
|
|
|
|
DefaultBackend: &networking.IngressBackend{
|
|
|
|
Service: &networking.IngressServiceBackend{
|
|
|
|
Name: service,
|
|
|
|
Port: networking.ServiceBackendPort{
|
|
|
|
Number: int32(port),
|
|
|
|
},
|
|
|
|
},
|
2018-12-05 14:39:19 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
return newSingleIngress(name, ns, annotations, spec)
|
|
|
|
}
|
|
|
|
|
2019-12-13 05:47:11 +00:00
|
|
|
func newSingleIngress(name, ns string, annotations map[string]string, spec networking.IngressSpec) *networking.Ingress {
|
2019-12-12 23:12:12 +00:00
|
|
|
ing := &networking.Ingress{
|
2018-12-05 14:39:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
2019-12-13 05:47:11 +00:00
|
|
|
Name: name,
|
|
|
|
Namespace: ns,
|
2018-12-05 14:39:19 +00:00
|
|
|
},
|
|
|
|
Spec: spec,
|
|
|
|
}
|
2020-02-19 03:08:14 +00:00
|
|
|
|
|
|
|
if annotations == nil {
|
|
|
|
annotations = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
2019-12-13 05:47:11 +00:00
|
|
|
ing.SetAnnotations(annotations)
|
2018-12-05 14:39:19 +00:00
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
return ing
|
|
|
|
}
|
2020-06-27 15:57:00 +00:00
|
|
|
|
|
|
|
// defaultWaitDuration default sleep time for operations related
|
|
|
|
// to the API server and NGINX reloads.
|
|
|
|
var defaultWaitDuration = 5 * time.Second
|
|
|
|
|
|
|
|
// Sleep pauses the current goroutine for at least the duration d.
|
|
|
|
// If no duration is defined, it uses a default
|
|
|
|
func Sleep(duration ...time.Duration) {
|
|
|
|
sleepFor := defaultWaitDuration
|
|
|
|
if len(duration) != 0 {
|
|
|
|
sleepFor = duration[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(sleepFor)
|
|
|
|
}
|
2020-10-26 14:24:55 +00:00
|
|
|
|
|
|
|
func loadConfig() (*restclient.Config, error) {
|
|
|
|
config, err := rest.InClusterConfig()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
config.UserAgent = "ingress-nginx-e2e"
|
|
|
|
return config, nil
|
|
|
|
}
|