Compare commits

..

22 Commits

Author SHA1 Message Date
Vincent Demeester
86053ea54b Update Makefile to fix local builds (#397)
Use --build-arg only if DOCKER_VERSION is specified

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-23 16:07:35 +02:00
Vincent Demeester
938600ba95 Merge pull request #398 from containous/fix-safari-http2
Fix safari http2
2016-05-23 14:37:19 +02:00
Emile Vauge
80ab967d39 Fix benchmarks doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-23 14:02:25 +02:00
Emile Vauge
43acbaa702 Fix safari error with http2
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-23 14:00:14 +02:00
Vincent Demeester
5d6492e6f5 Merge pull request #395 from vdemeester/carry-pr-382
Carry: http protocol should not use TLS
2016-05-23 13:11:56 +02:00
Jonas Falck
aeb9cc1732 http protocol should not use TLS
I need this in order to run kubectl proxy and then
make traefik use http://localhost to get to my cluster
when developing
2016-05-23 09:51:05 +02:00
Vincent Demeester
fa25c8ef22 Merge pull request #394 from vdemeester/carry-pr-312
Carry: Updating Toml to sure PathPrefix instead of Path
2016-05-23 09:50:38 +02:00
Russell Clare
77a9613c3a Updating Toml to sure PathPrefix instead of Path 2016-05-23 09:35:18 +02:00
Vincent Demeester
153ab8f0fa Update engine-api to fix versions issues (#383)
Updating an engine-api that has fixed some versioning issues (filters
json marshalling)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-19 21:11:30 +02:00
Vincent Demeester
f6c860afc0 Merge pull request #380 from errm/k8s-ref-ports-by-name
Allow k8s ports to be referenced by name as well as number
2016-05-19 15:00:12 +02:00
Ed Robinson
d13b755df2 Allow k8s ports to be referenced by name as well as number 2016-05-19 13:36:19 +01:00
Vincent Demeester
6bacbf6cac Merge pull request #379 from errm/k8s-services-from-same-namespace
The referenced k8s service(s) must be in namespace
2016-05-19 14:08:53 +02:00
Ed Robinson
5923d22379 The referenced k8s service(s) must be in namespace
By design k8s ingress is only designed to ballance services from within
the namespace of the ingress.

This is disscuessed a little in
https://github.com/kubernetes/kubernetes/issues/17088.

For now traefik should only reference the services in the current
namespace. For me this was a confusing change of behaviour
from the reference implimentations, as I have services
with the same name in each namespace.
2016-05-18 17:38:47 +01:00
Vincent Demeester
70494117d1 Merge pull request #373 from AlmogBaku/master
K8s: add an option to configure "PathPrefixStrip" for the ingress-resource using annotation
2016-05-18 17:19:11 +02:00
AlmogBaku
8210743dad change log error of "ruleType" to warning 2016-05-17 16:54:40 +03:00
AlmogBaku
895f3cc109 fixes golint error 2016-05-17 16:22:37 +03:00
AlmogBaku
71f160dddc Following up to the conversation on Slack & GitHub:
- Change the annotation to define the rule type in `traefik.frontend.rule.type`
 - Update tests
 - Add documentation
 - Add example
2016-05-17 13:50:06 +03:00
AlmogBaku
92abaa0d47 fixes wrong actual on unit-test 2016-05-16 01:24:23 +03:00
AlmogBaku
47710c1385 fixes wrong names on tests - make it pass 2016-05-16 01:06:30 +03:00
AlmogBaku
df3abcbc9a gofmt to tests.. 2016-05-15 20:01:26 +03:00
AlmogBaku
dbb7ad41e5 Add tests for k8s PathPrefixStrip annotation 2016-05-15 12:16:27 +03:00
AlmogBaku
9773d4e409 K8s: add an option to configure "PathPrefixStrip" for the ingress-resource using annotation 2016-05-15 12:00:20 +03:00
10 changed files with 482 additions and 47 deletions

View File

@@ -18,6 +18,7 @@ REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"containous/traefik")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -v "/var/run/docker.sock:/var/run/docker.sock")
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
print-%: ; @echo $*=$($*)
@@ -46,7 +47,7 @@ validate: build ## validate gofmt, golint and go vet
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint
build: dist
docker build --build-arg=DOCKER_VERSION=${DOCKER_VERSION} -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
build-webui:
docker build -t traefik-webui -f webui/Dockerfile webui

