diff --git a/glide.lock b/glide.lock index 210531561003..72160adb5d76 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: df63691eefa0455af08310071c1457c268b7d58f2ceb813c0c29d06ec75a5d3d -updated: 2018-07-06T14:12:33.305926721-04:00 +updated: 2018-07-10T18:57:34.965135398-04:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -599,9 +599,9 @@ imports: - pagination - testhelper - name: github.com/gorilla/context - version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 + version: 14f550f51af52180c2eefed15e5fd18d63c0a64a - name: github.com/gorilla/mux - version: cb4698366aa625048f3b815af6a0dea8aef9280a + version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf - name: github.com/gorilla/securecookie version: 78f3d318a8bf316cda921f25e96fd0b441c5173d - name: github.com/gorilla/sessions @@ -809,7 +809,7 @@ imports: - go-selinux - go-selinux/label - name: github.com/openshift/api - version: 95626b0211df2ed778b4d68c3e9e61138677d315 + version: 04a26bf3b8d69c390642c5803fe4cfdb899112aa subpackages: - apps/v1 - authorization/v1 @@ -831,7 +831,7 @@ imports: - user/v1 - webconsole/v1 - name: github.com/openshift/client-go - version: 4688ad28de2e88110c0ea30179c51b9b205f99be + version: b22949ca0eae046da7611d0d20c8089dcec212d6 subpackages: - apps/clientset/versioned - apps/clientset/versioned/scheme @@ -938,7 +938,7 @@ imports: - user/informers/externalversions/user/v1 - user/listers/user/v1 - name: github.com/openshift/imagebuilder - version: 4670fc31fca6121da0dcf42d6b9b298479c1715a + version: bfc0aea02ce95dcfc1a83d452270dbc66933709b subpackages: - dockerclient - imageprogress @@ -957,7 +957,7 @@ imports: - pkg/operator/resource/resourcemerge - pkg/serviceability - name: github.com/openshift/service-serving-cert-signer - version: 4e91b73f7394df0fffb885c35ac9b517cc385d2e + version: 10d530a76d1e98ae342df2fa5a3cbefd5dc3f241 subpackages: - pkg/controller/servingcert - pkg/controller/servingcert/cryptoextensions @@ -1827,7 +1827,7 @@ imports: - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: 5200705703cbf4abe250da3822f67e244e11d5b0 + version: aebe0498deb85f935a0126a4859b2a7610bd69c5 repo: https://github.com/openshift/kubernetes.git subpackages: - cmd/controller-manager/app diff --git a/vendor/github.com/gorilla/context/.travis.yml b/vendor/github.com/gorilla/context/.travis.yml index 6f440f1e42d3..d87d46576867 100644 --- a/vendor/github.com/gorilla/context/.travis.yml +++ b/vendor/github.com/gorilla/context/.travis.yml @@ -1,19 +1,7 @@ language: go -sudo: false -matrix: - include: - - go: 1.3 - - go: 1.4 - - go: 1.5 - - go: 1.6 - - go: 1.7 - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... +go: + - 1.0 + - 1.1 + - 1.2 + - tip diff --git a/vendor/github.com/gorilla/context/README.md b/vendor/github.com/gorilla/context/README.md index 08f86693bcd8..c60a31b053bc 100644 --- a/vendor/github.com/gorilla/context/README.md +++ b/vendor/github.com/gorilla/context/README.md @@ -4,7 +4,4 @@ context gorilla/context is a general purpose registry for global request variables. -> Note: gorilla/context, having been born well before `context.Context` existed, does not play well -> with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`. - Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/vendor/github.com/gorilla/context/context_test.go b/vendor/github.com/gorilla/context/context_test.go index d70e91a239ff..6ada8ec31f6c 100644 --- a/vendor/github.com/gorilla/context/context_test.go +++ b/vendor/github.com/gorilla/context/context_test.go @@ -69,7 +69,7 @@ func TestContext(t *testing.T) { // GetAllOk() for empty request values, ok = GetAllOk(emptyR) - assertEqual(len(values), 0) + assertEqual(value, nil) assertEqual(ok, false) // Delete() @@ -98,7 +98,7 @@ func parallelReader(r *http.Request, key string, iterations int, wait, done chan func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) { <-wait for i := 0; i < iterations; i++ { - Set(r, key, value) + Get(r, key) } done <- struct{}{} diff --git a/vendor/github.com/gorilla/context/doc.go b/vendor/github.com/gorilla/context/doc.go index 448d1bfcac6e..73c7400311e1 100644 --- a/vendor/github.com/gorilla/context/doc.go +++ b/vendor/github.com/gorilla/context/doc.go @@ -5,12 +5,6 @@ /* Package context stores values shared during a request lifetime. -Note: gorilla/context, having been born well before `context.Context` existed, -does not play well > with the shallow copying of the request that -[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) -(added to net/http Go 1.7 onwards) performs. You should either use *just* -gorilla/context, or moving forward, the new `http.Request.Context()`. - For example, a router can set variables extracted from the URL and later application handlers can access those values, or it can be used to store sessions values to be saved at the end of a request. There are several diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml index ad0935dbd376..d87d46576867 100644 --- a/vendor/github.com/gorilla/mux/.travis.yml +++ b/vendor/github.com/gorilla/mux/.travis.yml @@ -1,23 +1,7 @@ language: go -sudo: false -matrix: - include: - - go: 1.5.x - - go: 1.6.x - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: tip - allow_failures: - - go: tip - -install: - - # Skip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go tool vet . - - go test -v -race ./... +go: + - 1.0 + - 1.1 + - 1.2 + - tip diff --git a/vendor/github.com/gorilla/mux/AUTHORS b/vendor/github.com/gorilla/mux/AUTHORS deleted file mode 100644 index b722392ee592..000000000000 --- a/vendor/github.com/gorilla/mux/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -# This is the official list of gorilla/mux authors for copyright purposes. -# -# Please keep the list sorted. - -Google LLC (https://opensource.google.com/) -Kamil Kisielk -Matt Silverlock -Rodrigo Moraes (https://github.com/moraes) diff --git a/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md b/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md deleted file mode 100644 index 232be82e47a6..000000000000 --- a/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,11 +0,0 @@ -**What version of Go are you running?** (Paste the output of `go version`) - - -**What version of gorilla/mux are you at?** (Paste the output of `git rev-parse HEAD` inside `$GOPATH/src/github.com/gorilla/mux`) - - -**Describe your problem** (and what you have tried so far) - - -**Paste a minimal, runnable, reproduction of your issue below** (use backticks to format it) - diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE index 6903df6386e9..0e5fb872800d 100644 --- a/vendor/github.com/gorilla/mux/LICENSE +++ b/vendor/github.com/gorilla/mux/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. +Copyright (c) 2012 Rodrigo Moraes. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index e424397ac4d0..e60301b03363 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -1,649 +1,7 @@ -# gorilla/mux +mux +=== +[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux) -[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) -[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) +gorilla/mux is a powerful URL router and dispatcher. -![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png) - -http://www.gorillatoolkit.org/pkg/mux - -Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to -their respective handler. - -The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: - -* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. -* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. -* URL hosts, paths and query values can have variables with an optional regular expression. -* Registered URLs can be built, or "reversed", which helps maintaining references to resources. -* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching. - ---- - -* [Install](#install) -* [Examples](#examples) -* [Matching Routes](#matching-routes) -* [Static Files](#static-files) -* [Registered URLs](#registered-urls) -* [Walking Routes](#walking-routes) -* [Graceful Shutdown](#graceful-shutdown) -* [Middleware](#middleware) -* [Testing Handlers](#testing-handlers) -* [Full Example](#full-example) - ---- - -## Install - -With a [correctly configured](https://golang.org/doc/install#testing) Go toolchain: - -```sh -go get -u github.com/gorilla/mux -``` - -## Examples - -Let's start registering a couple of URL paths and handlers: - -```go -func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) -} -``` - -Here we register three routes mapping URL paths to handlers. This is equivalent to how `http.HandleFunc()` works: if an incoming request URL matches one of the paths, the corresponding handler is called passing (`http.ResponseWriter`, `*http.Request`) as parameters. - -Paths can have variables. They are defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. For example: - -```go -r := mux.NewRouter() -r.HandleFunc("/products/{key}", ProductHandler) -r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) -r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) -``` - -The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: - -```go -func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, "Category: %v\n", vars["category"]) -} -``` - -And this is all you need to know about the basic usage. More advanced options are explained below. - -### Matching Routes - -Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: - -```go -r := mux.NewRouter() -// Only matches if domain is "www.example.com". -r.Host("www.example.com") -// Matches a dynamic subdomain. -r.Host("{subdomain:[a-z]+}.domain.com") -``` - -There are several other matchers that can be added. To match path prefixes: - -```go -r.PathPrefix("/products/") -``` - -...or HTTP methods: - -```go -r.Methods("GET", "POST") -``` - -...or URL schemes: - -```go -r.Schemes("https") -``` - -...or header values: - -```go -r.Headers("X-Requested-With", "XMLHttpRequest") -``` - -...or query values: - -```go -r.Queries("key", "value") -``` - -...or to use a custom matcher function: - -```go -r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 -}) -``` - -...and finally, it is possible to combine several matchers in a single route: - -```go -r.HandleFunc("/products", ProductsHandler). - Host("www.example.com"). - Methods("GET"). - Schemes("http") -``` - -Routes are tested in the order they were added to the router. If two routes match, the first one wins: - -```go -r := mux.NewRouter() -r.HandleFunc("/specific", specificHandler) -r.PathPrefix("/").Handler(catchAllHandler) -``` - -Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". - -For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: - -```go -r := mux.NewRouter() -s := r.Host("www.example.com").Subrouter() -``` - -Then register routes in the subrouter: - -```go -s.HandleFunc("/products/", ProductsHandler) -s.HandleFunc("/products/{key}", ProductHandler) -s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) -``` - -The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. - -Subrouters can be used to create domain or path "namespaces": you define subrouters in a central place and then parts of the app can register its paths relatively to a given subrouter. - -There's one more thing about subroutes. When a subrouter has a path prefix, the inner routes use it as base for their paths: - -```go -r := mux.NewRouter() -s := r.PathPrefix("/products").Subrouter() -// "/products/" -s.HandleFunc("/", ProductsHandler) -// "/products/{key}/" -s.HandleFunc("/{key}/", ProductHandler) -// "/products/{key}/details" -s.HandleFunc("/{key}/details", ProductDetailsHandler) -``` - - -### Static Files - -Note that the path provided to `PathPrefix()` represents a "wildcard": calling -`PathPrefix("/static/").Handler(...)` means that the handler will be passed any -request that matches "/static/\*". This makes it easy to serve static files with mux: - -```go -func main() { - var dir string - - flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") - flag.Parse() - r := mux.NewRouter() - - // This will serve files under http://localhost:8000/static/ - r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) - - srv := &http.Server{ - Handler: r, - Addr: "127.0.0.1:8000", - // Good practice: enforce timeouts for servers you create! - WriteTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - } - - log.Fatal(srv.ListenAndServe()) -} -``` - -### Registered URLs - -Now let's see how to build registered URLs. - -Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example: - -```go -r := mux.NewRouter() -r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). - Name("article") -``` - -To build a URL, get the route and call the `URL()` method, passing a sequence of key/value pairs for the route variables. For the previous route, we would do: - -```go -url, err := r.Get("article").URL("category", "technology", "id", "42") -``` - -...and the result will be a `url.URL` with the following path: - -``` -"/articles/technology/42" -``` - -This also works for host and query value variables: - -```go -r := mux.NewRouter() -r.Host("{subdomain}.domain.com"). - Path("/articles/{category}/{id:[0-9]+}"). - Queries("filter", "{filter}"). - HandlerFunc(ArticleHandler). - Name("article") - -// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" -url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42", - "filter", "gorilla") -``` - -All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. - -Regex support also exists for matching Headers within a route. For example, we could do: - -```go -r.HeadersRegexp("Content-Type", "application/(text|json)") -``` - -...and the route will match both requests with a Content-Type of `application/json` as well as `application/text` - -There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: - -```go -// "http://news.domain.com/" -host, err := r.Get("article").URLHost("subdomain", "news") - -// "/articles/technology/42" -path, err := r.Get("article").URLPath("category", "technology", "id", "42") -``` - -And if you use subrouters, host and path defined separately can be built as well: - -```go -r := mux.NewRouter() -s := r.Host("{subdomain}.domain.com").Subrouter() -s.Path("/articles/{category}/{id:[0-9]+}"). - HandlerFunc(ArticleHandler). - Name("article") - -// "http://news.domain.com/articles/technology/42" -url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") -``` - -### Walking Routes - -The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example, -the following prints all of the registered routes: - -```go -package main - -import ( - "fmt" - "net/http" - "strings" - - "github.com/gorilla/mux" -) - -func handler(w http.ResponseWriter, r *http.Request) { - return -} - -func main() { - r := mux.NewRouter() - r.HandleFunc("/", handler) - r.HandleFunc("/products", handler).Methods("POST") - r.HandleFunc("/articles", handler).Methods("GET") - r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") - r.HandleFunc("/authors", handler).Queries("surname", "{surname}") - err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { - pathTemplate, err := route.GetPathTemplate() - if err == nil { - fmt.Println("ROUTE:", pathTemplate) - } - pathRegexp, err := route.GetPathRegexp() - if err == nil { - fmt.Println("Path regexp:", pathRegexp) - } - queriesTemplates, err := route.GetQueriesTemplates() - if err == nil { - fmt.Println("Queries templates:", strings.Join(queriesTemplates, ",")) - } - queriesRegexps, err := route.GetQueriesRegexp() - if err == nil { - fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ",")) - } - methods, err := route.GetMethods() - if err == nil { - fmt.Println("Methods:", strings.Join(methods, ",")) - } - fmt.Println() - return nil - }) - - if err != nil { - fmt.Println(err) - } - - http.Handle("/", r) -} -``` - -### Graceful Shutdown - -Go 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`: - -```go -package main - -import ( - "context" - "flag" - "log" - "net/http" - "os" - "os/signal" - "time" - - "github.com/gorilla/mux" -) - -func main() { - var wait time.Duration - flag.DurationVar(&wait, "graceful-timeout", time.Second * 15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m") - flag.Parse() - - r := mux.NewRouter() - // Add your routes as needed - - srv := &http.Server{ - Addr: "0.0.0.0:8080", - // Good practice to set timeouts to avoid Slowloris attacks. - WriteTimeout: time.Second * 15, - ReadTimeout: time.Second * 15, - IdleTimeout: time.Second * 60, - Handler: r, // Pass our instance of gorilla/mux in. - } - - // Run our server in a goroutine so that it doesn't block. - go func() { - if err := srv.ListenAndServe(); err != nil { - log.Println(err) - } - }() - - c := make(chan os.Signal, 1) - // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) - // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. - signal.Notify(c, os.Interrupt) - - // Block until we receive our signal. - <-c - - // Create a deadline to wait for. - ctx, cancel := context.WithTimeout(context.Background(), wait) - defer cancel() - // Doesn't block if no connections, but will otherwise wait - // until the timeout deadline. - srv.Shutdown(ctx) - // Optionally, you could run srv.Shutdown in a goroutine and block on - // <-ctx.Done() if your application should wait for other services - // to finalize based on context cancellation. - log.Println("shutting down") - os.Exit(0) -} -``` - -### Middleware - -Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters. -Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking. - -Mux middlewares are defined using the de facto standard type: - -```go -type MiddlewareFunc func(http.Handler) http.Handler -``` - -Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers. - -A very basic middleware which logs the URI of the request being handled could be written as: - -```go -func loggingMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Do stuff here - log.Println(r.RequestURI) - // Call the next handler, which can be another middleware in the chain, or the final handler. - next.ServeHTTP(w, r) - }) -} -``` - -Middlewares can be added to a router using `Router.Use()`: - -```go -r := mux.NewRouter() -r.HandleFunc("/", handler) -r.Use(loggingMiddleware) -``` - -A more complex authentication middleware, which maps session token to users, could be written as: - -```go -// Define our struct -type authenticationMiddleware struct { - tokenUsers map[string]string -} - -// Initialize it somewhere -func (amw *authenticationMiddleware) Populate() { - amw.tokenUsers["00000000"] = "user0" - amw.tokenUsers["aaaaaaaa"] = "userA" - amw.tokenUsers["05f717e5"] = "randomUser" - amw.tokenUsers["deadbeef"] = "user0" -} - -// Middleware function, which will be called for each request -func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - token := r.Header.Get("X-Session-Token") - - if user, found := amw.tokenUsers[token]; found { - // We found the token in our map - log.Printf("Authenticated user %s\n", user) - // Pass down the request to the next middleware (or final handler) - next.ServeHTTP(w, r) - } else { - // Write an error and stop the handler chain - http.Error(w, "Forbidden", http.StatusForbidden) - } - }) -} -``` - -```go -r := mux.NewRouter() -r.HandleFunc("/", handler) - -amw := authenticationMiddleware{} -amw.Populate() - -r.Use(amw.Middleware) -``` - -Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. - -### Testing Handlers - -Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. - -First, our simple HTTP handler: - -```go -// endpoints.go -package main - -func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { - // A very simple health check. - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - - // In the future we could report back on the status of our DB, or our cache - // (e.g. Redis) by performing a simple PING, and include them in the response. - io.WriteString(w, `{"alive": true}`) -} - -func main() { - r := mux.NewRouter() - r.HandleFunc("/health", HealthCheckHandler) - - log.Fatal(http.ListenAndServe("localhost:8080", r)) -} -``` - -Our test code: - -```go -// endpoints_test.go -package main - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestHealthCheckHandler(t *testing.T) { - // Create a request to pass to our handler. We don't have any query parameters for now, so we'll - // pass 'nil' as the third parameter. - req, err := http.NewRequest("GET", "/health", nil) - if err != nil { - t.Fatal(err) - } - - // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. - rr := httptest.NewRecorder() - handler := http.HandlerFunc(HealthCheckHandler) - - // Our handlers satisfy http.Handler, so we can call their ServeHTTP method - // directly and pass in our Request and ResponseRecorder. - handler.ServeHTTP(rr, req) - - // Check the status code is what we expect. - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", - status, http.StatusOK) - } - - // Check the response body is what we expect. - expected := `{"alive": true}` - if rr.Body.String() != expected { - t.Errorf("handler returned unexpected body: got %v want %v", - rr.Body.String(), expected) - } -} -``` - -In the case that our routes have [variables](#examples), we can pass those in the request. We could write -[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple -possible route variables as needed. - -```go -// endpoints.go -func main() { - r := mux.NewRouter() - // A route with a route variable: - r.HandleFunc("/metrics/{type}", MetricsHandler) - - log.Fatal(http.ListenAndServe("localhost:8080", r)) -} -``` - -Our test file, with a table-driven test of `routeVariables`: - -```go -// endpoints_test.go -func TestMetricsHandler(t *testing.T) { - tt := []struct{ - routeVariable string - shouldPass bool - }{ - {"goroutines", true}, - {"heap", true}, - {"counters", true}, - {"queries", true}, - {"adhadaeqm3k", false}, - } - - for _, tc := range tt { - path := fmt.Sprintf("/metrics/%s", tc.routeVariable) - req, err := http.NewRequest("GET", path, nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - - // Need to create a router that we can pass the request through so that the vars will be added to the context - router := mux.NewRouter() - router.HandleFunc("/metrics/{type}", MetricsHandler) - router.ServeHTTP(rr, req) - - // In this case, our MetricsHandler returns a non-200 response - // for a route variable it doesn't know about. - if rr.Code == http.StatusOK && !tc.shouldPass { - t.Errorf("handler should have failed on routeVariable %s: got %v want %v", - tc.routeVariable, rr.Code, http.StatusOK) - } - } -} -``` - -## Full Example - -Here's a complete, runnable example of a small `mux` based server: - -```go -package main - -import ( - "net/http" - "log" - "github.com/gorilla/mux" -) - -func YourHandler(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Gorilla!\n")) -} - -func main() { - r := mux.NewRouter() - // Routes consist of a path and a handler function. - r.HandleFunc("/", YourHandler) - - // Bind to a port and pass our router in - log.Fatal(http.ListenAndServe(":8000", r)) -} -``` - -## License - -BSD licensed. See the LICENSE file for details. +Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux diff --git a/vendor/github.com/gorilla/mux/bench_test.go b/vendor/github.com/gorilla/mux/bench_test.go index 522156dccff2..c5f97b2b2a80 100644 --- a/vendor/github.com/gorilla/mux/bench_test.go +++ b/vendor/github.com/gorilla/mux/bench_test.go @@ -6,7 +6,6 @@ package mux import ( "net/http" - "net/http/httptest" "testing" ) @@ -20,30 +19,3 @@ func BenchmarkMux(b *testing.B) { router.ServeHTTP(nil, request) } } - -func BenchmarkMuxAlternativeInRegexp(b *testing.B) { - router := new(Router) - handler := func(w http.ResponseWriter, r *http.Request) {} - router.HandleFunc("/v1/{v1:(?:a|b)}", handler) - - requestA, _ := http.NewRequest("GET", "/v1/a", nil) - requestB, _ := http.NewRequest("GET", "/v1/b", nil) - for i := 0; i < b.N; i++ { - router.ServeHTTP(nil, requestA) - router.ServeHTTP(nil, requestB) - } -} - -func BenchmarkManyPathVariables(b *testing.B) { - router := new(Router) - handler := func(w http.ResponseWriter, r *http.Request) {} - router.HandleFunc("/v1/{v1}/{v2}/{v3}/{v4}/{v5}", handler) - - matchingRequest, _ := http.NewRequest("GET", "/v1/1/2/3/4/5", nil) - notMatchingRequest, _ := http.NewRequest("GET", "/v1/1/2/3/4", nil) - recorder := httptest.NewRecorder() - for i := 0; i < b.N; i++ { - router.ServeHTTP(nil, matchingRequest) - router.ServeHTTP(recorder, notMatchingRequest) - } -} diff --git a/vendor/github.com/gorilla/mux/context_gorilla.go b/vendor/github.com/gorilla/mux/context_gorilla.go deleted file mode 100644 index d7adaa8fad4f..000000000000 --- a/vendor/github.com/gorilla/mux/context_gorilla.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -package mux - -import ( - "net/http" - - "github.com/gorilla/context" -) - -func contextGet(r *http.Request, key interface{}) interface{} { - return context.Get(r, key) -} - -func contextSet(r *http.Request, key, val interface{}) *http.Request { - if val == nil { - return r - } - - context.Set(r, key, val) - return r -} - -func contextClear(r *http.Request) { - context.Clear(r) -} diff --git a/vendor/github.com/gorilla/mux/context_gorilla_test.go b/vendor/github.com/gorilla/mux/context_gorilla_test.go deleted file mode 100644 index ffaf384c0441..000000000000 --- a/vendor/github.com/gorilla/mux/context_gorilla_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build !go1.7 - -package mux - -import ( - "net/http" - "testing" - - "github.com/gorilla/context" -) - -// Tests that the context is cleared or not cleared properly depending on -// the configuration of the router -func TestKeepContext(t *testing.T) { - func1 := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.HandleFunc("/", func1).Name("func1") - - req, _ := http.NewRequest("GET", "http://localhost/", nil) - context.Set(req, "t", 1) - - res := new(http.ResponseWriter) - r.ServeHTTP(*res, req) - - if _, ok := context.GetOk(req, "t"); ok { - t.Error("Context should have been cleared at end of request") - } - - r.KeepContext = true - - req, _ = http.NewRequest("GET", "http://localhost/", nil) - context.Set(req, "t", 1) - - r.ServeHTTP(*res, req) - if _, ok := context.GetOk(req, "t"); !ok { - t.Error("Context should NOT have been cleared at end of request") - } - -} diff --git a/vendor/github.com/gorilla/mux/context_native.go b/vendor/github.com/gorilla/mux/context_native.go deleted file mode 100644 index 209cbea7d661..000000000000 --- a/vendor/github.com/gorilla/mux/context_native.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build go1.7 - -package mux - -import ( - "context" - "net/http" -) - -func contextGet(r *http.Request, key interface{}) interface{} { - return r.Context().Value(key) -} - -func contextSet(r *http.Request, key, val interface{}) *http.Request { - if val == nil { - return r - } - - return r.WithContext(context.WithValue(r.Context(), key, val)) -} - -func contextClear(r *http.Request) { - return -} diff --git a/vendor/github.com/gorilla/mux/context_native_test.go b/vendor/github.com/gorilla/mux/context_native_test.go deleted file mode 100644 index c150edf0166f..000000000000 --- a/vendor/github.com/gorilla/mux/context_native_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// +build go1.7 - -package mux - -import ( - "context" - "net/http" - "testing" - "time" -) - -func TestNativeContextMiddleware(t *testing.T) { - withTimeout := func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx, cancel := context.WithTimeout(r.Context(), time.Minute) - defer cancel() - h.ServeHTTP(w, r.WithContext(ctx)) - }) - } - - r := NewRouter() - r.Handle("/path/{foo}", withTimeout(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - vars := Vars(r) - if vars["foo"] != "bar" { - t.Fatal("Expected foo var to be set") - } - }))) - - rec := NewRecorder() - req := newRequest("GET", "/path/bar") - r.ServeHTTP(rec, req) -} diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index 38957deead3d..b2deed34c47f 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. /* -Package mux implements a request router and dispatcher. +Package gorilla/mux implements a request router and dispatcher. The name mux stands for "HTTP request multiplexer". Like the standard http.ServeMux, mux.Router matches incoming requests against a list of @@ -12,8 +12,8 @@ or other conditions. The main features are: * Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. - * URL hosts, paths and query values can have variables with an optional - regular expression. + * URL hosts and paths can have variables with an optional regular + expression. * Registered URLs can be built, or "reversed", which helps maintaining references to resources. * Routes can be used as subrouters: nested routes are only tested if the @@ -47,21 +47,12 @@ variable will be anything until the next slash. For example: r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) -Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: - - r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) - The names are used to create a map of route variables which can be retrieved calling mux.Vars(): vars := mux.Vars(request) category := vars["category"] -Note that if any capturing groups are present, mux will panic() during parsing. To prevent -this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to -"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably -when capturing groups were present. - And this is all you need to know about the basic usage. More advanced options are explained below. @@ -69,8 +60,8 @@ Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: r := mux.NewRouter() - // Only matches if domain is "www.example.com". - r.Host("www.example.com") + // Only matches if domain is "www.domain.com". + r.Host("www.domain.com") // Matches a dynamic subdomain. r.Host("{subdomain:[a-z]+}.domain.com") @@ -98,12 +89,12 @@ There are several other matchers that can be added. To match path prefixes: r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { return r.ProtoMajor == 0 - }) + }) ...and finally, it is possible to combine several matchers in a single route: r.HandleFunc("/products", ProductsHandler). - Host("www.example.com"). + Host("www.domain.com"). Methods("GET"). Schemes("http") @@ -112,11 +103,11 @@ a way to group several routes that share the same requirements. We call it "subrouting". For example, let's say we have several URLs that should only match when the -host is "www.example.com". Create a route for that host and get a "subrouter" +host is "www.domain.com". Create a route for that host and get a "subrouter" from it: r := mux.NewRouter() - s := r.Host("www.example.com").Subrouter() + s := r.Host("www.domain.com").Subrouter() Then register routes in the subrouter: @@ -125,7 +116,7 @@ Then register routes in the subrouter: s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) The three URL paths we registered above will only be tested if the domain is -"www.example.com", because the subrouter is tested first. This is not +"www.domain.com", because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. @@ -145,31 +136,6 @@ the inner routes use it as base for their paths: // "/products/{key}/details" s.HandleFunc("/{key}/details", ProductDetailsHandler) -Note that the path provided to PathPrefix() represents a "wildcard": calling -PathPrefix("/static/").Handler(...) means that the handler will be passed any -request that matches "/static/*". This makes it easy to serve static files with mux: - - func main() { - var dir string - - flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") - flag.Parse() - r := mux.NewRouter() - - // This will serve files under http://localhost:8000/static/ - r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) - - srv := &http.Server{ - Handler: r, - Addr: "127.0.0.1:8000", - // Good practice: enforce timeouts for servers you create! - WriteTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - } - - log.Fatal(srv.ListenAndServe()) - } - Now let's see how to build registered URLs. Routes can be named. All routes that define a name can have their URLs built, @@ -188,33 +154,24 @@ key/value pairs for the route variables. For the previous route, we would do: "/articles/technology/42" -This also works for host and query value variables: +This also works for host variables: r := mux.NewRouter() r.Host("{subdomain}.domain.com"). Path("/articles/{category}/{id:[0-9]+}"). - Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") - // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" + // url.String() will be "http://news.domain.com/articles/technology/42" url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42", - "filter", "gorilla") + "category", "technology", + "id", "42") All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. -Regex support also exists for matching Headers within a route. For example, we could do: - - r.HeadersRegexp("Content-Type", "application/(text|json)") - -...and the route will match both requests with a Content-Type of `application/json` as well as -`application/text` - There's also a way to build only the URL host or path for a route: use the methods URLHost() or URLPath() instead. For the previous route, we would do: @@ -236,71 +193,7 @@ as well: // "http://news.domain.com/articles/technology/42" url, err := r.Get("article").URL("subdomain", "news", - "category", "technology", - "id", "42") - -Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking. - - type MiddlewareFunc func(http.Handler) http.Handler - -Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). - -A very basic middleware which logs the URI of the request being handled could be written as: - - func simpleMw(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Do stuff here - log.Println(r.RequestURI) - // Call the next handler, which can be another middleware in the chain, or the final handler. - next.ServeHTTP(w, r) - }) - } - -Middlewares can be added to a router using `Router.Use()`: - - r := mux.NewRouter() - r.HandleFunc("/", handler) - r.Use(simpleMw) - -A more complex authentication middleware, which maps session token to users, could be written as: - - // Define our struct - type authenticationMiddleware struct { - tokenUsers map[string]string - } - - // Initialize it somewhere - func (amw *authenticationMiddleware) Populate() { - amw.tokenUsers["00000000"] = "user0" - amw.tokenUsers["aaaaaaaa"] = "userA" - amw.tokenUsers["05f717e5"] = "randomUser" - amw.tokenUsers["deadbeef"] = "user0" - } - - // Middleware function, which will be called for each request - func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - token := r.Header.Get("X-Session-Token") - - if user, found := amw.tokenUsers[token]; found { - // We found the token in our map - log.Printf("Authenticated user %s\n", user) - next.ServeHTTP(w, r) - } else { - http.Error(w, "Forbidden", http.StatusForbidden) - } - }) - } - - r := mux.NewRouter() - r.HandleFunc("/", handler) - - amw := authenticationMiddleware{} - amw.Populate() - - r.Use(amw.Middleware) - -Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. - + "category", "technology", + "id", "42") */ package mux diff --git a/vendor/github.com/gorilla/mux/example_authentication_middleware_test.go b/vendor/github.com/gorilla/mux/example_authentication_middleware_test.go deleted file mode 100644 index 6f2ea86ca708..000000000000 --- a/vendor/github.com/gorilla/mux/example_authentication_middleware_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package mux_test - -import ( - "log" - "net/http" - - "github.com/gorilla/mux" -) - -// Define our struct -type authenticationMiddleware struct { - tokenUsers map[string]string -} - -// Initialize it somewhere -func (amw *authenticationMiddleware) Populate() { - amw.tokenUsers["00000000"] = "user0" - amw.tokenUsers["aaaaaaaa"] = "userA" - amw.tokenUsers["05f717e5"] = "randomUser" - amw.tokenUsers["deadbeef"] = "user0" -} - -// Middleware function, which will be called for each request -func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - token := r.Header.Get("X-Session-Token") - - if user, found := amw.tokenUsers[token]; found { - // We found the token in our map - log.Printf("Authenticated user %s\n", user) - next.ServeHTTP(w, r) - } else { - http.Error(w, "Forbidden", http.StatusForbidden) - } - }) -} - -func Example_authenticationMiddleware() { - r := mux.NewRouter() - r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - // Do something here - }) - amw := authenticationMiddleware{make(map[string]string)} - amw.Populate() - r.Use(amw.Middleware) -} diff --git a/vendor/github.com/gorilla/mux/example_route_test.go b/vendor/github.com/gorilla/mux/example_route_test.go deleted file mode 100644 index 1125570713e6..000000000000 --- a/vendor/github.com/gorilla/mux/example_route_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package mux_test - -import ( - "fmt" - "net/http" - - "github.com/gorilla/mux" -) - -// This example demonstrates setting a regular expression matcher for -// the header value. A plain word will match any value that contains a -// matching substring as if the pattern was wrapped with `.*`. -func ExampleRoute_HeadersRegexp() { - r := mux.NewRouter() - route := r.NewRoute().HeadersRegexp("Accept", "html") - - req1, _ := http.NewRequest("GET", "example.com", nil) - req1.Header.Add("Accept", "text/plain") - req1.Header.Add("Accept", "text/html") - - req2, _ := http.NewRequest("GET", "example.com", nil) - req2.Header.Set("Accept", "application/xhtml+xml") - - matchInfo := &mux.RouteMatch{} - fmt.Printf("Match: %v %q\n", route.Match(req1, matchInfo), req1.Header["Accept"]) - fmt.Printf("Match: %v %q\n", route.Match(req2, matchInfo), req2.Header["Accept"]) - // Output: - // Match: true ["text/plain" "text/html"] - // Match: true ["application/xhtml+xml"] -} - -// This example demonstrates setting a strict regular expression matcher -// for the header value. Using the start and end of string anchors, the -// value must be an exact match. -func ExampleRoute_HeadersRegexp_exactMatch() { - r := mux.NewRouter() - route := r.NewRoute().HeadersRegexp("Origin", "^https://example.co$") - - yes, _ := http.NewRequest("GET", "example.co", nil) - yes.Header.Set("Origin", "https://example.co") - - no, _ := http.NewRequest("GET", "example.co.uk", nil) - no.Header.Set("Origin", "https://example.co.uk") - - matchInfo := &mux.RouteMatch{} - fmt.Printf("Match: %v %q\n", route.Match(yes, matchInfo), yes.Header["Origin"]) - fmt.Printf("Match: %v %q\n", route.Match(no, matchInfo), no.Header["Origin"]) - // Output: - // Match: true ["https://example.co"] - // Match: false ["https://example.co.uk"] -} diff --git a/vendor/github.com/gorilla/mux/go.mod b/vendor/github.com/gorilla/mux/go.mod deleted file mode 100644 index cfc8ede5818b..000000000000 --- a/vendor/github.com/gorilla/mux/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/gorilla/mux diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go deleted file mode 100644 index ceb812cee284..000000000000 --- a/vendor/github.com/gorilla/mux/middleware.go +++ /dev/null @@ -1,72 +0,0 @@ -package mux - -import ( - "net/http" - "strings" -) - -// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. -// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed -// to it, and then calls the handler passed as parameter to the MiddlewareFunc. -type MiddlewareFunc func(http.Handler) http.Handler - -// middleware interface is anything which implements a MiddlewareFunc named Middleware. -type middleware interface { - Middleware(handler http.Handler) http.Handler -} - -// Middleware allows MiddlewareFunc to implement the middleware interface. -func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { - return mw(handler) -} - -// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. -func (r *Router) Use(mwf ...MiddlewareFunc) { - for _, fn := range mwf { - r.middlewares = append(r.middlewares, fn) - } -} - -// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. -func (r *Router) useInterface(mw middleware) { - r.middlewares = append(r.middlewares, mw) -} - -// CORSMethodMiddleware sets the Access-Control-Allow-Methods response header -// on a request, by matching routes based only on paths. It also handles -// OPTIONS requests, by settings Access-Control-Allow-Methods, and then -// returning without calling the next http handler. -func CORSMethodMiddleware(r *Router) MiddlewareFunc { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var allMethods []string - - err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { - for _, m := range route.matchers { - if _, ok := m.(*routeRegexp); ok { - if m.Match(req, &RouteMatch{}) { - methods, err := route.GetMethods() - if err != nil { - return err - } - - allMethods = append(allMethods, methods...) - } - break - } - } - return nil - }) - - if err == nil { - w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ",")) - - if req.Method == "OPTIONS" { - return - } - } - - next.ServeHTTP(w, req) - }) - } -} diff --git a/vendor/github.com/gorilla/mux/middleware_test.go b/vendor/github.com/gorilla/mux/middleware_test.go deleted file mode 100644 index acf4e160b90f..000000000000 --- a/vendor/github.com/gorilla/mux/middleware_test.go +++ /dev/null @@ -1,377 +0,0 @@ -package mux - -import ( - "bytes" - "net/http" - "net/http/httptest" - "testing" -) - -type testMiddleware struct { - timesCalled uint -} - -func (tm *testMiddleware) Middleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - tm.timesCalled++ - h.ServeHTTP(w, r) - }) -} - -func dummyHandler(w http.ResponseWriter, r *http.Request) {} - -func TestMiddlewareAdd(t *testing.T) { - router := NewRouter() - router.HandleFunc("/", dummyHandler).Methods("GET") - - mw := &testMiddleware{} - - router.useInterface(mw) - if len(router.middlewares) != 1 || router.middlewares[0] != mw { - t.Fatal("Middleware was not added correctly") - } - - router.Use(mw.Middleware) - if len(router.middlewares) != 2 { - t.Fatal("MiddlewareFunc method was not added correctly") - } - - banalMw := func(handler http.Handler) http.Handler { - return handler - } - router.Use(banalMw) - if len(router.middlewares) != 3 { - t.Fatal("MiddlewareFunc method was not added correctly") - } -} - -func TestMiddleware(t *testing.T) { - router := NewRouter() - router.HandleFunc("/", dummyHandler).Methods("GET") - - mw := &testMiddleware{} - router.useInterface(mw) - - rw := NewRecorder() - req := newRequest("GET", "/") - - // Test regular middleware call - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - // Middleware should not be called for 404 - req = newRequest("GET", "/not/found") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - // Middleware should not be called if there is a method mismatch - req = newRequest("POST", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - // Add the middleware again as function - router.Use(mw.Middleware) - req = newRequest("GET", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 3 { - t.Fatalf("Expected %d calls, but got only %d", 3, mw.timesCalled) - } - -} - -func TestMiddlewareSubrouter(t *testing.T) { - router := NewRouter() - router.HandleFunc("/", dummyHandler).Methods("GET") - - subrouter := router.PathPrefix("/sub").Subrouter() - subrouter.HandleFunc("/x", dummyHandler).Methods("GET") - - mw := &testMiddleware{} - subrouter.useInterface(mw) - - rw := NewRecorder() - req := newRequest("GET", "/") - - router.ServeHTTP(rw, req) - if mw.timesCalled != 0 { - t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) - } - - req = newRequest("GET", "/sub/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 0 { - t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) - } - - req = newRequest("GET", "/sub/x") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - req = newRequest("GET", "/sub/not/found") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - router.useInterface(mw) - - req = newRequest("GET", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 2 { - t.Fatalf("Expected %d calls, but got only %d", 2, mw.timesCalled) - } - - req = newRequest("GET", "/sub/x") - router.ServeHTTP(rw, req) - if mw.timesCalled != 4 { - t.Fatalf("Expected %d calls, but got only %d", 4, mw.timesCalled) - } -} - -func TestMiddlewareExecution(t *testing.T) { - mwStr := []byte("Middleware\n") - handlerStr := []byte("Logic\n") - - router := NewRouter() - router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }) - - rw := NewRecorder() - req := newRequest("GET", "/") - - // Test handler-only call - router.ServeHTTP(rw, req) - - if bytes.Compare(rw.Body.Bytes(), handlerStr) != 0 { - t.Fatal("Handler response is not what it should be") - } - - // Test middleware call - rw = NewRecorder() - - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) - }) - }) - - router.ServeHTTP(rw, req) - if bytes.Compare(rw.Body.Bytes(), append(mwStr, handlerStr...)) != 0 { - t.Fatal("Middleware + handler response is not what it should be") - } -} - -func TestMiddlewareNotFound(t *testing.T) { - mwStr := []byte("Middleware\n") - handlerStr := []byte("Logic\n") - - router := NewRouter() - router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }) - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) - }) - }) - - // Test not found call with default handler - rw := NewRecorder() - req := newRequest("GET", "/notfound") - - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a 404") - } - - // Test not found call with custom handler - rw = NewRecorder() - req = newRequest("GET", "/notfound") - - router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) - }) - router.ServeHTTP(rw, req) - - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a custom 404") - } -} - -func TestMiddlewareMethodMismatch(t *testing.T) { - mwStr := []byte("Middleware\n") - handlerStr := []byte("Logic\n") - - router := NewRouter() - router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }).Methods("GET") - - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) - }) - }) - - // Test method mismatch - rw := NewRecorder() - req := newRequest("POST", "/") - - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } - - // Test not found call - rw = NewRecorder() - req = newRequest("POST", "/") - - router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) - }) - router.ServeHTTP(rw, req) - - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } -} - -func TestMiddlewareNotFoundSubrouter(t *testing.T) { - mwStr := []byte("Middleware\n") - handlerStr := []byte("Logic\n") - - router := NewRouter() - router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }) - - subrouter := router.PathPrefix("/sub/").Subrouter() - subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }) - - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) - }) - }) - - // Test not found call for default handler - rw := NewRecorder() - req := newRequest("GET", "/sub/notfound") - - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a 404") - } - - // Test not found call with custom handler - rw = NewRecorder() - req = newRequest("GET", "/sub/notfound") - - subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) - }) - router.ServeHTTP(rw, req) - - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a custom 404") - } -} - -func TestMiddlewareMethodMismatchSubrouter(t *testing.T) { - mwStr := []byte("Middleware\n") - handlerStr := []byte("Logic\n") - - router := NewRouter() - router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }) - - subrouter := router.PathPrefix("/sub/").Subrouter() - subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) { - w.Write(handlerStr) - }).Methods("GET") - - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) - }) - }) - - // Test method mismatch without custom handler - rw := NewRecorder() - req := newRequest("POST", "/sub/") - - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } - - // Test method mismatch with custom handler - rw = NewRecorder() - req = newRequest("POST", "/sub/") - - router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) - }) - router.ServeHTTP(rw, req) - - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } -} - -func TestCORSMethodMiddleware(t *testing.T) { - router := NewRouter() - - cases := []struct { - path string - response string - method string - testURL string - expectedAllowedMethods string - }{ - {"/g/{o}", "a", "POST", "/g/asdf", "POST,PUT,GET,OPTIONS"}, - {"/g/{o}", "b", "PUT", "/g/bla", "POST,PUT,GET,OPTIONS"}, - {"/g/{o}", "c", "GET", "/g/orilla", "POST,PUT,GET,OPTIONS"}, - {"/g", "d", "POST", "/g", "POST,OPTIONS"}, - } - - for _, tt := range cases { - router.HandleFunc(tt.path, stringHandler(tt.response)).Methods(tt.method) - } - - router.Use(CORSMethodMiddleware(router)) - - for _, tt := range cases { - rr := httptest.NewRecorder() - req := newRequest(tt.method, tt.testURL) - - router.ServeHTTP(rr, req) - - if rr.Body.String() != tt.response { - t.Errorf("Expected body '%s', found '%s'", tt.response, rr.Body.String()) - } - - allowedMethods := rr.HeaderMap.Get("Access-Control-Allow-Methods") - - if allowedMethods != tt.expectedAllowedMethods { - t.Errorf("Expected Access-Control-Allow-Methods '%s', found '%s'", tt.expectedAllowedMethods, allowedMethods) - } - } -} diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index 4bbafa51da30..5b5f8e7db5dc 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -5,19 +5,11 @@ package mux import ( - "errors" "fmt" "net/http" "path" - "regexp" -) -var ( - // ErrMethodMismatch is returned when the method in the request does not match - // the method defined against the route. - ErrMethodMismatch = errors.New("method is not allowed") - // ErrNotFound is returned when no route match is found. - ErrNotFound = errors.New("no matching route was found") + "github.com/gorilla/context" ) // NewRouter returns a new router instance. @@ -46,10 +38,6 @@ func NewRouter() *Router { type Router struct { // Configurable Handler to be used when no route matches. NotFoundHandler http.Handler - - // Configurable Handler to be used when the request method does not match the route. - MethodNotAllowedHandler http.Handler - // Parent route, if this is a subrouter. parent parentRoute // Routes to be matched, in order. @@ -58,59 +46,17 @@ type Router struct { namedRoutes map[string]*Route // See Router.StrictSlash(). This defines the flag for new routes. strictSlash bool - // See Router.SkipClean(). This defines the flag for new routes. - skipClean bool - // If true, do not clear the request context after handling the request. - // This has no effect when go1.7+ is used, since the context is stored - // on the request itself. + // If true, do not clear the request context after handling the request KeepContext bool - // see Router.UseEncodedPath(). This defines a flag for all routes. - useEncodedPath bool - // Slice of middlewares to be called after a match is found - middlewares []middleware } -// Match attempts to match the given request against the router's registered routes. -// -// If the request matches a route of this router or one of its subrouters the Route, -// Handler, and Vars fields of the the match argument are filled and this function -// returns true. -// -// If the request does not match any of this router's or its subrouters' routes -// then this function returns false. If available, a reason for the match failure -// will be filled in the match argument's MatchErr field. If the match failure type -// (eg: not found) has a registered handler, the handler is assigned to the Handler -// field of the match argument. +// Match matches registered routes against the request. func (r *Router) Match(req *http.Request, match *RouteMatch) bool { for _, route := range r.routes { if route.Match(req, match) { - // Build middleware chain if no error was found - if match.MatchErr == nil { - for i := len(r.middlewares) - 1; i >= 0; i-- { - match.Handler = r.middlewares[i].Middleware(match.Handler) - } - } - return true - } - } - - if match.MatchErr == ErrMethodMismatch { - if r.MethodNotAllowedHandler != nil { - match.Handler = r.MethodNotAllowedHandler return true } - - return false } - - // Closest match for a router (includes sub-routers) - if r.NotFoundHandler != nil { - match.Handler = r.NotFoundHandler - match.MatchErr = ErrNotFound - return true - } - - match.MatchErr = ErrNotFound return false } @@ -119,46 +65,36 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool { // When there is a match, the route variables can be retrieved calling // mux.Vars(request). func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if !r.skipClean { - path := req.URL.Path - if r.useEncodedPath { - path = req.URL.EscapedPath() - } - // Clean path to canonical form and redirect. - if p := cleanPath(path); p != path { - - // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. - // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: - // http://code.google.com/p/go/issues/detail?id=5252 - url := *req.URL - url.Path = p - p = url.String() - - w.Header().Set("Location", p) - w.WriteHeader(http.StatusMovedPermanently) - return - } + // Clean path to canonical form and redirect. + if p := cleanPath(req.URL.Path); p != req.URL.Path { + + // Added 3 lines (Philip Schlump) - It was droping the query string and #whatever from query. + // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: + // http://code.google.com/p/go/issues/detail?id=5252 + url := *req.URL + url.Path = p + p = url.String() + + w.Header().Set("Location", p) + w.WriteHeader(http.StatusMovedPermanently) + return } var match RouteMatch var handler http.Handler if r.Match(req, &match) { handler = match.Handler - req = setVars(req, match.Vars) - req = setCurrentRoute(req, match.Route) - } - - if handler == nil && match.MatchErr == ErrMethodMismatch { - handler = methodNotAllowedHandler() + setVars(req, match.Vars) + setCurrentRoute(req, match.Route) } - if handler == nil { - handler = http.NotFoundHandler() + handler = r.NotFoundHandler + if handler == nil { + handler = http.NotFoundHandler() + } } - if !r.KeepContext { - defer contextClear(req) + defer context.Clear(req) } - handler.ServeHTTP(w, req) } @@ -176,18 +112,13 @@ func (r *Router) GetRoute(name string) *Route { // StrictSlash defines the trailing slash behavior for new routes. The initial // value is false. // -// When true, if the route path is "/path/", accessing "/path" will perform a redirect +// When true, if the route path is "/path/", accessing "/path" will redirect // to the former and vice versa. In other words, your application will always // see the path as specified in the route. // // When false, if the route path is "/path", accessing "/path/" will not match // this route and vice versa. // -// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for -// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed -// request will be made as a GET by most clients. Use middleware or client settings -// to modify this behaviour as needed. -// // Special case: when a route sets a path prefix using the PathPrefix() method, // strict slash is ignored for that route because the redirect behavior can't // be determined from a prefix alone. However, any subrouters created from that @@ -197,41 +128,10 @@ func (r *Router) StrictSlash(value bool) *Router { return r } -// SkipClean defines the path cleaning behaviour for new routes. The initial -// value is false. Users should be careful about which routes are not cleaned -// -// When true, if the route path is "/path//to", it will remain with the double -// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/ -// -// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will -// become /fetch/http/xkcd.com/534 -func (r *Router) SkipClean(value bool) *Router { - r.skipClean = value - return r -} - -// UseEncodedPath tells the router to match the encoded original path -// to the routes. -// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". -// -// If not called, the router will match the unencoded path to the routes. -// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" -func (r *Router) UseEncodedPath() *Router { - r.useEncodedPath = true - return r -} - // ---------------------------------------------------------------------------- // parentRoute // ---------------------------------------------------------------------------- -func (r *Router) getBuildScheme() string { - if r.parent != nil { - return r.parent.getBuildScheme() - } - return "" -} - // getNamedRoutes returns the map where named routes are registered. func (r *Router) getNamedRoutes() map[string]*Route { if r.namedRoutes == nil { @@ -252,20 +152,13 @@ func (r *Router) getRegexpGroup() *routeRegexpGroup { return nil } -func (r *Router) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - return m -} - // ---------------------------------------------------------------------------- // Route factories // ---------------------------------------------------------------------------- // NewRoute registers an empty route. func (r *Router) NewRoute() *Route { - route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean, useEncodedPath: r.useEncodedPath} + route := &Route{parent: r, strictSlash: r.strictSlash} r.routes = append(r.routes, route) return route } @@ -331,59 +224,6 @@ func (r *Router) Schemes(schemes ...string) *Route { return r.NewRoute().Schemes(schemes...) } -// BuildVarsFunc registers a new route with a custom function for modifying -// route variables before building a URL. -func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route { - return r.NewRoute().BuildVarsFunc(f) -} - -// Walk walks the router and all its sub-routers, calling walkFn for each route -// in the tree. The routes are walked in the order they were added. Sub-routers -// are explored depth-first. -func (r *Router) Walk(walkFn WalkFunc) error { - return r.walk(walkFn, []*Route{}) -} - -// SkipRouter is used as a return value from WalkFuncs to indicate that the -// router that walk is about to descend down to should be skipped. -var SkipRouter = errors.New("skip this router") - -// WalkFunc is the type of the function called for each route visited by Walk. -// At every invocation, it is given the current route, and the current router, -// and a list of ancestor routes that lead to the current route. -type WalkFunc func(route *Route, router *Router, ancestors []*Route) error - -func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { - for _, t := range r.routes { - err := walkFn(t, r, ancestors) - if err == SkipRouter { - continue - } - if err != nil { - return err - } - for _, sr := range t.matchers { - if h, ok := sr.(*Router); ok { - ancestors = append(ancestors, t) - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - ancestors = ancestors[:len(ancestors)-1] - } - } - if h, ok := t.handler.(*Router); ok { - ancestors = append(ancestors, t) - err := h.walk(walkFn, ancestors) - if err != nil { - return err - } - ancestors = ancestors[:len(ancestors)-1] - } - } - return nil -} - // ---------------------------------------------------------------------------- // Context // ---------------------------------------------------------------------------- @@ -393,11 +233,6 @@ type RouteMatch struct { Route *Route Handler http.Handler Vars map[string]string - - // MatchErr is set to appropriate matching error - // It is set to ErrMethodMismatch if there is a mismatch in - // the request method and route method - MatchErr error } type contextKey int @@ -409,30 +244,26 @@ const ( // Vars returns the route variables for the current request, if any. func Vars(r *http.Request) map[string]string { - if rv := contextGet(r, varsKey); rv != nil { + if rv := context.Get(r, varsKey); rv != nil { return rv.(map[string]string) } return nil } // CurrentRoute returns the matched route for the current request, if any. -// This only works when called inside the handler of the matched route -// because the matched route is stored in the request context which is cleared -// after the handler returns, unless the KeepContext option is set on the -// Router. func CurrentRoute(r *http.Request) *Route { - if rv := contextGet(r, routeKey); rv != nil { + if rv := context.Get(r, routeKey); rv != nil { return rv.(*Route) } return nil } -func setVars(r *http.Request, val interface{}) *http.Request { - return contextSet(r, varsKey, val) +func setVars(r *http.Request, val interface{}) { + context.Set(r, varsKey, val) } -func setCurrentRoute(r *http.Request, val interface{}) *http.Request { - return contextSet(r, routeKey, val) +func setCurrentRoute(r *http.Request, val interface{}) { + context.Set(r, routeKey, val) } // ---------------------------------------------------------------------------- @@ -454,7 +285,6 @@ func cleanPath(p string) string { if p[len(p)-1] == '/' && np != "/" { np += "/" } - return np } @@ -470,24 +300,13 @@ func uniqueVars(s1, s2 []string) error { return nil } -// checkPairs returns the count of strings passed in, and an error if -// the count is not an even number. -func checkPairs(pairs ...string) (int, error) { +// mapFromPairs converts variadic string parameters to a string map. +func mapFromPairs(pairs ...string) (map[string]string, error) { length := len(pairs) if length%2 != 0 { - return length, fmt.Errorf( + return nil, fmt.Errorf( "mux: number of parameters must be multiple of 2, got %v", pairs) } - return length, nil -} - -// mapFromPairsToString converts variadic string parameters to a -// string to string map. -func mapFromPairsToString(pairs ...string) (map[string]string, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } m := make(map[string]string, length/2) for i := 0; i < length; i += 2 { m[pairs[i]] = pairs[i+1] @@ -495,24 +314,6 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) { return m, nil } -// mapFromPairsToRegex converts variadic string parameters to a -// string to regex map. -func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { - length, err := checkPairs(pairs...) - if err != nil { - return nil, err - } - m := make(map[string]*regexp.Regexp, length/2) - for i := 0; i < length; i += 2 { - regex, err := regexp.Compile(pairs[i+1]) - if err != nil { - return nil, err - } - m[pairs[i]] = regex - } - return m, nil -} - // matchInArray returns true if the given string value is in the array. func matchInArray(arr []string, value string) bool { for _, v := range arr { @@ -523,8 +324,9 @@ func matchInArray(arr []string, value string) bool { return false } -// matchMapWithString returns true if the given key/value pairs exist in a given map. -func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool { +// matchMap returns true if the given key/value pairs exist in a given map. +func matchMap(toCheck map[string]string, toMatch map[string][]string, + canonicalKey bool) bool { for k, v := range toCheck { // Check if key exists. if canonicalKey { @@ -549,40 +351,3 @@ func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, } return true } - -// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against -// the given regex -func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool { - for k, v := range toCheck { - // Check if key exists. - if canonicalKey { - k = http.CanonicalHeaderKey(k) - } - if values := toMatch[k]; values == nil { - return false - } else if v != nil { - // If value was defined as an empty string we only check that the - // key exists. Otherwise we also check for equality. - valueExists := false - for _, value := range values { - if v.MatchString(value) { - valueExists = true - break - } - } - if !valueExists { - return false - } - } - } - return true -} - -// methodNotAllowed replies to the request with an HTTP status code 405. -func methodNotAllowed(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusMethodNotAllowed) -} - -// methodNotAllowedHandler returns a simple request handler -// that replies to each request with a status code 405. -func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/mux_test.go b/vendor/github.com/gorilla/mux/mux_test.go index af21329f2030..e455bce8fdfe 100644 --- a/vendor/github.com/gorilla/mux/mux_test.go +++ b/vendor/github.com/gorilla/mux/mux_test.go @@ -5,46 +5,22 @@ package mux import ( - "bufio" - "bytes" - "errors" "fmt" "net/http" - "net/url" - "reflect" - "strings" "testing" -) - -func (r *Route) GoString() string { - matchers := make([]string, len(r.matchers)) - for i, m := range r.matchers { - matchers[i] = fmt.Sprintf("%#v", m) - } - return fmt.Sprintf("&Route{matchers:[]matcher{%s}}", strings.Join(matchers, ", ")) -} -func (r *routeRegexp) GoString() string { - return fmt.Sprintf("&routeRegexp{template: %q, regexpType: %v, options: %v, regexp: regexp.MustCompile(%q), reverse: %q, varsN: %v, varsR: %v", r.template, r.regexpType, r.options, r.regexp.String(), r.reverse, r.varsN, r.varsR) -} + "github.com/gorilla/context" +) type routeTest struct { - title string // title of the test - route *Route // the route being tested - request *http.Request // a request to test the route - vars map[string]string // the expected vars of the match - scheme string // the expected scheme of the built URL - host string // the expected host of the built URL - path string // the expected path of the built URL - query string // the expected query string of the built URL - pathTemplate string // the expected path template of the route - hostTemplate string // the expected host template of the route - queriesTemplate string // the expected query template of the route - methods []string // the expected route methods - pathRegexp string // the expected path regexp - queriesRegexp string // the expected query regexp - shouldMatch bool // whether the request is expected to match the route at all - shouldRedirect bool // whether the request should result in a redirect + title string // title of the test + route *Route // the route being tested + request *http.Request // a request to test the route + vars map[string]string // the expected vars of the match + host string // the expected host of the match + path string // the expected path of the match + shouldMatch bool // whether the request is expected to match the route at all + shouldRedirect bool // whether the request should result in a redirect } func TestHost(t *testing.T) { @@ -124,89 +100,44 @@ func TestHost(t *testing.T) { shouldMatch: false, }, { - title: "Host route with pattern, match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `aaa.{v1:[a-z]{3}}.ccc`, - shouldMatch: true, - }, - { - title: "Host route with pattern, additional capturing group, match", - route: new(Route).Host("aaa.{v1:[a-z]{2}(?:b|c)}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `aaa.{v1:[a-z]{2}(?:b|c)}.ccc`, - shouldMatch: true, - }, - { - title: "Host route with pattern, wrong host in request URL", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `aaa.{v1:[a-z]{3}}.ccc`, - shouldMatch: false, - }, - { - title: "Host route with multiple patterns, match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}`, - shouldMatch: true, - }, - { - title: "Host route with multiple patterns, wrong host in request URL", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}`, - shouldMatch: false, + title: "Host route with pattern, match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, }, { - title: "Host route with hyphenated name and pattern, match", - route: new(Route).Host("aaa.{v-1:[a-z]{3}}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `aaa.{v-1:[a-z]{3}}.ccc`, - shouldMatch: true, + title: "Host route with pattern, wrong host in request URL", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, }, { - title: "Host route with hyphenated name and pattern, additional capturing group, match", - route: new(Route).Host("aaa.{v-1:[a-z]{2}(?:b|c)}.ccc"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "bbb"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `aaa.{v-1:[a-z]{2}(?:b|c)}.ccc`, - shouldMatch: true, + title: "Host route with multiple patterns, match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, }, { - title: "Host route with multiple hyphenated names and patterns, match", - route: new(Route).Host("{v-1:[a-z]{3}}.{v-2:[a-z]{3}}.{v-3:[a-z]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v-1": "aaa", "v-2": "bbb", "v-3": "ccc"}, - host: "aaa.bbb.ccc", - path: "", - hostTemplate: `{v-1:[a-z]{3}}.{v-2:[a-z]{3}}.{v-3:[a-z]{3}}`, - shouldMatch: true, + title: "Host route with multiple patterns, wrong host in request URL", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) } } @@ -231,50 +162,22 @@ func TestPath(t *testing.T) { shouldMatch: true, }, { - title: "Path route, do not match with trailing slash in path", - route: new(Route).Path("/111/"), - request: newRequest("GET", "http://localhost/111"), - vars: map[string]string{}, - host: "", - path: "/111", - pathTemplate: `/111/`, - pathRegexp: `^/111/$`, - shouldMatch: false, - }, - { - title: "Path route, do not match with trailing slash in request", - route: new(Route).Path("/111"), - request: newRequest("GET", "http://localhost/111/"), - vars: map[string]string{}, - host: "", - path: "/111/", - pathTemplate: `/111`, - shouldMatch: false, - }, - { - title: "Path route, match root with no host", - route: new(Route).Path("/"), - request: newRequest("GET", "/"), - vars: map[string]string{}, - host: "", - path: "/", - pathTemplate: `/`, - pathRegexp: `^/$`, - shouldMatch: true, + title: "Path route, do not match with trailing slash in path", + route: new(Route).Path("/111/"), + request: newRequest("GET", "http://localhost/111"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: false, }, { - title: "Path route, match root with no host, App Engine format", - route: new(Route).Path("/"), - request: func() *http.Request { - r := newRequest("GET", "http://localhost/") - r.RequestURI = "/" - return r - }(), - vars: map[string]string{}, - host: "", - path: "/", - pathTemplate: `/`, - shouldMatch: true, + title: "Path route, do not match with trailing slash in request", + route: new(Route).Path("/111"), + request: newRequest("GET", "http://localhost/111/"), + vars: map[string]string{}, + host: "", + path: "/111/", + shouldMatch: false, }, { title: "Path route, wrong path in request in request URL", @@ -286,161 +189,45 @@ func TestPath(t *testing.T) { shouldMatch: false, }, { - title: "Path route with pattern, match", - route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222/333", - pathTemplate: `/111/{v1:[0-9]{3}}/333`, - shouldMatch: true, - }, - { - title: "Path route with pattern, URL in request does not match", - route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222/333", - pathTemplate: `/111/{v1:[0-9]{3}}/333`, - pathRegexp: `^/111/(?P[0-9]{3})/333$`, - shouldMatch: false, - }, - { - title: "Path route with multiple patterns, match", - route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, - host: "", - path: "/111/222/333", - pathTemplate: `/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}`, - pathRegexp: `^/(?P[0-9]{3})/(?P[0-9]{3})/(?P[0-9]{3})$`, - shouldMatch: true, - }, - { - title: "Path route with multiple patterns, URL in request does not match", - route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, - host: "", - path: "/111/222/333", - pathTemplate: `/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}`, - pathRegexp: `^/(?P[0-9]{3})/(?P[0-9]{3})/(?P[0-9]{3})$`, - shouldMatch: false, - }, - { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|(?:b/c)}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"category": "a", "product": "product_name", "id": "1"}, - host: "", - path: "/a/product_name/1", - pathTemplate: `/{category:a|(?:b/c)}/{product}/{id:[0-9]+}`, - pathRegexp: `^/(?Pa|(?:b/c))/(?P[^/]+)/(?P[0-9]+)$`, - shouldMatch: true, - }, - { - title: "Path route with hyphenated name and pattern, match", - route: new(Route).Path("/111/{v-1:[0-9]{3}}/333"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v-1": "222"}, - host: "", - path: "/111/222/333", - pathTemplate: `/111/{v-1:[0-9]{3}}/333`, - pathRegexp: `^/111/(?P[0-9]{3})/333$`, - shouldMatch: true, - }, - { - title: "Path route with multiple hyphenated names and patterns, match", - route: new(Route).Path("/{v-1:[0-9]{3}}/{v-2:[0-9]{3}}/{v-3:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v-1": "111", "v-2": "222", "v-3": "333"}, - host: "", - path: "/111/222/333", - pathTemplate: `/{v-1:[0-9]{3}}/{v-2:[0-9]{3}}/{v-3:[0-9]{3}}`, - pathRegexp: `^/(?P[0-9]{3})/(?P[0-9]{3})/(?P[0-9]{3})$`, - shouldMatch: true, - }, - { - title: "Path route with multiple hyphenated names and patterns with pipe, match", - route: new(Route).Path("/{product-category:a|(?:b/c)}/{product-name}/{product-id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"product-category": "a", "product-name": "product_name", "product-id": "1"}, - host: "", - path: "/a/product_name/1", - pathTemplate: `/{product-category:a|(?:b/c)}/{product-name}/{product-id:[0-9]+}`, - pathRegexp: `^/(?Pa|(?:b/c))/(?P[^/]+)/(?P[0-9]+)$`, - shouldMatch: true, - }, - { - title: "Path route with multiple hyphenated names and patterns with pipe and case insensitive, match", - route: new(Route).Path("/{type:(?i:daily|mini|variety)}-{date:\\d{4,4}-\\d{2,2}-\\d{2,2}}"), - request: newRequest("GET", "http://localhost/daily-2016-01-01"), - vars: map[string]string{"type": "daily", "date": "2016-01-01"}, - host: "", - path: "/daily-2016-01-01", - pathTemplate: `/{type:(?i:daily|mini|variety)}-{date:\d{4,4}-\d{2,2}-\d{2,2}}`, - pathRegexp: `^/(?P(?i:daily|mini|variety))-(?P\d{4,4}-\d{2,2}-\d{2,2})$`, - shouldMatch: true, - }, - { - title: "Path route with empty match right after other match", - route: new(Route).Path(`/{v1:[0-9]*}{v2:[a-z]*}/{v3:[0-9]*}`), - request: newRequest("GET", "http://localhost/111/222"), - vars: map[string]string{"v1": "111", "v2": "", "v3": "222"}, - host: "", - path: "/111/222", - pathTemplate: `/{v1:[0-9]*}{v2:[a-z]*}/{v3:[0-9]*}`, - pathRegexp: `^/(?P[0-9]*)(?P[a-z]*)/(?P[0-9]*)$`, - shouldMatch: true, - }, - { - title: "Path route with single pattern with pipe, match", - route: new(Route).Path("/{category:a|b/c}"), - request: newRequest("GET", "http://localhost/a"), - vars: map[string]string{"category": "a"}, - host: "", - path: "/a", - pathTemplate: `/{category:a|b/c}`, - shouldMatch: true, + title: "Path route with pattern, match", + route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222/333", + shouldMatch: true, }, { - title: "Path route with single pattern with pipe, match", - route: new(Route).Path("/{category:a|b/c}"), - request: newRequest("GET", "http://localhost/b/c"), - vars: map[string]string{"category": "b/c"}, - host: "", - path: "/b/c", - pathTemplate: `/{category:a|b/c}`, - shouldMatch: true, + title: "Path route with pattern, URL in request does not match", + route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222/333", + shouldMatch: false, }, { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|b/c}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/a/product_name/1"), - vars: map[string]string{"category": "a", "product": "product_name", "id": "1"}, - host: "", - path: "/a/product_name/1", - pathTemplate: `/{category:a|b/c}/{product}/{id:[0-9]+}`, - shouldMatch: true, + title: "Path route with multiple patterns, match", + route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, + host: "", + path: "/111/222/333", + shouldMatch: true, }, { - title: "Path route with multiple patterns with pipe, match", - route: new(Route).Path("/{category:a|b/c}/{product}/{id:[0-9]+}"), - request: newRequest("GET", "http://localhost/b/c/product_name/1"), - vars: map[string]string{"category": "b/c", "product": "product_name", "id": "1"}, - host: "", - path: "/b/c/product_name/1", - pathTemplate: `/{category:a|b/c}/{product}/{id:[0-9]+}`, - shouldMatch: true, + title: "Path route with multiple patterns, URL in request does not match", + route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, + host: "", + path: "/111/222/333", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testUseEscapedRoute(t, test) - testRegexp(t, test) } } @@ -474,158 +261,108 @@ func TestPathPrefix(t *testing.T) { shouldMatch: false, }, { - title: "PathPrefix route with pattern, match", - route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222", - pathTemplate: `/111/{v1:[0-9]{3}}`, - shouldMatch: true, + title: "PathPrefix route with pattern, match", + route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222", + shouldMatch: true, }, { - title: "PathPrefix route with pattern, URL prefix in request does not match", - route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "222"}, - host: "", - path: "/111/222", - pathTemplate: `/111/{v1:[0-9]{3}}`, - shouldMatch: false, + title: "PathPrefix route with pattern, URL prefix in request does not match", + route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222", + shouldMatch: false, }, { - title: "PathPrefix route with multiple patterns, match", - route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/222/333"), - vars: map[string]string{"v1": "111", "v2": "222"}, - host: "", - path: "/111/222", - pathTemplate: `/{v1:[0-9]{3}}/{v2:[0-9]{3}}`, - shouldMatch: true, + title: "PathPrefix route with multiple patterns, match", + route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "111", "v2": "222"}, + host: "", + path: "/111/222", + shouldMatch: true, }, { - title: "PathPrefix route with multiple patterns, URL prefix in request does not match", - route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), - request: newRequest("GET", "http://localhost/111/aaa/333"), - vars: map[string]string{"v1": "111", "v2": "222"}, - host: "", - path: "/111/222", - pathTemplate: `/{v1:[0-9]{3}}/{v2:[0-9]{3}}`, - shouldMatch: false, + title: "PathPrefix route with multiple patterns, URL prefix in request does not match", + route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "111", "v2": "222"}, + host: "", + path: "/111/222", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testUseEscapedRoute(t, test) } } -func TestSchemeHostPath(t *testing.T) { +func TestHostPath(t *testing.T) { tests := []routeTest{ { - title: "Host and Path route, match", - route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/222/333`, - hostTemplate: `aaa.bbb.ccc`, - shouldMatch: true, - }, - { - title: "Scheme, Host, and Path route, match", - route: new(Route).Schemes("https").Host("aaa.bbb.ccc").Path("/111/222/333"), - request: newRequest("GET", "https://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{}, - scheme: "https", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/222/333`, - hostTemplate: `aaa.bbb.ccc`, - shouldMatch: true, - }, - { - title: "Host and Path route, wrong host in request URL", - route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/222/333`, - hostTemplate: `aaa.bbb.ccc`, - shouldMatch: false, + title: "Host and Path route, match", + route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Host and Path route with pattern, match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb", "v2": "222"}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/{v2:[0-9]{3}}/333`, - hostTemplate: `aaa.{v1:[a-z]{3}}.ccc`, - shouldMatch: true, + title: "Host and Path route, wrong host in request URL", + route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, }, { - title: "Scheme, Host, and Path route with host and path patterns, match", - route: new(Route).Schemes("ftp", "ssss").Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), - request: newRequest("GET", "ssss://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb", "v2": "222"}, - scheme: "ftp", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/{v2:[0-9]{3}}/333`, - hostTemplate: `aaa.{v1:[a-z]{3}}.ccc`, - shouldMatch: true, + title: "Host and Path route with pattern, match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb", "v2": "222"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: true, }, { - title: "Host and Path route with pattern, URL in request does not match", - route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "bbb", "v2": "222"}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/111/{v2:[0-9]{3}}/333`, - hostTemplate: `aaa.{v1:[a-z]{3}}.ccc`, - shouldMatch: false, + title: "Host and Path route with pattern, URL in request does not match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb", "v2": "222"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: false, }, { - title: "Host and Path route with multiple patterns, match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), - request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}`, - hostTemplate: `{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}`, - shouldMatch: true, + title: "Host and Path route with multiple patterns, match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: true, }, { - title: "Host and Path route with multiple patterns, URL in request does not match", - route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), - request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), - vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, - scheme: "http", - host: "aaa.bbb.ccc", - path: "/111/222/333", - pathTemplate: `/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}`, - hostTemplate: `{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}`, - shouldMatch: false, + title: "Host and Path route with multiple patterns, URL in request does not match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testUseEscapedRoute(t, test) } } @@ -661,30 +398,12 @@ func TestHeaders(t *testing.T) { path: "", shouldMatch: false, }, - { - title: "Headers route, regex header values to match", - route: new(Route).Headers("foo", "ba[zr]"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: false, - }, - { - title: "Headers route, regex header values to match", - route: new(Route).HeadersRegexp("foo", "ba[zr]"), - request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "baz"}), - vars: map[string]string{}, - host: "", - path: "", - shouldMatch: true, - }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) } + } func TestMethods(t *testing.T) { @@ -696,7 +415,6 @@ func TestMethods(t *testing.T) { vars: map[string]string{}, host: "", path: "", - methods: []string{"GET", "POST"}, shouldMatch: true, }, { @@ -706,7 +424,6 @@ func TestMethods(t *testing.T) { vars: map[string]string{}, host: "", path: "", - methods: []string{"GET", "POST"}, shouldMatch: true, }, { @@ -716,334 +433,93 @@ func TestMethods(t *testing.T) { vars: map[string]string{}, host: "", path: "", - methods: []string{"GET", "POST"}, shouldMatch: false, }, - { - title: "Route without methods", - route: new(Route), - request: newRequest("PUT", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - methods: []string{}, - shouldMatch: true, - }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testMethods(t, test) } } func TestQueries(t *testing.T) { tests := []routeTest{ { - title: "Queries route, match", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{}, - host: "", - path: "", - query: "foo=bar&baz=ding", - queriesTemplate: "foo=bar,baz=ding", - queriesRegexp: "^foo=bar$,^baz=ding$", - shouldMatch: true, - }, - { - title: "Queries route, match with a query string", - route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), - vars: map[string]string{}, - host: "", - path: "", - query: "foo=bar&baz=ding", - pathTemplate: `/api`, - hostTemplate: `www.example.com`, - queriesTemplate: "foo=bar,baz=ding", - queriesRegexp: "^foo=bar$,^baz=ding$", - shouldMatch: true, - }, - { - title: "Queries route, match with a query string out of order", - route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), - vars: map[string]string{}, - host: "", - path: "", - query: "foo=bar&baz=ding", - pathTemplate: `/api`, - hostTemplate: `www.example.com`, - queriesTemplate: "foo=bar,baz=ding", - queriesRegexp: "^foo=bar$,^baz=ding$", - shouldMatch: true, - }, - { - title: "Queries route, bad query", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo=bar,baz=ding", - queriesRegexp: "^foo=bar$,^baz=ding$", - shouldMatch: false, - }, - { - title: "Queries route with pattern, match", - route: new(Route).Queries("foo", "{v1}"), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{"v1": "bar"}, - host: "", - path: "", - query: "foo=bar", - queriesTemplate: "foo={v1}", - queriesRegexp: "^foo=(?P.*)$", - shouldMatch: true, - }, - { - title: "Queries route with multiple patterns, match", - route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "", - query: "foo=bar&baz=ding", - queriesTemplate: "foo={v1},baz={v2}", - queriesRegexp: "^foo=(?P.*)$,^baz=(?P.*)$", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern, match", - route: new(Route).Queries("foo", "{v1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=10"), - vars: map[string]string{"v1": "10"}, - host: "", - path: "", - query: "foo=10", - queriesTemplate: "foo={v1:[0-9]+}", - queriesRegexp: "^foo=(?P[0-9]+)$", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=a"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo={v1:[0-9]+}", - queriesRegexp: "^foo=(?P[0-9]+)$", - shouldMatch: false, - }, - { - title: "Queries route with regexp pattern with quantifier, match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=1"), - vars: map[string]string{"v1": "1"}, - host: "", - path: "", - query: "foo=1", - queriesTemplate: "foo={v1:[0-9]{1}}", - queriesRegexp: "^foo=(?P[0-9]{1})$", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, additional variable in query string, match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?bar=2&foo=1"), - vars: map[string]string{"v1": "1"}, - host: "", - path: "", - query: "foo=1", - queriesTemplate: "foo={v1:[0-9]{1}}", - queriesRegexp: "^foo=(?P[0-9]{1})$", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=12"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo={v1:[0-9]{1}}", - queriesRegexp: "^foo=(?P[0-9]{1})$", - shouldMatch: false, - }, - { - title: "Queries route with regexp pattern with quantifier, additional capturing group", - route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"), - request: newRequest("GET", "http://localhost?foo=1a"), - vars: map[string]string{"v1": "1a"}, - host: "", - path: "", - query: "foo=1a", - queriesTemplate: "foo={v1:[0-9]{1}(?:a|b)}", - queriesRegexp: "^foo=(?P[0-9]{1}(?:a|b))$", - shouldMatch: true, - }, - { - title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match", - route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), - request: newRequest("GET", "http://localhost?foo=12"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo={v1:[0-9]{1}}", - queriesRegexp: "^foo=(?P[0-9]{1})$", - shouldMatch: false, - }, - { - title: "Queries route with hyphenated name, match", - route: new(Route).Queries("foo", "{v-1}"), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{"v-1": "bar"}, - host: "", - path: "", - query: "foo=bar", - queriesTemplate: "foo={v-1}", - queriesRegexp: "^foo=(?P.*)$", - shouldMatch: true, - }, - { - title: "Queries route with multiple hyphenated names, match", - route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"), - request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), - vars: map[string]string{"v-1": "bar", "v-2": "ding"}, - host: "", - path: "", - query: "foo=bar&baz=ding", - queriesTemplate: "foo={v-1},baz={v-2}", - queriesRegexp: "^foo=(?P.*)$,^baz=(?P.*)$", - shouldMatch: true, - }, - { - title: "Queries route with hyphenate name and pattern, match", - route: new(Route).Queries("foo", "{v-1:[0-9]+}"), - request: newRequest("GET", "http://localhost?foo=10"), - vars: map[string]string{"v-1": "10"}, - host: "", - path: "", - query: "foo=10", - queriesTemplate: "foo={v-1:[0-9]+}", - queriesRegexp: "^foo=(?P[0-9]+)$", - shouldMatch: true, - }, - { - title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group", - route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"), - request: newRequest("GET", "http://localhost?foo=1a"), - vars: map[string]string{"v-1": "1a"}, - host: "", - path: "", - query: "foo=1a", - queriesTemplate: "foo={v-1:[0-9]{1}(?:a|b)}", - queriesRegexp: "^foo=(?P[0-9]{1}(?:a|b))$", - shouldMatch: true, - }, - { - title: "Queries route with empty value, should match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost?foo=bar"), - vars: map[string]string{}, - host: "", - path: "", - query: "foo=", - queriesTemplate: "foo=", - queriesRegexp: "^foo=.*$", - shouldMatch: true, + title: "Queries route, match", + route: new(Route).Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route with empty value and no parameter in request, should not match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo=", - queriesRegexp: "^foo=.*$", - shouldMatch: false, + title: "Queries route, match with a query string", + route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route with empty value and empty parameter in request, should match", - route: new(Route).Queries("foo", ""), - request: newRequest("GET", "http://localhost?foo="), - vars: map[string]string{}, - host: "", - path: "", - query: "foo=", - queriesTemplate: "foo=", - queriesRegexp: "^foo=.*$", - shouldMatch: true, + title: "Queries route, match with a query string out of order", + route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route with overlapping value, should not match", - route: new(Route).Queries("foo", "bar"), - request: newRequest("GET", "http://localhost?foo=barfoo"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo=bar", - queriesRegexp: "^foo=bar$", - shouldMatch: false, + title: "Queries route, bad query", + route: new(Route).Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, }, { - title: "Queries route with no parameter in request, should not match", - route: new(Route).Queries("foo", "{bar}"), - request: newRequest("GET", "http://localhost"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo={bar}", - queriesRegexp: "^foo=(?P.*)$", - shouldMatch: false, + title: "Queries route with pattern, match", + route: new(Route).Queries("foo", "{v1}"), + request: newRequest("GET", "http://localhost?foo=bar"), + vars: map[string]string{"v1": "bar"}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route with empty parameter in request, should match", - route: new(Route).Queries("foo", "{bar}"), - request: newRequest("GET", "http://localhost?foo="), - vars: map[string]string{"foo": ""}, - host: "", - path: "", - query: "foo=", - queriesTemplate: "foo={bar}", - queriesRegexp: "^foo=(?P.*)$", - shouldMatch: true, + title: "Queries route with multiple patterns, match", + route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), + request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route, bad submatch", - route: new(Route).Queries("foo", "bar", "baz", "ding"), - request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"), - vars: map[string]string{}, - host: "", - path: "", - queriesTemplate: "foo=bar,baz=ding", - queriesRegexp: "^foo=bar$,^baz=ding$", - shouldMatch: false, + title: "Queries route with regexp pattern, match", + route: new(Route).Queries("foo", "{v1:[0-9]+}"), + request: newRequest("GET", "http://localhost?foo=10"), + vars: map[string]string{"v1": "10"}, + host: "", + path: "", + shouldMatch: true, }, { - title: "Queries route with pattern, match, escaped value", - route: new(Route).Queries("foo", "{v1}"), - request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"), - vars: map[string]string{"v1": "%bar& /=?"}, - host: "", - path: "", - query: "foo=%25bar%26+%2F%3D%3F", - queriesTemplate: "foo={v1}", - queriesRegexp: "^foo=(?P.*)$", - shouldMatch: true, + title: "Queries route with regexp pattern, regexp does not match", + route: new(Route).Queries("foo", "{v1:[0-9]+}"), + request: newRequest("GET", "http://localhost?foo=a"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testQueriesTemplates(t, test) - testUseEscapedRoute(t, test) - testQueriesRegexp(t, test) } } @@ -1051,49 +527,35 @@ func TestSchemes(t *testing.T) { tests := []routeTest{ // Schemes { - title: "Schemes route, default scheme, match http, build http", - route: new(Route).Host("localhost"), - request: newRequest("GET", "http://localhost"), - scheme: "http", - host: "localhost", - shouldMatch: true, - }, - { - title: "Schemes route, match https, build https", - route: new(Route).Schemes("https", "ftp").Host("localhost"), + title: "Schemes route, match https", + route: new(Route).Schemes("https", "ftp"), request: newRequest("GET", "https://localhost"), - scheme: "https", - host: "localhost", - shouldMatch: true, - }, - { - title: "Schemes route, match ftp, build https", - route: new(Route).Schemes("https", "ftp").Host("localhost"), - request: newRequest("GET", "ftp://localhost"), - scheme: "https", - host: "localhost", + vars: map[string]string{}, + host: "", + path: "", shouldMatch: true, }, { - title: "Schemes route, match ftp, build ftp", - route: new(Route).Schemes("ftp", "https").Host("localhost"), + title: "Schemes route, match ftp", + route: new(Route).Schemes("https", "ftp"), request: newRequest("GET", "ftp://localhost"), - scheme: "ftp", - host: "localhost", + vars: map[string]string{}, + host: "", + path: "", shouldMatch: true, }, { title: "Schemes route, bad scheme", - route: new(Route).Schemes("https", "ftp").Host("localhost"), + route: new(Route).Schemes("https", "ftp"), request: newRequest("GET", "http://localhost"), - scheme: "https", - host: "localhost", + vars: map[string]string{}, + host: "", + path: "", shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) } } @@ -1128,175 +590,50 @@ func TestMatcherFunc(t *testing.T) { for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - } -} - -func TestBuildVarsFunc(t *testing.T) { - tests := []routeTest{ - { - title: "BuildVarsFunc set on route", - route: new(Route).Path(`/111/{v1:\d}{v2:.*}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v1"] = "3" - vars["v2"] = "a" - return vars - }), - request: newRequest("GET", "http://localhost/111/2"), - path: "/111/3a", - pathTemplate: `/111/{v1:\d}{v2:.*}`, - shouldMatch: true, - }, - { - title: "BuildVarsFunc set on route and parent route", - route: new(Route).PathPrefix(`/{v1:\d}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v1"] = "2" - return vars - }).Subrouter().Path(`/{v2:\w}`).BuildVarsFunc(func(vars map[string]string) map[string]string { - vars["v2"] = "b" - return vars - }), - request: newRequest("GET", "http://localhost/1/a"), - path: "/2/b", - pathTemplate: `/{v1:\d}/{v2:\w}`, - shouldMatch: true, - }, - } - - for _, test := range tests { - testRoute(t, test) - testTemplate(t, test) } } func TestSubRouter(t *testing.T) { subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter() subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter() - subrouter3 := new(Route).PathPrefix("/foo").Subrouter() - subrouter4 := new(Route).PathPrefix("/foo/bar").Subrouter() - subrouter5 := new(Route).PathPrefix("/{category}").Subrouter() tests := []routeTest{ { - route: subrouter1.Path("/{v2:[a-z]+}"), - request: newRequest("GET", "http://aaa.google.com/bbb"), - vars: map[string]string{"v1": "aaa", "v2": "bbb"}, - host: "aaa.google.com", - path: "/bbb", - pathTemplate: `/{v2:[a-z]+}`, - hostTemplate: `{v1:[a-z]+}.google.com`, - shouldMatch: true, - }, - { - route: subrouter1.Path("/{v2:[a-z]+}"), - request: newRequest("GET", "http://111.google.com/111"), - vars: map[string]string{"v1": "aaa", "v2": "bbb"}, - host: "aaa.google.com", - path: "/bbb", - pathTemplate: `/{v2:[a-z]+}`, - hostTemplate: `{v1:[a-z]+}.google.com`, - shouldMatch: false, - }, - { - route: subrouter2.Path("/baz/{v2}"), - request: newRequest("GET", "http://localhost/foo/bar/baz/ding"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "/foo/bar/baz/ding", - pathTemplate: `/foo/{v1}/baz/{v2}`, - shouldMatch: true, - }, - { - route: subrouter2.Path("/baz/{v2}"), - request: newRequest("GET", "http://localhost/foo/bar"), - vars: map[string]string{"v1": "bar", "v2": "ding"}, - host: "", - path: "/foo/bar/baz/ding", - pathTemplate: `/foo/{v1}/baz/{v2}`, - shouldMatch: false, - }, - { - route: subrouter3.Path("/"), - request: newRequest("GET", "http://localhost/foo/"), - vars: map[string]string{}, - host: "", - path: "/foo/", - pathTemplate: `/foo/`, - shouldMatch: true, - }, - { - route: subrouter3.Path(""), - request: newRequest("GET", "http://localhost/foo"), - vars: map[string]string{}, - host: "", - path: "/foo", - pathTemplate: `/foo`, - shouldMatch: true, - }, - - { - route: subrouter4.Path("/"), - request: newRequest("GET", "http://localhost/foo/bar/"), - vars: map[string]string{}, - host: "", - path: "/foo/bar/", - pathTemplate: `/foo/bar/`, - shouldMatch: true, - }, - { - route: subrouter4.Path(""), - request: newRequest("GET", "http://localhost/foo/bar"), - vars: map[string]string{}, - host: "", - path: "/foo/bar", - pathTemplate: `/foo/bar`, - shouldMatch: true, - }, - { - route: subrouter5.Path("/"), - request: newRequest("GET", "http://localhost/baz/"), - vars: map[string]string{"category": "baz"}, - host: "", - path: "/baz/", - pathTemplate: `/{category}/`, - shouldMatch: true, + route: subrouter1.Path("/{v2:[a-z]+}"), + request: newRequest("GET", "http://aaa.google.com/bbb"), + vars: map[string]string{"v1": "aaa", "v2": "bbb"}, + host: "aaa.google.com", + path: "/bbb", + shouldMatch: true, }, { - route: subrouter5.Path(""), - request: newRequest("GET", "http://localhost/baz"), - vars: map[string]string{"category": "baz"}, - host: "", - path: "/baz", - pathTemplate: `/{category}`, - shouldMatch: true, + route: subrouter1.Path("/{v2:[a-z]+}"), + request: newRequest("GET", "http://111.google.com/111"), + vars: map[string]string{"v1": "aaa", "v2": "bbb"}, + host: "aaa.google.com", + path: "/bbb", + shouldMatch: false, }, { - title: "Build with scheme on parent router", - route: new(Route).Schemes("ftp").Host("google.com").Subrouter().Path("/"), - request: newRequest("GET", "ftp://google.com/"), - scheme: "ftp", - host: "google.com", - path: "/", - pathTemplate: `/`, - hostTemplate: `google.com`, - shouldMatch: true, + route: subrouter2.Path("/baz/{v2}"), + request: newRequest("GET", "http://localhost/foo/bar/baz/ding"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "/foo/bar/baz/ding", + shouldMatch: true, }, { - title: "Prefer scheme on child route when building URLs", - route: new(Route).Schemes("https", "ftp").Host("google.com").Subrouter().Schemes("ftp").Path("/"), - request: newRequest("GET", "ftp://google.com/"), - scheme: "ftp", - host: "google.com", - path: "/", - pathTemplate: `/`, - hostTemplate: `google.com`, - shouldMatch: true, + route: subrouter2.Path("/baz/{v2}"), + request: newRequest("GET", "http://localhost/foo/bar"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "/foo/bar/baz/ding", + shouldMatch: false, }, } for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testUseEscapedRoute(t, test) } } @@ -1392,245 +729,22 @@ func TestStrictSlash(t *testing.T) { for _, test := range tests { testRoute(t, test) - testTemplate(t, test) - testUseEscapedRoute(t, test) } } -func TestUseEncodedPath(t *testing.T) { - r := NewRouter() - r.UseEncodedPath() - - tests := []routeTest{ - { - title: "Router with useEncodedPath, URL with encoded slash does match", - route: r.NewRoute().Path("/v1/{v1}/v2"), - request: newRequest("GET", "http://localhost/v1/1%2F2/v2"), - vars: map[string]string{"v1": "1%2F2"}, - host: "", - path: "/v1/1%2F2/v2", - pathTemplate: `/v1/{v1}/v2`, - shouldMatch: true, - }, - { - title: "Router with useEncodedPath, URL with encoded slash doesn't match", - route: r.NewRoute().Path("/v1/1/2/v2"), - request: newRequest("GET", "http://localhost/v1/1%2F2/v2"), - vars: map[string]string{"v1": "1%2F2"}, - host: "", - path: "/v1/1%2F2/v2", - pathTemplate: `/v1/1/2/v2`, - shouldMatch: false, - }, - } - - for _, test := range tests { - testRoute(t, test) - testTemplate(t, test) - } -} - -func TestWalkSingleDepth(t *testing.T) { - r0 := NewRouter() - r1 := NewRouter() - r2 := NewRouter() - - r0.Path("/g") - r0.Path("/o") - r0.Path("/d").Handler(r1) - r0.Path("/r").Handler(r2) - r0.Path("/a") - - r1.Path("/z") - r1.Path("/i") - r1.Path("/l") - r1.Path("/l") - - r2.Path("/i") - r2.Path("/l") - r2.Path("/l") - - paths := []string{"g", "o", "r", "i", "l", "l", "a"} - depths := []int{0, 0, 0, 1, 1, 1, 0} - i := 0 - err := r0.Walk(func(route *Route, router *Router, ancestors []*Route) error { - matcher := route.matchers[0].(*routeRegexp) - if matcher.template == "/d" { - return SkipRouter - } - if len(ancestors) != depths[i] { - t.Errorf(`Expected depth of %d at i = %d; got "%d"`, depths[i], i, len(ancestors)) - } - if matcher.template != "/"+paths[i] { - t.Errorf(`Expected "/%s" at i = %d; got "%s"`, paths[i], i, matcher.template) - } - i++ - return nil - }) - if err != nil { - panic(err) - } - if i != len(paths) { - t.Errorf("Expected %d routes, found %d", len(paths), i) - } -} - -func TestWalkNested(t *testing.T) { - router := NewRouter() - - g := router.Path("/g").Subrouter() - o := g.PathPrefix("/o").Subrouter() - r := o.PathPrefix("/r").Subrouter() - i := r.PathPrefix("/i").Subrouter() - l1 := i.PathPrefix("/l").Subrouter() - l2 := l1.PathPrefix("/l").Subrouter() - l2.Path("/a") - - testCases := []struct { - path string - ancestors []*Route - }{ - {"/g", []*Route{}}, - {"/g/o", []*Route{g.parent.(*Route)}}, - {"/g/o/r", []*Route{g.parent.(*Route), o.parent.(*Route)}}, - {"/g/o/r/i", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route)}}, - {"/g/o/r/i/l", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route)}}, - {"/g/o/r/i/l/l", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route), l1.parent.(*Route)}}, - {"/g/o/r/i/l/l/a", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route), l1.parent.(*Route), l2.parent.(*Route)}}, - } - - idx := 0 - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - path := testCases[idx].path - tpl := route.regexp.path.template - if tpl != path { - t.Errorf(`Expected %s got %s`, path, tpl) - } - currWantAncestors := testCases[idx].ancestors - if !reflect.DeepEqual(currWantAncestors, ancestors) { - t.Errorf(`Expected %+v got %+v`, currWantAncestors, ancestors) - } - idx++ - return nil - }) - if err != nil { - panic(err) - } - if idx != len(testCases) { - t.Errorf("Expected %d routes, found %d", len(testCases), idx) - } -} - -func TestWalkSubrouters(t *testing.T) { - router := NewRouter() - - g := router.Path("/g").Subrouter() - o := g.PathPrefix("/o").Subrouter() - o.Methods("GET") - o.Methods("PUT") - - // all 4 routes should be matched, but final 2 routes do not have path templates - paths := []string{"/g", "/g/o", "", ""} - idx := 0 - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - path := paths[idx] - tpl, _ := route.GetPathTemplate() - if tpl != path { - t.Errorf(`Expected %s got %s`, path, tpl) - } - idx++ - return nil - }) - if err != nil { - panic(err) - } - if idx != len(paths) { - t.Errorf("Expected %d routes, found %d", len(paths), idx) - } -} - -func TestWalkErrorRoute(t *testing.T) { - router := NewRouter() - router.Path("/g") - expectedError := errors.New("error") - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - return expectedError - }) - if err != expectedError { - t.Errorf("Expected %v routes, found %v", expectedError, err) - } -} - -func TestWalkErrorMatcher(t *testing.T) { - router := NewRouter() - expectedError := router.Path("/g").Subrouter().Path("").GetError() - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - return route.GetError() - }) - if err != expectedError { - t.Errorf("Expected %v routes, found %v", expectedError, err) - } -} - -func TestWalkErrorHandler(t *testing.T) { - handler := NewRouter() - expectedError := handler.Path("/path").Subrouter().Path("").GetError() - router := NewRouter() - router.Path("/g").Handler(handler) - err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error { - return route.GetError() - }) - if err != expectedError { - t.Errorf("Expected %v routes, found %v", expectedError, err) - } -} - -func TestSubrouterErrorHandling(t *testing.T) { - superRouterCalled := false - subRouterCalled := false - - router := NewRouter() - router.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - superRouterCalled = true - }) - subRouter := router.PathPrefix("/bign8").Subrouter() - subRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - subRouterCalled = true - }) - - req, _ := http.NewRequest("GET", "http://localhost/bign8/was/here", nil) - router.ServeHTTP(NewRecorder(), req) - - if superRouterCalled { - t.Error("Super router 404 handler called when sub-router 404 handler is available.") - } - if !subRouterCalled { - t.Error("Sub-router 404 handler was not called.") - } -} - -// See: https://github.com/gorilla/mux/issues/200 -func TestPanicOnCapturingGroups(t *testing.T) { - defer func() { - if recover() == nil { - t.Errorf("(Test that capturing groups now fail fast) Expected panic, however test completed successfully.\n") - } - }() - NewRouter().NewRoute().Path("/{type:(promo|special)}/{promoId}.json") -} - // ---------------------------------------------------------------------------- // Helpers // ---------------------------------------------------------------------------- func getRouteTemplate(route *Route) string { - host, err := route.GetHostTemplate() - if err != nil { - host = "none" - } - path, err := route.GetPathTemplate() - if err != nil { - path = "none" + host, path := "none", "none" + if route.regexp != nil { + if route.regexp.host != nil { + host = route.regexp.host.template + } + if route.regexp.path != nil { + path = route.regexp.path.template + } } return fmt.Sprintf("Host: %v, Path: %v", host, path) } @@ -1640,16 +754,10 @@ func testRoute(t *testing.T, test routeTest) { route := test.route vars := test.vars shouldMatch := test.shouldMatch - query := test.query + host := test.host + path := test.path + url := test.host + test.path shouldRedirect := test.shouldRedirect - uri := url.URL{ - Scheme: test.scheme, - Host: test.host, - Path: test.path, - } - if uri.Scheme == "" { - uri.Scheme = "http" - } var match RouteMatch ok := route.Match(request, &match) @@ -1662,58 +770,28 @@ func testRoute(t *testing.T, test routeTest) { return } if shouldMatch { - if vars != nil && !stringMapEqual(vars, match.Vars) { + if test.vars != nil && !stringMapEqual(test.vars, match.Vars) { t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars) return } - if test.scheme != "" { - u, err := route.URL(mapToPairs(match.Vars)...) - if err != nil { - t.Fatalf("(%v) URL error: %v -- %v", test.title, err, getRouteTemplate(route)) - } - if uri.Scheme != u.Scheme { - t.Errorf("(%v) URLScheme not equal: expected %v, got %v", test.title, uri.Scheme, u.Scheme) - return - } - } - if test.host != "" { - u, err := test.route.URLHost(mapToPairs(match.Vars)...) - if err != nil { - t.Fatalf("(%v) URLHost error: %v -- %v", test.title, err, getRouteTemplate(route)) - } - if uri.Scheme != u.Scheme { - t.Errorf("(%v) URLHost scheme not equal: expected %v, got %v -- %v", test.title, uri.Scheme, u.Scheme, getRouteTemplate(route)) - return - } - if uri.Host != u.Host { - t.Errorf("(%v) URLHost host not equal: expected %v, got %v -- %v", test.title, uri.Host, u.Host, getRouteTemplate(route)) - return - } - } - if test.path != "" { - u, err := route.URLPath(mapToPairs(match.Vars)...) - if err != nil { - t.Fatalf("(%v) URLPath error: %v -- %v", test.title, err, getRouteTemplate(route)) - } - if uri.Path != u.Path { - t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, uri.Path, u.Path, getRouteTemplate(route)) + if host != "" { + u, _ := test.route.URLHost(mapToPairs(match.Vars)...) + if host != u.Host { + t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route)) return } } - if test.host != "" && test.path != "" { - u, err := route.URL(mapToPairs(match.Vars)...) - if err != nil { - t.Fatalf("(%v) URL error: %v -- %v", test.title, err, getRouteTemplate(route)) - } - if expected, got := uri.String(), u.String(); expected != got { - t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, expected, got, getRouteTemplate(route)) + if path != "" { + u, _ := route.URLPath(mapToPairs(match.Vars)...) + if path != u.Path { + t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route)) return } } - if query != "" { + if url != "" { u, _ := route.URL(mapToPairs(match.Vars)...) - if query != u.RawQuery { - t.Errorf("(%v) URL query not equal: expected %v, got %v", test.title, query, u.RawQuery) + if url != u.Host+u.Path { + t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route)) return } } @@ -1728,65 +806,34 @@ func testRoute(t *testing.T, test routeTest) { } } -func testUseEscapedRoute(t *testing.T, test routeTest) { - test.route.useEncodedPath = true - testRoute(t, test) -} +// Tests that the context is cleared or not cleared properly depending on +// the configuration of the router +func TestKeepContext(t *testing.T) { + func1 := func(w http.ResponseWriter, r *http.Request) {} -func testTemplate(t *testing.T, test routeTest) { - route := test.route - pathTemplate := test.pathTemplate - if len(pathTemplate) == 0 { - pathTemplate = test.path - } - hostTemplate := test.hostTemplate - if len(hostTemplate) == 0 { - hostTemplate = test.host - } + r := NewRouter() + r.HandleFunc("/", func1).Name("func1") - routePathTemplate, pathErr := route.GetPathTemplate() - if pathErr == nil && routePathTemplate != pathTemplate { - t.Errorf("(%v) GetPathTemplate not equal: expected %v, got %v", test.title, pathTemplate, routePathTemplate) - } + req, _ := http.NewRequest("GET", "http://localhost/", nil) + context.Set(req, "t", 1) - routeHostTemplate, hostErr := route.GetHostTemplate() - if hostErr == nil && routeHostTemplate != hostTemplate { - t.Errorf("(%v) GetHostTemplate not equal: expected %v, got %v", test.title, hostTemplate, routeHostTemplate) - } -} + res := new(http.ResponseWriter) + r.ServeHTTP(*res, req) -func testMethods(t *testing.T, test routeTest) { - route := test.route - methods, _ := route.GetMethods() - if strings.Join(methods, ",") != strings.Join(test.methods, ",") { - t.Errorf("(%v) GetMethods not equal: expected %v, got %v", test.title, test.methods, methods) + if _, ok := context.GetOk(req, "t"); ok { + t.Error("Context should have been cleared at end of request") } -} -func testRegexp(t *testing.T, test routeTest) { - route := test.route - routePathRegexp, regexpErr := route.GetPathRegexp() - if test.pathRegexp != "" && regexpErr == nil && routePathRegexp != test.pathRegexp { - t.Errorf("(%v) GetPathRegexp not equal: expected %v, got %v", test.title, test.pathRegexp, routePathRegexp) - } -} + r.KeepContext = true -func testQueriesRegexp(t *testing.T, test routeTest) { - route := test.route - queries, queriesErr := route.GetQueriesRegexp() - gotQueries := strings.Join(queries, ",") - if test.queriesRegexp != "" && queriesErr == nil && gotQueries != test.queriesRegexp { - t.Errorf("(%v) GetQueriesRegexp not equal: expected %v, got %v", test.title, test.queriesRegexp, gotQueries) - } -} + req, _ = http.NewRequest("GET", "http://localhost/", nil) + context.Set(req, "t", 1) -func testQueriesTemplates(t *testing.T, test routeTest) { - route := test.route - queries, queriesErr := route.GetQueriesTemplates() - gotQueries := strings.Join(queries, ",") - if test.queriesTemplate != "" && queriesErr == nil && gotQueries != test.queriesTemplate { - t.Errorf("(%v) GetQueriesTemplates not equal: expected %v, got %v", test.title, test.queriesTemplate, gotQueries) + r.ServeHTTP(*res, req) + if _, ok := context.GetOk(req, "t"); !ok { + t.Error("Context should NOT have been cleared at end of request") } + } type TestA301ResponseWriter struct { @@ -1794,15 +841,15 @@ type TestA301ResponseWriter struct { status int } -func (ho *TestA301ResponseWriter) Header() http.Header { +func (ho TestA301ResponseWriter) Header() http.Header { return http.Header(ho.hh) } -func (ho *TestA301ResponseWriter) Write(b []byte) (int, error) { +func (ho TestA301ResponseWriter) Write(b []byte) (int, error) { return 0, nil } -func (ho *TestA301ResponseWriter) WriteHeader(code int) { +func (ho TestA301ResponseWriter) WriteHeader(code int) { ho.status = code } @@ -1829,24 +876,6 @@ func Test301Redirect(t *testing.T) { } } -func TestSkipClean(t *testing.T) { - func1 := func(w http.ResponseWriter, r *http.Request) {} - func2 := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.SkipClean(true) - r.HandleFunc("/api/", func2).Name("func2") - r.HandleFunc("/", func1).Name("func1") - - req, _ := http.NewRequest("GET", "http://localhost//api/?abc=def", nil) - res := NewRecorder() - r.ServeHTTP(res, req) - - if len(res.HeaderMap["Location"]) != 0 { - t.Errorf("Shouldn't redirect since skip clean is disabled") - } -} - // https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW func TestSubrouterHeader(t *testing.T) { expected := "func1 response" @@ -1877,417 +906,6 @@ func TestSubrouterHeader(t *testing.T) { } } -func TestNoMatchMethodErrorHandler(t *testing.T) { - func1 := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.HandleFunc("/", func1).Methods("GET", "POST") - - req, _ := http.NewRequest("PUT", "http://localhost/", nil) - match := new(RouteMatch) - matched := r.Match(req, match) - - if matched { - t.Error("Should not have matched route for methods") - } - - if match.MatchErr != ErrMethodMismatch { - t.Error("Should get ErrMethodMismatch error") - } - - resp := NewRecorder() - r.ServeHTTP(resp, req) - if resp.Code != 405 { - t.Errorf("Expecting code %v", 405) - } - - // Add matching route - r.HandleFunc("/", func1).Methods("PUT") - - match = new(RouteMatch) - matched = r.Match(req, match) - - if !matched { - t.Error("Should have matched route for methods") - } - - if match.MatchErr != nil { - t.Error("Should not have any matching error. Found:", match.MatchErr) - } -} - -func TestErrMatchNotFound(t *testing.T) { - emptyHandler := func(w http.ResponseWriter, r *http.Request) {} - - r := NewRouter() - r.HandleFunc("/", emptyHandler) - s := r.PathPrefix("/sub/").Subrouter() - s.HandleFunc("/", emptyHandler) - - // Regular 404 not found - req, _ := http.NewRequest("GET", "/sub/whatever", nil) - match := new(RouteMatch) - matched := r.Match(req, match) - - if matched { - t.Errorf("Subrouter should not have matched that, got %v", match.Route) - } - // Even without a custom handler, MatchErr is set to ErrNotFound - if match.MatchErr != ErrNotFound { - t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr) - } - - // Now lets add a 404 handler to subrouter - s.NotFoundHandler = http.NotFoundHandler() - req, _ = http.NewRequest("GET", "/sub/whatever", nil) - - // Test the subrouter first - match = new(RouteMatch) - matched = s.Match(req, match) - // Now we should get a match - if !matched { - t.Errorf("Subrouter should have matched %s", req.RequestURI) - } - // But MatchErr should be set to ErrNotFound anyway - if match.MatchErr != ErrNotFound { - t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr) - } - - // Now test the parent (MatchErr should propagate) - match = new(RouteMatch) - matched = r.Match(req, match) - - // Now we should get a match - if !matched { - t.Errorf("Router should have matched %s via subrouter", req.RequestURI) - } - // But MatchErr should be set to ErrNotFound anyway - if match.MatchErr != ErrNotFound { - t.Errorf("Expected ErrNotFound MatchErr, but was %v", match.MatchErr) - } -} - -// methodsSubrouterTest models the data necessary for testing handler -// matching for subrouters created after HTTP methods matcher registration. -type methodsSubrouterTest struct { - title string - wantCode int - router *Router - // method is the input into the request and expected response - method string - // input request path - path string - // redirectTo is the expected location path for strict-slash matches - redirectTo string -} - -// methodHandler writes the method string in response. -func methodHandler(method string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(method)) - } -} - -// TestMethodsSubrouterCatchall matches handlers for subrouters where a -// catchall handler is set for a mis-matching method. -func TestMethodsSubrouterCatchall(t *testing.T) { - t.Parallel() - - router := NewRouter() - router.Methods("PATCH").Subrouter().PathPrefix("/").HandlerFunc(methodHandler("PUT")) - router.Methods("GET").Subrouter().HandleFunc("/foo", methodHandler("GET")) - router.Methods("POST").Subrouter().HandleFunc("/foo", methodHandler("POST")) - router.Methods("DELETE").Subrouter().HandleFunc("/foo", methodHandler("DELETE")) - - tests := []methodsSubrouterTest{ - { - title: "match GET handler", - router: router, - path: "http://localhost/foo", - method: "GET", - wantCode: http.StatusOK, - }, - { - title: "match POST handler", - router: router, - method: "POST", - path: "http://localhost/foo", - wantCode: http.StatusOK, - }, - { - title: "match DELETE handler", - router: router, - method: "DELETE", - path: "http://localhost/foo", - wantCode: http.StatusOK, - }, - { - title: "disallow PUT method", - router: router, - method: "PUT", - path: "http://localhost/foo", - wantCode: http.StatusMethodNotAllowed, - }, - } - - for _, test := range tests { - testMethodsSubrouter(t, test) - } -} - -// TestMethodsSubrouterStrictSlash matches handlers on subrouters with -// strict-slash matchers. -func TestMethodsSubrouterStrictSlash(t *testing.T) { - t.Parallel() - - router := NewRouter() - sub := router.PathPrefix("/").Subrouter() - sub.StrictSlash(true).Path("/foo").Methods("GET").Subrouter().HandleFunc("", methodHandler("GET")) - sub.StrictSlash(true).Path("/foo/").Methods("PUT").Subrouter().HandleFunc("/", methodHandler("PUT")) - sub.StrictSlash(true).Path("/foo/").Methods("POST").Subrouter().HandleFunc("/", methodHandler("POST")) - - tests := []methodsSubrouterTest{ - { - title: "match POST handler", - router: router, - method: "POST", - path: "http://localhost/foo/", - wantCode: http.StatusOK, - }, - { - title: "match GET handler", - router: router, - method: "GET", - path: "http://localhost/foo", - wantCode: http.StatusOK, - }, - { - title: "match POST handler, redirect strict-slash", - router: router, - method: "POST", - path: "http://localhost/foo", - redirectTo: "http://localhost/foo/", - wantCode: http.StatusMovedPermanently, - }, - { - title: "match GET handler, redirect strict-slash", - router: router, - method: "GET", - path: "http://localhost/foo/", - redirectTo: "http://localhost/foo", - wantCode: http.StatusMovedPermanently, - }, - { - title: "disallow DELETE method", - router: router, - method: "DELETE", - path: "http://localhost/foo", - wantCode: http.StatusMethodNotAllowed, - }, - } - - for _, test := range tests { - testMethodsSubrouter(t, test) - } -} - -// TestMethodsSubrouterPathPrefix matches handlers on subrouters created -// on a router with a path prefix matcher and method matcher. -func TestMethodsSubrouterPathPrefix(t *testing.T) { - t.Parallel() - - router := NewRouter() - router.PathPrefix("/1").Methods("POST").Subrouter().HandleFunc("/2", methodHandler("POST")) - router.PathPrefix("/1").Methods("DELETE").Subrouter().HandleFunc("/2", methodHandler("DELETE")) - router.PathPrefix("/1").Methods("PUT").Subrouter().HandleFunc("/2", methodHandler("PUT")) - router.PathPrefix("/1").Methods("POST").Subrouter().HandleFunc("/2", methodHandler("POST2")) - - tests := []methodsSubrouterTest{ - { - title: "match first POST handler", - router: router, - method: "POST", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "match DELETE handler", - router: router, - method: "DELETE", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "match PUT handler", - router: router, - method: "PUT", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "disallow PATCH method", - router: router, - method: "PATCH", - path: "http://localhost/1/2", - wantCode: http.StatusMethodNotAllowed, - }, - } - - for _, test := range tests { - testMethodsSubrouter(t, test) - } -} - -// TestMethodsSubrouterSubrouter matches handlers on subrouters produced -// from method matchers registered on a root subrouter. -func TestMethodsSubrouterSubrouter(t *testing.T) { - t.Parallel() - - router := NewRouter() - sub := router.PathPrefix("/1").Subrouter() - sub.Methods("POST").Subrouter().HandleFunc("/2", methodHandler("POST")) - sub.Methods("GET").Subrouter().HandleFunc("/2", methodHandler("GET")) - sub.Methods("PATCH").Subrouter().HandleFunc("/2", methodHandler("PATCH")) - sub.HandleFunc("/2", methodHandler("PUT")).Subrouter().Methods("PUT") - sub.HandleFunc("/2", methodHandler("POST2")).Subrouter().Methods("POST") - - tests := []methodsSubrouterTest{ - { - title: "match first POST handler", - router: router, - method: "POST", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "match GET handler", - router: router, - method: "GET", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "match PATCH handler", - router: router, - method: "PATCH", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "match PUT handler", - router: router, - method: "PUT", - path: "http://localhost/1/2", - wantCode: http.StatusOK, - }, - { - title: "disallow DELETE method", - router: router, - method: "DELETE", - path: "http://localhost/1/2", - wantCode: http.StatusMethodNotAllowed, - }, - } - - for _, test := range tests { - testMethodsSubrouter(t, test) - } -} - -// TestMethodsSubrouterPathVariable matches handlers on matching paths -// with path variables in them. -func TestMethodsSubrouterPathVariable(t *testing.T) { - t.Parallel() - - router := NewRouter() - router.Methods("GET").Subrouter().HandleFunc("/foo", methodHandler("GET")) - router.Methods("POST").Subrouter().HandleFunc("/{any}", methodHandler("POST")) - router.Methods("DELETE").Subrouter().HandleFunc("/1/{any}", methodHandler("DELETE")) - router.Methods("PUT").Subrouter().HandleFunc("/1/{any}", methodHandler("PUT")) - - tests := []methodsSubrouterTest{ - { - title: "match GET handler", - router: router, - method: "GET", - path: "http://localhost/foo", - wantCode: http.StatusOK, - }, - { - title: "match POST handler", - router: router, - method: "POST", - path: "http://localhost/foo", - wantCode: http.StatusOK, - }, - { - title: "match DELETE handler", - router: router, - method: "DELETE", - path: "http://localhost/1/foo", - wantCode: http.StatusOK, - }, - { - title: "match PUT handler", - router: router, - method: "PUT", - path: "http://localhost/1/foo", - wantCode: http.StatusOK, - }, - { - title: "disallow PATCH method", - router: router, - method: "PATCH", - path: "http://localhost/1/foo", - wantCode: http.StatusMethodNotAllowed, - }, - } - - for _, test := range tests { - testMethodsSubrouter(t, test) - } -} - -func ExampleSetURLVars() { - req, _ := http.NewRequest("GET", "/foo", nil) - req = SetURLVars(req, map[string]string{"foo": "bar"}) - - fmt.Println(Vars(req)["foo"]) - - // Output: bar -} - -// testMethodsSubrouter runs an individual methodsSubrouterTest. -func testMethodsSubrouter(t *testing.T, test methodsSubrouterTest) { - // Execute request - req, _ := http.NewRequest(test.method, test.path, nil) - resp := NewRecorder() - test.router.ServeHTTP(resp, req) - - switch test.wantCode { - case http.StatusMethodNotAllowed: - if resp.Code != http.StatusMethodNotAllowed { - t.Errorf(`(%s) Expected "405 Method Not Allowed", but got %d code`, test.title, resp.Code) - } else if matchedMethod := resp.Body.String(); matchedMethod != "" { - t.Errorf(`(%s) Expected "405 Method Not Allowed", but %q handler was called`, test.title, matchedMethod) - } - - case http.StatusMovedPermanently: - if gotLocation := resp.HeaderMap.Get("Location"); gotLocation != test.redirectTo { - t.Errorf("(%s) Expected %q route-match to redirect to %q, but got %q", test.title, test.method, test.redirectTo, gotLocation) - } - - case http.StatusOK: - if matchedMethod := resp.Body.String(); matchedMethod != test.method { - t.Errorf("(%s) Expected %q handler to be called, but %q handler was called", test.title, test.method, matchedMethod) - } - - default: - expectedCodes := []int{http.StatusMethodNotAllowed, http.StatusMovedPermanently, http.StatusOK} - t.Errorf("(%s) Expected wantCode to be one of: %v, but got %d", test.title, expectedCodes, test.wantCode) - } -} - // mapToPairs converts a string map to a slice of string pairs func mapToPairs(m map[string]string) []string { var i int @@ -2315,50 +933,11 @@ func stringMapEqual(m1, m2 map[string]string) bool { return true } -// stringHandler returns a handler func that writes a message 's' to the -// http.ResponseWriter. -func stringHandler(s string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(s)) - } -} - -// newRequest is a helper function to create a new request with a method and url. -// The request returned is a 'server' request as opposed to a 'client' one through -// simulated write onto the wire and read off of the wire. -// The differences between requests are detailed in the net/http package. +// newRequest is a helper function to create a new request with a method and url func newRequest(method, url string) *http.Request { req, err := http.NewRequest(method, url, nil) if err != nil { panic(err) } - // extract the escaped original host+path from url - // http://localhost/path/here?v=1#frag -> //localhost/path/here - opaque := "" - if i := len(req.URL.Scheme); i > 0 { - opaque = url[i+1:] - } - - if i := strings.LastIndex(opaque, "?"); i > -1 { - opaque = opaque[:i] - } - if i := strings.LastIndex(opaque, "#"); i > -1 { - opaque = opaque[:i] - } - - // Escaped host+path workaround as detailed in https://golang.org/pkg/net/url/#URL - // for < 1.5 client side workaround - req.URL.Opaque = opaque - - // Simulate writing to wire - var buff bytes.Buffer - req.Write(&buff) - ioreader := bufio.NewReader(&buff) - - // Parse request off of 'wire' - req, err = http.ReadRequest(ioreader) - if err != nil { - panic(err) - } return req } diff --git a/vendor/github.com/gorilla/mux/old_test.go b/vendor/github.com/gorilla/mux/old_test.go index b228983c4834..1f7c190c0f97 100644 --- a/vendor/github.com/gorilla/mux/old_test.go +++ b/vendor/github.com/gorilla/mux/old_test.go @@ -36,6 +36,10 @@ func NewRecorder() *ResponseRecorder { } } +// DefaultRemoteAddr is the default remote address to return in RemoteAddr if +// an explicit DefaultRemoteAddr isn't set on ResponseRecorder. +const DefaultRemoteAddr = "1.2.3.4" + // Header returns the response headers. func (rw *ResponseRecorder) Header() http.Header { return rw.HeaderMap @@ -121,7 +125,12 @@ func TestRouteMatchers(t *testing.T) { var routeMatch RouteMatch matched := router.Match(request, &routeMatch) if matched != shouldMatch { - t.Errorf("Expected: %v\nGot: %v\nRequest: %v %v", shouldMatch, matched, request.Method, url) + // Need better messages. :) + if matched { + t.Errorf("Should match.") + } else { + t.Errorf("Should not match.") + } } if matched { @@ -183,6 +192,7 @@ func TestRouteMatchers(t *testing.T) { match(true) // 2nd route -------------------------------------------------------------- + // Everything match. reset2() match(true) @@ -535,7 +545,7 @@ func TestMatchedRouteName(t *testing.T) { router := NewRouter() route := router.NewRoute().Path("/products/").Name(routeName) - url := "http://www.example.com/products/" + url := "http://www.domain.com/products/" request, _ := http.NewRequest("GET", url, nil) var rv RouteMatch ok := router.Match(request, &rv) @@ -553,10 +563,10 @@ func TestMatchedRouteName(t *testing.T) { func TestSubRouting(t *testing.T) { // Example from docs. router := NewRouter() - subrouter := router.NewRoute().Host("www.example.com").Subrouter() + subrouter := router.NewRoute().Host("www.domain.com").Subrouter() route := subrouter.NewRoute().Path("/products/").Name("products") - url := "http://www.example.com/products/" + url := "http://www.domain.com/products/" request, _ := http.NewRequest("GET", url, nil) var rv RouteMatch ok := router.Match(request, &rv) @@ -566,10 +576,10 @@ func TestSubRouting(t *testing.T) { } u, _ := router.Get("products").URL() - builtURL := u.String() + builtUrl := u.String() // Yay, subroute aware of the domain when building! - if builtURL != url { - t.Errorf("Expected %q, got %q.", url, builtURL) + if builtUrl != url { + t.Errorf("Expected %q, got %q.", url, builtUrl) } } @@ -681,7 +691,7 @@ func TestNewRegexp(t *testing.T) { } for pattern, paths := range tests { - p, _ = newRouteRegexp(pattern, regexpTypePath, routeRegexpOptions{}) + p, _ = newRouteRegexp(pattern, false, false, false, false) for path, result := range paths { matches = p.regexp.FindStringSubmatch(path) if result == nil { diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index 2b57e5627d54..a6305483d5ae 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -10,24 +10,9 @@ import ( "net/http" "net/url" "regexp" - "strconv" "strings" ) -type routeRegexpOptions struct { - strictSlash bool - useEncodedPath bool -} - -type regexpType int - -const ( - regexpTypePath regexpType = 0 - regexpTypeHost regexpType = 1 - regexpTypePrefix regexpType = 2 - regexpTypeQuery regexpType = 3 -) - // newRouteRegexp parses a route template and returns a routeRegexp, // used to match a host, a path or a query string. // @@ -38,7 +23,7 @@ const ( // Previously we accepted only Python-like identifiers for variable // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that // name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { +func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { // Check if it is well-formed. idxs, errBraces := braceIndices(tpl) if errBraces != nil { @@ -48,25 +33,29 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro template := tpl // Now let's parse it. defaultPattern := "[^/]+" - if typ == regexpTypeQuery { - defaultPattern = ".*" - } else if typ == regexpTypeHost { + if matchQuery { + defaultPattern = "[^?&]+" + matchPrefix = true + } else if matchHost { defaultPattern = "[^.]+" + matchPrefix = false } // Only match strict slash if not matching - if typ != regexpTypePath { - options.strictSlash = false + if matchPrefix || matchHost || matchQuery { + strictSlash = false } // Set a flag for strictSlash. endSlash := false - if options.strictSlash && strings.HasSuffix(tpl, "/") { + if strictSlash && strings.HasSuffix(tpl, "/") { tpl = tpl[:len(tpl)-1] endSlash = true } varsN := make([]string, len(idxs)/2) varsR := make([]*regexp.Regexp, len(idxs)/2) pattern := bytes.NewBufferString("") - pattern.WriteByte('^') + if !matchQuery { + pattern.WriteByte('^') + } reverse := bytes.NewBufferString("") var end int var err error @@ -86,11 +75,9 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro tpl[idxs[i]:end]) } // Build the regexp pattern. - fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt) - + fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) // Build the reverse template. fmt.Fprintf(reverse, "%s%%s", raw) - // Append variable name and compiled pattern. varsN[i/2] = name varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) @@ -101,16 +88,10 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro // Add the remaining. raw := tpl[end:] pattern.WriteString(regexp.QuoteMeta(raw)) - if options.strictSlash { + if strictSlash { pattern.WriteString("[/]?") } - if typ == regexpTypeQuery { - // Add the default pattern if the query value is empty - if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { - pattern.WriteString(defaultPattern) - } - } - if typ != regexpTypePrefix { + if !matchPrefix { pattern.WriteByte('$') } reverse.WriteString(raw) @@ -122,22 +103,16 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro if errCompile != nil { return nil, errCompile } - - // Check for capturing groups which used to work in older versions - if reg.NumSubexp() != len(idxs)/2 { - panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + - "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") - } - // Done! return &routeRegexp{ - template: template, - regexpType: typ, - options: options, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, + template: template, + matchHost: matchHost, + matchQuery: matchQuery, + strictSlash: strictSlash, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, }, nil } @@ -146,10 +121,12 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro type routeRegexp struct { // The unmodified template. template string - // The type of match - regexpType regexpType - // Options for matching - options routeRegexpOptions + // True for host match, false for path or query string match. + matchHost bool + // True for query string match, false for path and host match. + matchQuery bool + // The strictSlash value defined on the route, but disabled if PathPrefix was used. + strictSlash bool // Expanded regexp. regexp *regexp.Regexp // Reverse template. @@ -162,31 +139,28 @@ type routeRegexp struct { // Match matches the regexp against the URL host or path. func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if r.regexpType != regexpTypeHost { - if r.regexpType == regexpTypeQuery { - return r.matchQueryString(req) + if !r.matchHost { + if r.matchQuery { + return r.regexp.MatchString(req.URL.RawQuery) + } else { + return r.regexp.MatchString(req.URL.Path) } - path := req.URL.Path - if r.options.useEncodedPath { - path = req.URL.EscapedPath() - } - return r.regexp.MatchString(path) } - return r.regexp.MatchString(getHost(req)) } // url builds a URL part using the given values. -func (r *routeRegexp) url(values map[string]string) (string, error) { +func (r *routeRegexp) url(pairs ...string) (string, error) { + values, err := mapFromPairs(pairs...) + if err != nil { + return "", err + } urlValues := make([]interface{}, len(r.varsN)) for k, v := range r.varsN { value, ok := values[v] if !ok { return "", fmt.Errorf("mux: missing route variable %q", v) } - if r.regexpType == regexpTypeQuery { - value = url.QueryEscape(value) - } urlValues[k] = value } rv := fmt.Sprintf(r.reverse, urlValues...) @@ -205,31 +179,11 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { return rv, nil } -// getURLQuery returns a single query parameter from a request URL. -// For a URL with foo=bar&baz=ding, we return only the relevant key -// value pair for the routeRegexp. -func (r *routeRegexp) getURLQuery(req *http.Request) string { - if r.regexpType != regexpTypeQuery { - return "" - } - templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } - } - return "" -} - -func (r *routeRegexp) matchQueryString(req *http.Request) bool { - return r.regexp.MatchString(r.getURLQuery(req)) -} - // braceIndices returns the first level curly brace indices from a string. // It returns an error in case of unbalanced braces. func braceIndices(s string) ([]int, error) { var level, idx int - var idxs []int + idxs := make([]int, 0) for i := 0; i < len(s); i++ { switch s[i] { case '{': @@ -250,11 +204,6 @@ func braceIndices(s string) ([]int, error) { return idxs, nil } -// varGroupName builds a capturing group name for the indexed variable. -func varGroupName(idx int) string { - return "v" + strconv.Itoa(idx) -} - // ---------------------------------------------------------------------------- // routeRegexpGroup // ---------------------------------------------------------------------------- @@ -270,24 +219,23 @@ type routeRegexpGroup struct { func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { // Store host variables. if v.host != nil { - host := getHost(req) - matches := v.host.regexp.FindStringSubmatchIndex(host) - if len(matches) > 0 { - extractVars(host, matches, v.host.varsN, m.Vars) + hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) + if hostVars != nil { + for k, v := range v.host.varsN { + m.Vars[v] = hostVars[k+1] + } } } - path := req.URL.Path - if r.useEncodedPath { - path = req.URL.EscapedPath() - } // Store path variables. if v.path != nil { - matches := v.path.regexp.FindStringSubmatchIndex(path) - if len(matches) > 0 { - extractVars(path, matches, v.path.varsN, m.Vars) + pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) + if pathVars != nil { + for k, v := range v.path.varsN { + m.Vars[v] = pathVars[k+1] + } // Check if we should redirect. - if v.path.options.strictSlash { - p1 := strings.HasSuffix(path, "/") + if v.path.strictSlash { + p1 := strings.HasSuffix(req.URL.Path, "/") p2 := strings.HasSuffix(v.path.template, "/") if p1 != p2 { u, _ := url.Parse(req.URL.String()) @@ -302,11 +250,13 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } } // Store query string variables. + rawQuery := req.URL.RawQuery for _, q := range v.queries { - queryURL := q.getURLQuery(req) - matches := q.regexp.FindStringSubmatchIndex(queryURL) - if len(matches) > 0 { - extractVars(queryURL, matches, q.varsN, m.Vars) + queryVars := q.regexp.FindStringSubmatch(rawQuery) + if queryVars != nil { + for k, v := range q.varsN { + m.Vars[v] = queryVars[k+1] + } } } } @@ -324,9 +274,3 @@ func getHost(r *http.Request) string { return host } - -func extractVars(input string, matches []int, names []string, output map[string]string) { - for i, name := range names { - output[name] = input[matches[2*i+2]:matches[2*i+3]] - } -} diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index a591d7354500..c310e66bc7c3 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -9,7 +9,6 @@ import ( "fmt" "net/http" "net/url" - "regexp" "strings" ) @@ -26,27 +25,12 @@ type Route struct { // If true, when the path pattern is "/path/", accessing "/path" will // redirect to the former and vice versa. strictSlash bool - // If true, when the path pattern is "/path//to", accessing "/path//to" - // will not redirect - skipClean bool - // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" - useEncodedPath bool - // The scheme used when building URLs. - buildScheme string // If true, this route never matches: it is only used to build URLs. buildOnly bool // The name used to build URLs. name string // Error resulted from building a route. err error - - buildVarsFunc BuildVarsFunc -} - -// SkipClean reports whether path cleaning is enabled for this route via -// Router.SkipClean. -func (r *Route) SkipClean() bool { - return r.skipClean } // Match matches the route against the request. @@ -54,33 +38,12 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if r.buildOnly || r.err != nil { return false } - - var matchErr error - // Match everything. for _, m := range r.matchers { if matched := m.Match(req, match); !matched { - if _, ok := m.(methodMatcher); ok { - matchErr = ErrMethodMismatch - continue - } - matchErr = nil return false } } - - if matchErr != nil { - match.MatchErr = matchErr - return false - } - - if match.MatchErr == ErrMethodMismatch { - // We found a route which matches request method, clear MatchErr - match.MatchErr = nil - // Then override the mis-matched handler - match.Handler = r.handler - } - // Yay, we have a match. Let's collect some info about it. if match.Route == nil { match.Route = r @@ -91,7 +54,6 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if match.Vars == nil { match.Vars = make(map[string]string) } - // Set variables. if r.regexp != nil { r.regexp.setMatch(req, match, r) @@ -173,23 +135,20 @@ func (r *Route) addMatcher(m matcher) *Route { } // addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { +func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { if r.err != nil { return r.err } r.regexp = r.getRegexpGroup() - if typ == regexpTypePath || typ == regexpTypePrefix { - if len(tpl) > 0 && tpl[0] != '/' { + if !matchHost && !matchQuery { + if len(tpl) == 0 || tpl[0] != '/' { return fmt.Errorf("mux: path must start with a slash, got %q", tpl) } if r.regexp.path != nil { tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl } } - rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ - strictSlash: r.strictSlash, - useEncodedPath: r.useEncodedPath, - }) + rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) if err != nil { return err } @@ -198,7 +157,7 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { return err } } - if typ == regexpTypeHost { + if matchHost { if r.regexp.path != nil { if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { return err @@ -211,7 +170,7 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { return err } } - if typ == regexpTypeQuery { + if matchQuery { r.regexp.queries = append(r.regexp.queries, rr) } else { r.regexp.path = rr @@ -227,7 +186,7 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { type headerMatcher map[string]string func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithString(m, r.Header, true) + return matchMap(m, r.Header, true) } // Headers adds a matcher for request header values. @@ -238,47 +197,22 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { // "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both request header values match. -// If the value is an empty string, it will match any value if the key is set. +// +// It the value is an empty string, it will match any value if the key is set. func (r *Route) Headers(pairs ...string) *Route { if r.err == nil { var headers map[string]string - headers, r.err = mapFromPairsToString(pairs...) + headers, r.err = mapFromPairs(pairs...) return r.addMatcher(headerMatcher(headers)) } return r } -// headerRegexMatcher matches the request against the route given a regex for the header -type headerRegexMatcher map[string]*regexp.Regexp - -func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchMapWithRegex(m, r.Header, true) -} - -// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex -// support. For example: -// -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") -// -// The above route will only match if both the request header matches both regular expressions. -// If the value is an empty string, it will match any value if the key is set. -// Use the start and end of string anchors (^ and $) to match an exact value. -func (r *Route) HeadersRegexp(pairs ...string) *Route { - if r.err == nil { - var headers map[string]*regexp.Regexp - headers, r.err = mapFromPairsToRegex(pairs...) - return r.addMatcher(headerRegexMatcher(headers)) - } - return r -} - // Host ----------------------------------------------------------------------- // Host adds a matcher for the URL host. // It accepts a template with zero or more URL variables enclosed by {}. -// Variables can define an optional regexp pattern to be matched: +// Variables can define an optional regexp pattern to me matched: // // - {name} matches anything until the next dot. // @@ -287,14 +221,14 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route { // For example: // // r := mux.NewRouter() -// r.Host("www.example.com") +// r.Host("www.domain.com") // r.Host("{subdomain}.domain.com") // r.Host("{subdomain:[a-z]+}.domain.com") // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypeHost) + r.err = r.addRegexpMatcher(tpl, true, false, false) return r } @@ -303,7 +237,6 @@ func (r *Route) Host(tpl string) *Route { // MatcherFunc is the function signature used by custom matchers. type MatcherFunc func(*http.Request, *RouteMatch) bool -// Match returns the match for a given request. func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { return m(r, match) } @@ -337,7 +270,7 @@ func (r *Route) Methods(methods ...string) *Route { // Path adds a matcher for the URL path. // It accepts a template with zero or more URL variables enclosed by {}. The // template must start with a "/". -// Variables can define an optional regexp pattern to be matched: +// Variables can define an optional regexp pattern to me matched: // // - {name} matches anything until the next slash. // @@ -354,7 +287,7 @@ func (r *Route) Methods(methods ...string) *Route { // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypePath) + r.err = r.addRegexpMatcher(tpl, false, false, false) return r } @@ -370,7 +303,7 @@ func (r *Route) Path(tpl string) *Route { // Also note that the setting of Router.StrictSlash() has no effect on routes // with a PathPrefix matcher. func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) + r.err = r.addRegexpMatcher(tpl, false, true, false) return r } @@ -388,7 +321,7 @@ func (r *Route) PathPrefix(tpl string) *Route { // // It the value is an empty string, it will match any value if the key is set. // -// Variables can define an optional regexp pattern to be matched: +// Variables can define an optional regexp pattern to me matched: // // - {name} matches anything until the next slash. // @@ -401,7 +334,7 @@ func (r *Route) Queries(pairs ...string) *Route { return nil } for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, true, true); r.err != nil { return r } } @@ -424,25 +357,9 @@ func (r *Route) Schemes(schemes ...string) *Route { for k, v := range schemes { schemes[k] = strings.ToLower(v) } - if r.buildScheme == "" && len(schemes) > 0 { - r.buildScheme = schemes[0] - } return r.addMatcher(schemeMatcher(schemes)) } -// BuildVarsFunc -------------------------------------------------------------- - -// BuildVarsFunc is the function signature used by custom build variable -// functions (which can modify route variables before a route's URL is built). -type BuildVarsFunc func(map[string]string) map[string]string - -// BuildVarsFunc adds a custom function to be used to modify build variables -// before a route's URL is built. -func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { - r.buildVarsFunc = f - return r -} - // Subrouter ------------------------------------------------------------------ // Subrouter creates a subrouter for the route. @@ -450,7 +367,7 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { // It will test the inner routes only if the parent route matched. For example: // // r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() +// s := r.Host("www.domain.com").Subrouter() // s.HandleFunc("/products/", ProductsHandler) // s.HandleFunc("/products/{key}", ProductHandler) // s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) @@ -505,38 +422,24 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) { if r.regexp == nil { return nil, errors.New("mux: route doesn't have a host or path") } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } var scheme, host, path string - queries := make([]string, 0, len(r.regexp.queries)) + var err error if r.regexp.host != nil { - if host, err = r.regexp.host.url(values); err != nil { - return nil, err - } + // Set a default scheme. scheme = "http" - if s := r.getBuildScheme(); s != "" { - scheme = s - } - } - if r.regexp.path != nil { - if path, err = r.regexp.path.url(values); err != nil { + if host, err = r.regexp.host.url(pairs...); err != nil { return nil, err } } - for _, q := range r.regexp.queries { - var query string - if query, err = q.url(values); err != nil { + if r.regexp.path != nil { + if path, err = r.regexp.path.url(pairs...); err != nil { return nil, err } - queries = append(queries, query) } return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, - RawQuery: strings.Join(queries, "&"), + Scheme: scheme, + Host: host, + Path: path, }, nil } @@ -550,22 +453,14 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if r.regexp == nil || r.regexp.host == nil { return nil, errors.New("mux: route doesn't have a host") } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - host, err := r.regexp.host.url(values) + host, err := r.regexp.host.url(pairs...) if err != nil { return nil, err } - u := &url.URL{ + return &url.URL{ Scheme: "http", Host: host, - } - if s := r.getBuildScheme(); s != "" { - u.Scheme = s - } - return u, nil + }, nil } // URLPath builds the path part of the URL for a route. See Route.URL(). @@ -578,11 +473,7 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) { if r.regexp == nil || r.regexp.path == nil { return nil, errors.New("mux: route doesn't have a path") } - values, err := r.prepareVars(pairs...) - if err != nil { - return nil, err - } - path, err := r.regexp.path.url(values) + path, err := r.regexp.path.url(pairs...) if err != nil { return nil, err } @@ -591,144 +482,14 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) { }, nil } -// GetPathTemplate returns the template used to build the -// route match. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a path. -func (r *Route) GetPathTemplate() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.path == nil { - return "", errors.New("mux: route doesn't have a path") - } - return r.regexp.path.template, nil -} - -// GetPathRegexp returns the expanded regular expression used to match route path. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a path. -func (r *Route) GetPathRegexp() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.path == nil { - return "", errors.New("mux: route does not have a path") - } - return r.regexp.path.regexp.String(), nil -} - -// GetQueriesRegexp returns the expanded regular expressions used to match the -// route queries. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not have queries. -func (r *Route) GetQueriesRegexp() ([]string, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.queries == nil { - return nil, errors.New("mux: route doesn't have queries") - } - var queries []string - for _, query := range r.regexp.queries { - queries = append(queries, query.regexp.String()) - } - return queries, nil -} - -// GetQueriesTemplates returns the templates used to build the -// query matching. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define queries. -func (r *Route) GetQueriesTemplates() ([]string, error) { - if r.err != nil { - return nil, r.err - } - if r.regexp == nil || r.regexp.queries == nil { - return nil, errors.New("mux: route doesn't have queries") - } - var queries []string - for _, query := range r.regexp.queries { - queries = append(queries, query.template) - } - return queries, nil -} - -// GetMethods returns the methods the route matches against -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if route does not have methods. -func (r *Route) GetMethods() ([]string, error) { - if r.err != nil { - return nil, r.err - } - for _, m := range r.matchers { - if methods, ok := m.(methodMatcher); ok { - return []string(methods), nil - } - } - return nil, errors.New("mux: route doesn't have methods") -} - -// GetHostTemplate returns the template used to build the -// route match. -// This is useful for building simple REST API documentation and for instrumentation -// against third-party services. -// An error will be returned if the route does not define a host. -func (r *Route) GetHostTemplate() (string, error) { - if r.err != nil { - return "", r.err - } - if r.regexp == nil || r.regexp.host == nil { - return "", errors.New("mux: route doesn't have a host") - } - return r.regexp.host.template, nil -} - -// prepareVars converts the route variable pairs into a map. If the route has a -// BuildVarsFunc, it is invoked. -func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { - m, err := mapFromPairsToString(pairs...) - if err != nil { - return nil, err - } - return r.buildVars(m), nil -} - -func (r *Route) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - if r.buildVarsFunc != nil { - m = r.buildVarsFunc(m) - } - return m -} - // ---------------------------------------------------------------------------- // parentRoute // ---------------------------------------------------------------------------- // parentRoute allows routes to know about parent host and path definitions. type parentRoute interface { - getBuildScheme() string getNamedRoutes() map[string]*Route getRegexpGroup() *routeRegexpGroup - buildVars(map[string]string) map[string]string -} - -func (r *Route) getBuildScheme() string { - if r.buildScheme != "" { - return r.buildScheme - } - if r.parent != nil { - return r.parent.getBuildScheme() - } - return "" } // getNamedRoutes returns the map where named routes are registered. diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go deleted file mode 100644 index 32ecffde489f..000000000000 --- a/vendor/github.com/gorilla/mux/test_helpers.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mux - -import "net/http" - -// SetURLVars sets the URL variables for the given request, to be accessed via -// mux.Vars for testing route behaviour. Arguments are not modified, a shallow -// copy is returned. -// -// This API should only be used for testing purposes; it provides a way to -// inject variables into the request context. Alternatively, URL variables -// can be set by making a route that captures the required variables, -// starting a server and sending the request to that server. -func SetURLVars(r *http.Request, val map[string]string) *http.Request { - return setVars(r, val) -} diff --git a/vendor/github.com/openshift/api/authorization/install.go b/vendor/github.com/openshift/api/authorization/install.go index 2cb6e4369a49..08ecc95f49d7 100644 --- a/vendor/github.com/openshift/api/authorization/install.go +++ b/vendor/github.com/openshift/api/authorization/install.go @@ -1,4 +1,4 @@ -package apps +package authorization import ( "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/github.com/openshift/api/image/v1/generated.pb.go b/vendor/github.com/openshift/api/image/v1/generated.pb.go index cf5b1a799525..cec6c04de6fd 100644 --- a/vendor/github.com/openshift/api/image/v1/generated.pb.go +++ b/vendor/github.com/openshift/api/image/v1/generated.pb.go @@ -11,9 +11,11 @@ It has these top-level messages: DockerImageReference Image + ImageBlobReferences ImageImportSpec ImageImportStatus ImageLayer + ImageLayerData ImageList ImageLookupPolicy ImageSignature @@ -22,6 +24,7 @@ ImageStreamImport ImageStreamImportSpec ImageStreamImportStatus + ImageStreamLayers ImageStreamList ImageStreamMapping ImageStreamSpec @@ -76,130 +79,144 @@ func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} } +func (m *ImageBlobReferences) Reset() { *m = ImageBlobReferences{} } +func (*ImageBlobReferences) ProtoMessage() {} +func (*ImageBlobReferences) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} } + func (m *ImageImportSpec) Reset() { *m = ImageImportSpec{} } func (*ImageImportSpec) ProtoMessage() {} -func (*ImageImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} } +func (*ImageImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} } func (m *ImageImportStatus) Reset() { *m = ImageImportStatus{} } func (*ImageImportStatus) ProtoMessage() {} -func (*ImageImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} } +func (*ImageImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} } func (m *ImageLayer) Reset() { *m = ImageLayer{} } func (*ImageLayer) ProtoMessage() {} -func (*ImageLayer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} } +func (*ImageLayer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} } + +func (m *ImageLayerData) Reset() { *m = ImageLayerData{} } +func (*ImageLayerData) ProtoMessage() {} +func (*ImageLayerData) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} } func (m *ImageList) Reset() { *m = ImageList{} } func (*ImageList) ProtoMessage() {} -func (*ImageList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} } +func (*ImageList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} } func (m *ImageLookupPolicy) Reset() { *m = ImageLookupPolicy{} } func (*ImageLookupPolicy) ProtoMessage() {} -func (*ImageLookupPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} } +func (*ImageLookupPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} } func (m *ImageSignature) Reset() { *m = ImageSignature{} } func (*ImageSignature) ProtoMessage() {} -func (*ImageSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} } +func (*ImageSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } func (m *ImageStream) Reset() { *m = ImageStream{} } func (*ImageStream) ProtoMessage() {} -func (*ImageStream) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} } +func (*ImageStream) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } func (m *ImageStreamImage) Reset() { *m = ImageStreamImage{} } func (*ImageStreamImage) ProtoMessage() {} -func (*ImageStreamImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } +func (*ImageStreamImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } func (m *ImageStreamImport) Reset() { *m = ImageStreamImport{} } func (*ImageStreamImport) ProtoMessage() {} -func (*ImageStreamImport) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } +func (*ImageStreamImport) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *ImageStreamImportSpec) Reset() { *m = ImageStreamImportSpec{} } func (*ImageStreamImportSpec) ProtoMessage() {} -func (*ImageStreamImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*ImageStreamImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *ImageStreamImportStatus) Reset() { *m = ImageStreamImportStatus{} } func (*ImageStreamImportStatus) ProtoMessage() {} func (*ImageStreamImportStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{12} + return fileDescriptorGenerated, []int{14} } +func (m *ImageStreamLayers) Reset() { *m = ImageStreamLayers{} } +func (*ImageStreamLayers) ProtoMessage() {} +func (*ImageStreamLayers) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } + func (m *ImageStreamList) Reset() { *m = ImageStreamList{} } func (*ImageStreamList) ProtoMessage() {} -func (*ImageStreamList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*ImageStreamList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *ImageStreamMapping) Reset() { *m = ImageStreamMapping{} } func (*ImageStreamMapping) ProtoMessage() {} -func (*ImageStreamMapping) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*ImageStreamMapping) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *ImageStreamSpec) Reset() { *m = ImageStreamSpec{} } func (*ImageStreamSpec) ProtoMessage() {} -func (*ImageStreamSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*ImageStreamSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *ImageStreamStatus) Reset() { *m = ImageStreamStatus{} } func (*ImageStreamStatus) ProtoMessage() {} -func (*ImageStreamStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*ImageStreamStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *ImageStreamTag) Reset() { *m = ImageStreamTag{} } func (*ImageStreamTag) ProtoMessage() {} -func (*ImageStreamTag) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*ImageStreamTag) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *ImageStreamTagList) Reset() { *m = ImageStreamTagList{} } func (*ImageStreamTagList) ProtoMessage() {} -func (*ImageStreamTagList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*ImageStreamTagList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } func (m *NamedTagEventList) Reset() { *m = NamedTagEventList{} } func (*NamedTagEventList) ProtoMessage() {} -func (*NamedTagEventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*NamedTagEventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } func (m *RepositoryImportSpec) Reset() { *m = RepositoryImportSpec{} } func (*RepositoryImportSpec) ProtoMessage() {} -func (*RepositoryImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*RepositoryImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *RepositoryImportStatus) Reset() { *m = RepositoryImportStatus{} } func (*RepositoryImportStatus) ProtoMessage() {} -func (*RepositoryImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } +func (*RepositoryImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *SignatureCondition) Reset() { *m = SignatureCondition{} } func (*SignatureCondition) ProtoMessage() {} -func (*SignatureCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*SignatureCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *SignatureGenericEntity) Reset() { *m = SignatureGenericEntity{} } func (*SignatureGenericEntity) ProtoMessage() {} -func (*SignatureGenericEntity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*SignatureGenericEntity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *SignatureIssuer) Reset() { *m = SignatureIssuer{} } func (*SignatureIssuer) ProtoMessage() {} -func (*SignatureIssuer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*SignatureIssuer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *SignatureSubject) Reset() { *m = SignatureSubject{} } func (*SignatureSubject) ProtoMessage() {} -func (*SignatureSubject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*SignatureSubject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *TagEvent) Reset() { *m = TagEvent{} } func (*TagEvent) ProtoMessage() {} -func (*TagEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*TagEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *TagEventCondition) Reset() { *m = TagEventCondition{} } func (*TagEventCondition) ProtoMessage() {} -func (*TagEventCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*TagEventCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } func (m *TagImportPolicy) Reset() { *m = TagImportPolicy{} } func (*TagImportPolicy) ProtoMessage() {} -func (*TagImportPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } +func (*TagImportPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *TagReference) Reset() { *m = TagReference{} } func (*TagReference) ProtoMessage() {} -func (*TagReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*TagReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *TagReferencePolicy) Reset() { *m = TagReferencePolicy{} } func (*TagReferencePolicy) ProtoMessage() {} -func (*TagReferencePolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*TagReferencePolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func init() { proto.RegisterType((*DockerImageReference)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.DockerImageReference") proto.RegisterType((*Image)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.Image") + proto.RegisterType((*ImageBlobReferences)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageBlobReferences") proto.RegisterType((*ImageImportSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageImportSpec") proto.RegisterType((*ImageImportStatus)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageImportStatus") proto.RegisterType((*ImageLayer)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLayer") + proto.RegisterType((*ImageLayerData)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLayerData") proto.RegisterType((*ImageList)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageList") proto.RegisterType((*ImageLookupPolicy)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLookupPolicy") proto.RegisterType((*ImageSignature)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageSignature") @@ -208,6 +225,7 @@ func init() { proto.RegisterType((*ImageStreamImport)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImport") proto.RegisterType((*ImageStreamImportSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImportSpec") proto.RegisterType((*ImageStreamImportStatus)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImportStatus") + proto.RegisterType((*ImageStreamLayers)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamLayers") proto.RegisterType((*ImageStreamList)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamList") proto.RegisterType((*ImageStreamMapping)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamMapping") proto.RegisterType((*ImageStreamSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamSpec") @@ -351,6 +369,45 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageBlobReferences) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageBlobReferences) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Layers) > 0 { + for _, s := range m.Layers { + dAtA[i] = 0xa + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if m.Manifest != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Manifest))) + i += copy(dAtA[i:], *m.Manifest) + } + return i, nil +} + func (m *ImageImportSpec) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -480,6 +537,33 @@ func (m *ImageLayer) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageLayerData) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageLayerData) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.LayerSize != nil { + dAtA[i] = 0x8 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.LayerSize)) + } + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.MediaType))) + i += copy(dAtA[i:], m.MediaType) + return i, nil +} + func (m *ImageList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -864,6 +948,94 @@ func (m *ImageStreamImportStatus) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageStreamLayers) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageStreamLayers) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) + n25, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n25 + if len(m.Blobs) > 0 { + keysForBlobs := make([]string, 0, len(m.Blobs)) + for k := range m.Blobs { + keysForBlobs = append(keysForBlobs, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForBlobs) + for _, k := range keysForBlobs { + dAtA[i] = 0x12 + i++ + v := m.Blobs[string(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n26, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n26 + } + } + if len(m.Images) > 0 { + keysForImages := make([]string, 0, len(m.Images)) + for k := range m.Images { + keysForImages = append(keysForImages, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForImages) + for _, k := range keysForImages { + dAtA[i] = 0x1a + i++ + v := m.Images[string(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n27, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n27 + } + } + return i, nil +} + func (m *ImageStreamList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -882,11 +1054,11 @@ func (m *ImageStreamList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n25, err := m.ListMeta.MarshalTo(dAtA[i:]) + n28, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n28 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -920,19 +1092,19 @@ func (m *ImageStreamMapping) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n26, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n29, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n29 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Image.Size())) - n27, err := m.Image.MarshalTo(dAtA[i:]) + n30, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n30 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Tag))) @@ -974,11 +1146,11 @@ func (m *ImageStreamSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LookupPolicy.Size())) - n28, err := m.LookupPolicy.MarshalTo(dAtA[i:]) + n31, err := m.LookupPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n31 return i, nil } @@ -1038,20 +1210,20 @@ func (m *ImageStreamTag) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n29, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n32, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n32 if m.Tag != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Tag.Size())) - n30, err := m.Tag.MarshalTo(dAtA[i:]) + n33, err := m.Tag.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n33 } dAtA[i] = 0x18 i++ @@ -1071,19 +1243,19 @@ func (m *ImageStreamTag) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Image.Size())) - n31, err := m.Image.MarshalTo(dAtA[i:]) + n34, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n34 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LookupPolicy.Size())) - n32, err := m.LookupPolicy.MarshalTo(dAtA[i:]) + n35, err := m.LookupPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n35 return i, nil } @@ -1105,11 +1277,11 @@ func (m *ImageStreamTagList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n33, err := m.ListMeta.MarshalTo(dAtA[i:]) + n36, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n36 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -1189,19 +1361,19 @@ func (m *RepositoryImportSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.From.Size())) - n34, err := m.From.MarshalTo(dAtA[i:]) + n37, err := m.From.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n37 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ImportPolicy.Size())) - n35, err := m.ImportPolicy.MarshalTo(dAtA[i:]) + n38, err := m.ImportPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n38 dAtA[i] = 0x18 i++ if m.IncludeManifest { @@ -1213,11 +1385,11 @@ func (m *RepositoryImportSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReferencePolicy.Size())) - n36, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) + n39, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n39 return i, nil } @@ -1239,11 +1411,11 @@ func (m *RepositoryImportStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n37, err := m.Status.MarshalTo(dAtA[i:]) + n40, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n40 if len(m.Images) > 0 { for _, msg := range m.Images { dAtA[i] = 0x12 @@ -1300,19 +1472,19 @@ func (m *SignatureCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n38, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n41, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n41 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n39, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n42, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n42 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -1368,11 +1540,11 @@ func (m *SignatureIssuer) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SignatureGenericEntity.Size())) - n40, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) + n43, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n43 return i, nil } @@ -1394,11 +1566,11 @@ func (m *SignatureSubject) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SignatureGenericEntity.Size())) - n41, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) + n44, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n44 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PublicKeyID))) @@ -1424,11 +1596,11 @@ func (m *TagEvent) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Created.Size())) - n42, err := m.Created.MarshalTo(dAtA[i:]) + n45, err := m.Created.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n45 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.DockerImageReference))) @@ -1469,11 +1641,11 @@ func (m *TagEventCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n43, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n46, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n46 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -1567,11 +1739,11 @@ func (m *TagReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.From.Size())) - n44, err := m.From.MarshalTo(dAtA[i:]) + n47, err := m.From.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n47 } dAtA[i] = 0x20 i++ @@ -1589,19 +1761,19 @@ func (m *TagReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ImportPolicy.Size())) - n45, err := m.ImportPolicy.MarshalTo(dAtA[i:]) + n48, err := m.ImportPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n48 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReferencePolicy.Size())) - n46, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) + n49, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n49 return i, nil } @@ -1708,6 +1880,22 @@ func (m *Image) Size() (n int) { return n } +func (m *ImageBlobReferences) Size() (n int) { + var l int + _ = l + if len(m.Layers) > 0 { + for _, s := range m.Layers { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + if m.Manifest != nil { + l = len(*m.Manifest) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *ImageImportSpec) Size() (n int) { var l int _ = l @@ -1750,6 +1938,17 @@ func (m *ImageLayer) Size() (n int) { return n } +func (m *ImageLayerData) Size() (n int) { + var l int + _ = l + if m.LayerSize != nil { + n += 1 + sovGenerated(uint64(*m.LayerSize)) + } + l = len(m.MediaType) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ImageList) Size() (n int) { var l int _ = l @@ -1884,6 +2083,32 @@ func (m *ImageStreamImportStatus) Size() (n int) { return n } +func (m *ImageStreamLayers) Size() (n int) { + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Blobs) > 0 { + for k, v := range m.Blobs { + _ = k + _ = v + l = v.Size() + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + l + sovGenerated(uint64(l)) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + if len(m.Images) > 0 { + for k, v := range m.Images { + _ = k + _ = v + l = v.Size() + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + l + sovGenerated(uint64(l)) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + return n +} + func (m *ImageStreamList) Size() (n int) { var l int _ = l @@ -2198,6 +2423,17 @@ func (this *Image) String() string { }, "") return s } +func (this *ImageBlobReferences) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageBlobReferences{`, + `Layers:` + fmt.Sprintf("%v", this.Layers) + `,`, + `Manifest:` + valueToStringGenerated(this.Manifest) + `,`, + `}`, + }, "") + return s +} func (this *ImageImportSpec) String() string { if this == nil { return "nil" @@ -2236,6 +2472,17 @@ func (this *ImageLayer) String() string { }, "") return s } +func (this *ImageLayerData) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageLayerData{`, + `LayerSize:` + valueToStringGenerated(this.LayerSize) + `,`, + `MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`, + `}`, + }, "") + return s +} func (this *ImageList) String() string { if this == nil { return "nil" @@ -2344,6 +2591,38 @@ func (this *ImageStreamImportStatus) String() string { }, "") return s } +func (this *ImageStreamLayers) String() string { + if this == nil { + return "nil" + } + keysForBlobs := make([]string, 0, len(this.Blobs)) + for k := range this.Blobs { + keysForBlobs = append(keysForBlobs, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForBlobs) + mapStringForBlobs := "map[string]ImageLayerData{" + for _, k := range keysForBlobs { + mapStringForBlobs += fmt.Sprintf("%v: %v,", k, this.Blobs[k]) + } + mapStringForBlobs += "}" + keysForImages := make([]string, 0, len(this.Images)) + for k := range this.Images { + keysForImages = append(keysForImages, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForImages) + mapStringForImages := "map[string]ImageBlobReferences{" + for _, k := range keysForImages { + mapStringForImages += fmt.Sprintf("%v: %v,", k, this.Images[k]) + } + mapStringForImages += "}" + s := strings.Join([]string{`&ImageStreamLayers{`, + `ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Blobs:` + mapStringForBlobs + `,`, + `Images:` + mapStringForImages + `,`, + `}`, + }, "") + return s +} func (this *ImageStreamList) String() string { if this == nil { return "nil" @@ -3125,7 +3404,7 @@ func (m *Image) Unmarshal(dAtA []byte) error { } return nil } -func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { +func (m *ImageBlobReferences) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3148,17 +3427,17 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ImageImportSpec: wiretype end group for non-group") + return fmt.Errorf("proto: ImageBlobReferences: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ImageImportSpec: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ImageBlobReferences: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Layers", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -3168,27 +3447,26 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.From.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Layers = append(m.Layers, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Manifest", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -3198,32 +3476,142 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if m.To == nil { - m.To = &k8s_io_api_core_v1.LocalObjectReference{} - } - if err := m.To.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + s := string(dAtA[iNdEx:postIndex]) + m.Manifest = &s + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { return err } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ImportPolicy", wireType) + if skippy < 0 { + return ErrInvalidLengthGenerated } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageImportSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageImportSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.From.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.To == nil { + m.To = &k8s_io_api_core_v1.LocalObjectReference{} + } + if err := m.To.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ImportPolicy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { return ErrIntOverflowGenerated } if iNdEx >= l { @@ -3587,6 +3975,105 @@ func (m *ImageLayer) Unmarshal(dAtA []byte) error { } return nil } +func (m *ImageLayerData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageLayerData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageLayerData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LayerSize", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.LayerSize = &v + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MediaType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MediaType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -4854,6 +5341,328 @@ func (m *ImageStreamImportStatus) Unmarshal(dAtA []byte) error { } return nil } +func (m *ImageStreamLayers) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageStreamLayers: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageStreamLayers: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blobs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + if m.Blobs == nil { + m.Blobs = make(map[string]ImageLayerData) + } + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue := &ImageLayerData{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + m.Blobs[mapkey] = *mapvalue + } else { + var mapvalue ImageLayerData + m.Blobs[mapkey] = mapvalue + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + if m.Images == nil { + m.Images = make(map[string]ImageBlobReferences) + } + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue := &ImageBlobReferences{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + m.Images[mapkey] = *mapvalue + } else { + var mapvalue ImageBlobReferences + m.Images[mapkey] = mapvalue + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageStreamList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -7660,148 +8469,158 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2284 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0x4d, 0x8c, 0x1b, 0x49, - 0x15, 0x4e, 0xbb, 0xed, 0xb1, 0xe7, 0x8d, 0x33, 0x93, 0xa9, 0x64, 0xb2, 0xde, 0x49, 0xd6, 0x13, - 0x3a, 0x64, 0x15, 0x20, 0xdb, 0x66, 0x66, 0xb3, 0x90, 0x04, 0x09, 0x36, 0x8e, 0xc3, 0xca, 0x30, - 0x43, 0x66, 0x6b, 0x4c, 0x0e, 0x51, 0x90, 0xa8, 0x69, 0xd7, 0xf4, 0x14, 0x63, 0x77, 0x5b, 0xdd, - 0xed, 0xd9, 0x9d, 0x08, 0x24, 0x0e, 0x68, 0xb5, 0x07, 0x0e, 0x70, 0xde, 0x23, 0x42, 0x88, 0x33, - 0x02, 0x71, 0x07, 0xa4, 0x88, 0x0b, 0xab, 0xe5, 0xb2, 0x17, 0x46, 0xc4, 0x70, 0xe6, 0xc6, 0x65, - 0x4f, 0xa8, 0xaa, 0xab, 0x7f, 0xdd, 0x9e, 0xb4, 0x43, 0xc6, 0x82, 0x9b, 0x5d, 0xef, 0xbd, 0xaf, - 0x5e, 0xbd, 0x57, 0xef, 0xa7, 0x5e, 0xc3, 0xba, 0xc9, 0xbc, 0xfd, 0xe1, 0xae, 0x6e, 0xd8, 0xfd, - 0x86, 0x3d, 0xa0, 0x96, 0xbb, 0xcf, 0xf6, 0xbc, 0x06, 0x19, 0xb0, 0x06, 0xeb, 0x13, 0x93, 0x36, - 0x0e, 0xd7, 0x1b, 0x26, 0xb5, 0xa8, 0x43, 0x3c, 0xda, 0xd5, 0x07, 0x8e, 0xed, 0xd9, 0xe8, 0x73, - 0x91, 0x88, 0x1e, 0x8a, 0xe8, 0x64, 0xc0, 0x74, 0x21, 0xa2, 0x1f, 0xae, 0xaf, 0xbe, 0x11, 0x43, - 0x35, 0x6d, 0xd3, 0x6e, 0x08, 0xc9, 0xdd, 0xe1, 0x9e, 0xf8, 0x27, 0xfe, 0x88, 0x5f, 0x3e, 0xe2, - 0xaa, 0x76, 0x70, 0xcb, 0xd5, 0x99, 0x2d, 0xb6, 0x35, 0x6c, 0x27, 0x6b, 0xd7, 0xd5, 0x9b, 0x11, - 0x4f, 0x9f, 0x18, 0xfb, 0xcc, 0xa2, 0xce, 0x51, 0x63, 0x70, 0x60, 0xf2, 0x05, 0xb7, 0xd1, 0xa7, - 0x1e, 0xc9, 0x92, 0x6a, 0x4c, 0x92, 0x72, 0x86, 0x96, 0xc7, 0xfa, 0x74, 0x4c, 0xe0, 0x2b, 0xcf, - 0x13, 0x70, 0x8d, 0x7d, 0xda, 0x27, 0x63, 0x72, 0x6f, 0x4e, 0x92, 0x1b, 0x7a, 0xac, 0xd7, 0x60, - 0x96, 0xe7, 0x7a, 0x4e, 0x5a, 0x48, 0xfb, 0x44, 0x81, 0x0b, 0x2d, 0xdb, 0x38, 0xa0, 0x4e, 0x9b, - 0x5b, 0x0e, 0xd3, 0x3d, 0xea, 0x50, 0xcb, 0xa0, 0xe8, 0x06, 0x54, 0x1c, 0x6a, 0x32, 0xd7, 0x73, - 0x8e, 0x6a, 0xca, 0x15, 0xe5, 0xfa, 0x7c, 0xf3, 0xdc, 0xd3, 0xe3, 0xb5, 0x33, 0xa3, 0xe3, 0xb5, - 0x0a, 0x96, 0xeb, 0x38, 0xe4, 0x40, 0x0d, 0x98, 0xb7, 0x48, 0x9f, 0xba, 0x03, 0x62, 0xd0, 0x5a, - 0x41, 0xb0, 0x2f, 0x4b, 0xf6, 0xf9, 0xef, 0x04, 0x04, 0x1c, 0xf1, 0xa0, 0x2b, 0x50, 0xe4, 0x7f, - 0x6a, 0xaa, 0xe0, 0xad, 0x4a, 0xde, 0x22, 0xe7, 0xc5, 0x82, 0x82, 0x5e, 0x03, 0xd5, 0x23, 0x66, - 0xad, 0x28, 0x18, 0x16, 0x24, 0x83, 0xda, 0x21, 0x26, 0xe6, 0xeb, 0x68, 0x15, 0x0a, 0xac, 0x55, - 0x2b, 0x09, 0x2a, 0x48, 0x6a, 0xa1, 0xdd, 0xc2, 0x05, 0xd6, 0xd2, 0xfe, 0x52, 0x86, 0x92, 0x38, - 0x0e, 0xfa, 0x3e, 0x54, 0xb8, 0x5f, 0xba, 0xc4, 0x23, 0xe2, 0x14, 0x0b, 0x1b, 0x5f, 0xd6, 0x7d, - 0x33, 0xe9, 0x71, 0x33, 0xe9, 0x83, 0x03, 0x93, 0x2f, 0xb8, 0x3a, 0xe7, 0xd6, 0x0f, 0xd7, 0xf5, - 0x07, 0xbb, 0x3f, 0xa0, 0x86, 0xb7, 0x45, 0x3d, 0xd2, 0x44, 0x12, 0x1d, 0xa2, 0x35, 0x1c, 0xa2, - 0xa2, 0x6d, 0xb8, 0xd0, 0xcd, 0xb0, 0x9f, 0x34, 0xc2, 0x65, 0x29, 0x9b, 0x69, 0x63, 0x9c, 0x29, - 0x89, 0x7e, 0x08, 0xe7, 0x63, 0xeb, 0x5b, 0x81, 0xfa, 0xaa, 0x50, 0xff, 0x8d, 0x89, 0xea, 0xcb, - 0xdb, 0xa1, 0x63, 0xf2, 0xde, 0xfd, 0xf7, 0x3d, 0x6a, 0xb9, 0xcc, 0xb6, 0x9a, 0x97, 0xe4, 0xfe, - 0xe7, 0x5b, 0xe3, 0x88, 0x38, 0x6b, 0x1b, 0xb4, 0x0b, 0xab, 0x19, 0xcb, 0x0f, 0xa9, 0xc3, 0xf1, - 0xa4, 0x37, 0x34, 0x89, 0xba, 0xda, 0x9a, 0xc8, 0x89, 0x4f, 0x40, 0x41, 0x5b, 0xc9, 0x13, 0x12, - 0x8b, 0xed, 0x51, 0xd7, 0x93, 0xce, 0xcc, 0x54, 0x59, 0xb2, 0xe0, 0x2c, 0x39, 0x74, 0x08, 0xcb, - 0xb1, 0xe5, 0x4d, 0x72, 0x44, 0x1d, 0xb7, 0x36, 0x77, 0x45, 0x15, 0xe6, 0x7a, 0x6e, 0xa6, 0xd0, - 0x23, 0xa9, 0xe6, 0xab, 0x72, 0xef, 0xe5, 0x56, 0x1a, 0x0f, 0x8f, 0x6f, 0x81, 0x28, 0x80, 0xcb, - 0x4c, 0x8b, 0x78, 0x43, 0x87, 0xba, 0xb5, 0xb2, 0xd8, 0x70, 0x3d, 0xef, 0x86, 0x3b, 0x81, 0x64, - 0x74, 0xbf, 0xc2, 0x25, 0x17, 0xc7, 0x80, 0xd1, 0x03, 0x58, 0x89, 0xed, 0x1d, 0x31, 0xd5, 0x2a, - 0x57, 0xd4, 0xeb, 0xd5, 0xe6, 0xab, 0xa3, 0xe3, 0xb5, 0x95, 0x56, 0x16, 0x03, 0xce, 0x96, 0x43, - 0xfb, 0x70, 0x39, 0xc3, 0x8c, 0x5b, 0xb4, 0xcb, 0x48, 0xe7, 0x68, 0x40, 0x6b, 0xf3, 0xc2, 0x0f, - 0x9f, 0x97, 0x6a, 0x5d, 0x6e, 0x9d, 0xc0, 0x8b, 0x4f, 0x44, 0x42, 0xef, 0x24, 0x3c, 0x73, 0xcf, - 0xb6, 0xf6, 0x98, 0x59, 0x03, 0x01, 0x9f, 0x65, 0x6a, 0x9f, 0x01, 0x8f, 0xcb, 0x68, 0x7f, 0x52, - 0x61, 0x49, 0xfc, 0x6f, 0xf7, 0x07, 0xb6, 0xe3, 0xed, 0x0c, 0xa8, 0x81, 0xee, 0x43, 0x71, 0xcf, - 0xb1, 0xfb, 0x32, 0xae, 0xaf, 0xc6, 0x02, 0x43, 0xe7, 0x19, 0x3c, 0x8a, 0xe2, 0x30, 0xb4, 0xa2, - 0x3c, 0xf3, 0x4d, 0xc7, 0xee, 0x63, 0x21, 0x8e, 0xde, 0x86, 0x82, 0x67, 0x8b, 0x70, 0x5d, 0xd8, - 0xb8, 0x9e, 0x05, 0xb2, 0x69, 0x1b, 0xa4, 0x97, 0x46, 0x9a, 0xe3, 0xe9, 0xa6, 0x63, 0xe3, 0x82, - 0x67, 0xa3, 0x1e, 0x54, 0x99, 0x50, 0x6b, 0xdb, 0xee, 0x31, 0xe3, 0x48, 0x46, 0xea, 0x46, 0x8e, - 0x9b, 0xd0, 0x21, 0x66, 0x3b, 0x26, 0xd9, 0xbc, 0x20, 0xf5, 0xab, 0xc6, 0x57, 0x71, 0x02, 0x1d, - 0xdd, 0x85, 0x25, 0x66, 0x19, 0xbd, 0x61, 0x37, 0x0a, 0x1c, 0x1e, 0x95, 0x95, 0xe6, 0x2b, 0x52, - 0x78, 0xa9, 0x9d, 0x24, 0xe3, 0x34, 0x3f, 0x7a, 0x1f, 0x96, 0x9c, 0xe0, 0x24, 0x52, 0xe7, 0x92, - 0xd0, 0xf9, 0xad, 0x7c, 0x3a, 0xe3, 0xa4, 0x70, 0xb4, 0x73, 0x8a, 0x80, 0xd3, 0xdb, 0x68, 0x7f, - 0x55, 0x60, 0x39, 0xee, 0x47, 0x8f, 0x78, 0x43, 0x17, 0x75, 0x60, 0xce, 0x15, 0xbf, 0xa4, 0x2f, - 0x6f, 0xe4, 0xcb, 0xd1, 0xbe, 0x74, 0x73, 0x51, 0xee, 0x3e, 0xe7, 0xff, 0xc7, 0x12, 0x0b, 0xb5, - 0xa1, 0x24, 0x94, 0x0e, 0x7d, 0x9b, 0x33, 0x32, 0x9b, 0xf3, 0xa3, 0xe3, 0x35, 0xbf, 0x7e, 0x60, - 0x1f, 0x21, 0xa8, 0x45, 0x6a, 0x76, 0x2d, 0xd2, 0x3e, 0x50, 0x00, 0xa2, 0xc4, 0x10, 0xd6, 0x36, - 0x65, 0x62, 0x6d, 0xbb, 0x06, 0x45, 0x97, 0x3d, 0xf1, 0x35, 0x53, 0xa3, 0x4a, 0x29, 0xc4, 0x77, - 0xd8, 0x13, 0x8a, 0x05, 0x99, 0x57, 0xd5, 0x7e, 0x18, 0x95, 0x6a, 0xb2, 0xaa, 0x46, 0x21, 0x18, - 0xf1, 0x68, 0xbf, 0x57, 0x60, 0xde, 0x57, 0x84, 0xb9, 0x1e, 0x7a, 0x3c, 0x56, 0xfc, 0xf4, 0x7c, - 0x86, 0xe5, 0xd2, 0xa2, 0xf4, 0x85, 0x25, 0x3f, 0x58, 0x89, 0x15, 0xbe, 0x2d, 0x28, 0x31, 0x8f, - 0xf6, 0xdd, 0x5a, 0x41, 0x24, 0xbe, 0xfc, 0xe6, 0x3d, 0x2b, 0x41, 0x4b, 0x6d, 0x2e, 0x8e, 0x7d, - 0x14, 0xed, 0x96, 0xbc, 0x18, 0x9b, 0xb6, 0x7d, 0x30, 0x1c, 0xc8, 0xbb, 0x7e, 0x15, 0x4a, 0x3d, - 0x1e, 0x7d, 0xe2, 0xf0, 0x95, 0x48, 0x52, 0x84, 0x24, 0xf6, 0x69, 0xda, 0x6f, 0xe6, 0x60, 0x31, - 0x99, 0xe2, 0x66, 0x50, 0xf6, 0xaf, 0x40, 0xd1, 0xe3, 0x5e, 0x29, 0x24, 0x7d, 0x2c, 0x1c, 0x22, - 0x28, 0xe8, 0x1a, 0x94, 0x0d, 0xdb, 0xf2, 0xa8, 0xe5, 0x09, 0xed, 0xab, 0xcd, 0x85, 0xd1, 0xf1, - 0x5a, 0xf9, 0x9e, 0xbf, 0x84, 0x03, 0x1a, 0x62, 0x00, 0x86, 0x6d, 0x75, 0x99, 0xc7, 0x6c, 0xcb, - 0xad, 0x15, 0x85, 0x2d, 0xf3, 0x84, 0x61, 0x78, 0xd8, 0x7b, 0x81, 0x74, 0xa4, 0x71, 0xb8, 0xe4, - 0xe2, 0x18, 0x38, 0xfa, 0x1a, 0x9c, 0x15, 0xe2, 0xed, 0x2e, 0xb5, 0x3c, 0xe6, 0x1d, 0xc9, 0x82, - 0xbb, 0x22, 0xc5, 0xce, 0xb6, 0xe3, 0x44, 0x9c, 0xe4, 0x45, 0x3f, 0x82, 0x2a, 0xaf, 0x49, 0xb4, - 0x7b, 0xaf, 0x47, 0x58, 0x3f, 0xa8, 0xaf, 0xf7, 0xa6, 0x2e, 0x77, 0x42, 0xf1, 0x00, 0xe5, 0xbe, - 0xe5, 0x39, 0xb1, 0xac, 0x17, 0x27, 0xe1, 0xc4, 0x76, 0xe8, 0x5d, 0x28, 0x1b, 0x0e, 0xe5, 0x8d, - 0x6b, 0xad, 0x2c, 0x1c, 0xfa, 0xc5, 0x7c, 0x0e, 0xed, 0xb0, 0x3e, 0x95, 0x96, 0xf7, 0xc5, 0x71, - 0x80, 0xc3, 0xc3, 0x83, 0xb9, 0xee, 0x90, 0x76, 0x9b, 0x47, 0xb5, 0x4a, 0xee, 0x94, 0x1d, 0x1e, - 0xa4, 0xcd, 0x65, 0x9d, 0x66, 0x95, 0x87, 0x47, 0x5b, 0xe2, 0xe0, 0x10, 0x11, 0x7d, 0x2f, 0x40, - 0xef, 0xd8, 0xa2, 0xa0, 0x2e, 0x6c, 0xbc, 0x39, 0x0d, 0xfa, 0xce, 0x50, 0xdc, 0xba, 0x38, 0x7c, - 0xc7, 0xc6, 0x21, 0xe4, 0xea, 0x37, 0x60, 0x79, 0xcc, 0x90, 0xe8, 0x1c, 0xa8, 0x07, 0x54, 0xb6, - 0xeb, 0x98, 0xff, 0x44, 0x17, 0xa0, 0x74, 0x48, 0x7a, 0x43, 0x79, 0x4f, 0xb1, 0xff, 0xe7, 0x4e, - 0xe1, 0x96, 0xa2, 0xfd, 0xa2, 0x00, 0x0b, 0xbe, 0x67, 0x3c, 0x87, 0x92, 0xfe, 0x0c, 0x42, 0xa6, - 0x03, 0x45, 0x77, 0x40, 0x0d, 0x99, 0x8e, 0x37, 0x72, 0xdf, 0x1c, 0xa1, 0x1f, 0xaf, 0xf8, 0x51, - 0x98, 0xf1, 0x7f, 0x58, 0xa0, 0xa1, 0xc7, 0x61, 0xed, 0xf0, 0xcb, 0xee, 0xcd, 0x29, 0x71, 0x4f, - 0xac, 0x21, 0xda, 0x1f, 0x14, 0x38, 0x17, 0xe3, 0x9e, 0xd5, 0xa3, 0x62, 0xeb, 0x45, 0x4b, 0x57, - 0x94, 0x5b, 0x63, 0xe5, 0x4b, 0xfb, 0x6d, 0x41, 0x26, 0xd7, 0xe0, 0x14, 0xbc, 0xf6, 0xce, 0xe0, - 0x18, 0x8f, 0x12, 0x1e, 0xbf, 0x35, 0x9d, 0x67, 0xa2, 0x4e, 0x2f, 0xd3, 0xef, 0xbb, 0x29, 0xbf, - 0xdf, 0x79, 0x21, 0xf4, 0x93, 0xbd, 0xff, 0x93, 0x02, 0xac, 0x64, 0x6a, 0x84, 0x5e, 0x87, 0x39, - 0xbf, 0x29, 0x13, 0x96, 0xab, 0x44, 0x08, 0x3e, 0x0f, 0x96, 0x54, 0x64, 0x02, 0x38, 0x74, 0x60, - 0xbb, 0xcc, 0xb3, 0x9d, 0x23, 0x69, 0x87, 0xaf, 0xe6, 0xd0, 0x14, 0x87, 0x42, 0x31, 0x33, 0x2c, - 0x72, 0x43, 0x47, 0x14, 0x1c, 0x83, 0x46, 0x8f, 0xb8, 0x42, 0xc4, 0xa4, 0xdc, 0x1c, 0xea, 0x34, - 0xe1, 0x15, 0xc7, 0x8f, 0x0e, 0xc1, 0x91, 0xb0, 0x44, 0xd4, 0x7e, 0x57, 0x80, 0x57, 0x26, 0x98, - 0x0e, 0xe1, 0x84, 0x21, 0x78, 0x87, 0x31, 0x95, 0x1b, 0x9a, 0x90, 0x61, 0x34, 0x96, 0x61, 0xb4, - 0xdb, 0x2f, 0x62, 0x34, 0xe9, 0xdd, 0x13, 0xcc, 0xf6, 0x38, 0x65, 0xb6, 0x9b, 0x53, 0x9a, 0x2d, - 0x75, 0x7f, 0x52, 0x86, 0xfb, 0xa3, 0x22, 0x5f, 0x2d, 0xfe, 0x61, 0x67, 0xd0, 0x94, 0xed, 0x24, - 0x9b, 0xb2, 0x69, 0xbd, 0x91, 0xdd, 0x9a, 0xfd, 0x53, 0x01, 0x14, 0xe3, 0xda, 0x22, 0x83, 0x01, - 0xb3, 0xcc, 0xff, 0xbb, 0x34, 0xf8, 0xbc, 0x2e, 0xfe, 0xd7, 0x85, 0x84, 0xb7, 0x44, 0x9c, 0xef, - 0x24, 0xde, 0xde, 0xd1, 0x25, 0x92, 0xbd, 0xfd, 0x6b, 0x12, 0x64, 0xa5, 0x95, 0xc5, 0x84, 0xb3, - 0x65, 0xd1, 0xbb, 0x50, 0xf4, 0x88, 0x19, 0xf8, 0xa8, 0x31, 0xe5, 0x9b, 0x2b, 0xd6, 0x6c, 0x12, - 0xd3, 0xc5, 0x02, 0x0a, 0x59, 0x50, 0xed, 0xc5, 0x1a, 0xe7, 0x69, 0x6b, 0x61, 0xbc, 0xe9, 0x8e, - 0xda, 0xb1, 0xf8, 0x2a, 0x4e, 0xe0, 0x6b, 0xbf, 0x4a, 0x56, 0x14, 0x99, 0x0c, 0x4e, 0xc5, 0x5a, - 0x0f, 0x13, 0xd6, 0xca, 0x73, 0x24, 0xfe, 0xd0, 0xea, 0x76, 0x88, 0x79, 0xff, 0x90, 0x5a, 0x1e, - 0x0f, 0x92, 0x4c, 0x93, 0x51, 0xb8, 0x34, 0x18, 0xee, 0xf6, 0x98, 0x91, 0xa9, 0x8d, 0xbc, 0x25, - 0x57, 0xa5, 0xe0, 0xa5, 0xed, 0xc9, 0xac, 0xf8, 0x24, 0x1c, 0xed, 0xa3, 0x62, 0xf0, 0x3a, 0x11, - 0x96, 0xea, 0x90, 0x59, 0x04, 0xce, 0xb7, 0xfc, 0x9b, 0xee, 0x87, 0xcd, 0xd4, 0x17, 0xac, 0x9c, - 0x18, 0xb4, 0x6e, 0x00, 0xc8, 0xa1, 0x31, 0xb3, 0x2d, 0x61, 0x16, 0x35, 0xda, 0xfd, 0x9d, 0x90, - 0x82, 0x63, 0x5c, 0x68, 0x3f, 0xe3, 0x51, 0x73, 0x33, 0x9f, 0x1a, 0xc2, 0x69, 0xf9, 0xdf, 0x34, - 0x61, 0x8a, 0x28, 0xbd, 0x94, 0x14, 0x91, 0x8e, 0xa3, 0xb9, 0x53, 0x8e, 0xa3, 0x3f, 0x27, 0x53, - 0x6b, 0x87, 0x98, 0x33, 0x28, 0x12, 0x0f, 0x93, 0x45, 0x62, 0x7d, 0xba, 0x22, 0xd1, 0x21, 0xe6, - 0x84, 0x3a, 0xf1, 0x2f, 0x05, 0x96, 0xc7, 0x62, 0x2f, 0xc8, 0xba, 0xca, 0x84, 0x39, 0xfe, 0x76, - 0x52, 0x99, 0x2f, 0x4d, 0x71, 0x4b, 0xb2, 0xd5, 0x48, 0x5d, 0x3e, 0xf5, 0xf4, 0x2e, 0x9f, 0xf6, - 0xa1, 0x0a, 0x17, 0xb2, 0x3a, 0xb5, 0x97, 0x35, 0x9a, 0x4c, 0x0f, 0x16, 0x0b, 0xb3, 0x1e, 0x2c, - 0xaa, 0xff, 0xfd, 0x60, 0xb1, 0x38, 0x9b, 0xc1, 0xe2, 0x87, 0x05, 0xb8, 0x98, 0xdd, 0xff, 0x9d, - 0xd2, 0x74, 0x31, 0xea, 0x1c, 0x0b, 0x2f, 0xbf, 0x73, 0x44, 0x77, 0x60, 0x91, 0x74, 0xfd, 0x6b, - 0x46, 0x7a, 0xbc, 0x68, 0x89, 0x7b, 0x3c, 0xdf, 0x44, 0xa3, 0xe3, 0xb5, 0xc5, 0xbb, 0x09, 0x0a, - 0x4e, 0x71, 0x6a, 0x9f, 0xa8, 0x80, 0xc6, 0xa7, 0x43, 0xe8, 0x8e, 0x9c, 0x58, 0xf9, 0x81, 0xf8, - 0x7a, 0x7c, 0x62, 0xf5, 0xd9, 0xf1, 0xda, 0xc5, 0x71, 0x89, 0xd8, 0x2c, 0x6b, 0x33, 0x34, 0xa1, - 0x3f, 0xef, 0xba, 0x99, 0x34, 0xca, 0x67, 0xc7, 0x6b, 0x19, 0xdf, 0x4f, 0xf5, 0x10, 0x29, 0x65, - 0x3a, 0x13, 0xce, 0xf6, 0x88, 0xeb, 0x6d, 0x3b, 0xf6, 0x2e, 0xed, 0x30, 0xf9, 0x11, 0x70, 0xba, - 0x89, 0x4e, 0x38, 0xb3, 0xda, 0x8c, 0x03, 0xe1, 0x24, 0x2e, 0x3a, 0x04, 0xc4, 0x17, 0x3a, 0x0e, - 0xb1, 0x5c, 0xff, 0x48, 0x7c, 0xb7, 0xe2, 0xd4, 0xbb, 0xad, 0xca, 0xdd, 0xd0, 0xe6, 0x18, 0x1a, - 0xce, 0xd8, 0x81, 0xbf, 0x0e, 0x1d, 0x4a, 0x5c, 0xdb, 0x92, 0x13, 0xb6, 0xd0, 0xcb, 0x58, 0xac, - 0x62, 0x49, 0x45, 0x5f, 0x80, 0x72, 0x9f, 0xba, 0x2e, 0x2f, 0x5f, 0x73, 0x82, 0x71, 0x49, 0x32, - 0x96, 0xb7, 0xfc, 0x65, 0x1c, 0xd0, 0xb5, 0x0f, 0x14, 0x88, 0x5c, 0x24, 0xaa, 0x2e, 0x33, 0xee, - 0xfb, 0x93, 0xb9, 0x5b, 0x50, 0xb5, 0x1d, 0x93, 0x58, 0xec, 0x89, 0x5f, 0xa2, 0x7d, 0x07, 0x87, - 0x11, 0xff, 0x20, 0x46, 0xc3, 0x09, 0x4e, 0x5e, 0xda, 0x0d, 0xbb, 0xdf, 0xb7, 0x2d, 0x9e, 0xb5, - 0xa5, 0x6b, 0x63, 0x39, 0x2f, 0xa0, 0xe0, 0x18, 0x97, 0xf6, 0x4b, 0x05, 0x96, 0x52, 0x33, 0x30, - 0xf4, 0x73, 0x05, 0x2e, 0xba, 0x99, 0xca, 0xc9, 0x90, 0xbb, 0x3d, 0xcd, 0xe8, 0x2b, 0x01, 0xd0, - 0xac, 0x4b, 0x7d, 0x26, 0x9c, 0x1e, 0x4f, 0xd8, 0x58, 0xfb, 0x9b, 0x02, 0xe7, 0xd2, 0xd3, 0xb4, - 0xff, 0x45, 0x45, 0xd1, 0x5b, 0xb0, 0xe0, 0xf7, 0x8f, 0xdf, 0xa6, 0x47, 0xed, 0x96, 0xf4, 0xc2, - 0x79, 0x09, 0xb6, 0xb0, 0x1d, 0x91, 0x70, 0x9c, 0x4f, 0xfb, 0x69, 0x01, 0x2a, 0x41, 0xc5, 0x42, - 0xdf, 0x8d, 0xa6, 0xa3, 0xca, 0xd4, 0xb7, 0x3b, 0xbc, 0x74, 0x63, 0x13, 0xd2, 0x97, 0xff, 0x6d, - 0xfb, 0x6a, 0xd0, 0xae, 0xf9, 0xed, 0x75, 0x76, 0x13, 0x96, 0xec, 0x38, 0x8b, 0x79, 0x3a, 0x4e, - 0xed, 0x23, 0x15, 0x96, 0xc7, 0x0a, 0x38, 0xba, 0x9d, 0xc8, 0x79, 0xd7, 0x52, 0x39, 0x6f, 0x65, - 0x4c, 0xe0, 0xd4, 0x52, 0x5e, 0x76, 0x26, 0x52, 0x67, 0x98, 0x89, 0x8a, 0x79, 0x33, 0x51, 0xe9, - 0xe4, 0x4c, 0x94, 0xf2, 0xce, 0x5c, 0x2e, 0xef, 0x0c, 0x60, 0x29, 0xd5, 0x91, 0xa0, 0x1b, 0x50, - 0x61, 0x96, 0x4b, 0x8d, 0xa1, 0x43, 0xe5, 0x0c, 0x2d, 0x6c, 0x59, 0xdb, 0x72, 0x1d, 0x87, 0x1c, - 0xa8, 0x01, 0xf3, 0xae, 0xb1, 0x4f, 0xbb, 0xc3, 0x1e, 0xed, 0x0a, 0x87, 0x54, 0xa2, 0x2f, 0x61, - 0x3b, 0x01, 0x01, 0x47, 0x3c, 0xda, 0xbf, 0x8b, 0x50, 0x8d, 0x37, 0x14, 0x39, 0x3e, 0xca, 0xbd, - 0x07, 0x0b, 0xc4, 0xb2, 0x6c, 0x8f, 0xf8, 0x8d, 0xa3, 0x5f, 0xd6, 0xdf, 0x9e, 0xb2, 0x71, 0xd1, - 0xef, 0x46, 0x10, 0xfe, 0xd7, 0x8d, 0x30, 0x94, 0x63, 0x14, 0x1c, 0xdf, 0x09, 0xdd, 0x95, 0xdd, - 0xa2, 0x9a, 0xbf, 0x5b, 0xac, 0xa4, 0x3a, 0xc5, 0x06, 0xcc, 0x87, 0x1d, 0x91, 0xfc, 0x1c, 0x1c, - 0xda, 0x27, 0x8a, 0xc9, 0x88, 0x07, 0xe9, 0x09, 0x2f, 0x96, 0x84, 0x17, 0x17, 0x4f, 0x78, 0xd1, - 0xa5, 0x5b, 0xd1, 0xb9, 0x53, 0x6d, 0x45, 0x33, 0xfa, 0xc8, 0xf2, 0x4c, 0xfa, 0xc8, 0xd5, 0xaf, - 0xc3, 0xb9, 0xb4, 0x07, 0xa7, 0xfa, 0xac, 0xb2, 0x0d, 0x68, 0x7c, 0xff, 0xe7, 0xf5, 0x5e, 0xe3, - 0x12, 0x51, 0x22, 0x6a, 0x5e, 0x7f, 0xfa, 0xac, 0x7e, 0xe6, 0xe3, 0x67, 0xf5, 0x33, 0x9f, 0x3e, - 0xab, 0x9f, 0xf9, 0xf1, 0xa8, 0xae, 0x3c, 0x1d, 0xd5, 0x95, 0x8f, 0x47, 0x75, 0xe5, 0xd3, 0x51, - 0x5d, 0xf9, 0xfb, 0xa8, 0xae, 0xfc, 0xec, 0x1f, 0xf5, 0x33, 0x8f, 0x0a, 0x87, 0xeb, 0xff, 0x09, - 0x00, 0x00, 0xff, 0xff, 0x9e, 0x09, 0x46, 0xf1, 0x49, 0x27, 0x00, 0x00, + // 2445 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0x4f, 0x6c, 0xdb, 0xc8, + 0xd5, 0x0f, 0x45, 0x49, 0x96, 0x9f, 0x1d, 0x3b, 0x9e, 0xc4, 0x59, 0xad, 0x92, 0xb5, 0xbd, 0xcc, + 0x97, 0x20, 0x5f, 0x9b, 0xa5, 0x6a, 0x6f, 0x76, 0x9b, 0xa4, 0x40, 0x77, 0xa3, 0x28, 0x0d, 0xd4, + 0xda, 0x8d, 0x77, 0xac, 0xe6, 0x10, 0xa4, 0x40, 0x69, 0x6a, 0x4c, 0x4f, 0x2d, 0x91, 0x2a, 0x49, + 0x79, 0xd7, 0x41, 0x0b, 0xf4, 0x50, 0x2c, 0xf6, 0xd0, 0x43, 0x7b, 0xde, 0x63, 0xb1, 0x28, 0x7a, + 0x2e, 0x5a, 0xf4, 0xde, 0x16, 0x08, 0x7a, 0xe9, 0x62, 0x7b, 0xd9, 0x4b, 0x8d, 0x46, 0xed, 0xb9, + 0xb7, 0x5e, 0xf6, 0x54, 0xcc, 0x70, 0x48, 0x0e, 0x29, 0xca, 0xa6, 0xd2, 0xd8, 0x68, 0x6f, 0xe2, + 0xcc, 0x7b, 0xbf, 0xf7, 0xf8, 0xde, 0xbc, 0x3f, 0xf3, 0x28, 0x58, 0xb5, 0xa8, 0xbf, 0x3b, 0xd8, + 0xd6, 0x4d, 0xa7, 0x57, 0x77, 0xfa, 0xc4, 0xf6, 0x76, 0xe9, 0x8e, 0x5f, 0x37, 0xfa, 0xb4, 0x4e, + 0x7b, 0x86, 0x45, 0xea, 0xfb, 0xab, 0x75, 0x8b, 0xd8, 0xc4, 0x35, 0x7c, 0xd2, 0xd1, 0xfb, 0xae, + 0xe3, 0x3b, 0xe8, 0xf5, 0x98, 0x45, 0x8f, 0x58, 0x74, 0xa3, 0x4f, 0x75, 0xce, 0xa2, 0xef, 0xaf, + 0xd6, 0xde, 0x90, 0x50, 0x2d, 0xc7, 0x72, 0xea, 0x9c, 0x73, 0x7b, 0xb0, 0xc3, 0x9f, 0xf8, 0x03, + 0xff, 0x15, 0x20, 0xd6, 0xb4, 0xbd, 0x5b, 0x9e, 0x4e, 0x1d, 0x2e, 0xd6, 0x74, 0xdc, 0x2c, 0xa9, + 0xb5, 0x9b, 0x31, 0x4d, 0xcf, 0x30, 0x77, 0xa9, 0x4d, 0xdc, 0x83, 0x7a, 0x7f, 0xcf, 0x62, 0x0b, + 0x5e, 0xbd, 0x47, 0x7c, 0x23, 0x8b, 0xab, 0x3e, 0x8e, 0xcb, 0x1d, 0xd8, 0x3e, 0xed, 0x91, 0x11, + 0x86, 0xb7, 0x8f, 0x63, 0xf0, 0xcc, 0x5d, 0xd2, 0x33, 0x46, 0xf8, 0xde, 0x1c, 0xc7, 0x37, 0xf0, + 0x69, 0xb7, 0x4e, 0x6d, 0xdf, 0xf3, 0xdd, 0x34, 0x93, 0xf6, 0x99, 0x02, 0x17, 0x9a, 0x8e, 0xb9, + 0x47, 0xdc, 0x16, 0xb3, 0x1c, 0x26, 0x3b, 0xc4, 0x25, 0xb6, 0x49, 0xd0, 0x0d, 0xa8, 0xb8, 0xc4, + 0xa2, 0x9e, 0xef, 0x1e, 0x54, 0x95, 0x15, 0xe5, 0xfa, 0x74, 0xe3, 0xdc, 0xb3, 0xc3, 0xe5, 0x33, + 0xc3, 0xc3, 0xe5, 0x0a, 0x16, 0xeb, 0x38, 0xa2, 0x40, 0x75, 0x98, 0xb6, 0x8d, 0x1e, 0xf1, 0xfa, + 0x86, 0x49, 0xaa, 0x05, 0x4e, 0xbe, 0x20, 0xc8, 0xa7, 0xbf, 0x1d, 0x6e, 0xe0, 0x98, 0x06, 0xad, + 0x40, 0x91, 0x3d, 0x54, 0x55, 0x4e, 0x3b, 0x2b, 0x68, 0x8b, 0x8c, 0x16, 0xf3, 0x1d, 0xf4, 0x1a, + 0xa8, 0xbe, 0x61, 0x55, 0x8b, 0x9c, 0x60, 0x46, 0x10, 0xa8, 0x6d, 0xc3, 0xc2, 0x6c, 0x1d, 0xd5, + 0xa0, 0x40, 0x9b, 0xd5, 0x12, 0xdf, 0x05, 0xb1, 0x5b, 0x68, 0x35, 0x71, 0x81, 0x36, 0xb5, 0x3f, + 0x4f, 0x41, 0x89, 0xbf, 0x0e, 0xfa, 0x1e, 0x54, 0x98, 0x5f, 0x3a, 0x86, 0x6f, 0xf0, 0xb7, 0x98, + 0x59, 0xfb, 0x8a, 0x1e, 0x98, 0x49, 0x97, 0xcd, 0xa4, 0xf7, 0xf7, 0x2c, 0xb6, 0xe0, 0xe9, 0x8c, + 0x5a, 0xdf, 0x5f, 0xd5, 0x1f, 0x6e, 0x7f, 0x9f, 0x98, 0xfe, 0x06, 0xf1, 0x8d, 0x06, 0x12, 0xe8, + 0x10, 0xaf, 0xe1, 0x08, 0x15, 0x6d, 0xc2, 0x85, 0x4e, 0x86, 0xfd, 0x84, 0x11, 0x2e, 0x0b, 0xde, + 0x4c, 0x1b, 0xe3, 0x4c, 0x4e, 0xf4, 0x43, 0x38, 0x2f, 0xad, 0x6f, 0x84, 0xea, 0xab, 0x5c, 0xfd, + 0x37, 0xc6, 0xaa, 0x2f, 0x4e, 0x87, 0x8e, 0x8d, 0xf7, 0xef, 0x7f, 0xe0, 0x13, 0xdb, 0xa3, 0x8e, + 0xdd, 0xb8, 0x24, 0xe4, 0x9f, 0x6f, 0x8e, 0x22, 0xe2, 0x2c, 0x31, 0x68, 0x1b, 0x6a, 0x19, 0xcb, + 0x8f, 0x88, 0xcb, 0xf0, 0x84, 0x37, 0x34, 0x81, 0x5a, 0x6b, 0x8e, 0xa5, 0xc4, 0x47, 0xa0, 0xa0, + 0x8d, 0xe4, 0x1b, 0x1a, 0x36, 0xdd, 0x21, 0x9e, 0x2f, 0x9c, 0x99, 0xa9, 0xb2, 0x20, 0xc1, 0x59, + 0x7c, 0x68, 0x1f, 0x16, 0xa4, 0xe5, 0x75, 0xe3, 0x80, 0xb8, 0x5e, 0xb5, 0xbc, 0xa2, 0x72, 0x73, + 0x1d, 0x9b, 0x29, 0xf4, 0x98, 0xab, 0xf1, 0xaa, 0x90, 0xbd, 0xd0, 0x4c, 0xe3, 0xe1, 0x51, 0x11, + 0x88, 0x00, 0x78, 0xd4, 0xb2, 0x0d, 0x7f, 0xe0, 0x12, 0xaf, 0x3a, 0xc5, 0x05, 0xae, 0xe6, 0x15, + 0xb8, 0x15, 0x72, 0xc6, 0xe7, 0x2b, 0x5a, 0xf2, 0xb0, 0x04, 0x8c, 0x1e, 0xc2, 0xa2, 0x24, 0x3b, + 0x26, 0xaa, 0x56, 0x56, 0xd4, 0xeb, 0xb3, 0x8d, 0x57, 0x87, 0x87, 0xcb, 0x8b, 0xcd, 0x2c, 0x02, + 0x9c, 0xcd, 0x87, 0x76, 0xe1, 0x72, 0x86, 0x19, 0x37, 0x48, 0x87, 0x1a, 0xed, 0x83, 0x3e, 0xa9, + 0x4e, 0x73, 0x3f, 0xfc, 0x9f, 0x50, 0xeb, 0x72, 0xf3, 0x08, 0x5a, 0x7c, 0x24, 0x12, 0x7a, 0x90, + 0xf0, 0xcc, 0x3d, 0xc7, 0xde, 0xa1, 0x56, 0x15, 0x38, 0x7c, 0x96, 0xa9, 0x03, 0x02, 0x3c, 0xca, + 0xa3, 0x99, 0x70, 0x9e, 0x3f, 0x36, 0xba, 0xce, 0x76, 0x14, 0x29, 0x1e, 0xd2, 0xa0, 0xdc, 0x0d, + 0xdc, 0xad, 0xac, 0xa8, 0x2c, 0x11, 0x0c, 0x0f, 0x97, 0xcb, 0xc2, 0x61, 0x62, 0x07, 0x5d, 0x87, + 0x4a, 0x2f, 0x3c, 0x61, 0x41, 0x50, 0xce, 0xb2, 0x24, 0x16, 0x1d, 0xa9, 0x68, 0x57, 0xfb, 0xa3, + 0x0a, 0xf3, 0x5c, 0x4a, 0xab, 0xd7, 0x77, 0x5c, 0x7f, 0xab, 0x4f, 0x4c, 0x74, 0x1f, 0x8a, 0x3b, + 0xae, 0xd3, 0x13, 0xc9, 0xe3, 0x8a, 0x14, 0x7d, 0x3a, 0x2b, 0x13, 0x71, 0xaa, 0x88, 0xb4, 0x8a, + 0x93, 0xd9, 0x37, 0x5c, 0xa7, 0x87, 0x39, 0x3b, 0x7a, 0x17, 0x0a, 0xbe, 0xc3, 0xc5, 0xcf, 0xac, + 0x5d, 0xcf, 0x02, 0x59, 0x77, 0x4c, 0xa3, 0x9b, 0x46, 0x2a, 0xb3, 0x9c, 0xd6, 0x76, 0x70, 0xc1, + 0x77, 0x50, 0x17, 0x66, 0x29, 0x57, 0x6b, 0xd3, 0xe9, 0x52, 0xf3, 0x40, 0xa4, 0x83, 0xb5, 0x1c, + 0xc7, 0xad, 0x6d, 0x58, 0x2d, 0x89, 0xb3, 0x71, 0x41, 0xe8, 0x37, 0x2b, 0xaf, 0xe2, 0x04, 0x3a, + 0xba, 0x0b, 0xf3, 0xd4, 0x36, 0xbb, 0x83, 0x4e, 0x1c, 0x9d, 0x2c, 0xf4, 0x2b, 0x8d, 0x57, 0x04, + 0xf3, 0x7c, 0x2b, 0xb9, 0x8d, 0xd3, 0xf4, 0xe8, 0x03, 0x98, 0x77, 0xc3, 0x37, 0x11, 0x3a, 0x97, + 0xb8, 0xce, 0x6f, 0xe5, 0xd3, 0x19, 0x27, 0x99, 0x63, 0xc9, 0xa9, 0x0d, 0x9c, 0x16, 0xa3, 0xfd, + 0x45, 0x81, 0x05, 0xd9, 0x8f, 0xbe, 0xe1, 0x0f, 0x3c, 0xd4, 0x86, 0xb2, 0xc7, 0x7f, 0x09, 0x5f, + 0xde, 0xc8, 0x57, 0x08, 0x02, 0xee, 0xc6, 0x9c, 0x90, 0x5e, 0x0e, 0x9e, 0xb1, 0xc0, 0x42, 0x2d, + 0x28, 0x71, 0xa5, 0x23, 0xdf, 0xe6, 0x0c, 0xff, 0xc6, 0xf4, 0xf0, 0x70, 0x39, 0x28, 0x52, 0x38, + 0x40, 0x08, 0x0b, 0x9e, 0x9a, 0x5d, 0xf0, 0xb4, 0x0f, 0x15, 0x80, 0x38, 0xfb, 0x44, 0x05, 0x54, + 0x19, 0x5b, 0x40, 0xaf, 0x42, 0xd1, 0xa3, 0x4f, 0x03, 0xcd, 0xd4, 0xb8, 0x1c, 0x73, 0xf6, 0x2d, + 0xfa, 0x94, 0x60, 0xbe, 0xcd, 0x4a, 0x77, 0x2f, 0x0a, 0x7d, 0x35, 0x59, 0xba, 0xe3, 0x38, 0x8f, + 0x69, 0xb4, 0x0e, 0xcc, 0xc5, 0x7a, 0x34, 0x59, 0xcd, 0x78, 0x5d, 0x48, 0x52, 0xb8, 0xa4, 0xb3, + 0xc7, 0x4a, 0x29, 0xe4, 0x90, 0xf2, 0x3b, 0x05, 0xa6, 0x03, 0x31, 0xd4, 0xf3, 0xd1, 0x93, 0x91, + 0x3a, 0xae, 0xe7, 0x73, 0x1f, 0xe3, 0xe6, 0x55, 0x3c, 0xea, 0x5e, 0xc2, 0x15, 0xa9, 0x86, 0x6f, + 0x40, 0x89, 0xfa, 0xa4, 0xe7, 0x55, 0x0b, 0x3c, 0x87, 0xe7, 0x77, 0xe2, 0x59, 0x01, 0x5a, 0x6a, + 0x31, 0x76, 0x1c, 0xa0, 0x68, 0xb7, 0xc4, 0xf1, 0x5b, 0x77, 0x9c, 0xbd, 0x41, 0x5f, 0x44, 0xd4, + 0x15, 0x28, 0x75, 0x59, 0x8c, 0x73, 0x13, 0x57, 0x62, 0x4e, 0x1e, 0xf8, 0x38, 0xd8, 0xd3, 0x7e, + 0x5d, 0x16, 0xb6, 0x8d, 0xb2, 0xf5, 0x29, 0x74, 0x30, 0x2b, 0x50, 0xf4, 0x63, 0xaf, 0x44, 0x27, + 0x89, 0x3b, 0x84, 0xef, 0xa0, 0xab, 0x30, 0x65, 0x3a, 0xb6, 0x4f, 0x6c, 0x9f, 0x6b, 0x3f, 0xdb, + 0x98, 0x19, 0x1e, 0x2e, 0x4f, 0xdd, 0x0b, 0x96, 0x70, 0xb8, 0x87, 0x28, 0x80, 0xe9, 0xd8, 0x1d, + 0xea, 0x53, 0xc7, 0xf6, 0xaa, 0x45, 0x6e, 0xcb, 0x3c, 0xc1, 0x1e, 0xbd, 0xec, 0xbd, 0x90, 0x3b, + 0xd6, 0x38, 0x5a, 0xf2, 0xb0, 0x04, 0x8e, 0xbe, 0x06, 0x67, 0x39, 0x7b, 0xab, 0x43, 0x6c, 0x9f, + 0xfa, 0x07, 0xa2, 0x77, 0x58, 0x14, 0x6c, 0x67, 0x5b, 0xf2, 0x26, 0x4e, 0xd2, 0xa2, 0x1f, 0xc1, + 0x2c, 0x2b, 0xaf, 0xa4, 0x73, 0xaf, 0x6b, 0xd0, 0x5e, 0xd8, 0x2a, 0xdc, 0x9b, 0xb8, 0x72, 0x73, + 0xc5, 0x43, 0x94, 0xfb, 0xb6, 0xef, 0x4a, 0xb9, 0x55, 0xde, 0xc2, 0x09, 0x71, 0xe8, 0x3d, 0x98, + 0x32, 0x5d, 0xc2, 0x7a, 0xf0, 0xea, 0x14, 0x77, 0xe8, 0x97, 0xf2, 0x39, 0xb4, 0x4d, 0x7b, 0x44, + 0x58, 0x3e, 0x60, 0xc7, 0x21, 0x0e, 0x0b, 0x0f, 0xea, 0x79, 0x03, 0xd2, 0x69, 0x1c, 0x54, 0x2b, + 0xb9, 0x0b, 0x43, 0xf4, 0x22, 0x2d, 0xc6, 0xeb, 0x06, 0x75, 0xb1, 0x25, 0x70, 0x70, 0x84, 0x88, + 0xbe, 0x1b, 0xa2, 0xb7, 0x1d, 0xde, 0x1b, 0xcc, 0xac, 0xbd, 0x39, 0x09, 0xfa, 0xd6, 0x80, 0x9f, + 0x3a, 0x19, 0xbe, 0xed, 0xe0, 0x08, 0xb2, 0xf6, 0x0e, 0x2c, 0x8c, 0x18, 0x12, 0x9d, 0x03, 0x75, + 0x8f, 0x88, 0x9b, 0x07, 0x66, 0x3f, 0xd1, 0x05, 0x28, 0xed, 0x1b, 0xdd, 0x81, 0x38, 0xa7, 0x38, + 0x78, 0xb8, 0x53, 0xb8, 0xa5, 0x68, 0xbf, 0x28, 0xc0, 0x4c, 0xe0, 0x19, 0xdf, 0x25, 0x46, 0xef, + 0x14, 0x42, 0xa6, 0x0d, 0x45, 0xaf, 0x4f, 0x4c, 0x91, 0xf4, 0xd7, 0x72, 0x9f, 0x1c, 0xae, 0x1f, + 0xeb, 0x2b, 0xe2, 0x30, 0x63, 0x4f, 0x98, 0xa3, 0xa1, 0x27, 0x51, 0x85, 0x0a, 0x8a, 0xfb, 0xcd, + 0x09, 0x71, 0x8f, 0xac, 0x54, 0xda, 0xef, 0x15, 0x38, 0x27, 0x51, 0x9f, 0xd6, 0xfd, 0x68, 0xe3, + 0x45, 0x0b, 0x64, 0x9c, 0x5b, 0xa5, 0x22, 0xa9, 0xfd, 0xa6, 0x20, 0x92, 0x6b, 0xf8, 0x16, 0xac, + 0xc2, 0x9f, 0xc2, 0x6b, 0x3c, 0x4e, 0x78, 0xfc, 0xd6, 0x64, 0x9e, 0x89, 0xfb, 0xc9, 0x4c, 0xbf, + 0x6f, 0xa7, 0xfc, 0x7e, 0xe7, 0x85, 0xd0, 0x8f, 0xf6, 0xfe, 0x4f, 0x0a, 0xb0, 0x98, 0xa9, 0x11, + 0xba, 0x06, 0xe5, 0xa0, 0xf5, 0xe3, 0x96, 0xab, 0xc4, 0x08, 0x01, 0x0d, 0x16, 0xbb, 0xc8, 0x02, + 0x70, 0x49, 0xdf, 0xf1, 0xa8, 0xef, 0xb8, 0x07, 0xc2, 0x0e, 0x5f, 0xcd, 0xa1, 0x29, 0x8e, 0x98, + 0x24, 0x33, 0xcc, 0x31, 0x43, 0xc7, 0x3b, 0x58, 0x82, 0x46, 0x8f, 0x99, 0x42, 0x86, 0x45, 0x98, + 0x39, 0xd4, 0x49, 0xc2, 0x4b, 0xc6, 0x8f, 0x5f, 0x82, 0x21, 0x61, 0x81, 0xa8, 0xfd, 0xb6, 0x00, + 0xaf, 0x8c, 0x31, 0x1d, 0xc2, 0x09, 0x43, 0xb0, 0x0e, 0x63, 0x22, 0x37, 0x04, 0x97, 0x8f, 0x94, + 0xd1, 0x68, 0x86, 0xd1, 0x6e, 0xbf, 0x88, 0xd1, 0x84, 0x77, 0x8f, 0x30, 0xdb, 0x93, 0x94, 0xd9, + 0x6e, 0x4e, 0x68, 0xb6, 0xd4, 0xf9, 0x49, 0x19, 0xee, 0x93, 0x62, 0x22, 0xee, 0xc4, 0x0d, 0xf8, + 0xe4, 0xe3, 0xae, 0x03, 0xa5, 0xed, 0xae, 0xb3, 0x1d, 0xb6, 0x66, 0xef, 0x4c, 0xe6, 0x93, 0x40, + 0x4d, 0x9d, 0xdd, 0x1a, 0x45, 0x81, 0x8e, 0xb2, 0x0a, 0x5f, 0xc3, 0x01, 0x38, 0xda, 0x4d, 0xd9, + 0xee, 0xdd, 0x17, 0x12, 0x13, 0x98, 0x2c, 0x90, 0x33, 0xc6, 0x8e, 0xb5, 0x3d, 0x80, 0x58, 0x9b, + 0x8c, 0x2a, 0xf7, 0x40, 0xae, 0x72, 0x13, 0x8c, 0x13, 0xa2, 0x66, 0x5c, 0x2a, 0x8c, 0xb5, 0x1f, + 0x88, 0xba, 0x38, 0x56, 0xda, 0x7a, 0x52, 0xda, 0xdb, 0xb9, 0x93, 0x73, 0xe2, 0x1a, 0x2e, 0xd7, + 0xe2, 0x3f, 0x28, 0xe2, 0x0e, 0x2d, 0x2c, 0x73, 0xf2, 0xcd, 0xfb, 0x56, 0xb2, 0x79, 0x9f, 0x34, + 0x6a, 0xb3, 0x5b, 0xf8, 0x7f, 0x28, 0x80, 0x24, 0xaa, 0x0d, 0xa3, 0xdf, 0xa7, 0xb6, 0xf5, 0x3f, + 0x57, 0x2e, 0x8f, 0xbb, 0x53, 0xfe, 0xaa, 0x90, 0xf0, 0x16, 0xaf, 0x07, 0x5b, 0x89, 0x71, 0x53, + 0x9c, 0x6c, 0xc4, 0x4d, 0xf3, 0x35, 0x01, 0xb2, 0xd8, 0xcc, 0x22, 0xc2, 0xd9, 0xbc, 0xe8, 0x3d, + 0x28, 0xfa, 0x86, 0x15, 0xfa, 0xa8, 0x3e, 0xe1, 0x04, 0x40, 0xba, 0x94, 0x18, 0x96, 0x87, 0x39, + 0x14, 0xb2, 0x61, 0xb6, 0x2b, 0x5d, 0xb0, 0x26, 0xed, 0x99, 0xe4, 0xcb, 0x59, 0xdc, 0xb6, 0xcb, + 0xab, 0x38, 0x81, 0xaf, 0xfd, 0x32, 0xd9, 0x79, 0x88, 0xa2, 0x71, 0x22, 0xd6, 0x7a, 0x94, 0xb0, + 0x56, 0x9e, 0x57, 0x62, 0xd7, 0xfe, 0x4e, 0xdb, 0xb0, 0xee, 0xef, 0x13, 0xdb, 0x67, 0x41, 0x92, + 0x69, 0x32, 0x02, 0x97, 0xfa, 0x83, 0xed, 0x2e, 0x35, 0x33, 0xb5, 0x11, 0xa7, 0xe4, 0x8a, 0x60, + 0xbc, 0xb4, 0x39, 0x9e, 0x14, 0x1f, 0x85, 0xa3, 0x7d, 0x5c, 0x0c, 0x6f, 0xb1, 0xdc, 0x52, 0x6d, + 0xe3, 0x34, 0x02, 0xe7, 0x9b, 0xc1, 0x49, 0x0f, 0xc2, 0x66, 0xe2, 0x03, 0x36, 0x95, 0xf8, 0xb6, + 0xb0, 0x06, 0x20, 0xbe, 0x93, 0x50, 0xc7, 0xe6, 0x66, 0x51, 0x63, 0xe9, 0x0f, 0xa2, 0x1d, 0x2c, + 0x51, 0xa1, 0xdd, 0x8c, 0xcb, 0xef, 0xcd, 0x7c, 0x6a, 0x70, 0xa7, 0xe5, 0xbf, 0xfb, 0x46, 0x29, + 0xa2, 0xf4, 0x52, 0x52, 0x44, 0x3a, 0x8e, 0xca, 0x27, 0x1c, 0x47, 0x7f, 0x4a, 0xa6, 0xd6, 0xb6, + 0x61, 0x9d, 0x42, 0x91, 0x78, 0x94, 0x2c, 0x12, 0xab, 0x93, 0x15, 0x89, 0xb6, 0x61, 0x8d, 0xa9, + 0x13, 0xff, 0x54, 0x60, 0x61, 0x24, 0xf6, 0xc2, 0xac, 0xab, 0x8c, 0xf9, 0x74, 0xb5, 0x99, 0x54, + 0xe6, 0xcb, 0x13, 0x9c, 0x92, 0x6c, 0x35, 0x52, 0x87, 0x4f, 0x3d, 0xb9, 0xc3, 0xa7, 0x7d, 0xa4, + 0xc2, 0x85, 0xac, 0x8e, 0xfe, 0x65, 0x0d, 0xca, 0xd3, 0x63, 0xee, 0xc2, 0x69, 0x8f, 0xb9, 0xd5, + 0xff, 0x7c, 0xcc, 0x5d, 0x3c, 0x9d, 0x31, 0xf7, 0x47, 0x05, 0xb8, 0x98, 0x7d, 0x4f, 0x38, 0xa1, + 0x59, 0x77, 0x7c, 0xc3, 0x28, 0xbc, 0xfc, 0x1b, 0x06, 0xba, 0x03, 0x73, 0x46, 0x27, 0x38, 0x66, + 0x46, 0x97, 0x15, 0x2d, 0x7e, 0x8e, 0xa7, 0x1b, 0x68, 0x78, 0xb8, 0x3c, 0x77, 0x37, 0xb1, 0x83, + 0x53, 0x94, 0xda, 0x67, 0x2a, 0xa0, 0xd1, 0x29, 0x22, 0xba, 0x23, 0x26, 0x9b, 0x41, 0x20, 0x5e, + 0x93, 0x27, 0x9b, 0x5f, 0x1c, 0x2e, 0x5f, 0x1c, 0xe5, 0x90, 0x66, 0x9e, 0xeb, 0x91, 0x09, 0x83, + 0xb9, 0xe8, 0xcd, 0xa4, 0x51, 0xbe, 0x38, 0x5c, 0xce, 0xf8, 0xcb, 0x80, 0x1e, 0x21, 0xa5, 0x4c, + 0x67, 0xc1, 0xd9, 0xae, 0xe1, 0xf9, 0x9b, 0xae, 0xb3, 0x4d, 0xda, 0x54, 0x7c, 0xf7, 0x9e, 0x6c, + 0xf2, 0x17, 0xcd, 0x36, 0xd7, 0x65, 0x20, 0x9c, 0xc4, 0x45, 0xfb, 0x80, 0xd8, 0x42, 0xdb, 0x35, + 0x6c, 0x2f, 0x78, 0x25, 0x26, 0xad, 0x38, 0xb1, 0xb4, 0x9a, 0x90, 0x86, 0xd6, 0x47, 0xd0, 0x70, + 0x86, 0x04, 0x74, 0x0d, 0xca, 0x2e, 0x31, 0x3c, 0xc7, 0x16, 0x93, 0xd8, 0xc8, 0xcb, 0x98, 0xaf, + 0x62, 0xb1, 0x8b, 0xfe, 0x1f, 0xa6, 0x7a, 0xc4, 0xf3, 0x58, 0xf9, 0x2a, 0x73, 0xc2, 0x79, 0x41, + 0x38, 0xb5, 0x11, 0x2c, 0xe3, 0x70, 0x5f, 0xfb, 0x50, 0x81, 0xd8, 0x45, 0xbc, 0xea, 0x52, 0xf3, + 0x7e, 0x30, 0xc1, 0xbd, 0x05, 0xb3, 0x8e, 0x6b, 0x19, 0x36, 0x7d, 0x1a, 0x94, 0xe8, 0xc0, 0xc1, + 0x51, 0xc4, 0x3f, 0x94, 0xf6, 0x70, 0x82, 0x92, 0x95, 0x76, 0xd3, 0xe9, 0xf5, 0x1c, 0x9b, 0x65, + 0x6d, 0xe1, 0x5a, 0x29, 0xe7, 0x85, 0x3b, 0x58, 0xa2, 0xd2, 0x3e, 0x51, 0x60, 0x3e, 0x35, 0x2b, + 0x45, 0x3f, 0x57, 0xe0, 0xa2, 0x97, 0xa9, 0x9c, 0x08, 0xb9, 0xdb, 0x93, 0x8c, 0x48, 0x13, 0x00, + 0x8d, 0x25, 0xa1, 0xcf, 0x98, 0xb7, 0xc7, 0x63, 0x04, 0x6b, 0x7f, 0x55, 0xe0, 0x5c, 0x7a, 0xea, + 0xfa, 0xdf, 0xa8, 0x28, 0x7a, 0x0b, 0x66, 0x82, 0xfe, 0xf1, 0x5b, 0xe4, 0xa0, 0xd5, 0x14, 0x5e, + 0x38, 0x2f, 0xc0, 0x66, 0x36, 0xe3, 0x2d, 0x2c, 0xd3, 0x69, 0x3f, 0x2d, 0x40, 0x25, 0xac, 0x58, + 0xe8, 0x3b, 0xf1, 0x14, 0x5d, 0x99, 0xf8, 0x74, 0x47, 0x87, 0x6e, 0x64, 0x92, 0xfe, 0xf2, 0xff, + 0xce, 0x71, 0x25, 0x6c, 0xd7, 0x82, 0xf6, 0x3a, 0xbb, 0x09, 0x4b, 0x76, 0x9c, 0xc5, 0x3c, 0x1d, + 0xa7, 0xf6, 0xb1, 0x0a, 0x0b, 0x23, 0x05, 0x1c, 0xdd, 0x4e, 0xe4, 0xbc, 0xab, 0xa9, 0x9c, 0xb7, + 0x38, 0xc2, 0x70, 0x62, 0x29, 0x2f, 0x3b, 0x13, 0xa9, 0xa7, 0x98, 0x89, 0x8a, 0x79, 0x33, 0x51, + 0xe9, 0xe8, 0x4c, 0x94, 0xf2, 0x4e, 0x39, 0x97, 0x77, 0xfa, 0x30, 0x9f, 0xea, 0x48, 0xd0, 0x0d, + 0xa8, 0x50, 0xdb, 0x23, 0xe6, 0xc0, 0x25, 0x62, 0xd6, 0x1a, 0xb5, 0xac, 0x2d, 0xb1, 0x8e, 0x23, + 0x0a, 0x54, 0x87, 0x69, 0xcf, 0xdc, 0x25, 0x9d, 0x41, 0x97, 0x74, 0xb8, 0x43, 0x2a, 0xf1, 0x17, + 0xd3, 0xad, 0x70, 0x03, 0xc7, 0x34, 0xda, 0xbf, 0x8a, 0x30, 0x2b, 0x37, 0x14, 0x39, 0x3e, 0x11, + 0xbf, 0x0f, 0x33, 0x86, 0x6d, 0x3b, 0xbe, 0x11, 0x34, 0x8e, 0x85, 0xdc, 0xc3, 0x2f, 0x59, 0x8e, + 0x7e, 0x37, 0x86, 0x08, 0x86, 0x5f, 0x51, 0x28, 0x4b, 0x3b, 0x58, 0x96, 0x84, 0xee, 0x8a, 0x6e, + 0x51, 0xcd, 0xdf, 0x2d, 0x56, 0x52, 0x9d, 0x62, 0x1d, 0xa6, 0xa3, 0x8e, 0x48, 0xfc, 0x39, 0x21, + 0xb2, 0x4f, 0x1c, 0x93, 0x31, 0x0d, 0xd2, 0x13, 0x5e, 0x2c, 0x71, 0x2f, 0xce, 0x1d, 0x71, 0xa3, + 0x4b, 0xb7, 0xa2, 0xe5, 0x13, 0x6d, 0x45, 0x33, 0xfa, 0xc8, 0xa9, 0x53, 0xe9, 0x23, 0x6b, 0x5f, + 0x87, 0x73, 0x69, 0x0f, 0x4e, 0xf4, 0xf9, 0x6d, 0x13, 0xd0, 0xa8, 0xfc, 0xe3, 0x7a, 0xaf, 0x51, + 0x8e, 0x38, 0x11, 0x35, 0xae, 0x3f, 0x7b, 0xbe, 0x74, 0xe6, 0xd3, 0xe7, 0x4b, 0x67, 0x3e, 0x7f, + 0xbe, 0x74, 0xe6, 0xc7, 0xc3, 0x25, 0xe5, 0xd9, 0x70, 0x49, 0xf9, 0x74, 0xb8, 0xa4, 0x7c, 0x3e, + 0x5c, 0x52, 0xfe, 0x36, 0x5c, 0x52, 0x7e, 0xf6, 0xf7, 0xa5, 0x33, 0x8f, 0x0b, 0xfb, 0xab, 0xff, + 0x0e, 0x00, 0x00, 0xff, 0xff, 0x09, 0x41, 0xe3, 0x7d, 0x3c, 0x2a, 0x00, 0x00, } diff --git a/vendor/github.com/openshift/api/image/v1/generated.proto b/vendor/github.com/openshift/api/image/v1/generated.proto index bbbfa5df7d40..417a6c1bb29d 100644 --- a/vendor/github.com/openshift/api/image/v1/generated.proto +++ b/vendor/github.com/openshift/api/image/v1/generated.proto @@ -68,6 +68,20 @@ message Image { optional string dockerImageConfig = 10; } +// ImageBlobReferences describes the blob references within an image. +message ImageBlobReferences { + // layers is the list of blobs that compose this image, from base layer to top layer. + // All layers referenced by this array will be defined in the blobs map. Some images + // may have zero layers. + // +optional + repeated string layers = 1; + + // manifest, if set, is the blob that contains the image manifest. Some images do + // not have separate manifest blobs and this field will be set to nil if so. + // +optional + optional string manifest = 2; +} + // ImageImportSpec describes a request to import a specific image. message ImageImportSpec { // From is the source of an image to import; only kind DockerImage is allowed @@ -110,6 +124,16 @@ message ImageLayer { optional string mediaType = 3; } +// ImageLayerData contains metadata about an image layer. +message ImageLayerData { + // Size of the layer in bytes as defined by the underlying store. This field is + // optional if the necessary information about size is not available. + optional int64 size = 1; + + // MediaType of the referenced object. + optional string mediaType = 2; +} + // ImageList is a list of Image objects. message ImageList { // Standard object's metadata. @@ -237,6 +261,20 @@ message ImageStreamImportStatus { repeated ImageImportStatus images = 3; } +// ImageStreamLayers describes information about the layers referenced by images in this +// image stream. +message ImageStreamLayers { + // Standard object's metadata. + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // blobs is a map of blob name to metadata about the blob. + map blobs = 2; + + // images is a map between an image name and the names of the blobs and manifests that + // comprise the image. + map images = 3; +} + // ImageStreamList is a list of ImageStream objects. message ImageStreamList { // Standard object's metadata. diff --git a/vendor/github.com/openshift/api/image/v1/register.go b/vendor/github.com/openshift/api/image/v1/register.go index 5377b4cade6d..46f785c471aa 100644 --- a/vendor/github.com/openshift/api/image/v1/register.go +++ b/vendor/github.com/openshift/api/image/v1/register.go @@ -43,6 +43,7 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ImageStreamTag{}, &ImageStreamTagList{}, &ImageStreamImage{}, + &ImageStreamLayers{}, &ImageStreamImport{}, &corev1.SecretList{}, ) diff --git a/vendor/github.com/openshift/api/image/v1/types.go b/vendor/github.com/openshift/api/image/v1/types.go index 2d268174e723..9887fe542a88 100644 --- a/vendor/github.com/openshift/api/image/v1/types.go +++ b/vendor/github.com/openshift/api/image/v1/types.go @@ -159,6 +159,7 @@ type ImageStreamList struct { // +genclient // +genclient:method=Secrets,verb=get,subresource=secrets,result=k8s.io/api/core/v1.SecretList +// +genclient:method=Layers,verb=get,subresource=layers,result=github.com/openshift/api/image/v1.ImageStreamLayers // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ImageStream stores a mapping of tags to images, metadata overrides that are applied @@ -417,6 +418,43 @@ type DockerImageReference struct { ID string `protobuf:"bytes,5,opt,name=iD"` } +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ImageStreamLayers describes information about the layers referenced by images in this +// image stream. +type ImageStreamLayers struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // blobs is a map of blob name to metadata about the blob. + Blobs map[string]ImageLayerData `json:"blobs" protobuf:"bytes,2,rep,name=blobs"` + // images is a map between an image name and the names of the blobs and manifests that + // comprise the image. + Images map[string]ImageBlobReferences `json:"images" protobuf:"bytes,3,rep,name=images"` +} + +// ImageBlobReferences describes the blob references within an image. +type ImageBlobReferences struct { + // layers is the list of blobs that compose this image, from base layer to top layer. + // All layers referenced by this array will be defined in the blobs map. Some images + // may have zero layers. + // +optional + Layers []string `json:"layers" protobuf:"bytes,1,rep,name=layers"` + // manifest, if set, is the blob that contains the image manifest. Some images do + // not have separate manifest blobs and this field will be set to nil if so. + // +optional + Manifest *string `json:"manifest" protobuf:"bytes,2,opt,name=manifest"` +} + +// ImageLayerData contains metadata about an image layer. +type ImageLayerData struct { + // Size of the layer in bytes as defined by the underlying store. This field is + // optional if the necessary information about size is not available. + LayerSize *int64 `json:"size" protobuf:"varint,1,opt,name=size"` + // MediaType of the referenced object. + MediaType string `json:"mediaType" protobuf:"bytes,2,opt,name=mediaType"` +} + // +genclient // +genclient:onlyVerbs=create // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go b/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go index 43f9d8951bcb..dc9b83c49779 100644 --- a/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go @@ -42,6 +42,16 @@ func (Image) SwaggerDoc() map[string]string { return map_Image } +var map_ImageBlobReferences = map[string]string{ + "": "ImageBlobReferences describes the blob references within an image.", + "layers": "layers is the list of blobs that compose this image, from base layer to top layer. All layers referenced by this array will be defined in the blobs map. Some images may have zero layers.", + "manifest": "manifest, if set, is the blob that contains the image manifest. Some images do not have separate manifest blobs and this field will be set to nil if so.", +} + +func (ImageBlobReferences) SwaggerDoc() map[string]string { + return map_ImageBlobReferences +} + var map_ImageImportSpec = map[string]string{ "": "ImageImportSpec describes a request to import a specific image.", "from": "From is the source of an image to import; only kind DockerImage is allowed", @@ -77,6 +87,16 @@ func (ImageLayer) SwaggerDoc() map[string]string { return map_ImageLayer } +var map_ImageLayerData = map[string]string{ + "": "ImageLayerData contains metadata about an image layer.", + "size": "Size of the layer in bytes as defined by the underlying store. This field is optional if the necessary information about size is not available.", + "mediaType": "MediaType of the referenced object.", +} + +func (ImageLayerData) SwaggerDoc() map[string]string { + return map_ImageLayerData +} + var map_ImageList = map[string]string{ "": "ImageList is a list of Image objects.", "metadata": "Standard object's metadata.", @@ -167,6 +187,17 @@ func (ImageStreamImportStatus) SwaggerDoc() map[string]string { return map_ImageStreamImportStatus } +var map_ImageStreamLayers = map[string]string{ + "": "ImageStreamLayers describes information about the layers referenced by images in this image stream.", + "metadata": "Standard object's metadata.", + "blobs": "blobs is a map of blob name to metadata about the blob.", + "images": "images is a map between an image name and the names of the blobs and manifests that comprise the image.", +} + +func (ImageStreamLayers) SwaggerDoc() map[string]string { + return map_ImageStreamLayers +} + var map_ImageStreamList = map[string]string{ "": "ImageStreamList is a list of ImageStream objects.", "metadata": "Standard object's metadata.", diff --git a/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go index fd84d5c30817..6aa13046be40 100644 --- a/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go @@ -75,6 +75,36 @@ func (in *Image) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageBlobReferences) DeepCopyInto(out *ImageBlobReferences) { + *out = *in + if in.Layers != nil { + in, out := &in.Layers, &out.Layers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Manifest != nil { + in, out := &in.Manifest, &out.Manifest + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageBlobReferences. +func (in *ImageBlobReferences) DeepCopy() *ImageBlobReferences { + if in == nil { + return nil + } + out := new(ImageBlobReferences) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageImportSpec) DeepCopyInto(out *ImageImportSpec) { *out = *in @@ -145,6 +175,31 @@ func (in *ImageLayer) DeepCopy() *ImageLayer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageLayerData) DeepCopyInto(out *ImageLayerData) { + *out = *in + if in.LayerSize != nil { + in, out := &in.LayerSize, &out.LayerSize + if *in == nil { + *out = nil + } else { + *out = new(int64) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageLayerData. +func (in *ImageLayerData) DeepCopy() *ImageLayerData { + if in == nil { + return nil + } + out := new(ImageLayerData) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageList) DeepCopyInto(out *ImageList) { *out = *in @@ -421,6 +476,50 @@ func (in *ImageStreamImportStatus) DeepCopy() *ImageStreamImportStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageStreamLayers) DeepCopyInto(out *ImageStreamLayers) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Blobs != nil { + in, out := &in.Blobs, &out.Blobs + *out = make(map[string]ImageLayerData, len(*in)) + for key, val := range *in { + newVal := new(ImageLayerData) + val.DeepCopyInto(newVal) + (*out)[key] = *newVal + } + } + if in.Images != nil { + in, out := &in.Images, &out.Images + *out = make(map[string]ImageBlobReferences, len(*in)) + for key, val := range *in { + newVal := new(ImageBlobReferences) + val.DeepCopyInto(newVal) + (*out)[key] = *newVal + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStreamLayers. +func (in *ImageStreamLayers) DeepCopy() *ImageStreamLayers { + if in == nil { + return nil + } + out := new(ImageStreamLayers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImageStreamLayers) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageStreamList) DeepCopyInto(out *ImageStreamList) { *out = *in diff --git a/vendor/github.com/openshift/client-go/glide.lock b/vendor/github.com/openshift/client-go/glide.lock index 046d6e411796..9991bea1ac0e 100644 --- a/vendor/github.com/openshift/client-go/glide.lock +++ b/vendor/github.com/openshift/client-go/glide.lock @@ -1,5 +1,5 @@ hash: 91748cede774246187f6a8627e0a335015261f8e28708731a279c6ce205d9254 -updated: 2018-06-29T15:11:35.519708105-04:00 +updated: 2018-07-10T15:41:29.920958699-04:00 imports: - name: github.com/davecgh/go-spew version: 782f4967f2dc4564575ca782fe2d04090b5faca8 @@ -49,7 +49,7 @@ imports: - name: github.com/modern-go/reflect2 version: 05fbef0ca5da472bbf96c9322b84a53edc03c9fd - name: github.com/openshift/api - version: 31a7bbd2266d178da3c12bb83f5274d387f775e6 + version: 04a26bf3b8d69c390642c5803fe4cfdb899112aa subpackages: - apps/v1 - authorization/v1 diff --git a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go index 15d18fa8888d..b193c7d793bf 100644 --- a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go +++ b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go @@ -134,3 +134,14 @@ func (c *FakeImageStreams) Secrets(imageStreamName string, options v1.GetOptions } return obj.(*core_v1.SecretList), err } + +// Layers takes name of the imageStream, and returns the corresponding imageStreamLayers object, and an error if there is any. +func (c *FakeImageStreams) Layers(imageStreamName string, options v1.GetOptions) (result *image_v1.ImageStreamLayers, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetSubresourceAction(imagestreamsResource, c.ns, "layers", imageStreamName), &image_v1.ImageStreamLayers{}) + + if obj == nil { + return nil, err + } + return obj.(*image_v1.ImageStreamLayers), err +} diff --git a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go index 1e1cc2e24f9d..307afcfff68e 100644 --- a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go +++ b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go @@ -30,6 +30,7 @@ type ImageStreamInterface interface { Watch(opts meta_v1.ListOptions) (watch.Interface, error) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ImageStream, err error) Secrets(imageStreamName string, options meta_v1.GetOptions) (*core_v1.SecretList, error) + Layers(imageStreamName string, options meta_v1.GetOptions) (*v1.ImageStreamLayers, error) ImageStreamExpansion } @@ -173,3 +174,17 @@ func (c *imageStreams) Secrets(imageStreamName string, options meta_v1.GetOption Into(result) return } + +// Layers takes name of the imageStream, and returns the corresponding v1.ImageStreamLayers object, and an error if there is any. +func (c *imageStreams) Layers(imageStreamName string, options meta_v1.GetOptions) (result *v1.ImageStreamLayers, err error) { + result = &v1.ImageStreamLayers{} + err = c.client.Get(). + Namespace(c.ns). + Resource("imagestreams"). + Name(imageStreamName). + SubResource("layers"). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go b/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go index 62a932c27049..499e466f987b 100644 --- a/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go +++ b/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go @@ -82,7 +82,7 @@ func main() { if glog.V(2) { log.Printf("Builder: "+format, args...) } else { - fmt.Fprintf(options.ErrOut, "--> %s\n", fmt.Sprintf(format, args...)) + fmt.Fprintf(options.Out, "--> %s\n", fmt.Sprintf(format, args...)) } } diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go b/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go index ee5ca9a30e51..c8c0f68bc92f 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go @@ -38,7 +38,9 @@ func FilterArchive(r io.Reader, w io.Writer, fn TransformFileFunc) error { } var body io.Reader = tr + name := h.Name data, ok, skip, err := fn(h, tr) + glog.V(6).Infof("Transform %s -> %s: data=%t ok=%t skip=%t err=%v", name, h.Name, data != nil, ok, skip, err) if err != nil { return err } @@ -100,7 +102,7 @@ func NewLazyArchive(fn CreateFileFunc) io.ReadCloser { return pr } -func archiveFromURL(src, dst, tempDir string) (io.Reader, io.Closer, error) { +func archiveFromURL(src, dst, tempDir string, check DirectoryCheck) (io.Reader, io.Closer, error) { // get filename from URL u, err := url.Parse(src) if err != nil { @@ -151,7 +153,7 @@ func archiveFromURL(src, dst, tempDir string) (io.Reader, io.Closer, error) { return archive, closers{resp.Body.Close, archive.Close}, nil } -func archiveFromDisk(directory string, src, dst string, allowDownload bool, excludes []string) (io.Reader, io.Closer, error) { +func archiveFromDisk(directory string, src, dst string, allowDownload bool, excludes []string, check DirectoryCheck) (io.Reader, io.Closer, error) { var err error if filepath.IsAbs(src) { src, err = filepath.Rel(filepath.Dir(src), src) @@ -173,13 +175,66 @@ func archiveFromDisk(directory string, src, dst string, allowDownload bool, excl directory = filepath.Dir(directory) } - options := archiveOptionsFor(infos, dst, excludes) + options, err := archiveOptionsFor(infos, dst, excludes, check) + if err != nil { + return nil, nil, err + } glog.V(4).Infof("Tar of %s %#v", directory, options) rc, err := archive.TarWithOptions(directory, options) return rc, rc, err } +func archiveFromFile(file string, src, dst string, excludes []string, check DirectoryCheck) (io.Reader, io.Closer, error) { + var err error + if filepath.IsAbs(src) { + src, err = filepath.Rel(filepath.Dir(src), src) + if err != nil { + return nil, nil, err + } + } + + mapper, _, err := newArchiveMapper(src, dst, excludes, true, check) + if err != nil { + return nil, nil, err + } + + f, err := os.Open(file) + if err != nil { + return nil, nil, err + } + + r, err := transformArchive(f, true, mapper.Filter) + return r, f, err +} + +func archiveFromContainer(in io.Reader, src, dst string, excludes []string, check DirectoryCheck) (io.Reader, string, error) { + mapper, archiveRoot, err := newArchiveMapper(src, dst, excludes, false, check) + if err != nil { + return nil, "", err + } + + r, err := transformArchive(in, false, mapper.Filter) + return r, archiveRoot, err +} + +func transformArchive(r io.Reader, compressed bool, fn TransformFileFunc) (io.Reader, error) { + pr, pw := io.Pipe() + go func() { + if compressed { + in, err := archive.DecompressStream(r) + if err != nil { + pw.CloseWithError(err) + return + } + r = in + } + err := FilterArchive(r, pw, fn) + pw.CloseWithError(err) + }() + return pr, nil +} + // * -> test // a (dir) -> test // a (file) -> test @@ -193,9 +248,15 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } pattern := filepath.Base(srcPattern) + glog.V(6).Infof("creating mapper for srcPattern=%s pattern=%s dst=%s isDestDir=%t", srcPattern, pattern, dst, isDestDir) + // no wildcards if !containsWildcards(pattern) { return func(name string, isDir bool) (string, bool) { + // when extracting from the working directory, Docker prefaces with ./ + if strings.HasPrefix(name, "."+string(filepath.Separator)) { + name = name[2:] + } if name == srcPattern { if isDir { return "", false @@ -232,7 +293,7 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } prefix += string(filepath.Separator) - // nested with pattern pattern + // nested with pattern return func(name string, isDir bool) (string, bool) { remainder := strings.TrimPrefix(name, prefix) if remainder == name { @@ -251,56 +312,6 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } } -func archiveFromFile(file string, src, dst string, excludes []string) (io.Reader, io.Closer, error) { - var err error - if filepath.IsAbs(src) { - src, err = filepath.Rel(filepath.Dir(src), src) - if err != nil { - return nil, nil, err - } - } - - mapper, _, err := newArchiveMapper(src, dst, excludes, true) - if err != nil { - return nil, nil, err - } - - f, err := os.Open(file) - if err != nil { - return nil, nil, err - } - - r, err := transformArchive(f, true, mapper.Filter) - return r, f, err -} - -func archiveFromContainer(in io.Reader, src, dst string, excludes []string) (io.Reader, string, error) { - mapper, archiveRoot, err := newArchiveMapper(src, dst, excludes, false) - if err != nil { - return nil, "", err - } - - r, err := transformArchive(in, false, mapper.Filter) - return r, archiveRoot, err -} - -func transformArchive(r io.Reader, compressed bool, fn TransformFileFunc) (io.Reader, error) { - pr, pw := io.Pipe() - go func() { - if compressed { - in, err := archive.DecompressStream(r) - if err != nil { - pw.CloseWithError(err) - return - } - r = in - } - err := FilterArchive(r, pw, fn) - pw.CloseWithError(err) - }() - return pr, nil -} - type archiveMapper struct { exclude *fileutils.PatternMatcher rename func(name string, isDir bool) (string, bool) @@ -308,7 +319,7 @@ type archiveMapper struct { resetOwners bool } -func newArchiveMapper(src, dst string, excludes []string, resetOwners bool) (*archiveMapper, string, error) { +func newArchiveMapper(src, dst string, excludes []string, resetOwners bool, check DirectoryCheck) (*archiveMapper, string, error) { ex, err := fileutils.NewPatternMatcher(excludes) if err != nil { return nil, "", err @@ -316,6 +327,13 @@ func newArchiveMapper(src, dst string, excludes []string, resetOwners bool) (*ar isDestDir := strings.HasSuffix(dst, "/") || path.Base(dst) == "." dst = path.Clean(dst) + if !isDestDir && check != nil { + isDir, err := check.IsDirectory(dst) + if err != nil { + return nil, "", err + } + isDestDir = isDir + } var prefix string archiveRoot := src @@ -380,19 +398,27 @@ func (m *archiveMapper) Filter(h *tar.Header, r io.Reader) ([]byte, bool, bool, return nil, false, false, nil } -func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive.TarOptions { +func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string, check DirectoryCheck) (*archive.TarOptions, error) { dst = trimLeadingPath(dst) dstIsDir := strings.HasSuffix(dst, "/") || dst == "." || dst == "/" || strings.HasSuffix(dst, "/.") dst = trimTrailingSlash(dst) dstIsRoot := dst == "." || dst == "/" + if !dstIsDir && check != nil { + isDir, err := check.IsDirectory(dst) + if err != nil { + return nil, fmt.Errorf("unable to check whether %s is a directory: %v", dst, err) + } + dstIsDir = isDir + } + options := &archive.TarOptions{ ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, } pm, err := fileutils.NewPatternMatcher(excludes) if err != nil { - return options + return options, nil } for _, info := range infos { @@ -418,12 +444,9 @@ func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive case len(infos) > 1: // put each input into the target, which is assumed to be a directory ([Dockerfile, dir] -> [a/Dockerfile, a/dir]) options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) - case info.FileInfo.IsDir() && dstIsDir: - // mapping a directory to an explicit directory ([dir] -> [a]) - options.RebaseNames[infoPath] = dst case info.FileInfo.IsDir(): - // mapping a directory to an implicit directory ([Dockerfile] -> [dir/Dockerfile]) - options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) + // mapping a directory to a destination, explicit or not ([dir] -> [a]) + options.RebaseNames[infoPath] = dst case info.FromDir: // this is a file that was part of an explicit directory request, no transformation options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) @@ -437,7 +460,7 @@ func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive } options.ExcludePatterns = excludes - return options + return options, nil } func sourceToDestinationName(src, dst string, forceDir bool) string { diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go index 89961c769b63..978c8564bfd3 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go @@ -13,6 +13,20 @@ import ( "github.com/docker/docker/pkg/archive" ) +type testDirectoryCheck map[string]bool + +func (c testDirectoryCheck) IsDirectory(path string) (bool, error) { + if c == nil { + return false, nil + } + + isDir, ok := c[path] + if !ok { + return false, fmt.Errorf("no path defined for %s", path) + } + return isDir, nil +} + type archiveGenerator struct { Headers []*tar.Header } @@ -81,6 +95,7 @@ func Test_archiveFromFile(t *testing.T) { dst string excludes []string expect []string + check map[string]bool }{ { file: testArchive, @@ -233,6 +248,7 @@ func Test_archiveFromFile(t *testing.T) { testCase.src, testCase.dst, testCase.excludes, + testDirectoryCheck(testCase.check), ) if err != nil { t.Fatal(err) @@ -266,6 +282,7 @@ func Test_archiveFromContainer(t *testing.T) { excludes []string expect []string path string + check map[string]bool }{ { gen: newArchiveGenerator().File("file").Dir("test").File("test/file2"), @@ -394,6 +411,14 @@ func Test_archiveFromContainer(t *testing.T) { path: "/a", expect: nil, }, + { + gen: newArchiveGenerator().File("b"), + src: "/a/b", + dst: "/a", + check: map[string]bool{"/a": true}, + path: "/a", + expect: nil, + }, { gen: newArchiveGenerator().Dir("a/").File("a/b"), src: "/a/b", @@ -403,6 +428,13 @@ func Test_archiveFromContainer(t *testing.T) { "/a", }, }, + { + gen: newArchiveGenerator().Dir("./a").File("./a/b"), + src: "a", + dst: "/a", + path: ".", + expect: []string{"/a/b"}, + }, } for i := range testCases { testCase := testCases[i] @@ -412,6 +444,7 @@ func Test_archiveFromContainer(t *testing.T) { testCase.src, testCase.dst, testCase.excludes, + testDirectoryCheck(testCase.check), ) if err != nil { t.Fatal(err) diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/client.go b/vendor/github.com/openshift/imagebuilder/dockerclient/client.go index bbf1ab0ec2ae..fa8b4a8fa2be 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/client.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/client.go @@ -799,8 +799,9 @@ func (e *ClientExecutor) archiveFromContainer(from string, src, dst string) (io. e.Deferred = append([]func() error{func() error { return e.removeContainer(containerID) }}, e.Deferred...) } + check := newDirectoryCheck(e.Client, e.Container.ID) pr, pw := io.Pipe() - ar, archiveRoot, err := archiveFromContainer(pr, src, dst, nil) + ar, archiveRoot, err := archiveFromContainer(pr, src, dst, nil, check) if err != nil { pr.Close() return nil, nil, err @@ -818,26 +819,30 @@ func (e *ClientExecutor) archiveFromContainer(from string, src, dst string) (io. // TODO: this does not support decompressing nested archives for ADD (when the source is a compressed file) func (e *ClientExecutor) Archive(fromFS bool, src, dst string, allowDownload bool, excludes []string) (io.Reader, io.Closer, error) { + var check DirectoryCheck + if e.Container != nil { + check = newDirectoryCheck(e.Client, e.Container.ID) + } if isURL(src) { if !allowDownload { return nil, nil, fmt.Errorf("source can't be a URL") } glog.V(5).Infof("Archiving %s -> %s from URL", src, dst) - return archiveFromURL(src, dst, e.TempDir) + return archiveFromURL(src, dst, e.TempDir, check) } // the input is from the filesystem, use the source as the input if fromFS { glog.V(5).Infof("Archiving %s %s -> %s from a filesystem location", src, ".", dst) - return archiveFromDisk(src, ".", dst, allowDownload, excludes) + return archiveFromDisk(src, ".", dst, allowDownload, excludes, check) } // if the context is in archive form, read from it without decompressing if len(e.ContextArchive) > 0 { glog.V(5).Infof("Archiving %s %s -> %s from context archive", e.ContextArchive, src, dst) - return archiveFromFile(e.ContextArchive, src, dst, excludes) + return archiveFromFile(e.ContextArchive, src, dst, excludes, check) } // if the context is a directory, we only allow relative includes glog.V(5).Infof("Archiving %q %q -> %q from disk", e.Directory, src, dst) - return archiveFromDisk(e.Directory, src, dst, allowDownload, excludes) + return archiveFromDisk(e.Directory, src, dst, allowDownload, excludes, check) } // ContainerVolumeTracker manages tracking archives of specific paths inside a container. diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go index 4a5c8fc9d510..911083ada297 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go @@ -111,6 +111,8 @@ func TestCopyFrom(t *testing.T) { {name: "copy file to deeper directory with explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a/1 /a/b/c/", expect: "ls -al /a/b/c/1 && ! ls -al /a/b/1"}, {name: "copy file to deeper directory without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a/1 /a/b/c", expect: "ls -al /a/b/c && ! ls -al /a/b/1"}, {name: "copy directory to deeper directory without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a /a/b/c", expect: "ls -al /a/b/c/1 && ! ls -al /a/b/1"}, + {name: "copy directory to root without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "a /a", expect: "ls -al /a/1 && ! ls -al /a/a"}, + {name: "copy directory trailing to root without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "a/. /a", expect: "ls -al /a/1 && ! ls -al /a/a"}, } for i, testCase := range testCases { name := fmt.Sprintf("%d", i) @@ -143,6 +145,7 @@ func TestCopyFrom(t *testing.T) { stages := imagebuilder.NewStages(node, b) if _, err := e.Stages(b, stages, ""); err != nil { + t.Log(out.String()) t.Fatal(err) } }) @@ -250,6 +253,18 @@ func TestConformanceInternal(t *testing.T) { Name: "directory", ContextDir: "testdata/dir", }, + { + Name: "copy to dir", + ContextDir: "testdata/copy", + }, + { + Name: "copy dir", + ContextDir: "testdata/copydir", + }, + { + Name: "copy to renamed file", + ContextDir: "testdata/copyrename", + }, { Name: "directory with slash", ContextDir: "testdata/overlapdir", @@ -391,8 +406,8 @@ func TestTransientMount(t *testing.T) { e.AllowPull = true e.Directory = "testdata" e.TransientMounts = []Mount{ - {SourcePath: "dir", DestinationPath: "/mountdir"}, - {SourcePath: "Dockerfile.env", DestinationPath: "/mountfile"}, + {SourcePath: "testdata/dir", DestinationPath: "/mountdir"}, + {SourcePath: "testdata/Dockerfile.env", DestinationPath: "/mountfile"}, } e.Tag = fmt.Sprintf("conformance%d", rand.Int63()) diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go index 7828e3511850..24854441b945 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go @@ -17,6 +17,7 @@ func TestCalcCopyInfo(t *testing.T) { paths map[string]struct{} excludes []string rebaseNames map[string]string + check map[string]bool }{ { origPath: "subdir/*", @@ -106,6 +107,33 @@ func TestCalcCopyInfo(t *testing.T) { "Dockerfile": "copy/Dockerfile", }, }, + { + origPath: "Dockerfile", + dstPath: "copy", + rootPath: "testdata/singlefile", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "Dockerfile": {}, + }, + rebaseNames: map[string]string{ + "Dockerfile": "copy", + }, + }, + { + origPath: "Dockerfile", + dstPath: "copy", + check: map[string]bool{"copy": true}, + rootPath: "testdata/singlefile", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "Dockerfile": {}, + }, + rebaseNames: map[string]string{ + "Dockerfile": "copy/Dockerfile", + }, + }, { origPath: "existing/", dstPath: ".", @@ -185,6 +213,20 @@ func TestCalcCopyInfo(t *testing.T) { "subdir": "test", }, }, + { + origPath: "dir", + dstPath: "/dir", + check: map[string]bool{"dir": false}, + rootPath: "testdata/copydir", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "dir": {}, + }, + rebaseNames: map[string]string{ + "dir": "dir", + }, + }, } for i, test := range tests { @@ -211,7 +253,10 @@ func TestCalcCopyInfo(t *testing.T) { t.Errorf("did not see paths: %#v", expect) } - options := archiveOptionsFor(infos, test.dstPath, test.excludes) + options, err := archiveOptionsFor(infos, test.dstPath, test.excludes, testDirectoryCheck(test.check)) + if err != nil { + t.Fatal(err) + } if !reflect.DeepEqual(test.rebaseNames, options.RebaseNames) { t.Errorf("rebase names did not match:\n%#v\n%#v", test.rebaseNames, options.RebaseNames) } diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go b/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go new file mode 100644 index 000000000000..4e0a9f8bf01a --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go @@ -0,0 +1,87 @@ +package dockerclient + +import ( + "archive/tar" + "context" + "io" + "io/ioutil" + + "github.com/golang/glog" + + docker "github.com/fsouza/go-dockerclient" +) + +type DirectoryCheck interface { + IsDirectory(path string) (bool, error) +} + +type directoryCheck struct { + containerID string + client *docker.Client +} + +func newDirectoryCheck(client *docker.Client, containerID string) *directoryCheck { + return &directoryCheck{ + containerID: containerID, + client: client, + } +} + +func (c *directoryCheck) IsDirectory(path string) (bool, error) { + if path == "/" || path == "." || path == "./" { + return true, nil + } + + dir, err := isContainerPathDirectory(c.client, c.containerID, path) + if err != nil { + return false, err + } + + return dir, nil +} + +func isContainerPathDirectory(client *docker.Client, containerID, path string) (bool, error) { + pr, pw := io.Pipe() + defer pw.Close() + ctx, cancel := context.WithCancel(context.TODO()) + go func() { + err := client.DownloadFromContainer(containerID, docker.DownloadFromContainerOptions{ + OutputStream: pw, + Path: path, + Context: ctx, + }) + if err != nil { + if apiErr, ok := err.(*docker.Error); ok && apiErr.Status == 404 { + glog.V(4).Infof("path %s did not exist in container %s: %v", path, containerID, err) + err = nil + } + if err != nil && err != context.Canceled { + glog.V(6).Infof("error while checking directory contents for container %s at path %s: %v", containerID, path, err) + } + } + pw.CloseWithError(err) + }() + + tr := tar.NewReader(pr) + + h, err := tr.Next() + if err != nil { + if err == io.EOF { + err = nil + } + return false, err + } + + glog.V(4).Infof("Retrieved first header from container %s at path %s: %#v", containerID, path, h) + + // take the remainder of the input and discard it + go func() { + cancel() + n, err := io.Copy(ioutil.Discard, pr) + if n > 0 || err != nil { + glog.V(6).Infof("Discarded %d bytes from end of container directory check, and got error: %v", n, err) + } + }() + + return h.FileInfo().IsDir(), nil +} diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile new file mode 100644 index 000000000000..815de493ba73 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY script /usr/bin +RUN ls -al /usr/bin/script \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script new file mode 100644 index 000000000000..c3c3f3f53f62 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script @@ -0,0 +1,2 @@ +#!/bin/bash +exit 0 \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile new file mode 100644 index 000000000000..92c53fdf6dad --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY dir /dir +RUN ls -al /dir/file \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/dir/file b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/dir/file new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile new file mode 100644 index 000000000000..575bf2cd4de4 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY file1 /usr/bin/file2 +RUN ls -al /usr/bin/file2 && ! ls -al /usr/bin/file1 \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 new file mode 100644 index 000000000000..c3c3f3f53f62 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 @@ -0,0 +1,2 @@ +#!/bin/bash +exit 0 \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile b/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile new file mode 100644 index 000000000000..6243895c8c2d --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile @@ -0,0 +1,11 @@ +# +# This is the integrated OpenShift Service Serving Cert Signer. It signs serving certificates for use inside the platform. +# +# The standard name for this image is openshift/origin-service-serving-cert-signer +# +FROM openshift/origin-release:golang-1.10 +COPY . /go/src/github.com/openshift/service-serving-cert-signer +RUN cd /go/src/github.com/openshift/service-serving-cert-signer && go build ./cmd/service-serving-cert-signer + +FROM centos:7 +COPY --from=0 /go/src/github.com/openshift/service-serving-cert-signer/service-serving-cert-signer /usr/bin/service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/Makefile b/vendor/github.com/openshift/service-serving-cert-signer/Makefile index b7fba95c867b..4e48a3a570ac 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/Makefile +++ b/vendor/github.com/openshift/service-serving-cert-signer/Makefile @@ -120,6 +120,6 @@ build-rpms: # # Example: # make build-images -build-images: build-rpms +build-images: hack/build-images.sh .PHONY: build-images diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh index c45ebc5884f1..d3eb62c3c3e3 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh @@ -20,6 +20,13 @@ os::util::ensure::gopath_binary_exists imagebuilder os::build::release::check_for_rpms # we need to mount RPMs into the container builds for installation -OS_BUILD_IMAGE_ARGS="${OS_BUILD_IMAGE_ARGS:-} -mount ${OS_OUTPUT_RPMPATH}/:/srv/origin-local-release/" +cat < "${OS_OUTPUT_RPMPATH}/_local.repo" +[origin-local-release] +name = OpenShift Origin Release from Local Source +baseurl = file:///srv/origin-local-release/ +gpgcheck = 0 +enabled = 0 +END +OS_BUILD_IMAGE_ARGS="${OS_BUILD_IMAGE_ARGS:-} -mount ${OS_OUTPUT_RPMPATH}/:/srv/origin-local-release/ -mount ${OS_OUTPUT_RPMPATH}/_local.repo:/etc/yum.repos.d/origin-local-release.repo" os::build::images \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh index f615360b83d4..6f74078ac614 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh @@ -146,5 +146,5 @@ readonly OS_ALL_IMAGES=( # os::build::images builds all images in this repo. function os::build::images() { tag_prefix="${OS_IMAGE_PREFIX:-"openshift/origin"}" - os::build::image "${tag_prefix}-service-serving-cert-signer" images/service-serving-cert-signer + os::build::image "${tag_prefix}-service-serving-cert-signer" . } \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh index 21026f89faff..45cdf4b9104b 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh @@ -143,62 +143,3 @@ function os::test::junit::reconcile_output() { done } readonly -f os::test::junit::reconcile_output - -# os::test::junit::generate_report determines which type of report is to -# be generated and does so from the raw output of the tests. -# -# Globals: -# - JUNIT_REPORT_OUTPUT -# - ARTIFACT_DIR -# Arguments: -# None -# Returns: -# None -function os::test::junit::generate_report() { - if [[ -z "${JUNIT_REPORT_OUTPUT:-}" || - -n "${JUNIT_REPORT_OUTPUT:-}" && ! -s "${JUNIT_REPORT_OUTPUT:-}" ]]; then - # we can't generate a report - return - fi - - if grep -q "=== END TEST CASE ===" "${JUNIT_REPORT_OUTPUT}"; then - os::test::junit::reconcile_output - os::test::junit::check_test_counters - os::test::junit::internal::generate_report "oscmd" - else - os::test::junit::internal::generate_report "gotest" - fi -} - -# os::test::junit::internal::generate_report generats an XML jUnit -# report for either `os::cmd` or `go test`, based on the passed -# argument. If the `junitreport` binary is not present, it will be built. -# -# Globals: -# - JUNIT_REPORT_OUTPUT -# - ARTIFACT_DIR -# Arguments: -# - 1: specify which type of tests command output should junitreport read -# Returns: -# export JUNIT_REPORT_NUM_FAILED -function os::test::junit::internal::generate_report() { - local report_type="$1" - os::util::ensure::built_binary_exists 'junitreport' - - local report_file - report_file="$( mktemp "${ARTIFACT_DIR}/${report_type}_report_XXXXX" ).xml" - os::log::info "jUnit XML report placed at $( os::util::repository_relative_path ${report_file} )" - junitreport --type "${report_type}" \ - --suites nested \ - --roots github.com/openshift/origin \ - --output "${report_file}" \ - <"${JUNIT_REPORT_OUTPUT}" - - local summary - summary=$( junitreport summarize <"${report_file}" ) - - JUNIT_REPORT_NUM_FAILED="$( grep -oE "[0-9]+ failed" <<<"${summary}" )" - export JUNIT_REPORT_NUM_FAILED - - echo "${summary}" -} \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh index 3bbb1ebf48b0..2ae80ce24e30 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh @@ -1,22 +1,3 @@ #!/bin/bash # # This library holds golang related utility functions. - -# os::golang::verify_go_version ensure the go tool exists and is a viable version. -function os::golang::verify_go_version() { - os::util::ensure::system_binary_exists 'go' - - local go_version - go_version=($(go version)) - if [[ "${go_version[2]}" != go1.8* ]]; then - os::log::info "Detected go version: ${go_version[*]}." - if [[ -z "${PERMISSIVE_GO:-}" ]]; then - os::log::fatal "Please install Go version ${OS_REQUIRED_GO_VERSION} or use PERMISSIVE_GO=y to bypass this check." - else - os::log::warning "Detected golang version doesn't match required Go version." - os::log::warning "This version mismatch could lead to differences in execution between this run and the CI systems." - return 0 - fi - fi -} -readonly -f os::golang::verify_go_version diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh index 61743037de29..08d1731aa261 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh @@ -21,14 +21,6 @@ function cleanup() { return_code=$? - os::test::junit::generate_report - if [[ "${JUNIT_REPORT_NUM_FAILED:-}" == "0 failed" ]]; then - if [[ "${return_code}" -ne "0" ]]; then - os::log::warning "While the jUnit report found no failed tests, the \`go test\` process failed." - os::log::warning "This usually means that the unit test suite failed to compile." - fi - fi - os::util::describe_return_code "${return_code}" exit "${return_code}" } @@ -135,11 +127,15 @@ if [[ -n "${junit_report}" ]]; then # we don't care if the `go test` fails in this pipe, as we want to generate the report and summarize the output anyway set +o pipefail - go test -i ${gotest_flags} ${test_packages} - go test ${gotest_flags} ${test_packages} 2>"${test_error_file}" | tee "${JUNIT_REPORT_OUTPUT}" + os::util::ensure::built_binary_exists 'gotest2junit' + report_file="$( mktemp "${ARTIFACT_DIR}/unit_report_XXXXX" ).xml" + go test -json ${gotest_flags} ${test_packages} 2>"${test_error_file}" | tee "${JUNIT_REPORT_OUTPUT}" | gotest2junit > "${report_file}" test_return_code="${PIPESTATUS[0]}" + gzip "${test_error_file}" -c > "${ARTIFACT_DIR}/unit-error.log.gz" + gzip "${JUNIT_REPORT_OUTPUT}" -c > "${ARTIFACT_DIR}/unit.log.gz" + set -o pipefail if [[ -s "${test_error_file}" ]]; then @@ -162,7 +158,6 @@ $( cat "${test_error_file}") " elif [[ -n "${coverage_output_dir}" ]]; then # we need to generate coverage reports - go test -i ${gotest_flags} ${test_packages} for test_package in ${test_packages}; do mkdir -p "${coverage_output_dir}/${test_package}" local_gotest_flags="${gotest_flags} -coverprofile=${coverage_output_dir}/${test_package}/profile.out" @@ -187,6 +182,5 @@ elif [[ -n "${dlv_debug}" ]]; then dlv test ${test_packages} else # we need to generate neither jUnit XML nor coverage reports - go test -i ${gotest_flags} ${test_packages} go test ${gotest_flags} ${test_packages} fi diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh index 95d477f61014..3ff24e84c394 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh @@ -8,8 +8,6 @@ function cleanup() { } trap "cleanup" EXIT -os::golang::verify_go_version - bad_files=$(os::util::list_go_src_files | xargs gofmt -s -l) if [[ -n "${bad_files}" ]]; then os::log::warning "!!! gofmt needs to be run on the listed files" diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh index 3c7ba6e27cb7..c61e20d83228 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh @@ -1,7 +1,6 @@ #!/bin/bash source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -os::golang::verify_go_version os::util::ensure::system_binary_exists 'golint' arg="${1:-""}" diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh index c8cee8e9be51..f1746cdf3f10 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh @@ -8,8 +8,6 @@ function cleanup() { } trap "cleanup" EXIT -os::golang::verify_go_version - govet_blacklist=( "${OS_GOVET_BLACKLIST[@]-}" ) function govet_blacklist_contains() { diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh index 6e00177feac1..a5c510499343 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh @@ -6,7 +6,6 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" function cleanup() { return_code=$? - os::test::junit::generate_report os::util::describe_return_code "${return_code}" exit "${return_code}" } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh index d3c2f988b21e..b5fc0aa4cb81 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh @@ -3,7 +3,6 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" function cleanup() { return_code=$? - os::test::junit::generate_report os::util::describe_return_code "${return_code}" exit "${return_code}" } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml deleted file mode 100644 index f555da819426..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml +++ /dev/null @@ -1 +0,0 @@ -job-id: origin-service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile deleted file mode 100644 index c6c50457d76a..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -# -# This is the integrated OpenShift Service Serving Cert Signer. It signs serving certificates for use inside the platform. -# -# The standard name for this image is openshift/origin-service-serving-cert-signer -# -FROM openshift/origin-base - -RUN INSTALL_PKGS="origin-service-serving-cert-signer" && \ - yum --enablerepo=origin-local-release install -y ${INSTALL_PKGS} && \ - rpm -V ${INSTALL_PKGS} && \ - yum clean all - -LABEL io.k8s.display-name="OpenShift Service Serving Cert Signer" \ - io.k8s.description="This is a component of OpenShift that signs serving certificates for use inside the platform." \ - io.openshift.tags="openshift" - -# The process doesn't require a root user. -USER 1001 - -CMD /usr/bin/service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore deleted file mode 100644 index d6b7ef32c847..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go new file mode 100644 index 000000000000..952373d25acb --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go @@ -0,0 +1,91 @@ +package operator + +import ( + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + kyaml "k8s.io/apimachinery/pkg/util/yaml" +) + +func mergeProcessConfig(defaultConfigYAML, userConfigYAML []byte, specialCases map[string]mergeFunc) ([]byte, error) { + defaultConfigJSON, err := kyaml.ToJSON(defaultConfigYAML) + if err != nil { + return nil, err + } + defaultConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, defaultConfigJSON) + if err != nil { + return nil, err + } + defaultConfig := defaultConfigObj.(*unstructured.Unstructured) + + if len(userConfigYAML) > 0 { + userConfigJSON, err := kyaml.ToJSON(userConfigYAML) + if err != nil { + glog.Warning(err) + // maybe it's just yaml + userConfigJSON = userConfigYAML + } + userConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, userConfigJSON) + if err != nil { + return nil, err + } + userConfig := userConfigObj.(*unstructured.Unstructured) + if err := mergeConfig(defaultConfig.Object, userConfig.Object, "", specialCases); err != nil { + return nil, err + } + } + + configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, defaultConfig) + if err != nil { + return nil, err + } + return configBytes, nil +} + +type mergeFunc func(dst, src interface{}, currentPath string) (interface{}, error) + +// mergeConfig overwrites entries in curr by additional. It modifies curr. +func mergeConfig(curr, additional map[string]interface{}, currentPath string, specialCases map[string]mergeFunc) error { + for additionalKey, additionalVal := range additional { + fullKey := currentPath + "." + additionalKey + specialCase, ok := specialCases[fullKey] + if ok { + var err error + curr[additionalKey], err = specialCase(curr[additionalKey], additionalVal, currentPath) + if err != nil { + return err + } + continue + } + + currVal, ok := curr[additionalKey] + if !ok { + curr[additionalKey] = additionalVal + continue + } + + // only some scalars are accepted + switch castVal := additionalVal.(type) { + case map[string]interface{}: + currValAsMap, ok := currVal.(map[string]interface{}) + if !ok { + currValAsMap = map[string]interface{}{} + curr[additionalKey] = currValAsMap + } + + err := mergeConfig(currValAsMap, castVal, fullKey, specialCases) + if err != nil { + return err + } + continue + + default: + if err := unstructured.SetNestedField(curr, castVal, additionalKey); err != nil { + return err + } + } + + } + + return nil +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go new file mode 100644 index 000000000000..c2a200c66ae5 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go @@ -0,0 +1,122 @@ +package operator + +import ( + "reflect" + "strings" + "testing" + + "k8s.io/apimachinery/pkg/util/diff" +) + +func TestMergeConfig(t *testing.T) { + tests := []struct { + name string + curr map[string]interface{} + additional map[string]interface{} + specialCases map[string]mergeFunc + + expected map[string]interface{} + expectedErr string + }{ + { + name: "add non-conflicting", + curr: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + }, + }, + additional: map[string]interface{}{ + "bravo": map[string]interface{}{ + "banana": "two", + "cake": map[string]interface{}{ + "armadillo": "uno", + }, + }, + "charlie": "third", + }, + + expected: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + "banana": "two", + "cake": map[string]interface{}{ + "armadillo": "uno", + }, + }, + "charlie": "third", + }, + }, + { + name: "add conflicting, replace type", + curr: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + }, + }, + additional: map[string]interface{}{ + "bravo": map[string]interface{}{ + "apple": map[string]interface{}{ + "armadillo": "uno", + }, + }, + }, + + expected: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": map[string]interface{}{ + "armadillo": "uno", + }, + }, + }, + }, + { + name: "nil out", + curr: map[string]interface{}{ + "alpha": "first", + }, + additional: map[string]interface{}{ + "alpha": nil, + }, + + expected: map[string]interface{}{ + "alpha": nil, + }, + }, + { + name: "force empty", + curr: map[string]interface{}{ + "alpha": "first", + }, + additional: map[string]interface{}{ + "alpha": "", + }, + + expected: map[string]interface{}{ + "alpha": "", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := mergeConfig(test.curr, test.additional, "", test.specialCases) + switch { + case err == nil && len(test.expectedErr) == 0: + case err == nil && len(test.expectedErr) != 0: + t.Fatalf("missing %q", test.expectedErr) + case err != nil && len(test.expectedErr) == 0: + t.Fatal(err) + case err != nil && len(test.expectedErr) != 0 && !strings.Contains(err.Error(), test.expectedErr): + t.Fatalf("expected %q, got %q", test.expectedErr, err) + } + + if !reflect.DeepEqual(test.expected, test.curr) { + t.Error(diff.ObjectDiff(test.expected, test.curr)) + } + }) + } +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go index a27bfdb717f8..eb2477821a2d 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go @@ -9,8 +9,6 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" @@ -41,6 +39,9 @@ func sync_v310_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1al if signingVersionAvailability.ReadyReplicas > 0 && apiServiceInjectorVersionAvailability.ReadyReplicas > 0 { mergedVersionAvailability.ReadyReplicas = 1 } + for _, err := range allErrors { + mergedVersionAvailability.Errors = append(mergedVersionAvailability.Errors, err.Error()) + } return mergedVersionAvailability, allErrors } @@ -213,12 +214,7 @@ func manageSigningSecret(c ServiceCertSignerOperator) (*corev1.Secret, bool, err } func ensureServingSignerConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - // TODO use an unstructured object to merge configs - config, err := readServiceServingCertSignerConfig(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml")) - if err != nil { - return nil, false, err - } - configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, config) + configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml"), options.ServiceServingCertSignerConfig.Raw, nil) if err != nil { return nil, false, err } @@ -251,12 +247,7 @@ func serviceServingCertSignerName() string { } func ensureAPIServiceInjectorConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - // TODO use an unstructured object to merge configs - config, err := readServiceServingCertSignerConfig(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml")) - if err != nil { - return nil, false, err - } - configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, config) + configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml"), options.APIServiceCABundleInjectorConfig.Raw, nil) if err != nil { return nil, false, err } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go new file mode 100644 index 000000000000..026d43698836 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go @@ -0,0 +1,211 @@ +package main + +import ( + "bufio" + "encoding/json" + "encoding/xml" + "flag" + "fmt" + "io" + "os" + "sort" + "strings" + "time" + + "github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api" +) + +type Record struct { + Package string + Test string + + Time time.Time + Action string + Output string + Elapsed float64 +} + +type testSuite struct { + suite *api.TestSuite + tests map[string]*api.TestCase +} + +func main() { + summarize := false + verbose := false + flag.BoolVar(&summarize, "summary", true, "display a summary as items are processed") + flag.BoolVar(&verbose, "v", false, "display passing results") + flag.Parse() + + if err := process(os.Stdin, summarize, verbose); err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } +} + +func process(r io.Reader, summarize, verbose bool) error { + suites, err := stream(r, summarize, verbose) + if err != nil { + return err + } + obj := newTestSuites(suites) + out, err := xml.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + fmt.Fprintf(os.Stdout, "%s\n", string(out)) + return nil +} + +func newTestSuites(suites map[string]*testSuite) *api.TestSuites { + all := &api.TestSuites{} + for _, suite := range suites { + for _, test := range suite.suite.TestCases { + suite.suite.NumTests++ + if test.SkipMessage != nil { + suite.suite.NumSkipped++ + continue + } + if test.FailureOutput != nil { + suite.suite.NumFailed++ + continue + } + } + // suites with no tests are usually empty packages, ignore them + if suite.suite.NumTests == 0 { + continue + } + // always return the test cases in consistent order + sort.Slice(suite.suite.TestCases, func(i, j int) bool { + return suite.suite.TestCases[i].Name < suite.suite.TestCases[j].Name + }) + all.Suites = append(all.Suites, suite.suite) + } + // always return the test suites in consistent order + sort.Slice(all.Suites, func(i, j int) bool { + return all.Suites[i].Name < all.Suites[j].Name + }) + return all +} + +func stream(r io.Reader, summarize, verbose bool) (map[string]*testSuite, error) { + suites := make(map[string]*testSuite) + defaultTest := &api.TestCase{ + Name: "build and execution", + } + defaultSuite := &testSuite{ + suite: &api.TestSuite{Name: "go test", TestCases: []*api.TestCase{defaultTest}}, + } + suites[""] = defaultSuite + + rdr := bufio.NewReader(r) + for { + // some output from go test -json is not valid JSON - read the line to see whether it + // starts with { - if not, just mirror it to stderr and continue. + line, err := rdr.ReadString('\n') + if err != nil { + if err != io.EOF { + return suites, err + } + break + } + if len(line) == 0 || line[0] != '{' { + defaultTest.SystemOut += line + if strings.HasPrefix(line, "FAIL") { + defaultTest.FailureOutput = &api.FailureOutput{} + } + fmt.Fprint(os.Stderr, line) + continue + } + var r Record + if err := json.Unmarshal([]byte(line), &r); err != nil { + if err == io.EOF { + return suites, nil + } + fmt.Fprintf(os.Stderr, "error: Unable to parse remainder of output %v\n", err) + return suites, nil + } + + suite, ok := suites[r.Package] + if !ok { + suite = &testSuite{ + suite: &api.TestSuite{ + Name: r.Package, + }, + tests: make(map[string]*api.TestCase), + } + suites[r.Package] = suite + } + + // if this is package level output, we only care about pass/fail duration + if len(r.Test) == 0 { + switch r.Action { + case "pass", "fail": + suite.suite.Duration = r.Elapsed + } + continue + } + + test, ok := suite.tests[r.Test] + if !ok { + test = &api.TestCase{ + Name: r.Test, + } + suite.suite.TestCases = append(suite.suite.TestCases, test) + suite.tests[r.Test] = test + } + + switch r.Action { + case "run": + case "pause": + case "cont": + case "bench": + case "skip": + if summarize { + fmt.Fprintf(os.Stderr, "SKIP: %s %s\n", r.Package, r.Test) + } + test.SkipMessage = &api.SkipMessage{ + Message: r.Output, + } + case "pass": + if summarize && verbose { + fmt.Fprintf(os.Stderr, "PASS: %s %s %s\n", r.Package, r.Test, time.Duration(r.Elapsed*float64(time.Second))) + } + test.SystemOut = "" + test.Duration = r.Elapsed + case "fail": + if summarize { + fmt.Fprintf(os.Stderr, "FAIL: %s %s %s\n", r.Package, r.Test, time.Duration(r.Elapsed*float64(time.Second))) + } + test.Duration = r.Elapsed + if len(r.Output) == 0 { + r.Output = test.SystemOut + if len(r.Output) > 50 { + r.Output = r.Output[:50] + " ..." + } + } + test.FailureOutput = &api.FailureOutput{ + Message: r.Output, + Output: r.Output, + } + case "output": + test.SystemOut += r.Output + default: + // usually a bug in go test -json + out := fmt.Sprintf("error: Unrecognized go test action %s: %#v\n", r.Action, r) + defaultTest.SystemOut += line + defaultTest.SystemOut += out + defaultTest.FailureOutput = &api.FailureOutput{} + fmt.Fprintf(os.Stderr, out) + } + } + + // if we recorded any failure output + if defaultTest.FailureOutput != nil { + defaultTest.FailureOutput.Message = "Some packages failed during test execution" + defaultTest.FailureOutput.Output = defaultTest.SystemOut + defaultTest.SystemOut = "" + } + + return suites, nil +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd new file mode 100644 index 000000000000..92552b33db5d --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd @@ -0,0 +1,203 @@ + + + + JUnit test result schema for the Apache Ant JUnit and JUnitReport tasks +Copyright © 2011, Windy Road Technology Pty. Limited +The Apache Ant JUnit XML Schema is distributed under the terms of the GNU Lesser General Public License (LGPL) http://www.gnu.org/licenses/lgpl.html +Permission to waive conditions of this license may be requested from Windy Road Support (http://windyroad.org/support). + + + + + + + + + + Contains an aggregation of testsuite results + + + + + + + + + + Derived from testsuite/@name in the non-aggregated documents + + + + + Starts at '0' for the first testsuite and is incremented by 1 for each following testsuite + + + + + + + + + + + + Contains the results of exexuting a testsuite + + + + + Properties (e.g., environment settings) set during test execution + + + + + + + + + + + + + + + + + + + + + + + + Indicates that the test errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Contains as a text node relevant data for the error, e.g., a stack trace + + + + + + + The error message. e.g., if a java exception is thrown, the return value of getMessage() + + + + + The type of error that occured. e.g., if a java execption is thrown the full class name of the exception. + + + + + + + + + Indicates that the test failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals. Contains as a text node relevant data for the failure, e.g., a stack trace + + + + + + + The message specified in the assert + + + + + The type of the assert. + + + + + + + + + + Name of the test method + + + + + Full class name for the class the test method is in. + + + + + Time taken (in seconds) to execute the test + + + + + + + Data that was written to standard out while the test was executed + + + + + + + + + + Data that was written to standard error while the test was executed + + + + + + + + + + + Full class name of the test for non-aggregated testsuite documents. Class name without the package for aggregated testsuites documents + + + + + + + + + + when the test was executed. Timezone may not be specified. + + + + + Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined. + + + + + + + + + + The total number of tests in the suite + + + + + The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals + + + + + The total number of tests in the suite that errorrd. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. + + + + + Time taken (in seconds) to execute the tests in the suite + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go new file mode 100644 index 000000000000..be8e650f4af5 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go @@ -0,0 +1,37 @@ +package api + +import "fmt" + +// This file implements Stringer for the API types for ease of debugging + +func (t *TestSuites) String() string { + return fmt.Sprintf("Test Suites with suites: %s.", t.Suites) +} + +func (t *TestSuite) String() string { + childDescriptions := []string{} + for _, child := range t.Children { + childDescriptions = append(childDescriptions, child.String()) + } + return fmt.Sprintf("Test Suite %q with properties: %s, %d test cases, of which %d failed and %d were skipped: %s, and children: %s.", t.Name, t.Properties, t.NumTests, t.NumFailed, t.NumSkipped, t.TestCases, childDescriptions) +} + +func (t *TestCase) String() string { + var result, message, output string + result = "passed" + if t.SkipMessage != nil { + result = "skipped" + message = t.SkipMessage.Message + } + if t.FailureOutput != nil { + result = "failed" + message = t.FailureOutput.Message + output = t.FailureOutput.Output + } + + return fmt.Sprintf("Test Case %q %s after %f seconds with message %q and output %q.", t.Name, result, t.Duration, message, output) +} + +func (p *TestSuiteProperty) String() string { + return fmt.Sprintf("%q=%q", p.Name, p.Value) +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go new file mode 100644 index 000000000000..ec83e2dddde3 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go @@ -0,0 +1,30 @@ +package api + +import "time" + +// SetDuration sets the runtime duration of the test case +func (t *TestCase) SetDuration(duration string) error { + parsedDuration, err := time.ParseDuration(duration) + if err != nil { + return err + } + + // we round to the millisecond on duration + t.Duration = float64(int(parsedDuration.Seconds()*1000)) / 1000 + return nil +} + +// MarkSkipped marks the test as skipped with the given message +func (t *TestCase) MarkSkipped(message string) { + t.SkipMessage = &SkipMessage{ + Message: message, + } +} + +// MarkFailed marks the test as failed with the given message and output +func (t *TestCase) MarkFailed(message, output string) { + t.FailureOutput = &FailureOutput{ + Message: message, + Output: output, + } +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go new file mode 100644 index 000000000000..1e36d06ca33a --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go @@ -0,0 +1,67 @@ +package api + +import "time" + +// AddProperty adds a property to the test suite, deduplicating multiple additions of the same property +// by overwriting the previous record to reflect the new values +func (t *TestSuite) AddProperty(name, value string) { + for _, property := range t.Properties { + if property.Name == name { + property.Value = value + return + } + } + + t.Properties = append(t.Properties, &TestSuiteProperty{Name: name, Value: value}) +} + +// AddTestCase adds a test case to the test suite and updates test suite metrics as necessary +func (t *TestSuite) AddTestCase(testCase *TestCase) { + t.NumTests += 1 + + switch { + case testCase.SkipMessage != nil: + t.NumSkipped += 1 + case testCase.FailureOutput != nil: + t.NumFailed += 1 + default: + // we do not preserve output on tests that are not failures or skips + testCase.SystemOut = "" + testCase.SystemErr = "" + } + + t.Duration += testCase.Duration + // we round to the millisecond on duration + t.Duration = float64(int(t.Duration*1000)) / 1000 + + t.TestCases = append(t.TestCases, testCase) +} + +// SetDuration sets the duration of the test suite if this value is not calculated by aggregating the durations +// of all of the substituent test cases. This should *not* be used if the total duration of the test suite is +// calculated as that sum, as AddTestCase will handle that case. +func (t *TestSuite) SetDuration(duration string) error { + parsedDuration, err := time.ParseDuration(duration) + if err != nil { + return err + } + + // we round to the millisecond on duration + t.Duration = float64(int(parsedDuration.Seconds()*1000)) / 1000 + return nil +} + +// ByName implements sort.Interface for []*TestSuite based on the Name field +type ByName []*TestSuite + +func (n ByName) Len() int { + return len(n) +} + +func (n ByName) Swap(i, j int) { + n[i], n[j] = n[j], n[i] +} + +func (n ByName) Less(i, j int) bool { + return n[i].Name < n[j].Name +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go new file mode 100644 index 000000000000..58339044c589 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go @@ -0,0 +1,108 @@ +package api + +import "encoding/xml" + +// The below types are directly marshalled into XML. The types correspond to jUnit +// XML schema, but do not contain all valid fields. For instance, the class name +// field for test cases is omitted, as this concept does not directly apply to Go. +// For XML specifications see http://help.catchsoftware.com/display/ET/JUnit+Format +// or view the XSD included in this package as 'junit.xsd' + +// TestSuites represents a flat collection of jUnit test suites. +type TestSuites struct { + XMLName xml.Name `xml:"testsuites"` + + // Suites are the jUnit test suites held in this collection + Suites []*TestSuite `xml:"testsuite"` +} + +// TestSuite represents a single jUnit test suite, potentially holding child suites. +type TestSuite struct { + XMLName xml.Name `xml:"testsuite"` + + // Name is the name of the test suite + Name string `xml:"name,attr"` + + // NumTests records the number of tests in the TestSuite + NumTests uint `xml:"tests,attr"` + + // NumSkipped records the number of skipped tests in the suite + NumSkipped uint `xml:"skipped,attr"` + + // NumFailed records the number of failed tests in the suite + NumFailed uint `xml:"failures,attr"` + + // Duration is the time taken in seconds to run all tests in the suite + Duration float64 `xml:"time,attr"` + + // Properties holds other properties of the test suite as a mapping of name to value + Properties []*TestSuiteProperty `xml:"properties,omitempty"` + + // TestCases are the test cases contained in the test suite + TestCases []*TestCase `xml:"testcase"` + + // Children holds nested test suites + Children []*TestSuite `xml:"testsuite"` +} + +// TestSuiteProperty contains a mapping of a property name to a value +type TestSuiteProperty struct { + XMLName xml.Name `xml:"property"` + + Name string `xml:"name,attr"` + Value string `xml:"value,attr"` +} + +// TestCase represents a jUnit test case +type TestCase struct { + XMLName xml.Name `xml:"testcase"` + + // Name is the name of the test case + Name string `xml:"name,attr"` + + // Classname is an attribute set by the package type and is required + Classname string `xml:"classname,attr,omitempty"` + + // Duration is the time taken in seconds to run the test + Duration float64 `xml:"time,attr"` + + // SkipMessage holds the reason why the test was skipped + SkipMessage *SkipMessage `xml:"skipped"` + + // FailureOutput holds the output from a failing test + FailureOutput *FailureOutput `xml:"failure"` + + // SystemOut is output written to stdout during the execution of this test case + SystemOut string `xml:"system-out,omitempty"` + + // SystemErr is output written to stderr during the execution of this test case + SystemErr string `xml:"system-err,omitempty"` +} + +// SkipMessage holds a message explaining why a test was skipped +type SkipMessage struct { + XMLName xml.Name `xml:"skipped"` + + // Message explains why the test was skipped + Message string `xml:"message,attr,omitempty"` +} + +// FailureOutput holds the output from a failing test +type FailureOutput struct { + XMLName xml.Name `xml:"failure"` + + // Message holds the failure message from the test + Message string `xml:"message,attr"` + + // Output holds verbose failure output from the test + Output string `xml:",chardata"` +} + +// TestResult is the result of a test case +type TestResult string + +const ( + TestResultPass TestResult = "pass" + TestResultSkip TestResult = "skip" + TestResultFail TestResult = "fail" +) diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go new file mode 100644 index 000000000000..21f4695e8a4f --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go @@ -0,0 +1,18 @@ +// +build output + +package test + +import ( + "testing" +) + +func TestFoo(t *testing.T) { + t.Run("panic", func(t *testing.T) { + panic("here") + }) + t.Run("pass", func(t *testing.T) { + }) + t.Run("skip", func(t *testing.T) { + t.Skip("skipped") + }) +}