Merge pull request #4948 from medyagh/paralell_integration_tests4

refactor integration tests to run in parallel
pull/4958/head
Medya Ghazizadeh 2019-08-02 00:19:46 -07:00 committed by GitHub
commit f872767afe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1330 additions and 889 deletions

2
.gitignore vendored
View File

@ -42,3 +42,5 @@ deploy/iso/minikube-iso/board/coreos/minikube/rootfs-overlay/etc/VERSION
/.idea
/.vscode
test/integration/testdata/minikube-linux-amd64-latest-stable

6
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/blang/semver v3.5.0+incompatible
github.com/c4milo/gotoolkit v0.0.0-20170318115440-bcc06269efa9 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect
github.com/docker/docker v1.13.1 // indirect
@ -15,7 +16,6 @@ require (
github.com/docker/machine v0.16.1-0.20190718054102-a555e4f7a8f5
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
@ -24,9 +24,9 @@ require (
github.com/google/go-github/v25 v25.0.2
github.com/gorilla/mux v1.7.1 // indirect
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect
github.com/hashicorp/go-getter v1.3.0
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604 // indirect
github.com/hashicorp/go-retryablehttp v0.5.4
github.com/hashicorp/go-version v1.1.0 // indirect
github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect
github.com/hooklift/iso9660 v0.0.0-20170318115843-1cf07e5970d8
github.com/intel-go/cpuid v0.0.0-20181003105527-1a4a6f06a1c6 // indirect
@ -36,7 +36,6 @@ require (
github.com/machine-drivers/docker-machine-driver-vmware v0.1.1
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.5
github.com/mattn/go-runewidth v0.0.0-20161012013512-737072b4e32b // indirect
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936
github.com/moby/hyperkit v0.0.0-20171020124204-a12cd7250bcd
github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd
@ -62,7 +61,6 @@ require (
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f
golang.org/x/text v0.3.2
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.6 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
k8s.io/api v0.0.0
k8s.io/apimachinery v0.0.0

168
go.sum
View File

@ -1,5 +1,14 @@
bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690/go.mod h1:Ulb78X89vxKYgdL24HMTiXYHlyHEvruOj1ZPlqeNEZM=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8=
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/Azure/azure-sdk-for-go v21.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@ -24,23 +33,33 @@ github.com/Sirupsen/logrus v0.0.0-20170822132746-89742aefa4b2 h1:k1A7eIeUk6rnX2y
github.com/Sirupsen/logrus v0.0.0-20170822132746-89742aefa4b2/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.16.26 h1:GWkl3rkRO/JGRTWoLLIqwf7AWC4/W/1hMOUZqmX0js4=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/bazelbuild/bazel-gazelle v0.0.0-20181012220611-c728ce9f663e/go.mod h1:uHBSeeATKpVazAACZBDPL/Nk/UhQDDsJWDlqYJo8/Us=
github.com/bazelbuild/buildtools v0.0.0-20180226164855-80c7f0d45d7e/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/c4milo/gotoolkit v0.0.0-20170318115440-bcc06269efa9 h1:+ziP/wVJWuAORkjv7386TRidVKY57X0bXBZFMeFlW+U=
github.com/c4milo/gotoolkit v0.0.0-20170318115440-bcc06269efa9/go.mod h1:txokOny9wavBtq2PWuHmj1P+eFwpCsj+gQeNNANChfU=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/client9/misspell v0.0.0-20170928000206-9ce5d979ffda/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cfssl v0.0.0-20180726162950-56268a613adf/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:Yg2hDs4b13Evkpj42FU2idX2cVXVFqQSheXYKM86Qsk=
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:MgJyK38wkzZbiZSKeIeFankxxSA8gayko/nr5x5bgBA=
@ -63,6 +82,7 @@ github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a/go.mod h1:nnelYz7
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/rkt v1.30.0/go.mod h1:O634mlH6U7qk87poQifK6M2rsFNt+FyUTWNMnP1hF1U=
github.com/cpuguy83/go-md2man v1.0.4/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY=
@ -71,8 +91,6 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
github.com/cyphar/filepath-securejoin v0.0.0-20170720062807-ae69057f2299/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v0.0.0-20170829104524-6e570ed0a266/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -91,6 +109,7 @@ github.com/docker/machine v0.16.1-0.20190718054102-a555e4f7a8f5 h1:5OiV/JwT55JRK
github.com/docker/machine v0.16.1-0.20190718054102-a555e4f7a8f5/go.mod h1:I8mPNDeK1uH+JTcUU7X0ZW8KiYz0jyAgNaeSJ1rCfDI=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
@ -106,9 +125,12 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM
github.com/fatih/camelcase v0.0.0-20160318181535-f6a740d52f96/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
@ -137,25 +159,34 @@ github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6m
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/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/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
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=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v0.0.0-20160127222235-bd3c8e81be01/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/cadvisor v0.33.2-0.20190411163913-9db8c7dee20a/go.mod h1:1nql6U13uTHaLYB8rLS5x9IJc2qT6Xd/Tr1sTX6NE48=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-containerregistry v0.0.0-20190318164241-019cdfc6adf9 h1:YVdfjqpMrLPm95Jc5JBFaEeGoPfhFxr43VW/UHQ2NVo=
github.com/google/go-containerregistry v0.0.0-20190318164241-019cdfc6adf9/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v25 v25.0.2 h1:MqXE7nOlIF91NJ/PXAcvS2dC+XXCDbY7RvJzjyEPAoU=
github.com/google/go-github/v25 v25.0.2/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
@ -163,9 +194,15 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO
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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3 h1:siORttZ36U2R/WjiJuDz8znElWBiAlO9rVt+mqJt0Cc=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
@ -176,17 +213,23 @@ github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-getter v1.3.0 h1:pFMSFlI9l5NaeuzkpE3L7BYk9qQ9juTAgXW/H0cqxcU=
github.com/hashicorp/go-getter v1.3.0/go.mod h1:/O1k/AizTN0QmfEKknCYGvICeyKUDqCYA8vvWtGWDeQ=
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604 h1:VIq8E7fMiC4h3agg0ya56L0jHn7QisZZcWZXVKJb9jQ=
github.com/hashicorp/go-multierror v0.0.0-20160811015721-8c5f0ad93604/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
@ -210,8 +253,11 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/intel-go/cpuid v0.0.0-20181003105527-1a4a6f06a1c6 h1:XboatR7lasl05yel5hNXF7kQBw2oFUGdMztcgisfhNU=
github.com/intel-go/cpuid v0.0.0-20181003105527-1a4a6f06a1c6/go.mod h1:RmeVYf9XrPRbRc3XIx0gLYA8qOFvNoPOfaEZduRlEp4=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jimmidyson/go-download v0.0.0-20161028105827-7f9a90c8c95b h1:3TknJxYSK1eDe21QorC3C2Yz8jylk6vlJG9YABnFzkU=
github.com/jimmidyson/go-download v0.0.0-20161028105827-7f9a90c8c95b/go.mod h1:I3WsAhNNoG7a/d8HMlYUywJJlfOs/+/83NEUjuDp4lc=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/johanneswuerbach/nfsexports v0.0.0-20181204082207-1aa528dcb345 h1:XP1VL9iOZu4yz/rq8zj+yvB23XEY5erXRzp8JYmkWu0=
github.com/johanneswuerbach/nfsexports v0.0.0-20181204082207-1aa528dcb345/go.mod h1:+c1/kUpg2zlkoWqTOvzDs36Wpbm3Gd1nlmtXAEB0WGU=
@ -225,11 +271,16 @@ github.com/jteeuwen/go-bindata v0.0.0-20151023091102-a0ff2567cfb7/go.mod h1:JVvh
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg=
github.com/kr/pretty v0.0.0-20140812000539-f31442d60e51/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.0.0-20130911015532-6807e777504f/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/libopenstorage/openstorage v0.0.0-20170906232338-093a0c388875/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc=
github.com/libvirt/libvirt-go v3.4.0+incompatible h1:Cpyalgj1x8JIeTlL6SDYZBo7j8nY3+5XHqmi8DaunCk=
github.com/libvirt/libvirt-go v3.4.0+incompatible/go.mod h1:34zsnB4iGeOv7Byj6qotuW8Ya4v4Tr43ttjz/F0wjLE=
@ -243,24 +294,31 @@ github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDe
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.0-20161012013512-737072b4e32b h1:idzeyUe3K4aU/SIZWMykIkJJyTD7CgDkxUQEjV07fno=
github.com/mattn/go-runewidth v0.0.0-20161012013512-737072b4e32b/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-shellwords v0.0.0-20180605041737-f8471b0a71de/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mesos/mesos-go v0.0.9/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4=
github.com/mholt/caddy v0.0.0-20180213163048-2de495001514/go.mod h1:Wb1PlT4DAYSqOEd03MsqkdkXnTxA8v9pKjdpxbqM1kY=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v0.0.0-20160614162101-5d001d020961 h1:vX2vkMipgQZ8gfmAsFeZdcgmhHoB7jMo6chAtajG3AI=
github.com/miekg/dns v0.0.0-20160614162101-5d001d020961/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mindprince/gonvml v0.0.0-20171110221305-fee913ce8fb2/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY=
github.com/mistifyio/go-zfs v0.0.0-20151009155749-1b4ae6fb4e77/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8Ma8CLF2Zzgjfx95gs3/GN3vYAPpo=
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
@ -279,6 +337,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd h1:nEatQ6JnwCT9iYD5uqYUiFqq8tJGX25to8KVKXqya7k=
github.com/olekukonko/tablewriter v0.0.0-20160923125401-bdcc175572fd/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -292,12 +352,12 @@ github.com/opencontainers/image-spec v0.0.0-20170604055404-372ad780f634/go.mod h
github.com/opencontainers/runc v0.0.0-20181113202123-f000fe11ece1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v0.0.0-20170621221121-4a2974bf1ee9/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
@ -312,12 +372,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/ffjson v0.0.0-20180717144149-af8b230fcd20/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
@ -332,18 +395,41 @@ github.com/samalba/dockerclient v0.0.0-20160414174713-91d7393ff859 h1:XRl74t6xHK
github.com/samalba/dockerclient v0.0.0-20160414174713-91d7393ff859/go.mod h1:yeYR4SlaRZJct6lwNRKR+qd0CocnxxWDE7Vh5dxsn/w=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/seccomp/libseccomp-golang v0.0.0-20150813023252-1b506fc7c24e/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM=
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20151028001915-10ef21a441db h1:lrOUn8raSZS/V52c7elGaEyuogqSkEo/Qj2Auo2G1ik=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20151028001915-10ef21a441db/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sigma/go-inotify v0.0.0-20181102212354-c87b6cf5033d/go.mod h1:stlh9OsqBQSdwxTxX73mu41BBtRbIpZLQ7flcAoxAfo=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spf13/afero v0.0.0-20160816080757-b28a7effac97/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
@ -351,7 +437,6 @@ github.com/spf13/cast v0.0.0-20160730092037-e31f36ffc91a/go.mod h1:r2rcYCSwa1IEx
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20180319062004-c439c4fa0937/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.4 h1:S0tLZ3VOKl2Te0hpq8+ke0eSJPfCnNTPiDlsfwi1/NE=
github.com/spf13/cobra v0.0.4/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
@ -366,17 +451,16 @@ github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
@ -394,50 +478,62 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097 h1:Ucx5I1l1+TWXvqFmBigYu4Ub4MLvUuUU/whjoUvV95I=
github.com/zchee/go-vmnet v0.0.0-20161021174912-97ebf9174097/go.mod h1:lFZSWRIpCfE/pt91hHBBpV6+x87YlCjsp+aIR2qCPPU=
go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181004145325-8469e314837c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -445,33 +541,54 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-20170824195420-5d2fd3ccab98/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=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 h1:mBVYJnbrXLA/ZCBTCe7PtEgAUP+1bg92qTaFoPHdz+8=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.6 h1:YQye4a1JysUfXYB6VihDfxb4lxOAei0xS44yN+srOew=
gopkg.in/cheggaaa/pb.v1 v1.0.6/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo=
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
@ -479,19 +596,22 @@ 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/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM=
k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
@ -541,4 +661,6 @@ sigs.k8s.io/sig-storage-lib-external-provisioner v4.0.0+incompatible/go.mod h1:q
sigs.k8s.io/structured-merge-diff v0.0.0-20190302045857-e85c7b244fd2/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=

View File

@ -23,7 +23,7 @@
# EXTRA_START_ARGS: additional flags to pass into minikube start
# EXTRA_ARGS: additional flags to pass into minikube
# JOB_NAME: the name of the logfile and check name to update on github
#
# PARALLEL_COUNT: number of tests to run in parallel
readonly TEST_ROOT="${HOME}/minikube-integration"
@ -75,6 +75,7 @@ gsutil -qm cp \
gsutil -qm cp "gs://minikube-builds/${MINIKUBE_LOCATION}/testdata"/* testdata/
# Set the executable bit on the e2e binary and out binary
export MINIKUBE_BIN="out/minikube-${OS_ARCH}"
export E2E_BIN="out/e2e-${OS_ARCH}"
@ -82,7 +83,7 @@ chmod +x "${MINIKUBE_BIN}" "${E2E_BIN}" out/docker-machine-driver-*
procs=$(pgrep "minikube-${OS_ARCH}|e2e-${OS_ARCH}" || true)
if [[ "${procs}" != "" ]]; then
echo "ERROR: found stale test processes to kill:"
echo "Warning: found stale test processes to kill:"
ps -f -p ${procs} || true
kill ${procs} || true
kill -9 ${procs} || true
@ -130,8 +131,13 @@ if type -P virsh; then
| awk '{ print $2 }' \
| xargs -I {} sh -c "virsh -c qemu:///system destroy {}; virsh -c qemu:///system undefine {}" \
|| true
# list again after clean up
virsh -c qemu:///system list --all
virsh -c qemu:///system list --all \
| grep Test \
| awk '{ print $2 }' \
| xargs -I {} sh -c "virsh -c qemu:///system destroy {}; virsh -c qemu:///system undefine {}" \
|| true
echo ">> Virsh VM list after clean up (should be empty) :"
virsh -c qemu:///system list --all || true
fi
if type -P vboxmanage; then
@ -141,6 +147,11 @@ if type -P vboxmanage; then
| cut -d'"' -f2 \
| xargs -I {} sh -c "vboxmanage startvm {} --type emergencystop; vboxmanage unregistervm {} --delete" \
|| true
vboxmanage list vms \
| grep Test \
| cut -d'"' -f2 \
| xargs -I {} sh -c "vboxmanage startvm {} --type emergencystop; vboxmanage unregistervm {} --delete" \
|| true
# remove inaccessible stale VMs https://github.com/kubernetes/minikube/issues/4872
vboxmanage list vms \
@ -148,6 +159,7 @@ if type -P vboxmanage; then
| cut -d'"' -f3 \
| xargs -I {} sh -c "vboxmanage startvm {} --type emergencystop; vboxmanage unregistervm {} --delete" \
|| true
# list them again after clean up
vboxmanage list vms || true
fi
@ -238,7 +250,7 @@ echo ">> Starting ${E2E_BIN} at $(date)"
${SUDO_PREFIX}${E2E_BIN} \
-minikube-start-args="--vm-driver=${VM_DRIVER} ${EXTRA_START_ARGS}" \
-minikube-args="--v=10 --logtostderr ${EXTRA_ARGS}" \
-test.v -test.timeout=100m -binary="${MINIKUBE_BIN}" && result=$? || result=$?
-test.v -test.timeout=100m -test.parallel=${PARALLEL_COUNT} -binary="${MINIKUBE_BIN}" && result=$? || result=$?
echo ">> ${E2E_BIN} exited with ${result} at $(date)"
echo ""

View File

@ -28,6 +28,7 @@ set -e
OS_ARCH="linux-amd64"
VM_DRIVER="kvm2"
JOB_NAME="Linux-KVM"
PARALLEL_COUNT=4
# Download files and set permissions
source ./common.sh

View File

@ -30,6 +30,7 @@ OS_ARCH="linux-amd64"
VM_DRIVER="none"
JOB_NAME="Linux-None"
EXTRA_ARGS="--bootstrapper=kubeadm"
PARALLEL_COUNT=1
SUDO_PREFIX="sudo -E "
export KUBECONFIG="/root/.kube/config"

View File

@ -28,6 +28,7 @@ set -e
OS_ARCH="linux-amd64"
VM_DRIVER="virtualbox"
JOB_NAME="Linux-VirtualBox"
PARALLEL_COUNT=4
# Download files and set permissions
source ./common.sh

View File

@ -31,7 +31,7 @@ VM_DRIVER="hyperkit"
JOB_NAME="OSX-Hyperkit"
EXTRA_ARGS="--bootstrapper=kubeadm"
EXTRA_START_ARGS=""
PARALLEL_COUNT=3
# Download files and set permissions
source common.sh

View File

@ -29,6 +29,7 @@ OS_ARCH="darwin-amd64"
VM_DRIVER="virtualbox"
JOB_NAME="OSX-Virtualbox"
EXTRA_ARGS="--bootstrapper=kubeadm"
PARALLEL_COUNT=3
# Download files and set permissions
source common.sh

View File

@ -71,9 +71,14 @@ func (s *PodStore) Stop() {
}
// GetClient gets the client from config
func GetClient() (kubernetes.Interface, error) {
func GetClient(kubectlContext ...string) (kubernetes.Interface, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
configOverrides := &clientcmd.ConfigOverrides{}
if kubectlContext != nil {
configOverrides = &clientcmd.ConfigOverrides{
CurrentContext: kubectlContext[0],
}
}
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
config, err := kubeConfig.ClientConfig()
if err != nil {

View File

@ -0,0 +1,90 @@
// +build integration
/*
Copyright 2019 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// a_download_only_test.go filename starts with a, for the purpose that it runs before all parallel tests and downloads the images and caches them.
package integration
import (
"fmt"
"os"
"path/filepath"
"runtime"
"testing"
"time"
"github.com/hashicorp/go-getter"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/constants"
pkgutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/test/integration/util"
)
// Note this test runs before all because filename is alphabetically first
// is used to cache images and binaries used by other parallel tests to avoid redownloading.
// TestDownloadOnly tests the --download-only option
func TestDownloadOnly(t *testing.T) {
p := profileName(t)
mk := NewMinikubeRunner(t, p)
if !isTestNoneDriver(t) { // none driver doesnt need to be deleted
defer mk.TearDown(t)
}
t.Run("Oldest", func(t *testing.T) {
stdout, stderr, err := mk.Start("--download-only", fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion))
if err != nil {
t.Errorf("%s minikube --download-only failed : %v\nstdout: %s\nstderr: %s", p, err, stdout, stderr)
}
})
t.Run("Newest", func(t *testing.T) {
stdout, stderr, err := mk.Start("--download-only", fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion))
if err != nil {
t.Errorf("%s minikube --download-only failed : %v\nstdout: %s\nstderr: %s", p, err, stdout, stderr)
}
// TODO: add test to check if files are downloaded
})
t.Run("DownloadLatestRelease", func(t *testing.T) {
dest := filepath.Join(*testdataDir, fmt.Sprintf("minikube-%s-%s-latest-stable", runtime.GOOS, runtime.GOARCH))
err := downloadMinikubeBinary(t, dest, "latest")
if err != nil {
t.Errorf("erorr downloading the latest minikube release %v", err)
}
})
}
// downloadMinikubeBinary downloads the minikube binary from github used by TestVersionUpgrade
// acts as a test setup for TestVersionUpgrade
func downloadMinikubeBinary(t *testing.T, dest string, version string) error {
t.Helper()
// Grab latest release binary
url := pkgutil.GetBinaryDownloadURL(version, runtime.GOOS)
download := func() error {
return getter.GetFile(dest, url)
}
if err := util.RetryX(download, 13*time.Second, 5*time.Minute); err != nil {
return errors.Wrap(err, "Failed to get latest release binary")
}
if runtime.GOOS != "windows" {
if err := os.Chmod(dest, 0700); err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,133 @@
// +build integration
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package integration
import (
"path/filepath"
"testing"
"github.com/docker/machine/libmachine/state"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/labels"
commonutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/test/integration/util"
)
func TestContainerd(t *testing.T) {
if isTestNoneDriver(t) {
t.Skip("Can't run containerd backend with none driver")
}
if shouldRunInParallel(t) {
t.Parallel()
}
t.Run("GvisorRestart", testGvisorRestart)
}
func testGvisorRestart(t *testing.T) {
p := profileName(t)
if shouldRunInParallel(t) {
t.Parallel()
}
mk := NewMinikubeRunner(t, p, "--wait=false")
defer mk.TearDown(t)
stdout, stderr, err := mk.Start("--container-runtime=containerd", "--docker-opt containerd=/var/run/containerd/containerd.sock")
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", p, err, stdout, stderr)
}
mk.RunCommand("addons enable gvisor", true)
t.Log("waiting for gvisor controller to come up")
if err := waitForGvisorControllerRunning(p); err != nil {
t.Errorf("waiting for gvisor controller to be up: %v", err)
}
createUntrustedWorkload(t, p)
t.Log("making sure untrusted workload is Running")
if err := waitForUntrustedNginxRunning(p); err != nil {
t.Errorf("waiting for nginx to be up: %v", err)
}
deleteUntrustedWorkload(t, p)
mk.RunCommand("delete", true)
stdout, stderr, err = mk.Start()
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) failed : %v \nstdout: %s \nstderr: %s", t.Name(), err, stdout, stderr)
}
mk.CheckStatus(state.Running.String())
t.Log("waiting for gvisor controller to come up")
if err := waitForGvisorControllerRunning(p); err != nil {
t.Errorf("waiting for gvisor controller to be up: %v", err)
}
createUntrustedWorkload(t, p)
t.Log("making sure untrusted workload is Running")
if err := waitForUntrustedNginxRunning(p); err != nil {
t.Errorf("waiting for nginx to be up: %v", err)
}
deleteUntrustedWorkload(t, p)
}
func createUntrustedWorkload(t *testing.T, profile string) {
kr := util.NewKubectlRunner(t, profile)
untrustedPath := filepath.Join(*testdataDir, "nginx-untrusted.yaml")
t.Log("creating pod with untrusted workload annotation")
if _, err := kr.RunCommand([]string{"replace", "-f", untrustedPath, "--force"}); err != nil {
t.Fatalf("creating untrusted nginx resource: %v", err)
}
}
func deleteUntrustedWorkload(t *testing.T, profile string) {
kr := util.NewKubectlRunner(t, profile)
untrustedPath := filepath.Join(*testdataDir, "nginx-untrusted.yaml")
if _, err := kr.RunCommand([]string{"delete", "-f", untrustedPath}); err != nil {
t.Logf("error deleting untrusted nginx resource: %v", err)
}
}
// waitForGvisorControllerRunning waits for the gvisor controller pod to be running
func waitForGvisorControllerRunning(p string) error {
client, err := commonutil.GetClient(p)
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"kubernetes.io/minikube-addons": "gvisor"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
return errors.Wrap(err, "waiting for gvisor controller pod to stabilize")
}
return nil
}
// waitForUntrustedNginxRunning waits for the untrusted nginx pod to start running
func waitForUntrustedNginxRunning(miniProfile string) error {
client, err := commonutil.GetClient(miniProfile)
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
return errors.Wrap(err, "waiting for nginx pods")
}
return nil
}

View File

@ -20,34 +20,38 @@ package integration
import (
"context"
"fmt"
"strings"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
)
func TestDocker(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
if usingNoneDriver(mk) {
if isTestNoneDriver(t) {
t.Skip("skipping test as none driver does not bundle docker")
}
p := profileName(t)
if shouldRunInParallel(t) {
t.Parallel()
}
mk := NewMinikubeRunner(t, p, "--wait=false")
defer mk.TearDown(t)
// Start a timer for all remaining commands, to display failure output before a panic.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
defer cancel()
if _, _, err := mk.RunWithContext(ctx, "delete"); err != nil {
t.Logf("pre-delete failed (probably ok): %v", err)
}
startCmd := fmt.Sprintf("start %s %s %s", mk.StartArgs, mk.GlobalArgs,
"--docker-env=FOO=BAR --docker-env=BAZ=BAT --docker-opt=debug --docker-opt=icc=true")
stdout, stderr, err := mk.RunWithContext(ctx, startCmd)
stdout, stderr, err := mk.Start("--docker-env=FOO=BAR", "--docker-env=BAZ=BAT", "--docker-opt=debug", " --docker-opt=icc=true")
if err != nil {
t.Fatalf("start: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
t.Fatalf("TestDocker minikube start failed : %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
}
mk.EnsureRunning()
mk.CheckStatus(state.Running.String())
stdout, stderr, err = mk.RunWithContext(ctx, "ssh -- systemctl show docker --property=Environment --no-pager")
if err != nil {

View File

@ -21,6 +21,7 @@ import (
"os"
"strings"
"testing"
"time"
"k8s.io/minikube/test/integration/util"
)
@ -31,19 +32,56 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
var startTimeout = flag.Int("timeout", 25, "number of minutes to wait for minikube start")
var binaryPath = flag.String("binary", "../../out/minikube", "path to minikube binary")
var globalArgs = flag.String("minikube-args", "", "Arguments to pass to minikube")
var startArgs = flag.String("minikube-start-args", "", "Arguments to pass to minikube start")
var mountArgs = flag.String("minikube-mount-args", "", "Arguments to pass to minikube mount")
var testdataDir = flag.String("testdata-dir", "testdata", "the directory relative to test/integration where the testdata lives")
var parallel = flag.Bool("parallel", true, "run the tests in parallel, set false for run sequentially")
// NewMinikubeRunner creates a new MinikubeRunner
func NewMinikubeRunner(t *testing.T, extraArgs ...string) util.MinikubeRunner {
func NewMinikubeRunner(t *testing.T, profile string, extraStartArgs ...string) util.MinikubeRunner {
return util.MinikubeRunner{
BinaryPath: *binaryPath,
StartArgs: *startArgs + " " + strings.Join(extraArgs, " "),
GlobalArgs: *globalArgs,
MountArgs: *mountArgs,
T: t,
Profile: profile,
BinaryPath: *binaryPath,
StartArgs: *startArgs + " " + strings.Join(extraStartArgs, " "),
GlobalArgs: *globalArgs,
MountArgs: *mountArgs,
TimeOutStart: time.Duration(*startTimeout) * time.Minute,
T: t,
}
}
// isTestNoneDriver checks if the current test is for none driver
func isTestNoneDriver(t *testing.T) bool {
t.Helper()
return strings.Contains(*startArgs, "--vm-driver=none")
}
// profileName chooses a profile name based on the test name
// to be used in minikube and kubecontext across that test
func profileName(t *testing.T) string {
t.Helper()
if isTestNoneDriver(t) {
return "minikube"
}
p := strings.Split(t.Name(), "/")[0] // for i.e, TestFunctional/SSH returns TestFunctional
if p == "TestFunctional" {
return "minikube"
}
return p
}
// shouldRunInParallel deterimines if test should run in parallel or not
func shouldRunInParallel(t *testing.T) bool {
t.Helper()
if !*parallel {
return false
}
if isTestNoneDriver(t) {
return false
}
p := strings.Split(t.Name(), "/")[0] // for i.e, TestFunctional/SSH returns TestFunctional
return p != "TestFunctional" // gosimple lint: https://staticcheck.io/docs/checks#S1008
}

View File

@ -25,22 +25,24 @@ import (
"net"
"net/http"
"net/url"
"path"
"path/filepath"
"strings"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
"github.com/pkg/errors"
retryablehttp "github.com/hashicorp/go-retryablehttp"
"k8s.io/apimachinery/pkg/labels"
commonutil "k8s.io/minikube/pkg/util"
pkgutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/test/integration/util"
)
func testAddons(t *testing.T) {
t.Parallel()
client, err := pkgutil.GetClient()
p := profileName(t)
client, err := pkgutil.GetClient(p)
if err != nil {
t.Fatalf("Could not get kubernetes client: %v", err)
}
@ -76,7 +78,8 @@ func readLineWithTimeout(b *bufio.Reader, timeout time.Duration) (string, error)
func testDashboard(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
cmd, out := mk.RunDaemon("dashboard --url")
defer func() {
err := cmd.Process.Kill()
@ -85,7 +88,7 @@ func testDashboard(t *testing.T) {
}
}()
s, err := readLineWithTimeout(out, 180*time.Second)
s, err := readLineWithTimeout(out, 240*time.Second)
if err != nil {
t.Fatalf("failed to read url: %v", err)
}
@ -121,30 +124,27 @@ func testDashboard(t *testing.T) {
func testIngressController(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t, "--wait=false")
kr := util.NewKubectlRunner(t)
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
kr := util.NewKubectlRunner(t, p)
mk.RunCommand("addons enable ingress", true)
if err := util.WaitForIngressControllerRunning(t); err != nil {
t.Fatalf("waiting for ingress-controller to be up: %v", err)
if err := waitForIngressControllerRunning(p); err != nil {
t.Fatalf("Failed waiting for ingress-controller to be up: %v", err)
}
curdir, err := filepath.Abs("")
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
}
ingressPath := path.Join(curdir, "testdata", "nginx-ing.yaml")
ingressPath := filepath.Join(*testdataDir, "nginx-ing.yaml")
if _, err := kr.RunCommand([]string{"create", "-f", ingressPath}); err != nil {
t.Fatalf("creating nginx ingress resource: %v", err)
t.Fatalf("Failed creating nginx ingress resource: %v", err)
}
podPath := path.Join(curdir, "testdata", "nginx-pod-svc.yaml")
podPath := filepath.Join(*testdataDir, "nginx-pod-svc.yaml")
if _, err := kr.RunCommand([]string{"create", "-f", podPath}); err != nil {
t.Fatalf("creating nginx ingress resource: %v", err)
t.Fatalf("Failed creating nginx ingress resource: %v", err)
}
if err := util.WaitForNginxRunning(t); err != nil {
t.Fatalf("waiting for nginx to be up: %v", err)
if err := waitForNginxRunning(t, p); err != nil {
t.Fatalf("Failed waiting for nginx to be up: %v", err)
}
checkIngress := func() error {
@ -157,7 +157,7 @@ func testIngressController(t *testing.T) {
return nil
}
if err := util.Retry(t, checkIngress, 3*time.Second, 5); err != nil {
if err := util.Retry(t, checkIngress, 2*time.Second, 5); err != nil {
t.Fatalf(err.Error())
}
@ -173,12 +173,13 @@ func testIngressController(t *testing.T) {
func testServicesList(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t)
p := profileName(t)
mk := NewMinikubeRunner(t, p)
checkServices := func() error {
output := mk.RunCommand("service list", false)
output, stderr := mk.RunCommand("service list", false)
if !strings.Contains(output, "kubernetes") {
return fmt.Errorf("Error, kubernetes service missing from output %s", output)
return fmt.Errorf("error, kubernetes service missing from output: %s, \n stderr: %s", output, stderr)
}
return nil
}
@ -188,9 +189,10 @@ func testServicesList(t *testing.T) {
}
func testRegistry(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t)
p := profileName(t)
mk := NewMinikubeRunner(t, p)
mk.RunCommand("addons enable registry", true)
client, err := pkgutil.GetClient()
client, err := pkgutil.GetClient(p)
if err != nil {
t.Fatalf("getting kubernetes client: %v", err)
}
@ -208,12 +210,12 @@ func testRegistry(t *testing.T) {
if err := pkgutil.WaitForPodsWithLabelRunning(client, "kube-system", ps); err != nil {
t.Fatalf("waiting for registry-proxy pods: %v", err)
}
ip := strings.TrimSpace(mk.RunCommand("ip", true))
ip, stderr := mk.RunCommand("ip", true)
ip = strings.TrimSpace(ip)
endpoint := fmt.Sprintf("http://%s:%d", ip, 5000)
u, err := url.Parse(endpoint)
if err != nil {
t.Fatalf("failed to parse %q: %v", endpoint, err)
t.Fatalf("failed to parse %q: %v stderr : %s", endpoint, err, stderr)
}
t.Log("checking registry access from outside cluster")
@ -235,7 +237,8 @@ func testRegistry(t *testing.T) {
}
t.Log("checking registry access from inside cluster")
kr := util.NewKubectlRunner(t)
kr := util.NewKubectlRunner(t, p)
// TODO: Fix this
out, _ := kr.RunCommand([]string{
"run",
"registry-test",
@ -259,88 +262,41 @@ func testRegistry(t *testing.T) {
}()
mk.RunCommand("addons disable registry", true)
}
func testGvisor(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
mk.RunCommand("addons enable gvisor", true)
t.Log("waiting for gvisor controller to come up")
if err := util.WaitForGvisorControllerRunning(t); err != nil {
t.Fatalf("waiting for gvisor controller to be up: %v", err)
}
// waitForNginxRunning waits for nginx service to be up
func waitForNginxRunning(t *testing.T, miniProfile string) error {
client, err := commonutil.GetClient(miniProfile)
createUntrustedWorkload(t)
t.Log("making sure untrusted workload is Running")
if err := util.WaitForUntrustedNginxRunning(); err != nil {
t.Fatalf("waiting for nginx to be up: %v", err)
}
t.Log("disabling gvisor addon")
mk.RunCommand("addons disable gvisor", true)
t.Log("waiting for gvisor controller pod to be deleted")
if err := util.WaitForGvisorControllerDeleted(); err != nil {
t.Fatalf("waiting for gvisor controller to be deleted: %v", err)
}
createUntrustedWorkload(t)
t.Log("waiting for FailedCreatePodSandBox event")
if err := util.WaitForFailedCreatePodSandBoxEvent(); err != nil {
t.Fatalf("waiting for FailedCreatePodSandBox event: %v", err)
}
deleteUntrustedWorkload(t)
}
func testGvisorRestart(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
mk.EnsureRunning()
mk.RunCommand("addons enable gvisor", true)
t.Log("waiting for gvisor controller to come up")
if err := util.WaitForGvisorControllerRunning(t); err != nil {
t.Fatalf("waiting for gvisor controller to be up: %v", err)
}
// TODO: @priyawadhwa to add test for stop as well
mk.RunCommand("delete", false)
mk.CheckStatus(state.None.String())
mk.Start()
mk.CheckStatus(state.Running.String())
t.Log("waiting for gvisor controller to come up")
if err := util.WaitForGvisorControllerRunning(t); err != nil {
t.Fatalf("waiting for gvisor controller to be up: %v", err)
}
createUntrustedWorkload(t)
t.Log("making sure untrusted workload is Running")
if err := util.WaitForUntrustedNginxRunning(); err != nil {
t.Fatalf("waiting for nginx to be up: %v", err)
}
deleteUntrustedWorkload(t)
}
func createUntrustedWorkload(t *testing.T) {
kr := util.NewKubectlRunner(t)
curdir, err := filepath.Abs("")
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
return errors.Wrap(err, "getting kubernetes client")
}
untrustedPath := path.Join(curdir, "testdata", "nginx-untrusted.yaml")
t.Log("creating pod with untrusted workload annotation")
if _, err := kr.RunCommand([]string{"replace", "-f", untrustedPath, "--force"}); err != nil {
t.Fatalf("creating untrusted nginx resource: %v", err)
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
return errors.Wrap(err, "waiting for nginx pods")
}
if err := commonutil.WaitForService(client, "default", "nginx", true, time.Millisecond*500, time.Minute*10); err != nil {
t.Errorf("Error waiting for nginx service to be up")
}
return nil
}
func deleteUntrustedWorkload(t *testing.T) {
kr := util.NewKubectlRunner(t)
curdir, err := filepath.Abs("")
// waitForIngressControllerRunning waits until ingress controller pod to be running
func waitForIngressControllerRunning(miniProfile string) error {
client, err := commonutil.GetClient(miniProfile)
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
return errors.Wrap(err, "getting kubernetes client")
}
untrustedPath := path.Join(curdir, "testdata", "nginx-untrusted.yaml")
if _, err := kr.RunCommand([]string{"delete", "-f", untrustedPath}); err != nil {
t.Logf("error deleting untrusted nginx resource: %v", err)
if err := commonutil.WaitForDeploymentToStabilize(client, "kube-system", "nginx-ingress-controller", time.Minute*10); err != nil {
return errors.Wrap(err, "waiting for ingress-controller deployment to stabilize")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"app.kubernetes.io/name": "nginx-ingress-controller"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
return errors.Wrap(err, "waiting for ingress-controller pods")
}
return nil
}

View File

@ -32,13 +32,14 @@ import (
func testClusterDNS(t *testing.T) {
t.Parallel()
client, err := pkgutil.GetClient()
p := profileName(t)
client, err := pkgutil.GetClient(p)
if err != nil {
t.Fatalf("Error getting kubernetes client %v", err)
}
kr := util.NewKubectlRunner(t)
busybox := busyBoxPod(t, client, kr)
kr := util.NewKubectlRunner(t, p)
busybox := busyBoxPod(t, client, kr, p)
defer func() {
if _, err := kr.RunCommand([]string{"delete", "po", busybox}); err != nil {
t.Errorf("delete failed: %v", err)
@ -61,12 +62,12 @@ func testClusterDNS(t *testing.T) {
}
}
func busyBoxPod(t *testing.T, c kubernetes.Interface, kr *util.KubectlRunner) string {
func busyBoxPod(t *testing.T, c kubernetes.Interface, kr *util.KubectlRunner, profile string) string {
if _, err := kr.RunCommand([]string{"create", "-f", filepath.Join(*testdataDir, "busybox.yaml")}); err != nil {
t.Fatalf("creating busybox pod: %s", err)
}
// TODO(tstromberg): Refactor WaitForBusyboxRunning to return name of pod.
if err := util.WaitForBusyboxRunning(t, "default"); err != nil {
if err := util.WaitForBusyboxRunning(t, "default", profile); err != nil {
t.Fatalf("Waiting for busybox pod to be up: %v", err)
}

View File

@ -30,13 +30,14 @@ import (
// Assert that docker-env subcommand outputs usable information for "docker ps"
func testClusterEnv(t *testing.T) {
t.Parallel()
r := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
// Set a specific shell syntax so that we don't have to handle every possible user shell
envOut := r.RunCommand("docker-env --shell=bash", true)
vars := r.ParseEnvCmdOutput(envOut)
envOut, stderr := mk.RunCommand("docker-env --shell=bash", true)
vars := mk.ParseEnvCmdOutput(envOut)
if len(vars) == 0 {
t.Fatalf("Failed to parse env vars:\n%s", envOut)
t.Fatalf("Failed to parse env vars:\n%s, \n stderr: %s ", envOut, stderr)
}
for k, v := range vars {
t.Logf("Found: %s=%s", k, v)

View File

@ -25,8 +25,8 @@ import (
func testClusterLogs(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t)
mk.EnsureRunning()
p := profileName(t)
mk := NewMinikubeRunner(t, p)
logsCmdOutput := mk.GetLogs()
// check for # of lines or check for strings

View File

@ -25,10 +25,11 @@ import (
func testClusterSSH(t *testing.T) {
t.Parallel()
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
expectedStr := "hello"
sshCmdOutput := mk.RunCommand("ssh echo "+expectedStr, true)
sshCmdOutput, stderr := mk.RunCommand("ssh echo "+expectedStr, true)
if !strings.Contains(sshCmdOutput, expectedStr) {
t.Fatalf("ExpectedStr sshCmdOutput to be: %s. Output was: %s", expectedStr, sshCmdOutput)
t.Fatalf("ExpectedStr sshCmdOutput to be: %s. Output was: %s Stderr: %s", expectedStr, sshCmdOutput, stderr)
}
}

View File

@ -28,12 +28,13 @@ import (
)
func testClusterStatus(t *testing.T) {
kubectlRunner := util.NewKubectlRunner(t)
p := profileName(t)
kr := util.NewKubectlRunner(t, p)
cs := api.ComponentStatusList{}
healthy := func() error {
t.Log("Checking if cluster is healthy.")
if err := kubectlRunner.RunCommandParseOutput([]string{"get", "cs"}, &cs); err != nil {
if err := kr.RunCommandParseOutput([]string{"get", "cs"}, &cs); err != nil {
return err
}
for _, i := range cs.Items {
@ -45,7 +46,7 @@ func testClusterStatus(t *testing.T) {
status = c.Status
}
if status != api.ConditionTrue {
err := fmt.Errorf("Component %s is not Healthy! Status: %s", i.GetName(), status)
err := fmt.Errorf("component %s is not Healthy! Status: %s", i.GetName(), status)
t.Logf("Retrying, %v", err)
return err
}

View File

@ -22,7 +22,6 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
"strings"
@ -38,12 +37,13 @@ func testMounting(t *testing.T) {
if runtime.GOOS == "darwin" {
t.Skip("mount tests disabled in darwin due to timeout (issue#3200)")
}
if strings.Contains(*globalArgs, "--vm-driver=none") {
if isTestNoneDriver(t) {
t.Skip("skipping test for none driver as it does not need mount")
}
t.Parallel()
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
tempDir, err := ioutil.TempDir("", "mounttest")
if err != nil {
@ -60,14 +60,9 @@ func testMounting(t *testing.T) {
}
}()
kubectlRunner := util.NewKubectlRunner(t)
kr := util.NewKubectlRunner(t, p)
podName := "busybox-mount"
curdir, err := filepath.Abs("")
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
}
podPath := path.Join(curdir, "testdata", "busybox-mount-test.yaml")
podPath := filepath.Join(*testdataDir, "busybox-mount-test.yaml")
// Write file in mounted dir from host
expected := "test\n"
if err := writeFilesFromHost(tempDir, []string{"fromhost", "fromhostremove"}, expected); err != nil {
@ -77,14 +72,14 @@ func testMounting(t *testing.T) {
// Create the pods we need outside the main test loop.
setupTest := func() error {
t.Logf("Deploying pod from: %s", podPath)
if _, err := kubectlRunner.RunCommand([]string{"create", "-f", podPath}); err != nil {
if _, err := kr.RunCommand([]string{"create", "-f", podPath}); err != nil {
return err
}
return nil
}
defer func() {
t.Logf("Deleting pod from: %s", podPath)
if out, err := kubectlRunner.RunCommand([]string{"delete", "-f", podPath}); err != nil {
if out, err := kr.RunCommand([]string{"delete", "-f", podPath}); err != nil {
t.Logf("delete -f %s failed: %v\noutput: %s\n", podPath, err, out)
}
}()
@ -93,13 +88,13 @@ func testMounting(t *testing.T) {
t.Fatal("mountTest failed with error:", err)
}
if err := waitForPods(map[string]string{"integration-test": "busybox-mount"}); err != nil {
if err := waitForPods(map[string]string{"integration-test": "busybox-mount"}, p); err != nil {
t.Fatalf("Error waiting for busybox mount pod to be up: %v", err)
}
t.Logf("Pods appear to be running")
mountTest := func() error {
if err := verifyFiles(mk, kubectlRunner, tempDir, podName, expected); err != nil {
if err := verifyFiles(mk, kr, tempDir, podName, expected); err != nil {
t.Fatalf(err.Error())
}
@ -126,14 +121,14 @@ func writeFilesFromHost(mountedDir string, files []string, content string) error
path := filepath.Join(mountedDir, file)
err := ioutil.WriteFile(path, []byte(content), 0644)
if err != nil {
return fmt.Errorf("Unexpected error while writing file %s: %v", path, err)
return fmt.Errorf("unexpected error while writing file %s: %v", path, err)
}
}
return nil
}
func waitForPods(s map[string]string) error {
client, err := pkgutil.GetClient()
func waitForPods(s map[string]string, profile string) error {
client, err := pkgutil.GetClient(profile)
if err != nil {
return fmt.Errorf("getting kubernetes client: %v", err)
}
@ -144,7 +139,7 @@ func waitForPods(s map[string]string) error {
return nil
}
func verifyFiles(mk util.MinikubeRunner, kubectlRunner *util.KubectlRunner, tempDir string, podName string, expected string) error {
func verifyFiles(mk util.MinikubeRunner, kr *util.KubectlRunner, tempDir string, podName string, expected string) error {
path := filepath.Join(tempDir, "frompod")
out, err := ioutil.ReadFile(path)
if err != nil {
@ -156,7 +151,7 @@ func verifyFiles(mk util.MinikubeRunner, kubectlRunner *util.KubectlRunner, temp
}
// test that file written from host was read in by the pod via cat /mount-9p/fromhost;
if out, err = kubectlRunner.RunCommand([]string{"logs", podName}); err != nil {
if out, err = kr.RunCommand([]string{"logs", podName}); err != nil {
return err
}
if string(out) != expected {
@ -169,30 +164,30 @@ func verifyFiles(mk util.MinikubeRunner, kubectlRunner *util.KubectlRunner, temp
statCmd := fmt.Sprintf("stat /mount-9p/%s", file)
statOutput, err := mk.SSH(statCmd)
if err != nil {
return fmt.Errorf("Unable to stat %s via SSH. error %v, %s", file, err, statOutput)
return fmt.Errorf("inable to stat %s via SSH. error %v, %s", file, err, statOutput)
}
if runtime.GOOS == "windows" {
if strings.Contains(statOutput, "Access: 1970-01-01") {
return fmt.Errorf("Invalid access time\n%s", statOutput)
return fmt.Errorf("invalid access time\n%s", statOutput)
}
}
if strings.Contains(statOutput, "Modify: 1970-01-01") {
return fmt.Errorf("Invalid modify time\n%s", statOutput)
return fmt.Errorf("invalid modify time\n%s", statOutput)
}
}
// test that fromhostremove was deleted by the pod from the mount via rm /mount-9p/fromhostremove
path = filepath.Join(tempDir, "fromhostremove")
if _, err := os.Stat(path); err == nil {
return fmt.Errorf("Expected file %s to be removed", path)
return fmt.Errorf("expected file %s to be removed", path)
}
// test that frompodremove can be deleted on the host
path = filepath.Join(tempDir, "frompodremove")
if err := os.Remove(path); err != nil {
return fmt.Errorf("Unexpected error removing file %s: %v", path, err)
return fmt.Errorf("unexpected error removing file %s: %v", path, err)
}
return nil

View File

@ -25,11 +25,11 @@ import (
// testProfileList tests the `minikube profile list` command
func testProfileList(t *testing.T) {
p := profileName(t)
t.Parallel()
profile := "minikube"
mk := NewMinikubeRunner(t, "--wait=false")
out := mk.RunCommand("profile list", true)
if !strings.Contains(out, profile) {
t.Errorf("Error , failed to read profile name (%s) in `profile list` command output : \n %q ", profile, out)
mk := NewMinikubeRunner(t, p, "--wait=false")
out, stderr := mk.RunCommand("profile list", true)
if !strings.Contains(out, p) {
t.Errorf("Error , failed to read profile name (%s) in `profile list` command output : \n %q : \n stderr: %s ", p, out, stderr)
}
}

View File

@ -39,11 +39,13 @@ var (
)
func testProvisioning(t *testing.T) {
p := profileName(t)
t.Parallel()
kubectlRunner := util.NewKubectlRunner(t)
kr := util.NewKubectlRunner(t, p)
defer func() {
if out, err := kubectlRunner.RunCommand([]string{"delete", "pvc", pvcName}); err != nil {
if out, err := kr.RunCommand([]string{"delete", "pvc", pvcName}); err != nil {
t.Logf("delete pvc %s failed: %v\noutput: %s\n", pvcName, err, out)
}
}()
@ -53,7 +55,7 @@ func testProvisioning(t *testing.T) {
checkStorageClass := func() error {
scl := storage.StorageClassList{}
if err := kubectlRunner.RunCommandParseOutput([]string{"get", "storageclass"}, &scl); err != nil {
if err := kr.RunCommandParseOutput([]string{"get", "storageclass"}, &scl); err != nil {
return fmt.Errorf("get storageclass: %v", err)
}
@ -63,14 +65,14 @@ func testProvisioning(t *testing.T) {
return fmt.Errorf("no default StorageClass yet")
}
if err := util.Retry(t, checkStorageClass, 5*time.Second, 20); err != nil {
if err := util.Retry(t, checkStorageClass, 10*time.Second, 10); err != nil {
t.Fatalf("no default storage class after retry: %v", err)
}
// Check that the storage provisioner pod is running
checkPodRunning := func() error {
client, err := commonutil.GetClient()
client, err := commonutil.GetClient(p)
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
@ -82,20 +84,20 @@ func testProvisioning(t *testing.T) {
return nil
}
if err := checkPodRunning(); err != nil {
if err := util.Retry(t, checkPodRunning, 2*time.Second, 5); err != nil {
t.Fatalf("Check storage-provisioner pod running failed with error: %v", err)
}
// Now create the PVC
pvcPath := filepath.Join(*testdataDir, "pvc.yaml")
if _, err := kubectlRunner.RunCommand([]string{"create", "-f", pvcPath}); err != nil {
if _, err := kr.RunCommand([]string{"create", "-f", pvcPath}); err != nil {
t.Fatalf("Error creating pvc: %v", err)
}
// And check that it gets bound to a PV.
checkStorage := func() error {
pvc := core.PersistentVolumeClaim{}
if err := kubectlRunner.RunCommandParseOutput(pvcCmd, &pvc); err != nil {
if err := kr.RunCommandParseOutput(pvcCmd, &pvc); err != nil {
return err
}
// The test passes if the volume claim gets bound.

View File

@ -21,7 +21,6 @@ import (
"io/ioutil"
"net/http"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
@ -46,11 +45,13 @@ func testTunnel(t *testing.T) {
}
t.Log("starting tunnel test...")
runner := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
go func() {
output := runner.RunCommand("tunnel --alsologtostderr -v 8 --logtostderr", true)
output, stderr := mk.RunCommand("tunnel --alsologtostderr -v 8 --logtostderr", true)
if t.Failed() {
fmt.Println(output)
t.Errorf("tunnel stderr : %s", stderr)
t.Errorf("tunnel output : %s", output)
}
}()
@ -60,19 +61,15 @@ func testTunnel(t *testing.T) {
t.Fatal(errors.Wrap(err, "cleaning up tunnels"))
}
kubectlRunner := util.NewKubectlRunner(t)
kr := util.NewKubectlRunner(t, p)
t.Log("deploying nginx...")
curdir, err := filepath.Abs("")
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
}
podPath := path.Join(curdir, "testdata", "testsvc.yaml")
if _, err := kubectlRunner.RunCommand([]string{"apply", "-f", podPath}); err != nil {
podPath := filepath.Join(*testdataDir, "testsvc.yaml")
if _, err := kr.RunCommand([]string{"apply", "-f", podPath}); err != nil {
t.Fatalf("creating nginx ingress resource: %s", err)
}
client, err := commonutil.GetClient()
client, err := commonutil.GetClient(p)
if err != nil {
t.Fatal(errors.Wrap(err, "getting kubernetes client"))
@ -89,13 +86,13 @@ func testTunnel(t *testing.T) {
t.Log("getting nginx ingress...")
nginxIP, err := getIngress(kubectlRunner)
nginxIP, err := getIngress(kr)
if err != nil {
t.Errorf("error getting ingress IP for nginx: %s", err)
}
if len(nginxIP) == 0 {
stdout, err := describeIngress(kubectlRunner)
stdout, err := describeIngress(kr)
if err != nil {
t.Errorf("error debugging nginx service: %s", err)
@ -113,12 +110,12 @@ func testTunnel(t *testing.T) {
}
}
func getIngress(kubectlRunner *util.KubectlRunner) (string, error) {
func getIngress(kr *util.KubectlRunner) (string, error) {
nginxIP := ""
var ret error
err := wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
cmd := []string{"get", "svc", "nginx-svc", "-o", "jsonpath={.status.loadBalancer.ingress[0].ip}"}
stdout, err := kubectlRunner.RunCommand(cmd)
stdout, err := kr.RunCommand(cmd)
switch {
case err == nil:
nginxIP = string(stdout)
@ -137,8 +134,8 @@ func getIngress(kubectlRunner *util.KubectlRunner) (string, error) {
return nginxIP, ret
}
func describeIngress(kubectlRunner *util.KubectlRunner) ([]byte, error) {
return kubectlRunner.RunCommand([]string{"get", "svc", "nginx-svc", "-o", "jsonpath={.status}"})
func describeIngress(kr *util.KubectlRunner) ([]byte, error) {
return kr.RunCommand([]string{"get", "svc", "nginx-svc", "-o", "jsonpath={.status}"})
}
// getResponseBody returns the contents of a URL

View File

@ -19,54 +19,43 @@ limitations under the License.
package integration
import (
"strings"
"testing"
"github.com/docker/machine/libmachine/state"
"k8s.io/minikube/test/integration/util"
)
func TestFunctional(t *testing.T) {
r := NewMinikubeRunner(t)
r.EnsureRunning()
// This one is not parallel, and ensures the cluster comes up
// before we run any other tests.
t.Run("Status", testClusterStatus)
t.Run("ProfileList", testProfileList)
t.Run("DNS", testClusterDNS)
t.Run("Logs", testClusterLogs)
t.Run("Addons", testAddons)
t.Run("Registry", testRegistry)
t.Run("Dashboard", testDashboard)
t.Run("ServicesList", testServicesList)
t.Run("Provisioning", testProvisioning)
t.Run("Tunnel", testTunnel)
if !usingNoneDriver(r) {
t.Run("EnvVars", testClusterEnv)
t.Run("SSH", testClusterSSH)
t.Run("IngressController", testIngressController)
t.Run("Mounting", testMounting)
p := profileName(t)
mk := NewMinikubeRunner(t, p)
stdout, stderr, err := mk.Start()
if err != nil {
t.Fatalf("failed to start minikube failed : %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
}
}
func TestFunctionalContainerd(t *testing.T) {
r := NewMinikubeRunner(t)
if usingNoneDriver(r) {
t.Skip("Can't run containerd backend with none driver")
if !isTestNoneDriver(t) { // none driver doesn't need to be deleted
defer mk.TearDown(t)
}
if r.GetStatus() != state.None.String() {
r.RunCommand("delete", true)
}
r.Start("--container-runtime=containerd", "--docker-opt containerd=/var/run/containerd/containerd.sock")
t.Run("Gvisor", testGvisor)
t.Run("GvisorRestart", testGvisorRestart)
r.RunCommand("delete", true)
}
// group is needed to make sure tear down runs after parallel runs
// https://github.com/golang/go/issues/17791#issuecomment-258476786
t.Run("group", func(t *testing.T) {
// This one is not parallel, and ensures the cluster comes up
// before we run any other tests.
t.Run("Status", testClusterStatus)
t.Run("ProfileList", testProfileList)
t.Run("DNS", testClusterDNS)
t.Run("Logs", testClusterLogs)
t.Run("Addons", testAddons)
t.Run("Registry", testRegistry)
t.Run("Dashboard", testDashboard)
t.Run("ServicesList", testServicesList)
t.Run("Provisioning", testProvisioning)
t.Run("Tunnel", testTunnel)
if !isTestNoneDriver(t) {
t.Run("EnvVars", testClusterEnv)
t.Run("SSH", testClusterSSH)
t.Run("IngressController", testIngressController)
t.Run("Mounting", testMounting)
}
})
// usingNoneDriver returns true if using the none driver
func usingNoneDriver(r util.MinikubeRunner) bool {
return strings.Contains(r.StartArgs, "--vm-driver=none")
}

View File

@ -25,19 +25,30 @@ import (
)
func TestISO(t *testing.T) {
p := profileName(t)
if shouldRunInParallel(t) {
t.Parallel()
}
mk := NewMinikubeRunner(t, "--wait=false")
mk := NewMinikubeRunner(t, p, "--wait=false")
mk.RunCommand("delete", false)
mk.Start()
stdout, stderr, err := mk.Start()
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) %s) failed : %v\nstdout: %s\nstderr: %s", t.Name(), err, stdout, stderr)
}
if !isTestNoneDriver(t) { // none driver doesn't need to be deleted
defer mk.TearDown(t)
}
t.Run("permissions", testMountPermissions)
t.Run("packages", testPackages)
t.Run("persistence", testPersistence)
}
func testMountPermissions(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
// test mount permissions
mountPoints := []string{"/Users", "/hosthome"}
perms := "drwxr-xr-x"
@ -59,7 +70,8 @@ func testMountPermissions(t *testing.T) {
}
func testPackages(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
packages := []string{
"git",
@ -81,7 +93,8 @@ func testPackages(t *testing.T) {
}
func testPersistence(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t)
mk := NewMinikubeRunner(t, p, "--wait=false")
for _, dir := range []string{
"/data",

View File

@ -19,59 +19,51 @@ limitations under the License.
package integration
import (
"path"
"path/filepath"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
"k8s.io/minikube/test/integration/util"
)
func TestPersistence(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
if usingNoneDriver(mk) {
if isTestNoneDriver(t) {
t.Skip("skipping test as none driver does not support persistence")
}
mk.EnsureRunning()
p := profileName(t)
if shouldRunInParallel(t) {
t.Parallel()
}
kubectlRunner := util.NewKubectlRunner(t)
curdir, err := filepath.Abs("")
mk := NewMinikubeRunner(t, p, "--wait=false")
defer mk.TearDown(t)
stdout, stderr, err := mk.Start()
if err != nil {
t.Errorf("Error getting the file path for current directory: %s", curdir)
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", t.Name(), err, stdout, stderr)
}
podPath := path.Join(curdir, "testdata", "busybox.yaml")
// Create a pod and wait for it to be running.
if _, err := kubectlRunner.RunCommand([]string{"create", "-f", podPath}); err != nil {
t.Fatalf("Error creating test pod: %v", err)
kr := util.NewKubectlRunner(t, p)
if _, err := kr.RunCommand([]string{"create", "-f", filepath.Join(*testdataDir, "busybox.yaml")}); err != nil {
t.Fatalf("creating busybox pod: %s", err)
}
verify := func(t *testing.T) {
if err := util.WaitForBusyboxRunning(t, "default"); err != nil {
verifyBusybox := func(t *testing.T) {
if err := util.WaitForBusyboxRunning(t, "default", p); err != nil {
t.Fatalf("waiting for busybox to be up: %v", err)
}
}
// Make sure everything is up before we stop.
verify(t)
verifyBusybox(t)
// Now restart minikube and make sure the pod is still there.
// mk.RunCommand("stop", true)
// mk.CheckStatus("Stopped")
checkStop := func() error {
mk.RunCommand("stop", true)
return mk.CheckStatusNoFail(state.Stopped.String())
mk.RunCommand("stop", true)
mk.CheckStatus(state.Stopped.String())
stdout, stderr, err = mk.Start()
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", t.Name(), err, stdout, stderr)
}
if err := util.Retry(t, checkStop, 5*time.Second, 6); err != nil {
t.Fatalf("timed out while checking stopped status: %v", err)
}
mk.Start()
mk.CheckStatus(state.Running.String())
// Make sure the same things come up after we've restarted.
verify(t)
verifyBusybox(t)
}

View File

@ -31,86 +31,96 @@ import (
)
func TestStartStop(t *testing.T) {
tests := []struct {
name string
args []string
}{
{"nocache_oldest", []string{
"--cache-images=false",
fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
// default is the network created by libvirt, if we change the name minikube won't boot
// because the given network doesn't exist
"--kvm-network=default",
"--kvm-qemu-uri=qemu:///system",
}},
{"feature_gates_newest_cni", []string{
"--feature-gates",
"ServerSideApply=true",
"--network-plugin=cni",
"--extra-config=kubelet.network-plugin=cni",
"--extra-config=kubeadm.pod-network-cidr=192.168.111.111/16",
fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
}},
{"containerd_and_non_default_apiserver_port", []string{
"--container-runtime=containerd",
"--docker-opt containerd=/var/run/containerd/containerd.sock",
"--apiserver-port=8444",
}},
{"crio_ignore_preflights", []string{
"--container-runtime=crio",
"--extra-config",
"kubeadm.ignore-preflight-errors=SystemVerification",
}},
p := profileName(t) // gets profile name used for minikube and kube context
if shouldRunInParallel(t) {
t.Parallel()
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
r := NewMinikubeRunner(t)
if !strings.Contains(test.name, "docker") && usingNoneDriver(r) {
t.Skipf("skipping %s - incompatible with none driver", test.name)
}
t.Run("group", func(t *testing.T) {
if shouldRunInParallel(t) {
t.Parallel()
}
tests := []struct {
name string
args []string
}{
{"oldest", []string{ // nocache_oldest
"--cache-images=false",
fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
// default is the network created by libvirt, if we change the name minikube won't boot
// because the given network doesn't exist
"--kvm-network=default",
"--kvm-qemu-uri=qemu:///system",
}},
{"cni", []string{ // feature_gates_newest_cni
"--feature-gates",
"ServerSideApply=true",
"--network-plugin=cni",
"--extra-config=kubelet.network-plugin=cni",
"--extra-config=kubeadm.pod-network-cidr=192.168.111.111/16",
fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
}},
{"containerd", []string{ // containerd_and_non_default_apiserver_port
"--container-runtime=containerd",
"--docker-opt containerd=/var/run/containerd/containerd.sock",
"--apiserver-port=8444",
}},
{"crio", []string{ // crio_ignore_preflights
"--container-runtime=crio",
"--extra-config",
"kubeadm.ignore-preflight-errors=SystemVerification",
}},
}
r.RunCommand("config set WantReportErrorPrompt false", true)
r.RunCommand("delete", false)
r.CheckStatus(state.None.String())
r.Start(test.args...)
r.CheckStatus(state.Running.String())
for _, tc := range tests {
n := tc.name // because similar to https://golang.org/doc/faq#closures_and_goroutines
t.Run(tc.name, func(t *testing.T) {
if shouldRunInParallel(t) {
t.Parallel()
}
ip := r.RunCommand("ip", true)
ip = strings.TrimRight(ip, "\n")
if net.ParseIP(ip) == nil {
t.Fatalf("IP command returned an invalid address: %s", ip)
}
pn := p + n // TestStartStopoldest
mk := NewMinikubeRunner(t, pn, "--wait=false")
// TODO : redundant first clause ? never happens?
if !strings.Contains(pn, "docker") && isTestNoneDriver(t) {
t.Skipf("skipping %s - incompatible with none driver", t.Name())
}
// check for the current-context before and after the stop
kubectlRunner := util.NewKubectlRunner(t)
currentContext, err := kubectlRunner.RunCommand([]string{"config", "current-context"})
if err != nil {
t.Fatalf("Failed to fetch current-context")
}
if strings.TrimRight(string(currentContext), "\n") != "minikube" {
t.Fatalf("got current-context - %q, want current-context %q", string(currentContext), "minikube")
}
mk.RunCommand("config set WantReportErrorPrompt false", true)
stdout, stderr, err := mk.Start(tc.args...)
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", pn, err, stdout, stderr)
}
checkStop := func() error {
r.RunCommand("stop", true)
return r.CheckStatusNoFail(state.Stopped.String())
}
mk.CheckStatus(state.Running.String())
if err := util.Retry(t, checkStop, 5*time.Second, 6); err != nil {
t.Fatalf("timed out while checking stopped status: %v", err)
}
ip, stderr := mk.RunCommand("ip", true)
ip = strings.TrimRight(ip, "\n")
if net.ParseIP(ip) == nil {
t.Fatalf("IP command returned an invalid address: %s \n %s", ip, stderr)
}
// running this command results in error when the current-context is not set
if err := r.Run("config current-context"); err != nil {
t.Logf("current-context is not set to minikube")
}
stop := func() error {
stdout, stderr, err = mk.RunCommandRetriable("stop")
return mk.CheckStatusNoFail(state.Stopped.String())
}
r.Start(test.args...)
r.CheckStatus(state.Running.String())
err = util.RetryX(stop, 10*time.Second, 2*time.Minute)
mk.CheckStatus(state.Stopped.String())
r.RunCommand("delete", true)
r.CheckStatus(state.None.String())
})
}
// TODO medyagh:
// https://github.com/kubernetes/minikube/issues/4854
stdout, stderr, err = mk.Start(tc.args...)
if err != nil {
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", t.Name(), err, stdout, stderr)
}
mk.CheckStatus(state.Running.String())
mk.RunCommand("delete", true)
mk.CheckStatus(state.None.String())
})
}
})
}

View File

@ -0,0 +1,82 @@
/*
Copyright 2019 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"fmt"
"testing"
"time"
"github.com/cenkalti/backoff"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/labels"
commonutil "k8s.io/minikube/pkg/util"
)
// WaitForBusyboxRunning waits until busybox pod to be running
func WaitForBusyboxRunning(t *testing.T, namespace string, miniProfile string) error {
client, err := commonutil.GetClient(miniProfile)
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"integration-test": "busybox"}))
return commonutil.WaitForPodsWithLabelRunning(client, namespace, selector)
}
// Retry tries the callback for a number of attempts, with a delay between attempts
func Retry(t *testing.T, callback func() error, d time.Duration, attempts int) (err error) {
for i := 0; i < attempts; i++ {
err = callback()
if err == nil {
return nil
}
time.Sleep(d)
}
return err
}
// Retry2 tries the callback for a number of attempts, with a delay without *testing.T
func Retry2(callback func() error, d time.Duration, attempts int) (err error) {
for i := 0; i < attempts; i++ {
err = callback()
if err == nil {
return nil
}
time.Sleep(d)
}
return err
}
// RetryX is expontential backoff retry
func RetryX(callback func() error, initInterv time.Duration, maxTime time.Duration) error {
b := backoff.NewExponentialBackOff()
b.MaxElapsedTime = maxTime
b.InitialInterval = initInterv
b.RandomizationFactor = 0.5
b.Multiplier = 1.5
b.Reset()
return backoff.Retry(callback, b)
}
// Logf writes logs to stdout if -v is set.
func Logf(str string, args ...interface{}) {
if !testing.Verbose() {
return
}
fmt.Printf(" %s | ", time.Now().Format("15:04:05"))
fmt.Println(fmt.Sprintf(str, args...))
}

View File

@ -0,0 +1,117 @@
/*
Copyright 2019 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"bytes"
"encoding/json"
"fmt"
"math/rand"
"os/exec"
"testing"
"time"
commonutil "k8s.io/minikube/pkg/util"
)
const kubectlBinary = "kubectl"
// KubectlRunner runs a command using kubectl
type KubectlRunner struct {
Profile string // kube-context maps to a minikube profile
T *testing.T
BinaryPath string
}
// NewKubectlRunner creates a new KubectlRunner
func NewKubectlRunner(t *testing.T, profile ...string) *KubectlRunner {
if profile == nil {
profile = []string{"minikube"}
}
p, err := exec.LookPath(kubectlBinary)
if err != nil {
t.Fatalf("Couldn't find kubectl on path.")
}
return &KubectlRunner{Profile: profile[0], BinaryPath: p, T: t}
}
// RunCommandParseOutput runs a command and parses the JSON output
func (k *KubectlRunner) RunCommandParseOutput(args []string, outputObj interface{}, useKubeContext ...bool) error {
args = append(args, "-o=json")
output, err := k.RunCommand(args, useKubeContext...)
if err != nil {
return err
}
d := json.NewDecoder(bytes.NewReader(output))
if err := d.Decode(outputObj); err != nil {
return err
}
return nil
}
// RunCommand runs a command, returning stdout
func (k *KubectlRunner) RunCommand(args []string, useKubeContext ...bool) (stdout []byte, err error) {
if useKubeContext == nil {
useKubeContext = []bool{true}
}
if useKubeContext[0] {
kubecContextArg := fmt.Sprintf("--context=%s", k.Profile)
args = append([]string{kubecContextArg}, args...) // prepending --context so it can be with with -- space
}
inner := func() error {
cmd := exec.Command(k.BinaryPath, args...)
stdout, err = cmd.CombinedOutput()
if err != nil {
retriable := &commonutil.RetriableError{Err: fmt.Errorf("error running command %s: %v. Stdout: \n %s", args, err, stdout)}
k.T.Log(retriable)
return retriable
}
return nil
}
err = commonutil.RetryAfter(3, inner, 2*time.Second)
return stdout, err
}
// CreateRandomNamespace creates a random namespace
func (k *KubectlRunner) CreateRandomNamespace() string {
const strLen = 20
name := genRandString(strLen)
if _, err := k.RunCommand([]string{"create", "namespace", name}); err != nil {
k.T.Fatalf("Error creating namespace: %v", err)
}
return name
}
func genRandString(strLen int) string {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
rand.Seed(time.Now().UTC().UnixNano())
result := make([]byte, strLen)
for i := 0; i < strLen; i++ {
result[i] = chars[rand.Intn(len(chars))]
}
return string(result)
}
// DeleteNamespace deletes the namespace
func (k *KubectlRunner) DeleteNamespace(namespace string) error {
_, err := k.RunCommand([]string{"delete", "namespace", namespace})
return err
}

View File

@ -0,0 +1,318 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"bufio"
"bytes"
"context"
"fmt"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/assets"
commonutil "k8s.io/minikube/pkg/util"
)
// MinikubeRunner runs a command
type MinikubeRunner struct {
Profile string
T *testing.T
BinaryPath string
GlobalArgs string
StartArgs string
MountArgs string
Runtime string
TimeOutStart time.Duration // time to wait for minikube start before killing it
}
// Remove removes a file
func (m *MinikubeRunner) Remove(f assets.CopyableFile) error {
_, err := m.SSH(fmt.Sprintf("rm -rf %s", filepath.Join(f.GetTargetDir(), f.GetTargetName())))
return err
}
// teeRun runs a command, streaming stdout, stderr to console
func (m *MinikubeRunner) teeRun(cmd *exec.Cmd, waitForRun ...bool) (string, string, error) {
w := true
if waitForRun != nil {
w = waitForRun[0]
}
errPipe, err := cmd.StderrPipe()
if err != nil {
return "", "", err
}
outPipe, err := cmd.StdoutPipe()
if err != nil {
return "", "", err
}
if err := cmd.Start(); err != nil {
return "", "", err
}
if w {
var outB bytes.Buffer
var errB bytes.Buffer
var wg sync.WaitGroup
wg.Add(2)
go func() {
if err := commonutil.TeePrefix(commonutil.ErrPrefix, errPipe, &errB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
wg.Done()
}()
go func() {
if err := commonutil.TeePrefix(commonutil.OutPrefix, outPipe, &outB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
wg.Done()
}()
err = cmd.Wait()
wg.Wait()
return outB.String(), errB.String(), err
}
return "", "", err
}
// RunCommand executes a command, optionally checking for error and by default waits for run to finish
func (m *MinikubeRunner) RunCommand(cmdStr string, failError bool, waitForRun ...bool) (string, string) {
profileArg := fmt.Sprintf("-p=%s ", m.Profile)
cmdStr = profileArg + cmdStr
cmdArgs := strings.Split(cmdStr, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, cmdArgs...)
Logf("Run: %s", cmd.Args)
stdout, stderr, err := m.teeRun(cmd, waitForRun...)
if err != nil {
errMsg := ""
if exitError, ok := err.(*exec.ExitError); ok {
errMsg = fmt.Sprintf("Error running command: %s %s. Output: %s Stderr: %s", cmdStr, exitError.Stderr, stdout, stderr)
} else {
errMsg = fmt.Sprintf("Error running command: %s %s. Output: %s", cmdStr, stderr, stdout)
}
if failError {
m.T.Fatalf(errMsg)
} else {
m.T.Errorf(errMsg)
}
}
return stdout, stderr
}
// RunCommandRetriable Error executes a command, returns error
// the purpose of this command is to make it retriable and
// better logging for retrying
func (m *MinikubeRunner) RunCommandRetriable(cmdStr string, waitForRun ...bool) (stdout string, stderr string, err error) {
profileArg := fmt.Sprintf("-p=%s ", m.Profile)
cmdStr = profileArg + cmdStr
cmdArgs := strings.Split(cmdStr, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, cmdArgs...)
Logf("Run: %s", cmd.Args)
stdout, stderr, err = m.teeRun(cmd, waitForRun...)
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
m.T.Logf("temporary error: running command: %s %s. Output: \n%s", cmdStr, exitError.Stderr, stdout)
} else {
m.T.Logf("temporary error: running command: %s %s. Output: \n%s", cmdStr, stderr, stdout)
}
}
return stdout, stderr, err
}
// RunWithContext calls the minikube command with a context, useful for timeouts.
func (m *MinikubeRunner) RunWithContext(ctx context.Context, cmdStr string, wait ...bool) (string, string, error) {
profileArg := fmt.Sprintf("-p=%s ", m.Profile)
cmdStr = profileArg + cmdStr
cmdArgs := strings.Split(cmdStr, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.CommandContext(ctx, path, cmdArgs...)
Logf("Run: %s", cmd.Args)
return m.teeRun(cmd, wait...)
}
// RunDaemon executes a command, returning the stdout
func (m *MinikubeRunner) RunDaemon(cmdStr string) (*exec.Cmd, *bufio.Reader) {
profileArg := fmt.Sprintf("-p=%s ", m.Profile)
cmdStr = profileArg + cmdStr
cmdArgs := strings.Split(cmdStr, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, cmdArgs...)
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
m.T.Fatalf("stdout pipe failed: %s %v", cmdStr, err)
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
m.T.Fatalf("stderr pipe failed: %s %v", cmdStr, err)
}
var errB bytes.Buffer
go func() {
if err := commonutil.TeePrefix(commonutil.ErrPrefix, stderrPipe, &errB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
}()
err = cmd.Start()
if err != nil {
m.T.Fatalf("Error running command: %s %v", cmdStr, err)
}
return cmd, bufio.NewReader(stdoutPipe)
}
// RunDaemon2 executes a command, returning the stdout and stderr
func (m *MinikubeRunner) RunDaemon2(cmdStr string) (*exec.Cmd, *bufio.Reader, *bufio.Reader) {
profileArg := fmt.Sprintf("-p=%s ", m.Profile)
cmdStr = profileArg + cmdStr
cmdArgs := strings.Split(cmdStr, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, cmdArgs...)
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
m.T.Fatalf("stdout pipe failed: %s %v", cmdStr, err)
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
m.T.Fatalf("stderr pipe failed: %s %v", cmdStr, err)
}
err = cmd.Start()
if err != nil {
m.T.Fatalf("Error running command: %s %v", cmdStr, err)
}
return cmd, bufio.NewReader(stdoutPipe), bufio.NewReader(stderrPipe)
}
// SSH returns the output of running a command using SSH
func (m *MinikubeRunner) SSH(cmdStr string) (string, error) {
profileArg := fmt.Sprintf("-p=%s", m.Profile)
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, profileArg, "ssh", cmdStr)
Logf("SSH: %s", cmdStr)
stdout, err := cmd.CombinedOutput()
Logf("Output: %s", stdout)
if err, ok := err.(*exec.ExitError); ok {
return string(stdout), err
}
return string(stdout), nil
}
// Start starts the cluster
func (m *MinikubeRunner) Start(opts ...string) (stdout string, stderr string, err error) {
cmd := fmt.Sprintf("start %s %s %s", m.StartArgs, m.GlobalArgs, strings.Join(opts, " "))
s := func() error {
stdout, stderr, err = m.RunCommandRetriable(cmd)
return err
}
err = RetryX(s, 10*time.Second, m.TimeOutStart)
return stdout, stderr, err
}
// TearDown deletes minikube without waiting for it. used to free up ram/cpu after each test
func (m *MinikubeRunner) TearDown(t *testing.T) {
profileArg := fmt.Sprintf("-p=%s", m.Profile)
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, profileArg, "delete")
err := cmd.Start()
if err != nil {
t.Errorf("error tearing down minikube %s : %v", profileArg, err)
}
}
// EnsureRunning makes sure the container runtime is running
func (m *MinikubeRunner) EnsureRunning(opts ...string) {
s, _, err := m.Status()
if err != nil {
m.T.Errorf("error getting status for ensure running: %v", err)
}
if s != state.Running.String() {
stdout, stderr, err := m.Start(opts...)
if err != nil {
m.T.Errorf("error starting while running EnsureRunning : %v , stdout %s stderr %s", err, stdout, stderr)
}
}
m.CheckStatus(state.Running.String())
}
// ParseEnvCmdOutput parses the output of `env` (assumes bash)
func (m *MinikubeRunner) ParseEnvCmdOutput(out string) map[string]string {
env := map[string]string{}
re := regexp.MustCompile(`(\w+?) ?= ?"?(.+?)"?\n`)
for _, m := range re.FindAllStringSubmatch(out, -1) {
env[m[1]] = m[2]
}
return env
}
// Status returns the status of a service
func (m *MinikubeRunner) Status() (status string, stderr string, err error) {
cmd := fmt.Sprintf("status --format={{.Host}} %s", m.GlobalArgs)
s := func() error {
status, stderr, err = m.RunCommandRetriable(cmd)
status = strings.TrimRight(status, "\n")
return err
}
err = RetryX(s, 15*time.Second, 1*time.Minute)
if err != nil && (status == state.None.String() || status == state.Stopped.String()) {
err = nil // because https://github.com/kubernetes/minikube/issues/4932
}
return status, stderr, err
}
// GetLogs returns the logs of a service
func (m *MinikubeRunner) GetLogs() string {
// TODO: this test needs to check sterr too !
stdout, _ := m.RunCommand(fmt.Sprintf("logs %s", m.GlobalArgs), true)
return stdout
}
// CheckStatus makes sure the service has the desired status, or cause fatal error
func (m *MinikubeRunner) CheckStatus(desired string) {
err := m.CheckStatusNoFail(desired)
if err != nil { // none status returns 1 exit code
m.T.Fatalf("%v", err)
}
}
// CheckStatusNoFail makes sure the service has the desired status, returning error
func (m *MinikubeRunner) CheckStatusNoFail(desired string) error {
s, stderr, err := m.Status()
if s != desired {
return fmt.Errorf("got state: %q, expected %q : stderr: %s err: %v ", s, desired, stderr, err)
}
if err != nil {
return errors.Wrapf(err, stderr)
}
return nil
}

View File

@ -1,445 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"bufio"
"bytes"
"context"
"encoding/json"
"fmt"
"math/rand"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
"testing"
"time"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/minikube/pkg/minikube/assets"
commonutil "k8s.io/minikube/pkg/util"
)
const kubectlBinary = "kubectl"
// MinikubeRunner runs a command
type MinikubeRunner struct {
T *testing.T
BinaryPath string
GlobalArgs string
StartArgs string
MountArgs string
Runtime string
}
// Logf writes logs to stdout if -v is set.
func Logf(str string, args ...interface{}) {
if !testing.Verbose() {
return
}
fmt.Printf(" %s | ", time.Now().Format("15:04:05"))
fmt.Println(fmt.Sprintf(str, args...))
}
// Run executes a command
func (m *MinikubeRunner) Run(cmd string) error {
_, err := m.SSH(cmd)
return err
}
// Copy copies a file
func (m *MinikubeRunner) Copy(f assets.CopyableFile) error {
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command("/bin/bash", "-c", path, "ssh", "--", fmt.Sprintf("cat >> %s", filepath.Join(f.GetTargetDir(), f.GetTargetName())))
Logf("Running: %s", cmd.Args)
return cmd.Run()
}
// CombinedOutput executes a command, returning the combined stdout and stderr
func (m *MinikubeRunner) CombinedOutput(cmd string) (string, error) {
return m.SSH(cmd)
}
// Remove removes a file
func (m *MinikubeRunner) Remove(f assets.CopyableFile) error {
_, err := m.SSH(fmt.Sprintf("rm -rf %s", filepath.Join(f.GetTargetDir(), f.GetTargetName())))
return err
}
// teeRun runs a command, streaming stdout, stderr to console
func (m *MinikubeRunner) teeRun(cmd *exec.Cmd) (string, string, error) {
errPipe, err := cmd.StderrPipe()
if err != nil {
return "", "", err
}
outPipe, err := cmd.StdoutPipe()
if err != nil {
return "", "", err
}
if err := cmd.Start(); err != nil {
return "", "", err
}
var outB bytes.Buffer
var errB bytes.Buffer
var wg sync.WaitGroup
wg.Add(2)
go func() {
if err := commonutil.TeePrefix(commonutil.ErrPrefix, errPipe, &errB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
wg.Done()
}()
go func() {
if err := commonutil.TeePrefix(commonutil.OutPrefix, outPipe, &outB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
wg.Done()
}()
err = cmd.Wait()
wg.Wait()
return outB.String(), errB.String(), err
}
// RunCommand executes a command, optionally checking for error
func (m *MinikubeRunner) RunCommand(command string, checkError bool) string {
commandArr := strings.Split(command, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, commandArr...)
Logf("Run: %s", cmd.Args)
stdout, stderr, err := m.teeRun(cmd)
if checkError && err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
m.T.Fatalf("Error running command: %s %s. Output: %s", command, exitError.Stderr, stdout)
} else {
m.T.Fatalf("Error running command: %s %v. Output: %s", command, err, stderr)
}
}
return stdout
}
// RunWithContext calls the minikube command with a context, useful for timeouts.
func (m *MinikubeRunner) RunWithContext(ctx context.Context, command string) (string, string, error) {
commandArr := strings.Split(command, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.CommandContext(ctx, path, commandArr...)
Logf("Run: %s", cmd.Args)
return m.teeRun(cmd)
}
// RunDaemon executes a command, returning the stdout
func (m *MinikubeRunner) RunDaemon(command string) (*exec.Cmd, *bufio.Reader) {
commandArr := strings.Split(command, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, commandArr...)
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
m.T.Fatalf("stdout pipe failed: %s %v", command, err)
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
m.T.Fatalf("stderr pipe failed: %s %v", command, err)
}
var errB bytes.Buffer
go func() {
if err := commonutil.TeePrefix(commonutil.ErrPrefix, stderrPipe, &errB, Logf); err != nil {
m.T.Logf("tee: %v", err)
}
}()
err = cmd.Start()
if err != nil {
m.T.Fatalf("Error running command: %s %v", command, err)
}
return cmd, bufio.NewReader(stdoutPipe)
}
// RunDaemon2 executes a command, returning the stdout and stderr
func (m *MinikubeRunner) RunDaemon2(command string) (*exec.Cmd, *bufio.Reader, *bufio.Reader) {
commandArr := strings.Split(command, " ")
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, commandArr...)
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
m.T.Fatalf("stdout pipe failed: %s %v", command, err)
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
m.T.Fatalf("stderr pipe failed: %s %v", command, err)
}
err = cmd.Start()
if err != nil {
m.T.Fatalf("Error running command: %s %v", command, err)
}
return cmd, bufio.NewReader(stdoutPipe), bufio.NewReader(stderrPipe)
}
// SSH returns the output of running a command using SSH
func (m *MinikubeRunner) SSH(command string) (string, error) {
path, _ := filepath.Abs(m.BinaryPath)
cmd := exec.Command(path, "ssh", command)
Logf("SSH: %s", command)
stdout, err := cmd.CombinedOutput()
Logf("Output: %s", stdout)
if err, ok := err.(*exec.ExitError); ok {
return string(stdout), err
}
return string(stdout), nil
}
// Start starts the cluster
func (m *MinikubeRunner) Start(opts ...string) {
cmd := fmt.Sprintf("start %s %s %s --alsologtostderr --v=2", m.StartArgs, m.GlobalArgs, strings.Join(opts, " "))
m.RunCommand(cmd, true)
}
// EnsureRunning makes sure the container runtime is running
func (m *MinikubeRunner) EnsureRunning() {
if m.GetStatus() != "Running" {
m.Start()
}
m.CheckStatus("Running")
}
// ParseEnvCmdOutput parses the output of `env` (assumes bash)
func (m *MinikubeRunner) ParseEnvCmdOutput(out string) map[string]string {
env := map[string]string{}
re := regexp.MustCompile(`(\w+?) ?= ?"?(.+?)"?\n`)
for _, m := range re.FindAllStringSubmatch(out, -1) {
env[m[1]] = m[2]
}
return env
}
// GetStatus returns the status of a service
func (m *MinikubeRunner) GetStatus() string {
return m.RunCommand(fmt.Sprintf("status --format={{.Host}} %s", m.GlobalArgs), false)
}
// GetLogs returns the logs of a service
func (m *MinikubeRunner) GetLogs() string {
return m.RunCommand(fmt.Sprintf("logs %s", m.GlobalArgs), true)
}
// CheckStatus makes sure the service has the desired status, or cause fatal error
func (m *MinikubeRunner) CheckStatus(desired string) {
if err := m.CheckStatusNoFail(desired); err != nil {
m.T.Fatalf("%v", err)
}
}
// CheckStatusNoFail makes sure the service has the desired status, returning error
func (m *MinikubeRunner) CheckStatusNoFail(desired string) error {
s := m.GetStatus()
if s != desired {
return fmt.Errorf("got state: %q, expected %q", s, desired)
}
return nil
}
// KubectlRunner runs a command using kubectl
type KubectlRunner struct {
T *testing.T
BinaryPath string
}
// NewKubectlRunner creates a new KubectlRunner
func NewKubectlRunner(t *testing.T) *KubectlRunner {
p, err := exec.LookPath(kubectlBinary)
if err != nil {
t.Fatalf("Couldn't find kubectl on path.")
}
return &KubectlRunner{BinaryPath: p, T: t}
}
// RunCommandParseOutput runs a command and parses the JSON output
func (k *KubectlRunner) RunCommandParseOutput(args []string, outputObj interface{}) error {
args = append(args, "-o=json")
output, err := k.RunCommand(args)
if err != nil {
return err
}
d := json.NewDecoder(bytes.NewReader(output))
if err := d.Decode(outputObj); err != nil {
return err
}
return nil
}
// RunCommand runs a command, returning stdout
func (k *KubectlRunner) RunCommand(args []string) (stdout []byte, err error) {
inner := func() error {
cmd := exec.Command(k.BinaryPath, args...)
stdout, err = cmd.CombinedOutput()
if err != nil {
retriable := &commonutil.RetriableError{Err: fmt.Errorf("error running command %s: %v. Stdout: \n %s", args, err, stdout)}
k.T.Log(retriable)
return retriable
}
return nil
}
err = commonutil.RetryAfter(3, inner, 2*time.Second)
return stdout, err
}
// CreateRandomNamespace creates a random namespace
func (k *KubectlRunner) CreateRandomNamespace() string {
const strLen = 20
name := genRandString(strLen)
if _, err := k.RunCommand([]string{"create", "namespace", name}); err != nil {
k.T.Fatalf("Error creating namespace: %v", err)
}
return name
}
func genRandString(strLen int) string {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
rand.Seed(time.Now().UTC().UnixNano())
result := make([]byte, strLen)
for i := 0; i < strLen; i++ {
result[i] = chars[rand.Intn(len(chars))]
}
return string(result)
}
// DeleteNamespace deletes the namespace
func (k *KubectlRunner) DeleteNamespace(namespace string) error {
_, err := k.RunCommand([]string{"delete", "namespace", namespace})
return err
}
// WaitForBusyboxRunning waits until busybox pod to be running
func WaitForBusyboxRunning(t *testing.T, namespace string) error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"integration-test": "busybox"}))
return commonutil.WaitForPodsWithLabelRunning(client, namespace, selector)
}
// WaitForIngressControllerRunning waits until ingress controller pod to be running
func WaitForIngressControllerRunning(t *testing.T) error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
if err := commonutil.WaitForDeploymentToStabilize(client, "kube-system", "nginx-ingress-controller", time.Minute*10); err != nil {
return errors.Wrap(err, "waiting for ingress-controller deployment to stabilize")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"app.kubernetes.io/name": "nginx-ingress-controller"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
return errors.Wrap(err, "waiting for ingress-controller pods")
}
return nil
}
// WaitForGvisorControllerRunning waits for the gvisor controller pod to be running
func WaitForGvisorControllerRunning(t *testing.T) error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"kubernetes.io/minikube-addons": "gvisor"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "kube-system", selector); err != nil {
return errors.Wrap(err, "waiting for gvisor controller pod to stabilize")
}
return nil
}
// WaitForGvisorControllerDeleted waits for the gvisor controller pod to be deleted
func WaitForGvisorControllerDeleted() error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"kubernetes.io/minikube-addons": "gvisor"}))
if err := commonutil.WaitForPodDelete(client, "kube-system", selector); err != nil {
return errors.Wrap(err, "waiting for gvisor controller pod deletion")
}
return nil
}
// WaitForUntrustedNginxRunning waits for the untrusted nginx pod to start running
func WaitForUntrustedNginxRunning() error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
return errors.Wrap(err, "waiting for nginx pods")
}
return nil
}
// WaitForFailedCreatePodSandBoxEvent waits for a FailedCreatePodSandBox event to appear
func WaitForFailedCreatePodSandBoxEvent() error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
if err := commonutil.WaitForEvent(client, "default", "FailedCreatePodSandBox"); err != nil {
return errors.Wrap(err, "waiting for FailedCreatePodSandBox event")
}
return nil
}
// WaitForNginxRunning waits for nginx service to be up
func WaitForNginxRunning(t *testing.T) error {
client, err := commonutil.GetClient()
if err != nil {
return errors.Wrap(err, "getting kubernetes client")
}
selector := labels.SelectorFromSet(labels.Set(map[string]string{"run": "nginx"}))
if err := commonutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil {
return errors.Wrap(err, "waiting for nginx pods")
}
if err := commonutil.WaitForService(client, "default", "nginx", true, time.Millisecond*500, time.Minute*10); err != nil {
t.Errorf("Error waiting for nginx service to be up")
}
return nil
}
// Retry tries the callback for a number of attempts, with a delay between attempts
func Retry(t *testing.T, callback func() error, d time.Duration, attempts int) (err error) {
for i := 0; i < attempts; i++ {
err = callback()
if err == nil {
return nil
}
time.Sleep(d)
}
return err
}

View File

@ -18,74 +18,77 @@ package integration
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
retryablehttp "github.com/hashicorp/go-retryablehttp"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/constants"
pkgutil "k8s.io/minikube/pkg/util"
"k8s.io/minikube/test/integration/util"
)
func downloadMinikubeBinary(version string) (*os.File, error) {
// Grab latest release binary
url := pkgutil.GetBinaryDownloadURL(version, runtime.GOOS)
resp, err := retryablehttp.Get(url)
if err != nil {
return nil, errors.Wrap(err, "Failed to get latest release binary")
}
defer resp.Body.Close()
tf, err := ioutil.TempFile("", "minikube")
if err != nil {
return nil, errors.Wrap(err, "Failed to create binary file")
}
_, err = io.Copy(tf, resp.Body)
if err != nil {
return nil, errors.Wrap(err, "Failed to populate temp file")
}
if err := tf.Close(); err != nil {
return nil, errors.Wrap(err, "Failed to close temp file")
}
if runtime.GOOS != "windows" {
if err := os.Chmod(tf.Name(), 0700); err != nil {
return nil, err
// t.Fatal(errors.Wrap(err, "Failed to make binary executable."))
func fileExists(fname string) error {
check := func() error {
info, err := os.Stat(fname)
if os.IsNotExist(err) {
return err
}
if info.IsDir() {
return fmt.Errorf("Error expect file got dir")
}
return nil
}
return tf, err
if err := util.Retry2(check, 1*time.Second, 3); err != nil {
return errors.Wrap(err, fmt.Sprintf("Failed check if file (%q) exists,", fname))
}
return nil
}
// TestVersionUpgrade downloads latest version of minikube and runs with
// the odlest supported k8s version and then runs the current head minikube
// and it tries to upgrade from the older supported k8s to news supported k8s
func TestVersionUpgrade(t *testing.T) {
currentRunner := NewMinikubeRunner(t)
currentRunner.RunCommand("delete", true)
currentRunner.CheckStatus(state.None.String())
tf, err := downloadMinikubeBinary("latest")
if err != nil || tf == nil {
t.Fatal(errors.Wrap(err, "Failed to download minikube binary."))
p := profileName(t)
if shouldRunInParallel(t) {
t.Parallel()
}
defer os.Remove(tf.Name())
// fname is the filename for the minikube's latetest binary. this file been pre-downloaded before test by hacks/jenkins/common.sh
fname := filepath.Join(*testdataDir, fmt.Sprintf("minikube-%s-%s-latest-stable", runtime.GOOS, runtime.GOARCH))
err := fileExists(fname)
if err != nil { // download file if it is not downloaded by other test
dest := filepath.Join(*testdataDir, fmt.Sprintf("minikube-%s-%s-latest-stable", runtime.GOOS, runtime.GOARCH))
err := downloadMinikubeBinary(t, dest, "latest")
if err != nil {
// binary is needed for the test
t.Fatalf("erorr downloading the latest minikube release %v", err)
}
}
defer os.Remove(fname)
releaseRunner := NewMinikubeRunner(t)
releaseRunner.BinaryPath = tf.Name()
mkCurrent := NewMinikubeRunner(t, p)
defer mkCurrent.TearDown(t)
mkRelease := NewMinikubeRunner(t, p)
mkRelease.BinaryPath = fname
// For full coverage: also test upgrading from oldest to newest supported k8s release
releaseRunner.Start(fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion))
releaseRunner.CheckStatus(state.Running.String())
releaseRunner.RunCommand("stop", true)
releaseRunner.CheckStatus(state.Stopped.String())
stdout, stderr, err := mkRelease.Start(fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion))
if err != nil {
t.Fatalf("TestVersionUpgrade minikube start failed : %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
}
mkRelease.CheckStatus(state.Running.String())
mkRelease.RunCommand("stop", true)
mkRelease.CheckStatus(state.Stopped.String())
// Trim the leading "v" prefix to assert that we handle it properly.
currentRunner.Start(fmt.Sprintf("--kubernetes-version=%s", strings.TrimPrefix(constants.NewestKubernetesVersion, "v")))
currentRunner.CheckStatus(state.Running.String())
currentRunner.RunCommand("delete", true)
currentRunner.CheckStatus(state.None.String())
stdout, stderr, err = mkCurrent.Start(fmt.Sprintf("--kubernetes-version=%s", strings.TrimPrefix(constants.NewestKubernetesVersion, "v")))
if err != nil {
t.Fatalf("TestVersionUpgrade mkCurrent.Start start failed : %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
}
mkCurrent.CheckStatus(state.Running.String())
}

View File

@ -16,6 +16,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// the name of this file starts with z intentionally to make it run last after all other tests
// the intent is to make sure os env proxy settings be done after all other tests.
// for example in the case the test proxy clean up gets killed or fails
package integration
import (
@ -66,20 +69,20 @@ func setUpProxy(t *testing.T) (*http.Server, error) {
func TestProxy(t *testing.T) {
origHP := os.Getenv("HTTP_PROXY")
origNP := os.Getenv("NO_PROXY")
p := profileName(t) // profile name
if isTestNoneDriver(t) {
// TODO fix this later
t.Skip("Skipping proxy warning for none")
}
srv, err := setUpProxy(t)
if err != nil {
t.Fatalf("Failed to set up the test proxy: %s", err)
}
// making sure there is no running minikube to avoid https://github.com/kubernetes/minikube/issues/4132
r := NewMinikubeRunner(t)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
_, _, err = r.RunWithContext(ctx, "delete")
if err != nil {
t.Logf("Error deleting minikube before test setup %s : ", err)
}
mk := NewMinikubeRunner(t, p)
// Clean up after setting up proxy
defer func(t *testing.T) {
err = os.Setenv("HTTP_PROXY", origHP)
@ -95,27 +98,23 @@ func TestProxy(t *testing.T) {
if err != nil {
t.Errorf("Error shutting down the http proxy")
}
_, _, err = r.RunWithContext(ctx, "delete")
if err != nil {
t.Logf("Error deleting minikube when cleaning up proxy setup: %s", err)
if !isTestNoneDriver(t) {
mk.TearDown(t)
}
}(t)
t.Run("Proxy Console Warnning", testProxyWarning)
t.Run("Proxy Dashboard", testProxyDashboard)
}(t)
t.Run("ProxyConsoleWarnning", testProxyWarning)
t.Run("ProxyDashboard", testProxyDashboard)
}
// testProxyWarning checks user is warned correctly about the proxy related env vars
func testProxyWarning(t *testing.T) {
r := NewMinikubeRunner(t, "--wait=false")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
startCmd := fmt.Sprintf("start %s %s", r.StartArgs, r.GlobalArgs)
stdout, stderr, err := r.RunWithContext(ctx, startCmd)
p := profileName(t) // profile name
mk := NewMinikubeRunner(t, p)
stdout, stderr, err := mk.Start()
if err != nil {
t.Fatalf("start: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
t.Fatalf("failed to start minikube (for profile %s) failed : %v\nstdout: %s\nstderr: %s", t.Name(), err, stdout, stderr)
}
msg := "Found network options:"
@ -131,7 +130,8 @@ func testProxyWarning(t *testing.T) {
// testProxyDashboard checks if dashboard URL is accessible if proxy is set
func testProxyDashboard(t *testing.T) {
mk := NewMinikubeRunner(t, "--wait=false")
p := profileName(t) // profile name
mk := NewMinikubeRunner(t, p)
cmd, out := mk.RunDaemon("dashboard --url")
defer func() {
err := cmd.Process.Kill()