Compare commits

...

13 Commits

Author SHA1 Message Date
Ludovic Fernandez
8a1c3510ea Prepare release v1.7.11 2019-04-26 10:34:06 +02:00
Jean-Baptiste Doumenjou
787b0a3ac7 Enhance KV client error management
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-04-26 09:36:03 +02:00
Ludovic Fernandez
a6d86cdddb fix: update lego. 2019-04-23 11:40:05 +02:00
mpl
9559a56011 Improve log message about redundant TLS certificate 2019-04-15 12:32:03 +02:00
ctas582
07e8042192 Forward all header values from forward auth response 2019-04-10 17:18:06 +02:00
Martin Hoefling
edd8e36dcc Documentation Update: Hosting.de wildcard support tested 2019-04-09 16:52:05 +02:00
Ludovic Fernandez
e291dcb8d1 Get Structor version from CI env var. 2019-04-08 08:44:03 +02:00
Ludovic Fernandez
de6e365b74 Update zipkin-go-opentracing. 2019-04-05 11:18:04 +02:00
Amir Aslaminejad
98a5e08553 Remove usage of github.com/satori/go.uuid 2019-04-05 08:44:03 +02:00
Brandon McNama
ba44619828 Update Wildcard Domain documentation 2019-04-01 17:42:04 +02:00
Ludovic Fernandez
86d700c845 Enhance k8s tests maintainability 2019-04-01 17:02:06 +02:00
Ludovic Fernandez
b2f11afcc2 Update certificates for some Docker images 2019-04-01 00:54:03 +02:00
Maxim Fominykh
cfb356c68e Keep consistent order 2019-03-29 16:40:03 +01:00
355 changed files with 19968 additions and 7381 deletions

View File

@@ -30,7 +30,7 @@ before_deploy:
make -j${N_MAKE_JOBS} crossbinary-parallel;
tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .;
fi;
curl -sfL https://raw.githubusercontent.com/containous/structor/master/godownloader.sh | bash -s -- -b "${GOPATH}/bin" v1.7.0
curl -sfL https://raw.githubusercontent.com/containous/structor/master/godownloader.sh | bash -s -- -b "${GOPATH}/bin" ${STRUCTOR_VERSION}
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --force-edit-url --debug;
fi
deploy:

View File

