diff --git a/test/e2e/Makefile b/test/e2e/Makefile index 471c8523d5..cc4972f09b 100644 --- a/test/e2e/Makefile +++ b/test/e2e/Makefile @@ -18,6 +18,9 @@ $(MOD_PATH): fix-go-modules: $(MOD_PATH) MOD_PATH=$(MOD_PATH) ./setup_modules.sh +deps: fix-go-modules + GO111MODULE=on go get github.com/onsi/ginkgo/ginkgo@v1.8.0 + e2e.test: fix-go-modules GO111MODULE=on go test -v -c -o e2e.test diff --git a/test/e2e/README.md b/test/e2e/README.md index 178beb2d11..c40d2184f2 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -12,7 +12,7 @@ examples of how to write the tests or checkout the files already defined e.g. 1. First you need [ginkgo] which is used to orchestrate the tests: ```bash - GO111MODULE=on go get github.com/onsi/ginkgo/ginkgo@v1.8.0 + make deps ``` 2. Build the e2e test binary: diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 8c60d4153a..26ced78207 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -59,12 +59,12 @@ require ( github.com/go-openapi/validate v0.17.2 // indirect github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55 // indirect - github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e // indirect + github.com/gogo/protobuf v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 // indirect github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect github.com/google/cadvisor v0.31.0 // indirect github.com/google/go-cmp v0.2.0 // indirect - github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 // indirect + github.com/google/gofuzz v1.0.0 // indirect github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9 // indirect github.com/gophercloud/gophercloud v0.0.0-20180330165814-781450b3c4fc // indirect github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect @@ -137,7 +137,7 @@ require ( github.com/spf13/cast v0.0.0-20160730092037-e31f36ffc91a // indirect github.com/spf13/cobra v0.0.0-20160722081547-f62e98d28ab7 // indirect github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 // indirect - github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff // indirect + github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/viper v0.0.0-20160820190039-7fb2782df3d8 // indirect github.com/storageos/go-api v0.0.0-20180126153955-3a4032328d99 // indirect github.com/stretchr/objx v0.1.1 // indirect @@ -162,7 +162,7 @@ require ( gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/gcfg.v1 v1.2.0 // indirect gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect - gopkg.in/inf.v0 v0.9.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7 // indirect gopkg.in/square/go-jose.v2 v2.2.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect @@ -171,7 +171,7 @@ require ( gotest.tools v2.2.0+incompatible // indirect k8s.io/api v0.0.0-20170719033850-4d5cc6efc5e8 k8s.io/apiextensions-apiserver v0.0.0-20170616221715-abd4538a1176 // indirect - k8s.io/apimachinery v0.0.0-20170616220319-2c6e1537d30b + k8s.io/apimachinery v0.0.0-20190409092423-760d1845f48b k8s.io/apiserver v0.0.0-20170616221227-b1c85a6c288c // indirect k8s.io/cli-runtime v0.0.0-20190301175653-0c2382d2cffa // indirect k8s.io/client-go v0.0.0-20170617220358-c1b6a1c0a439 diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 5502c10b89..91882bc510 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -109,6 +109,7 @@ github.com/fatih/camelcase v0.0.0-20160318181535-f6a740d52f96 h1:5e8GDOdG6jKeeqN github.com/fatih/camelcase v0.0.0-20160318181535-f6a740d52f96/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fsnotify/fsnotify v0.0.0-20160816051541-f12c6236fe7b h1:lHoxUxMozh/yCASOoFep9dPMva62ztmxKK2VB8//Aoo= github.com/fsnotify/fsnotify v0.0.0-20160816051541-f12c6236fe7b/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvUbuvHW93esHg7F8N/OYeBBcJoTr0= @@ -143,6 +144,11 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55 h1:oIgNYSrSUbNH5DJh6DM github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e h1:ago6fNuQ6IhszPsXkeU7qRCyfsIX7L67WDybsAPkLl8= github.com/gogo/protobuf v0.0.0-20170330071051-c0656edd0d9e/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20141105023935-44145f04b68c/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= @@ -160,6 +166,10 @@ github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 h1:ScAXWS+TR6MZKex+7Z8rneuSJH+FSDqd6ocQyl+ZHo4= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9 h1:Dk8DO58y0wXeNG49dRqzf4HrZAK9lFfTgS/FNtB6NlM= @@ -204,6 +214,7 @@ github.com/jmespath/go-jmespath v0.0.0-20151117175822-3433f3ea46d9 h1:1SlajWtS+u github.com/jmespath/go-jmespath v0.0.0-20151117175822-3433f3ea46d9/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jteeuwen/go-bindata v3.0.8-0.20180305030458-6025e8de665b+incompatible h1:eX6cWzw+KSwhN430wwbdWPgqnlbnK5ux76/q5ko+Qu8= @@ -212,6 +223,7 @@ github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpR github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro= github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q= github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg= @@ -317,6 +329,10 @@ github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 h1:evyGXhH github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff h1:VARhShG49tiji6mdRNp7JTNDtJ0FhuprF93GBQ37xGU= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v0.0.0-20160820190039-7fb2782df3d8 h1:hh6dlnX5EheZdLFxYsRZt7d2z6lOnP8qVEksE/7UrhM= github.com/spf13/viper v0.0.0-20160820190039-7fb2782df3d8/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/storageos/go-api v0.0.0-20180126153955-3a4032328d99 h1:FRurKqd9bRx8aOnMBWRtfqvCYYulMAhBqLTCdH7+8Mw= @@ -353,6 +369,8 @@ golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= @@ -362,9 +380,13 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUk golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/api v0.0.0-20181129220737-af4fc4062c26 h1:RPZDMF+4oXwRE3YH8oxQXeORJvVzSLPusZrxbwgpVVg= google.golang.org/api v0.0.0-20181129220737-af4fc4062c26/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= @@ -386,6 +408,8 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNj gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7 h1:986b60BAz5vO2Vaf48yQaq+wb2bU4JsXxKu1+itW6x8= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/square/go-jose.v2 v2.2.0 h1:0kdiskBe/uJirf0T5GGmZlS8bWRYUszavQpx91WycKs= diff --git a/test/e2e/ingress.go b/test/e2e/ingress.go index de5dd006b1..b19775bcba 100644 --- a/test/e2e/ingress.go +++ b/test/e2e/ingress.go @@ -15,12 +15,16 @@ package e2e import ( "fmt" + "log" + "net/http" "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" ) @@ -97,12 +101,564 @@ var _ = framework.KubeDescribe("Ingress ALB creation", func() { // ALB ready By("Waiting for ALB to create endpoint " + addr + " and skipper route, to see that our ingress-controller and skipper works") - err = waitForResponse(addr, "https", 10*time.Minute, isSuccess, true) + err = waitForResponse(addr, "https", 10*time.Minute, isNotFound, true) Expect(err).NotTo(HaveOccurred()) // DNS ready - By("Waiting for DNS to see that mate and skipper route to service and pod works") + By("Waiting for DNS to see that external-dns and skipper route to service and pod works") err = waitForResponse(hostName, "https", 10*time.Minute, isSuccess, false) Expect(err).NotTo(HaveOccurred()) }) }) + +var __ = framework.KubeDescribe("Ingress tests simple", func() { + f := framework.NewDefaultFramework("skipper-ingress-simple") + var ( + cs kubernetes.Interface + jig *framework.IngressTestJig + ) + + It("Should create simple ingress [Ingress] [Zalando]", func() { + jig = framework.NewIngressTestJig(f.ClientSet) + cs = f.ClientSet + serviceName := "skipper-ingress-test" + ns := f.Namespace.Name + hostName := fmt.Sprintf("%s-%d.%s", serviceName, time.Now().UTC().Unix(), e2eHostedZone()) + labels := map[string]string{ + "app": serviceName, + } + port := 8080 + replicas := int32(3) + targetPort := 9090 + backendContent := "mytest" + route := fmt.Sprintf(`* -> inlineContent("%s") -> `, backendContent) + waitTime := 10 * time.Minute + + // CREATE setup + // backend deployment + By("Creating a deployment with " + serviceName + " in namespace " + ns) + depl := createSkipperBackendDeployment(serviceName, ns, route, labels, int32(targetPort), replicas) + deployment, err := cs.Apps().Deployments(ns).Create(depl) + defer func() { + By("deleting the deployment") + defer GinkgoRecover() + err2 := cs.Apps().Deployments(ns).Delete(deployment.Name, metav1.NewDeleteOptions(0)) + Expect(err2).NotTo(HaveOccurred()) + }() + Expect(err).NotTo(HaveOccurred()) + + By("Creating service " + serviceName + " in namespace " + ns) + service := createServiceTypeClusterIP(serviceName, labels, port, targetPort) + _, err = cs.Core().Services(ns).Create(service) + Expect(err).NotTo(HaveOccurred()) + + ing := createIngress(serviceName, hostName, ns, labels, port) + ingressCreate, err := cs.Extensions().Ingresses(ns).Create(ing) + Expect(err).NotTo(HaveOccurred()) + + addr, err := jig.WaitForIngressAddress(cs, ns, ingressCreate.Name, waitTime) + Expect(err).NotTo(HaveOccurred()) + + _, err = cs.Extensions().Ingresses(ns).Get(ing.Name, metav1.GetOptions{ResourceVersion: "0"}) + Expect(err).NotTo(HaveOccurred()) + + // skipper http -> https redirect + By("Waiting for skipper route to default redirect from http to https, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "http", waitTime, isRedirect, true) + Expect(err).NotTo(HaveOccurred()) + + // ALB ready + By("Waiting for ALB to create endpoint " + addr + " and skipper route, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "https", waitTime, isNotFound, true) + Expect(err).NotTo(HaveOccurred()) + + // DNS ready + By("Waiting for DNS to see that external-dns and skipper route to service and pod works") + err = waitForResponse(hostName, "https", waitTime, isSuccess, false) + Expect(err).NotTo(HaveOccurred()) + + // Test that we get content from the default ingress + By("By checking the content of the reply we see that the ingress stack works") + rt, quit := createHTTPRoundTripper() + defer func() { + quit <- struct{}{} + }() + url := "https://" + hostName + "/" + req, err := http.NewRequest("GET", url, nil) + Expect(err).NotTo(HaveOccurred()) + resp, err := rt.RoundTrip(req) + Expect(err).NotTo(HaveOccurred()) + s, err := getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content got: %s, expected: %s", s, backendContent) + } + + // Start actual ingress tests + // Test ingress Predicates with Method("GET") + path := "/" + updatedIng := updateIngress(ingressCreate.ObjectMeta.Name, + ingressCreate.ObjectMeta.Namespace, + hostName, + serviceName, + path, + ingressCreate.ObjectMeta.Labels, + map[string]string{ + "zalando.org/skipper-predicate": `Method("GET")`, + }, + port, + ) + ingressUpdate, err := cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Waiting for ingress %s/%s we wait to get a 200 with the right content for the next request", ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get status code expected status code 200: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + + // Test ingress Predicates with Method("PUT") + path = "/" + updatedIng = updateIngress(ingressCreate.ObjectMeta.Name, + ingressCreate.ObjectMeta.Namespace, + hostName, + serviceName, + path, + ingressCreate.ObjectMeta.Labels, + map[string]string{ + "zalando.org/skipper-predicate": `Method("PUT")`, + }, + port, + ) + ingressUpdate, err = cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Waiting for ingress %s/%s we wait to get a 404 for the next request", ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusNotFound) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusNotFound { + log.Fatalf("Failed to get the right the right status code 404, got: %d", resp.StatusCode) + } + + // Test ingress Filters + path = "/" + headerKey := "X-Foo" + headerVal := "f00" + updatedIng = updateIngress(ingressCreate.ObjectMeta.Name, + ingressCreate.ObjectMeta.Namespace, + hostName, + serviceName, + path, + ingressCreate.ObjectMeta.Labels, + map[string]string{ + "zalando.org/skipper-filter": fmt.Sprintf(`setResponseHeader("%s", "%s")`, headerKey, headerVal), + }, + port, + ) + ingressUpdate, err = cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Waiting for ingress %s/%s we wait to get a 200 with %s header set to %s for the next request", ingressUpdate.Namespace, ingressUpdate.Name, headerKey, headerVal)) + time.Sleep(10 * time.Second) // wait for routing change propagation + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get the right the right status code 200, got: %d", resp.StatusCode) + } + if got := resp.Header.Get(headerKey); got != headerVal { + log.Fatalf("Failed to get Header, got: %s, want: %s", got, headerVal) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + + // Test additional hostname + additionalHostname := fmt.Sprintf("foo-%d.%s", time.Now().UTC().Unix(), e2eHostedZone()) + addHostIng := addHostIngress(updatedIng, additionalHostname) + ingressUpdate, err = cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(addHostIng) + Expect(err).NotTo(HaveOccurred()) + By("Waiting for new DNS hostname to be resolvable " + additionalHostname) + err = waitForResponse(additionalHostname, "https", waitTime, isSuccess, false) + Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Testing the old hostname %s for ingress %s/%s we make sure old routes are working", hostName, ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get the right the right status code 200, got: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + By(fmt.Sprintf("Testing the new hostname %s for ingress %s/%s we make sure old routes are working", additionalHostname, ingressUpdate.Namespace, ingressUpdate.Name)) + url = "https://" + additionalHostname + "/" + req, err = http.NewRequest("GET", url, nil) + Expect(err).NotTo(HaveOccurred()) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get the right the right status code 200, got: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + + // Test changed path + newPath := "/foo" + changePathIng := changePathIngress(updatedIng, newPath) + ingressUpdate, err = cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(changePathIng) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Waiting for ingress %s/%s we wait to get a 404 for the old request, because of the path route", ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusNotFound) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusNotFound { + log.Fatalf("Failed to get the right the right status code 404, got: %d", resp.StatusCode) + } + pathURL := "https://" + hostName + newPath + pathReq, err := http.NewRequest("GET", pathURL, nil) + Expect(err).NotTo(HaveOccurred()) + By(fmt.Sprintf("Waiting for ingress %s/%s we wait to get a 200 for a new request to the path route", ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, pathReq, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get the right the right for %s status code 200, got: %d", newPath, resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content from %s after update got: %s, expected: %s", newPath, s, backendContent) + } + + }) +}) + +var ___ = framework.KubeDescribe("Ingress tests paths", func() { + f := framework.NewDefaultFramework("skipper-ingress-paths") + var ( + cs kubernetes.Interface + jig *framework.IngressTestJig + ) + + It("Should create path routes ingress [Ingress] [Zalando]", func() { + jig = framework.NewIngressTestJig(f.ClientSet) + cs = f.ClientSet + serviceName := "skipper-ingress-test-pr" + serviceName2 := "skipper-ingress-test-pr2" + ns := f.Namespace.Name + hostName := fmt.Sprintf("%s-%d.%s", serviceName, time.Now().UTC().Unix(), e2eHostedZone()) + labels := map[string]string{ + "app": serviceName, + } + labels2 := map[string]string{ + "app": serviceName2, + } + port := 8080 + replicas := int32(3) + targetPort := 9090 + backendContent := "be-foo" + backendContent2 := "be-bar" + route := fmt.Sprintf(`* -> inlineContent("%s") -> `, backendContent) + route2 := fmt.Sprintf(`* -> inlineContent("%s") -> `, backendContent2) + waitTime := 10 * time.Minute + + // CREATE setup + // backend deployment + By("Creating a deployment with " + serviceName + " in namespace " + ns) + depl := createSkipperBackendDeployment(serviceName, ns, route, labels, int32(targetPort), replicas) + deployment, err := cs.Apps().Deployments(ns).Create(depl) + defer func() { + By("deleting the deployment") + defer GinkgoRecover() + err2 := cs.Apps().Deployments(ns).Delete(deployment.Name, metav1.NewDeleteOptions(0)) + Expect(err2).NotTo(HaveOccurred()) + }() + Expect(err).NotTo(HaveOccurred()) + By("Creating a 2nd deployment with " + serviceName2 + " in namespace " + ns) + depl2 := createSkipperBackendDeployment(serviceName2, ns, route2, labels2, int32(targetPort), replicas) + deployment2, err := cs.Apps().Deployments(ns).Create(depl2) + defer func() { + By("deleting the deployment") + defer GinkgoRecover() + err2 := cs.Apps().Deployments(ns).Delete(deployment2.Name, metav1.NewDeleteOptions(0)) + Expect(err2).NotTo(HaveOccurred()) + }() + Expect(err).NotTo(HaveOccurred()) + + By("Creating service " + serviceName + " in namespace " + ns) + service := createServiceTypeClusterIP(serviceName, labels, port, targetPort) + _, err = cs.Core().Services(ns).Create(service) + Expect(err).NotTo(HaveOccurred()) + + By("Creating service " + serviceName2 + " in namespace " + ns) + service2 := createServiceTypeClusterIP(serviceName2, labels2, port, targetPort) + _, err = cs.Core().Services(ns).Create(service2) + Expect(err).NotTo(HaveOccurred()) + + By("Creating ingress " + serviceName + " in namespace " + ns + "with hostname " + hostName) + ing := createIngress(serviceName, hostName, ns, labels, port) + ingressCreate, err := cs.Extensions().Ingresses(ns).Create(ing) + Expect(err).NotTo(HaveOccurred()) + + addr, err := jig.WaitForIngressAddress(cs, ns, ingressCreate.Name, waitTime) + Expect(err).NotTo(HaveOccurred()) + + _, err = cs.Extensions().Ingresses(ns).Get(ing.Name, metav1.GetOptions{ResourceVersion: "0"}) + Expect(err).NotTo(HaveOccurred()) + + // skipper http -> https redirect + By("Waiting for skipper route to default redirect from http to https, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "http", waitTime, isRedirect, true) + Expect(err).NotTo(HaveOccurred()) + + // ALB ready + By("Waiting for ALB to create endpoint " + addr + " and skipper route, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "https", waitTime, isNotFound, true) + Expect(err).NotTo(HaveOccurred()) + + // DNS ready + By("Waiting for DNS to see that external-dns and skipper route to service and pod works") + err = waitForResponse(hostName, "https", waitTime, isSuccess, false) + Expect(err).NotTo(HaveOccurred()) + + // Test that we get content from the default ingress + By("By checking the content of the reply we see that the ingress stack works") + rt, quit := createHTTPRoundTripper() + defer func() { + quit <- struct{}{} + }() + url := "https://" + hostName + "/" + req, err := http.NewRequest("GET", url, nil) + Expect(err).NotTo(HaveOccurred()) + resp, err := rt.RoundTrip(req) + Expect(err).NotTo(HaveOccurred()) + s, err := getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content got: %s, expected: %s", s, backendContent) + } + + // Start actual ingress tests + // Test ingress with 1 path + bepath := "/foo" + updatedIng := updateIngress(ingressCreate.ObjectMeta.Name, + ingressCreate.ObjectMeta.Namespace, + hostName, + serviceName, + bepath, + ingressCreate.ObjectMeta.Labels, + ingressCreate.ObjectMeta.Annotations, + port, + ) + ingressUpdate, err := cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 404 for path /", ingressUpdate.Namespace, ingressUpdate.Name)) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusNotFound) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusNotFound { + log.Fatalf("Failed to get status code expected status code 404: %d", resp.StatusCode) + } + + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 200 for path %s", ingressUpdate.Namespace, ingressUpdate.Name, bepath)) + beurl := "https://" + hostName + bepath + bereq, err := http.NewRequest("GET", beurl, nil) + resp, err = getAndWaitResponse(rt, bereq, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get status code expected status code 200: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + + // Test ingress with 2 paths + bepath2 := "/bar" + beurl2 := "https://" + hostName + bepath2 + bereq2, err := http.NewRequest("GET", beurl2, nil) + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 404 for path %s", ingressUpdate.Namespace, ingressUpdate.Name, bepath2)) + resp, err = getAndWaitResponse(rt, bereq2, 10*time.Second, http.StatusNotFound) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusNotFound { + log.Fatalf("Failed to get status code expected status code 404: %d", resp.StatusCode) + } + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 200 for path %s", ingressUpdate.Namespace, ingressUpdate.Name, bepath2)) + updatedIng = addPathIngress(updatedIng, + bepath2, + v1beta1.IngressBackend{ + ServiceName: serviceName2, + ServicePort: intstr.FromInt(port), + }, + ) + ingressUpdate, err = cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + resp, err = getAndWaitResponse(rt, bereq2, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get status code expected status code 200: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent2 { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent2) + } + + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 200 for path %s without change from the other path", ingressUpdate.Namespace, ingressUpdate.Name, bepath)) + beurl = "https://" + hostName + bepath + bereq, err = http.NewRequest("GET", beurl, nil) + resp, err = getAndWaitResponse(rt, bereq, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get status code expected status code 200: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + }) +}) + +var ____ = framework.KubeDescribe("Ingress tests custom routes", func() { + f := framework.NewDefaultFramework("skipper-ingress-custom") + var ( + cs kubernetes.Interface + jig *framework.IngressTestJig + ) + + It("Should create custom routes ingress [Ingress] [Zalando]", func() { + jig = framework.NewIngressTestJig(f.ClientSet) + cs = f.ClientSet + serviceName := "skipper-ingress-test-custom" + ns := f.Namespace.Name + hostName := fmt.Sprintf("%s-%d.%s", serviceName, time.Now().UTC().Unix(), e2eHostedZone()) + labels := map[string]string{ + "app": serviceName, + } + port := 8080 + replicas := int32(3) + targetPort := 9090 + backendContent := "custom-foo" + route := fmt.Sprintf(`* -> inlineContent("%s") -> `, backendContent) + waitTime := 10 * time.Minute + + // CREATE setup + // backend deployment + By("Creating a deployment with " + serviceName + " in namespace " + ns) + depl := createSkipperBackendDeployment(serviceName, ns, route, labels, int32(targetPort), replicas) + deployment, err := cs.Apps().Deployments(ns).Create(depl) + defer func() { + By("deleting the deployment") + defer GinkgoRecover() + err2 := cs.Apps().Deployments(ns).Delete(deployment.Name, metav1.NewDeleteOptions(0)) + Expect(err2).NotTo(HaveOccurred()) + }() + Expect(err).NotTo(HaveOccurred()) + + By("Creating service " + serviceName + " in namespace " + ns) + service := createServiceTypeClusterIP(serviceName, labels, port, targetPort) + _, err = cs.Core().Services(ns).Create(service) + Expect(err).NotTo(HaveOccurred()) + + By("Creating ingress " + serviceName + " in namespace " + ns + "with hostname " + hostName) + ing := createIngress(serviceName, hostName, ns, labels, port) + ingressCreate, err := cs.Extensions().Ingresses(ns).Create(ing) + Expect(err).NotTo(HaveOccurred()) + + addr, err := jig.WaitForIngressAddress(cs, ns, ingressCreate.Name, waitTime) + Expect(err).NotTo(HaveOccurred()) + + _, err = cs.Extensions().Ingresses(ns).Get(ing.Name, metav1.GetOptions{ResourceVersion: "0"}) + Expect(err).NotTo(HaveOccurred()) + + // skipper http -> https redirect + By("Waiting for skipper route to default redirect from http to https, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "http", waitTime, isRedirect, true) + Expect(err).NotTo(HaveOccurred()) + + // ALB ready + By("Waiting for ALB to create endpoint " + addr + " and skipper route, to see that our ingress-controller and skipper works") + err = waitForResponse(addr, "https", waitTime, isNotFound, true) + Expect(err).NotTo(HaveOccurred()) + + // DNS ready + By("Waiting for DNS to see that external-dns and skipper route to service and pod works") + err = waitForResponse(hostName, "https", waitTime, isSuccess, false) + Expect(err).NotTo(HaveOccurred()) + + // Test that we get content from the default ingress + By("By checking the content of the reply we see that the ingress stack works") + rt, quit := createHTTPRoundTripper() + defer func() { + quit <- struct{}{} + }() + url := "https://" + hostName + "/" + req, err := http.NewRequest("GET", url, nil) + Expect(err).NotTo(HaveOccurred()) + resp, err := rt.RoundTrip(req) + Expect(err).NotTo(HaveOccurred()) + s, err := getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content got: %s, expected: %s", s, backendContent) + } + + // Start actual ingress tests + // Test ingress with 1 custom route + path := "/" + baseURL := "https://" + hostName + redirectDestinationURL := baseURL + path + redirectPath := "/redirect" + redirectURL := baseURL + redirectPath + redirectRoute := fmt.Sprintf(`redirecttoself: PathRegexp("%s") -> modPath("%s", "%s") -> redirectTo(307, "%s") -> ;`, redirectPath, redirectPath, path, redirectDestinationURL) + updatedIng := updateIngress(ingressCreate.ObjectMeta.Name, + ingressCreate.ObjectMeta.Namespace, + hostName, + serviceName, + path, + ingressCreate.ObjectMeta.Labels, + map[string]string{ + "zalando.org/skipper-routes": redirectRoute, + }, + port, + ) + ingressUpdate, err := cs.Extensions().Ingresses(ingressCreate.ObjectMeta.Namespace).Update(updatedIng) + Expect(err).NotTo(HaveOccurred()) + + By(fmt.Sprintf("Testing for ingress %s/%s we want to get a 307 for path %s", ingressUpdate.Namespace, ingressUpdate.Name, redirectPath)) + req, err = http.NewRequest("GET", redirectURL, nil) + Expect(err).NotTo(HaveOccurred()) + resp, err = getAndWaitResponse(rt, req, 10*time.Second, http.StatusTemporaryRedirect) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusTemporaryRedirect { + log.Fatalf("Failed to get status code expected status code 307: %d", resp.StatusCode) + } + + reqRedirectURL := resp.Header.Get("Location") + By(fmt.Sprintf("Testing for ingress %s/%s rediretc Location we want to get a 200 for URL %s", ingressUpdate.Namespace, ingressUpdate.Name, reqRedirectURL)) + if redirectDestinationURL != reqRedirectURL { + log.Fatalf("Failed to get the right redirect from header: %s, expected: %s", reqRedirectURL, redirectDestinationURL) + } + redirectreq, err := http.NewRequest("GET", reqRedirectURL, nil) + resp, err = getAndWaitResponse(rt, redirectreq, 10*time.Second, http.StatusOK) + Expect(err).NotTo(HaveOccurred()) + if resp.StatusCode != http.StatusOK { + log.Fatalf("Failed to get status code expected status code 200: %d", resp.StatusCode) + } + s, err = getBody(resp) + Expect(err).NotTo(HaveOccurred()) + if s != backendContent { + log.Fatalf("Failed to get the right content after update got: %s, expected: %s", s, backendContent) + } + }) +}) diff --git a/test/e2e/util.go b/test/e2e/util.go index cb444ee262..1e86a50ebd 100644 --- a/test/e2e/util.go +++ b/test/e2e/util.go @@ -1,8 +1,12 @@ package e2e import ( + "bytes" "crypto/tls" "fmt" + "io" + "log" + "net" "net/http" "net/url" "time" @@ -13,8 +17,8 @@ import ( "k8s.io/kubernetes/test/e2e/framework" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -29,10 +33,6 @@ func createIngress(name, hostname, namespace string, label map[string]string, po Labels: label, }, Spec: v1beta1.IngressSpec{ - Backend: &v1beta1.IngressBackend{ - ServiceName: name, - ServicePort: intstr.FromInt(port), - }, Rules: []v1beta1.IngressRule{ { Host: hostname, @@ -55,6 +55,84 @@ func createIngress(name, hostname, namespace string, label map[string]string, po } } +func updateIngress(name, namespace, hostname, svcName, path string, labels, annotations map[string]string, port int) *v1beta1.Ingress { + return &v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: labels, + Annotations: annotations, + }, + Spec: v1beta1.IngressSpec{ + Rules: []v1beta1.IngressRule{ + { + Host: hostname, + IngressRuleValue: v1beta1.IngressRuleValue{ + HTTP: &v1beta1.HTTPIngressRuleValue{ + Paths: []v1beta1.HTTPIngressPath{ + { + Path: path, + Backend: v1beta1.IngressBackend{ + ServiceName: svcName, + ServicePort: intstr.FromInt(port), + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func addHostIngress(ing *v1beta1.Ingress, hostnames ...string) *v1beta1.Ingress { + addRules := []v1beta1.IngressRule{} + origRules := ing.Spec.Rules + + for _, hostname := range hostnames { + for _, rule := range origRules { + r := rule + r.Host = hostname + addRules = append(addRules, r) + } + } + ing.Spec.Rules = append(origRules, addRules...) + return ing +} + +func addPathIngress(ing *v1beta1.Ingress, path string, backend v1beta1.IngressBackend) *v1beta1.Ingress { + addRules := []v1beta1.IngressRule{} + origRules := ing.Spec.Rules + + for _, rule := range origRules { + r := rule + r.Host = rule.Host + origPaths := r.IngressRuleValue.HTTP.Paths + origPaths = append(origPaths, v1beta1.HTTPIngressPath{ + Path: path, + Backend: backend, + }) + r.IngressRuleValue.HTTP.Paths = origPaths + addRules = append(addRules, r) + } + ing.Spec.Rules = addRules + return ing +} + +func changePathIngress(ing *v1beta1.Ingress, path string) *v1beta1.Ingress { + return updateIngress( + ing.ObjectMeta.Name, + ing.ObjectMeta.Namespace, + ing.Spec.Rules[0].Host, + ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName, + path, + ing.ObjectMeta.Labels, + ing.ObjectMeta.Annotations, + ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServicePort.IntValue(), + ) +} + func createNginxDeployment(nameprefix, namespace string, label map[string]string, port, replicas int32) *appsv1.Deployment { zero := int64(0) return &appsv1.Deployment{ @@ -192,6 +270,54 @@ func createNginxDeploymentWithHostNetwork(nameprefix, namespace, serviceAccount } } +func createSkipperBackendDeployment(nameprefix, namespace, route string, label map[string]string, port, replicas int32) *appsv1.Deployment { + return &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: nameprefix + string(uuid.NewUUID()), + Namespace: namespace, + Labels: label, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{MatchLabels: label}, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: label, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "skipper", + Image: "registry.opensource.zalan.do/pathfinder/skipper:v0.10.203", + Args: []string{ + "skipper", + "-inline-routes", + route, + }, + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: port, + }, + }, + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("250Mi"), + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("250Mi"), + }, + }, + }, + }, + }, + }, + }, + } +} + func createServiceAccount(namespace, serviceAccount string) *v1.ServiceAccount { trueValue := true return &v1.ServiceAccount{ @@ -318,7 +444,11 @@ func isRedirect(code int) bool { } func isSuccess(code int) bool { - return code == 200 + return code == http.StatusOK +} + +func isNotFound(code int) bool { + return code == http.StatusNotFound } func waitForResponse(hostname, scheme string, timeout time.Duration, expectedCode func(int) bool, insecure bool) error { @@ -463,3 +593,71 @@ func createVegetaDeployment(hostPath string, rate int) *appsv1.Deployment { }, } } + +func createHTTPRoundTripper() (http.RoundTripper, chan<- struct{}) { + tr := &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + TLSHandshakeTimeout: 5 * time.Second, + IdleConnTimeout: 5 * time.Second, + } + ch := make(chan struct{}) + go func(transport *http.Transport, quit <-chan struct{}) { + for { + select { + case <-time.After(3 * time.Second): + transport.CloseIdleConnections() + case <-quit: + return + } + } + }(tr, ch) + return tr, ch +} + +func getAndWaitResponse(rt http.RoundTripper, req *http.Request, timeout time.Duration, expectedStatusCode int) (resp *http.Response, err error) { + d := 1 * time.Second + if timeout < d { + d = timeout - 1 + } + timeoutCH := make(chan struct{}) + go func() { + time.Sleep(timeout) + timeoutCH <- struct{}{} + }() + + for { + resp, err = rt.RoundTrip(req) + if err == nil && resp.StatusCode == expectedStatusCode { + return + } + if err != nil { + log.Printf("Failed to do rountrip: %v", err) + } + + select { + case <-timeoutCH: + log.Printf("timeout to GET %s", req.URL) + return + case <-time.After(d): + log.Printf("retry to GET %s", req.URL) + continue + } + } +} + +func getBody(resp *http.Response) (string, error) { + defer resp.Body.Close() + if resp.StatusCode >= 400 { + return "", fmt.Errorf("response code from backend: %d", resp.StatusCode) + } + b := make([]byte, 0, 1024) + buf := bytes.NewBuffer(b) + if _, err := io.Copy(buf, resp.Body); err != nil { + return "", fmt.Errorf("failed to copy body: %v", err) + } + return buf.String(), nil +}