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 (
|
|
|
|
"fmt"
|
2018-07-07 17:46:18 +00:00
|
|
|
"os"
|
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
|
|
|
|
2018-04-01 20:09:27 +00:00
|
|
|
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
2019-01-09 19:13:17 +00:00
|
|
|
v1 "k8s.io/api/core/v1"
|
2018-04-18 19:15:08 +00:00
|
|
|
extensions "k8s.io/api/extensions/v1beta1"
|
2017-10-17 22:50:27 +00:00
|
|
|
apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
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"
|
2018-04-18 19:15:08 +00:00
|
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
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"
|
2017-11-12 16:52:55 +00:00
|
|
|
restclient "k8s.io/client-go/rest"
|
2017-10-17 22:50:27 +00:00
|
|
|
|
2018-04-01 20:09:27 +00:00
|
|
|
"github.com/pkg/errors"
|
2018-12-05 16:28:28 +00:00
|
|
|
"k8s.io/klog"
|
2018-01-23 23:37:47 +00:00
|
|
|
|
2017-10-17 22:50:27 +00:00
|
|
|
. "github.com/onsi/ginkgo"
|
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
)
|
|
|
|
|
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
|
|
|
|
|
|
|
|
// To make sure that this framework cleans up after itself, no matter what,
|
2018-03-07 16:37:30 +00:00
|
|
|
// we install a Cleanup action before each test and clear it after. If we
|
2017-10-17 22:50:27 +00:00
|
|
|
// should abort, the AfterSuite hook should run all Cleanup actions.
|
|
|
|
cleanupHandle CleanupActionHandle
|
2017-11-10 02:00:38 +00:00
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
IngressController *ingressController
|
|
|
|
}
|
|
|
|
|
|
|
|
type ingressController struct {
|
|
|
|
HTTPURL string
|
|
|
|
HTTPSURL string
|
2018-04-16 19:30:35 +00:00
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
Namespace string
|
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 {
|
|
|
|
f := &Framework{
|
2018-04-18 19:15:08 +00:00
|
|
|
BaseName: baseName,
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BeforeEach(f.BeforeEach)
|
|
|
|
AfterEach(f.AfterEach)
|
|
|
|
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
// BeforeEach gets a client and makes a namespace.
|
|
|
|
func (f *Framework) BeforeEach() {
|
|
|
|
f.cleanupHandle = AddCleanupAction(f.AfterEach)
|
|
|
|
|
|
|
|
By("Creating a kubernetes client")
|
|
|
|
kubeConfig, err := LoadConfig(TestContext.KubeConfig, TestContext.KubeContext)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
2017-11-12 16:52:55 +00:00
|
|
|
f.KubeConfig = kubeConfig
|
2017-10-17 22:50:27 +00:00
|
|
|
f.KubeClientSet, err = kubernetes.NewForConfig(kubeConfig)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
By("Building a namespace api object")
|
2018-04-18 19:15:08 +00:00
|
|
|
ingressNamespace, err := CreateKubeNamespace(f.BaseName, f.KubeClientSet)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
f.IngressController = &ingressController{
|
|
|
|
Namespace: ingressNamespace,
|
|
|
|
}
|
|
|
|
|
|
|
|
By("Starting new ingress controller")
|
|
|
|
err = f.NewIngressController(f.IngressController.Namespace)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
2018-11-30 21:55:53 +00:00
|
|
|
err = WaitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.IngressController.Namespace, metav1.ListOptions{
|
2018-09-04 03:25:30 +00:00
|
|
|
LabelSelector: "app.kubernetes.io/name=ingress-nginx",
|
2018-04-18 19:15:08 +00:00
|
|
|
})
|
2017-10-17 22:50:27 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
2017-11-10 02:00:38 +00:00
|
|
|
|
2018-10-29 21:39:04 +00:00
|
|
|
HTTPURL := f.GetNginxURL(HTTP)
|
2018-04-18 19:15:08 +00:00
|
|
|
f.IngressController.HTTPURL = HTTPURL
|
|
|
|
|
2018-10-29 21:39:04 +00:00
|
|
|
HTTPSURL := f.GetNginxURL(HTTPS)
|
2018-04-18 19:15:08 +00:00
|
|
|
f.IngressController.HTTPSURL = HTTPSURL
|
|
|
|
|
|
|
|
// we wait for any change in the informers and SSL certificate generation
|
|
|
|
time.Sleep(5 * time.Second)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AfterEach deletes the namespace, after reading its events.
|
|
|
|
func (f *Framework) AfterEach() {
|
|
|
|
RemoveCleanupAction(f.cleanupHandle)
|
|
|
|
|
|
|
|
By("Waiting for test namespace to no longer exist")
|
2018-04-18 19:15:08 +00:00
|
|
|
err := DeleteKubeNamespace(f.KubeClientSet, f.IngressController.Namespace)
|
2018-04-16 19:30:35 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
2018-08-03 13:50:53 +00:00
|
|
|
|
|
|
|
if CurrentGinkgoTestDescription().Failed {
|
|
|
|
log, err := f.NginxLogs()
|
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
By("Dumping NGINX logs after a failure running a test")
|
|
|
|
Logf("%v", log)
|
|
|
|
}
|
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 {
|
|
|
|
return Describe("[nginx-ingress] "+text, body)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNginxIP returns the IP address of the minikube cluster
|
|
|
|
// where the NGINX ingress controller is running
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) GetNginxIP() string {
|
|
|
|
nodeIP := os.Getenv("NODE_IP")
|
|
|
|
Expect(nodeIP).NotTo(BeEmpty(), "env variable NODE_IP is empty")
|
|
|
|
return nodeIP
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetNginxPort returns the number of TCP port where NGINX is running
|
|
|
|
func (f *Framework) GetNginxPort(name string) (int, error) {
|
2018-04-18 19:15:08 +00:00
|
|
|
s, err := f.KubeClientSet.
|
|
|
|
CoreV1().
|
|
|
|
Services(f.IngressController.Namespace).
|
|
|
|
Get("ingress-nginx", metav1.GetOptions{})
|
2017-10-17 22:50:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return -1, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, p := range s.Spec.Ports {
|
|
|
|
if p.NodePort != 0 && p.Name == name {
|
|
|
|
return int(p.NodePort), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNginxURL returns the URL should be used to make a request to NGINX
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) GetNginxURL(scheme RequestScheme) string {
|
|
|
|
ip := f.GetNginxIP()
|
2017-10-17 22:50:27 +00:00
|
|
|
port, err := f.GetNginxPort(fmt.Sprintf("%v", scheme))
|
2018-10-29 21:39:04 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error obtaning NGINX Port")
|
2017-10-17 22:50:27 +00:00
|
|
|
|
2018-10-29 21:39:04 +00:00
|
|
|
return fmt.Sprintf("%v://%v:%v", scheme, ip, port)
|
2017-10-17 22:50:27 +00:00
|
|
|
}
|
2017-11-10 02:00:38 +00:00
|
|
|
|
2017-11-12 16:52:55 +00:00
|
|
|
// WaitForNginxServer waits until the nginx configuration contains a particular server section
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) bool) {
|
|
|
|
err := wait.Poll(Poll, time.Minute*5, f.matchNginxConditions(name, matcher))
|
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error waiting for nginx server condition/s")
|
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
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) WaitForNginxConfiguration(matcher func(cfg string) bool) {
|
|
|
|
err := wait.Poll(Poll, time.Minute*5, f.matchNginxConditions("", matcher))
|
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error waiting for nginx server condition/s")
|
2018-01-17 12:26:53 +00:00
|
|
|
}
|
|
|
|
|
2018-10-29 16:01:41 +00:00
|
|
|
func nginxLogs(client kubernetes.Interface, namespace string) (string, error) {
|
2018-11-29 13:53:48 +00:00
|
|
|
pod, err := getIngressNGINXPod(namespace, client)
|
2017-11-14 20:50:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2018-11-29 13:53:48 +00:00
|
|
|
if isRunning, err := podRunningReady(pod); err == nil && isRunning {
|
|
|
|
return Logs(pod)
|
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
|
|
|
}
|
|
|
|
|
2018-10-29 16:01:41 +00:00
|
|
|
// NginxLogs returns the logs of the nginx ingress controller pod running
|
|
|
|
func (f *Framework) NginxLogs() (string, error) {
|
|
|
|
return nginxLogs(f.KubeClientSet, f.IngressController.Namespace)
|
|
|
|
}
|
|
|
|
|
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-11-29 13:53:48 +00:00
|
|
|
pod, err := getIngressNGINXPod(f.IngressController.Namespace, f.KubeClientSet)
|
2017-11-12 16:52:55 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-01-23 20:09:41 +00:00
|
|
|
o, err := f.ExecCommand(pod, cmd)
|
2017-11-12 16:52:55 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
2017-11-22 13:54:44 +00:00
|
|
|
var match bool
|
|
|
|
errs := InterceptGomegaFailures(func() {
|
2018-12-05 16:27:55 +00:00
|
|
|
if klog.V(10) && len(o) > 0 {
|
|
|
|
klog.Infof("nginx.conf:\n%v", o)
|
2018-04-18 19:15:08 +00:00
|
|
|
}
|
|
|
|
|
2018-10-06 03:35:56 +00:00
|
|
|
// passes the nginx config to the passed function
|
2018-04-25 21:38:30 +00:00
|
|
|
if matcher(strings.Join(strings.Fields(o), " ")) {
|
2017-11-22 13:54:44 +00:00
|
|
|
match = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if match {
|
2017-11-12 16:52:55 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
if len(errs) > 0 {
|
2018-12-05 16:27:55 +00:00
|
|
|
klog.V(2).Infof("Errors waiting for conditions: %v", errs)
|
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
|
|
|
|
2018-04-16 19:30:35 +00:00
|
|
|
func (f *Framework) getNginxConfigMap() (*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().
|
|
|
|
ConfigMaps(f.IngressController.Namespace).
|
|
|
|
Get("nginx-configuration", metav1.GetOptions{})
|
2018-04-10 18:14:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return config, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNginxConfigMapData gets ingress-nginx's nginx-configuration map's data
|
|
|
|
func (f *Framework) GetNginxConfigMapData() (map[string]string, error) {
|
2018-04-16 19:30:35 +00:00
|
|
|
config, err := f.getNginxConfigMap()
|
2018-04-10 18:14:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if config.Data == nil {
|
|
|
|
config.Data = map[string]string{}
|
|
|
|
}
|
|
|
|
|
|
|
|
return config.Data, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetNginxConfigMapData sets ingress-nginx's nginx-configuration configMap data
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) SetNginxConfigMapData(cmData map[string]string) {
|
2018-04-10 18:14:36 +00:00
|
|
|
// Needs to do a Get and Set, Update will not take just the Data field
|
|
|
|
// or a configMap that is not the very last revision
|
2018-04-16 19:30:35 +00:00
|
|
|
config, err := f.getNginxConfigMap()
|
2018-10-29 21:39:04 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(config).NotTo(BeNil(), "expected a configmap but none returned")
|
2018-04-10 18:14:36 +00:00
|
|
|
|
|
|
|
config.Data = cmData
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
_, err = f.KubeClientSet.
|
|
|
|
CoreV1().
|
|
|
|
ConfigMaps(f.IngressController.Namespace).
|
|
|
|
Update(config)
|
2018-10-29 21:39:04 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
2018-04-10 18:14:36 +00:00
|
|
|
|
2018-05-17 21:50:21 +00:00
|
|
|
time.Sleep(5 * time.Second)
|
2018-04-10 18:14:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateNginxConfigMapData updates single field in ingress-nginx's nginx-configuration map data
|
2018-10-29 21:39:04 +00:00
|
|
|
func (f *Framework) UpdateNginxConfigMapData(key string, value string) {
|
2018-04-10 18:14:36 +00:00
|
|
|
config, err := f.GetNginxConfigMapData()
|
2018-10-29 21:39:04 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error reading configmap")
|
2018-04-10 18:14:36 +00:00
|
|
|
|
|
|
|
config[key] = value
|
|
|
|
|
2018-10-29 21:39:04 +00:00
|
|
|
f.SetNginxConfigMapData(config)
|
2018-04-10 18:14:36 +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) {
|
|
|
|
ns := f.IngressController.Namespace
|
|
|
|
pod, err := getIngressNGINXPod(ns, f.KubeClientSet)
|
|
|
|
Expect(err).NotTo(HaveOccurred(), "expected ingress nginx pod to be running")
|
|
|
|
|
|
|
|
err = f.KubeClientSet.CoreV1().Pods(ns).Delete(pod.GetName(), metav1.NewDeleteOptions(grace))
|
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error deleting ingress nginx pod")
|
|
|
|
|
|
|
|
err = wait.Poll(Poll, time.Minute*5, func() (bool, error) {
|
|
|
|
pod, err := getIngressNGINXPod(ns, f.KubeClientSet)
|
|
|
|
if err != nil || pod == nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return pod.GetName() != "", nil
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred(), "unexpected error while waiting for ingress nginx pod to come up again")
|
|
|
|
}
|
|
|
|
|
2018-04-01 20:09:27 +00:00
|
|
|
// UpdateDeployment runs the given updateFunc on the deployment and waits for it to be updated
|
|
|
|
func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name string, replicas int, updateFunc func(d *appsv1beta1.Deployment) error) error {
|
|
|
|
deployment, err := kubeClientSet.AppsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
if updateFunc != nil {
|
|
|
|
if err := updateFunc(deployment); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if *deployment.Spec.Replicas != int32(replicas) {
|
2018-12-05 16:27:55 +00:00
|
|
|
klog.Infof("updating replica count from %v to %v...", *deployment.Spec.Replicas, replicas)
|
2018-04-18 19:15:08 +00:00
|
|
|
deployment, err := kubeClientSet.AppsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
deployment.Spec.Replicas = NewInt32(int32(replicas))
|
|
|
|
_, err = kubeClientSet.AppsV1beta1().Deployments(namespace).Update(deployment)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "scaling the number of replicas to %v", replicas)
|
|
|
|
}
|
2018-04-01 20:09:27 +00:00
|
|
|
}
|
|
|
|
|
2018-11-30 21:55:53 +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 {
|
2018-10-29 16:01:41 +00:00
|
|
|
return errors.Wrapf(err, "waiting for nginx-ingress-controller replica count to be %v", replicas)
|
2018-04-01 20:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2018-12-11 21:57:46 +00:00
|
|
|
// UpdateIngress runs the given updateFunc on the ingress
|
|
|
|
func UpdateIngress(kubeClientSet kubernetes.Interface, namespace string, name string, updateFunc func(d *extensions.Ingress) error) error {
|
|
|
|
ingress, err := kubeClientSet.ExtensionsV1beta1().Ingresses(namespace).Get(name, metav1.GetOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := updateFunc(ingress); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = kubeClientSet.ExtensionsV1beta1().Ingresses(namespace).Update(ingress)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-08-23 00:25:21 +00:00
|
|
|
// NewSingleIngressWithTLS creates a simple ingress rule with TLS spec included
|
2019-01-09 19:13:17 +00:00
|
|
|
func NewSingleIngressWithTLS(name, path, host string, tlsHosts []string, ns, service string, port int, annotations *map[string]string) *extensions.Ingress {
|
|
|
|
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
|
2018-05-17 12:35:11 +00:00
|
|
|
func NewSingleIngress(name, path, host, ns, service string, port int, annotations *map[string]string) *extensions.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
|
|
|
}
|
|
|
|
|
2019-01-09 19:13:17 +00:00
|
|
|
func newSingleIngressWithRules(name, path, host, ns, service string, port int, annotations *map[string]string, tlsHosts []string) *extensions.Ingress {
|
2018-04-18 19:15:08 +00:00
|
|
|
|
2018-12-05 14:39:19 +00:00
|
|
|
spec := extensions.IngressSpec{
|
|
|
|
Rules: []extensions.IngressRule{
|
|
|
|
{
|
|
|
|
Host: host,
|
|
|
|
IngressRuleValue: extensions.IngressRuleValue{
|
|
|
|
HTTP: &extensions.HTTPIngressRuleValue{
|
|
|
|
Paths: []extensions.HTTPIngressPath{
|
|
|
|
{
|
|
|
|
Path: path,
|
|
|
|
Backend: extensions.IngressBackend{
|
|
|
|
ServiceName: service,
|
|
|
|
ServicePort: intstr.FromInt(port),
|
2018-04-18 19:15:08 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-10-29 21:39:04 +00:00
|
|
|
|
2019-01-09 19:13:17 +00:00
|
|
|
if len(tlsHosts) > 0 {
|
2018-12-05 14:39:19 +00:00
|
|
|
spec.TLS = []extensions.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)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSingleCatchAllIngress creates a simple ingress with a catch-all backend
|
|
|
|
func NewSingleCatchAllIngress(name, ns, service string, port int, annotations *map[string]string) *extensions.Ingress {
|
|
|
|
spec := extensions.IngressSpec{
|
|
|
|
Backend: &extensions.IngressBackend{
|
|
|
|
ServiceName: service,
|
|
|
|
ServicePort: intstr.FromInt(port),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return newSingleIngress(name, ns, annotations, spec)
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSingleIngress(name, ns string, annotations *map[string]string, spec extensions.IngressSpec) *extensions.Ingress {
|
|
|
|
if annotations == nil {
|
|
|
|
annotations = &map[string]string{}
|
|
|
|
}
|
|
|
|
|
|
|
|
ing := &extensions.Ingress{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: name,
|
|
|
|
Namespace: ns,
|
|
|
|
Annotations: *annotations,
|
|
|
|
},
|
|
|
|
Spec: spec,
|
|
|
|
}
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
return ing
|
|
|
|
}
|