@@ -1,5 +1,24 @@
# Change Log
## [v1.7.11](https://github.com/containous/traefik/tree/v1.7.11) (2019-04-26)
[All Commits](https://github.com/containous/traefik/compare/v1.7.10...v1.7.11)
**Enhancements:**
- **[k8s,k8s/ingress]** Enhance k8s tests maintainability ([#4696](https://github.com/containous/traefik/pull/4696) by [ldez](https://github.com/ldez))
**Bug fixes:**
- **[acme]** fix: update lego. ([#4800](https://github.com/containous/traefik/pull/4800) by [ldez](https://github.com/ldez))
- **[authentication,middleware]** Forward all header values from forward auth response ([#4515](https://github.com/containous/traefik/pull/4515) by [ctas582](https://github.com/ctas582))
- **[cluster]** Remove usage of github.com/satori/go.uuid ([#4722](https://github.com/containous/traefik/pull/4722) by [aaslamin](https://github.com/aaslamin))
- **[kv]** Enhance KV client error management ([#4819](https://github.com/containous/traefik/pull/4819) by [jbdoumenjou](https://github.com/jbdoumenjou))
- **[tls]** Improve log message about redundant TLS certificate ([#4765](https://github.com/containous/traefik/pull/4765) by [mpl](https://github.com/mpl))
- **[tracing]** Update zipkin-go-opentracing. ([#4720](https://github.com/containous/traefik/pull/4720) by [ldez](https://github.com/ldez))
**Documentation:**
- **[acme]** Documentation Update: Hosting.de wildcard support tested ([#4747](https://github.com/containous/traefik/pull/4747) by [martinhoefling](https://github.com/martinhoefling))
- **[acme]** Update Wildcard Domain documentation ([#4682](https://github.com/containous/traefik/pull/4682) by [DWSR](https://github.com/DWSR))
- **[middleware]** Keep consistent order ([#4690](https://github.com/containous/traefik/pull/4690) by [maxifom](https://github.com/maxifom))
## [v1.7.10](https://github.com/containous/traefik/tree/v1.7.10) (2019-03-28)
[All Commits](https://github.com/containous/traefik/compare/v1.7.9...v1.7.10)

107
Gopkg.lock generated
View File

@@ -96,6 +96,14 @@
pruneopts = "NUT"
revision = "2fd0705ce648e602e6c9c57329a174270a4f6688"
[[projects]]
digest = "1:25870183293a3fb61cc9afd060a61d63a486f091db72af01a8ea3449f5ca530d"
name = "github.com/Masterminds/goutils"
packages = ["."]
pruneopts = "NUT"
revision = "41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0"
version = "v1.1.0"
[[projects]]
digest = "1:0ce2a409217f52078c6b8642993deb1025940cded6d5054047c1d5c7379f753c"
name = "github.com/Masterminds/semver"
@@ -105,11 +113,12 @@
version = "v1.2.2"
[[projects]]
digest = "1:a49472e7d73071005f436b7da85567220f24bb26fbfccbec45d2cd1359d4c67d"
digest = "1:876a1121171c083c4e3a4789683d02a40c0f644c8190da521d15b59799f556d6"
name = "github.com/Masterminds/sprig"
packages = ["."]
pruneopts = "NUT"
revision = "e039e20e500c2c025d9145be375e27cf42a94174"
revision = "9f8fceff796fb9f4e992cd2bece016be0121ab74"
version = "2.19.0"
[[projects]]
digest = "1:c8e7aea759874984f67a75e43fe764137188b1b062e27639efcba4b801fbcf42"
@@ -238,20 +247,12 @@
version = "1.27.7"
[[projects]]
digest = "1:975108e8d4f5dab096fc991326e96a5716ee8d02e5e7386bb4796171afc4ab9a"
name = "github.com/aokoli/goutils"
packages = ["."]
pruneopts = "NUT"
revision = "3391d3790d23d03408670993e957e8f408993c34"
version = "v1.0.1"
[[projects]]
digest = "1:9752dad5e89cd779096bf2477a4ded16bea7ac62de453c8d6b4bf841d51a8512"
digest = "1:b39cf81d5f440b9c0757a25058432d33af867e5201109bf53621356d9dab4b73"
name = "github.com/apache/thrift"
packages = ["lib/go/thrift"]
pruneopts = "NUT"
revision = "b2a4d4ae21c789b689dd162deb819665567f481c"
version = "0.10.0"
revision = "384647d290e2e4a55a14b1b7ef1b7e66293a2c33"
version = "v0.12.0"
[[projects]]
branch = "master"
@@ -734,7 +735,7 @@
revision = "73d445a93680fa1a78ae23a5839bad48f32ba1ee"
[[projects]]
digest = "1:a04af13190b67ff69cf8fcd79ee133a24c4a7a900cacbc296261dd43f3fbde5c"
digest = "1:68a7713d996a30a8394715220e779bbcbc880a18b1e0ab0e12fd1fbbf9c711e6"
name = "github.com/go-acme/lego"
packages = [
"acme",
@@ -819,8 +820,8 @@
"registration",
]
pruneopts = "NUT"
revision = "aaecc1ca7254190b71c5f01f57ee3bb6701bc937"
version = "v2.4.0"
revision = "3d13faf68920543a393ad6cdfdea429627af2d34"
version = "v2.5.0"
[[projects]]
branch = "fork-containous"
@@ -1110,11 +1111,12 @@
revision = "19f2c401e122352c047a84d6584dd51e2fb8fcc4"
[[projects]]
digest = "1:45e66b20393507035c6a7d15bef5ffe8faf5b083621c1284d9824cc052776de5"
digest = "1:dc54242755f5b6721dd880843de6e45fe234838ea9149ec8249951880fd5802f"
name = "github.com/huandu/xstrings"
packages = ["."]
pruneopts = "NUT"
revision = "3959339b333561bf62a38b424fd41517c2c90f40"
revision = "f02667b379e2fb5916c3cda2cf31e0eb885d79f8"
version = "v1.2.0"
[[projects]]
branch = "master"
@@ -1480,8 +1482,8 @@
version = "v1.0.2"
[[projects]]
digest = "1:07c44a0ce6012eafd2f05b715d30852d576aeda7798b8760a2ff51b1e90eb753"
name = "github.com/openzipkin/zipkin-go-opentracing"
digest = "1:0f4793617dc898d3ee99fe1abab076d3976a9d17d14f8327af2dc3f1ec0fd92c"
name = "github.com/openzipkin-contrib/zipkin-go-opentracing"
packages = [
".",
"flag",
@@ -1491,7 +1493,8 @@
"wire",
]
pruneopts = "NUT"
revision = "1f5c07e90700ae93ddcba0c7af7d9c7201646ccc"
revision = "f0f479ad013a498e4cbfb369414e5d3880903779"
version = "v0.3.5"
[[projects]]
digest = "1:8a5a270130e940b167027e8c9a07c20d01410bd6053160432351139ddc2cb501"
@@ -1645,17 +1648,18 @@
revision = "256dc444b735e061061cf46c809487313d5b0065"
[[projects]]
branch = "master"
digest = "1:fff470b0a7bbf05cfe8bfc73bfdf4d21eb009ea84e601f3d27781474e5da960f"
digest = "1:253f275bd72c42f8d234712d1574c8b222fe9b72838bfaca11b21ace9c0e3d0a"
name = "github.com/sacloud/libsacloud"
packages = [
".",
"api",
"sacloud",
"sacloud/ostype",
"utils/mutexkv",
]
pruneopts = "NUT"
revision = "306ea89b6ef19334614f7b0fc5aa19595022bb8c"
revision = "41c392dee98a83260abbe0fcd5c13beb7c75d103"
version = "v1.21.1"
[[projects]]
digest = "1:142520cf3c9bb85449dd0000f820b8c604531587ee654793c54909be7dabadac"
@@ -1716,13 +1720,11 @@
revision = "c4434f09ec131ecf30f986d5dcb1636508bfa49a"
[[projects]]
branch = "containous-fork"
digest = "1:84b9a5318d8ce3b8a9b1509bf15734f4f9dcd4decf9d9e9c7346a16c7b64d49e"
name = "github.com/thoas/stats"
packages = ["."]
pruneopts = "NUT"
revision = "4975baf6a358ed3ddaa42133996e1959f96c9300"
source = "github.com/containous/stats"
[[projects]]
branch = "master"
@@ -1882,6 +1884,42 @@
pruneopts = "NUT"
revision = "0c8571ac0ce161a5feb57375a9cdf148c98c0f70"
[[projects]]
digest = "1:045bc0ab96bb83bdffd2606f019003da03d1c139d3cb8aad13596863e4dd37d6"
name = "go.opencensus.io"
packages = [
".",
"internal",
"internal/tagencoding",
"metric/metricdata",
"metric/metricproducer",
"plugin/ochttp",
"plugin/ochttp/propagation/b3",
"resource",
"stats",
"stats/internal",
"stats/view",
"tag",
"trace",
"trace/internal",
"trace/propagation",
"trace/tracestate",
]
pruneopts = "NUT"
revision = "75c0cca22312e51bfd4fafdbe9197ae399e18b38"
version = "v0.20.2"
[[projects]]
branch = "master"
digest = "1:02fe59517e10f9b400b500af8ac228c74cecb0cba7a5f438d8283edb97e14270"
name = "go.uber.org/ratelimit"
packages = [
".",
"internal/clock",
]
pruneopts = "NUT"
revision = "c15da02342779cb6dc027fc95ee2277787698f36"
[[projects]]
branch = "master"
digest = "1:30c1930f8c9fee79f3af60c8b7cd92edd12a4f22187f5527d53509b1a794f555"
@@ -1985,17 +2023,22 @@
revision = "8be79e1e0910c292df4e79c241bb7e8f7e725959"
[[projects]]
branch = "master"
digest = "1:da32ebe70dd3ec97d2df26281b08b18d05c2f12491ae79f389813f6c8d3006b3"
digest = "1:887c07769ee52c81222ea1112b11a3947c703da529d1643d85c216b9537d87b8"
name = "google.golang.org/api"
packages = [
"dns/v1",
"gensupport",
"googleapi",
"googleapi/internal/uritemplates",
"googleapi/transport",
"internal",
"option",
"transport/http",
"transport/http/internal/propagation",
]
pruneopts = "NUT"
revision = "de943baf05a022a8f921b544b7827bacaba1aed5"
revision = "0cbcb99a9ea0c8023c794b2693cbe1def82ed4d7"
version = "v0.3.2"
[[projects]]
digest = "1:7206d98ec77c90c72ec2c405181a1dcf86965803b6dbc4f98ceab7a5047c37a9"
@@ -2408,6 +2451,7 @@
"github.com/go-kit/kit/metrics/statsd",
"github.com/golang/protobuf/proto",
"github.com/google/go-github/github",
"github.com/google/uuid",
"github.com/gorilla/websocket",
"github.com/hashicorp/consul/api",
"github.com/hashicorp/go-version",
@@ -2433,7 +2477,7 @@
"github.com/opentracing/opentracing-go",
"github.com/opentracing/opentracing-go/ext",
"github.com/opentracing/opentracing-go/log",
"github.com/openzipkin/zipkin-go-opentracing",
"github.com/openzipkin-contrib/zipkin-go-opentracing",
"github.com/patrickmn/go-cache",
"github.com/pkg/errors",
"github.com/prometheus/client_golang/prometheus",
@@ -2442,7 +2486,6 @@
"github.com/rancher/go-rancher-metadata/metadata",
"github.com/rancher/go-rancher/v2",
"github.com/ryanuber/go-glob",
"github.com/satori/go.uuid",
"github.com/sirupsen/logrus",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/mock",
@@ -2478,11 +2521,13 @@
"k8s.io/apimachinery/pkg/api/errors",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/labels",
"k8s.io/apimachinery/pkg/runtime",
"k8s.io/apimachinery/pkg/runtime/schema",
"k8s.io/apimachinery/pkg/types",
"k8s.io/apimachinery/pkg/util/intstr",
"k8s.io/client-go/informers",
"k8s.io/client-go/kubernetes",
"k8s.io/client-go/kubernetes/scheme",
"k8s.io/client-go/rest",
"k8s.io/client-go/tools/cache",
]

View File

@@ -36,6 +36,10 @@
branch = "master"
name = "github.com/BurntSushi/ty"
[[constraint]]
name = "github.com/Masterminds/sprig"
version = "2.19.0"
[[constraint]]
branch = "master"
name = "github.com/NYTimes/gziphandler"
@@ -146,10 +150,6 @@
branch = "master"
name = "github.com/ryanuber/go-glob"
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/stvp/go-udp-testing"
@@ -256,3 +256,7 @@
[[constraint]]
name = "gopkg.in/DataDog/dd-trace-go.v1"
version = "1.7.0"
[[constraint]]
name = "github.com/google/uuid"
version = "0.2.0"

View File

@@ -1,8 +1,9 @@
FROM golang:1.11-alpine
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
&& rm -rf /var/cache/apk/*
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
RUN go get golang.org/x/lint/golint \
&& go get github.com/kisielk/errcheck \

View File

@@ -13,7 +13,7 @@ import (
"github.com/containous/traefik/job"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
uuid "github.com/satori/go.uuid"
"github.com/google/uuid"
)
// Metadata stores Object plus metadata
@@ -125,7 +125,7 @@ func (d *Datastore) reload() error {
// Begin creates a transaction with the KV store.
func (d *Datastore) Begin() (Transaction, Object, error) {
id := uuid.NewV4().String()
id := uuid.New().String()
log.Debugf("Transaction %s begins", id)
remoteLock, err := d.kv.NewLock(d.lockKey, &store.LockOptions{TTL: 20 * time.Second, Value: []byte(id)})
if err != nil {

View File

@@ -303,7 +303,7 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | Not tested yet |
| [GoDaddy](https://godaddy.com/domains) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | Not tested yet |
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials (2) (3), [`GCE_SERVICE_ACCOUNT_FILE`] | YES |
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | Not tested yet |
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | YES |
| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` (1) | YES |
| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | Not tested yet |
| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | YES |
@@ -394,7 +394,6 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
```
It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`).
Due to ACME limitation it is not possible to define wildcards in SANs (alternative domains). Thus, the wildcard domain has to be defined as a main domain.
Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are executed.
In this case the generated DNS TXT record for both domains is the same.
Even though this behaviour is [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) compliant, it can lead to problems as all DNS providers keep DNS records cached for a certain time (TTL) and this TTL can be superior to the challenge timeout making the `DNS-01` challenge fail.

View File

@@ -249,8 +249,8 @@ Multiple sets of rates can be added to each frontend, but the time periods must
```
In the above example, frontend1 is configured to limit requests by the client's ip address.
An average of 5 requests every 3 seconds is allowed and an average of 100 requests every 10 seconds.
These can "burst" up to 10 and 200 in each period respectively.
An average of 100 requests every 10 seconds is allowed and an average of 5 requests every 3 seconds.
These can "burst" up to 200 and 10 in each period respectively.
Valid values for `extractorfunc` are:
* `client.ip`

View File

@@ -15,8 +15,9 @@ RUN npm run build
FROM golang:1.11-alpine as gobuild
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
&& rm -rf /var/cache/apk/*
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
RUN mkdir -p /usr/local/bin \
&& curl -fsSL -o /usr/local/bin/go-bindata https://github.com/containous/go-bindata/releases/download/v1.0.0/go-bindata \
@@ -33,7 +34,8 @@ RUN ./script/make.sh generate binary
## IMAGE
FROM scratch
COPY script/ca-certificates.crt /etc/ssl/certs/
COPY --from=gobuild /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=gobuild /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=gobuild /go/src/github.com/containous/traefik/dist/traefik /
EXPOSE 80

View File

@@ -1,7 +1,5 @@
zipkin:
# Fix zipkin version 2.4.2
# due to a bug in latest version https://github.com/openzipkin/zipkin/releases/tag/2.4.4
image: openzipkin/zipkin:2.4.2
image: openzipkin/zipkin:2.12.6
environment:
STORAGE_TYPE: mem
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG

View File

@@ -96,7 +96,11 @@ func Forward(config *types.Forward, w http.ResponseWriter, r *http.Request, next
}
for _, headerName := range config.AuthResponseHeaders {
r.Header.Set(headerName, forwardResponse.Header.Get(headerName))
headerKey := http.CanonicalHeaderKey(headerName)
r.Header.Del(headerKey)
if len(forwardResponse.Header[headerKey]) > 0 {
r.Header[headerKey] = append([]string(nil), forwardResponse.Header[headerKey]...)
}
}
r.RequestURI = r.URL.RequestURI()

View File

@@ -50,6 +50,8 @@ func TestForwardAuthFail(t *testing.T) {
func TestForwardAuthSuccess(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Auth-User", "user@example.com")
w.Header().Add("X-Auth-Group", "group1")
w.Header().Add("X-Auth-Group", "group2")
w.Header().Set("X-Auth-Secret", "secret")
fmt.Fprintln(w, "Success")
}))
@@ -58,13 +60,14 @@ func TestForwardAuthSuccess(t *testing.T) {
middleware, err := NewAuthenticator(&types.Auth{
Forward: &types.Forward{
Address: server.URL,
AuthResponseHeaders: []string{"X-Auth-User"},
AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"},
},
}, &tracing.Tracing{})
assert.NoError(t, err, "there should be no error")
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "user@example.com", r.Header.Get("X-Auth-User"))
assert.Equal(t, []string{"group1", "group2"}, r.Header["X-Auth-Group"])
assert.Empty(t, r.Header.Get("X-Auth-Secret"))
fmt.Fprintln(w, "traefik")
})
@@ -74,6 +77,7 @@ func TestForwardAuthSuccess(t *testing.T) {
defer ts.Close()
req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil)
req.Header.Set("X-Auth-Group", "admin_group")
res, err := http.DefaultClient.Do(req)
assert.NoError(t, err, "there should be no error")
assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal")

View File

@@ -5,7 +5,7 @@ import (
"github.com/containous/traefik/log"
"github.com/opentracing/opentracing-go"
zipkin "github.com/openzipkin/zipkin-go-opentracing"
zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing"
)
// Name sets the name of this tracer

View File

@@ -230,9 +230,25 @@ func auth(opt func(*types.Auth)) func(*types.Frontend) {
}
}
func basicAuth(users ...string) func(*types.Auth) {
func basicAuth(opts ...func(*types.Basic)) func(*types.Auth) {
return func(a *types.Auth) {
a.Basic = &types.Basic{Users: users}
basic := &types.Basic{}
for _, opt := range opts {
opt(basic)
}
a.Basic = basic
}
}
func baUsers(users ...string) func(*types.Basic) {
return func(b *types.Basic) {
b.Users = users
}
}
func baRemoveHeaders() func(*types.Basic) {
return func(b *types.Basic) {
b.RemoveHeader = true
}
}

View File

@@ -61,13 +61,6 @@ func eAddress(ip string) func(*corev1.EndpointAddress) {
}
}
func eAddressWithTargetRef(targetRef, ip string) func(*corev1.EndpointAddress) {
return func(address *corev1.EndpointAddress) {
address.TargetRef = &corev1.ObjectReference{Name: targetRef}
address.IP = ip
}
}
func ePorts(opts ...func(port *corev1.EndpointPort)) func(*corev1.EndpointSubset) {
return func(spec *corev1.EndpointSubset) {
for _, opt := range opts {

View File

@@ -35,15 +35,6 @@ func sUID(value types.UID) func(*corev1.Service) {
}
}
func sAnnotation(name string, value string) func(*corev1.Service) {
return func(s *corev1.Service) {
if s.Annotations == nil {
s.Annotations = make(map[string]string)
}
s.Annotations[name] = value
}
}
func sSpec(opts ...func(*corev1.ServiceSpec)) func(*corev1.Service) {
return func(s *corev1.Service) {
spec := &corev1.ServiceSpec{}
@@ -54,30 +45,6 @@ func sSpec(opts ...func(*corev1.ServiceSpec)) func(*corev1.Service) {
}
}
func sLoadBalancerStatus(opts ...func(*corev1.LoadBalancerStatus)) func(service *corev1.Service) {
return func(s *corev1.Service) {
loadBalancer := &corev1.LoadBalancerStatus{}
for _, opt := range opts {
if opt != nil {
opt(loadBalancer)
}
}
s.Status = corev1.ServiceStatus{
LoadBalancer: *loadBalancer,
}
}
}
func sLoadBalancerIngress(ip string, hostname string) func(*corev1.LoadBalancerStatus) {
return func(status *corev1.LoadBalancerStatus) {
ingress := corev1.LoadBalancerIngress{
IP: ip,
Hostname: hostname,
}
status.Ingress = append(status.Ingress, ingress)
}
}
func clusterIP(ip string) func(*corev1.ServiceSpec) {
return func(spec *corev1.ServiceSpec) {
spec.ClusterIP = ip

View File

@@ -1,21 +1,57 @@
package kubernetes
import (
"fmt"
"io/ioutil"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
v1beta12 "k8s.io/api/extensions/v1beta1"
)
var _ Client = (*clientMock)(nil)
type clientMock struct {
ingresses []*extensionsv1beta1.Ingress
services []*corev1.Service
secrets []*corev1.Secret
endpoints []*corev1.Endpoints
watchChan chan interface{}
apiServiceError error
apiSecretError error
apiEndpointsError error
apiIngressStatusError error
watchChan chan interface{}
}
func newClientMock(paths ...string) clientMock {
var c clientMock
for _, path := range paths {
yamlContent, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
k8sObjects := MustDecodeYaml(yamlContent)
for _, obj := range k8sObjects {
switch o := obj.(type) {
case *corev1.Service:
c.services = append(c.services, o)
case *corev1.Secret:
c.secrets = append(c.secrets, o)
case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o)
case *v1beta12.Ingress:
c.ingresses = append(c.ingresses, o)
default:
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
}
}
}
return c
}
func (c clientMock) GetIngresses() []*extensionsv1beta1.Ingress {

View File

@@ -0,0 +1,21 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 10%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,31 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service2: 40%
service3: 40%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service3
servicePort: 8080
path: /foo
- backend:
serviceName: service4
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,29 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 60%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service1
servicePort: 8080
path: /bar
- backend:
serviceName: service3
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,30 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service3: 20%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /bar
- backend:
serviceName: service3
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,23 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service2: 40%
service3: 40%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: noservice
servicePort: 8080
path: /foo
- backend:
serviceName: noservice
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,22 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 70%
service2: 80%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,19 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: ""
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,62 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.2
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service2
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.3
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service3
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.4
ports:
- port: 8080
- addresses:
- ip: 10.21.0.5
ports:
- port: 8080
- addresses:
- ip: 10.21.0.6
ports:
- port: 8080
- addresses:
- ip: 10.21.0.7
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service4
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.7
ports:
- port: 8080

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service3
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service4
namespace: testing

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- name: http
port: 80
- addresses:
- ip: 10.10.0.2
ports:
- name: http
port: 80

View File

@@ -0,0 +1,26 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: host-a
http:
paths:
- backend:
serviceName: service1
servicePort: "80"
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: host-a
http:
paths:
- backend:
serviceName: missing
servicePort: "80"

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 80

View File

@@ -0,0 +1,13 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 801
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
ports:
- name: http
port: 801

View File

@@ -0,0 +1,13 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
ports:
- name: http
port: 801

View File

@@ -0,0 +1,12 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- http:
paths:
- backend:
serviceName: service1
servicePort: 801
path: /bar

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 801

View File

@@ -0,0 +1,431 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/preserve-host: "false"
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/preserve-host: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /stuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/pass-client-tls-cert: |2
pem: true
infos:
notafter: true
notbefore: true
sans: true
subject:
country: true
province: true
locality: true
organization: true
commonname: true
serialnumber: true
domaincomponent: true
issuer:
country: true
province: true
locality: true
organization: true
commonname: true
serialnumber: true
domaincomponent: true
ingress.kubernetes.io/pass-tls-cert: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /sslstuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/frontend-entry-points: http,https
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-secret: mySecret
ingress.kubernetes.io/auth-type: basic
namespace: testing
spec:
rules:
- host: basic
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /auth
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik-other
namespace: testing
spec:
rules:
- host: herp
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /derp
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/whitelist-source-range: 1.1.1.1/24, 1234:abcd::42/32
ingress.kubernetes.io/whitelist-x-forwarded-for: "true"
namespace: testing
spec:
rules:
- host: test
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /whitelist-source-range
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
namespace: testing
spec:
rules:
- host: rewrite
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /api
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-realm: customized
namespace: testing
spec:
rules:
- host: auth-realm-customized
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /auth-realm-customized
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/redirect-entry-point: https
namespace: testing
spec:
rules:
- host: redirect
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /https
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/error-pages: |2
foo:
status:
- "123"
- "456"
backend: bar
query: /bar
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: error-pages
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /errorpages
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rate-limit: |2
extractorfunc: client.ip
rateset:
bar:
period: 3s
average: 6
burst: 9
foo:
period: 6s
average: 12
burst: 18
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: rate-limit
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /ratelimit
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root
namespace: testing
spec:
rules:
- host: root
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
- backend:
serviceName: service1
servicePort: 80
path: /root1
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root2
ingress.kubernetes.io/rewrite-target: /abc
namespace: testing
spec:
rules:
- host: root2
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /abc
ingress.kubernetes.io/rule-type: ReplacePath
namespace: testing
spec:
rules:
- host: root2
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root
namespace: testing
spec:
rules:
- host: root3
http:
paths:
- backend:
serviceName: service1
servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/allowed-hosts: foo, fii, fuu
ingress.kubernetes.io/browser-xss-filter: "true"
ingress.kubernetes.io/content-security-policy: foo
ingress.kubernetes.io/content-type-nosniff: "true"
ingress.kubernetes.io/custom-browser-xss-value: foo
ingress.kubernetes.io/custom-frame-options-value: foo
ingress.kubernetes.io/custom-request-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/custom-response-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/force-hsts: "true"
ingress.kubernetes.io/frame-deny: "true"
ingress.kubernetes.io/hsts-include-subdomains: "true"
ingress.kubernetes.io/hsts-max-age: "666"
ingress.kubernetes.io/hsts-preload: "true"
ingress.kubernetes.io/is-development: "true"
ingress.kubernetes.io/proxy-headers: foo, fii, fuu
ingress.kubernetes.io/public-key: foo
ingress.kubernetes.io/referrer-policy: foo
ingress.kubernetes.io/ssl-force-host: "true"
ingress.kubernetes.io/ssl-host: foo
ingress.kubernetes.io/ssl-proxy-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/ssl-temporary-redirect: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: custom-headers
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /customheaders
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: h2c
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /valid
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: foobar
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /notvalid
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: http
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: serviceHTTPS
servicePort: 443
path: /missmatch
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: serviceHTTPS
servicePort: 443
path: /noAnnotation

View File

@@ -0,0 +1,7 @@
apiVersion: v1
data:
auth: bXlVc2VyOm15RW5jb2RlZFBX
kind: Secret
metadata:
name: mySecret
namespace: testing

View File

@@ -0,0 +1,37 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- port: 802
---
apiVersion: v1
kind: Service
metadata:
name: serviceHTTPS
namespace: testing
spec:
clusterIP: 10.0.0.3
externalName: example.com
ports:
- name: https
port: 443
type: ExternalName

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service2
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- name: http
port: 80

View File

@@ -0,0 +1,81 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /stuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ""
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /sslstuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik-other
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: custom
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /bar

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- name: http
port: 80

View File

@@ -0,0 +1,15 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/preserve-host: herpderp
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName

View File

@@ -0,0 +1,15 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/pass-tls-cert: herpderp
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName

View File

@@ -0,0 +1,8 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
backend:
serviceName: service1
servicePort: 80

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
externalName: some-external-name
ports:
- port: 80
type: ExternalName

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- name: https-global
port: 8080

View File

@@ -0,0 +1,8 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
backend:
serviceName: service1
servicePort: https-global

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- name: https-global
port: 8443

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080

View File

@@ -0,0 +1,8 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
backend:
serviceName: service1
servicePort: 80

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80

View File

@@ -0,0 +1,17 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-remove-header: "true"
ingress.kubernetes.io/auth-secret: mySecret
ingress.kubernetes.io/auth-type: basic
namespace: testing
spec:
rules:
- host: basic
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /auth

View File

@@ -0,0 +1,7 @@
apiVersion: v1
data:
auth: bXlVc2VyOm15RW5jb2RlZFBX
kind: Secret
metadata:
name: mySecret
namespace: testing

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080

View File

@@ -0,0 +1,15 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-type: forward
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080

View File

@@ -0,0 +1,17 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-tls-secret: secret
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: https://auth.host
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80
targetPort: 0

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080

View File

@@ -0,0 +1,18 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-tls-insecure: "true"
ingress.kubernetes.io/auth-tls-secret: secret
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: https://auth.host
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,8 @@
apiVersion: v1
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
kind: Secret
metadata:
name: secret
namespace: testing

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080

View File

@@ -0,0 +1,18 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-response-headers: X-Auth,X-Test,X-Secret
ingress.kubernetes.io/auth-trust-headers: "true"
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: https://auth.host
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80

View File

@@ -0,0 +1,74 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service3
namespace: testing
subsets:
- addresses:
- ip: 10.15.0.1
ports:
- name: http
port: 8080
- name: https
port: 8443
- addresses:
- ip: 10.15.0.2
ports:
- name: http
port: 9080
- name: https
port: 9443
---
apiVersion: v1
kind: Endpoints
metadata:
name: service6
namespace: testing
subsets:
- addresses:
- ip: 10.15.0.3
targetRef:
name: http://10.15.0.3:80
ports:
- port: 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: service7
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.7
ports:
- port: 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: service8
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.8
ports:
- port: 80

View File

@@ -0,0 +1,49 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
- backend:
serviceName: service4
servicePort: https
path: /namedthing
- host: bar
http:
paths:
- backend:
serviceName: service3
servicePort: https
- backend:
serviceName: service2
servicePort: 802
- host: service5
http:
paths:
- backend:
serviceName: service5
servicePort: 8888
- host: service6
http:
paths:
- backend:
serviceName: service6
servicePort: 80
- host: '*.service7'
http:
paths:
- backend:
serviceName: service7
servicePort: 80
- http:
paths:
- backend:
serviceName: service8
servicePort: 80

View File

@@ -0,0 +1,95 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- port: 802
---
apiVersion: v1
kind: Service
metadata:
name: service3
namespace: testing
spec:
clusterIP: 10.0.0.3
ports:
- name: http
port: 80
- name: https
port: 443
---
apiVersion: v1
kind: Service
metadata:
name: service4
namespace: testing
spec:
clusterIP: 10.0.0.4
externalName: example.com
ports:
- name: https
port: 443
type: ExternalName
---
apiVersion: v1
kind: Service
metadata:
name: service5
namespace: testing
spec:
clusterIP: 10.0.0.5
externalName: example.com
ports:
- name: http
port: 8888
type: ExternalName
---
apiVersion: v1
kind: Service
metadata:
name: service6
namespace: testing
spec:
clusterIP: 10.0.0.6
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: service7
namespace: testing
spec:
clusterIP: 10.0.0.7
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: service8
namespace: testing
spec:
clusterIP: 10.0.0.8
ports:
- port: 80

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Endpoints
metadata:
name: fully_working_service
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: missing_endpoint_subsets_service
namespace: testing
subsets: null

View File

@@ -0,0 +1,30 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: fully_working
http:
paths:
- backend:
serviceName: fully_working_service
servicePort: 80
- host: missing_service
http:
paths:
- backend:
serviceName: missing_service_service
servicePort: 80
- host: missing_endpoints
http:
paths:
- backend:
serviceName: missing_endpoints_service
servicePort: 80
- host: missing_endpoint_subsets
http:
paths:
- backend:
serviceName: missing_endpoint_subsets_service
servicePort: 80

View File

@@ -0,0 +1,31 @@
apiVersion: v1
kind: Service
metadata:
name: fully_working_service
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: missing_endpoints_service
namespace: testing
spec:
clusterIP: 10.0.0.3
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: missing_endpoint_subsets_service
namespace: testing
spec:
clusterIP: 10.0.0.4
ports:
- port: 80

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: cheddar
port: 8080
- addresses:
- ip: 10.20.0.1
- ip: 10.20.0.2
ports:
- name: stilton
port: 8081

View File

@@ -0,0 +1,16 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- http:
paths:
- backend:
serviceName: service
servicePort: cheddar
path: /cheddar
- backend:
serviceName: service
servicePort: stilton
path: /stilton

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: service
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- name: cheddar
port: 80
- name: stilton
port: 81

View File

@@ -0,0 +1,12 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service
servicePort: 80

View File

@@ -0,0 +1,22 @@
apiVersion: v1
kind: Service
metadata:
name: service
namespace: awesome
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 80
---
apiVersion: v1
kind: Service
metadata:
name: service
namespace: not-awesome
spec:
clusterIP: 10.0.0.2
ports:
- name: http
port: 80

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service2
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.3
- ip: 10.10.0.4
ports:
- port: 7070

View File

@@ -0,0 +1,30 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 10%
service3: 20%
namespace: testing
spec:
rules:
- host: host1
http:
paths:
- backend:
serviceName: service1
servicePort: "8080"
path: /foo
- backend:
serviceName: service2
servicePort: "7070"
path: /foo
- backend:
serviceName: service3
servicePort: "9090"
path: /foo
- backend:
serviceName: service2
servicePort: "7070"
path: /bar

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 7070
---
apiVersion: v1
kind: Service
metadata:
name: service3
namespace: testing
spec:
externalName: example.com
ports:
- port: 9090
type: ExternalName

View File

@@ -0,0 +1,15 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/priority: "1337"
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
externalName: example.com
ports:
- name: http
port: 80
type: ExternalName

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
name: service-empty-status
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: service
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- port: 80
status:
loadBalancer:
ingress:
- ip: 127.0.0.1

View File

@@ -0,0 +1,84 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.1
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service2
namespace: testing
subsets:
- addresses:
- ip: 10.15.0.1
ports:
- port: 8080
- addresses:
- ip: 10.15.0.2
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service3
namespace: testing
subsets:
- addresses:
- ip: 10.14.0.1
ports:
- name: http
port: 8080
- addresses:
- ip: 10.12.0.1
ports:
- name: http
port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service4
namespace: testing
subsets:
- addresses:
- ip: 10.4.0.1
ports:
- name: http
port: 8080
- addresses:
- ip: 10.4.0.2
ports:
- name: http
port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service5
namespace: testing
subsets:
- addresses:
- ip: 10.4.0.1
ports:
- name: http
port: 8080
- addresses:
- ip: 10.4.0.2
ports:
- name: http
port: 8080

View File

@@ -0,0 +1,37 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
- host: bar
http:
paths:
- backend:
serviceName: service2
servicePort: 802
- host: baz
http:
paths:
- backend:
serviceName: service3
servicePort: 803
- host: max-conn
http:
paths:
- backend:
serviceName: service4
servicePort: 804
- host: flush
http:
paths:
- backend:
serviceName: service5
servicePort: 805

View File

@@ -0,0 +1,74 @@
apiVersion: v1
kind: Service
metadata:
annotations:
ingress.kubernetes.io/circuit-breaker-expression: NetworkErrorRatio() > 0.5
ingress.kubernetes.io/load-balancer-method: drr
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
annotations:
ingress.kubernetes.io/circuit-breaker-expression: ""
traefik.backend.loadbalancer.sticky: "true"
name: service2
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- port: 802
---
apiVersion: v1
kind: Service
metadata:
annotations:
ingress.kubernetes.io/buffering: |2
maxrequestbodybytes: 10485760
memrequestbodybytes: 2097153
maxresponsebodybytes: 10485761
memresponsebodybytes: 2097152
retryexpression: IsNetworkError() && Attempts() <= 2
name: service3
namespace: testing
spec:
clusterIP: 10.0.0.3
ports:
- name: http
port: 803
---
apiVersion: v1
kind: Service
metadata:
annotations:
ingress.kubernetes.io/max-conn-amount: "6"
ingress.kubernetes.io/max-conn-extractor-func: client.ip
name: service4
namespace: testing
spec:
clusterIP: 10.0.0.4
ports:
- name: http
port: 804
---
apiVersion: v1
kind: Service
metadata:
annotations:
ingress.kubernetes.io/responseforwarding-flushinterval: 10ms
name: service5
namespace: testing
spec:
clusterIP: 10.0.0.5
ports:
- port: 80

View File

@@ -0,0 +1,40 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/frontend-entry-points: ep1,ep2
namespace: testing
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: example-com
servicePort: 80
- host: example.org
http:
paths:
- backend:
serviceName: example-org
servicePort: 80
tls:
- secretName: myTlsSecret
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/frontend-entry-points: ep3
namespace: testing
spec:
rules:
- host: example.fail
http:
paths:
- backend:
serviceName: example-fail
servicePort: 80
tls:
- secretName: myUndefinedSecret

View File

@@ -0,0 +1,8 @@
apiVersion: v1
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
kind: Secret
metadata:
name: myTlsSecret
namespace: testing

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
name: example-com
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 80
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: example-org
namespace: testing
spec:
clusterIP: 10.0.0.2
ports:
- name: http
port: 80
type: ClusterIP

View File

@@ -0,0 +1,45 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: testing-"foo"
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: testing-"foo"
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /testing-"foo"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
package kubernetes
import (
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/containous/traefik/log"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes/scheme"
)
// MustEncodeYaml Encode object to YAML.
//
// ex:
// MustEncodeYaml(ingresses[0], "extensions/v1beta1", "ingress.yml")
// MustEncodeYaml(services[0], "v1", "service.yml")
// MustEncodeYaml(endpoints[0], "v1", "endpoint.yml")
func MustEncodeYaml(object runtime.Object, groupName string, w io.Writer) {
info, ok := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), "application/yaml")
if !ok {
panic("oops")
}
gv, err := schema.ParseGroupVersion(groupName)
if err != nil {
panic(err)
}
err = scheme.Codecs.EncoderForVersion(info.Serializer, gv).Encode(object, w)
if err != nil {
panic(err)
}
}
// MustDecodeYaml Decode a YAML to objects.
func MustDecodeYaml(content []byte) []runtime.Object {
acceptedK8sTypes := regexp.MustCompile(`(Deployment|Endpoints|Service|Ingress|Secret)`)
files := strings.Split(string(content), "---")
retVal := make([]runtime.Object, 0, len(files))
for _, file := range files {
if file == "\n" || file == "" {
continue
}
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, groupVersionKind, err := decode([]byte(file), nil, nil)
if err != nil {
panic(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err))
}
if !acceptedK8sTypes.MatchString(groupVersionKind.Kind) {
log.Debugf("The custom-roles configMap contained K8s object types which are not supported! Skipping object with type: %s", groupVersionKind.Kind)
} else {
retVal = append(retVal, obj)
}
}
return retVal
}
func mustCreateFile(filename string) *os.File {
fp := filepath.Join("fixtures", filename)
err := os.MkdirAll(filepath.Dir(fp), 0777)
if err != nil {
panic(err)
}
file, err := os.Create(fp)
if err != nil {
panic(err)
}
return file
}

View File

@@ -2,14 +2,13 @@ package kubernetes
import (
"fmt"
"io/ioutil"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
func TestString(t *testing.T) {
@@ -147,13 +146,9 @@ service1: 1000%
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
ingress := &extensionsv1beta1.Ingress{
ObjectMeta: v1.ObjectMeta{
Annotations: map[string]string{
annotationKubernetesServiceWeights: test.annotationValue,
},
},
}
ingress := buildIngress(
iAnnotation(annotationKubernetesServiceWeights, test.annotationValue),
)
weights, err := getServicesPercentageWeights(ingress)
@@ -168,93 +163,20 @@ service1: 1000%
}
func TestComputeServiceWeights(t *testing.T) {
client := clientMock{
services: []*corev1.Service{
buildService(
sName("service1"),
sNamespace("testing"),
),
buildService(
sName("service2"),
sNamespace("testing"),
),
buildService(
sName("service3"),
sNamespace("testing"),
),
buildService(
sName("service4"),
sNamespace("testing"),
),
},
endpoints: []*corev1.Endpoints{
buildEndpoint(
eNamespace("testing"),
eName("service1"),
eUID("1"),
subset(
eAddresses(eAddress("10.10.0.1")),
ePorts(ePort(8080, ""))),
subset(
eAddresses(eAddress("10.21.0.2")),
ePorts(ePort(8080, ""))),
),
buildEndpoint(
eNamespace("testing"),
eName("service2"),
eUID("2"),
subset(
eAddresses(eAddress("10.10.0.3")),
ePorts(ePort(8080, ""))),
),
buildEndpoint(
eNamespace("testing"),
eName("service3"),
eUID("3"),
subset(
eAddresses(eAddress("10.10.0.4")),
ePorts(ePort(8080, ""))),
subset(
eAddresses(eAddress("10.21.0.5")),
ePorts(ePort(8080, ""))),
subset(
eAddresses(eAddress("10.21.0.6")),
ePorts(ePort(8080, ""))),
subset(
eAddresses(eAddress("10.21.0.7")),
ePorts(ePort(8080, ""))),
),
buildEndpoint(
eNamespace("testing"),
eName("service4"),
eUID("4"),
subset(
eAddresses(eAddress("10.10.0.7")),
ePorts(ePort(8080, ""))),
),
},
}
client := newClientMock(
filepath.Join("fixtures", "computeServiceWeights_endpoints.yml"),
filepath.Join("fixtures", "computeServiceWeights_services.yml"),
)
testCases := []struct {
desc string
ingress *extensionsv1beta1.Ingress
ingress string
expectError bool
expectedWeights map[ingressService]percentageValue
}{
{
desc: "1 path 2 service",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 10%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromInt(8080))),
)),
),
),
desc: "1 path 2 service",
ingress: filepath.Join("fixtures", "computeServiceWeights", "1_path_2_service_ingresses.yml"),
expectError: false,
expectedWeights: map[ingressService]percentageValue{
{
@@ -270,21 +192,8 @@ service1: 10%
},
},
{
desc: "2 path 2 service",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 60%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("service3", intstr.FromInt(8080))),
)),
),
),
desc: "2 path 2 service",
ingress: filepath.Join("fixtures", "computeServiceWeights", "2_path_2_service_ingresses.yml"),
expectError: false,
expectedWeights: map[ingressService]percentageValue{
{
@@ -310,22 +219,8 @@ service1: 60%
},
},
{
desc: "2 path 3 service",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 20%
service3: 20%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("service2", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("service3", intstr.FromInt(8080))),
)),
),
),
desc: "2 path 3 service",
ingress: filepath.Join("fixtures", "computeServiceWeights", "2_path_3_service_ingresses.yml"),
expectError: false,
expectedWeights: map[ingressService]percentageValue{
{
@@ -351,23 +246,8 @@ service3: 20%
},
},
{
desc: "1 path 4 service",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 20%
service2: 40%
service3: 40%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service3", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service4", intstr.FromInt(8080))),
)),
),
),
desc: "1 path 4 service",
ingress: filepath.Join("fixtures", "computeServiceWeights", "1_path_4_service_ingresses.yml"),
expectError: false,
expectedWeights: map[ingressService]percentageValue{
{
@@ -393,35 +273,13 @@ service3: 40%
},
},
{
desc: "2 path no service",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 20%
service2: 40%
service3: 40%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("noservice", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("noservice", intstr.FromInt(8080))),
)),
),
),
desc: "2 path no service",
ingress: filepath.Join("fixtures", "computeServiceWeights", "2_path_no_service_ingresses.yml"),
expectError: true,
},
{
desc: "2 path without weight",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, ``),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/bar"), iBackend("service2", intstr.FromInt(8080))),
)),
),
),
desc: "2 path without weight",
ingress: filepath.Join("fixtures", "computeServiceWeights", "2_path_without_weight_ingresses.yml"),
expectError: false,
expectedWeights: map[ingressService]percentageValue{
{
@@ -437,20 +295,8 @@ service3: 40%
},
},
{
desc: "2 path overflow",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesServiceWeights, `
service1: 70%
service2: 80%
`),
iRules(
iRule(iHost("foo.test"), iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromInt(8080))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromInt(8080))),
)),
),
),
desc: "2 path overflow",
ingress: filepath.Join("fixtures", "computeServiceWeights", "2_path_overflow_ingresses.yml"),
expectError: true,
},
}
@@ -460,7 +306,20 @@ service2: 80%
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
weightAllocator, err := newFractionalWeightAllocator(test.ingress, client)
yamlContent, err := ioutil.ReadFile(test.ingress)
require.NoError(t, err)
k8sObjects := MustDecodeYaml(yamlContent)
require.Len(t, k8sObjects, 1)
var ingress *extensionsv1beta1.Ingress
switch o := k8sObjects[0].(type) {
case *extensionsv1beta1.Ingress:
ingress = o
default:
require.Fail(t, fmt.Sprintf("Unknown runtime object %+v %T", o, o))
}
weightAllocator, err := newFractionalWeightAllocator(ingress, client)
if test.expectError {
require.Error(t, err)
} else {

View File

@@ -75,7 +75,11 @@ func (p *Provider) watchKv(configurationChan chan<- types.ConfigMessage, prefix
if !ok {
return errors.New("watchtree channel closed")
}
configuration := p.buildConfiguration()
configuration, errC := p.buildConfiguration()
if errC != nil {
return errC
}
if configuration != nil {
configurationChan <- types.ConfigMessage{
ProviderName: string(p.storeType),
@@ -110,7 +114,11 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
}
})
}
configuration := p.buildConfiguration()
configuration, err := p.buildConfiguration()
if err != nil {
return err
}
configurationChan <- types.ConfigMessage{
ProviderName: string(p.storeType),
Configuration: configuration,

View File

@@ -18,7 +18,7 @@ import (
"github.com/containous/traefik/types"
)
func (p *Provider) buildConfiguration() *types.Configuration {
func (p *Provider) buildConfiguration() (*types.Configuration, error) {
templateObjects := struct {
Prefix string
}{
@@ -26,7 +26,7 @@ func (p *Provider) buildConfiguration() *types.Configuration {
Prefix: strings.TrimSuffix(p.get(p.Prefix, p.Prefix+pathAlias), pathSeparator),
}
var KvFuncMap = template.FuncMap{
kvFuncMap := template.FuncMap{
"List": p.list,
"ListServers": p.listServers,
"Get": p.get,
@@ -69,9 +69,9 @@ func (p *Provider) buildConfiguration() *types.Configuration {
"getStickinessCookieName": p.getStickinessCookieName, // Deprecated [breaking]
}
configuration, err := p.GetConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects)
configuration, err := p.safeGetConfiguration("templates/kv.tmpl", kvFuncMap, templateObjects)
if err != nil {
log.Error(err)
return nil, err
}
for key, frontend := range configuration.Frontends {
@@ -80,7 +80,19 @@ func (p *Provider) buildConfiguration() *types.Configuration {
}
}
return configuration
return configuration, nil
}
func (p *Provider) safeGetConfiguration(defaultTemplate string, funcMap template.FuncMap, templateObjects interface{}) (configuration *types.Configuration, err error) {
defer func() {
e := recover()
if e != nil {
err = fmt.Errorf("%v", e)
}
}()
configuration, err = p.GetConfiguration("templates/kv.tmpl", funcMap, templateObjects)
return
}
// Deprecated
@@ -564,9 +576,9 @@ func (p *Provider) listServers(backend string) []string {
func (p *Provider) serverFilter(serverName string) bool {
key := fmt.Sprint(serverName, pathBackendServerURL)
if _, err := p.kvClient.Get(key, nil); err != nil {
if err != store.ErrKeyNotFound {
log.Errorf("Failed to retrieve value for key %s: %s", key, err)
}
checkError(err)
log.Errorf("failed to retrieve value for key %s: %s", key, err)
return false
}
return p.checkConstraints(serverName, pathTags)
@@ -575,6 +587,9 @@ func (p *Provider) serverFilter(serverName string) bool {
func (p *Provider) checkConstraints(keys ...string) bool {
joinedKeys := strings.Join(keys, "")
keyPair, err := p.kvClient.Get(joinedKeys, nil)
if err != nil {
checkError(err)
}
value := ""
if err == nil && keyPair != nil && keyPair.Value != nil {
@@ -625,9 +640,13 @@ func (p *Provider) get(defaultValue string, keyParts ...string) string {
keyPair, err := p.kvClient.Get(key, nil)
if err != nil {
checkError(err)
log.Debugf("Cannot get key %s %s, setting default %s", key, err, defaultValue)
return defaultValue
} else if keyPair == nil {
}
if keyPair == nil {
log.Debugf("Cannot get key %s, setting default %s", key, defaultValue)
return defaultValue
}
@@ -663,6 +682,8 @@ func (p *Provider) hasPrefix(keyParts ...string) bool {
listKeys, err := p.kvClient.List(baseKey, nil)
if err != nil {
checkError(err)
log.Debugf("Cannot list keys under %q: %v", baseKey, err)
return false
}
@@ -705,6 +726,8 @@ func (p *Provider) list(keyParts ...string) []string {
keysPairs, err := p.kvClient.List(rootKey, nil)
if err != nil {
checkError(err)
log.Debugf("Cannot list keys under %q: %v", rootKey, err)
return nil
}
@@ -776,3 +799,9 @@ func (p *Provider) getMap(keyParts ...string) map[string]string {
return mapData
}
func checkError(err error) {
if err != store.ErrKeyNotFound {
panic(err)
}
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func aKVPair(key string, value string) *store.KVPair {
@@ -22,6 +23,7 @@ func TestProviderBuildConfiguration(t *testing.T) {
testCases := []struct {
desc string
kvPairs []*store.KVPair
kvError KvError
expected *types.Configuration
}{
{
@@ -553,6 +555,22 @@ func TestProviderBuildConfiguration(t *testing.T) {
},
},
},
{
desc: "Should recover on panic",
kvPairs: filler("traefik",
frontend("frontend",
withPair(pathFrontendBackend, "backend"),
withPair(pathFrontendAuthHeaderField, "X-WebAuth-User"),
withPair(pathFrontendAuthBasicRemoveHeader, "true"),
withList(pathFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"),
),
backend("backend"),
),
kvError: KvError{
List: store.ErrNotReachable,
},
expected: nil,
},
}
for _, test := range testCases {
@@ -564,19 +582,66 @@ func TestProviderBuildConfiguration(t *testing.T) {
Prefix: "traefik",
kvClient: &Mock{
KVPairs: test.kvPairs,
Error: test.kvError,
},
}
actual := p.buildConfiguration()
assert.NotNil(t, actual)
actual, err := p.buildConfiguration()
if test.kvError.Get != nil || test.kvError.List != nil {
require.Error(t, err)
require.Nil(t, actual)
} else {
require.NoError(t, err)
require.NotNil(t, actual)
assert.EqualValues(t, test.expected.Backends, actual.Backends)
assert.EqualValues(t, test.expected.Frontends, actual.Frontends)
}
assert.EqualValues(t, test.expected.Backends, actual.Backends)
assert.EqualValues(t, test.expected.Frontends, actual.Frontends)
assert.EqualValues(t, test.expected, actual)
})
}
}
func TestProviderListShouldPanic(t *testing.T) {
testCases := []struct {
desc string
panic bool
kvError error
}{
{
desc: "Should panic on an unexpected error",
kvError: store.ErrBackendNotSupported,
panic: true,
},
{
desc: "Should not panic on an ErrKeyNotFound error",
kvError: store.ErrKeyNotFound,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
kvPairs := []*store.KVPair{
aKVPair("foo", "bar"),
}
p := &Provider{
kvClient: newKvClientMock(kvPairs, test.kvError),
}
keyParts := []string{"foo"}
if test.panic {
assert.Panics(t, func() { p.list(keyParts...) })
} else {
assert.NotPanics(t, func() { p.list(keyParts...) })
}
})
}
}
func TestProviderList(t *testing.T) {
testCases := []struct {
desc string
@@ -622,8 +687,8 @@ func TestProviderList(t *testing.T) {
expected: []string{"foo/baz/1", "foo/baz/2"},
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
desc: "when KV error key not found",
kvError: store.ErrKeyNotFound,
kvPairs: []*store.KVPair{
aKVPair("foo/baz/1", "bar1"),
aKVPair("foo/baz/2", "bar2"),
@@ -651,6 +716,46 @@ func TestProviderList(t *testing.T) {
}
}
func TestProviderGetShouldPanic(t *testing.T) {
testCases := []struct {
desc string
panic bool
kvError error
}{
{
desc: "Should panic on an unexpected error",
kvError: store.ErrBackendNotSupported,
panic: true,
},
{
desc: "Should not panic on an ErrKeyNotFound error",
kvError: store.ErrKeyNotFound,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
kvPairs := []*store.KVPair{
aKVPair("foo", "bar"),
}
p := &Provider{
kvClient: newKvClientMock(kvPairs, test.kvError),
}
keyParts := []string{"foo"}
if test.panic {
assert.Panics(t, func() { p.get("", keyParts...) })
} else {
assert.NotPanics(t, func() { p.get("", keyParts...) })
}
})
}
}
func TestProviderGet(t *testing.T) {
testCases := []struct {
desc string
@@ -718,7 +823,7 @@ func TestProviderGet(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: []*store.KVPair{
aKVPair("foo/baz/1", "bar1"),
aKVPair("foo/baz/2", "bar2"),
@@ -824,7 +929,7 @@ func TestProviderSplitGet(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", ""),
@@ -900,7 +1005,7 @@ func TestProviderGetList(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", ""),
@@ -973,7 +1078,7 @@ func TestProviderGetSlice(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", ""),
@@ -1046,7 +1151,7 @@ func TestProviderGetBool(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", "true"),
@@ -1111,7 +1216,7 @@ func TestProviderGetInt(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", "true"),
@@ -1176,7 +1281,7 @@ func TestProviderGetInt64(t *testing.T) {
},
{
desc: "when KV error",
kvError: store.ErrNotReachable,
kvError: store.ErrKeyNotFound,
kvPairs: filler("traefik",
frontend("foo",
withPair("bar", "true"),

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More