5
cmd.go
View File

@@ -10,12 +10,13 @@ import (
"strings"
"time"
"net/http"
log "github.com/Sirupsen/logrus"
"github.com/containous/traefik/middlewares"
"github.com/containous/traefik/provider"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"net/http"
)
var traefikCmd = &cobra.Command{
@@ -171,7 +172,7 @@ func init() {
traefikCmd.PersistentFlags().StringVar(&arguments.Boltdb.Prefix, "boltdb.prefix", "/traefik", "Prefix used for KV store")
traefikCmd.PersistentFlags().BoolVar(&arguments.kubernetes, "kubernetes", false, "Enable Kubernetes backend")
traefikCmd.PersistentFlags().StringVar(&arguments.Kubernetes.Endpoint, "kubernetes.endpoint", "127.0.0.1:8080", "Kubernetes server endpoint")
traefikCmd.PersistentFlags().StringVar(&arguments.Kubernetes.Endpoint, "kubernetes.endpoint", "http://127.0.0.1:8080", "Kubernetes server endpoint")
traefikCmd.PersistentFlags().StringSliceVar(&arguments.Kubernetes.Namespaces, "kubernetes.namespaces", []string{}, "Kubernetes namespaces")
_ = viper.BindPFlag("configFile", traefikCmd.PersistentFlags().Lookup("configFile"))

View File

@@ -146,7 +146,7 @@ defaultEntryPoints = ["http"]
### whoami:
```
wrk -t8 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-whoami:80/bench
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-whoami:80/bench
Running 1m test @ http://IP-whoami:80/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
@@ -184,7 +184,7 @@ Transfer/sec: 4.97MB
### traefik:
```
wrk -t8 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-traefik:8000/bench
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-traefik:8000/bench
Running 1m test @ http://IP-traefik:8000/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev

View File

@@ -619,7 +619,7 @@ Labels can be used on containers to override default behaviour:
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`.
* `traefik.domain=traefik.localhost`: override the default domain
- `traefik.domain=traefik.localhost`: override the default domain
## Kubernetes Ingress backend
@@ -651,6 +651,10 @@ Træfɪk can be configured to use Kubernetes Ingress as a backend configuration:
# namespaces = ["default","production"]
```
Annotations can be used on containers to override default behaviour for the whole Ingress resource:
- `traefik.frontend.rule.type: PathPrefixStrip`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
You can find here an example [ingress](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s.ingress.yaml) and [replication controller](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s.rc.yaml).
## Consul backend
@@ -930,7 +934,7 @@ The Keys-Values structure should look (using `prefix = "/traefik"`):
| `/traefik/frontends/frontend2/backend` | `backend1` |
| `/traefik/frontends/frontend2/passHostHeader` | `true` |
| `/traefik/frontends/frontend2/entrypoints` | `http,https` |
| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path:/test` |
| `/traefik/frontends/frontend2/routes/test_2/rule` | `PathPrefix:/test` |
## Atomic configuration changes

View File

@@ -91,3 +91,21 @@ spec:
- backend:
serviceName: service3
servicePort: 80
---
# Another Ingress with PathPrefixStrip
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: whoami-ingress-stripped
annotations:
traefik.frontend.rule.type: "PathPrefixStrip"
spec:
rules:
- host: foo.localhost
http:
paths:
- path: /prefixWillBeStripped
backend:
serviceName: service1
servicePort: 80

27
glide.lock generated
View File

@@ -1,5 +1,5 @@
hash: da7239dce8bda69f6e10b2f2bfae57dd4fd95b817055dca1379a72af42939b97
updated: 2016-05-12T11:48:22.158455011+02:00
hash: 68bc4f87206f9a486e1455f1dfcad737369c359a803566271432fcb85de3a12c
updated: 2016-05-23T13:57:35.191541555+02:00
imports:
- name: github.com/alecthomas/template
version: b867cc6ab45cece8143cfcc6fc9c77cf3f2c23c0
@@ -22,7 +22,7 @@ imports:
- name: github.com/codegangsta/negroni
version: c7477ad8e330bef55bf1ebe300cf8aa67c492d1b
- name: github.com/containous/oxy
version: 021f82bd8260ba15f5862a9fe62018437720dff5
version: 183212964e13e7b8afe01a08b193d04300554a68
subpackages:
- cbreaker
- forward
@@ -86,7 +86,7 @@ imports:
- utils
- volume
- name: github.com/docker/engine-api
version: fd7f99d354831e7e809386087e7ec3129fdb1520
version: 3d3d0b6c9d2651aac27f416a6da0224c1875b3eb
subpackages:
- client
- types
@@ -103,7 +103,7 @@ imports:
- types/versions
- types/blkiodev
- name: github.com/docker/go-connections
version: 5b7154ba2efe13ff86ae8830a9e7cb120b080d6e
version: c7838b258fbfa3fe88eecfb2a0e08ea0dbd6a646
subpackages:
- nat
- sockets
@@ -168,7 +168,7 @@ imports:
- name: github.com/kr/text
version: 7cafcd837844e784b526369c9bce262804aebc60
- name: github.com/libkermit/docker
version: 9f5a90f8eb3c49bf56e81621f98b3cd86fe4139f
version: 3b5eb2973efff7af33cfb65141deaf4ed25c6d02
- name: github.com/libkermit/docker-check
version: bb75a86b169c6c5d22c0ee98278124036f272d7b
- name: github.com/magiconair/properties
@@ -184,19 +184,19 @@ imports:
- name: github.com/mattn/go-shellwords
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
- name: github.com/Microsoft/go-winio
version: 3b8b3c98b207f95fe0cd6c7c311a9ac497ba7c0f
version: 4f1a71750d95a5a8a46c40a67ffbed8129c2f138
- name: github.com/miekg/dns
version: 48ab6605c66ac797e07f615101c3e9e10e932b66
- name: github.com/mitchellh/mapstructure
version: d2dd0262208475919e1a362f675cfc0e7c10e905
- name: github.com/moul/http2curl
version: 1812aee76a1ce98d604a44200c6a23c689b17a89
version: b1479103caacaa39319f75e7f57fc545287fca0d
- name: github.com/opencontainers/runc
version: 2441732d6fcc0fb0a542671a4372e0c7bc99c19e
subpackages:
- libcontainer/user
- name: github.com/parnurzeal/gorequest
version: a39a2f8d0463091df7344dbf586a9986e9f7184f
version: 2169dfca686cfcbefc983a98a25e9c22a2815be4
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
@@ -210,7 +210,7 @@ imports:
- name: github.com/spf13/cast
version: ee7b3e0353166ab1f3a605294ac8cd2b77953778
- name: github.com/spf13/cobra
version: 0f866a6211e33cde2091d9290c08f6afd6c9ebbc
version: f368244301305f414206f889b1735a54cfc8bde8
subpackages:
- cobra
- name: github.com/spf13/jwalterweatherman
@@ -237,7 +237,7 @@ imports:
- name: github.com/unrolled/render
version: 26b4e3aac686940fe29521545afad9966ddfc80c
- name: github.com/vdemeester/docker-events
version: ce5347b72aafad4e3bebd966f15e4183839d5172
version: b308d2e8d639d928c882913bcb4f85b3a84c7a07
- name: github.com/vdemeester/shakers
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
- name: github.com/vulcand/oxy
@@ -258,11 +258,11 @@ imports:
- name: github.com/wendal/errors
version: f66c77a7882b399795a8987ebf87ef64a427417e
- name: github.com/xenolf/lego
version: 948483535f53c34d144419869ecbed86251a30f6
version: b119bc45fbd1cc71348003541aac9d3a7da63654
subpackages:
- acme
- name: golang.org/x/crypto
version: b76c864ef1dca1d8f271f917c290cddcce3d9e0d
version: 5bcd134fee4dd1475da17714aac19c0aa0142e2f
subpackages:
- ocsp
- name: golang.org/x/net
@@ -275,6 +275,7 @@ imports:
version: eb2c74142fd19a79b3f237334c7384d5167b1b46
subpackages:
- unix
- windows
- name: gopkg.in/alecthomas/kingpin.v2
version: 639879d6110b1b0409410c7b737ef0bb18325038
- name: gopkg.in/fsnotify.v1

View File

@@ -7,7 +7,7 @@ import:
- package: github.com/mailgun/log
version: 44874009257d4d47ba9806f1b7f72a32a015e4d8
- package: github.com/containous/oxy
version: 021f82bd8260ba15f5862a9fe62018437720dff5
version: 183212964e13e7b8afe01a08b193d04300554a68
subpackages:
- cbreaker
- forward
@@ -160,7 +160,7 @@ import:
- package: github.com/libkermit/docker-check
version: bb75a86b169c6c5d22c0ee98278124036f272d7b
- package: github.com/libkermit/docker
version: 9f5a90f8eb3c49bf56e81621f98b3cd86fe4139f
version: 3b5eb2973efff7af33cfb65141deaf4ed25c6d02
- package: github.com/docker/libcompose
version: 8ee7bcc364f7b8194581a3c6bd9fa019467c7873
- package: github.com/docker/distribution
@@ -168,7 +168,7 @@ import:
subpackages:
- reference
- package: github.com/docker/engine-api
version: fd7f99d354831e7e809386087e7ec3129fdb1520
version: 3d3d0b6c9d2651aac27f416a6da0224c1875b3eb
subpackages:
- client
- types

View File

@@ -5,11 +5,12 @@ import (
"crypto/x509"
"encoding/json"
"fmt"
"github.com/containous/traefik/safe"
"github.com/parnurzeal/gorequest"
"net/http"
"net/url"
"strings"
"github.com/containous/traefik/safe"
"github.com/parnurzeal/gorequest"
)
const (
@@ -201,6 +202,11 @@ func (c *clientImpl) do(request *gorequest.SuperAgent) ([]byte, error) {
func (c *clientImpl) request(url string) *gorequest.SuperAgent {
// Make request to Kubernetes API
request := gorequest.New().Get(url)
if strings.HasPrefix(url, "http://") {
return request
}
if len(c.token) > 0 {
request.Header["Authorization"] = "Bearer " + c.token
pool := x509.NewCertPool()

View File

@@ -9,6 +9,7 @@ import (
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"text/template"
"time"
@@ -165,12 +166,28 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
}
}
if len(pa.Path) > 0 {
ruleType := i.Annotations["traefik.frontend.rule.type"]
switch strings.ToLower(ruleType) {
case "pathprefixstrip":
ruleType = "PathPrefixStrip"
case "pathstrip":
ruleType = "PathStrip"
case "path":
ruleType = "Path"
case "pathprefix":
ruleType = "PathPrefix"
default:
log.Warnf("Unknown RuleType `%s`, falling back to `PathPrefix", ruleType)
ruleType = "PathPrefix"
}
templateObjects.Frontends[r.Host+pa.Path].Routes[pa.Path] = types.Route{
Rule: "PathPrefix:" + pa.Path,
Rule: ruleType + ":" + pa.Path,
}
}
services, err := k8sClient.GetServices(func(service k8s.Service) bool {
return service.Name == pa.Backend.ServiceName
return service.ObjectMeta.Namespace == i.ObjectMeta.Namespace && service.Name == pa.Backend.ServiceName
})
if err != nil {
log.Errorf("Error retrieving services: %v", err)
@@ -184,12 +201,12 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
for _, service := range services {
protocol := "http"
for _, port := range service.Spec.Ports {
if port.Port == pa.Backend.ServicePort.IntValue() {
if equalPorts(port, pa.Backend.ServicePort) {
if port.Port == 443 {
protocol = "https"
}
templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
URL: protocol + "://" + service.Spec.ClusterIP + ":" + pa.Backend.ServicePort.String(),
URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(port.Port),
Weight: 1,
}
break
@@ -202,6 +219,16 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
return &templateObjects, nil
}
func equalPorts(servicePort k8s.ServicePort, ingressPort k8s.IntOrString) bool {
if servicePort.Port == ingressPort.IntValue() {
return true
}
if servicePort.Name != "" && servicePort.Name == ingressPort.String() {
return true
}
return false
}
func (provider *Kubernetes) getPassHostHeader() bool {
if provider.disablePassHostHeaders {
return false

View File

@@ -21,7 +21,7 @@ func TestLoadIngresses(t *testing.T) {
Path: "/bar",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
ServicePort: k8s.FromString("http"),
},
},
},
@@ -169,8 +169,234 @@ func TestLoadIngresses(t *testing.T) {
}
}
func TestRuleType(t *testing.T) {
ingresses := []k8s.Ingress{
{
ObjectMeta: k8s.ObjectMeta{
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefixStrip"}, //camel case
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo1",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Path: "/bar1",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
},
},
},
},
},
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Annotations: map[string]string{"traefik.frontend.rule.type": "path"}, //lower case
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo1",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Path: "/bar2",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
},
},
},
},
},
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefix"}, //path prefix
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo2",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Path: "/bar1",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
},
},
},
},
},
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Annotations: map[string]string{"traefik.frontend.rule.type": "PathStrip"}, //path strip
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo2",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Path: "/bar2",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
},
},
},
},
},
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Annotations: map[string]string{"traefik.frontend.rule.type": "PathXXStrip"}, //wrong rule
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo1",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Path: "/bar3",
Backend: k8s.IngressBackend{
ServiceName: "service1",
ServicePort: k8s.FromInt(801),
},
},
},
},
},
},
},
},
},
}
services := []k8s.Service{
{
ObjectMeta: k8s.ObjectMeta{
Name: "service1",
UID: "1",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
Ports: []k8s.ServicePort{
{
Name: "http",
Port: 801,
},
},
},
},
}
watchChan := make(chan interface{})
client := clientMock{
ingresses: ingresses,
services: services,
watchChan: watchChan,
}
provider := Kubernetes{disablePassHostHeaders: true}
actualConfig, err := provider.loadIngresses(client)
actual := actualConfig.Frontends
if err != nil {
t.Fatalf("error %+v", err)
}
expected := map[string]*types.Frontend{
"foo1/bar1": {
Backend: "foo1/bar1",
Routes: map[string]types.Route{
"/bar1": {
Rule: "PathPrefixStrip:/bar1",
},
"foo1": {
Rule: "Host:foo1",
},
},
},
"foo1/bar2": {
Backend: "foo1/bar2",
Routes: map[string]types.Route{
"/bar2": {
Rule: "Path:/bar2",
},
"foo1": {
Rule: "Host:foo1",
},
},
},
"foo2/bar1": {
Backend: "foo2/bar1",
Routes: map[string]types.Route{
"/bar1": {
Rule: "PathPrefix:/bar1",
},
"foo2": {
Rule: "Host:foo2",
},
},
},
"foo2/bar2": {
Backend: "foo2/bar2",
Routes: map[string]types.Route{
"/bar2": {
Rule: "PathStrip:/bar2",
},
"foo2": {
Rule: "Host:foo2",
},
},
},
"foo1/bar3": {
Backend: "foo1/bar3",
Routes: map[string]types.Route{
"/bar3": {
Rule: "PathPrefix:/bar3",
},
"foo1": {
Rule: "Host:foo1",
},
},
},
}
actualJSON, _ := json.Marshal(actual)
expectedJSON, _ := json.Marshal(expected)
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected %+v, got %+v", string(expectedJSON), string(actualJSON))
}
}
func TestGetPassHostHeader(t *testing.T) {
ingresses := []k8s.Ingress{{
ObjectMeta: k8s.ObjectMeta{
Namespace: "awesome",
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
@@ -195,8 +421,9 @@ func TestGetPassHostHeader(t *testing.T) {
services := []k8s.Service{
{
ObjectMeta: k8s.ObjectMeta{
Name: "service1",
UID: "1",
Name: "service1",
Namespace: "awesome",
UID: "1",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
@@ -256,6 +483,112 @@ func TestGetPassHostHeader(t *testing.T) {
}
}
func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
ingresses := []k8s.Ingress{
{
ObjectMeta: k8s.ObjectMeta{
Namespace: "awesome",
},
Spec: k8s.IngressSpec{
Rules: []k8s.IngressRule{
{
Host: "foo",
IngressRuleValue: k8s.IngressRuleValue{
HTTP: &k8s.HTTPIngressRuleValue{
Paths: []k8s.HTTPIngressPath{
{
Backend: k8s.IngressBackend{
ServiceName: "service",
ServicePort: k8s.FromInt(80),
},
},
},
},
},
},
},
},
},
}
services := []k8s.Service{
{
ObjectMeta: k8s.ObjectMeta{
Name: "service",
UID: "1",
Namespace: "awesome",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
Ports: []k8s.ServicePort{
{
Name: "http",
Port: 80,
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service",
UID: "2",
Namespace: "not-awesome",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.2",
Ports: []k8s.ServicePort{
{
Name: "http",
Port: 80,
},
},
},
},
}
watchChan := make(chan interface{})
client := clientMock{
ingresses: ingresses,
services: services,
watchChan: watchChan,
}
provider := Kubernetes{}
actual, err := provider.loadIngresses(client)
if err != nil {
t.Fatalf("error %+v", err)
}
expected := &types.Configuration{
Backends: map[string]*types.Backend{
"foo": {
Servers: map[string]types.Server{
"1": {
URL: "http://10.0.0.1:80",
Weight: 1,
},
},
CircuitBreaker: nil,
LoadBalancer: nil,
},
},
Frontends: map[string]*types.Frontend{
"foo": {
Backend: "foo",
PassHostHeader: true,
Routes: map[string]types.Route{
"foo": {
Rule: "Host:foo",
},
},
},
},
}
actualJSON, _ := json.Marshal(actual)
expectedJSON, _ := json.Marshal(expected)
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected %+v, got %+v", string(expectedJSON), string(actualJSON))
}
}
func TestLoadNamespacedIngresses(t *testing.T) {
ingresses := []k8s.Ingress{
{
@@ -333,8 +666,9 @@ func TestLoadNamespacedIngresses(t *testing.T) {
services := []k8s.Service{
{
ObjectMeta: k8s.ObjectMeta{
Name: "service1",
UID: "1",
Namespace: "awesome",
Name: "service1",
UID: "1",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
@@ -348,8 +682,25 @@ func TestLoadNamespacedIngresses(t *testing.T) {
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service2",
UID: "2",
Name: "service1",
Namespace: "not-awesome",
UID: "1",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
Ports: []k8s.ServicePort{
{
Name: "http",
Port: 801,
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service2",
Namespace: "awesome",
UID: "2",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.2",
@@ -362,8 +713,9 @@ func TestLoadNamespacedIngresses(t *testing.T) {
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service3",
UID: "3",
Name: "service3",
Namespace: "awesome",
UID: "3",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.3",
@@ -551,8 +903,9 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
services := []k8s.Service{
{
ObjectMeta: k8s.ObjectMeta{
Name: "service1",
UID: "1",
Name: "service1",
Namespace: "awesome",
UID: "1",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.1",
@@ -566,8 +919,25 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service2",
UID: "2",
Namespace: "somewhat-awesome",
Name: "service1",
UID: "17",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.4",
Ports: []k8s.ServicePort{
{
Name: "http",
Port: 801,
},
},
},
},
{
ObjectMeta: k8s.ObjectMeta{
Namespace: "awesome",
Name: "service2",
UID: "2",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.2",
@@ -580,8 +950,9 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
},
{
ObjectMeta: k8s.ObjectMeta{
Name: "service3",
UID: "3",
Namespace: "awesome",
Name: "service3",
UID: "3",
},
Spec: k8s.ServiceSpec{
ClusterIP: "10.0.0.3",
@@ -636,8 +1007,8 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
},
"awesome/quix": {
Servers: map[string]types.Server{
"1": {
URL: "http://10.0.0.1:801",
"17": {
URL: "http://10.0.0.4:801",
Weight: 1,
},
},
@@ -708,7 +1079,13 @@ func (c clientMock) WatchIngresses(predicate func(k8s.Ingress) bool, stopCh <-ch
return c.watchChan, make(chan error), nil
}
func (c clientMock) GetServices(predicate func(k8s.Service) bool) ([]k8s.Service, error) {
return c.services, nil
var services []k8s.Service
for _, service := range c.services {
if predicate(service) {
services = append(services, service)
}
}
return services, nil
}
func (c clientMock) WatchAll(stopCh <-chan bool) (chan interface{}, chan error, error) {
return c.watchChan, make(chan error), nil