Merge pull request #2789 from diazjf/mock-kube-in-unit-tests
Remove KubeConfig Dependency for Store Tests
This commit is contained in:
commit
96c289b1f9
4 changed files with 254 additions and 152 deletions
|
@ -33,9 +33,6 @@ jobs:
|
||||||
script:
|
script:
|
||||||
- make lua-test
|
- make lua-test
|
||||||
- stage: Coverage
|
- stage: Coverage
|
||||||
before_script:
|
|
||||||
# start minikube
|
|
||||||
- test/e2e/up.sh
|
|
||||||
script:
|
script:
|
||||||
- make cover
|
- make cover
|
||||||
- stage: e2e
|
- stage: e2e
|
||||||
|
|
|
@ -272,7 +272,6 @@ func registerHealthz(ic *controller.NGINXController, mux *http.ServeMux) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerMetrics(reg *prometheus.Registry, mux *http.ServeMux) {
|
func registerMetrics(reg *prometheus.Registry, mux *http.ServeMux) {
|
||||||
|
|
||||||
mux.Handle(
|
mux.Handle(
|
||||||
"/metrics",
|
"/metrics",
|
||||||
promhttp.InstrumentMetricHandler(
|
promhttp.InstrumentMetricHandler(
|
||||||
|
|
|
@ -18,46 +18,51 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
"k8s.io/ingress-nginx/internal/file"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/controller"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/internal/file"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/controller"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateApiserverClient(t *testing.T) {
|
func TestCreateApiserverClient(t *testing.T) {
|
||||||
home := os.Getenv("HOME")
|
_, err := createApiserverClient("", "")
|
||||||
kubeConfigFile := fmt.Sprintf("%v/.kube/config", home)
|
|
||||||
|
|
||||||
cli, err := createApiserverClient("", kubeConfigFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected error creating Kubernetes REST client: %v", err)
|
|
||||||
}
|
|
||||||
if cli == nil {
|
|
||||||
t.Fatal("Expected a REST client but none returned.")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = createApiserverClient("", "")
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected an error creating REST client without an API server URL or kubeconfig file.")
|
t.Fatal("Expected an error creating REST client without an API server URL or kubeconfig file.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandleSigterm(t *testing.T) {
|
func TestHandleSigterm(t *testing.T) {
|
||||||
home := os.Getenv("HOME")
|
clientSet := fake.NewSimpleClientset()
|
||||||
kubeConfigFile := fmt.Sprintf("%v/.kube/config", home)
|
|
||||||
|
|
||||||
cli, err := createApiserverClient("", kubeConfigFile)
|
ns := "test"
|
||||||
|
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
|
name := "test"
|
||||||
|
pod := v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: ns,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := clientSet.CoreV1().Pods(ns).Create(&pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error creating Kubernetes REST client: %v", err)
|
t.Fatalf("error creating pod %v: %v", pod, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resetForTesting(func() { t.Fatal("bad parse") })
|
resetForTesting(func() { t.Fatal("bad parse") })
|
||||||
|
|
||||||
os.Setenv("POD_NAME", "test")
|
os.Setenv("POD_NAME", name)
|
||||||
os.Setenv("POD_NAMESPACE", "test")
|
os.Setenv("POD_NAMESPACE", ns)
|
||||||
defer os.Setenv("POD_NAME", "")
|
defer os.Setenv("POD_NAME", "")
|
||||||
defer os.Setenv("POD_NAMESPACE", "")
|
defer os.Setenv("POD_NAMESPACE", "")
|
||||||
|
|
||||||
|
@ -69,7 +74,7 @@ func TestHandleSigterm(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error creating NGINX controller: %v", err)
|
t.Errorf("Unexpected error creating NGINX controller: %v", err)
|
||||||
}
|
}
|
||||||
conf.Client = cli
|
conf.Client = clientSet
|
||||||
|
|
||||||
fs, err := file.NewFakeFS()
|
fs, err := file.NewFakeFS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -93,8 +98,40 @@ func TestHandleSigterm(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Unexpected error sending SIGTERM signal.")
|
t.Error("Unexpected error sending SIGTERM signal.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = clientSet.CoreV1().Pods(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deleting pod %v: %v", pod, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterHandlers(t *testing.T) {
|
func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) string {
|
||||||
// TODO
|
t.Helper()
|
||||||
|
t.Log("Creating temporal config map")
|
||||||
|
|
||||||
|
configMap := &v1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "config",
|
||||||
|
SelfLink: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/config", ns),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cm, err := clientSet.CoreV1().ConfigMaps(ns).Create(configMap)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating the configuration map: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Temporal configmap %v created", cm)
|
||||||
|
|
||||||
|
return cm.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteConfigMap(cm, ns string, clientSet kubernetes.Interface, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
t.Logf("Deleting temporal configmap %v", cm)
|
||||||
|
|
||||||
|
err := clientSet.CoreV1().ConfigMaps(ns).Delete(cm, &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error deleting the configmap: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Temporal configmap %v deleted", cm)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,48 +18,36 @@ package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eapache/channels"
|
"github.com/eapache/channels"
|
||||||
"k8s.io/api/extensions/v1beta1"
|
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/ingress-nginx/internal/file"
|
"k8s.io/ingress-nginx/internal/file"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStore(t *testing.T) {
|
func TestStore(t *testing.T) {
|
||||||
// TODO: find a way to avoid the need to use a real api server
|
clientSet := fake.NewSimpleClientset()
|
||||||
home := os.Getenv("HOME")
|
|
||||||
kubeConfigFile := fmt.Sprintf("%v/.kube/config", home)
|
|
||||||
kubeContext := ""
|
|
||||||
|
|
||||||
kubeConfig, err := framework.LoadConfig(kubeConfigFile, kubeContext)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error loading kubeconfig file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
clientSet, err := kubernetes.NewForConfig(kubeConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error creating ingress client: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("should return an error searching for non existing objects", func(t *testing.T) {
|
t.Run("should return an error searching for non existing objects", func(t *testing.T) {
|
||||||
ns := createNamespace(clientSet, t)
|
ns := createNamespace(clientSet, t)
|
||||||
defer deleteNamespace(ns, clientSet, t)
|
defer deleteNamespace(ns, clientSet, t)
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
updateCh := channels.NewRingChannel(1024)
|
updateCh := channels.NewRingChannel(1024)
|
||||||
|
@ -121,6 +109,8 @@ func TestStore(t *testing.T) {
|
||||||
t.Run("should return one event for add, update and delete of ingress", func(t *testing.T) {
|
t.Run("should return one event for add, update and delete of ingress", func(t *testing.T) {
|
||||||
ns := createNamespace(clientSet, t)
|
ns := createNamespace(clientSet, t)
|
||||||
defer deleteNamespace(ns, clientSet, t)
|
defer deleteNamespace(ns, clientSet, t)
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
updateCh := channels.NewRingChannel(1024)
|
updateCh := channels.NewRingChannel(1024)
|
||||||
|
@ -141,8 +131,9 @@ func TestStore(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := e.Obj.(*extensions.Ingress); !ok {
|
if _, ok := e.Obj.(*extensions.Ingress); !ok {
|
||||||
t.Errorf("expected an Ingress type but %T returned", e.Obj)
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
case CreateEvent:
|
case CreateEvent:
|
||||||
atomic.AddUint64(&add, 1)
|
atomic.AddUint64(&add, 1)
|
||||||
|
@ -168,21 +159,22 @@ func TestStore(t *testing.T) {
|
||||||
|
|
||||||
storer.Run(stopCh)
|
storer.Run(stopCh)
|
||||||
|
|
||||||
ing, err := ensureIngress(&v1beta1.Ingress{
|
ing := ensureIngress(&extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "dummy",
|
Name: "dummy",
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
SelfLink: fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses/dummy", ns),
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "dummy",
|
Host: "dummy",
|
||||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
IngressRuleValue: extensions.IngressRuleValue{
|
||||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
HTTP: &extensions.HTTPIngressRuleValue{
|
||||||
Paths: []v1beta1.HTTPIngressPath{
|
Paths: []extensions.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: v1beta1.IngressBackend{
|
Backend: extensions.IngressBackend{
|
||||||
ServiceName: "http-svc",
|
ServiceName: "http-svc",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
@ -193,30 +185,34 @@ func TestStore(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, clientSet)
|
}, clientSet, t)
|
||||||
|
|
||||||
|
err := framework.WaitForIngressInNamespace(clientSet, ns, ing.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
// create an invalid ingress (different class)
|
// create an invalid ingress (different class)
|
||||||
_, err = ensureIngress(&v1beta1.Ingress{
|
invalidIngress := ensureIngress(&extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "custom-class",
|
Name: "custom-class",
|
||||||
|
SelfLink: fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses/custom-class", ns),
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"kubernetes.io/ingress.class": "something",
|
"kubernetes.io/ingress.class": "something",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "dummy",
|
Host: "dummy",
|
||||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
IngressRuleValue: extensions.IngressRuleValue{
|
||||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
HTTP: &extensions.HTTPIngressRuleValue{
|
||||||
Paths: []v1beta1.HTTPIngressPath{
|
Paths: []extensions.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: v1beta1.IngressBackend{
|
Backend: extensions.IngressBackend{
|
||||||
ServiceName: "http-svc",
|
ServiceName: "http-svc",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
@ -227,26 +223,28 @@ func TestStore(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, clientSet)
|
}, clientSet, t)
|
||||||
if err != nil {
|
defer deleteIngress(invalidIngress, clientSet, t)
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ni := ing.DeepCopy()
|
ni := ing.DeepCopy()
|
||||||
ni.Spec.Rules[0].Host = "update-dummy"
|
ni.Spec.Rules[0].Host = "update-dummy"
|
||||||
_, err = ensureIngress(ni, clientSet)
|
_ = ensureIngress(ni, clientSet, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
t.Errorf("error creating ingress: %v", err)
|
||||||
|
}
|
||||||
|
// Secret takes a bit to update
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
err = clientSet.Extensions().Ingresses(ni.Namespace).Delete(ni.Name, &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating ingress: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = clientSet.ExtensionsV1beta1().
|
err = framework.WaitForNoIngressInNamespace(clientSet, ni.Namespace, ni.Name)
|
||||||
Ingresses(ni.Namespace).
|
|
||||||
Delete(ni.Name, &metav1.DeleteOptions{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
framework.WaitForNoIngressInNamespace(clientSet, ni.Namespace, ni.Name)
|
|
||||||
|
|
||||||
if atomic.LoadUint64(&add) != 1 {
|
if atomic.LoadUint64(&add) != 1 {
|
||||||
t.Errorf("expected 1 event of type Create but %v occurred", add)
|
t.Errorf("expected 1 event of type Create but %v occurred", add)
|
||||||
|
@ -262,6 +260,8 @@ func TestStore(t *testing.T) {
|
||||||
t.Run("should not receive events from secret not referenced from ingress", func(t *testing.T) {
|
t.Run("should not receive events from secret not referenced from ingress", func(t *testing.T) {
|
||||||
ns := createNamespace(clientSet, t)
|
ns := createNamespace(clientSet, t)
|
||||||
defer deleteNamespace(ns, clientSet, t)
|
defer deleteNamespace(ns, clientSet, t)
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
updateCh := channels.NewRingChannel(1024)
|
updateCh := channels.NewRingChannel(1024)
|
||||||
|
@ -307,14 +307,14 @@ func TestStore(t *testing.T) {
|
||||||
storer.Run(stopCh)
|
storer.Run(stopCh)
|
||||||
|
|
||||||
secretName := "not-referenced"
|
secretName := "not-referenced"
|
||||||
_, err = framework.CreateIngressTLSSecret(clientSet, []string{"foo"}, secretName, ns)
|
_, err := framework.CreateIngressTLSSecret(clientSet, []string{"foo"}, secretName, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating secret: %v", err)
|
t.Errorf("error creating secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = framework.WaitForSecretInNamespace(clientSet, ns, secretName)
|
err = framework.WaitForSecretInNamespace(clientSet, ns, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for secret: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if atomic.LoadUint64(&add) != 0 {
|
if atomic.LoadUint64(&add) != 0 {
|
||||||
|
@ -329,7 +329,7 @@ func TestStore(t *testing.T) {
|
||||||
|
|
||||||
err = clientSet.CoreV1().Secrets(ns).Delete(secretName, &metav1.DeleteOptions{})
|
err = clientSet.CoreV1().Secrets(ns).Delete(secretName, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error deleting secret: %v", err)
|
t.Errorf("error deleting secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
@ -348,6 +348,8 @@ func TestStore(t *testing.T) {
|
||||||
t.Run("should receive events from secret referenced from ingress", func(t *testing.T) {
|
t.Run("should receive events from secret referenced from ingress", func(t *testing.T) {
|
||||||
ns := createNamespace(clientSet, t)
|
ns := createNamespace(clientSet, t)
|
||||||
defer deleteNamespace(ns, clientSet, t)
|
defer deleteNamespace(ns, clientSet, t)
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
updateCh := channels.NewRingChannel(1024)
|
updateCh := channels.NewRingChannel(1024)
|
||||||
|
@ -395,40 +397,39 @@ func TestStore(t *testing.T) {
|
||||||
ingressName := "ingress-with-secret"
|
ingressName := "ingress-with-secret"
|
||||||
secretName := "referenced"
|
secretName := "referenced"
|
||||||
|
|
||||||
_, err := ensureIngress(&v1beta1.Ingress{
|
ing := ensureIngress(&extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ingressName,
|
Name: ingressName,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
SelfLink: fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses/%s", ns, ingressName),
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
TLS: []v1beta1.IngressTLS{
|
TLS: []extensions.IngressTLS{
|
||||||
{
|
{
|
||||||
SecretName: secretName,
|
SecretName: secretName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Backend: &v1beta1.IngressBackend{
|
Backend: &extensions.IngressBackend{
|
||||||
ServiceName: "http-svc",
|
ServiceName: "http-svc",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, clientSet)
|
}, clientSet, t)
|
||||||
if err != nil {
|
defer deleteIngress(ing, clientSet, t)
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = framework.WaitForIngressInNamespace(clientSet, ns, ingressName)
|
err := framework.WaitForIngressInNamespace(clientSet, ns, ingressName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for secret: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = framework.CreateIngressTLSSecret(clientSet, []string{"foo"}, secretName, ns)
|
_, err = framework.CreateIngressTLSSecret(clientSet, []string{"foo"}, secretName, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating secret: %v", err)
|
t.Errorf("error creating secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = framework.WaitForSecretInNamespace(clientSet, ns, secretName)
|
err = framework.WaitForSecretInNamespace(clientSet, ns, secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for secret: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// take into account secret sync
|
// take into account secret sync
|
||||||
|
@ -444,7 +445,7 @@ func TestStore(t *testing.T) {
|
||||||
|
|
||||||
err = clientSet.CoreV1().Secrets(ns).Delete(secretName, &metav1.DeleteOptions{})
|
err = clientSet.CoreV1().Secrets(ns).Delete(secretName, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error deleting secret: %v", err)
|
t.Errorf("error deleting secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
@ -452,11 +453,14 @@ func TestStore(t *testing.T) {
|
||||||
if atomic.LoadUint64(&del) != 1 {
|
if atomic.LoadUint64(&del) != 1 {
|
||||||
t.Errorf("expected 1 events of type Delete but %v occurred", del)
|
t.Errorf("expected 1 events of type Delete but %v occurred", del)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should create an ingress with a secret which does not exist", func(t *testing.T) {
|
t.Run("should create an ingress with a secret which does not exist", func(t *testing.T) {
|
||||||
ns := createNamespace(clientSet, t)
|
ns := createNamespace(clientSet, t)
|
||||||
defer deleteNamespace(ns, clientSet, t)
|
defer deleteNamespace(ns, clientSet, t)
|
||||||
|
cm := createConfigMap(clientSet, ns, t)
|
||||||
|
defer deleteConfigMap(cm, ns, clientSet, t)
|
||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
updateCh := channels.NewRingChannel(1024)
|
updateCh := channels.NewRingChannel(1024)
|
||||||
|
@ -504,27 +508,28 @@ func TestStore(t *testing.T) {
|
||||||
name := "ingress-with-secret"
|
name := "ingress-with-secret"
|
||||||
secretHosts := []string{name}
|
secretHosts := []string{name}
|
||||||
|
|
||||||
_, err := ensureIngress(&v1beta1.Ingress{
|
ing := ensureIngress(&extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: ns,
|
Namespace: ns,
|
||||||
|
SelfLink: fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses/%s", ns, name),
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
TLS: []v1beta1.IngressTLS{
|
TLS: []extensions.IngressTLS{
|
||||||
{
|
{
|
||||||
Hosts: secretHosts,
|
Hosts: secretHosts,
|
||||||
SecretName: name,
|
SecretName: name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: name,
|
Host: name,
|
||||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
IngressRuleValue: extensions.IngressRuleValue{
|
||||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
HTTP: &extensions.HTTPIngressRuleValue{
|
||||||
Paths: []v1beta1.HTTPIngressPath{
|
Paths: []extensions.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: v1beta1.IngressBackend{
|
Backend: extensions.IngressBackend{
|
||||||
ServiceName: "http-svc",
|
ServiceName: "http-svc",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
@ -535,14 +540,12 @@ func TestStore(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, clientSet)
|
}, clientSet, t)
|
||||||
if err != nil {
|
defer deleteIngress(ing, clientSet, t)
|
||||||
t.Errorf("unexpected error creating ingress: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = framework.WaitForIngressInNamespace(clientSet, ns, name)
|
err := framework.WaitForIngressInNamespace(clientSet, ns, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for ingress: %v", err)
|
t.Errorf("error waiting for ingress: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// take into account delay caused by:
|
// take into account delay caused by:
|
||||||
|
@ -563,13 +566,13 @@ func TestStore(t *testing.T) {
|
||||||
|
|
||||||
_, err = framework.CreateIngressTLSSecret(clientSet, secretHosts, name, ns)
|
_, err = framework.CreateIngressTLSSecret(clientSet, secretHosts, name, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating secret: %v", err)
|
t.Errorf("error creating secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("should exists a secret in the local store and filesystem", func(t *testing.T) {
|
t.Run("should exists a secret in the local store and filesystem", func(t *testing.T) {
|
||||||
err := framework.WaitForSecretInNamespace(clientSet, ns, name)
|
err := framework.WaitForSecretInNamespace(clientSet, ns, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for secret: %v", err)
|
t.Errorf("error waiting for secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
@ -577,13 +580,13 @@ func TestStore(t *testing.T) {
|
||||||
pemFile := fmt.Sprintf("%v/%v-%v.pem", file.DefaultSSLDirectory, ns, name)
|
pemFile := fmt.Sprintf("%v/%v-%v.pem", file.DefaultSSLDirectory, ns, name)
|
||||||
err = framework.WaitForFileInFS(pemFile, fs)
|
err = framework.WaitForFileInFS(pemFile, fs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error waiting for file to exist on the file system: %v", err)
|
t.Errorf("error waiting for file to exist on the file system: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secretName := fmt.Sprintf("%v/%v", ns, name)
|
secretName := fmt.Sprintf("%v/%v", ns, name)
|
||||||
sslCert, err := storer.GetLocalSSLCert(secretName)
|
sslCert, err := storer.GetLocalSSLCert(secretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error reading local secret %v: %v", secretName, err)
|
t.Errorf("error reading local secret %v: %v", secretName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sslCert == nil {
|
if sslCert == nil {
|
||||||
|
@ -605,41 +608,107 @@ func TestStore(t *testing.T) {
|
||||||
// check invalid secret (missing ca)
|
// check invalid secret (missing ca)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNamespace(clientSet *kubernetes.Clientset, t *testing.T) string {
|
func createNamespace(clientSet kubernetes.Interface, t *testing.T) string {
|
||||||
t.Log("creating temporal namespace")
|
t.Helper()
|
||||||
ns, err := framework.CreateKubeNamespace("store-test", clientSet)
|
t.Log("Creating temporal namespace")
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error creating ingress client: %v", err)
|
|
||||||
}
|
|
||||||
t.Logf("temporal namespace %v created", ns)
|
|
||||||
|
|
||||||
return ns
|
namespace := &v1.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "store-test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ns, err := clientSet.CoreV1().Namespaces().Create(namespace)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating the namespace: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Temporal namespace %v created", ns)
|
||||||
|
|
||||||
|
return ns.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteNamespace(ns string, clientSet *kubernetes.Clientset, t *testing.T) {
|
func deleteNamespace(ns string, clientSet kubernetes.Interface, t *testing.T) {
|
||||||
t.Logf("deleting temporal namespace %v created", ns)
|
t.Helper()
|
||||||
err := framework.DeleteKubeNamespace(clientSet, ns)
|
t.Logf("Deleting temporal namespace %v", ns)
|
||||||
|
|
||||||
|
err := clientSet.CoreV1().Namespaces().Delete(ns, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error creating ingress client: %v", err)
|
t.Errorf("error deleting the namespace: %v", err)
|
||||||
}
|
}
|
||||||
t.Logf("temporal namespace %v deleted", ns)
|
t.Logf("Temporal namespace %v deleted", ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureIngress(ingress *extensions.Ingress, clientSet *kubernetes.Clientset) (*extensions.Ingress, error) {
|
func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) string {
|
||||||
s, err := clientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Update(ingress)
|
t.Helper()
|
||||||
|
t.Log("Creating temporal config map")
|
||||||
|
|
||||||
|
configMap := &v1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "config",
|
||||||
|
SelfLink: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/config", ns),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cm, err := clientSet.CoreV1().ConfigMaps(ns).Create(configMap)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating the configuration map: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Temporal configmap %v created", cm)
|
||||||
|
|
||||||
|
return cm.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteConfigMap(cm, ns string, clientSet kubernetes.Interface, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
t.Logf("Deleting temporal configmap %v", cm)
|
||||||
|
|
||||||
|
err := clientSet.CoreV1().ConfigMaps(ns).Delete(cm, &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error deleting the configmap: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("Temporal configmap %v deleted", cm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureIngress(ingress *extensions.Ingress, clientSet kubernetes.Interface, t *testing.T) *extensions.Ingress {
|
||||||
|
t.Helper()
|
||||||
|
ing, err := clientSet.Extensions().Ingresses(ingress.Namespace).Update(ingress)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if k8sErrors.IsNotFound(err) {
|
if k8sErrors.IsNotFound(err) {
|
||||||
return clientSet.ExtensionsV1beta1().Ingresses(ingress.Namespace).Create(ingress)
|
t.Logf("Ingress %v not found, creating", ingress)
|
||||||
|
|
||||||
|
ing, err = clientSet.Extensions().Ingresses(ingress.Namespace).Create(ingress)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating ingress %+v: %v", ingress, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Ingress %+v created", ingress)
|
||||||
|
return ing
|
||||||
}
|
}
|
||||||
return nil, err
|
|
||||||
|
t.Fatalf("error updating ingress %+v: %v", ingress, err)
|
||||||
}
|
}
|
||||||
return s, nil
|
|
||||||
|
t.Logf("Ingress %+v updated", ingress)
|
||||||
|
|
||||||
|
return ing
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteIngress(ingress *extensions.Ingress, clientSet kubernetes.Interface, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
err := clientSet.Extensions().Ingresses(ingress.Namespace).Delete(ingress.Name, &metav1.DeleteOptions{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to delete ingress %+v: %v", ingress, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Ingress %+v deleted", ingress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFS(t *testing.T) file.Filesystem {
|
func newFS(t *testing.T) file.Filesystem {
|
||||||
fs, err := file.NewFakeFS()
|
fs, err := file.NewFakeFS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error creating filesystem: %v", err)
|
t.Fatalf("error creating filesystem: %v", err)
|
||||||
}
|
}
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
@ -649,7 +718,7 @@ func newFS(t *testing.T) file.Filesystem {
|
||||||
func newStore(t *testing.T) *k8sStore {
|
func newStore(t *testing.T) *k8sStore {
|
||||||
fs, err := file.NewFakeFS()
|
fs, err := file.NewFakeFS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &k8sStore{
|
return &k8sStore{
|
||||||
|
@ -668,7 +737,7 @@ func newStore(t *testing.T) *k8sStore {
|
||||||
func TestUpdateSecretIngressMap(t *testing.T) {
|
func TestUpdateSecretIngressMap(t *testing.T) {
|
||||||
s := newStore(t)
|
s := newStore(t)
|
||||||
|
|
||||||
ingTpl := &v1beta1.Ingress{
|
ingTpl := &extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Namespace: "testns",
|
Namespace: "testns",
|
||||||
|
@ -678,8 +747,8 @@ func TestUpdateSecretIngressMap(t *testing.T) {
|
||||||
|
|
||||||
t.Run("with TLS secret", func(t *testing.T) {
|
t.Run("with TLS secret", func(t *testing.T) {
|
||||||
ing := ingTpl.DeepCopy()
|
ing := ingTpl.DeepCopy()
|
||||||
ing.Spec = v1beta1.IngressSpec{
|
ing.Spec = extensions.IngressSpec{
|
||||||
TLS: []v1beta1.IngressTLS{{SecretName: "tls"}},
|
TLS: []extensions.IngressTLS{{SecretName: "tls"}},
|
||||||
}
|
}
|
||||||
s.listers.Ingress.Update(ing)
|
s.listers.Ingress.Update(ing)
|
||||||
s.updateSecretIngressMap(ing)
|
s.updateSecretIngressMap(ing)
|
||||||
|
@ -732,17 +801,17 @@ func TestUpdateSecretIngressMap(t *testing.T) {
|
||||||
func TestListIngresses(t *testing.T) {
|
func TestListIngresses(t *testing.T) {
|
||||||
s := newStore(t)
|
s := newStore(t)
|
||||||
|
|
||||||
ingEmptyClass := &v1beta1.Ingress{
|
ingEmptyClass := &extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test-1",
|
Name: "test-1",
|
||||||
Namespace: "testns",
|
Namespace: "testns",
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Backend: &v1beta1.IngressBackend{
|
Backend: &extensions.IngressBackend{
|
||||||
ServiceName: "demo",
|
ServiceName: "demo",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo.bar",
|
Host: "foo.bar",
|
||||||
},
|
},
|
||||||
|
@ -751,7 +820,7 @@ func TestListIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
s.listers.Ingress.Add(ingEmptyClass)
|
s.listers.Ingress.Add(ingEmptyClass)
|
||||||
|
|
||||||
ingressToIgnore := &v1beta1.Ingress{
|
ingressToIgnore := &extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test-2",
|
Name: "test-2",
|
||||||
Namespace: "testns",
|
Namespace: "testns",
|
||||||
|
@ -759,8 +828,8 @@ func TestListIngresses(t *testing.T) {
|
||||||
"kubernetes.io/ingress.class": "something",
|
"kubernetes.io/ingress.class": "something",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Backend: &v1beta1.IngressBackend{
|
Backend: &extensions.IngressBackend{
|
||||||
ServiceName: "demo",
|
ServiceName: "demo",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
@ -768,20 +837,20 @@ func TestListIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
s.listers.Ingress.Add(ingressToIgnore)
|
s.listers.Ingress.Add(ingressToIgnore)
|
||||||
|
|
||||||
ingressWithoutPath := &v1beta1.Ingress{
|
ingressWithoutPath := &extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test-3",
|
Name: "test-3",
|
||||||
Namespace: "testns",
|
Namespace: "testns",
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo.bar",
|
Host: "foo.bar",
|
||||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
IngressRuleValue: extensions.IngressRuleValue{
|
||||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
HTTP: &extensions.HTTPIngressRuleValue{
|
||||||
Paths: []v1beta1.HTTPIngressPath{
|
Paths: []extensions.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Backend: v1beta1.IngressBackend{
|
Backend: extensions.IngressBackend{
|
||||||
ServiceName: "demo",
|
ServiceName: "demo",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
@ -795,7 +864,7 @@ func TestListIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
s.listers.Ingress.Add(ingressWithoutPath)
|
s.listers.Ingress.Add(ingressWithoutPath)
|
||||||
|
|
||||||
ingressWithNginxClass := &v1beta1.Ingress{
|
ingressWithNginxClass := &extensions.Ingress{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test-4",
|
Name: "test-4",
|
||||||
Namespace: "testns",
|
Namespace: "testns",
|
||||||
|
@ -803,16 +872,16 @@ func TestListIngresses(t *testing.T) {
|
||||||
"kubernetes.io/ingress.class": "nginx",
|
"kubernetes.io/ingress.class": "nginx",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: v1beta1.IngressSpec{
|
Spec: extensions.IngressSpec{
|
||||||
Rules: []v1beta1.IngressRule{
|
Rules: []extensions.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo.bar",
|
Host: "foo.bar",
|
||||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
IngressRuleValue: extensions.IngressRuleValue{
|
||||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
HTTP: &extensions.HTTPIngressRuleValue{
|
||||||
Paths: []v1beta1.HTTPIngressPath{
|
Paths: []extensions.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/demo",
|
Path: "/demo",
|
||||||
Backend: v1beta1.IngressBackend{
|
Backend: extensions.IngressBackend{
|
||||||
ServiceName: "demo",
|
ServiceName: "demo",
|
||||||
ServicePort: intstr.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue