Merge pull request #836 from yvespp/master
Migrate k8s to kubernetes/client-go
This commit is contained in:
commit
131f581f77
13 changed files with 1090 additions and 1195 deletions
|
@ -21,6 +21,10 @@ WORKDIR /go/src/github.com/containous/traefik
|
||||||
|
|
||||||
COPY glide.yaml glide.yaml
|
COPY glide.yaml glide.yaml
|
||||||
COPY glide.lock glide.lock
|
COPY glide.lock glide.lock
|
||||||
RUN glide install
|
RUN glide install -v
|
||||||
|
|
||||||
|
COPY integration/glide.yaml integration/glide.yaml
|
||||||
|
COPY integration/glide.lock integration/glide.lock
|
||||||
|
RUN cd integration && glide install
|
||||||
|
|
||||||
COPY . /go/src/github.com/containous/traefik
|
COPY . /go/src/github.com/containous/traefik
|
||||||
|
|
301
glide.lock
generated
301
glide.lock
generated
|
@ -1,5 +1,5 @@
|
||||||
hash: aae2fd761966717bcc30d8c03590cc28df8af49b36cc1d87689512cdfb44475e
|
hash: 3ff2f92356bc5d286ce4d72835d5ace63c43cc591e561fd2d557e8dc8abd1672
|
||||||
updated: 2016-11-16T21:37:51.673291661+01:00
|
updated: 2016-11-17T17:17:58.806741449Z
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/abbot/go-http-auth
|
- name: github.com/abbot/go-http-auth
|
||||||
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
|
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
|
||||||
|
@ -9,6 +9,8 @@ imports:
|
||||||
- eureka
|
- eureka
|
||||||
- name: github.com/ArthurHlt/gominlog
|
- name: github.com/ArthurHlt/gominlog
|
||||||
version: 068c01ce147ad68fca25ef3fa29ae5395ae273ab
|
version: 068c01ce147ad68fca25ef3fa29ae5395ae273ab
|
||||||
|
- name: github.com/blang/semver
|
||||||
|
version: 60ec3488bfea7cca02b021d106d9911120d25fe9
|
||||||
- name: github.com/boltdb/bolt
|
- name: github.com/boltdb/bolt
|
||||||
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
|
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
|
||||||
- name: github.com/BurntSushi/toml
|
- name: github.com/BurntSushi/toml
|
||||||
|
@ -19,10 +21,12 @@ imports:
|
||||||
- fun
|
- fun
|
||||||
- name: github.com/cenk/backoff
|
- name: github.com/cenk/backoff
|
||||||
version: 8edc80b07f38c27352fb186d971c628a6c32552b
|
version: 8edc80b07f38c27352fb186d971c628a6c32552b
|
||||||
|
- name: github.com/cloudfoundry-incubator/candiedyaml
|
||||||
|
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
|
||||||
- name: github.com/codahale/hdrhistogram
|
- name: github.com/codahale/hdrhistogram
|
||||||
version: f8ad88b59a584afeee9d334eff879b104439117b
|
version: 9208b142303c12d8899bae836fd524ac9338b4fd
|
||||||
- name: github.com/codegangsta/cli
|
- name: github.com/codegangsta/cli
|
||||||
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e
|
version: bf4a526f48af7badd25d2cb02d587e1b01be3b50
|
||||||
- name: github.com/codegangsta/negroni
|
- name: github.com/codegangsta/negroni
|
||||||
version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c
|
version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c
|
||||||
- name: github.com/containous/flaeg
|
- name: github.com/containous/flaeg
|
||||||
|
@ -32,11 +36,28 @@ imports:
|
||||||
- name: github.com/containous/staert
|
- name: github.com/containous/staert
|
||||||
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
|
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
|
||||||
- name: github.com/coreos/etcd
|
- name: github.com/coreos/etcd
|
||||||
version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899
|
version: c400d05d0aa73e21e431c16145e558d624098018
|
||||||
subpackages:
|
subpackages:
|
||||||
|
- Godeps/_workspace/src/github.com/ugorji/go/codec
|
||||||
|
- Godeps/_workspace/src/golang.org/x/net/context
|
||||||
- client
|
- client
|
||||||
- pkg/pathutil
|
- pkg/pathutil
|
||||||
- pkg/types
|
- pkg/types
|
||||||
|
- name: github.com/coreos/go-oidc
|
||||||
|
version: 16c5ecc505f1efa0fe4685826fd9962c4d137e87
|
||||||
|
subpackages:
|
||||||
|
- http
|
||||||
|
- jose
|
||||||
|
- key
|
||||||
|
- oauth2
|
||||||
|
- oidc
|
||||||
|
- name: github.com/coreos/pkg
|
||||||
|
version: 2c77715c4df99b5420ffcae14ead08f52104065d
|
||||||
|
subpackages:
|
||||||
|
- capnslog
|
||||||
|
- health
|
||||||
|
- httputil
|
||||||
|
- timeutil
|
||||||
- name: github.com/davecgh/go-spew
|
- name: github.com/davecgh/go-spew
|
||||||
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
subpackages:
|
subpackages:
|
||||||
|
@ -133,23 +154,6 @@ imports:
|
||||||
version: f2145db703495b2e525c59662db69a7344b00bb8
|
version: f2145db703495b2e525c59662db69a7344b00bb8
|
||||||
- name: github.com/docker/leadership
|
- name: github.com/docker/leadership
|
||||||
version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6
|
version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6
|
||||||
- name: github.com/docker/libcompose
|
|
||||||
version: d1876c1d68527a49c0aac22a0b161acc7296b740
|
|
||||||
subpackages:
|
|
||||||
- config
|
|
||||||
- docker
|
|
||||||
- docker/builder
|
|
||||||
- docker/client
|
|
||||||
- docker/network
|
|
||||||
- labels
|
|
||||||
- logger
|
|
||||||
- lookup
|
|
||||||
- project
|
|
||||||
- project/events
|
|
||||||
- project/options
|
|
||||||
- utils
|
|
||||||
- version
|
|
||||||
- yaml
|
|
||||||
- name: github.com/docker/libkv
|
- name: github.com/docker/libkv
|
||||||
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
|
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
|
||||||
subpackages:
|
subpackages:
|
||||||
|
@ -162,22 +166,42 @@ imports:
|
||||||
version: fd1de70867126402be23c306e1ce32828455d85b
|
version: fd1de70867126402be23c306e1ce32828455d85b
|
||||||
- name: github.com/elazarl/go-bindata-assetfs
|
- name: github.com/elazarl/go-bindata-assetfs
|
||||||
version: 9a6736ed45b44bf3835afeebb3034b57ed329f3e
|
version: 9a6736ed45b44bf3835afeebb3034b57ed329f3e
|
||||||
|
- name: github.com/emicklei/go-restful
|
||||||
|
version: 892402ba11a2e2fd5e1295dd633481f27365f14d
|
||||||
|
subpackages:
|
||||||
|
- log
|
||||||
|
- swagger
|
||||||
- name: github.com/gambol99/go-marathon
|
- name: github.com/gambol99/go-marathon
|
||||||
version: a558128c87724cd7430060ef5aedf39f83937f55
|
version: a558128c87724cd7430060ef5aedf39f83937f55
|
||||||
- name: github.com/go-check/check
|
- name: github.com/ghodss/yaml
|
||||||
version: 4f90aeace3a26ad7021961c297b22c42160c7b25
|
version: aa0c862057666179de291b67d9f093d12b5a8473
|
||||||
|
- name: github.com/go-openapi/jsonpointer
|
||||||
|
version: 8d96a2dc61536b690bd36b2e9df0b3c0b62825b2
|
||||||
|
- name: github.com/go-openapi/jsonreference
|
||||||
|
version: 36d33bfe519efae5632669801b180bf1a245da3b
|
||||||
|
- name: github.com/go-openapi/spec
|
||||||
|
version: d1c18b339aece4b16ead6d253b85b6ad7180ea54
|
||||||
|
- name: github.com/go-openapi/swag
|
||||||
|
version: 3b6d86cd965820f968760d5d419cb4add096bdd7
|
||||||
- name: github.com/gogo/protobuf
|
- name: github.com/gogo/protobuf
|
||||||
version: 99cb9b23110011cc45571c901ecae6f6f5e65cd3
|
version: 909568be09de550ed094403c2bf8a261b5bb730a
|
||||||
subpackages:
|
subpackages:
|
||||||
- proto
|
- proto
|
||||||
|
- sortkeys
|
||||||
- name: github.com/golang/glog
|
- name: github.com/golang/glog
|
||||||
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
|
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
|
||||||
|
- name: github.com/golang/protobuf
|
||||||
|
version: 5677a0e3d5e89854c9974e1256839ee23f8233ca
|
||||||
|
subpackages:
|
||||||
|
- proto
|
||||||
- name: github.com/google/go-querystring
|
- name: github.com/google/go-querystring
|
||||||
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
|
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
|
||||||
subpackages:
|
subpackages:
|
||||||
- query
|
- query
|
||||||
|
- name: github.com/google/gofuzz
|
||||||
|
version: fd52762d25a41827db7ef64c43756fd4b9f7e382
|
||||||
- name: github.com/gorilla/context
|
- name: github.com/gorilla/context
|
||||||
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
|
version: 14f550f51af52180c2eefed15e5fd18d63c0a64a
|
||||||
- name: github.com/hashicorp/consul
|
- name: github.com/hashicorp/consul
|
||||||
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
|
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
|
||||||
subpackages:
|
subpackages:
|
||||||
|
@ -185,21 +209,25 @@ imports:
|
||||||
- name: github.com/hashicorp/go-cleanhttp
|
- name: github.com/hashicorp/go-cleanhttp
|
||||||
version: ad28ea4487f05916463e2423a55166280e8254b5
|
version: ad28ea4487f05916463e2423a55166280e8254b5
|
||||||
- name: github.com/hashicorp/serf
|
- name: github.com/hashicorp/serf
|
||||||
version: b03bf85930b2349eb04b97c8fac437495296e3e7
|
version: 598c54895cc5a7b1a24a398d635e8c0ea0959870
|
||||||
subpackages:
|
subpackages:
|
||||||
- coordinate
|
- coordinate
|
||||||
- name: github.com/jarcoal/httpmock
|
- name: github.com/jarcoal/httpmock
|
||||||
version: 145b10d659265440f062c31ea15326166bae56ee
|
version: 145b10d659265440f062c31ea15326166bae56ee
|
||||||
- name: github.com/libkermit/compose
|
- name: github.com/jonboulle/clockwork
|
||||||
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
|
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
|
||||||
subpackages:
|
- name: github.com/juju/ratelimit
|
||||||
- check
|
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
|
||||||
- name: github.com/libkermit/docker
|
|
||||||
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
|
|
||||||
- name: github.com/mailgun/manners
|
- name: github.com/mailgun/manners
|
||||||
version: a585afd9d65c0e05f6c003f921e71ebc05074f4f
|
version: a585afd9d65c0e05f6c003f921e71ebc05074f4f
|
||||||
- name: github.com/mailgun/timetools
|
- name: github.com/mailgun/timetools
|
||||||
version: fd192d755b00c968d312d23f521eb0cdc6f66bd0
|
version: fd192d755b00c968d312d23f521eb0cdc6f66bd0
|
||||||
|
- name: github.com/mailru/easyjson
|
||||||
|
version: 159cdb893c982e3d1bc6450322fedd514f9c9de3
|
||||||
|
subpackages:
|
||||||
|
- buffer
|
||||||
|
- jlexer
|
||||||
|
- jwriter
|
||||||
- name: github.com/mattn/go-shellwords
|
- name: github.com/mattn/go-shellwords
|
||||||
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
|
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
|
||||||
- name: github.com/mesos/mesos-go
|
- name: github.com/mesos/mesos-go
|
||||||
|
@ -230,22 +258,22 @@ imports:
|
||||||
version: 5d001d020961ae1c184f9f8152fdc73810481677
|
version: 5d001d020961ae1c184f9f8152fdc73810481677
|
||||||
- name: github.com/mitchellh/mapstructure
|
- name: github.com/mitchellh/mapstructure
|
||||||
version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1
|
version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1
|
||||||
- name: github.com/moul/http2curl
|
|
||||||
version: b1479103caacaa39319f75e7f57fc545287fca0d
|
|
||||||
- name: github.com/NYTimes/gziphandler
|
- name: github.com/NYTimes/gziphandler
|
||||||
version: f6438dbf4a82c56684964b03956aa727b0d7816b
|
version: f6438dbf4a82c56684964b03956aa727b0d7816b
|
||||||
- name: github.com/ogier/pflag
|
- name: github.com/ogier/pflag
|
||||||
version: 45c278ab3607870051a2ea9040bb85fcb8557481
|
version: 45c278ab3607870051a2ea9040bb85fcb8557481
|
||||||
- name: github.com/opencontainers/runc
|
- name: github.com/opencontainers/runc
|
||||||
version: 02f8fa7863dd3f82909a73e2061897828460d52f
|
version: ba1568de399395774ad84c2ace65937814c542ed
|
||||||
subpackages:
|
subpackages:
|
||||||
- libcontainer/user
|
- libcontainer/user
|
||||||
- name: github.com/parnurzeal/gorequest
|
- name: github.com/parnurzeal/gorequest
|
||||||
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
|
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
|
||||||
- name: github.com/pmezard/go-difflib
|
- name: github.com/pborman/uuid
|
||||||
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
version: 3d4f2ba23642d3cfd06bd4b54cf03d99d95c0f1b
|
||||||
subpackages:
|
- name: github.com/PuerkitoBio/purell
|
||||||
- difflib
|
version: 0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4
|
||||||
|
- name: github.com/PuerkitoBio/urlesc
|
||||||
|
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
|
||||||
- name: github.com/ryanuber/go-glob
|
- name: github.com/ryanuber/go-glob
|
||||||
version: 572520ed46dbddaed19ea3d9541bdd0494163693
|
version: 572520ed46dbddaed19ea3d9541bdd0494163693
|
||||||
- name: github.com/samuel/go-zookeeper
|
- name: github.com/samuel/go-zookeeper
|
||||||
|
@ -256,12 +284,14 @@ imports:
|
||||||
version: 879c5887cd475cd7864858769793b2ceb0d44feb
|
version: 879c5887cd475cd7864858769793b2ceb0d44feb
|
||||||
- name: github.com/Sirupsen/logrus
|
- name: github.com/Sirupsen/logrus
|
||||||
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
|
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
|
||||||
|
- name: github.com/spf13/pflag
|
||||||
|
version: 5644820622454e71517561946e3d94b9f9db6842
|
||||||
- name: github.com/streamrail/concurrent-map
|
- name: github.com/streamrail/concurrent-map
|
||||||
version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5
|
version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5
|
||||||
- name: github.com/stretchr/objx
|
- name: github.com/stretchr/objx
|
||||||
version: cbeaeb16a013161a98496fad62933b1d21786672
|
version: cbeaeb16a013161a98496fad62933b1d21786672
|
||||||
- name: github.com/stretchr/testify
|
- name: github.com/stretchr/testify
|
||||||
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506
|
version: b8dc1cecf15bdaf1988d9e87aa7cd98d899a06d6
|
||||||
subpackages:
|
subpackages:
|
||||||
- assert
|
- assert
|
||||||
- mock
|
- mock
|
||||||
|
@ -270,15 +300,13 @@ imports:
|
||||||
- name: github.com/tv42/zbase32
|
- name: github.com/tv42/zbase32
|
||||||
version: 03389da7e0bf9844767f82690f4d68fc097a1306
|
version: 03389da7e0bf9844767f82690f4d68fc097a1306
|
||||||
- name: github.com/ugorji/go
|
- name: github.com/ugorji/go
|
||||||
version: b94837a2404ab90efe9289e77a70694c355739cb
|
version: ea9cd21fa0bc41ee4bdd50ac7ed8cbc7ea2ed960
|
||||||
subpackages:
|
subpackages:
|
||||||
- codec
|
- codec
|
||||||
- name: github.com/unrolled/render
|
- name: github.com/unrolled/render
|
||||||
version: 526faf80cd4b305bb8134abea8d20d5ced74faa6
|
version: 526faf80cd4b305bb8134abea8d20d5ced74faa6
|
||||||
- name: github.com/vdemeester/docker-events
|
- name: github.com/vdemeester/docker-events
|
||||||
version: be74d4929ec1ad118df54349fda4b0cba60f849b
|
version: be74d4929ec1ad118df54349fda4b0cba60f849b
|
||||||
- name: github.com/vdemeester/shakers
|
|
||||||
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
|
||||||
- name: github.com/vulcand/oxy
|
- name: github.com/vulcand/oxy
|
||||||
version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613
|
version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613
|
||||||
repo: https://github.com/containous/oxy.git
|
repo: https://github.com/containous/oxy.git
|
||||||
|
@ -296,7 +324,7 @@ imports:
|
||||||
- name: github.com/vulcand/route
|
- name: github.com/vulcand/route
|
||||||
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
|
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
|
||||||
- name: github.com/vulcand/vulcand
|
- name: github.com/vulcand/vulcand
|
||||||
version: bed092e10989250b48bdb6aa3b0557b207f05c80
|
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
|
||||||
subpackages:
|
subpackages:
|
||||||
- conntracker
|
- conntracker
|
||||||
- plugin
|
- plugin
|
||||||
|
@ -307,26 +335,62 @@ imports:
|
||||||
subpackages:
|
subpackages:
|
||||||
- acme
|
- acme
|
||||||
- name: golang.org/x/crypto
|
- name: golang.org/x/crypto
|
||||||
version: d81fdb778bf2c40a91b24519d60cdc5767318829
|
version: 4ed45ec682102c643324fae5dff8dab085b6c300
|
||||||
subpackages:
|
subpackages:
|
||||||
- bcrypt
|
- bcrypt
|
||||||
- blowfish
|
- blowfish
|
||||||
- ocsp
|
- ocsp
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: b400c2eff1badec7022a8c8f5bea058b6315eed7
|
version: d4c55e66d8c3a2f3382d264b08e3e3454a66355a
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
|
- http2
|
||||||
|
- http2/hpack
|
||||||
|
- idna
|
||||||
|
- lex/httplex
|
||||||
- proxy
|
- proxy
|
||||||
- publicsuffix
|
- publicsuffix
|
||||||
|
- name: golang.org/x/oauth2
|
||||||
|
version: 3046bc76d6dfd7d3707f6640f85e42d9c4050f50
|
||||||
|
subpackages:
|
||||||
|
- google
|
||||||
|
- internal
|
||||||
|
- jws
|
||||||
|
- jwt
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
version: 62bee037599929a6e9146f29d10dd5208c43507d
|
version: eb2c74142fd19a79b3f237334c7384d5167b1b46
|
||||||
subpackages:
|
subpackages:
|
||||||
- unix
|
- unix
|
||||||
- windows
|
- windows
|
||||||
|
- name: golang.org/x/text
|
||||||
|
version: a263ba8db058568bb9beba166777d9c9dbe75d68
|
||||||
|
subpackages:
|
||||||
|
- transform
|
||||||
|
- unicode/norm
|
||||||
|
- width
|
||||||
|
- name: google.golang.org/appengine
|
||||||
|
version: 12d5545dc1cfa6047a286d5e853841b6471f4c19
|
||||||
|
subpackages:
|
||||||
|
- internal
|
||||||
|
- internal/app_identity
|
||||||
|
- internal/base
|
||||||
|
- internal/datastore
|
||||||
|
- internal/log
|
||||||
|
- internal/modules
|
||||||
|
- internal/remote_api
|
||||||
|
- internal/urlfetch
|
||||||
|
- urlfetch
|
||||||
|
- name: google.golang.org/cloud
|
||||||
|
version: f20d6dcccb44ed49de45ae3703312cb46e627db1
|
||||||
|
subpackages:
|
||||||
|
- compute/metadata
|
||||||
|
- internal
|
||||||
- name: gopkg.in/fsnotify.v1
|
- name: gopkg.in/fsnotify.v1
|
||||||
version: 944cff21b3baf3ced9a880365682152ba577d348
|
version: 944cff21b3baf3ced9a880365682152ba577d348
|
||||||
|
- name: gopkg.in/inf.v0
|
||||||
|
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||||
- name: gopkg.in/mgo.v2
|
- name: gopkg.in/mgo.v2
|
||||||
version: 22287bab4379e1fbf6002fb4eb769888f3fb224c
|
version: 29cc868a5ca65f401ff318143f9408d02f4799cc
|
||||||
subpackages:
|
subpackages:
|
||||||
- bson
|
- bson
|
||||||
- name: gopkg.in/square/go-jose.v1
|
- name: gopkg.in/square/go-jose.v1
|
||||||
|
@ -334,27 +398,156 @@ imports:
|
||||||
subpackages:
|
subpackages:
|
||||||
- cipher
|
- cipher
|
||||||
- json
|
- json
|
||||||
|
- name: k8s.io/client-go
|
||||||
|
version: 843f7c4f28b1f647f664f883697107d5c02c5acc
|
||||||
|
subpackages:
|
||||||
|
- 1.5/discovery
|
||||||
|
- 1.5/kubernetes
|
||||||
|
- 1.5/kubernetes/typed/apps/v1alpha1
|
||||||
|
- 1.5/kubernetes/typed/authentication/v1beta1
|
||||||
|
- 1.5/kubernetes/typed/authorization/v1beta1
|
||||||
|
- 1.5/kubernetes/typed/autoscaling/v1
|
||||||
|
- 1.5/kubernetes/typed/batch/v1
|
||||||
|
- 1.5/kubernetes/typed/certificates/v1alpha1
|
||||||
|
- 1.5/kubernetes/typed/core/v1
|
||||||
|
- 1.5/kubernetes/typed/extensions/v1beta1
|
||||||
|
- 1.5/kubernetes/typed/policy/v1alpha1
|
||||||
|
- 1.5/kubernetes/typed/rbac/v1alpha1
|
||||||
|
- 1.5/kubernetes/typed/storage/v1beta1
|
||||||
|
- 1.5/pkg/api
|
||||||
|
- 1.5/pkg/api/errors
|
||||||
|
- 1.5/pkg/api/install
|
||||||
|
- 1.5/pkg/api/meta
|
||||||
|
- 1.5/pkg/api/meta/metatypes
|
||||||
|
- 1.5/pkg/api/resource
|
||||||
|
- 1.5/pkg/api/unversioned
|
||||||
|
- 1.5/pkg/api/v1
|
||||||
|
- 1.5/pkg/api/validation/path
|
||||||
|
- 1.5/pkg/apimachinery
|
||||||
|
- 1.5/pkg/apimachinery/announced
|
||||||
|
- 1.5/pkg/apimachinery/registered
|
||||||
|
- 1.5/pkg/apis/apps
|
||||||
|
- 1.5/pkg/apis/apps/install
|
||||||
|
- 1.5/pkg/apis/apps/v1alpha1
|
||||||
|
- 1.5/pkg/apis/authentication
|
||||||
|
- 1.5/pkg/apis/authentication/install
|
||||||
|
- 1.5/pkg/apis/authentication/v1beta1
|
||||||
|
- 1.5/pkg/apis/authorization
|
||||||
|
- 1.5/pkg/apis/authorization/install
|
||||||
|
- 1.5/pkg/apis/authorization/v1beta1
|
||||||
|
- 1.5/pkg/apis/autoscaling
|
||||||
|
- 1.5/pkg/apis/autoscaling/install
|
||||||
|
- 1.5/pkg/apis/autoscaling/v1
|
||||||
|
- 1.5/pkg/apis/batch
|
||||||
|
- 1.5/pkg/apis/batch/install
|
||||||
|
- 1.5/pkg/apis/batch/v1
|
||||||
|
- 1.5/pkg/apis/batch/v2alpha1
|
||||||
|
- 1.5/pkg/apis/certificates
|
||||||
|
- 1.5/pkg/apis/certificates/install
|
||||||
|
- 1.5/pkg/apis/certificates/v1alpha1
|
||||||
|
- 1.5/pkg/apis/extensions
|
||||||
|
- 1.5/pkg/apis/extensions/install
|
||||||
|
- 1.5/pkg/apis/extensions/v1beta1
|
||||||
|
- 1.5/pkg/apis/policy
|
||||||
|
- 1.5/pkg/apis/policy/install
|
||||||
|
- 1.5/pkg/apis/policy/v1alpha1
|
||||||
|
- 1.5/pkg/apis/rbac
|
||||||
|
- 1.5/pkg/apis/rbac/install
|
||||||
|
- 1.5/pkg/apis/rbac/v1alpha1
|
||||||
|
- 1.5/pkg/apis/storage
|
||||||
|
- 1.5/pkg/apis/storage/install
|
||||||
|
- 1.5/pkg/apis/storage/v1beta1
|
||||||
|
- 1.5/pkg/auth/user
|
||||||
|
- 1.5/pkg/conversion
|
||||||
|
- 1.5/pkg/conversion/queryparams
|
||||||
|
- 1.5/pkg/fields
|
||||||
|
- 1.5/pkg/genericapiserver/openapi/common
|
||||||
|
- 1.5/pkg/labels
|
||||||
|
- 1.5/pkg/runtime
|
||||||
|
- 1.5/pkg/runtime/serializer
|
||||||
|
- 1.5/pkg/runtime/serializer/json
|
||||||
|
- 1.5/pkg/runtime/serializer/protobuf
|
||||||
|
- 1.5/pkg/runtime/serializer/recognizer
|
||||||
|
- 1.5/pkg/runtime/serializer/streaming
|
||||||
|
- 1.5/pkg/runtime/serializer/versioning
|
||||||
|
- 1.5/pkg/selection
|
||||||
|
- 1.5/pkg/third_party/forked/golang/reflect
|
||||||
|
- 1.5/pkg/types
|
||||||
|
- 1.5/pkg/util
|
||||||
|
- 1.5/pkg/util/cert
|
||||||
|
- 1.5/pkg/util/clock
|
||||||
|
- 1.5/pkg/util/errors
|
||||||
|
- 1.5/pkg/util/flowcontrol
|
||||||
|
- 1.5/pkg/util/framer
|
||||||
|
- 1.5/pkg/util/integer
|
||||||
|
- 1.5/pkg/util/intstr
|
||||||
|
- 1.5/pkg/util/json
|
||||||
|
- 1.5/pkg/util/labels
|
||||||
|
- 1.5/pkg/util/net
|
||||||
|
- 1.5/pkg/util/parsers
|
||||||
|
- 1.5/pkg/util/rand
|
||||||
|
- 1.5/pkg/util/runtime
|
||||||
|
- 1.5/pkg/util/sets
|
||||||
|
- 1.5/pkg/util/uuid
|
||||||
|
- 1.5/pkg/util/validation
|
||||||
|
- 1.5/pkg/util/validation/field
|
||||||
|
- 1.5/pkg/util/wait
|
||||||
|
- 1.5/pkg/util/yaml
|
||||||
|
- 1.5/pkg/version
|
||||||
|
- 1.5/pkg/watch
|
||||||
|
- 1.5/pkg/watch/versioned
|
||||||
|
- 1.5/plugin/pkg/client/auth
|
||||||
|
- 1.5/plugin/pkg/client/auth/gcp
|
||||||
|
- 1.5/plugin/pkg/client/auth/oidc
|
||||||
|
- 1.5/rest
|
||||||
|
- 1.5/tools/cache
|
||||||
|
- 1.5/tools/clientcmd/api
|
||||||
|
- 1.5/tools/metrics
|
||||||
|
- 1.5/transport
|
||||||
testImports:
|
testImports:
|
||||||
- name: github.com/Azure/go-ansiterm
|
- name: github.com/Azure/go-ansiterm
|
||||||
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
|
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
|
||||||
subpackages:
|
subpackages:
|
||||||
- winterm
|
- winterm
|
||||||
- name: github.com/cloudfoundry-incubator/candiedyaml
|
- name: github.com/docker/libcompose
|
||||||
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
|
version: d1876c1d68527a49c0aac22a0b161acc7296b740
|
||||||
|
subpackages:
|
||||||
|
- config
|
||||||
|
- docker
|
||||||
|
- docker/builder
|
||||||
|
- docker/client
|
||||||
|
- docker/network
|
||||||
|
- labels
|
||||||
|
- logger
|
||||||
|
- lookup
|
||||||
|
- project
|
||||||
|
- project/events
|
||||||
|
- project/options
|
||||||
|
- utils
|
||||||
|
- version
|
||||||
|
- yaml
|
||||||
- name: github.com/flynn/go-shlex
|
- name: github.com/flynn/go-shlex
|
||||||
version: 3f9db97f856818214da2e1057f8ad84803971cff
|
version: 3f9db97f856818214da2e1057f8ad84803971cff
|
||||||
|
- name: github.com/go-check/check
|
||||||
|
version: 11d3bc7aa68e238947792f30573146a3231fc0f1
|
||||||
- name: github.com/gorilla/mux
|
- name: github.com/gorilla/mux
|
||||||
version: 9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e
|
version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf
|
||||||
|
- name: github.com/libkermit/compose
|
||||||
|
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
|
||||||
|
subpackages:
|
||||||
|
- check
|
||||||
|
- name: github.com/libkermit/docker
|
||||||
|
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
|
||||||
- name: github.com/libkermit/docker-check
|
- name: github.com/libkermit/docker-check
|
||||||
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
|
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
|
||||||
- name: github.com/spf13/pflag
|
|
||||||
version: 5644820622454e71517561946e3d94b9f9db6842
|
|
||||||
- name: github.com/vbatts/tar-split
|
- name: github.com/vbatts/tar-split
|
||||||
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721
|
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721
|
||||||
subpackages:
|
subpackages:
|
||||||
- archive/tar
|
- archive/tar
|
||||||
- tar/asm
|
- tar/asm
|
||||||
- tar/storage
|
- tar/storage
|
||||||
|
- name: github.com/vdemeester/shakers
|
||||||
|
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
||||||
- name: github.com/xeipuuv/gojsonpointer
|
- name: github.com/xeipuuv/gojsonpointer
|
||||||
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
|
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
|
||||||
- name: github.com/xeipuuv/gojsonreference
|
- name: github.com/xeipuuv/gojsonreference
|
||||||
|
|
17
glide.yaml
17
glide.yaml
|
@ -58,26 +58,23 @@ import:
|
||||||
- package: github.com/vdemeester/docker-events
|
- package: github.com/vdemeester/docker-events
|
||||||
version: be74d4929ec1ad118df54349fda4b0cba60f849b
|
version: be74d4929ec1ad118df54349fda4b0cba60f849b
|
||||||
- package: github.com/vulcand/vulcand
|
- package: github.com/vulcand/vulcand
|
||||||
|
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
|
||||||
subpackages:
|
subpackages:
|
||||||
- plugin/rewrite
|
- plugin/rewrite
|
||||||
- package: github.com/xenolf/lego
|
- package: github.com/xenolf/lego
|
||||||
version: b2fad6198110326662e9e356a97199078a4a775c
|
version: b2fad6198110326662e9e356a97199078a4a775c
|
||||||
subpackages:
|
subpackages:
|
||||||
- acme
|
- acme
|
||||||
|
- package: golang.org/x/net
|
||||||
|
version: release-branch.go1.7
|
||||||
|
subpackages:
|
||||||
|
- context
|
||||||
- package: gopkg.in/fsnotify.v1
|
- package: gopkg.in/fsnotify.v1
|
||||||
- package: github.com/libkermit/compose
|
|
||||||
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
|
|
||||||
- package: github.com/libkermit/docker
|
|
||||||
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
|
|
||||||
- package: github.com/docker/docker
|
- package: github.com/docker/docker
|
||||||
version: 534753663161334baba06f13b8efa4cad22b5bc5
|
version: 534753663161334baba06f13b8efa4cad22b5bc5
|
||||||
subpackages:
|
subpackages:
|
||||||
- namesgenerator
|
- namesgenerator
|
||||||
- package: github.com/go-check/check
|
|
||||||
- package: github.com/docker/libcompose
|
|
||||||
version: d1876c1d68527a49c0aac22a0b161acc7296b740
|
|
||||||
- package: github.com/mattn/go-shellwords
|
- package: github.com/mattn/go-shellwords
|
||||||
- package: github.com/vdemeester/shakers
|
|
||||||
- package: github.com/ryanuber/go-glob
|
- package: github.com/ryanuber/go-glob
|
||||||
- package: github.com/mesos/mesos-go
|
- package: github.com/mesos/mesos-go
|
||||||
subpackages:
|
subpackages:
|
||||||
|
@ -99,6 +96,10 @@ import:
|
||||||
- package: github.com/docker/leadership
|
- package: github.com/docker/leadership
|
||||||
- package: github.com/satori/go.uuid
|
- package: github.com/satori/go.uuid
|
||||||
version: ^1.1.0
|
version: ^1.1.0
|
||||||
|
- package: k8s.io/client-go
|
||||||
|
version: ^v1.5.0
|
||||||
|
- package: github.com/gogo/protobuf
|
||||||
|
version: 0.3
|
||||||
- package: github.com/ArthurHlt/go-eureka-client
|
- package: github.com/ArthurHlt/go-eureka-client
|
||||||
subpackages:
|
subpackages:
|
||||||
- eureka
|
- eureka
|
||||||
|
|
295
integration/glide.lock
generated
Normal file
295
integration/glide.lock
generated
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
hash: c53f57a45247b08a91f127ece494d49f1b7fee8c5f75be87ab12e27aa92d065f
|
||||||
|
updated: 2016-11-17T16:23:56.727970904Z
|
||||||
|
imports:
|
||||||
|
- name: github.com/cenk/backoff
|
||||||
|
version: 8edc80b07f38c27352fb186d971c628a6c32552b
|
||||||
|
testImports:
|
||||||
|
- name: github.com/ArthurHlt/go-eureka-client
|
||||||
|
version: ba361cd0f9f571b4e871421423d2f02f5689c3d2
|
||||||
|
subpackages:
|
||||||
|
- eureka
|
||||||
|
- name: github.com/ArthurHlt/gominlog
|
||||||
|
version: 068c01ce147ad68fca25ef3fa29ae5395ae273ab
|
||||||
|
- name: github.com/Azure/go-ansiterm
|
||||||
|
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
|
||||||
|
subpackages:
|
||||||
|
- winterm
|
||||||
|
- name: github.com/boltdb/bolt
|
||||||
|
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
|
||||||
|
- name: github.com/BurntSushi/toml
|
||||||
|
version: 99064174e013895bbd9b025c31100bd1d9b590ca
|
||||||
|
- name: github.com/BurntSushi/ty
|
||||||
|
version: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
|
||||||
|
subpackages:
|
||||||
|
- fun
|
||||||
|
- name: github.com/cloudfoundry-incubator/candiedyaml
|
||||||
|
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
|
||||||
|
- name: github.com/containous/flaeg
|
||||||
|
version: a731c034dda967333efce5f8d276aeff11f8ff87
|
||||||
|
- name: github.com/containous/staert
|
||||||
|
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
|
||||||
|
- name: github.com/containous/traefik
|
||||||
|
version: 15732269da23c35524bf7cabea5857e4c5f63881
|
||||||
|
subpackages:
|
||||||
|
- autogen
|
||||||
|
- cluster
|
||||||
|
- job
|
||||||
|
- log
|
||||||
|
- provider
|
||||||
|
- provider/k8s
|
||||||
|
- safe
|
||||||
|
- types
|
||||||
|
- version
|
||||||
|
- name: github.com/coreos/etcd
|
||||||
|
version: c400d05d0aa73e21e431c16145e558d624098018
|
||||||
|
subpackages:
|
||||||
|
- Godeps/_workspace/src/github.com/ugorji/go/codec
|
||||||
|
- Godeps/_workspace/src/golang.org/x/net/context
|
||||||
|
- client
|
||||||
|
- pkg/pathutil
|
||||||
|
- pkg/types
|
||||||
|
- name: github.com/daviddengcn/go-colortext
|
||||||
|
version: 3b18c8575a432453d41fdafb340099fff5bba2f7
|
||||||
|
- name: github.com/docker/distribution
|
||||||
|
version: 99cb7c0946d2f5a38015443e515dc916295064d7
|
||||||
|
subpackages:
|
||||||
|
- context
|
||||||
|
- digest
|
||||||
|
- reference
|
||||||
|
- registry/api/errcode
|
||||||
|
- registry/api/v2
|
||||||
|
- registry/client
|
||||||
|
- registry/client/auth
|
||||||
|
- registry/client/transport
|
||||||
|
- registry/storage/cache
|
||||||
|
- registry/storage/cache/memory
|
||||||
|
- uuid
|
||||||
|
- name: github.com/docker/docker
|
||||||
|
version: 534753663161334baba06f13b8efa4cad22b5bc5
|
||||||
|
subpackages:
|
||||||
|
- api/types/backend
|
||||||
|
- builder
|
||||||
|
- builder/dockerignore
|
||||||
|
- cliconfig
|
||||||
|
- cliconfig/configfile
|
||||||
|
- daemon/graphdriver
|
||||||
|
- image
|
||||||
|
- image/v1
|
||||||
|
- layer
|
||||||
|
- opts
|
||||||
|
- pkg/archive
|
||||||
|
- pkg/chrootarchive
|
||||||
|
- pkg/fileutils
|
||||||
|
- pkg/gitutils
|
||||||
|
- pkg/homedir
|
||||||
|
- pkg/httputils
|
||||||
|
- pkg/idtools
|
||||||
|
- pkg/ioutils
|
||||||
|
- pkg/jsonlog
|
||||||
|
- pkg/jsonmessage
|
||||||
|
- pkg/longpath
|
||||||
|
- pkg/mflag
|
||||||
|
- pkg/mount
|
||||||
|
- pkg/namesgenerator
|
||||||
|
- pkg/plugins
|
||||||
|
- pkg/plugins/transport
|
||||||
|
- pkg/pools
|
||||||
|
- pkg/progress
|
||||||
|
- pkg/promise
|
||||||
|
- pkg/random
|
||||||
|
- pkg/reexec
|
||||||
|
- pkg/signal
|
||||||
|
- pkg/stdcopy
|
||||||
|
- pkg/streamformatter
|
||||||
|
- pkg/stringid
|
||||||
|
- pkg/symlink
|
||||||
|
- pkg/system
|
||||||
|
- pkg/tarsum
|
||||||
|
- pkg/term
|
||||||
|
- pkg/term/windows
|
||||||
|
- pkg/urlutil
|
||||||
|
- reference
|
||||||
|
- registry
|
||||||
|
- runconfig/opts
|
||||||
|
- name: github.com/docker/engine-api
|
||||||
|
version: 62043eb79d581a32ea849645277023c550732e52
|
||||||
|
subpackages:
|
||||||
|
- client
|
||||||
|
- client/transport
|
||||||
|
- client/transport/cancellable
|
||||||
|
- types
|
||||||
|
- types/blkiodev
|
||||||
|
- types/container
|
||||||
|
- types/events
|
||||||
|
- types/filters
|
||||||
|
- types/network
|
||||||
|
- types/reference
|
||||||
|
- types/registry
|
||||||
|
- types/strslice
|
||||||
|
- types/swarm
|
||||||
|
- types/time
|
||||||
|
- types/versions
|
||||||
|
- name: github.com/docker/go-connections
|
||||||
|
version: 988efe982fdecb46f01d53465878ff1f2ff411ce
|
||||||
|
subpackages:
|
||||||
|
- nat
|
||||||
|
- sockets
|
||||||
|
- tlsconfig
|
||||||
|
- name: github.com/docker/go-units
|
||||||
|
version: f2145db703495b2e525c59662db69a7344b00bb8
|
||||||
|
- name: github.com/docker/leadership
|
||||||
|
version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6
|
||||||
|
- name: github.com/docker/libcompose
|
||||||
|
version: d1876c1d68527a49c0aac22a0b161acc7296b740
|
||||||
|
subpackages:
|
||||||
|
- config
|
||||||
|
- docker
|
||||||
|
- docker/builder
|
||||||
|
- docker/client
|
||||||
|
- docker/network
|
||||||
|
- labels
|
||||||
|
- logger
|
||||||
|
- lookup
|
||||||
|
- project
|
||||||
|
- project/events
|
||||||
|
- project/options
|
||||||
|
- utils
|
||||||
|
- version
|
||||||
|
- yaml
|
||||||
|
- name: github.com/docker/libkv
|
||||||
|
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
|
||||||
|
subpackages:
|
||||||
|
- store
|
||||||
|
- store/boltdb
|
||||||
|
- store/consul
|
||||||
|
- store/etcd
|
||||||
|
- store/zookeeper
|
||||||
|
- name: github.com/donovanhide/eventsource
|
||||||
|
version: fd1de70867126402be23c306e1ce32828455d85b
|
||||||
|
- name: github.com/flynn/go-shlex
|
||||||
|
version: 3f9db97f856818214da2e1057f8ad84803971cff
|
||||||
|
- name: github.com/gambol99/go-marathon
|
||||||
|
version: a558128c87724cd7430060ef5aedf39f83937f55
|
||||||
|
- name: github.com/go-check/check
|
||||||
|
version: 11d3bc7aa68e238947792f30573146a3231fc0f1
|
||||||
|
- name: github.com/gogo/protobuf
|
||||||
|
version: 43ab7f0ec7b6d072e0368bd537ffefe74ed30198
|
||||||
|
subpackages:
|
||||||
|
- proto
|
||||||
|
- name: github.com/golang/glog
|
||||||
|
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
|
||||||
|
- name: github.com/google/go-querystring
|
||||||
|
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
|
||||||
|
subpackages:
|
||||||
|
- query
|
||||||
|
- name: github.com/gorilla/context
|
||||||
|
version: 14f550f51af52180c2eefed15e5fd18d63c0a64a
|
||||||
|
- name: github.com/gorilla/mux
|
||||||
|
version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf
|
||||||
|
- name: github.com/hashicorp/consul
|
||||||
|
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
|
||||||
|
subpackages:
|
||||||
|
- api
|
||||||
|
- name: github.com/hashicorp/go-cleanhttp
|
||||||
|
version: ad28ea4487f05916463e2423a55166280e8254b5
|
||||||
|
- name: github.com/hashicorp/serf
|
||||||
|
version: 598c54895cc5a7b1a24a398d635e8c0ea0959870
|
||||||
|
subpackages:
|
||||||
|
- coordinate
|
||||||
|
- name: github.com/libkermit/compose
|
||||||
|
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
|
||||||
|
subpackages:
|
||||||
|
- check
|
||||||
|
- name: github.com/libkermit/docker
|
||||||
|
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
|
||||||
|
- name: github.com/libkermit/docker-check
|
||||||
|
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
|
||||||
|
- name: github.com/mattn/go-shellwords
|
||||||
|
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
|
||||||
|
- name: github.com/mesos/mesos-go
|
||||||
|
version: 068d5470506e3780189fe607af40892814197c5e
|
||||||
|
subpackages:
|
||||||
|
- detector
|
||||||
|
- detector/zoo
|
||||||
|
- mesosproto
|
||||||
|
- mesosutil
|
||||||
|
- upid
|
||||||
|
- name: github.com/mesosphere/mesos-dns
|
||||||
|
version: b47dc4c19f215e98da687b15b4c64e70f629bea5
|
||||||
|
repo: https://github.com/containous/mesos-dns.git
|
||||||
|
vcs: git
|
||||||
|
subpackages:
|
||||||
|
- detect
|
||||||
|
- errorutil
|
||||||
|
- logging
|
||||||
|
- models
|
||||||
|
- records
|
||||||
|
- records/labels
|
||||||
|
- records/state
|
||||||
|
- util
|
||||||
|
- name: github.com/Microsoft/go-winio
|
||||||
|
version: ce2922f643c8fd76b46cadc7f404a06282678b34
|
||||||
|
- name: github.com/miekg/dns
|
||||||
|
version: 5d001d020961ae1c184f9f8152fdc73810481677
|
||||||
|
- name: github.com/mitchellh/mapstructure
|
||||||
|
version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1
|
||||||
|
- name: github.com/moul/http2curl
|
||||||
|
version: b1479103caacaa39319f75e7f57fc545287fca0d
|
||||||
|
- name: github.com/ogier/pflag
|
||||||
|
version: 45c278ab3607870051a2ea9040bb85fcb8557481
|
||||||
|
- name: github.com/opencontainers/runc
|
||||||
|
version: ba1568de399395774ad84c2ace65937814c542ed
|
||||||
|
subpackages:
|
||||||
|
- libcontainer/user
|
||||||
|
- name: github.com/parnurzeal/gorequest
|
||||||
|
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
|
||||||
|
- name: github.com/ryanuber/go-glob
|
||||||
|
version: 572520ed46dbddaed19ea3d9541bdd0494163693
|
||||||
|
- name: github.com/samuel/go-zookeeper
|
||||||
|
version: 87e1bca4477a3cc767ca71be023ced183d74e538
|
||||||
|
subpackages:
|
||||||
|
- zk
|
||||||
|
- name: github.com/satori/go.uuid
|
||||||
|
version: 879c5887cd475cd7864858769793b2ceb0d44feb
|
||||||
|
- name: github.com/Sirupsen/logrus
|
||||||
|
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
|
||||||
|
- name: github.com/spf13/pflag
|
||||||
|
version: 5644820622454e71517561946e3d94b9f9db6842
|
||||||
|
- name: github.com/stretchr/objx
|
||||||
|
version: cbeaeb16a013161a98496fad62933b1d21786672
|
||||||
|
- name: github.com/stretchr/testify
|
||||||
|
version: b8dc1cecf15bdaf1988d9e87aa7cd98d899a06d6
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- mock
|
||||||
|
- name: github.com/tv42/zbase32
|
||||||
|
version: 03389da7e0bf9844767f82690f4d68fc097a1306
|
||||||
|
- name: github.com/vbatts/tar-split
|
||||||
|
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721
|
||||||
|
subpackages:
|
||||||
|
- archive/tar
|
||||||
|
- tar/asm
|
||||||
|
- tar/storage
|
||||||
|
- name: github.com/vdemeester/docker-events
|
||||||
|
version: be74d4929ec1ad118df54349fda4b0cba60f849b
|
||||||
|
- name: github.com/vdemeester/shakers
|
||||||
|
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
||||||
|
- name: github.com/xeipuuv/gojsonpointer
|
||||||
|
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
|
||||||
|
- name: github.com/xeipuuv/gojsonreference
|
||||||
|
version: e02fc20de94c78484cd5ffb007f8af96be030a45
|
||||||
|
- name: github.com/xeipuuv/gojsonschema
|
||||||
|
version: 00f9fafb54d2244d291b86ab63d12c38bd5c3886
|
||||||
|
- name: golang.org/x/net
|
||||||
|
version: db8e4de5b2d6653f66aea53094624468caad15d2
|
||||||
|
subpackages:
|
||||||
|
- context
|
||||||
|
- proxy
|
||||||
|
- publicsuffix
|
||||||
|
- name: golang.org/x/sys
|
||||||
|
version: 9c60d1c508f5134d1ca726b4641db998f2523357
|
||||||
|
subpackages:
|
||||||
|
- unix
|
||||||
|
- windows
|
||||||
|
- name: gopkg.in/fsnotify.v1
|
||||||
|
version: 944cff21b3baf3ced9a880365682152ba577d348
|
33
integration/glide.yaml
Normal file
33
integration/glide.yaml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package: github.com/containous/traefik/integration
|
||||||
|
import:
|
||||||
|
- package: github.com/cenk/backoff
|
||||||
|
testImport:
|
||||||
|
- package: github.com/containous/staert
|
||||||
|
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
|
||||||
|
- package: github.com/docker/docker
|
||||||
|
version: 534753663161334baba06f13b8efa4cad22b5bc5
|
||||||
|
subpackages:
|
||||||
|
- pkg/namesgenerator
|
||||||
|
- package: github.com/docker/libkv
|
||||||
|
subpackages:
|
||||||
|
- store
|
||||||
|
- store/consul
|
||||||
|
- store/etcd
|
||||||
|
- package: github.com/go-check/check
|
||||||
|
- package: github.com/hashicorp/consul
|
||||||
|
subpackages:
|
||||||
|
- api
|
||||||
|
- package: github.com/libkermit/compose
|
||||||
|
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
|
||||||
|
subpackages:
|
||||||
|
- check
|
||||||
|
- package: github.com/libkermit/docker
|
||||||
|
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
|
||||||
|
- package: github.com/libkermit/docker-check
|
||||||
|
- package: github.com/mattn/go-shellwords
|
||||||
|
- package: github.com/vdemeester/shakers
|
||||||
|
- package: golang.org/x/net
|
||||||
|
subpackages:
|
||||||
|
- context
|
||||||
|
- package: github.com/spf13/pflag
|
||||||
|
version: 5644820622454e71517561946e3d94b9f9db6842
|
|
@ -1,296 +1,268 @@
|
||||||
package k8s
|
package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"time"
|
||||||
"crypto/x509"
|
|
||||||
"encoding/json"
|
"k8s.io/client-go/1.5/kubernetes"
|
||||||
"fmt"
|
"k8s.io/client-go/1.5/pkg/api"
|
||||||
"github.com/containous/traefik/log"
|
"k8s.io/client-go/1.5/pkg/api/v1"
|
||||||
"github.com/parnurzeal/gorequest"
|
"k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1"
|
||||||
"net/http"
|
"k8s.io/client-go/1.5/pkg/fields"
|
||||||
"net/url"
|
"k8s.io/client-go/1.5/pkg/labels"
|
||||||
"strings"
|
"k8s.io/client-go/1.5/pkg/runtime"
|
||||||
|
"k8s.io/client-go/1.5/pkg/watch"
|
||||||
|
"k8s.io/client-go/1.5/rest"
|
||||||
|
"k8s.io/client-go/1.5/tools/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const resyncPeriod = time.Minute * 5
|
||||||
// APIEndpoint defines the base path for kubernetes API resources.
|
|
||||||
APIEndpoint = "/api/v1"
|
|
||||||
extentionsEndpoint = "/apis/extensions/v1beta1"
|
|
||||||
defaultIngress = "/ingresses"
|
|
||||||
namespaces = "/namespaces/"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client is a client for the Kubernetes master.
|
// Client is a client for the Kubernetes master.
|
||||||
|
// WatchAll starts the watch of the Kubernetes ressources and updates the stores.
|
||||||
|
// The stores can then be accessed via the Get* functions.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error)
|
GetIngresses(namespaces Namespaces) []*v1beta1.Ingress
|
||||||
GetService(name, namespace string) (Service, error)
|
GetService(namespace, name string) (*v1.Service, bool, error)
|
||||||
GetEndpoints(name, namespace string) (Endpoints, error)
|
GetEndpoints(namespace, name string) (*v1.Endpoints, bool, error)
|
||||||
WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error)
|
WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientImpl struct {
|
type clientImpl struct {
|
||||||
endpointURL string
|
ingController *cache.Controller
|
||||||
tls *tls.Config
|
svcController *cache.Controller
|
||||||
token string
|
epController *cache.Controller
|
||||||
caCert []byte
|
|
||||||
|
ingStore cache.Store
|
||||||
|
svcStore cache.Store
|
||||||
|
epStore cache.Store
|
||||||
|
|
||||||
|
clientset *kubernetes.Clientset
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new Kubernetes client.
|
// NewInClusterClient returns a new Kubernetes client that expect to run inside the cluster
|
||||||
// The provided host is an url (scheme://hostname[:port]) of a
|
func NewInClusterClient() (Client, error) {
|
||||||
// Kubernetes master without any path.
|
config, err := rest.InClusterConfig()
|
||||||
// The provided client is an authorized http.Client used to perform requests to the Kubernetes API master.
|
|
||||||
func NewClient(baseURL string, caCert []byte, token string) (Client, error) {
|
|
||||||
validURL, err := url.Parse(baseURL)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse URL %q: %v", baseURL, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &clientImpl{
|
return &clientImpl{
|
||||||
endpointURL: strings.TrimSuffix(validURL.String(), "/"),
|
clientset: clientset,
|
||||||
token: token,
|
|
||||||
caCert: caCert,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeQueryString(baseParams map[string]string, labelSelector string) (string, error) {
|
// NewInClusterClientWithEndpoint is the same as NewInClusterClient but uses the provided endpoint URL
|
||||||
if labelSelector != "" {
|
func NewInClusterClientWithEndpoint(endpoint string) (Client, error) {
|
||||||
baseParams["labelSelector"] = labelSelector
|
config, err := rest.InClusterConfig()
|
||||||
}
|
|
||||||
queryData, err := json.Marshal(baseParams)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return string(queryData), nil
|
|
||||||
|
config.Host = endpoint
|
||||||
|
|
||||||
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &clientImpl{
|
||||||
|
clientset: clientset,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIngresses returns all ingresses in the cluster
|
// GetIngresses returns all ingresses in the cluster
|
||||||
func (c *clientImpl) GetIngresses(labelSelector string, predicate func(Ingress) bool) ([]Ingress, error) {
|
func (c *clientImpl) GetIngresses(namespaces Namespaces) []*v1beta1.Ingress {
|
||||||
getURL := c.endpointURL + extentionsEndpoint + defaultIngress
|
ingList := c.ingStore.List()
|
||||||
queryParams := map[string]string{}
|
result := make([]*v1beta1.Ingress, 0, len(ingList))
|
||||||
queryData, err := makeQueryString(queryParams, labelSelector)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Had problems constructing query string %s : %v", queryParams, err)
|
|
||||||
}
|
|
||||||
body, err := c.do(c.request(getURL, queryData))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create ingresses request: GET %q : %v", getURL, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ingressList IngressList
|
for _, obj := range ingList {
|
||||||
if err := json.Unmarshal(body, &ingressList); err != nil {
|
ingress := obj.(*v1beta1.Ingress)
|
||||||
return nil, fmt.Errorf("failed to decode list of ingress resources: %v", err)
|
if HasNamespace(ingress, namespaces) {
|
||||||
}
|
result = append(result, ingress)
|
||||||
ingresses := ingressList.Items[:0]
|
|
||||||
for _, ingress := range ingressList.Items {
|
|
||||||
if predicate(ingress) {
|
|
||||||
ingresses = append(ingresses, ingress)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ingresses, nil
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchIngresses returns all ingresses in the cluster
|
// WatchIngresses starts the watch of Kubernetes Ingresses resources and updates the corresponding store
|
||||||
func (c *clientImpl) WatchIngresses(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
|
func (c *clientImpl) WatchIngresses(labelSelector labels.Selector, stopCh <-chan struct{}) chan interface{} {
|
||||||
getURL := c.endpointURL + extentionsEndpoint + defaultIngress
|
watchCh := make(chan interface{}, 10)
|
||||||
return c.watch(getURL, labelSelector, stopCh)
|
|
||||||
|
source := NewListWatchFromClient(
|
||||||
|
c.clientset.ExtensionsClient,
|
||||||
|
"ingresses",
|
||||||
|
api.NamespaceAll,
|
||||||
|
fields.Everything(),
|
||||||
|
labelSelector)
|
||||||
|
|
||||||
|
c.ingStore, c.ingController = cache.NewInformer(
|
||||||
|
source,
|
||||||
|
&v1beta1.Ingress{},
|
||||||
|
resyncPeriod,
|
||||||
|
newResourceEventHandlerFuncs(watchCh))
|
||||||
|
go c.ingController.Run(stopCh)
|
||||||
|
|
||||||
|
return watchCh
|
||||||
|
}
|
||||||
|
|
||||||
|
func newResourceEventHandlerFuncs(events chan interface{}) cache.ResourceEventHandlerFuncs {
|
||||||
|
|
||||||
|
return cache.ResourceEventHandlerFuncs{
|
||||||
|
AddFunc: func(obj interface{}) { events <- obj },
|
||||||
|
UpdateFunc: func(old, new interface{}) { events <- new },
|
||||||
|
DeleteFunc: func(obj interface{}) { events <- obj },
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetService returns the named service from the named namespace
|
// GetService returns the named service from the named namespace
|
||||||
func (c *clientImpl) GetService(name, namespace string) (Service, error) {
|
func (c *clientImpl) GetService(namespace, name string) (*v1.Service, bool, error) {
|
||||||
getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/services/" + name
|
var service *v1.Service
|
||||||
|
item, exists, err := c.svcStore.GetByKey(namespace + "/" + name)
|
||||||
body, err := c.do(c.request(getURL, ""))
|
if item != nil {
|
||||||
if err != nil {
|
service = item.(*v1.Service)
|
||||||
return Service{}, fmt.Errorf("failed to create services request: GET %q : %v", getURL, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var service Service
|
return service, exists, err
|
||||||
if err := json.Unmarshal(body, &service); err != nil {
|
|
||||||
return Service{}, fmt.Errorf("failed to decode service resource: %v", err)
|
|
||||||
}
|
|
||||||
return service, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchServices returns all services in the cluster
|
// WatchServices starts the watch of Kubernetes Service resources and updates the corresponding store
|
||||||
func (c *clientImpl) WatchServices(stopCh <-chan bool) (chan interface{}, chan error, error) {
|
func (c *clientImpl) WatchServices(stopCh <-chan struct{}) chan interface{} {
|
||||||
getURL := c.endpointURL + APIEndpoint + "/services"
|
watchCh := make(chan interface{}, 10)
|
||||||
return c.watch(getURL, "", stopCh)
|
|
||||||
|
source := cache.NewListWatchFromClient(
|
||||||
|
c.clientset.CoreClient,
|
||||||
|
"services",
|
||||||
|
api.NamespaceAll,
|
||||||
|
fields.Everything())
|
||||||
|
|
||||||
|
c.svcStore, c.svcController = cache.NewInformer(
|
||||||
|
source,
|
||||||
|
&v1.Service{},
|
||||||
|
resyncPeriod,
|
||||||
|
newResourceEventHandlerFuncs(watchCh))
|
||||||
|
go c.svcController.Run(stopCh)
|
||||||
|
|
||||||
|
return watchCh
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEndpoints returns the named Endpoints
|
// GetEndpoints returns the named Endpoints
|
||||||
// Endpoints have the same name as the coresponding service
|
// Endpoints have the same name as the coresponding service
|
||||||
func (c *clientImpl) GetEndpoints(name, namespace string) (Endpoints, error) {
|
func (c *clientImpl) GetEndpoints(namespace, name string) (*v1.Endpoints, bool, error) {
|
||||||
getURL := c.endpointURL + APIEndpoint + namespaces + namespace + "/endpoints/" + name
|
var endpoint *v1.Endpoints
|
||||||
|
item, exists, err := c.epStore.GetByKey(namespace + "/" + name)
|
||||||
|
|
||||||
body, err := c.do(c.request(getURL, ""))
|
if item != nil {
|
||||||
if err != nil {
|
endpoint = item.(*v1.Endpoints)
|
||||||
return Endpoints{}, fmt.Errorf("failed to create endpoints request: GET %q : %v", getURL, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoints Endpoints
|
return endpoint, exists, err
|
||||||
if err := json.Unmarshal(body, &endpoints); err != nil {
|
|
||||||
return Endpoints{}, fmt.Errorf("failed to decode endpoints resources: %v", err)
|
|
||||||
}
|
|
||||||
return endpoints, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchEndpoints returns endpoints in the cluster
|
// WatchEndpoints starts the watch of Kubernetes Endpoints resources and updates the corresponding store
|
||||||
func (c *clientImpl) WatchEndpoints(stopCh <-chan bool) (chan interface{}, chan error, error) {
|
func (c *clientImpl) WatchEndpoints(stopCh <-chan struct{}) chan interface{} {
|
||||||
getURL := c.endpointURL + APIEndpoint + "/endpoints"
|
|
||||||
return c.watch(getURL, "", stopCh)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WatchAll returns events in the cluster
|
|
||||||
func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
|
|
||||||
watchCh := make(chan interface{}, 10)
|
watchCh := make(chan interface{}, 10)
|
||||||
errCh := make(chan error, 10)
|
|
||||||
|
|
||||||
stopIngresses := make(chan bool)
|
source := cache.NewListWatchFromClient(
|
||||||
chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses)
|
c.clientset.CoreClient,
|
||||||
|
"endpoints",
|
||||||
|
api.NamespaceAll,
|
||||||
|
fields.Everything())
|
||||||
|
|
||||||
|
c.epStore, c.epController = cache.NewInformer(
|
||||||
|
source,
|
||||||
|
&v1.Endpoints{},
|
||||||
|
resyncPeriod,
|
||||||
|
newResourceEventHandlerFuncs(watchCh))
|
||||||
|
go c.epController.Run(stopCh)
|
||||||
|
|
||||||
|
return watchCh
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchAll returns events in the cluster and updates the stores via informer
|
||||||
|
// Filters ingresses by labelSelector
|
||||||
|
func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, error) {
|
||||||
|
watchCh := make(chan interface{}, 100)
|
||||||
|
stopWatchCh := make(chan struct{}, 1)
|
||||||
|
|
||||||
|
kubeLabelSelector, err := labels.Parse(labelSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
|
return nil, err
|
||||||
}
|
|
||||||
stopServices := make(chan bool)
|
|
||||||
chanServices, chanServicesErr, err := c.WatchServices(stopServices)
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
|
|
||||||
}
|
|
||||||
stopEndpoints := make(chan bool)
|
|
||||||
chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints)
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chanIngresses := c.WatchIngresses(kubeLabelSelector, stopWatchCh)
|
||||||
|
chanServices := c.WatchServices(stopWatchCh)
|
||||||
|
chanEndpoints := c.WatchEndpoints(stopWatchCh)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(stopWatchCh)
|
||||||
defer close(watchCh)
|
defer close(watchCh)
|
||||||
defer close(errCh)
|
|
||||||
defer close(stopIngresses)
|
|
||||||
defer close(stopServices)
|
|
||||||
defer close(stopEndpoints)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-stopCh:
|
case <-stopCh:
|
||||||
stopIngresses <- true
|
|
||||||
stopServices <- true
|
|
||||||
stopEndpoints <- true
|
|
||||||
return
|
return
|
||||||
case err := <-chanIngressesErr:
|
|
||||||
errCh <- err
|
|
||||||
case err := <-chanServicesErr:
|
|
||||||
errCh <- err
|
|
||||||
case err := <-chanEndpointsErr:
|
|
||||||
errCh <- err
|
|
||||||
case event := <-chanIngresses:
|
case event := <-chanIngresses:
|
||||||
watchCh <- event
|
c.fireEvent(event, watchCh)
|
||||||
case event := <-chanServices:
|
case event := <-chanServices:
|
||||||
watchCh <- event
|
c.fireEvent(event, watchCh)
|
||||||
case event := <-chanEndpoints:
|
case event := <-chanEndpoints:
|
||||||
watchCh <- event
|
c.fireEvent(event, watchCh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return watchCh, errCh, nil
|
return watchCh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientImpl) do(request *gorequest.SuperAgent) ([]byte, error) {
|
// fireEvent checks if all controllers have synced before firing
|
||||||
res, body, errs := request.EndBytes()
|
// Used after startup or a reconnect
|
||||||
if errs != nil {
|
func (c *clientImpl) fireEvent(event interface{}, watchCh chan interface{}) {
|
||||||
return nil, fmt.Errorf("failed to create request: GET %q : %v", request.Url, errs)
|
if c.ingController.HasSynced() && c.svcController.HasSynced() && c.epController.HasSynced() {
|
||||||
|
watchCh <- event
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("http error %d GET %q: %q", res.StatusCode, request.Url, string(body))
|
|
||||||
}
|
|
||||||
return body, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientImpl) request(reqURL string, queryContent interface{}) *gorequest.SuperAgent {
|
// HasNamespace checks if the ingress is in one of the namespaces
|
||||||
// Make request to Kubernetes API
|
func HasNamespace(ingress *v1beta1.Ingress, namespaces Namespaces) bool {
|
||||||
parsedURL, parseErr := url.Parse(reqURL)
|
if len(namespaces) == 0 {
|
||||||
if parseErr != nil {
|
return true
|
||||||
log.Errorf("Had issues parsing url %s. Trying anyway.", reqURL)
|
|
||||||
}
|
}
|
||||||
request := gorequest.New().Get(reqURL)
|
for _, n := range namespaces {
|
||||||
request.Transport.DisableKeepAlives = true
|
if ingress.ObjectMeta.Namespace == n {
|
||||||
|
return true
|
||||||
if parsedURL.Scheme == "https" {
|
|
||||||
pool := x509.NewCertPool()
|
|
||||||
pool.AppendCertsFromPEM(c.caCert)
|
|
||||||
c.tls = &tls.Config{RootCAs: pool}
|
|
||||||
request.TLSClientConfig(c.tls)
|
|
||||||
}
|
|
||||||
if len(c.token) > 0 {
|
|
||||||
request.Header["Authorization"] = "Bearer " + c.token
|
|
||||||
}
|
|
||||||
request.Query(queryContent)
|
|
||||||
return request
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenericObject generic object
|
|
||||||
type GenericObject struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ListMeta `json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
|
|
||||||
watchCh := make(chan interface{}, 10)
|
|
||||||
errCh := make(chan error, 10)
|
|
||||||
|
|
||||||
// get version
|
|
||||||
body, err := c.do(c.request(url, ""))
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to do version request: GET %q : %v", url, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var generic GenericObject
|
|
||||||
if err := json.Unmarshal(body, &generic); err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to decode version %v", err)
|
|
||||||
}
|
|
||||||
resourceVersion := generic.ResourceVersion
|
|
||||||
queryParams := map[string]string{"watch": "", "resourceVersion": resourceVersion}
|
|
||||||
queryData, err := makeQueryString(queryParams, labelSelector)
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("Unable to construct query args")
|
|
||||||
}
|
|
||||||
request := c.request(url, queryData)
|
|
||||||
req, err := request.MakeRequest()
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err)
|
|
||||||
}
|
|
||||||
request.Client.Transport = request.Transport
|
|
||||||
|
|
||||||
res, err := request.Client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
finishCh := make(chan bool)
|
|
||||||
defer close(finishCh)
|
|
||||||
defer close(watchCh)
|
|
||||||
defer close(errCh)
|
|
||||||
go func() {
|
|
||||||
defer res.Body.Close()
|
|
||||||
for {
|
|
||||||
var eventList interface{}
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&eventList); err != nil {
|
|
||||||
if !strings.Contains(err.Error(), "net/http: request canceled") {
|
|
||||||
errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err)
|
|
||||||
}
|
|
||||||
finishCh <- true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
watchCh <- eventList
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case <-stopCh:
|
|
||||||
go func() {
|
|
||||||
request.Transport.CancelRequest(req)
|
|
||||||
}()
|
|
||||||
<-finishCh
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
return watchCh, errCh, nil
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace, field selector and label selector.
|
||||||
|
// Extends cache.NewListWatchFromClient to support labelSelector
|
||||||
|
func NewListWatchFromClient(c cache.Getter, resource string, namespace string, fieldSelector fields.Selector, labelSelector labels.Selector) *cache.ListWatch {
|
||||||
|
listFunc := func(options api.ListOptions) (runtime.Object, error) {
|
||||||
|
return c.Get().
|
||||||
|
Namespace(namespace).
|
||||||
|
Resource(resource).
|
||||||
|
VersionedParams(&options, api.ParameterCodec).
|
||||||
|
FieldsSelectorParam(fieldSelector).
|
||||||
|
LabelsSelectorParam(labelSelector).
|
||||||
|
Do().
|
||||||
|
Get()
|
||||||
|
}
|
||||||
|
watchFunc := func(options api.ListOptions) (watch.Interface, error) {
|
||||||
|
return c.Get().
|
||||||
|
Prefix("watch").
|
||||||
|
Namespace(namespace).
|
||||||
|
Resource(resource).
|
||||||
|
VersionedParams(&options, api.ParameterCodec).
|
||||||
|
FieldsSelectorParam(fieldSelector).
|
||||||
|
LabelsSelectorParam(labelSelector).
|
||||||
|
Watch()
|
||||||
|
}
|
||||||
|
return &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
package k8s
|
|
||||||
|
|
||||||
// Endpoints is a collection of endpoints that implement the actual service. Example:
|
|
||||||
// Name: "mysvc",
|
|
||||||
// Subsets: [
|
|
||||||
// {
|
|
||||||
// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}],
|
|
||||||
// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}]
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// Addresses: [{"ip": "10.10.3.3"}],
|
|
||||||
// Ports: [{"name": "a", "port": 93}, {"name": "b", "port": 76}]
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
type Endpoints struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// The set of all endpoints is the union of all subsets.
|
|
||||||
Subsets []EndpointSubset
|
|
||||||
}
|
|
||||||
|
|
||||||
// EndpointSubset is a group of addresses with a common set of ports. The
|
|
||||||
// expanded set of endpoints is the Cartesian product of Addresses x Ports.
|
|
||||||
// For example, given:
|
|
||||||
// {
|
|
||||||
// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}],
|
|
||||||
// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}]
|
|
||||||
// }
|
|
||||||
// The resulting set of endpoints can be viewed as:
|
|
||||||
// a: [ 10.10.1.1:8675, 10.10.2.2:8675 ],
|
|
||||||
// b: [ 10.10.1.1:309, 10.10.2.2:309 ]
|
|
||||||
type EndpointSubset struct {
|
|
||||||
Addresses []EndpointAddress
|
|
||||||
NotReadyAddresses []EndpointAddress
|
|
||||||
Ports []EndpointPort
|
|
||||||
}
|
|
||||||
|
|
||||||
// EndpointAddress is a tuple that describes single IP address.
|
|
||||||
type EndpointAddress struct {
|
|
||||||
// The IP of this endpoint.
|
|
||||||
// IPv6 is also accepted but not fully supported on all platforms. Also, certain
|
|
||||||
// kubernetes components, like kube-proxy, are not IPv6 ready.
|
|
||||||
// TODO: This should allow hostname or IP, see #4447.
|
|
||||||
IP string
|
|
||||||
// Optional: Hostname of this endpoint
|
|
||||||
// Meant to be used by DNS servers etc.
|
|
||||||
Hostname string `json:"hostname,omitempty"`
|
|
||||||
// Optional: The kubernetes object related to the entry point.
|
|
||||||
TargetRef *ObjectReference
|
|
||||||
}
|
|
||||||
|
|
||||||
// EndpointPort is a tuple that describes a single port.
|
|
||||||
type EndpointPort struct {
|
|
||||||
// The name of this port (corresponds to ServicePort.Name). Optional
|
|
||||||
// if only one port is defined. Must be a DNS_LABEL.
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// The port number.
|
|
||||||
Port int32
|
|
||||||
|
|
||||||
// The IP protocol for this port.
|
|
||||||
Protocol Protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectReference contains enough information to let you inspect or modify the referred object.
|
|
||||||
type ObjectReference struct {
|
|
||||||
Kind string `json:"kind,omitempty"`
|
|
||||||
Namespace string `json:"namespace,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
UID UID `json:"uid,omitempty"`
|
|
||||||
APIVersion string `json:"apiVersion,omitempty"`
|
|
||||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
|
||||||
|
|
||||||
// Optional. If referring to a piece of an object instead of an entire object, this string
|
|
||||||
// should contain information to identify the sub-object. For example, if the object
|
|
||||||
// reference is to a container within a pod, this would take on a value like:
|
|
||||||
// "spec.containers{name}" (where "name" refers to the name of the container that triggered
|
|
||||||
// the event) or if no container name is specified "spec.containers[2]" (container with
|
|
||||||
// index 2 in this pod). This syntax is chosen only to have some well-defined way of
|
|
||||||
// referencing a part of an object.
|
|
||||||
// TODO: this design is not final and this field is subject to change in the future.
|
|
||||||
FieldPath string `json:"fieldPath,omitempty"`
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
package k8s
|
|
||||||
|
|
||||||
// Ingress is a collection of rules that allow inbound connections to reach the
|
|
||||||
// endpoints defined by a backend. An Ingress can be configured to give services
|
|
||||||
// externally-reachable urls, load balance traffic, terminate SSL, offer name
|
|
||||||
// based virtual hosting etc.
|
|
||||||
type Ingress struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
// Standard object's metadata.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
|
||||||
ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// Spec is the desired state of the Ingress.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
|
||||||
Spec IngressSpec `json:"spec,omitempty"`
|
|
||||||
|
|
||||||
// Status is the current state of the Ingress.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
|
||||||
Status IngressStatus `json:"status,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressList is a collection of Ingress.
|
|
||||||
type IngressList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
// Standard object's metadata.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
|
||||||
ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// Items is the list of Ingress.
|
|
||||||
Items []Ingress `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressSpec describes the Ingress the user wishes to exist.
|
|
||||||
type IngressSpec struct {
|
|
||||||
// A default backend capable of servicing requests that don't match any
|
|
||||||
// rule. At least one of 'backend' or 'rules' must be specified. This field
|
|
||||||
// is optional to allow the loadbalancer controller or defaulting logic to
|
|
||||||
// specify a global default.
|
|
||||||
Backend *IngressBackend `json:"backend,omitempty"`
|
|
||||||
|
|
||||||
// TLS configuration. Currently the Ingress only supports a single TLS
|
|
||||||
// port, 443. If multiple members of this list specify different hosts, they
|
|
||||||
// will be multiplexed on the same port according to the hostname specified
|
|
||||||
// through the SNI TLS extension, if the ingress controller fulfilling the
|
|
||||||
// ingress supports SNI.
|
|
||||||
TLS []IngressTLS `json:"tls,omitempty"`
|
|
||||||
|
|
||||||
// A list of host rules used to configure the Ingress. If unspecified, or
|
|
||||||
// no rule matches, all traffic is sent to the default backend.
|
|
||||||
Rules []IngressRule `json:"rules,omitempty"`
|
|
||||||
// TODO: Add the ability to specify load-balancer IP through claims
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressTLS describes the transport layer security associated with an Ingress.
|
|
||||||
type IngressTLS struct {
|
|
||||||
// Hosts are a list of hosts included in the TLS certificate. The values in
|
|
||||||
// this list must match the name/s used in the tlsSecret. Defaults to the
|
|
||||||
// wildcard host setting for the loadbalancer controller fulfilling this
|
|
||||||
// Ingress, if left unspecified.
|
|
||||||
Hosts []string `json:"hosts,omitempty"`
|
|
||||||
// SecretName is the name of the secret used to terminate SSL traffic on 443.
|
|
||||||
// Field is left optional to allow SSL routing based on SNI hostname alone.
|
|
||||||
// If the SNI host in a listener conflicts with the "Host" header field used
|
|
||||||
// by an IngressRule, the SNI host is used for termination and value of the
|
|
||||||
// Host header is used for routing.
|
|
||||||
SecretName string `json:"secretName,omitempty"`
|
|
||||||
// TODO: Consider specifying different modes of termination, protocols etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressStatus describe the current state of the Ingress.
|
|
||||||
type IngressStatus struct {
|
|
||||||
// LoadBalancer contains the current status of the load-balancer.
|
|
||||||
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressRule represents the rules mapping the paths under a specified host to
|
|
||||||
// the related backend services. Incoming requests are first evaluated for a host
|
|
||||||
// match, then routed to the backend associated with the matching IngressRuleValue.
|
|
||||||
type IngressRule struct {
|
|
||||||
// Host is the fully qualified domain name of a network host, as defined
|
|
||||||
// by RFC 3986. Note the following deviations from the "host" part of the
|
|
||||||
// URI as defined in the RFC:
|
|
||||||
// 1. IPs are not allowed. Currently an IngressRuleValue can only apply to the
|
|
||||||
// IP in the Spec of the parent Ingress.
|
|
||||||
// 2. The `:` delimiter is not respected because ports are not allowed.
|
|
||||||
// Currently the port of an Ingress is implicitly :80 for http and
|
|
||||||
// :443 for https.
|
|
||||||
// Both these may change in the future.
|
|
||||||
// Incoming requests are matched against the host before the IngressRuleValue.
|
|
||||||
// If the host is unspecified, the Ingress routes all traffic based on the
|
|
||||||
// specified IngressRuleValue.
|
|
||||||
Host string `json:"host,omitempty"`
|
|
||||||
// IngressRuleValue represents a rule to route requests for this IngressRule.
|
|
||||||
// If unspecified, the rule defaults to a http catch-all. Whether that sends
|
|
||||||
// just traffic matching the host to the default backend or all traffic to the
|
|
||||||
// default backend, is left to the controller fulfilling the Ingress. Http is
|
|
||||||
// currently the only supported IngressRuleValue.
|
|
||||||
IngressRuleValue `json:",inline,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressRuleValue represents a rule to apply against incoming requests. If the
|
|
||||||
// rule is satisfied, the request is routed to the specified backend. Currently
|
|
||||||
// mixing different types of rules in a single Ingress is disallowed, so exactly
|
|
||||||
// one of the following must be set.
|
|
||||||
type IngressRuleValue struct {
|
|
||||||
//TODO:
|
|
||||||
// 1. Consider renaming this resource and the associated rules so they
|
|
||||||
// aren't tied to Ingress. They can be used to route intra-cluster traffic.
|
|
||||||
// 2. Consider adding fields for ingress-type specific global options
|
|
||||||
// usable by a loadbalancer, like http keep-alive.
|
|
||||||
|
|
||||||
HTTP *HTTPIngressRuleValue `json:"http,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPIngressRuleValue is a list of http selectors pointing to backends.
|
|
||||||
// In the example: http://<host>/<path>?<searchpart> -> backend where
|
|
||||||
// where parts of the url correspond to RFC 3986, this resource will be used
|
|
||||||
// to match against everything after the last '/' and before the first '?'
|
|
||||||
// or '#'.
|
|
||||||
type HTTPIngressRuleValue struct {
|
|
||||||
// A collection of paths that map requests to backends.
|
|
||||||
Paths []HTTPIngressPath `json:"paths"`
|
|
||||||
// TODO: Consider adding fields for ingress-type specific global
|
|
||||||
// options usable by a loadbalancer, like http keep-alive.
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching
|
|
||||||
// the path are forwarded to the backend.
|
|
||||||
type HTTPIngressPath struct {
|
|
||||||
// Path is a extended POSIX regex as defined by IEEE Std 1003.1,
|
|
||||||
// (i.e this follows the egrep/unix syntax, not the perl syntax)
|
|
||||||
// matched against the path of an incoming request. Currently it can
|
|
||||||
// contain characters disallowed from the conventional "path"
|
|
||||||
// part of a URL as defined by RFC 3986. Paths must begin with
|
|
||||||
// a '/'. If unspecified, the path defaults to a catch all sending
|
|
||||||
// traffic to the backend.
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
|
|
||||||
// Backend defines the referenced service endpoint to which the traffic
|
|
||||||
// will be forwarded to.
|
|
||||||
Backend IngressBackend `json:"backend"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressBackend describes all endpoints for a given service and port.
|
|
||||||
type IngressBackend struct {
|
|
||||||
// Specifies the name of the referenced service.
|
|
||||||
ServiceName string `json:"serviceName"`
|
|
||||||
|
|
||||||
// Specifies the port of the referenced service.
|
|
||||||
ServicePort IntOrString `json:"servicePort"`
|
|
||||||
}
|
|
32
provider/k8s/namespace.go
Normal file
32
provider/k8s/namespace.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package k8s
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Namespaces holds kubernetes namespaces
|
||||||
|
type Namespaces []string
|
||||||
|
|
||||||
|
//Set adds strings elem into the the parser
|
||||||
|
//it splits str on , and ;
|
||||||
|
func (ns *Namespaces) Set(str string) error {
|
||||||
|
fargs := func(c rune) bool {
|
||||||
|
return c == ',' || c == ';'
|
||||||
|
}
|
||||||
|
// get function
|
||||||
|
slice := strings.FieldsFunc(str, fargs)
|
||||||
|
*ns = append(*ns, slice...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get []string
|
||||||
|
func (ns *Namespaces) Get() interface{} { return Namespaces(*ns) }
|
||||||
|
|
||||||
|
//String return slice in a string
|
||||||
|
func (ns *Namespaces) String() string { return fmt.Sprintf("%v", *ns) }
|
||||||
|
|
||||||
|
//SetValue sets []string into the parser
|
||||||
|
func (ns *Namespaces) SetValue(val interface{}) {
|
||||||
|
*ns = Namespaces(val.(Namespaces))
|
||||||
|
}
|
|
@ -1,326 +0,0 @@
|
||||||
package k8s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TypeMeta describes an individual object in an API response or request
|
|
||||||
// with strings representing the type of the object and its API schema version.
|
|
||||||
// Structures that are versioned or persisted should inline TypeMeta.
|
|
||||||
type TypeMeta struct {
|
|
||||||
// Kind is a string value representing the REST resource this object represents.
|
|
||||||
// Servers may infer this from the endpoint the client submits requests to.
|
|
||||||
// Cannot be updated.
|
|
||||||
// In CamelCase.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
|
||||||
Kind string `json:"kind,omitempty"`
|
|
||||||
|
|
||||||
// APIVersion defines the versioned schema of this representation of an object.
|
|
||||||
// Servers should convert recognized schemas to the latest internal value, and
|
|
||||||
// may reject unrecognized values.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources
|
|
||||||
APIVersion string `json:"apiVersion,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
|
|
||||||
// users must create.
|
|
||||||
type ObjectMeta struct {
|
|
||||||
// Name is unique within a namespace. Name is required when creating resources, although
|
|
||||||
// some resources may allow a client to request the generation of an appropriate name
|
|
||||||
// automatically. Name is primarily intended for creation idempotence and configuration
|
|
||||||
// definition.
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
|
|
||||||
// GenerateName indicates that the name should be made unique by the server prior to persisting
|
|
||||||
// it. A non-empty value for the field indicates the name will be made unique (and the name
|
|
||||||
// returned to the client will be different than the name passed). The value of this field will
|
|
||||||
// be combined with a unique suffix on the server if the Name field has not been provided.
|
|
||||||
// The provided value must be valid within the rules for Name, and may be truncated by the length
|
|
||||||
// of the suffix required to make the value unique on the server.
|
|
||||||
//
|
|
||||||
// If this field is specified, and Name is not present, the server will NOT return a 409 if the
|
|
||||||
// generated name exists - instead, it will either return 201 Created or 500 with Reason
|
|
||||||
// ServerTimeout indicating a unique name could not be found in the time allotted, and the client
|
|
||||||
// should retry (optionally after the time indicated in the Retry-After header).
|
|
||||||
GenerateName string `json:"generateName,omitempty"`
|
|
||||||
|
|
||||||
// Namespace defines the space within which name must be unique. An empty namespace is
|
|
||||||
// equivalent to the "default" namespace, but "default" is the canonical representation.
|
|
||||||
// Not all objects are required to be scoped to a namespace - the value of this field for
|
|
||||||
// those objects will be empty.
|
|
||||||
Namespace string `json:"namespace,omitempty"`
|
|
||||||
|
|
||||||
// SelfLink is a URL representing this object.
|
|
||||||
SelfLink string `json:"selfLink,omitempty"`
|
|
||||||
|
|
||||||
// UID is the unique in time and space value for this object. It is typically generated by
|
|
||||||
// the server on successful creation of a resource and is not allowed to change on PUT
|
|
||||||
// operations.
|
|
||||||
UID UID `json:"uid,omitempty"`
|
|
||||||
|
|
||||||
// An opaque value that represents the version of this resource. May be used for optimistic
|
|
||||||
// concurrency, change detection, and the watch operation on a resource or set of resources.
|
|
||||||
// Clients must treat these values as opaque and values may only be valid for a particular
|
|
||||||
// resource or set of resources. Only servers will generate resource versions.
|
|
||||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
|
||||||
|
|
||||||
// A sequence number representing a specific generation of the desired state.
|
|
||||||
// Populated by the system. Read-only.
|
|
||||||
Generation int64 `json:"generation,omitempty"`
|
|
||||||
|
|
||||||
// CreationTimestamp is a timestamp representing the server time when this object was
|
|
||||||
// created. It is not guaranteed to be set in happens-before order across separate operations.
|
|
||||||
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
|
|
||||||
CreationTimestamp Time `json:"creationTimestamp,omitempty"`
|
|
||||||
|
|
||||||
// DeletionTimestamp is the time after which this resource will be deleted. This
|
|
||||||
// field is set by the server when a graceful deletion is requested by the user, and is not
|
|
||||||
// directly settable by a client. The resource will be deleted (no longer visible from
|
|
||||||
// resource lists, and not reachable by name) after the time in this field. Once set, this
|
|
||||||
// value may not be unset or be set further into the future, although it may be shortened
|
|
||||||
// or the resource may be deleted prior to this time. For example, a user may request that
|
|
||||||
// a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination
|
|
||||||
// signal to the containers in the pod. Once the resource is deleted in the API, the Kubelet
|
|
||||||
// will send a hard termination signal to the container.
|
|
||||||
DeletionTimestamp *Time `json:"deletionTimestamp,omitempty"`
|
|
||||||
|
|
||||||
// DeletionGracePeriodSeconds records the graceful deletion value set when graceful deletion
|
|
||||||
// was requested. Represents the most recent grace period, and may only be shortened once set.
|
|
||||||
DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"`
|
|
||||||
|
|
||||||
// Labels are key value pairs that may be used to scope and select individual resources.
|
|
||||||
// Label keys are of the form:
|
|
||||||
// label-key ::= prefixed-name | name
|
|
||||||
// prefixed-name ::= prefix '/' name
|
|
||||||
// prefix ::= DNS_SUBDOMAIN
|
|
||||||
// name ::= DNS_LABEL
|
|
||||||
// The prefix is optional. If the prefix is not specified, the key is assumed to be private
|
|
||||||
// to the user. Other system components that wish to use labels must specify a prefix. The
|
|
||||||
// "kubernetes.io/" prefix is reserved for use by kubernetes components.
|
|
||||||
// TODO: replace map[string]string with labels.LabelSet type
|
|
||||||
Labels map[string]string `json:"labels,omitempty"`
|
|
||||||
|
|
||||||
// Annotations are unstructured key value data stored with a resource that may be set by
|
|
||||||
// external tooling. They are not queryable and should be preserved when modifying
|
|
||||||
// objects. Annotation keys have the same formatting restrictions as Label keys. See the
|
|
||||||
// comments on Labels for details.
|
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UID is a type that holds unique ID values, including UUIDs. Because we
|
|
||||||
// don't ONLY use UUIDs, this is an alias to string. Being a type captures
|
|
||||||
// intent and helps make sure that UIDs and names do not get conflated.
|
|
||||||
type UID string
|
|
||||||
|
|
||||||
// Time is a wrapper around time.Time which supports correct
|
|
||||||
// marshaling to YAML and JSON. Wrappers are provided for many
|
|
||||||
// of the factory methods that the time package offers.
|
|
||||||
//
|
|
||||||
// +protobuf.options.marshal=false
|
|
||||||
// +protobuf.as=Timestamp
|
|
||||||
type Time struct {
|
|
||||||
time.Time `protobuf:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
|
||||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
|
||||||
// will answer requests sent through the proxy.
|
|
||||||
type Service struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
// Spec defines the behavior of a service.
|
|
||||||
Spec ServiceSpec `json:"spec,omitempty"`
|
|
||||||
|
|
||||||
// Status represents the current status of a service.
|
|
||||||
Status ServiceStatus `json:"status,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSpec describes the attributes that a user creates on a service
|
|
||||||
type ServiceSpec struct {
|
|
||||||
// Type determines how the service will be exposed. Valid options: ClusterIP, NodePort, LoadBalancer
|
|
||||||
Type ServiceType `json:"type,omitempty"`
|
|
||||||
|
|
||||||
// Required: The list of ports that are exposed by this service.
|
|
||||||
Ports []ServicePort `json:"ports"`
|
|
||||||
|
|
||||||
// This service will route traffic to pods having labels matching this selector. If empty or not present,
|
|
||||||
// the service is assumed to have endpoints set by an external process and Kubernetes will not modify
|
|
||||||
// those endpoints.
|
|
||||||
Selector map[string]string `json:"selector"`
|
|
||||||
|
|
||||||
// ClusterIP is usually assigned by the master. If specified by the user
|
|
||||||
// we will try to respect it or else fail the request. This field can
|
|
||||||
// not be changed by updates.
|
|
||||||
// Valid values are None, empty string (""), or a valid IP address
|
|
||||||
// None can be specified for headless services when proxying is not required
|
|
||||||
ClusterIP string `json:"clusterIP,omitempty"`
|
|
||||||
|
|
||||||
// ExternalIPs are used by external load balancers, or can be set by
|
|
||||||
// users to handle external traffic that arrives at a node.
|
|
||||||
ExternalIPs []string `json:"externalIPs,omitempty"`
|
|
||||||
|
|
||||||
// Only applies to Service Type: LoadBalancer
|
|
||||||
// LoadBalancer will get created with the IP specified in this field.
|
|
||||||
// This feature depends on whether the underlying cloud-provider supports specifying
|
|
||||||
// the loadBalancerIP when a load balancer is created.
|
|
||||||
// This field will be ignored if the cloud-provider does not support the feature.
|
|
||||||
LoadBalancerIP string `json:"loadBalancerIP,omitempty"`
|
|
||||||
|
|
||||||
// Required: Supports "ClientIP" and "None". Used to maintain session affinity.
|
|
||||||
SessionAffinity ServiceAffinity `json:"sessionAffinity,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePort service port
|
|
||||||
type ServicePort struct {
|
|
||||||
// Optional if only one ServicePort is defined on this service: The
|
|
||||||
// name of this port within the service. This must be a DNS_LABEL.
|
|
||||||
// All ports within a ServiceSpec must have unique names. This maps to
|
|
||||||
// the 'Name' field in EndpointPort objects.
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// The IP protocol for this port. Supports "TCP" and "UDP".
|
|
||||||
Protocol Protocol `json:"protocol"`
|
|
||||||
|
|
||||||
// The port that will be exposed on the service.
|
|
||||||
Port int `json:"port"`
|
|
||||||
|
|
||||||
// Optional: The target port on pods selected by this service. If this
|
|
||||||
// is a string, it will be looked up as a named port in the target
|
|
||||||
// Pod's container ports. If this is not specified, the value
|
|
||||||
// of the 'port' field is used (an identity map).
|
|
||||||
// This field is ignored for services with clusterIP=None, and should be
|
|
||||||
// omitted or set equal to the 'port' field.
|
|
||||||
TargetPort IntOrString `json:"targetPort"`
|
|
||||||
|
|
||||||
// The port on each node on which this service is exposed.
|
|
||||||
// Default is to auto-allocate a port if the ServiceType of this Service requires one.
|
|
||||||
NodePort int `json:"nodePort"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceStatus represents the current status of a service
|
|
||||||
type ServiceStatus struct {
|
|
||||||
// LoadBalancer contains the current status of the load-balancer,
|
|
||||||
// if one is present.
|
|
||||||
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadBalancerStatus represents the status of a load-balancer
|
|
||||||
type LoadBalancerStatus struct {
|
|
||||||
// Ingress is a list containing ingress points for the load-balancer;
|
|
||||||
// traffic intended for the service should be sent to these ingress points.
|
|
||||||
Ingress []LoadBalancerIngress `json:"ingress,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
|
||||||
// traffic intended for the service should be sent to an ingress point.
|
|
||||||
type LoadBalancerIngress struct {
|
|
||||||
// IP is set for load-balancer ingress points that are IP based
|
|
||||||
// (typically GCE or OpenStack load-balancers)
|
|
||||||
IP string `json:"ip,omitempty"`
|
|
||||||
|
|
||||||
// Hostname is set for load-balancer ingress points that are DNS based
|
|
||||||
// (typically AWS load-balancers)
|
|
||||||
Hostname string `json:"hostname,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceAffinity Session Affinity Type string
|
|
||||||
type ServiceAffinity string
|
|
||||||
|
|
||||||
// ServiceType Service Type string describes ingress methods for a service
|
|
||||||
type ServiceType string
|
|
||||||
|
|
||||||
// Protocol defines network protocols supported for things like container ports.
|
|
||||||
type Protocol string
|
|
||||||
|
|
||||||
// IntOrString is a type that can hold an int32 or a string. When used in
|
|
||||||
// JSON or YAML marshalling and unmarshalling, it produces or consumes the
|
|
||||||
// inner type. This allows you to have, for example, a JSON field that can
|
|
||||||
// accept a name or number.
|
|
||||||
// TODO: Rename to Int32OrString
|
|
||||||
//
|
|
||||||
// +protobuf=true
|
|
||||||
// +protobuf.options.(gogoproto.goproto_stringer)=false
|
|
||||||
type IntOrString struct {
|
|
||||||
Type Type
|
|
||||||
IntVal int32
|
|
||||||
StrVal string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromInt creates an IntOrString object with an int32 value. It is
|
|
||||||
// your responsibility not to call this method with a value greater
|
|
||||||
// than int32.
|
|
||||||
// TODO: convert to (val int32)
|
|
||||||
func FromInt(val int) IntOrString {
|
|
||||||
return IntOrString{Type: Int, IntVal: int32(val)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromString creates an IntOrString object with a string value.
|
|
||||||
func FromString(val string) IntOrString {
|
|
||||||
return IntOrString{Type: String, StrVal: val}
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string value, or the Itoa of the int value.
|
|
||||||
func (intstr *IntOrString) String() string {
|
|
||||||
if intstr.Type == String {
|
|
||||||
return intstr.StrVal
|
|
||||||
}
|
|
||||||
return strconv.Itoa(intstr.IntValue())
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntValue returns the IntVal if type Int, or if
|
|
||||||
// it is a String, will attempt a conversion to int.
|
|
||||||
func (intstr *IntOrString) IntValue() int {
|
|
||||||
if intstr.Type == String {
|
|
||||||
i, _ := strconv.Atoi(intstr.StrVal)
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
return int(intstr.IntVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
|
||||||
func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
|
|
||||||
if value[0] == '"' {
|
|
||||||
intstr.Type = String
|
|
||||||
return json.Unmarshal(value, &intstr.StrVal)
|
|
||||||
}
|
|
||||||
intstr.Type = Int
|
|
||||||
return json.Unmarshal(value, &intstr.IntVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type represents the stored type of IntOrString.
|
|
||||||
type Type int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Int int
|
|
||||||
Int Type = iota // The IntOrString holds an int.
|
|
||||||
//String string
|
|
||||||
String // The IntOrString holds a string.
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServiceList holds a list of services.
|
|
||||||
type ServiceList struct {
|
|
||||||
TypeMeta `json:",inline"`
|
|
||||||
ListMeta `json:"metadata,omitempty"`
|
|
||||||
|
|
||||||
Items []Service `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListMeta describes metadata that synthetic resources must have, including lists and
|
|
||||||
// various status objects. A resource may have only one of {ObjectMeta, ListMeta}.
|
|
||||||
type ListMeta struct {
|
|
||||||
// SelfLink is a URL representing this object.
|
|
||||||
// Populated by the system.
|
|
||||||
// Read-only.
|
|
||||||
SelfLink string `json:"selfLink,omitempty"`
|
|
||||||
|
|
||||||
// String that identifies the server's internal version of this object that
|
|
||||||
// can be used by clients to determine when objects have changed.
|
|
||||||
// Value must be treated as opaque by clients and passed unmodified back to the server.
|
|
||||||
// Populated by the system.
|
|
||||||
// Read-only.
|
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency
|
|
||||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
|
||||||
}
|
|
|
@ -1,101 +1,49 @@
|
||||||
package provider
|
package provider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/containous/traefik/log"
|
|
||||||
"github.com/containous/traefik/provider/k8s"
|
|
||||||
"github.com/containous/traefik/safe"
|
|
||||||
"github.com/containous/traefik/types"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/client-go/1.5/pkg/api/v1"
|
||||||
|
"k8s.io/client-go/1.5/pkg/util/intstr"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/log"
|
||||||
|
"github.com/containous/traefik/provider/k8s"
|
||||||
|
"github.com/containous/traefik/safe"
|
||||||
|
"github.com/containous/traefik/types"
|
||||||
|
|
||||||
"github.com/cenk/backoff"
|
"github.com/cenk/backoff"
|
||||||
"github.com/containous/traefik/job"
|
"github.com/containous/traefik/job"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
serviceAccountToken = "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
|
||||||
serviceAccountCACert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
|
||||||
defaultKubeEndpoint = "http://127.0.0.1:8080"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Namespaces holds kubernetes namespaces
|
|
||||||
type Namespaces []string
|
|
||||||
|
|
||||||
//Set adds strings elem into the the parser
|
|
||||||
//it splits str on , and ;
|
|
||||||
func (ns *Namespaces) Set(str string) error {
|
|
||||||
fargs := func(c rune) bool {
|
|
||||||
return c == ',' || c == ';'
|
|
||||||
}
|
|
||||||
// get function
|
|
||||||
slice := strings.FieldsFunc(str, fargs)
|
|
||||||
*ns = append(*ns, slice...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get []string
|
|
||||||
func (ns *Namespaces) Get() interface{} { return Namespaces(*ns) }
|
|
||||||
|
|
||||||
//String return slice in a string
|
|
||||||
func (ns *Namespaces) String() string { return fmt.Sprintf("%v", *ns) }
|
|
||||||
|
|
||||||
//SetValue sets []string into the parser
|
|
||||||
func (ns *Namespaces) SetValue(val interface{}) {
|
|
||||||
*ns = Namespaces(val.(Namespaces))
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Provider = (*Kubernetes)(nil)
|
var _ Provider = (*Kubernetes)(nil)
|
||||||
|
|
||||||
// Kubernetes holds configurations of the Kubernetes provider.
|
// Kubernetes holds configurations of the Kubernetes provider.
|
||||||
type Kubernetes struct {
|
type Kubernetes struct {
|
||||||
BaseProvider `mapstructure:",squash"`
|
BaseProvider `mapstructure:",squash"`
|
||||||
Endpoint string `description:"Kubernetes server endpoint"`
|
Endpoint string `description:"Kubernetes server endpoint"`
|
||||||
DisablePassHostHeaders bool `description:"Kubernetes disable PassHost Headers"`
|
DisablePassHostHeaders bool `description:"Kubernetes disable PassHost Headers"`
|
||||||
Namespaces Namespaces `description:"Kubernetes namespaces"`
|
Namespaces k8s.Namespaces `description:"Kubernetes namespaces"`
|
||||||
LabelSelector string `description:"Kubernetes api label selector to use"`
|
LabelSelector string `description:"Kubernetes api label selector to use"`
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Kubernetes) createClient() (k8s.Client, error) {
|
func (provider *Kubernetes) newK8sClient() (k8s.Client, error) {
|
||||||
var token string
|
if provider.Endpoint != "" {
|
||||||
tokenBytes, err := ioutil.ReadFile(serviceAccountToken)
|
log.Infof("Creating in cluster Kubernetes client with endpoint %", provider.Endpoint)
|
||||||
if err == nil {
|
return k8s.NewInClusterClientWithEndpoint(provider.Endpoint)
|
||||||
token = string(tokenBytes)
|
|
||||||
log.Debugf("Kubernetes token: %s", token)
|
|
||||||
} else {
|
|
||||||
log.Errorf("Kubernetes load token error: %s", err)
|
|
||||||
}
|
}
|
||||||
caCert, err := ioutil.ReadFile(serviceAccountCACert)
|
log.Info("Creating in cluster Kubernetes client")
|
||||||
if err == nil {
|
return k8s.NewInClusterClient()
|
||||||
log.Debugf("Kubernetes CA cert: %s", serviceAccountCACert)
|
|
||||||
} else {
|
|
||||||
log.Errorf("Kubernetes load token error: %s", err)
|
|
||||||
}
|
|
||||||
kubernetesHost := os.Getenv("KUBERNETES_SERVICE_HOST")
|
|
||||||
kubernetesPort := os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS")
|
|
||||||
// Prioritize user provided kubernetes endpoint since kube container runtime will almost always have it
|
|
||||||
if provider.Endpoint == "" && len(kubernetesPort) > 0 && len(kubernetesHost) > 0 {
|
|
||||||
log.Debugf("Using environment provided kubernetes endpoint")
|
|
||||||
provider.Endpoint = "https://" + kubernetesHost + ":" + kubernetesPort
|
|
||||||
}
|
|
||||||
if provider.Endpoint == "" {
|
|
||||||
log.Debugf("Using default kubernetes api endpoint")
|
|
||||||
provider.Endpoint = defaultKubeEndpoint
|
|
||||||
}
|
|
||||||
log.Debugf("Kubernetes endpoint: %s", provider.Endpoint)
|
|
||||||
return k8s.NewClient(provider.Endpoint, caCert, token)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the provider to provide configurations to traefik
|
// Provide allows the provider to provide configurations to traefik
|
||||||
// using the given configuration channel.
|
// using the given configuration channel.
|
||||||
func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error {
|
func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error {
|
||||||
k8sClient, err := provider.createClient()
|
k8sClient, err := provider.newK8sClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -107,7 +55,7 @@ func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage
|
||||||
stopWatch := make(chan bool, 5)
|
stopWatch := make(chan bool, 5)
|
||||||
defer close(stopWatch)
|
defer close(stopWatch)
|
||||||
log.Debugf("Using label selector: '%s'", provider.LabelSelector)
|
log.Debugf("Using label selector: '%s'", provider.LabelSelector)
|
||||||
eventsChan, errEventsChan, err := k8sClient.WatchAll(provider.LabelSelector, stopWatch)
|
eventsChan, err := k8sClient.WatchAll(provider.LabelSelector, stopWatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error watching kubernetes events: %v", err)
|
log.Errorf("Error watching kubernetes events: %v", err)
|
||||||
timer := time.NewTimer(1 * time.Second)
|
timer := time.NewTimer(1 * time.Second)
|
||||||
|
@ -123,9 +71,6 @@ func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage
|
||||||
case <-stop:
|
case <-stop:
|
||||||
stopWatch <- true
|
stopWatch <- true
|
||||||
return nil
|
return nil
|
||||||
case err, _ := <-errEventsChan:
|
|
||||||
stopWatch <- true
|
|
||||||
return err
|
|
||||||
case event := <-eventsChan:
|
case event := <-eventsChan:
|
||||||
log.Debugf("Received event from kubernetes %+v", event)
|
log.Debugf("Received event from kubernetes %+v", event)
|
||||||
templateObjects, err := provider.loadIngresses(k8sClient)
|
templateObjects, err := provider.loadIngresses(k8sClient)
|
||||||
|
@ -155,39 +100,12 @@ func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
templateObjects, err := provider.loadIngresses(k8sClient)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if reflect.DeepEqual(provider.lastConfiguration.Get(), templateObjects) {
|
|
||||||
log.Debugf("Skipping configuration from kubernetes %+v", templateObjects)
|
|
||||||
} else {
|
|
||||||
provider.lastConfiguration.Set(templateObjects)
|
|
||||||
configurationChan <- types.ConfigMessage{
|
|
||||||
ProviderName: "kubernetes",
|
|
||||||
Configuration: provider.loadConfig(*templateObjects),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configuration, error) {
|
func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configuration, error) {
|
||||||
ingresses, err := k8sClient.GetIngresses(provider.LabelSelector, func(ingress k8s.Ingress) bool {
|
ingresses := k8sClient.GetIngresses(provider.Namespaces)
|
||||||
if len(provider.Namespaces) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, n := range provider.Namespaces {
|
|
||||||
if ingress.ObjectMeta.Namespace == n {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Error retrieving ingresses: %+v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
templateObjects := types.Configuration{
|
templateObjects := types.Configuration{
|
||||||
map[string]*types.Backend{},
|
map[string]*types.Backend{},
|
||||||
map[string]*types.Frontend{},
|
map[string]*types.Frontend{},
|
||||||
|
@ -239,28 +157,28 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
|
||||||
Rule: ruleType + ":" + pa.Path,
|
Rule: ruleType + ":" + pa.Path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
service, err := k8sClient.GetService(pa.Backend.ServiceName, i.ObjectMeta.Namespace)
|
service, exists, err := k8sClient.GetService(i.ObjectMeta.Namespace, pa.Backend.ServiceName)
|
||||||
if err != nil {
|
if err != nil || !exists {
|
||||||
log.Warnf("Error retrieving services: %v", err)
|
log.Warnf("Error retrieving service %s/%s: %v", i.ObjectMeta.Namespace, pa.Backend.ServiceName, err)
|
||||||
delete(templateObjects.Frontends, r.Host+pa.Path)
|
delete(templateObjects.Frontends, r.Host+pa.Path)
|
||||||
log.Warnf("Error retrieving services %s", pa.Backend.ServiceName)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := "http"
|
protocol := "http"
|
||||||
for _, port := range service.Spec.Ports {
|
for _, port := range service.Spec.Ports {
|
||||||
if equalPorts(port, pa.Backend.ServicePort) {
|
if equalPorts(port, pa.Backend.ServicePort) {
|
||||||
if port.Port == 443 {
|
if port.Port == 443 {
|
||||||
protocol = "https"
|
protocol = "https"
|
||||||
}
|
}
|
||||||
endpoints, err := k8sClient.GetEndpoints(service.ObjectMeta.Name, service.ObjectMeta.Namespace)
|
endpoints, exists, err := k8sClient.GetEndpoints(service.ObjectMeta.Namespace, service.ObjectMeta.Name)
|
||||||
if err != nil {
|
if err != nil || !exists {
|
||||||
log.Errorf("Error retrieving endpoints: %v", err)
|
log.Errorf("Error retrieving endpoints %s/%s: %v", service.ObjectMeta.Namespace, service.ObjectMeta.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(endpoints.Subsets) == 0 {
|
if len(endpoints.Subsets) == 0 {
|
||||||
log.Warnf("Endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
|
log.Warnf("Endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
|
||||||
templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
|
templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
|
||||||
URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(port.Port),
|
URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(int(port.Port)),
|
||||||
Weight: 1,
|
Weight: 1,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,7 +205,7 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
|
||||||
return &templateObjects, nil
|
return &templateObjects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func endpointPortNumber(servicePort k8s.ServicePort, endpointPorts []k8s.EndpointPort) int {
|
func endpointPortNumber(servicePort v1.ServicePort, endpointPorts []v1.EndpointPort) int {
|
||||||
if len(endpointPorts) > 0 {
|
if len(endpointPorts) > 0 {
|
||||||
//name is optional if there is only one port
|
//name is optional if there is only one port
|
||||||
port := endpointPorts[0]
|
port := endpointPorts[0]
|
||||||
|
@ -298,11 +216,11 @@ func endpointPortNumber(servicePort k8s.ServicePort, endpointPorts []k8s.Endpoin
|
||||||
}
|
}
|
||||||
return int(port.Port)
|
return int(port.Port)
|
||||||
}
|
}
|
||||||
return servicePort.Port
|
return int(servicePort.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalPorts(servicePort k8s.ServicePort, ingressPort k8s.IntOrString) bool {
|
func equalPorts(servicePort v1.ServicePort, ingressPort intstr.IntOrString) bool {
|
||||||
if servicePort.Port == ingressPort.IntValue() {
|
if int(servicePort.Port) == ingressPort.IntValue() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if servicePort.Name != "" && servicePort.Name == ingressPort.String() {
|
if servicePort.Name != "" && servicePort.Name == ingressPort.String() {
|
||||||
|
|
|
@ -2,29 +2,34 @@ package provider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/containous/traefik/provider/k8s"
|
|
||||||
"github.com/containous/traefik/types"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/client-go/1.5/pkg/api/v1"
|
||||||
|
"k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1"
|
||||||
|
"k8s.io/client-go/1.5/pkg/util/intstr"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/provider/k8s"
|
||||||
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadIngresses(t *testing.T) {
|
func TestLoadIngresses(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{{
|
ingresses := []*v1beta1.Ingress{{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo",
|
Host: "foo",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar",
|
Path: "/bar",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -33,19 +38,19 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Host: "bar",
|
Host: "bar",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service3",
|
ServiceName: "service3",
|
||||||
ServicePort: k8s.FromString("https"),
|
ServicePort: intstr.FromString("https"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service2",
|
ServiceName: "service2",
|
||||||
ServicePort: k8s.FromInt(802),
|
ServicePort: intstr.FromInt(802),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -55,16 +60,16 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
},
|
},
|
||||||
|
@ -72,14 +77,14 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service2",
|
Name: "service2",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.2",
|
ClusterIP: "10.0.0.2",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 802,
|
Port: 802,
|
||||||
},
|
},
|
||||||
|
@ -87,14 +92,14 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service3",
|
Name: "service3",
|
||||||
UID: "3",
|
UID: "3",
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.3",
|
ClusterIP: "10.0.0.3",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 80,
|
Port: 80,
|
||||||
|
@ -107,33 +112,33 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
endpoints := []k8s.Endpoints{
|
endpoints := []*v1.Endpoints{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Subsets: []k8s.EndpointSubset{
|
Subsets: []v1.EndpointSubset{
|
||||||
{
|
{
|
||||||
Addresses: []k8s.EndpointAddress{
|
Addresses: []v1.EndpointAddress{
|
||||||
{
|
{
|
||||||
IP: "10.10.0.1",
|
IP: "10.10.0.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ports: []k8s.EndpointPort{
|
Ports: []v1.EndpointPort{
|
||||||
{
|
{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Addresses: []k8s.EndpointAddress{
|
Addresses: []v1.EndpointAddress{
|
||||||
{
|
{
|
||||||
IP: "10.21.0.1",
|
IP: "10.21.0.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ports: []k8s.EndpointPort{
|
Ports: []v1.EndpointPort{
|
||||||
{
|
{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
},
|
},
|
||||||
|
@ -142,19 +147,19 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service3",
|
Name: "service3",
|
||||||
UID: "3",
|
UID: "3",
|
||||||
Namespace: "testing",
|
Namespace: "testing",
|
||||||
},
|
},
|
||||||
Subsets: []k8s.EndpointSubset{
|
Subsets: []v1.EndpointSubset{
|
||||||
{
|
{
|
||||||
Addresses: []k8s.EndpointAddress{
|
Addresses: []v1.EndpointAddress{
|
||||||
{
|
{
|
||||||
IP: "10.15.0.1",
|
IP: "10.15.0.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ports: []k8s.EndpointPort{
|
Ports: []v1.EndpointPort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
|
@ -166,12 +171,12 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Addresses: []k8s.EndpointAddress{
|
Addresses: []v1.EndpointAddress{
|
||||||
{
|
{
|
||||||
IP: "10.15.0.2",
|
IP: "10.15.0.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ports: []k8s.EndpointPort{
|
Ports: []v1.EndpointPort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 9080,
|
Port: 9080,
|
||||||
|
@ -267,23 +272,23 @@ func TestLoadIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRuleType(t *testing.T) {
|
func TestRuleType(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{
|
ingresses := []*v1beta1.Ingress{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefixStrip"}, //camel case
|
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefixStrip"}, //camel case
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo1",
|
Host: "foo1",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar1",
|
Path: "/bar1",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -294,21 +299,21 @@ func TestRuleType(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Annotations: map[string]string{"traefik.frontend.rule.type": "path"}, //lower case
|
Annotations: map[string]string{"traefik.frontend.rule.type": "path"}, //lower case
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo1",
|
Host: "foo1",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar2",
|
Path: "/bar2",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -319,21 +324,21 @@ func TestRuleType(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefix"}, //path prefix
|
Annotations: map[string]string{"traefik.frontend.rule.type": "PathPrefix"}, //path prefix
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo2",
|
Host: "foo2",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar1",
|
Path: "/bar1",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -344,21 +349,21 @@ func TestRuleType(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Annotations: map[string]string{"traefik.frontend.rule.type": "PathStrip"}, //path strip
|
Annotations: map[string]string{"traefik.frontend.rule.type": "PathStrip"}, //path strip
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo2",
|
Host: "foo2",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar2",
|
Path: "/bar2",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -369,21 +374,21 @@ func TestRuleType(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Annotations: map[string]string{"traefik.frontend.rule.type": "PathXXStrip"}, //wrong rule
|
Annotations: map[string]string{"traefik.frontend.rule.type": "PathXXStrip"}, //wrong rule
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo1",
|
Host: "foo1",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar3",
|
Path: "/bar3",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -394,15 +399,15 @@ func TestRuleType(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -495,22 +500,22 @@ func TestRuleType(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPassHostHeader(t *testing.T) {
|
func TestGetPassHostHeader(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{{
|
ingresses := []*v1beta1.Ingress{{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo",
|
Host: "foo",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar",
|
Path: "/bar",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -520,16 +525,16 @@ func TestGetPassHostHeader(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -587,22 +592,22 @@ func TestGetPassHostHeader(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
|
func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{
|
ingresses := []*v1beta1.Ingress{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo",
|
Host: "foo",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service",
|
ServiceName: "service",
|
||||||
ServicePort: k8s.FromInt(80),
|
ServicePort: intstr.FromInt(80),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -613,16 +618,16 @@ func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service",
|
Name: "service",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 80,
|
Port: 80,
|
||||||
|
@ -631,14 +636,14 @@ func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service",
|
Name: "service",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
Namespace: "not-awesome",
|
Namespace: "not-awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.2",
|
ClusterIP: "10.0.0.2",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 80,
|
Port: 80,
|
||||||
|
@ -693,23 +698,23 @@ func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadNamespacedIngresses(t *testing.T) {
|
func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{
|
ingresses := []*v1beta1.Ingress{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo",
|
Host: "foo",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar",
|
Path: "/bar",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -718,19 +723,19 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Host: "bar",
|
Host: "bar",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service3",
|
ServiceName: "service3",
|
||||||
ServicePort: k8s.FromInt(443),
|
ServicePort: intstr.FromInt(443),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service2",
|
ServiceName: "service2",
|
||||||
ServicePort: k8s.FromInt(802),
|
ServicePort: intstr.FromInt(802),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -741,21 +746,21 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "not-awesome",
|
Namespace: "not-awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "baz",
|
Host: "baz",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/baz",
|
Path: "/baz",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -766,16 +771,16 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -784,14 +789,14 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
Namespace: "not-awesome",
|
Namespace: "not-awesome",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -800,14 +805,14 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service2",
|
Name: "service2",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.2",
|
ClusterIP: "10.0.0.2",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 802,
|
Port: 802,
|
||||||
},
|
},
|
||||||
|
@ -815,14 +820,14 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service3",
|
Name: "service3",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
UID: "3",
|
UID: "3",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.3",
|
ClusterIP: "10.0.0.3",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 443,
|
Port: 443,
|
||||||
|
@ -906,23 +911,23 @@ func TestLoadNamespacedIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{
|
ingresses := []*v1beta1.Ingress{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "foo",
|
Host: "foo",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar",
|
Path: "/bar",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -931,19 +936,19 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Host: "bar",
|
Host: "bar",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service3",
|
ServiceName: "service3",
|
||||||
ServicePort: k8s.FromInt(443),
|
ServicePort: intstr.FromInt(443),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service2",
|
ServiceName: "service2",
|
||||||
ServicePort: k8s.FromInt(802),
|
ServicePort: intstr.FromInt(802),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -954,21 +959,21 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "somewhat-awesome",
|
Namespace: "somewhat-awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "awesome",
|
Host: "awesome",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/quix",
|
Path: "/quix",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -979,21 +984,21 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "not-awesome",
|
Namespace: "not-awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
Host: "baz",
|
Host: "baz",
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/baz",
|
Path: "/baz",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1004,16 +1009,16 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -1022,14 +1027,14 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "somewhat-awesome",
|
Namespace: "somewhat-awesome",
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
UID: "17",
|
UID: "17",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.4",
|
ClusterIP: "10.0.0.4",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -1038,14 +1043,14 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
Name: "service2",
|
Name: "service2",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.2",
|
ClusterIP: "10.0.0.2",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 802,
|
Port: 802,
|
||||||
},
|
},
|
||||||
|
@ -1053,14 +1058,14 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
Name: "service3",
|
Name: "service3",
|
||||||
UID: "3",
|
UID: "3",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.3",
|
ClusterIP: "10.0.0.3",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 443,
|
Port: 443,
|
||||||
|
@ -1167,21 +1172,21 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHostlessIngress(t *testing.T) {
|
func TestHostlessIngress(t *testing.T) {
|
||||||
ingresses := []k8s.Ingress{{
|
ingresses := []*v1beta1.Ingress{{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
},
|
},
|
||||||
Spec: k8s.IngressSpec{
|
Spec: v1beta1.IngressSpec{
|
||||||
Rules: []k8s.IngressRule{
|
Rules: []v1beta1.IngressRule{
|
||||||
{
|
{
|
||||||
IngressRuleValue: k8s.IngressRuleValue{
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
HTTP: &k8s.HTTPIngressRuleValue{
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
Paths: []k8s.HTTPIngressPath{
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/bar",
|
Path: "/bar",
|
||||||
Backend: k8s.IngressBackend{
|
Backend: v1beta1.IngressBackend{
|
||||||
ServiceName: "service1",
|
ServiceName: "service1",
|
||||||
ServicePort: k8s.FromInt(801),
|
ServicePort: intstr.FromInt(801),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1191,16 +1196,16 @@ func TestHostlessIngress(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
services := []k8s.Service{
|
services := []*v1.Service{
|
||||||
{
|
{
|
||||||
ObjectMeta: k8s.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
Name: "service1",
|
Name: "service1",
|
||||||
Namespace: "awesome",
|
Namespace: "awesome",
|
||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
Spec: k8s.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
ClusterIP: "10.0.0.1",
|
ClusterIP: "10.0.0.1",
|
||||||
Ports: []k8s.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Port: 801,
|
Port: 801,
|
||||||
|
@ -1255,42 +1260,45 @@ func TestHostlessIngress(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientMock struct {
|
type clientMock struct {
|
||||||
ingresses []k8s.Ingress
|
ingresses []*v1beta1.Ingress
|
||||||
services []k8s.Service
|
services []*v1.Service
|
||||||
endpoints []k8s.Endpoints
|
endpoints []*v1.Endpoints
|
||||||
watchChan chan interface{}
|
watchChan chan interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) GetIngresses(labelString string, predicate func(k8s.Ingress) bool) ([]k8s.Ingress, error) {
|
func (c clientMock) GetIngresses(namespaces k8s.Namespaces) []*v1beta1.Ingress {
|
||||||
var ingresses []k8s.Ingress
|
result := make([]*v1beta1.Ingress, 0, len(c.ingresses))
|
||||||
|
|
||||||
for _, ingress := range c.ingresses {
|
for _, ingress := range c.ingresses {
|
||||||
if predicate(ingress) {
|
if k8s.HasNamespace(ingress, namespaces) {
|
||||||
ingresses = append(ingresses, ingress)
|
result = append(result, ingress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ingresses, nil
|
return result
|
||||||
}
|
}
|
||||||
func (c clientMock) WatchIngresses(labelString string, predicate func(k8s.Ingress) bool, stopCh <-chan bool) (chan interface{}, chan error, error) {
|
|
||||||
return c.watchChan, make(chan error), nil
|
func (c clientMock) WatchIngresses(labelSelector string, stopCh <-chan struct{}) chan interface{} {
|
||||||
|
return c.watchChan
|
||||||
}
|
}
|
||||||
func (c clientMock) GetService(name, namespace string) (k8s.Service, error) {
|
|
||||||
|
func (c clientMock) GetService(namespace, name string) (*v1.Service, bool, error) {
|
||||||
for _, service := range c.services {
|
for _, service := range c.services {
|
||||||
if service.Namespace == namespace && service.Name == name {
|
if service.Namespace == namespace && service.Name == name {
|
||||||
return service, nil
|
return service, true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return k8s.Service{}, nil
|
return &v1.Service{}, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) GetEndpoints(name, namespace string) (k8s.Endpoints, error) {
|
func (c clientMock) GetEndpoints(namespace, name string) (*v1.Endpoints, bool, error) {
|
||||||
for _, endpoints := range c.endpoints {
|
for _, endpoints := range c.endpoints {
|
||||||
if endpoints.Namespace == namespace && endpoints.Name == name {
|
if endpoints.Namespace == namespace && endpoints.Name == name {
|
||||||
return endpoints, nil
|
return endpoints, true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return k8s.Endpoints{}, nil
|
return &v1.Endpoints{}, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) WatchAll(labelString string, stopCh <-chan bool) (chan interface{}, chan error, error) {
|
func (c clientMock) WatchAll(labelString string, stopCh <-chan bool) (chan interface{}, error) {
|
||||||
return c.watchChan, make(chan error), nil
|
return c.watchChan, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"github.com/containous/traefik/cluster"
|
"github.com/containous/traefik/cluster"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/middlewares"
|
"github.com/containous/traefik/middlewares"
|
||||||
"github.com/containous/traefik/provider"
|
"github.com/containous/traefik/provider/k8s"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/containous/traefik/version"
|
"github.com/containous/traefik/version"
|
||||||
"github.com/docker/libkv/store"
|
"github.com/docker/libkv/store"
|
||||||
|
@ -144,7 +144,7 @@ Complete documentation is available at https://traefik.io`,
|
||||||
f.AddParser(reflect.TypeOf(EntryPoints{}), &EntryPoints{})
|
f.AddParser(reflect.TypeOf(EntryPoints{}), &EntryPoints{})
|
||||||
f.AddParser(reflect.TypeOf(DefaultEntryPoints{}), &DefaultEntryPoints{})
|
f.AddParser(reflect.TypeOf(DefaultEntryPoints{}), &DefaultEntryPoints{})
|
||||||
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
|
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
|
||||||
f.AddParser(reflect.TypeOf(provider.Namespaces{}), &provider.Namespaces{})
|
f.AddParser(reflect.TypeOf(k8s.Namespaces{}), &k8s.Namespaces{})
|
||||||
f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{})
|
f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{})
|
||||||
|
|
||||||
//add commands
|
//add commands
|
||||||
|
|
Loading…
Reference in a new issue