diff --git a/Gopkg.lock b/Gopkg.lock index f634d117..87192e00 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,21 +1,8 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. -[[projects]] - digest = "1:f1f464dded149767f5ceb579e73628139ee1a63d9022602109d439862b18f708" - name = "github.com/Azure/go-autorest" - packages = [ - "autorest", - "autorest/adal", - "autorest/date", - ] - pruneopts = "" - revision = "fc3b03a2d2d1f43fad3007038bd16f044f870722" - version = "v9.10.0" - [[projects]] branch = "master" - digest = "1:9e5b855c99f9d265b8c087cc60195924361cd0a03947e316de07b4ac58fd575a" name = "github.com/Peripli/service-broker-proxy" packages = [ "pkg/config", @@ -24,67 +11,61 @@ "pkg/osb", "pkg/platform", "pkg/sbproxy", - "pkg/server", - "pkg/sm", + "pkg/sm" ] - pruneopts = "" - revision = "ee4d78cf9fc9b7eba4c61cd1603365b99584e17e" + revision = "8fe36b08cf14e0c39204f1f0dc1e4b6c9f0e01c5" [[projects]] branch = "master" - digest = "1:0f632458f0a0a0042793e2247bb4ad4bd925aa25ed91f76960ac6e1c1f3a9c72" name = "github.com/Peripli/service-manager" packages = [ + "api", + "api/broker", + "api/catalog", + "api/filters", + "api/filters/authn", + "api/healthcheck", + "api/info", + "api/osb", + "api/platform", "pkg/env", + "pkg/log", + "pkg/server", "pkg/types", "pkg/util", + "pkg/util/slice", "pkg/web", + "security", + "security/basic", + "security/oidc", + "storage" ] - pruneopts = "" - revision = "20b38a9167ca4d2f03208e6802f8494ef8899f92" + revision = "867632bb5ed70b67a07b0b70f0314e745a57ef23" [[projects]] - branch = "master" - digest = "1:c0bec5f9b98d0bc872ff5e834fac186b807b656683bd29cb82fb207a1513fabb" - name = "github.com/beorn7/perks" - packages = ["quantile"] - pruneopts = "" - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" - -[[projects]] - digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6" - name = "github.com/dgrijalva/jwt-go" + name = "github.com/coreos/go-oidc" packages = ["."] - pruneopts = "" - revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" - version = "v3.2.0" + revision = "1180514eaf4d9f38d0d19eef639a1d695e066e72" [[projects]] - digest = "1:55848e643a99a9dfceb19e090ce67111328fbb1780f34c62a0430994ff85fb90" name = "github.com/fatih/structs" packages = ["."] - pruneopts = "" revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" version = "v1.0" [[projects]] - digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd" name = "github.com/fsnotify/fsnotify" packages = ["."] - pruneopts = "" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] - digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/ghodss/yaml" packages = ["."] - pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] - digest = "1:9ab1b1c637d7c8f49e39d8538a650d7eb2137b076790cff69d160823b505964c" name = "github.com/gobwas/glob" packages = [ ".", @@ -94,119 +75,107 @@ "syntax/ast", "syntax/lexer", "util/runes", - "util/strings", + "util/strings" ] - pruneopts = "" revision = "5ccd90ef52e1e632236f7326478d4faa74f99438" version = "v0.2.3" [[projects]] - digest = "1:6e73003ecd35f4487a5e88270d3ca0a81bc80dc88053ac7e4dcfec5fba30d918" + name = "github.com/gofrs/uuid" + packages = ["."] + revision = "d41eeda0759468834c84365a32d1b1ec4264c75f" + version = "v3.1.0" + +[[projects]] name = "github.com/gogo/protobuf" packages = [ "proto", - "sortkeys", + "sortkeys" ] - pruneopts = "" revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" [[projects]] branch = "master" - digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a" name = "github.com/golang/glog" packages = ["."] - pruneopts = "" revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" [[projects]] - digest = "1:f958a1c137db276e52f0b50efee41a1a389dcdded59a69711f3e872757dab34b" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp", + "ptypes/timestamp" ] - pruneopts = "" - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" [[projects]] branch = "master" - digest = "1:be28c0531a755f2178acf1e327e6f5a8a3968feb5f2567cdc968064253141751" name = "github.com/google/btree" packages = ["."] - pruneopts = "" - revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4" + revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" [[projects]] branch = "master" - digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692" name = "github.com/google/gofuzz" packages = ["."] - pruneopts = "" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] - digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions", + "extensions" ] - pruneopts = "" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] - digest = "1:dbbeb8ddb0be949954c8157ee8439c2adfd8dc1c9510eb44a6e58cb68c3dce28" name = "github.com/gorilla/context" packages = ["."] - pruneopts = "" revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" [[projects]] - digest = "1:aa016bbb412f496a7baed9e02787a60cd15c9a3edfa72da9c4a95d6cea610334" + name = "github.com/gorilla/handlers" + packages = ["."] + revision = "90663712d74cb411cbef281bc1e08c19d1a76145" + version = "v1.3.0" + +[[projects]] name = "github.com/gorilla/mux" packages = ["."] - pruneopts = "" revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" version = "v1.6.1" [[projects]] branch = "master" - digest = "1:009a1928b8c096338b68b5822d838a72b4d8520715c1463614476359f3282ec8" name = "github.com/gregjones/httpcache" packages = [ ".", - "diskcache", + "diskcache" ] - pruneopts = "" revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] branch = "master" - digest = "1:4fe55793760295fbef367890352b720784243e0ad19b5ee242519a4682bb9ef8" name = "github.com/hashicorp/errwrap" packages = ["."] - pruneopts = "" revision = "d6c0cd88035724dd42e0f335ae30161c20575ecc" [[projects]] branch = "master" - digest = "1:0b5ca7d18e4ded1e4dacbb37ff027cb40a80c0fed969e4e03cf7aff129bc1b44" name = "github.com/hashicorp/go-multierror" packages = ["."] - pruneopts = "" revision = "3d5d8f294aa03d8e98859feac328afbdf1ae0703" [[projects]] branch = "master" - digest = "1:9b7c5846d70f425d7fe279595e32a20994c6075e87be03b5c367ed07280877c5" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -218,35 +187,29 @@ "hcl/token", "json/parser", "json/scanner", - "json/token", + "json/token" ] - pruneopts = "" revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" [[projects]] - digest = "1:b3c5b95e56c06f5aa72cb2500e6ee5f44fcd122872d4fec2023a488e561218bc" name = "github.com/hpcloud/tail" packages = [ ".", "ratelimiter", "util", "watch", - "winfile", + "winfile" ] - pruneopts = "" revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5" version = "v1.0.0" [[projects]] - digest = "1:53ac4e911e12dde0ab68655e2006449d207a5a681f084974da2b06e5dbeaca72" name = "github.com/json-iterator/go" packages = ["."] - pruneopts = "" - revision = "ab8a2e0c74be9d3be70b3184d9acc634935ded82" - version = "1.1.4" + revision = "1624edc4454b8682399def8740d46db5e4362ba4" + version = "1.1.5" [[projects]] - digest = "1:783dce2cae6d8a4ad98ae1a1debcd997572b769e45c65b1e48533b7cb5f08e28" name = "github.com/kubernetes-incubator/service-catalog" packages = [ "pkg/apis/servicecatalog", @@ -258,66 +221,45 @@ "pkg/client/clientset_generated/clientset/typed/servicecatalog/v1beta1", "pkg/client/clientset_generated/clientset/typed/settings/v1alpha1", "pkg/filter", - "pkg/svcat", - "pkg/svcat/service-catalog", + "pkg/svcat/service-catalog" ] - pruneopts = "N" revision = "f6f0e41fae6c4f1bdc5c507942ee7f1719555a19" version = "v0.1.27" [[projects]] - digest = "1:961dc3b1d11f969370533390fdf203813162980c858e1dabe827b60940c909a5" name = "github.com/magiconair/properties" packages = ["."] - pruneopts = "" revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" -[[projects]] - digest = "1:63722a4b1e1717be7b98fc686e0b30d5e7f734b9e93d7dee86293b6deab7ea28" - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - pruneopts = "" - revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" - version = "v1.0.1" - [[projects]] branch = "master" - digest = "1:f43ed2c836208c14f45158fd01577c985688a4d11cf9fd475a939819fef3b321" name = "github.com/mitchellh/mapstructure" packages = ["."] - pruneopts = "" revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] - digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" name = "github.com/modern-go/concurrent" packages = ["."] - pruneopts = "" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] - digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" name = "github.com/modern-go/reflect2" packages = ["."] - pruneopts = "" revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" version = "1.0.1" [[projects]] branch = "master" - digest = "1:57eb9b1281b805a5ac973a015658f366eabfe3454c76c587ef135d6f5c6dcdca" name = "github.com/onrik/logrus" packages = [ "filename", - "formatter", + "formatter" ] - pruneopts = "" revision = "ca0a758702be2ae04725ba88dcd27a71949faf33" [[projects]] - digest = "1:a7fd918fb5bd2188436785c0424f8a50b4addfedf37a2b14d796be2a927b8007" name = "github.com/onsi/ginkgo" packages = [ ".", @@ -337,14 +279,12 @@ "reporters/stenographer", "reporters/stenographer/support/go-colorable", "reporters/stenographer/support/go-isatty", - "types", + "types" ] - pruneopts = "" revision = "3774a09d95489ccaa16032e0770d08ea77ba6184" version = "v1.6.0" [[projects]] - digest = "1:a2453f1424ddc8c28a93b2bb59f9503f61f4a1a3a4719b007c8d48a2cada631b" name = "github.com/onsi/gomega" packages = [ ".", @@ -358,206 +298,141 @@ "matchers/support/goraph/edge", "matchers/support/goraph/node", "matchers/support/goraph/util", - "types", + "types" ] - pruneopts = "" revision = "b6ea1ea48f981d0f615a154a45eabb9dd466556d" version = "v1.4.1" [[projects]] - digest = "1:894aef961c056b6d85d12bac890bf60c44e99b46292888bfa66caf529f804457" name = "github.com/pelletier/go-toml" packages = ["."] - pruneopts = "" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" name = "github.com/petar/GoLLRB" packages = ["llrb"] - pruneopts = "" revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] - digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" name = "github.com/peterbourgon/diskv" packages = ["."] - pruneopts = "" revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" version = "v2.0.1" [[projects]] - digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca" name = "github.com/pkg/errors" packages = ["."] - pruneopts = "" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] - digest = "1:f6a2c6b4bb64f764947dd20e940487ac9f8ab090c5a1cee9e4b384fd859867c6" name = "github.com/pmorie/go-open-service-broker-client" packages = ["v2"] - pruneopts = "" - revision = "e8aa16c9036317bd59ced8921e9da6197ab577e3" - version = "0.0.5" - -[[projects]] - digest = "1:0686ab7b245ac8eb9e083322f0b27fc2267adace750b0b392a825b987b566c55" - name = "github.com/pmorie/osb-broker-lib" - packages = [ - "pkg/broker", - "pkg/metrics", - "pkg/rest", - "pkg/server", - ] - pruneopts = "" - revision = "f4ca270ef323318b363f986229bd10bccb2d28b1" + revision = "dca737037ce636eb282e84e3a1c7479c9692e884" version = "0.0.10" -[[projects]] - digest = "1:4142d94383572e74b42352273652c62afec5b23f325222ed09198f46009022d1" - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp", - ] - pruneopts = "" - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" - -[[projects]] - branch = "master" - digest = "1:185cf55b1f44a1bf243558901c3f06efa5c64ba62cfdcbb1bf7bbe8c3fb68561" - name = "github.com/prometheus/client_model" - packages = ["go"] - pruneopts = "" - revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" - -[[projects]] - branch = "master" - digest = "1:f477ef7b65d94fb17574fc6548cef0c99a69c1634ea3b6da248b63a61ebe0498" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model", - ] - pruneopts = "" - revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" - [[projects]] branch = "master" - digest = "1:e04aaa0e8f8da0ed3d6c0700bd77eda52a47f38510063209d72d62f0ef807d5e" - name = "github.com/prometheus/procfs" + name = "github.com/pquerna/cachecontrol" packages = [ ".", - "internal/util", - "nfs", - "xfs", + "cacheobject" ] - pruneopts = "" - revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" + revision = "1555304b9b35fdd2b425bccf1a5613677705e7d0" [[projects]] branch = "master" - digest = "1:6ab228f39a195cb1dab3564a0f27dc24a52bb3a19fa58dd2967f1e7b2482d82b" name = "github.com/robfig/cron" packages = ["."] - pruneopts = "" revision = "b41be1df696709bb6395fe435af20370037c0b4c" [[projects]] - digest = "1:42a42c4bc67bed17f40fddf0f24d4403e25e7b96488456cf4248e6d16659d370" name = "github.com/sirupsen/logrus" packages = ["."] - pruneopts = "" revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" version = "v1.0.4" [[projects]] - digest = "1:7ba2551c9a8de293bc575dbe2c0d862c52252d26f267f784547f059f512471c8" name = "github.com/spf13/afero" packages = [ ".", - "mem", + "mem" ] - pruneopts = "" revision = "787d034dfe70e44075ccc060d346146ef53270ad" version = "v1.1.1" [[projects]] - digest = "1:d0b38ba6da419a6d4380700218eeec8623841d44a856bb57369c172fbf692ab4" name = "github.com/spf13/cast" packages = ["."] - pruneopts = "" revision = "8965335b8c7107321228e3e3702cab9832751bac" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:104517520aab91164020ab6524a5d6b7cafc641b2e42ac6236f6ac1deac4f66a" name = "github.com/spf13/jwalterweatherman" packages = ["."] - pruneopts = "" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] - digest = "1:8e243c568f36b09031ec18dff5f7d2769dcf5ca4d624ea511c8e3197dc3d352d" name = "github.com/spf13/pflag" packages = ["."] - pruneopts = "" revision = "583c0c0531f06d5278b7d917446061adc344b5cd" version = "v1.0.1" [[projects]] - digest = "1:3dab237cd3263a290d771d133fed777bb56c22e380b00ebe92e6531d5c8d3d0c" name = "github.com/spf13/viper" packages = ["."] - pruneopts = "" revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736" version = "v1.0.2" [[projects]] branch = "master" - digest = "1:cae234a803b78380e4d769db6036b9fcc8c08ed4ff862571ffc1a958edc1f629" name = "golang.org/x/crypto" - packages = ["ssh/terminal"] - pruneopts = "" - revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + packages = [ + "ed25519", + "ed25519/internal/edwards25519", + "pbkdf2", + "ssh/terminal" + ] + revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] branch = "master" - digest = "1:b970d5e8b11b4c8927a06298566eb8daf66a009702688b4142cc2a961e374e91" name = "golang.org/x/net" packages = [ "context", + "context/ctxhttp", "html", "html/atom", "html/charset", "http/httpguts", "http2", "http2/hpack", - "idna", + "idna" + ] + revision = "922f4815f713f213882e8ef45e0d315b164d705c" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "internal" ] - pruneopts = "" - revision = "f4c29de78a2a91c00474a2e689954305c350adf9" + revision = "f720f1faee02c1fb456408c22886169405f239aa" [[projects]] branch = "master" - digest = "1:469d265422d3992c7af23257fb8198d4d9348156b73ea89ae56d8117d4b89005" name = "golang.org/x/sys" packages = [ "unix", - "windows", + "windows" ] - pruneopts = "" - revision = "3dc4335d56c789b04b0ba99b7a37249d9b614314" + revision = "4ea2f632f6e912459fe60b26b1749377f0d889d5" [[projects]] - digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" packages = [ "collate", @@ -585,55 +460,67 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable", + "unicode/rangetable" ] - pruneopts = "" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:55a681cb66f28755765fa5fa5104cbd8dc85c55c02d206f9f89566451e3fe1aa" name = "golang.org/x/time" packages = ["rate"] - pruneopts = "" revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" [[projects]] - digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd" + name = "google.golang.org/appengine" + packages = [ + "internal", + "internal/base", + "internal/datastore", + "internal/log", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] + revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" + version = "v1.1.0" + +[[projects]] name = "gopkg.in/fsnotify.v1" packages = ["."] - pruneopts = "" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" source = "https://github.com/fsnotify/fsnotify.git" version = "v1.4.7" [[projects]] - digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6" name = "gopkg.in/inf.v0" packages = ["."] - pruneopts = "" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" version = "v0.9.1" +[[projects]] + name = "gopkg.in/square/go-jose.v2" + packages = [ + ".", + "cipher", + "json" + ] + revision = "8254d6c783765f38c8675fae4427a1fe73fbd09d" + version = "v2.1.8" + [[projects]] branch = "v1" - digest = "1:a96d16bd088460f2e0685d46c39bcf1208ba46e0a977be2df49864ec7da447dd" name = "gopkg.in/tomb.v1" packages = ["."] - pruneopts = "" revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8" [[projects]] - digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" name = "gopkg.in/yaml.v2" packages = ["."] - pruneopts = "" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] - digest = "1:f420c8548c93242d8e5dcfa5b34e0243883b4e660f65076e869daafac877144d" name = "k8s.io/api" packages = [ "admissionregistration/v1alpha1", @@ -664,14 +551,12 @@ "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1", + "storage/v1beta1" ] - pruneopts = "" revision = "072894a440bdee3a891dea811fe42902311cd2a3" version = "kubernetes-1.11.0" [[projects]] - digest = "1:b6b2fb7b4da1ac973b64534ace2299a02504f16bc7820cb48edb8ca4077183e1" name = "k8s.io/apimachinery" packages = [ "pkg/api/errors", @@ -708,14 +593,12 @@ "pkg/util/yaml", "pkg/version", "pkg/watch", - "third_party/forked/golang/reflect", + "third_party/forked/golang/reflect" ] - pruneopts = "" revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" version = "kubernetes-1.11.0" [[projects]] - digest = "1:d04779a8de7d5465e0463bd986506348de5e89677c74777f695d3145a7a8d15e" name = "k8s.io/client-go" packages = [ "discovery", @@ -764,31 +647,14 @@ "util/cert", "util/connrotation", "util/flowcontrol", - "util/integer", + "util/integer" ] - pruneopts = "" revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" version = "v8.0.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - input-imports = [ - "github.com/Peripli/service-broker-proxy/pkg/config", - "github.com/Peripli/service-broker-proxy/pkg/middleware", - "github.com/Peripli/service-broker-proxy/pkg/platform", - "github.com/Peripli/service-broker-proxy/pkg/sbproxy", - "github.com/Peripli/service-manager/pkg/env", - "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1beta1", - "github.com/kubernetes-incubator/service-catalog/pkg/client/clientset_generated/clientset", - "github.com/kubernetes-incubator/service-catalog/pkg/svcat", - "github.com/onsi/ginkgo", - "github.com/onsi/gomega", - "github.com/sirupsen/logrus", - "github.com/spf13/pflag", - "k8s.io/apimachinery/pkg/apis/meta/v1", - "k8s.io/client-go/kubernetes", - "k8s.io/client-go/rest", - ] + inputs-digest = "4eebd76d4498f05d79921a7ef1c7fe7925fb4246c78a915bf7ad8560141c820b" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 2db13343..ea1e07b4 100755 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -27,7 +27,7 @@ [[constraint]] name = "github.com/kubernetes-incubator/service-catalog" - version = "0.1.27" + version = "=0.1.27" [[constraint]] name = "github.com/Peripli/service-broker-proxy" diff --git a/README.md b/README.md index 9b7d7b3d..f6c95428 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ Docker Images are available on quay.io/service-manager/sb-proxy The service-broker-proxy-k8s is installed via a helm chart. ```bash -helm install charts/service-broker-proxy --name service-broker-proxy --namespace service-broker-proxy --set config.sm.host= --set sm.user= --set sm.password= +helm install charts/service-broker-proxy --name service-broker-proxy --namespace service-broker-proxy --set config.sm.url= --set sm.user= --set sm.password= ``` -**Note:** Make sure you substitute with the Service Manager url, and with the credentials for the Service Manager. The credentials can be obtained when registering the cluster in Service Manager. +**Note:** Make sure you substitute with the Service Manager url, and with the credentials for the Service Manager. The credentials can be obtained when registering the cluster in Service Manager. To use your own images you can set `image.repository`, `image.tag` and `image.pullPolicy` to the helm install command. diff --git a/application.yml b/application.yml index 30380fcd..3a8b25ce 100644 --- a/application.yml +++ b/application.yml @@ -9,15 +9,19 @@ server: port: 8081 - logLevel: debug - logFormat: text - timeout: 5000ms + request_timeout: 4000ms + shutdown_timeout: 4000ms +log: + level: debug + format: text sm: user: admin password: admin - host: http://service-manager.local.pcfdev.io - osbApi: /v1/osb - requestTimeout: 6000ms + url: http://service-manager.local.pcfdev.io + osb_api_path: /v1/osb + request_timeout: 6000ms + skip_ssl_validation: true + resync_period: 1m k8s: client: timeout: 6000ms diff --git a/charts/service-broker-proxy/templates/deployment.yaml b/charts/service-broker-proxy/templates/deployment.yaml index 7471ed0a..b1547be4 100644 --- a/charts/service-broker-proxy/templates/deployment.yaml +++ b/charts/service-broker-proxy/templates/deployment.yaml @@ -33,7 +33,7 @@ spec: mountPath: {{ .Values.file.location }} readOnly: true env: - - name: SERVER_HOST + - name: SELF_URL value: http://{{ template "service-broker-proxy.name" . }}.{{ .Release.Namespace }}:{{ .Values.service.port }} - name: SM_USER valueFrom: diff --git a/charts/service-broker-proxy/values.yaml b/charts/service-broker-proxy/values.yaml index 44707420..07cd2c61 100644 --- a/charts/service-broker-proxy/values.yaml +++ b/charts/service-broker-proxy/values.yaml @@ -30,14 +30,17 @@ reg: config: server: port: 8081 - logLevel: debug - logFormat: text - timeout: 5000ms - # resyncPeriod: 10s + request_timeout: 4000ms + shutdown_timeout: 4000ms + log: + level: debug + format: text sm: - host: http://service-manager.local.pcfdev.io - osbApi: /v1/osb - requestTimeout: 6000ms + url: http://service-manager.local.pcfdev.io + osb_api_path: /v1/osb + request_timeout: 6000ms + skip_ssl_validation: false + resync_period: 1m k8s: client: - timeout: 6000ms + timeout: 30000ms diff --git a/main b/main new file mode 100755 index 00000000..a5f516df Binary files /dev/null and b/main differ diff --git a/main.go b/main.go index 4c5c8bf1..f1212c6c 100755 --- a/main.go +++ b/main.go @@ -6,11 +6,15 @@ import ( "github.com/Peripli/service-broker-proxy-k8s/k8s" "github.com/Peripli/service-broker-proxy/pkg/middleware" "github.com/Peripli/service-broker-proxy/pkg/sbproxy" + "github.com/Peripli/service-manager/pkg/util" "github.com/spf13/pflag" ) func main() { + ctx, cancel := util.HandleInterrupts() + defer cancel() + env := sbproxy.DefaultEnv(func(set *pflag.FlagSet) { k8s.CreatePFlagsForK8SClient(set) }) @@ -25,10 +29,8 @@ func main() { panic(fmt.Errorf("error creating K8S client: %s", err)) } - proxy, err := sbproxy.New(env, platformClient) - if err != nil { - panic(fmt.Errorf("error creating proxy: %s", err)) - } + proxyBuilder := sbproxy.New(ctx, env, platformClient) + proxy := proxyBuilder.Build() proxy.Server.Use(middleware.BasicAuth(platformConfig.Reg.User, platformConfig.Reg.Password)) diff --git a/vendor/github.com/Azure/go-autorest/.github/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/Azure/go-autorest/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index b9440428..00000000 --- a/vendor/github.com/Azure/go-autorest/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,7 +0,0 @@ -Thank you for your contribution to Go-AutoRest! We will triage and review it as soon as we can. - -As part of submitting, please make sure you can make the following assertions: - - [ ] I've tested my changes, adding unit tests if applicable. - - [ ] I've added Apache 2.0 Headers to the top of any new source files. - - [ ] I'm submitting this PR to the `dev` branch, except in the case of urgent bug fixes warranting their own release. - - [ ] If I'm targeting `master`, I've updated [CHANGELOG.md](https://github.com/Azure/go-autorest/blob/master/CHANGELOG.md) to address the changes I'm making. \ No newline at end of file diff --git a/vendor/github.com/Azure/go-autorest/.gitignore b/vendor/github.com/Azure/go-autorest/.gitignore deleted file mode 100644 index ab262cbe..00000000 --- a/vendor/github.com/Azure/go-autorest/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# The standard Go .gitignore file follows. (Sourced from: github.com/github/gitignore/master/Go.gitignore) -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test -.DS_Store -.idea/ - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -# go-autorest specific -vendor/ -autorest/azure/example/example diff --git a/vendor/github.com/Azure/go-autorest/.travis.yml b/vendor/github.com/Azure/go-autorest/.travis.yml deleted file mode 100644 index 14315d75..00000000 --- a/vendor/github.com/Azure/go-autorest/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -sudo: false - -language: go - -go: - - 1.9 - - 1.8 - - 1.7 - -install: - - go get -u github.com/golang/lint/golint - - go get -u github.com/Masterminds/glide - - go get -u github.com/stretchr/testify - - go get -u github.com/GoASTScanner/gas - - glide install - -script: - - grep -L -r --include *.go --exclude-dir vendor -P "Copyright (\d{4}|\(c\)) Microsoft" ./ | tee /dev/stderr | test -z "$(< /dev/stdin)" - - test -z "$(gofmt -s -l -w ./autorest/. | tee /dev/stderr)" - - test -z "$(golint ./autorest/... | tee /dev/stderr)" - - go vet ./autorest/... - - test -z "$(gas ./autorest/... | tee /dev/stderr | grep Error)" - - go build -v ./autorest/... - - go test -v ./autorest/... diff --git a/vendor/github.com/Azure/go-autorest/CHANGELOG.md b/vendor/github.com/Azure/go-autorest/CHANGELOG.md deleted file mode 100644 index 10f1de8e..00000000 --- a/vendor/github.com/Azure/go-autorest/CHANGELOG.md +++ /dev/null @@ -1,345 +0,0 @@ -# CHANGELOG - -## v9.10.0 -- Fix the Service Bus suffix in Azure public env -- Add Service Bus Endpoint (AAD ResourceURI) for use in [Azure Service Bus RBAC Preview](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-role-based-access-control) - -## v9.9.0 - -### New Features - -- Added EventGridKeyAuthorizer for key authorization with event grid topics. - -### Bug Fixes - -- Fixed race condition when auto-refreshing service principal tokens. - -## v9.8.1 - -### Bug Fixes - -- Added http.StatusNoContent (204) to the list of expected status codes for long-running operations. -- Updated runtime version info so it's current. - -## v9.8.0 - -### New Features - -- Added type azure.AsyncOpIncompleteError to be returned from a future's Result() method when the operation has not completed. - -## v9.7.1 - -### Bug Fixes - -- Use correct AAD and Graph endpoints for US Gov environment. - -## v9.7.0 - -### New Features - -- Added support for application/octet-stream MIME types. - -## v9.6.1 - -### Bug Fixes - -- Ensure Authorization header is added to request when polling for registration status. - -## v9.6.0 - -### New Features - -- Added support for acquiring tokens via MSI with a user assigned identity. - -## v9.5.3 - -### Bug Fixes -- Don't remove encoding of existing URL Query parameters when calling autorest.WithQueryParameters. -- Set correct Content Type when using autorest.WithFormData. - -## v9.5.2 - -### Bug Fixes - -- Check for nil *http.Response before dereferencing it. - -## v9.5.1 - -### Bug Fixes - -- Don't count http.StatusTooManyRequests (429) against the retry cap. -- Use retry logic when SkipResourceProviderRegistration is set to true. - -## v9.5.0 - -### New Features - -- Added support for username + password, API key, authoriazation code and cognitive services authentication. -- Added field SkipResourceProviderRegistration to clients to provide a way to skip auto-registration of RPs. -- Added utility function AsStringSlice() to convert its parameters to a string slice. - -### Bug Fixes - -- When checking for authentication failures look at the error type not the status code as it could vary. - -## v9.4.2 - -### Bug Fixes - -- Validate parameters when creating credentials. -- Don't retry requests if the returned status is a 401 (http.StatusUnauthorized) as it will never succeed. - -## v9.4.1 - -### Bug Fixes - -- Update the AccessTokensPath() to read access tokens path through AZURE_ACCESS_TOKEN_FILE. If this - environment variable is not set, it will fall back to use default path set by Azure CLI. -- Use case-insensitive string comparison for polling states. - -## v9.4.0 - -### New Features - -- Added WaitForCompletion() to Future as a default polling implementation. - -### Bug Fixes - -- Method Future.Done() shouldn't update polling status for unexpected HTTP status codes. - -## v9.3.1 - -### Bug Fixes - -- DoRetryForStatusCodes will retry if sender.Do returns a non-nil error. - -## v9.3.0 - -### New Features - -- Added PollingMethod() to Future so callers know what kind of polling mechanism is used. -- Added azure.ChangeToGet() which transforms an http.Request into a GET (to be used with LROs). - -## v9.2.0 - -### New Features - -- Added support for custom Azure Stack endpoints. -- Added type azure.Future used to track the status of long-running operations. - -### Bug Fixes - -- Preserve the original error in DoRetryWithRegistration when registration fails. - -## v9.1.1 - -- Fixes a bug regarding the cookie jar on `autorest.Client.Sender`. - -## v9.1.0 - -### New Features - -- In cases where there is a non-empty error from the service, attempt to unmarshal it instead of uniformly calling it an "Unknown" error. -- Support for loading Azure CLI Authentication files. -- Automatically register your subscription with the Azure Resource Provider if it hadn't been previously. - -### Bug Fixes - - - RetriableRequest can now tolerate a ReadSeekable body being read but not reset. - - Adding missing Apache Headers - -## v9.0.0 - -> **IMPORTANT:** This release was intially labeled incorrectly as `v8.4.0`. From the time it was released, it should have been marked `v9.0.0` because it contains breaking changes to the MSI packages. We appologize for any inconvenience this causes. - -Adding MSI Endpoint Support and CLI token rehydration. - -## v8.3.1 - -Pick up bug fix in adal for MSI support. - -## v8.3.0 - -Updates to Error string formats for clarity. Also, adding a copy of the http.Response to errors for an improved debugging experience. - -## v8.2.0 - -### New Features - -- Add support for bearer authentication callbacks -- Support 429 response codes that include "Retry-After" header -- Support validation constraint "Pattern" for map keys - -### Bug Fixes - -- Make RetriableRequest work with multiple versions of Go - -## v8.1.1 -Updates the RetriableRequest to take advantage of GetBody() added in Go 1.8. - -## v8.1.0 -Adds RetriableRequest type for more efficient handling of retrying HTTP requests. - -## v8.0.0 - -ADAL refactored into its own package. -Support for UNIX time. - -## v7.3.1 -- Version Testing now removed from production bits that are shipped with the library. - -## v7.3.0 -- Exposing new `RespondDecorator`, `ByDiscardingBody`. This allows operations - to acknowledge that they do not need either the entire or a trailing portion - of accepts response body. In doing so, Go's http library can reuse HTTP - connections more readily. -- Adding `PrepareDecorator` to target custom BaseURLs. -- Adding ACR suffix to public cloud environment. -- Updating Glide dependencies. - -## v7.2.5 -- Fixed the Active Directory endpoint for the China cloud. -- Removes UTF-8 BOM if present in response payload. -- Added telemetry. - -## v7.2.3 -- Fixing bug in calls to `DelayForBackoff` that caused doubling of delay - duration. - -## v7.2.2 -- autorest/azure: added ASM and ARM VM DNS suffixes. - -## v7.2.1 -- fixed parsing of UTC times that are not RFC3339 conformant. - -## v7.2.0 -- autorest/validation: Reformat validation error for better error message. - -## v7.1.0 -- preparer: Added support for multipart formdata - WithMultiPartFormdata() -- preparer: Added support for sending file in request body - WithFile -- client: Added RetryDuration parameter. -- autorest/validation: new package for validation code for Azure Go SDK. - -## v7.0.7 -- Add trailing / to endpoint -- azure: add EnvironmentFromName - -## v7.0.6 -- Add retry logic for 408, 500, 502, 503 and 504 status codes. -- Change url path and query encoding logic. -- Fix DelayForBackoff for proper exponential delay. -- Add CookieJar in Client. - -## v7.0.5 -- Add check to start polling only when status is in [200,201,202]. -- Refactoring for unchecked errors. -- azure/persist changes. -- Fix 'file in use' issue in renewing token in deviceflow. -- Store header RetryAfter for subsequent requests in polling. -- Add attribute details in service error. - -## v7.0.4 -- Better error messages for long running operation failures - -## v7.0.3 -- Corrected DoPollForAsynchronous to properly handle the initial response - -## v7.0.2 -- Corrected DoPollForAsynchronous to continue using the polling method first discovered - -## v7.0.1 -- Fixed empty JSON input error in ByUnmarshallingJSON -- Fixed polling support for GET calls -- Changed format name from TimeRfc1123 to TimeRFC1123 - -## v7.0.0 -- Added ByCopying responder with supporting TeeReadCloser -- Rewrote Azure asynchronous handling -- Reverted to only unmarshalling JSON -- Corrected handling of RFC3339 time strings and added support for Rfc1123 time format - -The `json.Decoder` does not catch bad data as thoroughly as `json.Unmarshal`. Since -`encoding/json` successfully deserializes all core types, and extended types normally provide -their custom JSON serialization handlers, the code has been reverted back to using -`json.Unmarshal`. The original change to use `json.Decode` was made to reduce duplicate -code; there is no loss of function, and there is a gain in accuracy, by reverting. - -Additionally, Azure services indicate requests to be polled by multiple means. The existing code -only checked for one of those (that is, the presence of the `Azure-AsyncOperation` header). -The new code correctly covers all cases and aligns with the other Azure SDKs. - -## v6.1.0 -- Introduced `date.ByUnmarshallingJSONDate` and `date.ByUnmarshallingJSONTime` to enable JSON encoded values. - -## v6.0.0 -- Completely reworked the handling of polled and asynchronous requests -- Removed unnecessary routines -- Reworked `mocks.Sender` to replay a series of `http.Response` objects -- Added `PrepareDecorators` for primitive types (e.g., bool, int32) - -Handling polled and asynchronous requests is no longer part of `Client#Send`. Instead new -`SendDecorators` implement different styles of polled behavior. See`autorest.DoPollForStatusCodes` -and `azure.DoPollForAsynchronous` for examples. - -## v5.0.0 -- Added new RespondDecorators unmarshalling primitive types -- Corrected application of inspection and authorization PrependDecorators - -## v4.0.0 -- Added support for Azure long-running operations. -- Added cancelation support to all decorators and functions that may delay. -- Breaking: `DelayForBackoff` now accepts a channel, which may be nil. - -## v3.1.0 -- Add support for OAuth Device Flow authorization. -- Add support for ServicePrincipalTokens that are backed by an existing token, rather than other secret material. -- Add helpers for persisting and restoring Tokens. -- Increased code coverage in the github.com/Azure/autorest/azure package - -## v3.0.0 -- Breaking: `NewErrorWithError` no longer takes `statusCode int`. -- Breaking: `NewErrorWithStatusCode` is replaced with `NewErrorWithResponse`. -- Breaking: `Client#Send()` no longer takes `codes ...int` argument. -- Add: XML unmarshaling support with `ByUnmarshallingXML()` -- Stopped vending dependencies locally and switched to [Glide](https://github.com/Masterminds/glide). - Applications using this library should either use Glide or vendor dependencies locally some other way. -- Add: `azure.WithErrorUnlessStatusCode()` decorator to handle Azure errors. -- Fix: use `net/http.DefaultClient` as base client. -- Fix: Missing inspection for polling responses added. -- Add: CopyAndDecode helpers. -- Improved `./autorest/to` with `[]string` helpers. -- Removed golint suppressions in .travis.yml. - -## v2.1.0 - -- Added `StatusCode` to `Error` for more easily obtaining the HTTP Reponse StatusCode (if any) - -## v2.0.0 - -- Changed `to.StringMapPtr` method signature to return a pointer -- Changed `ServicePrincipalCertificateSecret` and `NewServicePrincipalTokenFromCertificate` to support generic certificate and private keys - -## v1.0.0 - -- Added Logging inspectors to trace http.Request / Response -- Added support for User-Agent header -- Changed WithHeader PrepareDecorator to use set vs. add -- Added JSON to error when unmarshalling fails -- Added Client#Send method -- Corrected case of "Azure" in package paths -- Added "to" helpers, Azure helpers, and improved ease-of-use -- Corrected golint issues - -## v1.0.1 - -- Added CHANGELOG.md - -## v1.1.0 - -- Added mechanism to retrieve a ServicePrincipalToken using a certificate-signed JWT -- Added an example of creating a certificate-based ServicePrincipal and retrieving an OAuth token using the certificate - -## v1.1.1 - -- Introduce godeps and vendor dependencies introduced in v1.1.1 diff --git a/vendor/github.com/Azure/go-autorest/GNUmakefile b/vendor/github.com/Azure/go-autorest/GNUmakefile deleted file mode 100644 index a434e73a..00000000 --- a/vendor/github.com/Azure/go-autorest/GNUmakefile +++ /dev/null @@ -1,23 +0,0 @@ -DIR?=./autorest/ - -default: build - -build: fmt - go install $(DIR) - -test: - go test $(DIR) || exit 1 - -vet: - @echo "go vet ." - @go vet $(DIR)... ; if [ $$? -eq 1 ]; then \ - echo ""; \ - echo "Vet found suspicious constructs. Please check the reported constructs"; \ - echo "and fix them if necessary before submitting the code for review."; \ - exit 1; \ - fi - -fmt: - gofmt -w $(DIR) - -.PHONY: build test vet fmt diff --git a/vendor/github.com/Azure/go-autorest/LICENSE b/vendor/github.com/Azure/go-autorest/LICENSE deleted file mode 100644 index b9d6a27e..00000000 --- a/vendor/github.com/Azure/go-autorest/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/README.md b/vendor/github.com/Azure/go-autorest/README.md deleted file mode 100644 index f4c34d0e..00000000 --- a/vendor/github.com/Azure/go-autorest/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# go-autorest - -[![GoDoc](https://godoc.org/github.com/Azure/go-autorest/autorest?status.png)](https://godoc.org/github.com/Azure/go-autorest/autorest) [![Build Status](https://travis-ci.org/Azure/go-autorest.svg?branch=master)](https://travis-ci.org/Azure/go-autorest) [![Go Report Card](https://goreportcard.com/badge/Azure/go-autorest)](https://goreportcard.com/report/Azure/go-autorest) - -## Usage -Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines -and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/) -generated Go code. - -The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, -and Responding. A typical pattern is: - -```go - req, err := Prepare(&http.Request{}, - token.WithAuthorization()) - - resp, err := Send(req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusInternalServerError), - DoCloseIfError(), - DoRetryForAttempts(5, time.Second)) - - err = Respond(resp, - ByDiscardingBody(), - ByClosing()) -``` - -Each phase relies on decorators to modify and / or manage processing. Decorators may first modify -and then pass the data along, pass the data first and then modify the result, or wrap themselves -around passing the data (such as a logger might do). Decorators run in the order provided. For -example, the following: - -```go - req, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) -``` - -will set the URL to: - -``` - https://microsoft.com/a/b/c -``` - -Preparers and Responders may be shared and re-used (assuming the underlying decorators support -sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders -shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, -all bound together by means of input / output channels. - -Decorators hold their passed state within a closure (such as the path components in the example -above). Be careful to share Preparers and Responders only in a context where such held state -applies. For example, it may not make sense to share a Preparer that applies a query string from a -fixed set of values. Similarly, sharing a Responder that reads the response body into a passed -struct (e.g., `ByUnmarshallingJson`) is likely incorrect. - -Errors raised by autorest objects and methods will conform to the `autorest.Error` interface. - -See the included examples for more detail. For details on the suggested use of this package by -generated clients, see the Client described below. - -## Helpers - -### Handling Swagger Dates - -The Swagger specification (https://swagger.io) that drives AutoRest -(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The -github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure correct -parsing and formatting. - -### Handling Empty Values - -In JSON, missing values have different semantics than empty values. This is especially true for -services using the HTTP PATCH verb. The JSON submitted with a PATCH request generally contains -only those values to modify. Missing values are to be left unchanged. Developers, then, require a -means to both specify an empty value and to leave the value out of the submitted JSON. - -The Go JSON package (`encoding/json`) supports the `omitempty` tag. When specified, it omits -empty values from the rendered JSON. Since Go defines default values for all base types (such as "" -for string and 0 for int) and provides no means to mark a value as actually empty, the JSON package -treats default values as meaning empty, omitting them from the rendered JSON. This means that, using -the Go base types encoded through the default JSON package, it is not possible to create JSON to -clear a value at the server. - -The workaround within the Go community is to use pointers to base types in lieu of base types within -structures that map to JSON. For example, instead of a value of type `string`, the workaround uses -`*string`. While this enables distinguishing empty values from those to be unchanged, creating -pointers to a base type (notably constant, in-line values) requires additional variables. This, for -example, - -```go - s := struct { - S *string - }{ S: &"foo" } -``` -fails, while, this - -```go - v := "foo" - s := struct { - S *string - }{ S: &v } -``` -succeeds. - -To ease using pointers, the subpackage `to` contains helpers that convert to and from pointers for -Go base types which have Swagger analogs. It also provides a helper that converts between -`map[string]string` and `map[string]*string`, enabling the JSON to specify that the value -associated with a key should be cleared. With the helpers, the previous example becomes - -```go - s := struct { - S *string - }{ S: to.StringPtr("foo") } -``` - -## Install - -```bash -go get github.com/Azure/go-autorest/autorest -go get github.com/Azure/go-autorest/autorest/azure -go get github.com/Azure/go-autorest/autorest/date -go get github.com/Azure/go-autorest/autorest/to -``` - -## License - -See LICENSE file. - ------ -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md b/vendor/github.com/Azure/go-autorest/autorest/adal/README.md deleted file mode 100644 index 08966c9c..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md +++ /dev/null @@ -1,287 +0,0 @@ -# Azure Active Directory library for Go - -This project provides a stand alone Azure Active Directory library for Go. The code was extracted -from [go-autorest](https://github.com/Azure/go-autorest/) project, which is used as a base for -[azure-sdk-for-go](https://github.com/Azure/azure-sdk-for-go). - - -## Installation - -``` -go get -u github.com/Azure/go-autorest/autorest/adal -``` - -## Usage - -An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) follow these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli). - -### Register an Azure AD Application with secret - - -1. Register a new application with a `secret` credential - - ``` - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --password secret - ``` - -2. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "Application ID" - ``` - - * Replace `Application ID` with `appId` from step 1. - -### Register an Azure AD Application with certificate - -1. Create a private key - - ``` - openssl genrsa -out "example-app.key" 2048 - ``` - -2. Create the certificate - - ``` - openssl req -new -key "example-app.key" -subj "/CN=example-app" -out "example-app.csr" - openssl x509 -req -in "example-app.csr" -signkey "example-app.key" -out "example-app.crt" -days 10000 - ``` - -3. Create the PKCS12 version of the certificate containing also the private key - - ``` - openssl pkcs12 -export -out "example-app.pfx" -inkey "example-app.key" -in "example-app.crt" -passout pass: - - ``` - -4. Register a new application with the certificate content form `example-app.crt` - - ``` - certificateContents="$(tail -n+2 "example-app.crt" | head -n-1)" - - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --key-usage Verify --end-date 2018-01-01 \ - --key-value "${certificateContents}" - ``` - -5. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "APPLICATION_ID" - ``` - - * Replace `APPLICATION_ID` with `appId` from step 4. - - -### Grant the necessary permissions - -Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained -level. There is a set of [pre-defined roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles) -which can be assigned to a service principal of an Azure AD application depending of your needs. - -``` -az role assignment create --assigner "SERVICE_PRINCIPAL_ID" --role "ROLE_NAME" -``` - -* Replace the `SERVICE_PRINCIPAL_ID` with the `appId` from previous step. -* Replace the `ROLE_NAME` with a role name of your choice. - -It is also possible to define custom role definitions. - -``` -az role definition create --role-definition role-definition.json -``` - -* Check [custom roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file. - - -### Acquire Access Token - -The common configuration used by all flows: - -```Go -const activeDirectoryEndpoint = "https://login.microsoftonline.com/" -tenantID := "TENANT_ID" -oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) - -applicationID := "APPLICATION_ID" - -callback := func(token adal.Token) error { - // This is called after the token is acquired -} - -// The resource for which the token is acquired -resource := "https://management.core.windows.net/" -``` - -* Replace the `TENANT_ID` with your tenant ID. -* Replace the `APPLICATION_ID` with the value from previous section. - -#### Client Credentials - -```Go -applicationSecret := "APPLICATION_SECRET" - -spt, err := adal.NewServicePrincipalToken( - oauthConfig, - appliationID, - applicationSecret, - resource, - callbacks...) -if err != nil { - return nil, err -} - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Replace the `APPLICATION_SECRET` with the `password` value from previous section. - -#### Client Certificate - -```Go -certificatePath := "./example-app.pfx" - -certData, err := ioutil.ReadFile(certificatePath) -if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) -} - -// Get the certificate and private key from pfx file -certificate, rsaPrivateKey, err := decodePkcs12(certData, "") -if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) -} - -spt, err := adal.NewServicePrincipalTokenFromCertificate( - oauthConfig, - applicationID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Update the certificate path to point to the example-app.pfx file which was created in previous section. - - -#### Device Code - -```Go -oauthClient := &http.Client{} - -// Acquire the device code -deviceCode, err := adal.InitiateDeviceAuth( - oauthClient, - oauthConfig, - applicationID, - resource) -if err != nil { - return nil, fmt.Errorf("Failed to start device auth flow: %s", err) -} - -// Display the authentication message -fmt.Println(*deviceCode.Message) - -// Wait here until the user is authenticated -token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) -if err != nil { - return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) -} - -spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - applicationID, - resource, - *token, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Username password authenticate - -```Go -spt, err := adal.NewServicePrincipalTokenFromUsernamePassword( - oauthConfig, - applicationID, - username, - password, - resource, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Authorization code authenticate - -``` Go -spt, err := adal.NewServicePrincipalTokenFromAuthorizationCode( - oauthConfig, - applicationID, - clientSecret, - authorizationCode, - redirectURI, - resource, - callbacks...) - -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -### Command Line Tool - -A command line tool is available in `cmd/adal.go` that can acquire a token for a given resource. It supports all flows mentioned above. - -``` -adal -h - -Usage of ./adal: - -applicationId string - application id - -certificatePath string - path to pk12/PFC application certificate - -mode string - authentication mode (device, secret, cert, refresh) (default "device") - -resource string - resource for which the token is requested - -secret string - application secret - -tenantId string - tenant id - -tokenCachePath string - location of oath token cache (default "/home/cgc/.adal/accessToken.json") -``` - -Example acquire a token for `https://management.core.windows.net/` using device code flow: - -``` -adal -mode device \ - -applicationId "APPLICATION_ID" \ - -tenantId "TENANT_ID" \ - -resource https://management.core.windows.net/ - -``` diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/cmd/adal.go b/vendor/github.com/Azure/go-autorest/autorest/adal/cmd/adal.go deleted file mode 100644 index 56b7d20d..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/cmd/adal.go +++ /dev/null @@ -1,298 +0,0 @@ -package main - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "flag" - "fmt" - "log" - "strings" - - "crypto/rsa" - "crypto/x509" - "io/ioutil" - "net/http" - "os/user" - - "github.com/Azure/go-autorest/autorest/adal" - "golang.org/x/crypto/pkcs12" -) - -const ( - deviceMode = "device" - clientSecretMode = "secret" - clientCertMode = "cert" - refreshMode = "refresh" - - activeDirectoryEndpoint = "https://login.microsoftonline.com/" -) - -type option struct { - name string - value string -} - -var ( - mode string - resource string - - tenantID string - applicationID string - - applicationSecret string - certificatePath string - - tokenCachePath string -) - -func checkMandatoryOptions(mode string, options ...option) { - for _, option := range options { - if strings.TrimSpace(option.value) == "" { - log.Fatalf("Authentication mode '%s' requires mandatory option '%s'.", mode, option.name) - } - } -} - -func defaultTokenCachePath() string { - usr, err := user.Current() - if err != nil { - log.Fatal(err) - } - defaultTokenPath := usr.HomeDir + "/.adal/accessToken.json" - return defaultTokenPath -} - -func init() { - flag.StringVar(&mode, "mode", "device", "authentication mode (device, secret, cert, refresh)") - flag.StringVar(&resource, "resource", "", "resource for which the token is requested") - flag.StringVar(&tenantID, "tenantId", "", "tenant id") - flag.StringVar(&applicationID, "applicationId", "", "application id") - flag.StringVar(&applicationSecret, "secret", "", "application secret") - flag.StringVar(&certificatePath, "certificatePath", "", "path to pk12/PFC application certificate") - flag.StringVar(&tokenCachePath, "tokenCachePath", defaultTokenCachePath(), "location of oath token cache") - - flag.Parse() - - switch mode = strings.TrimSpace(mode); mode { - case clientSecretMode: - checkMandatoryOptions(clientSecretMode, - option{name: "resource", value: resource}, - option{name: "tenantId", value: tenantID}, - option{name: "applicationId", value: applicationID}, - option{name: "secret", value: applicationSecret}, - ) - case clientCertMode: - checkMandatoryOptions(clientCertMode, - option{name: "resource", value: resource}, - option{name: "tenantId", value: tenantID}, - option{name: "applicationId", value: applicationID}, - option{name: "certificatePath", value: certificatePath}, - ) - case deviceMode: - checkMandatoryOptions(deviceMode, - option{name: "resource", value: resource}, - option{name: "tenantId", value: tenantID}, - option{name: "applicationId", value: applicationID}, - ) - case refreshMode: - checkMandatoryOptions(refreshMode, - option{name: "resource", value: resource}, - option{name: "tenantId", value: tenantID}, - option{name: "applicationId", value: applicationID}, - ) - default: - log.Fatalln("Authentication modes 'secret, 'cert', 'device' or 'refresh' are supported.") - } -} - -func acquireTokenClientSecretFlow(oauthConfig adal.OAuthConfig, - appliationID string, - applicationSecret string, - resource string, - callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - - spt, err := adal.NewServicePrincipalToken( - oauthConfig, - appliationID, - applicationSecret, - resource, - callbacks...) - if err != nil { - return nil, err - } - - return spt, spt.Refresh() -} - -func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { - privateKey, certificate, err := pkcs12.Decode(pkcs, password) - if err != nil { - return nil, nil, err - } - - rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey) - if !isRsaKey { - return nil, nil, fmt.Errorf("PKCS#12 certificate must contain an RSA private key") - } - - return certificate, rsaPrivateKey, nil -} - -func acquireTokenClientCertFlow(oauthConfig adal.OAuthConfig, - applicationID string, - applicationCertPath string, - resource string, - callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - - certData, err := ioutil.ReadFile(certificatePath) - if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) - } - - certificate, rsaPrivateKey, err := decodePkcs12(certData, "") - if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) - } - - spt, err := adal.NewServicePrincipalTokenFromCertificate( - oauthConfig, - applicationID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - if err != nil { - return nil, err - } - - return spt, spt.Refresh() -} - -func acquireTokenDeviceCodeFlow(oauthConfig adal.OAuthConfig, - applicationID string, - resource string, - callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - - oauthClient := &http.Client{} - deviceCode, err := adal.InitiateDeviceAuth( - oauthClient, - oauthConfig, - applicationID, - resource) - if err != nil { - return nil, fmt.Errorf("Failed to start device auth flow: %s", err) - } - - fmt.Println(*deviceCode.Message) - - token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) - if err != nil { - return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) - } - - spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - applicationID, - resource, - *token, - callbacks...) - return spt, err -} - -func refreshToken(oauthConfig adal.OAuthConfig, - applicationID string, - resource string, - tokenCachePath string, - callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - - token, err := adal.LoadToken(tokenCachePath) - if err != nil { - return nil, fmt.Errorf("failed to load token from cache: %v", err) - } - - spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - applicationID, - resource, - *token, - callbacks...) - if err != nil { - return nil, err - } - return spt, spt.Refresh() -} - -func saveToken(spt adal.Token) error { - if tokenCachePath != "" { - err := adal.SaveToken(tokenCachePath, 0600, spt) - if err != nil { - return err - } - log.Printf("Acquired token was saved in '%s' file\n", tokenCachePath) - return nil - - } - return fmt.Errorf("empty path for token cache") -} - -func main() { - oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) - if err != nil { - panic(err) - } - - callback := func(token adal.Token) error { - return saveToken(token) - } - - log.Printf("Authenticating with mode '%s'\n", mode) - switch mode { - case clientSecretMode: - _, err = acquireTokenClientSecretFlow( - *oauthConfig, - applicationID, - applicationSecret, - resource, - callback) - case clientCertMode: - _, err = acquireTokenClientCertFlow( - *oauthConfig, - applicationID, - certificatePath, - resource, - callback) - case deviceMode: - var spt *adal.ServicePrincipalToken - spt, err = acquireTokenDeviceCodeFlow( - *oauthConfig, - applicationID, - resource, - callback) - if err == nil { - err = saveToken(spt.Token) - } - case refreshMode: - _, err = refreshToken( - *oauthConfig, - applicationID, - resource, - tokenCachePath, - callback) - } - - if err != nil { - log.Fatalf("Failed to acquire a token for resource %s. Error: %v", resource, err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/config.go b/vendor/github.com/Azure/go-autorest/autorest/adal/config.go deleted file mode 100644 index f570d540..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/config.go +++ /dev/null @@ -1,81 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/url" -) - -const ( - activeDirectoryAPIVersion = "1.0" -) - -// OAuthConfig represents the endpoints needed -// in OAuth operations -type OAuthConfig struct { - AuthorityEndpoint url.URL - AuthorizeEndpoint url.URL - TokenEndpoint url.URL - DeviceCodeEndpoint url.URL -} - -// IsZero returns true if the OAuthConfig object is zero-initialized. -func (oac OAuthConfig) IsZero() bool { - return oac == OAuthConfig{} -} - -func validateStringParam(param, name string) error { - if len(param) == 0 { - return fmt.Errorf("parameter '" + name + "' cannot be empty") - } - return nil -} - -// NewOAuthConfig returns an OAuthConfig with tenant specific urls -func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) { - if err := validateStringParam(activeDirectoryEndpoint, "activeDirectoryEndpoint"); err != nil { - return nil, err - } - // it's legal for tenantID to be empty so don't validate it - const activeDirectoryEndpointTemplate = "%s/oauth2/%s?api-version=%s" - u, err := url.Parse(activeDirectoryEndpoint) - if err != nil { - return nil, err - } - authorityURL, err := u.Parse(tenantID) - if err != nil { - return nil, err - } - authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", activeDirectoryAPIVersion)) - if err != nil { - return nil, err - } - tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", activeDirectoryAPIVersion)) - if err != nil { - return nil, err - } - deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", activeDirectoryAPIVersion)) - if err != nil { - return nil, err - } - - return &OAuthConfig{ - AuthorityEndpoint: *authorityURL, - AuthorizeEndpoint: *authorizeURL, - TokenEndpoint: *tokenURL, - DeviceCodeEndpoint: *deviceCodeURL, - }, nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go deleted file mode 100644 index 304280f6..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/config_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "testing" -) - -func TestNewOAuthConfig(t *testing.T) { - const testActiveDirectoryEndpoint = "https://login.test.com" - const testTenantID = "tenant-id-test" - - config, err := NewOAuthConfig(testActiveDirectoryEndpoint, testTenantID) - if err != nil { - t.Fatalf("autorest/adal: Unexpected error while creating oauth configuration for tenant: %v.", err) - } - - expected := "https://login.test.com/tenant-id-test/oauth2/authorize?api-version=1.0" - if config.AuthorizeEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.AuthorizeEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/token?api-version=1.0" - if config.TokenEndpoint.String() != expected { - t.Fatalf("autorest/adal: Incorrect authorize url for Tenant from Environment. expected(%s). actual(%v).", expected, config.TokenEndpoint) - } - - expected = "https://login.test.com/tenant-id-test/oauth2/devicecode?api-version=1.0" - if config.DeviceCodeEndpoint.String() != expected { - t.Fatalf("autorest/adal Incorrect devicecode url for Tenant from Environment. expected(%s). actual(%v).", expected, config.DeviceCodeEndpoint) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go b/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go deleted file mode 100644 index b38f4c24..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go +++ /dev/null @@ -1,242 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/* - This file is largely based on rjw57/oauth2device's code, with the follow differences: - * scope -> resource, and only allow a single one - * receive "Message" in the DeviceCode struct and show it to users as the prompt - * azure-xplat-cli has the following behavior that this emulates: - - does not send client_secret during the token exchange - - sends resource again in the token exchange request -*/ - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" -) - -const ( - logPrefix = "autorest/adal/devicetoken:" -) - -var ( - // ErrDeviceGeneric represents an unknown error from the token endpoint when using device flow - ErrDeviceGeneric = fmt.Errorf("%s Error while retrieving OAuth token: Unknown Error", logPrefix) - - // ErrDeviceAccessDenied represents an access denied error from the token endpoint when using device flow - ErrDeviceAccessDenied = fmt.Errorf("%s Error while retrieving OAuth token: Access Denied", logPrefix) - - // ErrDeviceAuthorizationPending represents the server waiting on the user to complete the device flow - ErrDeviceAuthorizationPending = fmt.Errorf("%s Error while retrieving OAuth token: Authorization Pending", logPrefix) - - // ErrDeviceCodeExpired represents the server timing out and expiring the code during device flow - ErrDeviceCodeExpired = fmt.Errorf("%s Error while retrieving OAuth token: Code Expired", logPrefix) - - // ErrDeviceSlowDown represents the service telling us we're polling too often during device flow - ErrDeviceSlowDown = fmt.Errorf("%s Error while retrieving OAuth token: Slow Down", logPrefix) - - // ErrDeviceCodeEmpty represents an empty device code from the device endpoint while using device flow - ErrDeviceCodeEmpty = fmt.Errorf("%s Error while retrieving device code: Device Code Empty", logPrefix) - - // ErrOAuthTokenEmpty represents an empty OAuth token from the token endpoint when using device flow - ErrOAuthTokenEmpty = fmt.Errorf("%s Error while retrieving OAuth token: Token Empty", logPrefix) - - errCodeSendingFails = "Error occurred while sending request for Device Authorization Code" - errCodeHandlingFails = "Error occurred while handling response from the Device Endpoint" - errTokenSendingFails = "Error occurred while sending request with device code for a token" - errTokenHandlingFails = "Error occurred while handling response from the Token Endpoint (during device flow)" - errStatusNotOK = "Error HTTP status != 200" -) - -// DeviceCode is the object returned by the device auth endpoint -// It contains information to instruct the user to complete the auth flow -type DeviceCode struct { - DeviceCode *string `json:"device_code,omitempty"` - UserCode *string `json:"user_code,omitempty"` - VerificationURL *string `json:"verification_url,omitempty"` - ExpiresIn *int64 `json:"expires_in,string,omitempty"` - Interval *int64 `json:"interval,string,omitempty"` - - Message *string `json:"message"` // Azure specific - Resource string // store the following, stored when initiating, used when exchanging - OAuthConfig OAuthConfig - ClientID string -} - -// TokenError is the object returned by the token exchange endpoint -// when something is amiss -type TokenError struct { - Error *string `json:"error,omitempty"` - ErrorCodes []int `json:"error_codes,omitempty"` - ErrorDescription *string `json:"error_description,omitempty"` - Timestamp *string `json:"timestamp,omitempty"` - TraceID *string `json:"trace_id,omitempty"` -} - -// DeviceToken is the object return by the token exchange endpoint -// It can either look like a Token or an ErrorToken, so put both here -// and check for presence of "Error" to know if we are in error state -type deviceToken struct { - Token - TokenError -} - -// InitiateDeviceAuth initiates a device auth flow. It returns a DeviceCode -// that can be used with CheckForUserCompletion or WaitForUserCompletion. -func InitiateDeviceAuth(sender Sender, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) { - v := url.Values{ - "client_id": []string{clientID}, - "resource": []string{resource}, - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - - req, err := http.NewRequest(http.MethodPost, oauthConfig.DeviceCodeEndpoint.String(), body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error()) - } - - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - resp, err := sender.Do(req) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error()) - } - defer resp.Body.Close() - - rb, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error()) - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, errStatusNotOK) - } - - if len(strings.Trim(string(rb), " ")) == 0 { - return nil, ErrDeviceCodeEmpty - } - - var code DeviceCode - err = json.Unmarshal(rb, &code) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error()) - } - - code.ClientID = clientID - code.Resource = resource - code.OAuthConfig = oauthConfig - - return &code, nil -} - -// CheckForUserCompletion takes a DeviceCode and checks with the Azure AD OAuth endpoint -// to see if the device flow has: been completed, timed out, or otherwise failed -func CheckForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) { - v := url.Values{ - "client_id": []string{code.ClientID}, - "code": []string{*code.DeviceCode}, - "grant_type": []string{OAuthGrantTypeDeviceCode}, - "resource": []string{code.Resource}, - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - - req, err := http.NewRequest(http.MethodPost, code.OAuthConfig.TokenEndpoint.String(), body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error()) - } - - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - resp, err := sender.Do(req) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error()) - } - defer resp.Body.Close() - - rb, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error()) - } - - if resp.StatusCode != http.StatusOK && len(strings.Trim(string(rb), " ")) == 0 { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, errStatusNotOK) - } - if len(strings.Trim(string(rb), " ")) == 0 { - return nil, ErrOAuthTokenEmpty - } - - var token deviceToken - err = json.Unmarshal(rb, &token) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error()) - } - - if token.Error == nil { - return &token.Token, nil - } - - switch *token.Error { - case "authorization_pending": - return nil, ErrDeviceAuthorizationPending - case "slow_down": - return nil, ErrDeviceSlowDown - case "access_denied": - return nil, ErrDeviceAccessDenied - case "code_expired": - return nil, ErrDeviceCodeExpired - default: - return nil, ErrDeviceGeneric - } -} - -// WaitForUserCompletion calls CheckForUserCompletion repeatedly until a token is granted or an error state occurs. -// This prevents the user from looping and checking against 'ErrDeviceAuthorizationPending'. -func WaitForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) { - intervalDuration := time.Duration(*code.Interval) * time.Second - waitDuration := intervalDuration - - for { - token, err := CheckForUserCompletion(sender, code) - - if err == nil { - return token, nil - } - - switch err { - case ErrDeviceSlowDown: - waitDuration += waitDuration - case ErrDeviceAuthorizationPending: - // noop - default: // everything else is "fatal" to us - return nil, err - } - - if waitDuration > (intervalDuration * 3) { - return nil, fmt.Errorf("%s Error waiting for user to complete device flow. Server told us to slow_down too much", logPrefix) - } - - time.Sleep(waitDuration) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go deleted file mode 100644 index 6beee161..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken_test.go +++ /dev/null @@ -1,330 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - TestResource = "SomeResource" - TestClientID = "SomeClientID" - TestTenantID = "SomeTenantID" - TestActiveDirectoryEndpoint = "https://login.test.com/" -) - -var ( - testOAuthConfig, _ = NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - TestOAuthConfig = *testOAuthConfig -) - -const MockDeviceCodeResponse = ` -{ - "device_code": "10000-40-1234567890", - "user_code": "ABCDEF", - "verification_url": "http://aka.ms/deviceauth", - "expires_in": "900", - "interval": "0" -} -` - -const MockDeviceTokenResponse = `{ - "access_token": "accessToken", - "refresh_token": "refreshToken", - "expires_in": "1000", - "expires_on": "2000", - "not_before": "3000", - "resource": "resource", - "token_type": "type" -} -` - -func TestDeviceCodeIncludesResource(t *testing.T) { - sender := mocks.NewSender() - sender.AppendResponse(mocks.NewResponseWithContent(MockDeviceCodeResponse)) - - code, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err != nil { - t.Fatalf("adal: unexpected error initiating device auth") - } - - if code.Resource != TestResource { - t.Fatalf("adal: InitiateDeviceAuth failed to stash the resource in the DeviceCode struct") - } -} - -func TestDeviceCodeReturnsErrorIfSendingFails(t *testing.T) { - sender := mocks.NewSender() - sender.SetError(fmt.Errorf("this is an error")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeSendingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeSendingFails, err.Error()) - } -} - -func TestDeviceCodeReturnsErrorIfBadRequest(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("doesn't matter") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceCodeReturnsErrorIfCannotDeserializeDeviceCode(t *testing.T) { - gibberishJSON := strings.Replace(MockDeviceCodeResponse, "expires_in", "\":, :gibberish", -1) - sender := mocks.NewSender() - body := mocks.NewBody(gibberishJSON) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err == nil || !strings.Contains(err.Error(), errCodeHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errCodeHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceCodeReturnsErrorIfEmptyDeviceCode(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := InitiateDeviceAuth(sender, TestOAuthConfig, TestClientID, TestResource) - if err != ErrDeviceCodeEmpty { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", ErrDeviceCodeEmpty, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func deviceCode() *DeviceCode { - var deviceCode DeviceCode - _ = json.Unmarshal([]byte(MockDeviceCodeResponse), &deviceCode) - deviceCode.Resource = TestResource - deviceCode.ClientID = TestClientID - return &deviceCode -} - -func TestDeviceTokenReturns(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(MockDeviceTokenResponse) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("adal: got error unexpectedly") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfSendingFails(t *testing.T) { - sender := mocks.NewSender() - sender.SetError(fmt.Errorf("this is an error")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenSendingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenSendingFails, err.Error()) - } -} - -func TestDeviceTokenReturnsErrorIfServerError(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusInternalServerError, "Internal Server Error")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfCannotDeserializeDeviceToken(t *testing.T) { - gibberishJSON := strings.Replace(MockDeviceTokenResponse, "expires_in", ";:\"gibberish", -1) - sender := mocks.NewSender() - body := mocks.NewBody(gibberishJSON) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil || !strings.Contains(err.Error(), errTokenHandlingFails) { - t.Fatalf("adal: failed to get correct error expected(%s) actual(%s)", errTokenHandlingFails, err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func errorDeviceTokenResponse(message string) string { - return `{ "error": "` + message + `" }` -} - -func TestDeviceTokenReturnsErrorIfAuthorizationPending(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("authorization_pending")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := CheckForUserCompletion(sender, deviceCode()) - if err != ErrDeviceAuthorizationPending { - t.Fatalf("!!!") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfSlowDown(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("slow_down")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := CheckForUserCompletion(sender, deviceCode()) - if err != ErrDeviceSlowDown { - t.Fatalf("!!!") - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -type deviceTokenSender struct { - errorString string - attempts int -} - -func newDeviceTokenSender(deviceErrorString string) *deviceTokenSender { - return &deviceTokenSender{errorString: deviceErrorString, attempts: 0} -} - -func (s *deviceTokenSender) Do(req *http.Request) (*http.Response, error) { - var resp *http.Response - if s.attempts < 1 { - s.attempts++ - resp = mocks.NewResponseWithContent(errorDeviceTokenResponse(s.errorString)) - } else { - resp = mocks.NewResponseWithContent(MockDeviceTokenResponse) - } - return resp, nil -} - -// since the above only exercise CheckForUserCompletion, we repeat the test here, -// but with the intent of showing that WaitForUserCompletion loops properly. -func TestDeviceTokenSucceedsWithIntermediateAuthPending(t *testing.T) { - sender := newDeviceTokenSender("authorization_pending") - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("unexpected error occurred") - } -} - -// same as above but with SlowDown now -func TestDeviceTokenSucceedsWithIntermediateSlowDown(t *testing.T) { - sender := newDeviceTokenSender("slow_down") - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != nil { - t.Fatalf("unexpected error occurred") - } -} - -func TestDeviceTokenReturnsErrorIfAccessDenied(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("access_denied")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrDeviceAccessDenied { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceAccessDenied.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfCodeExpired(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("code_expired")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrDeviceCodeExpired { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceCodeExpired.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorForUnknownError(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody(errorDeviceTokenResponse("unknown_error")) - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusBadRequest, "Bad Request")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err == nil { - t.Fatalf("failed to get error") - } - if err != ErrDeviceGeneric { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrDeviceGeneric.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} - -func TestDeviceTokenReturnsErrorIfTokenEmptyAndStatusOK(t *testing.T) { - sender := mocks.NewSender() - body := mocks.NewBody("") - sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK")) - - _, err := WaitForUserCompletion(sender, deviceCode()) - if err != ErrOAuthTokenEmpty { - t.Fatalf("adal: got wrong error expected(%s) actual(%s)", ErrOAuthTokenEmpty.Error(), err.Error()) - } - - if body.IsOpen() { - t.Fatalf("response body was left open!") - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/msi.go b/vendor/github.com/Azure/go-autorest/autorest/adal/msi.go deleted file mode 100644 index 5e02d52a..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/msi.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !windows - -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// msiPath is the path to the MSI Extension settings file (to discover the endpoint) -var msiPath = "/var/lib/waagent/ManagedIdentity-Settings" diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/msi_windows.go b/vendor/github.com/Azure/go-autorest/autorest/adal/msi_windows.go deleted file mode 100644 index 261b5688..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/msi_windows.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build windows - -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "os" - "strings" -) - -// msiPath is the path to the MSI Extension settings file (to discover the endpoint) -var msiPath = strings.Join([]string{os.Getenv("SystemDrive"), "WindowsAzure/Config/ManagedIdentity-Settings"}, "/") diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go b/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go deleted file mode 100644 index 9e15f275..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go +++ /dev/null @@ -1,73 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" -) - -// LoadToken restores a Token object from a file located at 'path'. -func LoadToken(path string) (*Token, error) { - file, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("failed to open file (%s) while loading token: %v", path, err) - } - defer file.Close() - - var token Token - - dec := json.NewDecoder(file) - if err = dec.Decode(&token); err != nil { - return nil, fmt.Errorf("failed to decode contents of file (%s) into Token representation: %v", path, err) - } - return &token, nil -} - -// SaveToken persists an oauth token at the given location on disk. -// It moves the new file into place so it can safely be used to replace an existing file -// that maybe accessed by multiple processes. -func SaveToken(path string, mode os.FileMode, token Token) error { - dir := filepath.Dir(path) - err := os.MkdirAll(dir, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to create directory (%s) to store token in: %v", dir, err) - } - - newFile, err := ioutil.TempFile(dir, "token") - if err != nil { - return fmt.Errorf("failed to create the temp file to write the token: %v", err) - } - tempPath := newFile.Name() - - if err := json.NewEncoder(newFile).Encode(token); err != nil { - return fmt.Errorf("failed to encode token to file (%s) while saving token: %v", tempPath, err) - } - if err := newFile.Close(); err != nil { - return fmt.Errorf("failed to close temp file %s: %v", tempPath, err) - } - - // Atomic replace to avoid multi-writer file corruptions - if err := os.Rename(tempPath, path); err != nil { - return fmt.Errorf("failed to move temporary token to desired output location. src=%s dst=%s: %v", tempPath, path, err) - } - if err := os.Chmod(path, mode); err != nil { - return fmt.Errorf("failed to chmod the token file %s: %v", path, err) - } - return nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go deleted file mode 100644 index a9c287c6..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/persist_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "io/ioutil" - "os" - "path" - "reflect" - "runtime" - "strings" - "testing" -) - -const MockTokenJSON string = `{ - "access_token": "accessToken", - "refresh_token": "refreshToken", - "expires_in": "1000", - "expires_on": "2000", - "not_before": "3000", - "resource": "resource", - "token_type": "type" -}` - -var TestToken = Token{ - AccessToken: "accessToken", - RefreshToken: "refreshToken", - ExpiresIn: "1000", - ExpiresOn: "2000", - NotBefore: "3000", - Resource: "resource", - Type: "type", -} - -func writeTestTokenFile(t *testing.T, suffix string, contents string) *os.File { - f, err := ioutil.TempFile(os.TempDir(), suffix) - if err != nil { - t.Fatalf("azure: unexpected error when creating temp file: %v", err) - } - defer f.Close() - - _, err = f.Write([]byte(contents)) - if err != nil { - t.Fatalf("azure: unexpected error when writing temp test file: %v", err) - } - - return f -} - -func TestLoadToken(t *testing.T) { - f := writeTestTokenFile(t, "testloadtoken", MockTokenJSON) - defer os.Remove(f.Name()) - - expectedToken := TestToken - actualToken, err := LoadToken(f.Name()) - if err != nil { - t.Fatalf("azure: unexpected error loading token from file: %v", err) - } - - if *actualToken != expectedToken { - t.Fatalf("azure: failed to decode properly expected(%v) actual(%v)", expectedToken, *actualToken) - } - - // test that LoadToken closes the file properly - err = SaveToken(f.Name(), 0600, *actualToken) - if err != nil { - t.Fatalf("azure: could not save token after LoadToken: %v", err) - } -} - -func TestLoadTokenFailsBadPath(t *testing.T) { - _, err := LoadToken("/tmp/this_file_should_never_exist_really") - expectedSubstring := "failed to open file" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%s)", expectedSubstring, err.Error()) - } -} - -func TestLoadTokenFailsBadJson(t *testing.T) { - gibberishJSON := strings.Replace(MockTokenJSON, "expires_on", ";:\"gibberish", -1) - f := writeTestTokenFile(t, "testloadtokenfailsbadjson", gibberishJSON) - defer os.Remove(f.Name()) - - _, err := LoadToken(f.Name()) - expectedSubstring := "failed to decode contents of file" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%s)", expectedSubstring, err.Error()) - } -} - -func token() *Token { - var token Token - json.Unmarshal([]byte(MockTokenJSON), &token) - return &token -} - -func TestSaveToken(t *testing.T) { - f, err := ioutil.TempFile("", "testloadtoken") - if err != nil { - t.Fatalf("azure: unexpected error when creating temp file: %v", err) - } - defer os.Remove(f.Name()) - f.Close() - - mode := os.ModePerm & 0642 - err = SaveToken(f.Name(), mode, *token()) - if err != nil { - t.Fatalf("azure: unexpected error saving token to file: %v", err) - } - fi, err := os.Stat(f.Name()) // open a new stat as held ones are not fresh - if err != nil { - t.Fatalf("azure: stat failed: %v", err) - } - if runtime.GOOS != "windows" { // permissions don't work on Windows - if perm := fi.Mode().Perm(); perm != mode { - t.Fatalf("azure: wrong file perm. got:%s; expected:%s file :%s", perm, mode, f.Name()) - } - } - - var actualToken Token - var expectedToken Token - - json.Unmarshal([]byte(MockTokenJSON), expectedToken) - - contents, err := ioutil.ReadFile(f.Name()) - if err != nil { - t.Fatal("!!") - } - json.Unmarshal(contents, actualToken) - - if !reflect.DeepEqual(actualToken, expectedToken) { - t.Fatal("azure: token was not serialized correctly") - } -} - -func TestSaveTokenFailsNoPermission(t *testing.T) { - pathWhereWeShouldntHavePermission := "/usr/thiswontwork/atall" - if runtime.GOOS == "windows" { - pathWhereWeShouldntHavePermission = path.Join(os.Getenv("windir"), "system32\\mytokendir\\mytoken") - } - err := SaveToken(pathWhereWeShouldntHavePermission, 0644, *token()) - expectedSubstring := "failed to create directory" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%v)", expectedSubstring, err) - } -} - -func TestSaveTokenFailsCantCreate(t *testing.T) { - tokenPath := "/thiswontwork" - if runtime.GOOS == "windows" { - tokenPath = path.Join(os.Getenv("windir"), "system32") - } - err := SaveToken(tokenPath, 0644, *token()) - expectedSubstring := "failed to create the temp file to write the token" - if err == nil || !strings.Contains(err.Error(), expectedSubstring) { - t.Fatalf("azure: failed to get correct error expected(%s) actual(%v)", expectedSubstring, err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go b/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go deleted file mode 100644 index 0e5ad14d..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go +++ /dev/null @@ -1,60 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "net/http" -) - -const ( - contentType = "Content-Type" - mimeTypeFormPost = "application/x-www-form-urlencoded" -) - -// Sender is the interface that wraps the Do method to send HTTP requests. -// -// The standard http.Client conforms to this interface. -type Sender interface { - Do(*http.Request) (*http.Response, error) -} - -// SenderFunc is a method that implements the Sender interface. -type SenderFunc func(*http.Request) (*http.Response, error) - -// Do implements the Sender interface on SenderFunc. -func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) { - return sf(r) -} - -// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then react to the -// http.Response result. -type SendDecorator func(Sender) Sender - -// CreateSender creates, decorates, and returns, as a Sender, the default http.Client. -func CreateSender(decorators ...SendDecorator) Sender { - return DecorateSender(&http.Client{}, decorators...) -} - -// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to -// the Sender. Decorators are applied in the order received, but their affect upon the request -// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a -// post-decorator (pass the http.Request along and react to the results in http.Response). -func DecorateSender(s Sender, decorators ...SendDecorator) Sender { - for _, decorate := range decorators { - s = decorate(s) - } - return s -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token.go deleted file mode 100644 index 941af281..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go +++ /dev/null @@ -1,662 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "crypto/x509" - "encoding/base64" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - "time" - - "github.com/Azure/go-autorest/autorest/date" - "github.com/dgrijalva/jwt-go" -) - -const ( - defaultRefresh = 5 * time.Minute - - // OAuthGrantTypeDeviceCode is the "grant_type" identifier used in device flow - OAuthGrantTypeDeviceCode = "device_code" - - // OAuthGrantTypeClientCredentials is the "grant_type" identifier used in credential flows - OAuthGrantTypeClientCredentials = "client_credentials" - - // OAuthGrantTypeUserPass is the "grant_type" identifier used in username and password auth flows - OAuthGrantTypeUserPass = "password" - - // OAuthGrantTypeRefreshToken is the "grant_type" identifier used in refresh token flows - OAuthGrantTypeRefreshToken = "refresh_token" - - // OAuthGrantTypeAuthorizationCode is the "grant_type" identifier used in authorization code flows - OAuthGrantTypeAuthorizationCode = "authorization_code" - - // metadataHeader is the header required by MSI extension - metadataHeader = "Metadata" -) - -// OAuthTokenProvider is an interface which should be implemented by an access token retriever -type OAuthTokenProvider interface { - OAuthToken() string -} - -// TokenRefreshError is an interface used by errors returned during token refresh. -type TokenRefreshError interface { - error - Response() *http.Response -} - -// Refresher is an interface for token refresh functionality -type Refresher interface { - Refresh() error - RefreshExchange(resource string) error - EnsureFresh() error -} - -// TokenRefreshCallback is the type representing callbacks that will be called after -// a successful token refresh -type TokenRefreshCallback func(Token) error - -// Token encapsulates the access token used to authorize Azure requests. -type Token struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - - ExpiresIn string `json:"expires_in"` - ExpiresOn string `json:"expires_on"` - NotBefore string `json:"not_before"` - - Resource string `json:"resource"` - Type string `json:"token_type"` -} - -// IsZero returns true if the token object is zero-initialized. -func (t Token) IsZero() bool { - return t == Token{} -} - -// Expires returns the time.Time when the Token expires. -func (t Token) Expires() time.Time { - s, err := strconv.Atoi(t.ExpiresOn) - if err != nil { - s = -3600 - } - - expiration := date.NewUnixTimeFromSeconds(float64(s)) - - return time.Time(expiration).UTC() -} - -// IsExpired returns true if the Token is expired, false otherwise. -func (t Token) IsExpired() bool { - return t.WillExpireIn(0) -} - -// WillExpireIn returns true if the Token will expire after the passed time.Duration interval -// from now, false otherwise. -func (t Token) WillExpireIn(d time.Duration) bool { - return !t.Expires().After(time.Now().Add(d)) -} - -//OAuthToken return the current access token -func (t *Token) OAuthToken() string { - return t.AccessToken -} - -// ServicePrincipalNoSecret represents a secret type that contains no secret -// meaning it is not valid for fetching a fresh token. This is used by Manual -type ServicePrincipalNoSecret struct { -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret -// It only returns an error for the ServicePrincipalNoSecret type -func (noSecret *ServicePrincipalNoSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token") -} - -// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form -// that is submitted when acquiring an oAuth token. -type ServicePrincipalSecret interface { - SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error -} - -// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization. -type ServicePrincipalTokenSecret struct { - ClientSecret string -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -// It will populate the form submitted during oAuth Token Acquisition using the client_secret. -func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("client_secret", tokenSecret.ClientSecret) - return nil -} - -// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs. -type ServicePrincipalCertificateSecret struct { - Certificate *x509.Certificate - PrivateKey *rsa.PrivateKey -} - -// ServicePrincipalMSISecret implements ServicePrincipalSecret for machines running the MSI Extension. -type ServicePrincipalMSISecret struct { -} - -// ServicePrincipalUsernamePasswordSecret implements ServicePrincipalSecret for username and password auth. -type ServicePrincipalUsernamePasswordSecret struct { - Username string - Password string -} - -// ServicePrincipalAuthorizationCodeSecret implements ServicePrincipalSecret for authorization code auth. -type ServicePrincipalAuthorizationCodeSecret struct { - ClientSecret string - AuthorizationCode string - RedirectURI string -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (secret *ServicePrincipalAuthorizationCodeSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("code", secret.AuthorizationCode) - v.Set("client_secret", secret.ClientSecret) - v.Set("redirect_uri", secret.RedirectURI) - return nil -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (secret *ServicePrincipalUsernamePasswordSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("username", secret.Username) - v.Set("password", secret.Password) - return nil -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (msiSecret *ServicePrincipalMSISecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - return nil -} - -// SignJwt returns the JWT signed with the certificate's private key. -func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) { - hasher := sha1.New() - _, err := hasher.Write(secret.Certificate.Raw) - if err != nil { - return "", err - } - - thumbprint := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) - - // The jti (JWT ID) claim provides a unique identifier for the JWT. - jti := make([]byte, 20) - _, err = rand.Read(jti) - if err != nil { - return "", err - } - - token := jwt.New(jwt.SigningMethodRS256) - token.Header["x5t"] = thumbprint - token.Claims = jwt.MapClaims{ - "aud": spt.oauthConfig.TokenEndpoint.String(), - "iss": spt.clientID, - "sub": spt.clientID, - "jti": base64.URLEncoding.EncodeToString(jti), - "nbf": time.Now().Unix(), - "exp": time.Now().Add(time.Hour * 24).Unix(), - } - - signedString, err := token.SignedString(secret.PrivateKey) - return signedString, err -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -// It will populate the form submitted during oAuth Token Acquisition using a JWT signed with a certificate. -func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - jwt, err := secret.SignJwt(spt) - if err != nil { - return err - } - - v.Set("client_assertion", jwt) - v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - return nil -} - -// ServicePrincipalToken encapsulates a Token created for a Service Principal. -type ServicePrincipalToken struct { - Token - - secret ServicePrincipalSecret - oauthConfig OAuthConfig - clientID string - resource string - autoRefresh bool - autoRefreshLock *sync.Mutex - refreshWithin time.Duration - sender Sender - - refreshCallbacks []TokenRefreshCallback -} - -func validateOAuthConfig(oac OAuthConfig) error { - if oac.IsZero() { - return fmt.Errorf("parameter 'oauthConfig' cannot be zero-initialized") - } - return nil -} - -// NewServicePrincipalTokenWithSecret create a ServicePrincipalToken using the supplied ServicePrincipalSecret implementation. -func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, resource string, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(id, "id"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if secret == nil { - return nil, fmt.Errorf("parameter 'secret' cannot be nil") - } - spt := &ServicePrincipalToken{ - oauthConfig: oauthConfig, - secret: secret, - clientID: id, - resource: resource, - autoRefresh: true, - autoRefreshLock: &sync.Mutex{}, - refreshWithin: defaultRefresh, - sender: &http.Client{}, - refreshCallbacks: callbacks, - } - return spt, nil -} - -// NewServicePrincipalTokenFromManualToken creates a ServicePrincipalToken using the supplied token -func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID string, resource string, token Token, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if token.IsZero() { - return nil, fmt.Errorf("parameter 'token' cannot be zero-initialized") - } - spt, err := NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalNoSecret{}, - callbacks...) - if err != nil { - return nil, err - } - - spt.Token = token - - return spt, nil -} - -// NewServicePrincipalToken creates a ServicePrincipalToken from the supplied Service Principal -// credentials scoped to the named resource. -func NewServicePrincipalToken(oauthConfig OAuthConfig, clientID string, secret string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(secret, "secret"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalTokenSecret{ - ClientSecret: secret, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromCertificate creates a ServicePrincipalToken from the supplied pkcs12 bytes. -func NewServicePrincipalTokenFromCertificate(oauthConfig OAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if certificate == nil { - return nil, fmt.Errorf("parameter 'certificate' cannot be nil") - } - if privateKey == nil { - return nil, fmt.Errorf("parameter 'privateKey' cannot be nil") - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalCertificateSecret{ - PrivateKey: privateKey, - Certificate: certificate, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromUsernamePassword creates a ServicePrincipalToken from the username and password. -func NewServicePrincipalTokenFromUsernamePassword(oauthConfig OAuthConfig, clientID string, username string, password string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(username, "username"); err != nil { - return nil, err - } - if err := validateStringParam(password, "password"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalUsernamePasswordSecret{ - Username: username, - Password: password, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromAuthorizationCode creates a ServicePrincipalToken from the -func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clientID string, clientSecret string, authorizationCode string, redirectURI string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(clientSecret, "clientSecret"); err != nil { - return nil, err - } - if err := validateStringParam(authorizationCode, "authorizationCode"); err != nil { - return nil, err - } - if err := validateStringParam(redirectURI, "redirectURI"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalAuthorizationCodeSecret{ - ClientSecret: clientSecret, - AuthorizationCode: authorizationCode, - RedirectURI: redirectURI, - }, - callbacks..., - ) -} - -// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines. -func GetMSIVMEndpoint() (string, error) { - return getMSIVMEndpoint(msiPath) -} - -func getMSIVMEndpoint(path string) (string, error) { - // Read MSI settings - bytes, err := ioutil.ReadFile(path) - if err != nil { - return "", err - } - msiSettings := struct { - URL string `json:"url"` - }{} - err = json.Unmarshal(bytes, &msiSettings) - if err != nil { - return "", err - } - - return msiSettings.URL, nil -} - -// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension. -// It will use the system assigned identity when creating the token. -func NewServicePrincipalTokenFromMSI(msiEndpoint, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - return newServicePrincipalTokenFromMSI(msiEndpoint, resource, nil, callbacks...) -} - -// NewServicePrincipalTokenFromMSIWithUserAssignedID creates a ServicePrincipalToken via the MSI VM Extension. -// It will use the specified user assigned identity when creating the token. -func NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint, resource string, userAssignedID string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - return newServicePrincipalTokenFromMSI(msiEndpoint, resource, &userAssignedID, callbacks...) -} - -func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedID *string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateStringParam(msiEndpoint, "msiEndpoint"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if userAssignedID != nil { - if err := validateStringParam(*userAssignedID, "userAssignedID"); err != nil { - return nil, err - } - } - // We set the oauth config token endpoint to be MSI's endpoint - msiEndpointURL, err := url.Parse(msiEndpoint) - if err != nil { - return nil, err - } - - oauthConfig, err := NewOAuthConfig(msiEndpointURL.String(), "") - if err != nil { - return nil, err - } - - spt := &ServicePrincipalToken{ - oauthConfig: *oauthConfig, - secret: &ServicePrincipalMSISecret{}, - resource: resource, - autoRefresh: true, - autoRefreshLock: &sync.Mutex{}, - refreshWithin: defaultRefresh, - sender: &http.Client{}, - refreshCallbacks: callbacks, - } - - if userAssignedID != nil { - spt.clientID = *userAssignedID - } - - return spt, nil -} - -// internal type that implements TokenRefreshError -type tokenRefreshError struct { - message string - resp *http.Response -} - -// Error implements the error interface which is part of the TokenRefreshError interface. -func (tre tokenRefreshError) Error() string { - return tre.message -} - -// Response implements the TokenRefreshError interface, it returns the raw HTTP response from the refresh operation. -func (tre tokenRefreshError) Response() *http.Response { - return tre.resp -} - -func newTokenRefreshError(message string, resp *http.Response) TokenRefreshError { - return tokenRefreshError{message: message, resp: resp} -} - -// EnsureFresh will refresh the token if it will expire within the refresh window (as set by -// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use. -func (spt *ServicePrincipalToken) EnsureFresh() error { - if spt.autoRefresh && spt.WillExpireIn(spt.refreshWithin) { - // take the lock then check to see if the token was already refreshed - spt.autoRefreshLock.Lock() - defer spt.autoRefreshLock.Unlock() - if spt.WillExpireIn(spt.refreshWithin) { - return spt.Refresh() - } - } - return nil -} - -// InvokeRefreshCallbacks calls any TokenRefreshCallbacks that were added to the SPT during initialization -func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error { - if spt.refreshCallbacks != nil { - for _, callback := range spt.refreshCallbacks { - err := callback(spt.Token) - if err != nil { - return fmt.Errorf("adal: TokenRefreshCallback handler failed. Error = '%v'", err) - } - } - } - return nil -} - -// Refresh obtains a fresh token for the Service Principal. -// This method is not safe for concurrent use and should be syncrhonized. -func (spt *ServicePrincipalToken) Refresh() error { - return spt.refreshInternal(spt.resource) -} - -// RefreshExchange refreshes the token, but for a different resource. -// This method is not safe for concurrent use and should be syncrhonized. -func (spt *ServicePrincipalToken) RefreshExchange(resource string) error { - return spt.refreshInternal(resource) -} - -func (spt *ServicePrincipalToken) getGrantType() string { - switch spt.secret.(type) { - case *ServicePrincipalUsernamePasswordSecret: - return OAuthGrantTypeUserPass - case *ServicePrincipalAuthorizationCodeSecret: - return OAuthGrantTypeAuthorizationCode - default: - return OAuthGrantTypeClientCredentials - } -} - -func (spt *ServicePrincipalToken) refreshInternal(resource string) error { - v := url.Values{} - v.Set("client_id", spt.clientID) - v.Set("resource", resource) - - if spt.RefreshToken != "" { - v.Set("grant_type", OAuthGrantTypeRefreshToken) - v.Set("refresh_token", spt.RefreshToken) - } else { - v.Set("grant_type", spt.getGrantType()) - err := spt.secret.SetAuthenticationValues(spt, &v) - if err != nil { - return err - } - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - req, err := http.NewRequest(http.MethodPost, spt.oauthConfig.TokenEndpoint.String(), body) - if err != nil { - return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err) - } - - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - if _, ok := spt.secret.(*ServicePrincipalMSISecret); ok { - req.Header.Set(metadataHeader, "true") - } - resp, err := spt.sender.Do(req) - if err != nil { - return fmt.Errorf("adal: Failed to execute the refresh request. Error = '%v'", err) - } - - defer resp.Body.Close() - rb, err := ioutil.ReadAll(resp.Body) - - if resp.StatusCode != http.StatusOK { - if err != nil { - return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body", resp.StatusCode), resp) - } - return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s", resp.StatusCode, string(rb)), resp) - } - - if err != nil { - return fmt.Errorf("adal: Failed to read a new service principal token during refresh. Error = '%v'", err) - } - if len(strings.Trim(string(rb), " ")) == 0 { - return fmt.Errorf("adal: Empty service principal token received during refresh") - } - var token Token - err = json.Unmarshal(rb, &token) - if err != nil { - return fmt.Errorf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb)) - } - - spt.Token = token - - return spt.InvokeRefreshCallbacks(token) -} - -// SetAutoRefresh enables or disables automatic refreshing of stale tokens. -func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) { - spt.autoRefresh = autoRefresh -} - -// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will -// refresh the token. -func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) { - spt.refreshWithin = d - return -} - -// SetSender sets the http.Client used when obtaining the Service Principal token. An -// undecorated http.Client is used by default. -func (spt *ServicePrincipalToken) SetSender(s Sender) { spt.sender = s } diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go deleted file mode 100644 index 56a3c3b5..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_test.go +++ /dev/null @@ -1,725 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "fmt" - "io/ioutil" - "math/big" - "net/http" - "net/url" - "os" - "reflect" - "strconv" - "strings" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/date" - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - defaultFormData = "client_id=id&client_secret=secret&grant_type=client_credentials&resource=resource" - defaultManualFormData = "client_id=id&grant_type=refresh_token&refresh_token=refreshtoken&resource=resource" -) - -func TestTokenExpires(t *testing.T) { - tt := time.Now().Add(5 * time.Second) - tk := newTokenExpiresAt(tt) - - if tk.Expires().Equal(tt) { - t.Fatalf("adal: Token#Expires miscalculated expiration time -- received %v, expected %v", tk.Expires(), tt) - } -} - -func TestTokenIsExpired(t *testing.T) { - tk := newTokenExpiresAt(time.Now().Add(-5 * time.Second)) - - if !tk.IsExpired() { - t.Fatalf("adal: Token#IsExpired failed to mark a stale token as expired -- now %v, token expires at %v", - time.Now().UTC(), tk.Expires()) - } -} - -func TestTokenIsExpiredUninitialized(t *testing.T) { - tk := &Token{} - - if !tk.IsExpired() { - t.Fatalf("adal: An uninitialized Token failed to mark itself as expired (expiration time %v)", tk.Expires()) - } -} - -func TestTokenIsNoExpired(t *testing.T) { - tk := newTokenExpiresAt(time.Now().Add(1000 * time.Second)) - - if tk.IsExpired() { - t.Fatalf("adal: Token marked a fresh token as expired -- now %v, token expires at %v", time.Now().UTC(), tk.Expires()) - } -} - -func TestTokenWillExpireIn(t *testing.T) { - d := 5 * time.Second - tk := newTokenExpiresIn(d) - - if !tk.WillExpireIn(d) { - t.Fatal("adal: Token#WillExpireIn mismeasured expiration time") - } -} - -func TestServicePrincipalTokenSetAutoRefresh(t *testing.T) { - spt := newServicePrincipalToken() - - if !spt.autoRefresh { - t.Fatal("adal: ServicePrincipalToken did not default to automatic token refreshing") - } - - spt.SetAutoRefresh(false) - if spt.autoRefresh { - t.Fatal("adal: ServicePrincipalToken#SetAutoRefresh did not disable automatic token refreshing") - } -} - -func TestServicePrincipalTokenSetRefreshWithin(t *testing.T) { - spt := newServicePrincipalToken() - - if spt.refreshWithin != defaultRefresh { - t.Fatal("adal: ServicePrincipalToken did not correctly set the default refresh interval") - } - - spt.SetRefreshWithin(2 * defaultRefresh) - if spt.refreshWithin != 2*defaultRefresh { - t.Fatal("adal: ServicePrincipalToken#SetRefreshWithin did not set the refresh interval") - } -} - -func TestServicePrincipalTokenSetSender(t *testing.T) { - spt := newServicePrincipalToken() - - c := &http.Client{} - spt.SetSender(c) - if !reflect.DeepEqual(c, spt.sender) { - t.Fatal("adal: ServicePrincipalToken#SetSender did not set the sender") - } -} - -func TestServicePrincipalTokenRefreshUsesPOST(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Method != "POST" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set HTTP method -- expected %v, received %v", "POST", r.Method) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - - if body.IsOpen() { - t.Fatalf("the response was not closed!") - } -} - -func TestServicePrincipalTokenFromMSIRefreshUsesPOST(t *testing.T) { - resource := "https://resource" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSI("http://msiendpoint/", resource, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Method != "POST" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set HTTP method -- expected %v, received %v", "POST", r.Method) - } - if h := r.Header.Get("Metadata"); h != "true" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set Metadata header for MSI") - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err = spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - - if body.IsOpen() { - t.Fatalf("the response was not closed!") - } -} - -func TestServicePrincipalTokenRefreshSetsMimeType(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.Header.Get(http.CanonicalHeaderKey("Content-Type")) != "application/x-www-form-urlencoded" { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set Content-Type -- expected %v, received %v", - "application/x-form-urlencoded", - r.Header.Get(http.CanonicalHeaderKey("Content-Type"))) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func TestServicePrincipalTokenRefreshSetsURL(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if r.URL.String() != TestOAuthConfig.TokenEndpoint.String() { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the URL -- expected %v, received %v", - TestOAuthConfig.TokenEndpoint, r.URL) - } - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func testServicePrincipalTokenRefreshSetsBody(t *testing.T, spt *ServicePrincipalToken, f func(*testing.T, []byte)) { - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("adal: Failed to read body of Service Principal token request (%v)", err) - } - f(t, b) - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } -} - -func TestServicePrincipalTokenManualRefreshSetsBody(t *testing.T) { - sptManual := newServicePrincipalTokenManual() - testServicePrincipalTokenRefreshSetsBody(t, sptManual, func(t *testing.T, b []byte) { - if string(b) != defaultManualFormData { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the HTTP Request Body -- expected %v, received %v", - defaultManualFormData, string(b)) - } - }) -} - -func TestServicePrincipalTokenCertficateRefreshSetsBody(t *testing.T) { - sptCert := newServicePrincipalTokenCertificate(t) - testServicePrincipalTokenRefreshSetsBody(t, sptCert, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_assertion_type"][0] != "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" || - values["client_id"][0] != "id" || - values["grant_type"][0] != "client_credentials" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenCertificate#Refresh did not correctly set the HTTP Request Body.") - } - }) -} - -func TestServicePrincipalTokenUsernamePasswordRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalTokenUsernamePassword(t) - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_id"][0] != "id" || - values["grant_type"][0] != "password" || - values["username"][0] != "username" || - values["password"][0] != "password" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenUsernamePassword#Refresh did not correctly set the HTTP Request Body.") - } - }) -} - -func TestServicePrincipalTokenAuthorizationCodeRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalTokenAuthorizationCode(t) - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - body := string(b) - - values, _ := url.ParseQuery(body) - if values["client_id"][0] != "id" || - values["grant_type"][0] != OAuthGrantTypeAuthorizationCode || - values["code"][0] != "code" || - values["client_secret"][0] != "clientSecret" || - values["redirect_uri"][0] != "http://redirectUri/getToken" || - values["resource"][0] != "resource" { - t.Fatalf("adal: ServicePrincipalTokenAuthorizationCode#Refresh did not correctly set the HTTP Request Body.") - } - }) -} - -func TestServicePrincipalTokenSecretRefreshSetsBody(t *testing.T) { - spt := newServicePrincipalToken() - testServicePrincipalTokenRefreshSetsBody(t, spt, func(t *testing.T, b []byte) { - if string(b) != defaultFormData { - t.Fatalf("adal: ServicePrincipalToken#Refresh did not correctly set the HTTP Request Body -- expected %v, received %v", - defaultFormData, string(b)) - } - - }) -} - -func TestServicePrincipalTokenRefreshClosesRequestBody(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - if resp.Body.(*mocks.Body).IsOpen() { - t.Fatal("adal: ServicePrincipalToken#Refresh failed to close the HTTP Response Body") - } -} - -func TestServicePrincipalTokenRefreshRejectsResponsesWithStatusNotOK(t *testing.T) { - spt := newServicePrincipalToken() - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusUnauthorized, "Unauthorized") - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh should reject a response with status != %d", http.StatusOK) - } -} - -func TestServicePrincipalTokenRefreshRejectsEmptyBody(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return mocks.NewResponse(), nil - }) - } - })()) - spt.SetSender(s) - err := spt.Refresh() - if err == nil { - t.Fatal("adal: ServicePrincipalToken#Refresh should reject an empty token") - } -} - -func TestServicePrincipalTokenRefreshPropagatesErrors(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - c.SetError(fmt.Errorf("Faux Error")) - spt.SetSender(c) - - err := spt.Refresh() - if err == nil { - t.Fatal("adal: Failed to propagate the request error") - } -} - -func TestServicePrincipalTokenRefreshReturnsErrorIfNotOk(t *testing.T) { - spt := newServicePrincipalToken() - - c := mocks.NewSender() - c.AppendResponse(mocks.NewResponseWithStatus("401 NotAuthorized", http.StatusUnauthorized)) - spt.SetSender(c) - - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: Failed to return an when receiving a status code other than HTTP %d", http.StatusOK) - } -} - -func TestServicePrincipalTokenRefreshUnmarshals(t *testing.T) { - spt := newServicePrincipalToken() - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - j := newTokenJSON(expiresOn, "resource") - resp := mocks.NewResponseWithContent(j) - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } else if spt.AccessToken != "accessToken" || - spt.ExpiresIn != "3600" || - spt.ExpiresOn != expiresOn || - spt.NotBefore != expiresOn || - spt.Resource != "resource" || - spt.Type != "Bearer" { - t.Fatalf("adal: ServicePrincipalToken#Refresh failed correctly unmarshal the JSON -- expected %v, received %v", - j, *spt) - } -} - -func TestServicePrincipalTokenEnsureFreshRefreshes(t *testing.T) { - spt := newServicePrincipalToken() - expireToken(&spt.Token) - - body := mocks.NewBody(newTokenJSON("test", "test")) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - - f := false - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return resp, nil - }) - } - })()) - spt.SetSender(s) - err := spt.EnsureFresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#EnsureFresh returned an unexpected error (%v)", err) - } - if !f { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh failed to call Refresh for stale token") - } -} - -func TestServicePrincipalTokenEnsureFreshSkipsIfFresh(t *testing.T) { - spt := newServicePrincipalToken() - setTokenToExpireIn(&spt.Token, 1000*time.Second) - - f := false - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return mocks.NewResponse(), nil - }) - } - })()) - spt.SetSender(s) - err := spt.EnsureFresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#EnsureFresh returned an unexpected error (%v)", err) - } - if f { - t.Fatal("adal: ServicePrincipalToken#EnsureFresh invoked Refresh for fresh token") - } -} - -func TestRefreshCallback(t *testing.T) { - callbackTriggered := false - spt := newServicePrincipalToken(func(Token) error { - callbackTriggered = true - return nil - }) - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - - sender := mocks.NewSender() - j := newTokenJSON(expiresOn, "resource") - sender.AppendResponse(mocks.NewResponseWithContent(j)) - spt.SetSender(sender) - err := spt.Refresh() - if err != nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh returned an unexpected error (%v)", err) - } - if !callbackTriggered { - t.Fatalf("adal: RefreshCallback failed to trigger call callback") - } -} - -func TestRefreshCallbackErrorPropagates(t *testing.T) { - errorText := "this is an error text" - spt := newServicePrincipalToken(func(Token) error { - return fmt.Errorf(errorText) - }) - - expiresOn := strconv.Itoa(int(time.Now().Add(3600 * time.Second).Sub(date.UnixEpoch()).Seconds())) - - sender := mocks.NewSender() - j := newTokenJSON(expiresOn, "resource") - sender.AppendResponse(mocks.NewResponseWithContent(j)) - spt.SetSender(sender) - err := spt.Refresh() - - if err == nil || !strings.Contains(err.Error(), errorText) { - t.Fatalf("adal: RefreshCallback failed to propagate error") - } -} - -// This demonstrates the danger of manual token without a refresh token -func TestServicePrincipalTokenManualRefreshFailsWithoutRefresh(t *testing.T) { - spt := newServicePrincipalTokenManual() - spt.RefreshToken = "" - err := spt.Refresh() - if err == nil { - t.Fatalf("adal: ServicePrincipalToken#Refresh should have failed with a ManualTokenSecret without a refresh token") - } -} - -func TestNewServicePrincipalTokenFromMSI(t *testing.T) { - resource := "https://resource" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSI("http://msiendpoint/", resource, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - // check some of the SPT fields - if _, ok := spt.secret.(*ServicePrincipalMSISecret); !ok { - t.Fatal("SPT secret was not of MSI type") - } - - if spt.resource != resource { - t.Fatal("SPT came back with incorrect resource") - } - - if len(spt.refreshCallbacks) != 1 { - t.Fatal("SPT had incorrect refresh callbacks.") - } -} - -func TestNewServicePrincipalTokenFromMSIWithUserAssignedID(t *testing.T) { - resource := "https://resource" - userID := "abc123" - cb := func(token Token) error { return nil } - - spt, err := NewServicePrincipalTokenFromMSIWithUserAssignedID("http://msiendpoint/", resource, userID, cb) - if err != nil { - t.Fatalf("Failed to get MSI SPT: %v", err) - } - - // check some of the SPT fields - if _, ok := spt.secret.(*ServicePrincipalMSISecret); !ok { - t.Fatal("SPT secret was not of MSI type") - } - - if spt.resource != resource { - t.Fatal("SPT came back with incorrect resource") - } - - if len(spt.refreshCallbacks) != 1 { - t.Fatal("SPT had incorrect refresh callbacks.") - } - - if spt.clientID != userID { - t.Fatal("SPT had incorrect client ID") - } -} - -func TestGetVMEndpoint(t *testing.T) { - tempSettingsFile, err := ioutil.TempFile("", "ManagedIdentity-Settings") - if err != nil { - t.Fatal("Couldn't write temp settings file") - } - defer os.Remove(tempSettingsFile.Name()) - - settingsContents := []byte(`{ - "url": "http://msiendpoint/" - }`) - - if _, err := tempSettingsFile.Write(settingsContents); err != nil { - t.Fatal("Couldn't fill temp settings file") - } - - endpoint, err := getMSIVMEndpoint(tempSettingsFile.Name()) - if err != nil { - t.Fatal("Coudn't get VM endpoint") - } - - if endpoint != "http://msiendpoint/" { - t.Fatal("Didn't get correct endpoint") - } -} - -func newToken() *Token { - return &Token{ - AccessToken: "ASECRETVALUE", - Resource: "https://azure.microsoft.com/", - Type: "Bearer", - } -} - -func newTokenJSON(expiresOn string, resource string) string { - return fmt.Sprintf(`{ - "access_token" : "accessToken", - "expires_in" : "3600", - "expires_on" : "%s", - "not_before" : "%s", - "resource" : "%s", - "token_type" : "Bearer" - }`, - expiresOn, expiresOn, resource) -} - -func newTokenExpiresIn(expireIn time.Duration) *Token { - return setTokenToExpireIn(newToken(), expireIn) -} - -func newTokenExpiresAt(expireAt time.Time) *Token { - return setTokenToExpireAt(newToken(), expireAt) -} - -func expireToken(t *Token) *Token { - return setTokenToExpireIn(t, 0) -} - -func setTokenToExpireAt(t *Token, expireAt time.Time) *Token { - t.ExpiresIn = "3600" - t.ExpiresOn = strconv.Itoa(int(expireAt.Sub(date.UnixEpoch()).Seconds())) - t.NotBefore = t.ExpiresOn - return t -} - -func setTokenToExpireIn(t *Token, expireIn time.Duration) *Token { - return setTokenToExpireAt(t, time.Now().Add(expireIn)) -} - -func newServicePrincipalToken(callbacks ...TokenRefreshCallback) *ServicePrincipalToken { - spt, _ := NewServicePrincipalToken(TestOAuthConfig, "id", "secret", "resource", callbacks...) - return spt -} - -func newServicePrincipalTokenManual() *ServicePrincipalToken { - token := newToken() - token.RefreshToken = "refreshtoken" - spt, _ := NewServicePrincipalTokenFromManualToken(TestOAuthConfig, "id", "resource", *token) - return spt -} - -func newServicePrincipalTokenCertificate(t *testing.T) *ServicePrincipalToken { - template := x509.Certificate{ - SerialNumber: big.NewInt(0), - Subject: pkix.Name{CommonName: "test"}, - BasicConstraintsValid: true, - } - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - t.Fatal(err) - } - certificateBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) - if err != nil { - t.Fatal(err) - } - certificate, err := x509.ParseCertificate(certificateBytes) - if err != nil { - t.Fatal(err) - } - - spt, _ := NewServicePrincipalTokenFromCertificate(TestOAuthConfig, "id", certificate, privateKey, "resource") - return spt -} - -func newServicePrincipalTokenUsernamePassword(t *testing.T) *ServicePrincipalToken { - spt, _ := NewServicePrincipalTokenFromUsernamePassword(TestOAuthConfig, "id", "username", "password", "resource") - return spt -} - -func newServicePrincipalTokenAuthorizationCode(t *testing.T) *ServicePrincipalToken { - spt, _ := NewServicePrincipalTokenFromAuthorizationCode(TestOAuthConfig, "id", "clientSecret", "code", "http://redirectUri/getToken", "resource") - return spt -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization.go b/vendor/github.com/Azure/go-autorest/autorest/authorization.go deleted file mode 100644 index 4a602f67..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization.go +++ /dev/null @@ -1,254 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "net/url" - "strings" - - "github.com/Azure/go-autorest/autorest/adal" -) - -const ( - bearerChallengeHeader = "Www-Authenticate" - bearer = "Bearer" - tenantID = "tenantID" - apiKeyAuthorizerHeader = "Ocp-Apim-Subscription-Key" - bingAPISdkHeader = "X-BingApis-SDK-Client" - golangBingAPISdkHeaderValue = "Go-SDK" -) - -// Authorizer is the interface that provides a PrepareDecorator used to supply request -// authorization. Most often, the Authorizer decorator runs last so it has access to the full -// state of the formed HTTP request. -type Authorizer interface { - WithAuthorization() PrepareDecorator -} - -// NullAuthorizer implements a default, "do nothing" Authorizer. -type NullAuthorizer struct{} - -// WithAuthorization returns a PrepareDecorator that does nothing. -func (na NullAuthorizer) WithAuthorization() PrepareDecorator { - return WithNothing() -} - -// APIKeyAuthorizer implements API Key authorization. -type APIKeyAuthorizer struct { - headers map[string]interface{} - queryParameters map[string]interface{} -} - -// NewAPIKeyAuthorizerWithHeaders creates an ApiKeyAuthorizer with headers. -func NewAPIKeyAuthorizerWithHeaders(headers map[string]interface{}) *APIKeyAuthorizer { - return NewAPIKeyAuthorizer(headers, nil) -} - -// NewAPIKeyAuthorizerWithQueryParameters creates an ApiKeyAuthorizer with query parameters. -func NewAPIKeyAuthorizerWithQueryParameters(queryParameters map[string]interface{}) *APIKeyAuthorizer { - return NewAPIKeyAuthorizer(nil, queryParameters) -} - -// NewAPIKeyAuthorizer creates an ApiKeyAuthorizer with headers. -func NewAPIKeyAuthorizer(headers map[string]interface{}, queryParameters map[string]interface{}) *APIKeyAuthorizer { - return &APIKeyAuthorizer{headers: headers, queryParameters: queryParameters} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Paramaters -func (aka *APIKeyAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return DecoratePreparer(p, WithHeaders(aka.headers), WithQueryParameters(aka.queryParameters)) - } -} - -// CognitiveServicesAuthorizer implements authorization for Cognitive Services. -type CognitiveServicesAuthorizer struct { - subscriptionKey string -} - -// NewCognitiveServicesAuthorizer is -func NewCognitiveServicesAuthorizer(subscriptionKey string) *CognitiveServicesAuthorizer { - return &CognitiveServicesAuthorizer{subscriptionKey: subscriptionKey} -} - -// WithAuthorization is -func (csa *CognitiveServicesAuthorizer) WithAuthorization() PrepareDecorator { - headers := make(map[string]interface{}) - headers[apiKeyAuthorizerHeader] = csa.subscriptionKey - headers[bingAPISdkHeader] = golangBingAPISdkHeaderValue - - return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization() -} - -// BearerAuthorizer implements the bearer authorization -type BearerAuthorizer struct { - tokenProvider adal.OAuthTokenProvider -} - -// NewBearerAuthorizer crates a BearerAuthorizer using the given token provider -func NewBearerAuthorizer(tp adal.OAuthTokenProvider) *BearerAuthorizer { - return &BearerAuthorizer{tokenProvider: tp} -} - -func (ba *BearerAuthorizer) withBearerAuthorization() PrepareDecorator { - return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken())) -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is "Bearer " followed by the token. -// -// By default, the token will be automatically refreshed through the Refresher interface. -func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - refresher, ok := ba.tokenProvider.(adal.Refresher) - if ok { - err := refresher.EnsureFresh() - if err != nil { - var resp *http.Response - if tokError, ok := err.(adal.TokenRefreshError); ok { - resp = tokError.Response() - } - return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp, - "Failed to refresh the Token for request to %s", r.URL) - } - } - return (ba.withBearerAuthorization()(p)).Prepare(r) - }) - } -} - -// BearerAuthorizerCallbackFunc is the authentication callback signature. -type BearerAuthorizerCallbackFunc func(tenantID, resource string) (*BearerAuthorizer, error) - -// BearerAuthorizerCallback implements bearer authorization via a callback. -type BearerAuthorizerCallback struct { - sender Sender - callback BearerAuthorizerCallbackFunc -} - -// NewBearerAuthorizerCallback creates a bearer authorization callback. The callback -// is invoked when the HTTP request is submitted. -func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbackFunc) *BearerAuthorizerCallback { - if sender == nil { - sender = &http.Client{} - } - return &BearerAuthorizerCallback{sender: sender, callback: callback} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose value -// is "Bearer " followed by the token. The BearerAuthorizer is obtained via a user-supplied callback. -// -// By default, the token will be automatically refreshed through the Refresher interface. -func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - // make a copy of the request and remove the body as it's not - // required and avoids us having to create a copy of it. - rCopy := *r - removeRequestBody(&rCopy) - - resp, err := bacb.sender.Do(&rCopy) - if err == nil && resp.StatusCode == 401 { - defer resp.Body.Close() - if hasBearerChallenge(resp) { - bc, err := newBearerChallenge(resp) - if err != nil { - return r, err - } - if bacb.callback != nil { - ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"]) - if err != nil { - return r, err - } - return ba.WithAuthorization()(p).Prepare(r) - } - } - } - return r, err - }) - } -} - -// returns true if the HTTP response contains a bearer challenge -func hasBearerChallenge(resp *http.Response) bool { - authHeader := resp.Header.Get(bearerChallengeHeader) - if len(authHeader) == 0 || strings.Index(authHeader, bearer) < 0 { - return false - } - return true -} - -type bearerChallenge struct { - values map[string]string -} - -func newBearerChallenge(resp *http.Response) (bc bearerChallenge, err error) { - challenge := strings.TrimSpace(resp.Header.Get(bearerChallengeHeader)) - trimmedChallenge := challenge[len(bearer)+1:] - - // challenge is a set of key=value pairs that are comma delimited - pairs := strings.Split(trimmedChallenge, ",") - if len(pairs) < 1 { - err = fmt.Errorf("challenge '%s' contains no pairs", challenge) - return bc, err - } - - bc.values = make(map[string]string) - for i := range pairs { - trimmedPair := strings.TrimSpace(pairs[i]) - pair := strings.Split(trimmedPair, "=") - if len(pair) == 2 { - // remove the enclosing quotes - key := strings.Trim(pair[0], "\"") - value := strings.Trim(pair[1], "\"") - - switch key { - case "authorization", "authorization_uri": - // strip the tenant ID from the authorization URL - asURL, err := url.Parse(value) - if err != nil { - return bc, err - } - bc.values[tenantID] = asURL.Path[1:] - default: - bc.values[key] = value - } - } - } - - return bc, err -} - -// EventGridKeyAuthorizer implements authorization for event grid using key authentication. -type EventGridKeyAuthorizer struct { - topicKey string -} - -// NewEventGridKeyAuthorizer creates a new EventGridKeyAuthorizer -// with the specified topic key. -func NewEventGridKeyAuthorizer(topicKey string) EventGridKeyAuthorizer { - return EventGridKeyAuthorizer{topicKey: topicKey} -} - -// WithAuthorization returns a PrepareDecorator that adds the aeg-sas-key authentication header. -func (egta EventGridKeyAuthorizer) WithAuthorization() PrepareDecorator { - headers := map[string]interface{}{ - "aeg-sas-key": egta.topicKey, - } - return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization() -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go deleted file mode 100644 index 6fae544c..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization_test.go +++ /dev/null @@ -1,230 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "reflect" - "testing" - - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - TestTenantID = "TestTenantID" - TestActiveDirectoryEndpoint = "https://login/test.com/" -) - -func TestWithAuthorizer(t *testing.T) { - r1 := mocks.NewRequest() - - na := &NullAuthorizer{} - r2, err := Prepare(r1, - na.WithAuthorization()) - if err != nil { - t.Fatalf("autorest: NullAuthorizer#WithAuthorization returned an unexpected error (%v)", err) - } else if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: NullAuthorizer#WithAuthorization modified the request -- received %v, expected %v", r2, r1) - } -} - -func TestTokenWithAuthorization(t *testing.T) { - token := &adal.Token{ - AccessToken: "TestToken", - Resource: "https://azure.microsoft.com/", - Type: "Bearer", - } - - ba := NewBearerAuthorizer(token) - req, err := Prepare(&http.Request{}, ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", token.AccessToken) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } -} - -func TestServicePrincipalTokenWithAuthorizationNoRefresh(t *testing.T) { - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt.SetAutoRefresh(false) - s := mocks.NewSender() - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.AccessToken) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } -} - -func TestServicePrincipalTokenWithAuthorizationRefresh(t *testing.T) { - - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - refreshed := false - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", func(t adal.Token) error { - refreshed = true - return nil - }) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - - jwt := `{ - "access_token" : "accessToken", - "expires_in" : "3600", - "expires_on" : "test", - "not_before" : "test", - "resource" : "test", - "token_type" : "Bearer" - }` - body := mocks.NewBody(jwt) - resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") - c := mocks.NewSender() - s := DecorateSender(c, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return resp, nil - }) - } - })()) - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.AccessToken) { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") - } - - if !refreshed { - t.Fatal("azure: BearerAuthorizer#WithAuthorization must refresh the token") - } -} - -func TestServicePrincipalTokenWithAuthorizationReturnsErrorIfConnotRefresh(t *testing.T) { - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) - if err != nil { - t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) - } - - s := mocks.NewSender() - s.AppendResponse(mocks.NewResponseWithStatus("400 Bad Request", http.StatusBadRequest)) - spt.SetSender(s) - - ba := NewBearerAuthorizer(spt) - _, err = Prepare(mocks.NewRequest(), ba.WithAuthorization()) - if err == nil { - t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to return an error when refresh fails") - } -} - -func TestBearerAuthorizerCallback(t *testing.T) { - tenantString := "123-tenantID-456" - resourceString := "https://fake.resource.net" - - s := mocks.NewSender() - resp := mocks.NewResponseWithStatus("401 Unauthorized", http.StatusUnauthorized) - mocks.SetResponseHeader(resp, bearerChallengeHeader, bearer+" \"authorization\"=\"https://fake.net/"+tenantString+"\",\"resource\"=\""+resourceString+"\"") - s.AppendResponse(resp) - - auth := NewBearerAuthorizerCallback(s, func(tenantID, resource string) (*BearerAuthorizer, error) { - if tenantID != tenantString { - t.Fatal("BearerAuthorizerCallback: bad tenant ID") - } - if resource != resourceString { - t.Fatal("BearerAuthorizerCallback: bad resource") - } - - oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, tenantID) - if err != nil { - t.Fatalf("azure: NewOAuthConfig returned an error (%v)", err) - } - - spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", resource) - if err != nil { - t.Fatalf("azure: NewServicePrincipalToken returned an error (%v)", err) - } - - spt.SetSender(s) - return NewBearerAuthorizer(spt), nil - }) - - _, err := Prepare(mocks.NewRequest(), auth.WithAuthorization()) - if err == nil { - t.Fatal("azure: BearerAuthorizerCallback#WithAuthorization failed to return an error when refresh fails") - } -} - -func TestApiKeyAuthorization(t *testing.T) { - - headers := make(map[string]interface{}) - queryParameters := make(map[string]interface{}) - - dummyAuthHeader := "dummyAuthHeader" - dummyAuthHeaderValue := "dummyAuthHeaderValue" - - dummyAuthQueryParameter := "dummyAuthQueryParameter" - dummyAuthQueryParameterValue := "dummyAuthQueryParameterValue" - - headers[dummyAuthHeader] = dummyAuthHeaderValue - queryParameters[dummyAuthQueryParameter] = dummyAuthQueryParameterValue - - aka := NewAPIKeyAuthorizer(headers, queryParameters) - - req, err := Prepare(mocks.NewRequest(), aka.WithAuthorization()) - - if err != nil { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey(dummyAuthHeader)) != dummyAuthHeaderValue { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s header", dummyAuthHeader) - - } else if req.URL.Query().Get(dummyAuthQueryParameter) != dummyAuthQueryParameterValue { - t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s query parameter", dummyAuthQueryParameterValue) - } -} - -func TestCognitivesServicesAuthorization(t *testing.T) { - subscriptionKey := "dummyKey" - csa := NewCognitiveServicesAuthorizer(subscriptionKey) - req, err := Prepare(mocks.NewRequest(), csa.WithAuthorization()) - - if err != nil { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization returned an error (%v)", err) - } else if req.Header.Get(http.CanonicalHeaderKey(bingAPISdkHeader)) != golangBingAPISdkHeaderValue { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", bingAPISdkHeader) - } else if req.Header.Get(http.CanonicalHeaderKey(apiKeyAuthorizerHeader)) != subscriptionKey { - t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", apiKeyAuthorizerHeader) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest.go b/vendor/github.com/Azure/go-autorest/autorest/autorest.go deleted file mode 100644 index f86b66a4..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/autorest.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines -and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/) -generated Go code. - -The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, -and Responding. A typical pattern is: - - req, err := Prepare(&http.Request{}, - token.WithAuthorization()) - - resp, err := Send(req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusInternalServerError), - DoCloseIfError(), - DoRetryForAttempts(5, time.Second)) - - err = Respond(resp, - ByDiscardingBody(), - ByClosing()) - -Each phase relies on decorators to modify and / or manage processing. Decorators may first modify -and then pass the data along, pass the data first and then modify the result, or wrap themselves -around passing the data (such as a logger might do). Decorators run in the order provided. For -example, the following: - - req, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) - -will set the URL to: - - https://microsoft.com/a/b/c - -Preparers and Responders may be shared and re-used (assuming the underlying decorators support -sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders -shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, -all bound together by means of input / output channels. - -Decorators hold their passed state within a closure (such as the path components in the example -above). Be careful to share Preparers and Responders only in a context where such held state -applies. For example, it may not make sense to share a Preparer that applies a query string from a -fixed set of values. Similarly, sharing a Responder that reads the response body into a passed -struct (e.g., ByUnmarshallingJson) is likely incorrect. - -Lastly, the Swagger specification (https://swagger.io) that drives AutoRest -(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The -github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure -correct parsing and formatting. - -Errors raised by autorest objects and methods will conform to the autorest.Error interface. - -See the included examples for more detail. For details on the suggested use of this package by -generated clients, see the Client described below. -*/ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "net/http" - "time" -) - -const ( - // HeaderLocation specifies the HTTP Location header. - HeaderLocation = "Location" - - // HeaderRetryAfter specifies the HTTP Retry-After header. - HeaderRetryAfter = "Retry-After" -) - -// ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set -// and false otherwise. -func ResponseHasStatusCode(resp *http.Response, codes ...int) bool { - if resp == nil { - return false - } - return containsInt(codes, resp.StatusCode) -} - -// GetLocation retrieves the URL from the Location header of the passed response. -func GetLocation(resp *http.Response) string { - return resp.Header.Get(HeaderLocation) -} - -// GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If -// the header is absent or is malformed, it will return the supplied default delay time.Duration. -func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration { - retry := resp.Header.Get(HeaderRetryAfter) - if retry == "" { - return defaultDelay - } - - d, err := time.ParseDuration(retry + "s") - if err != nil { - return defaultDelay - } - - return d -} - -// NewPollingRequest allocates and returns a new http.Request to poll for the passed response. -func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) { - location := GetLocation(resp) - if location == "" { - return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling") - } - - req, err := Prepare(&http.Request{Cancel: cancel}, - AsGet(), - WithBaseURL(location)) - if err != nil { - return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location) - } - - return req, nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go b/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go deleted file mode 100644 index 467ea438..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/autorest_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "net/http" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestResponseHasStatusCode(t *testing.T) { - codes := []int{http.StatusOK, http.StatusAccepted} - resp := &http.Response{StatusCode: http.StatusAccepted} - if !ResponseHasStatusCode(resp, codes...) { - t.Fatalf("autorest: ResponseHasStatusCode failed to find %v in %v", resp.StatusCode, codes) - } -} - -func TestResponseHasStatusCodeNotPresent(t *testing.T) { - codes := []int{http.StatusOK, http.StatusAccepted} - resp := &http.Response{StatusCode: http.StatusInternalServerError} - if ResponseHasStatusCode(resp, codes...) { - t.Fatalf("autorest: ResponseHasStatusCode unexpectedly found %v in %v", resp.StatusCode, codes) - } -} - -func TestNewPollingRequestDoesNotReturnARequestWhenLocationHeaderIsMissing(t *testing.T) { - resp := mocks.NewResponseWithStatus("500 InternalServerError", http.StatusInternalServerError) - - req, _ := NewPollingRequest(resp, nil) - if req != nil { - t.Fatal("autorest: NewPollingRequest returned an http.Request when the Location header was missing") - } -} - -func TestNewPollingRequestReturnsAnErrorWhenPrepareFails(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderLocation), mocks.TestBadURL) - - _, err := NewPollingRequest(resp, nil) - if err == nil { - t.Fatal("autorest: NewPollingRequest failed to return an error when Prepare fails") - } -} - -func TestNewPollingRequestDoesNotReturnARequestWhenPrepareFails(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderLocation), mocks.TestBadURL) - - req, _ := NewPollingRequest(resp, nil) - if req != nil { - t.Fatal("autorest: NewPollingRequest returned an http.Request when Prepare failed") - } -} - -func TestNewPollingRequestReturnsAGetRequest(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - req, _ := NewPollingRequest(resp, nil) - if req.Method != "GET" { - t.Fatalf("autorest: NewPollingRequest did not create an HTTP GET request -- actual method %v", req.Method) - } -} - -func TestNewPollingRequestProvidesTheURL(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - req, _ := NewPollingRequest(resp, nil) - if req.URL.String() != mocks.TestURL { - t.Fatalf("autorest: NewPollingRequest did not create an HTTP with the expected URL -- received %v, expected %v", req.URL, mocks.TestURL) - } -} - -func TestGetLocation(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - l := GetLocation(resp) - if len(l) == 0 { - t.Fatalf("autorest: GetLocation failed to return Location header -- expected %v, received %v", mocks.TestURL, l) - } -} - -func TestGetLocationReturnsEmptyStringForMissingLocation(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - - l := GetLocation(resp) - if len(l) != 0 { - t.Fatalf("autorest: GetLocation return a value without a Location header -- received %v", l) - } -} - -func TestGetRetryAfter(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != mocks.TestDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the expected delay -- expected %v, received %v", mocks.TestDelay, d) - } -} - -func TestGetRetryAfterReturnsDefaultDelayIfRetryHeaderIsMissing(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != DefaultPollingDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the default delay for a missing Retry-After header -- expected %v, received %v", - DefaultPollingDelay, d) - } -} - -func TestGetRetryAfterReturnsDefaultDelayIfRetryHeaderIsMalformed(t *testing.T) { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - resp.Header.Set(http.CanonicalHeaderKey(HeaderRetryAfter), "a very bad non-integer value") - - d := GetRetryAfter(resp, DefaultPollingDelay) - if d != DefaultPollingDelay { - t.Fatalf("autorest: GetRetryAfter failed to returned the default delay for a malformed Retry-After header -- expected %v, received %v", - DefaultPollingDelay, d) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go deleted file mode 100644 index 366fc537..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go +++ /dev/null @@ -1,478 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strings" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/date" -) - -const ( - headerAsyncOperation = "Azure-AsyncOperation" -) - -const ( - operationInProgress string = "InProgress" - operationCanceled string = "Canceled" - operationFailed string = "Failed" - operationSucceeded string = "Succeeded" -) - -var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.StatusCreated, http.StatusOK} - -// Future provides a mechanism to access the status and results of an asynchronous request. -// Since futures are stateful they should be passed by value to avoid race conditions. -type Future struct { - req *http.Request - resp *http.Response - ps pollingState -} - -// NewFuture returns a new Future object initialized with the specified request. -func NewFuture(req *http.Request) Future { - return Future{req: req} -} - -// Response returns the last HTTP response or nil if there isn't one. -func (f Future) Response() *http.Response { - return f.resp -} - -// Status returns the last status message of the operation. -func (f Future) Status() string { - if f.ps.State == "" { - return "Unknown" - } - return f.ps.State -} - -// PollingMethod returns the method used to monitor the status of the asynchronous operation. -func (f Future) PollingMethod() PollingMethodType { - return f.ps.PollingMethod -} - -// Done queries the service to see if the operation has completed. -func (f *Future) Done(sender autorest.Sender) (bool, error) { - // exit early if this future has terminated - if f.ps.hasTerminated() { - return true, f.errorInfo() - } - - resp, err := sender.Do(f.req) - f.resp = resp - if err != nil || !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) { - return false, err - } - - err = updatePollingState(resp, &f.ps) - if err != nil { - return false, err - } - - if f.ps.hasTerminated() { - return true, f.errorInfo() - } - - f.req, err = newPollingRequest(f.ps) - return false, err -} - -// GetPollingDelay returns a duration the application should wait before checking -// the status of the asynchronous request and true; this value is returned from -// the service via the Retry-After response header. If the header wasn't returned -// then the function returns the zero-value time.Duration and false. -func (f Future) GetPollingDelay() (time.Duration, bool) { - if f.resp == nil { - return 0, false - } - - retry := f.resp.Header.Get(autorest.HeaderRetryAfter) - if retry == "" { - return 0, false - } - - d, err := time.ParseDuration(retry + "s") - if err != nil { - panic(err) - } - - return d, true -} - -// WaitForCompletion will return when one of the following conditions is met: the long -// running operation has completed, the provided context is cancelled, or the client's -// polling duration has been exceeded. It will retry failed polling attempts based on -// the retry value defined in the client up to the maximum retry attempts. -func (f Future) WaitForCompletion(ctx context.Context, client autorest.Client) error { - ctx, cancel := context.WithTimeout(ctx, client.PollingDuration) - defer cancel() - - done, err := f.Done(client) - for attempts := 0; !done; done, err = f.Done(client) { - if attempts >= client.RetryAttempts { - return autorest.NewErrorWithError(err, "azure", "WaitForCompletion", f.resp, "the number of retries has been exceeded") - } - // we want delayAttempt to be zero in the non-error case so - // that DelayForBackoff doesn't perform exponential back-off - var delayAttempt int - var delay time.Duration - if err == nil { - // check for Retry-After delay, if not present use the client's polling delay - var ok bool - delay, ok = f.GetPollingDelay() - if !ok { - delay = client.PollingDelay - } - } else { - // there was an error polling for status so perform exponential - // back-off based on the number of attempts using the client's retry - // duration. update attempts after delayAttempt to avoid off-by-one. - delayAttempt = attempts - delay = client.RetryDuration - attempts++ - } - // wait until the delay elapses or the context is cancelled - delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, ctx.Done()) - if !delayElapsed { - return autorest.NewErrorWithError(ctx.Err(), "azure", "WaitForCompletion", f.resp, "context has been cancelled") - } - } - return err -} - -// if the operation failed the polling state will contain -// error information and implements the error interface -func (f *Future) errorInfo() error { - if !f.ps.hasSucceeded() { - return f.ps - } - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (f Future) MarshalJSON() ([]byte, error) { - return json.Marshal(&f.ps) -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (f *Future) UnmarshalJSON(data []byte) error { - err := json.Unmarshal(data, &f.ps) - if err != nil { - return err - } - f.req, err = newPollingRequest(f.ps) - return err -} - -// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure -// long-running operation. It will delay between requests for the duration specified in the -// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by -// closing the optional channel on the http.Request. -func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator { - return func(s autorest.Sender) autorest.Sender { - return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - resp, err = s.Do(r) - if err != nil { - return resp, err - } - if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) { - return resp, nil - } - - ps := pollingState{} - for err == nil { - err = updatePollingState(resp, &ps) - if err != nil { - break - } - if ps.hasTerminated() { - if !ps.hasSucceeded() { - err = ps - } - break - } - - r, err = newPollingRequest(ps) - if err != nil { - return resp, err - } - r.Cancel = resp.Request.Cancel - - delay = autorest.GetRetryAfter(resp, delay) - resp, err = autorest.SendWithSender(s, r, - autorest.AfterDelay(delay)) - } - - return resp, err - }) - } -} - -func getAsyncOperation(resp *http.Response) string { - return resp.Header.Get(http.CanonicalHeaderKey(headerAsyncOperation)) -} - -func hasSucceeded(state string) bool { - return strings.EqualFold(state, operationSucceeded) -} - -func hasTerminated(state string) bool { - return strings.EqualFold(state, operationCanceled) || strings.EqualFold(state, operationFailed) || strings.EqualFold(state, operationSucceeded) -} - -func hasFailed(state string) bool { - return strings.EqualFold(state, operationFailed) -} - -type provisioningTracker interface { - state() string - hasSucceeded() bool - hasTerminated() bool -} - -type operationResource struct { - // Note: - // The specification states services should return the "id" field. However some return it as - // "operationId". - ID string `json:"id"` - OperationID string `json:"operationId"` - Name string `json:"name"` - Status string `json:"status"` - Properties map[string]interface{} `json:"properties"` - OperationError ServiceError `json:"error"` - StartTime date.Time `json:"startTime"` - EndTime date.Time `json:"endTime"` - PercentComplete float64 `json:"percentComplete"` -} - -func (or operationResource) state() string { - return or.Status -} - -func (or operationResource) hasSucceeded() bool { - return hasSucceeded(or.state()) -} - -func (or operationResource) hasTerminated() bool { - return hasTerminated(or.state()) -} - -type provisioningProperties struct { - ProvisioningState string `json:"provisioningState"` -} - -type provisioningStatus struct { - Properties provisioningProperties `json:"properties,omitempty"` - ProvisioningError ServiceError `json:"error,omitempty"` -} - -func (ps provisioningStatus) state() string { - return ps.Properties.ProvisioningState -} - -func (ps provisioningStatus) hasSucceeded() bool { - return hasSucceeded(ps.state()) -} - -func (ps provisioningStatus) hasTerminated() bool { - return hasTerminated(ps.state()) -} - -func (ps provisioningStatus) hasProvisioningError() bool { - return ps.ProvisioningError != ServiceError{} -} - -// PollingMethodType defines a type used for enumerating polling mechanisms. -type PollingMethodType string - -const ( - // PollingAsyncOperation indicates the polling method uses the Azure-AsyncOperation header. - PollingAsyncOperation PollingMethodType = "AsyncOperation" - - // PollingLocation indicates the polling method uses the Location header. - PollingLocation PollingMethodType = "Location" - - // PollingUnknown indicates an unknown polling method and is the default value. - PollingUnknown PollingMethodType = "" -) - -type pollingState struct { - PollingMethod PollingMethodType `json:"pollingMethod"` - URI string `json:"uri"` - State string `json:"state"` - Code string `json:"code"` - Message string `json:"message"` -} - -func (ps pollingState) hasSucceeded() bool { - return hasSucceeded(ps.State) -} - -func (ps pollingState) hasTerminated() bool { - return hasTerminated(ps.State) -} - -func (ps pollingState) hasFailed() bool { - return hasFailed(ps.State) -} - -func (ps pollingState) Error() string { - return fmt.Sprintf("Long running operation terminated with status '%s': Code=%q Message=%q", ps.State, ps.Code, ps.Message) -} - -// updatePollingState maps the operation status -- retrieved from either a provisioningState -// field, the status field of an OperationResource, or inferred from the HTTP status code -- -// into a well-known states. Since the process begins from the initial request, the state -// always comes from either a the provisioningState returned or is inferred from the HTTP -// status code. Subsequent requests will read an Azure OperationResource object if the -// service initially returned the Azure-AsyncOperation header. The responseFormat field notes -// the expected response format. -func updatePollingState(resp *http.Response, ps *pollingState) error { - // Determine the response shape - // -- The first response will always be a provisioningStatus response; only the polling requests, - // depending on the header returned, may be something otherwise. - var pt provisioningTracker - if ps.PollingMethod == PollingAsyncOperation { - pt = &operationResource{} - } else { - pt = &provisioningStatus{} - } - - // If this is the first request (that is, the polling response shape is unknown), determine how - // to poll and what to expect - if ps.PollingMethod == PollingUnknown { - req := resp.Request - if req == nil { - return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Original HTTP request is missing") - } - - // Prefer the Azure-AsyncOperation header - ps.URI = getAsyncOperation(resp) - if ps.URI != "" { - ps.PollingMethod = PollingAsyncOperation - } else { - ps.PollingMethod = PollingLocation - } - - // Else, use the Location header - if ps.URI == "" { - ps.URI = autorest.GetLocation(resp) - } - - // Lastly, requests against an existing resource, use the last request URI - if ps.URI == "" { - m := strings.ToUpper(req.Method) - if m == http.MethodPatch || m == http.MethodPut || m == http.MethodGet { - ps.URI = req.URL.String() - } - } - } - - // Read and interpret the response (saving the Body in case no polling is necessary) - b := &bytes.Buffer{} - err := autorest.Respond(resp, - autorest.ByCopying(b), - autorest.ByUnmarshallingJSON(pt), - autorest.ByClosing()) - resp.Body = ioutil.NopCloser(b) - if err != nil { - return err - } - - // Interpret the results - // -- Terminal states apply regardless - // -- Unknown states are per-service inprogress states - // -- Otherwise, infer state from HTTP status code - if pt.hasTerminated() { - ps.State = pt.state() - } else if pt.state() != "" { - ps.State = operationInProgress - } else { - switch resp.StatusCode { - case http.StatusAccepted: - ps.State = operationInProgress - - case http.StatusNoContent, http.StatusCreated, http.StatusOK: - ps.State = operationSucceeded - - default: - ps.State = operationFailed - } - } - - if strings.EqualFold(ps.State, operationInProgress) && ps.URI == "" { - return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Unable to obtain polling URI for %s %s", resp.Request.Method, resp.Request.URL) - } - - // For failed operation, check for error code and message in - // -- Operation resource - // -- Response - // -- Otherwise, Unknown - if ps.hasFailed() { - if ps.PollingMethod == PollingAsyncOperation { - or := pt.(*operationResource) - ps.Code = or.OperationError.Code - ps.Message = or.OperationError.Message - } else { - p := pt.(*provisioningStatus) - if p.hasProvisioningError() { - ps.Code = p.ProvisioningError.Code - ps.Message = p.ProvisioningError.Message - } else { - ps.Code = "Unknown" - ps.Message = "None" - } - } - } - return nil -} - -func newPollingRequest(ps pollingState) (*http.Request, error) { - reqPoll, err := autorest.Prepare(&http.Request{}, - autorest.AsGet(), - autorest.WithBaseURL(ps.URI)) - if err != nil { - return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.URI) - } - - return reqPoll, nil -} - -// AsyncOpIncompleteError is the type that's returned from a future that has not completed. -type AsyncOpIncompleteError struct { - // FutureType is the name of the type composed of a azure.Future. - FutureType string -} - -// Error returns an error message including the originating type name of the error. -func (e AsyncOpIncompleteError) Error() string { - return fmt.Sprintf("%s: asynchronous operation has not completed", e.FutureType) -} - -// NewAsyncOpIncompleteError creates a new AsyncOpIncompleteError with the specified parameters. -func NewAsyncOpIncompleteError(futureType string) AsyncOpIncompleteError { - return AsyncOpIncompleteError{ - FutureType: futureType, - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go deleted file mode 100644 index 5757e25c..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go +++ /dev/null @@ -1,1327 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strings" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestGetAsyncOperation_ReturnsAzureAsyncOperationHeader(t *testing.T) { - r := newAsynchronousResponse() - - if getAsyncOperation(r) != mocks.TestAzureAsyncURL { - t.Fatalf("azure: getAsyncOperation failed to extract the Azure-AsyncOperation header -- expected %v, received %v", mocks.TestURL, getAsyncOperation(r)) - } -} - -func TestGetAsyncOperation_ReturnsEmptyStringIfHeaderIsAbsent(t *testing.T) { - r := mocks.NewResponse() - - if len(getAsyncOperation(r)) != 0 { - t.Fatalf("azure: getAsyncOperation failed to return empty string when the Azure-AsyncOperation header is absent -- received %v", getAsyncOperation(r)) - } -} - -func TestHasSucceeded_ReturnsTrueForSuccess(t *testing.T) { - if !hasSucceeded(operationSucceeded) { - t.Fatal("azure: hasSucceeded failed to return true for success") - } -} - -func TestHasSucceeded_ReturnsFalseOtherwise(t *testing.T) { - if hasSucceeded("not a success string") { - t.Fatal("azure: hasSucceeded returned true for a non-success") - } -} - -func TestHasTerminated_ReturnsTrueForValidTerminationStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - if !hasTerminated(state) { - t.Fatalf("azure: hasTerminated failed to return true for the '%s' state", state) - } - } -} - -func TestHasTerminated_ReturnsFalseForUnknownStates(t *testing.T) { - if hasTerminated("not a known state") { - t.Fatal("azure: hasTerminated returned true for an unknown state") - } -} - -func TestOperationError_ErrorReturnsAString(t *testing.T) { - s := (ServiceError{Code: "server code", Message: "server error"}).Error() - if s == "" { - t.Fatalf("azure: operationError#Error failed to return an error") - } - if !strings.Contains(s, "server code") || !strings.Contains(s, "server error") { - t.Fatalf("azure: operationError#Error returned a malformed error -- error='%v'", s) - } -} - -func TestOperationResource_StateReturnsState(t *testing.T) { - if (operationResource{Status: "state"}).state() != "state" { - t.Fatalf("azure: operationResource#state failed to return the correct state") - } -} - -func TestOperationResource_HasSucceededReturnsFalseIfNotSuccess(t *testing.T) { - if (operationResource{Status: "not a success string"}).hasSucceeded() { - t.Fatalf("azure: operationResource#hasSucceeded failed to return false for a canceled operation") - } -} - -func TestOperationResource_HasSucceededReturnsTrueIfSuccessful(t *testing.T) { - if !(operationResource{Status: operationSucceeded}).hasSucceeded() { - t.Fatalf("azure: operationResource#hasSucceeded failed to return true for a successful operation") - } -} - -func TestOperationResource_HasTerminatedReturnsTrueForKnownStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - if !(operationResource{Status: state}).hasTerminated() { - t.Fatalf("azure: operationResource#hasTerminated failed to return true for the '%s' state", state) - } - } -} - -func TestOperationResource_HasTerminatedReturnsFalseForUnknownStates(t *testing.T) { - if (operationResource{Status: "not a known state"}).hasTerminated() { - t.Fatalf("azure: operationResource#hasTerminated returned true for a non-terminal operation") - } -} - -func TestProvisioningStatus_StateReturnsState(t *testing.T) { - if (provisioningStatus{Properties: provisioningProperties{"state"}}).state() != "state" { - t.Fatalf("azure: provisioningStatus#state failed to return the correct state") - } -} - -func TestProvisioningStatus_HasSucceededReturnsFalseIfNotSuccess(t *testing.T) { - if (provisioningStatus{Properties: provisioningProperties{"not a success string"}}).hasSucceeded() { - t.Fatalf("azure: provisioningStatus#hasSucceeded failed to return false for a canceled operation") - } -} - -func TestProvisioningStatus_HasSucceededReturnsTrueIfSuccessful(t *testing.T) { - if !(provisioningStatus{Properties: provisioningProperties{operationSucceeded}}).hasSucceeded() { - t.Fatalf("azure: provisioningStatus#hasSucceeded failed to return true for a successful operation") - } -} - -func TestProvisioningStatus_HasTerminatedReturnsTrueForKnownStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - if !(provisioningStatus{Properties: provisioningProperties{state}}).hasTerminated() { - t.Fatalf("azure: provisioningStatus#hasTerminated failed to return true for the '%s' state", state) - } - } -} - -func TestProvisioningStatus_HasTerminatedReturnsFalseForUnknownStates(t *testing.T) { - if (provisioningStatus{Properties: provisioningProperties{"not a known state"}}).hasTerminated() { - t.Fatalf("azure: provisioningStatus#hasTerminated returned true for a non-terminal operation") - } -} - -func TestPollingState_HasSucceededReturnsFalseIfNotSuccess(t *testing.T) { - if (pollingState{State: "not a success string"}).hasSucceeded() { - t.Fatalf("azure: pollingState#hasSucceeded failed to return false for a canceled operation") - } -} - -func TestPollingState_HasSucceededReturnsTrueIfSuccessful(t *testing.T) { - if !(pollingState{State: operationSucceeded}).hasSucceeded() { - t.Fatalf("azure: pollingState#hasSucceeded failed to return true for a successful operation") - } -} - -func TestPollingState_HasTerminatedReturnsTrueForKnownStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - if !(pollingState{State: state}).hasTerminated() { - t.Fatalf("azure: pollingState#hasTerminated failed to return true for the '%s' state", state) - } - } -} - -func TestPollingState_HasTerminatedReturnsFalseForUnknownStates(t *testing.T) { - if (pollingState{State: "not a known state"}).hasTerminated() { - t.Fatalf("azure: pollingState#hasTerminated returned true for a non-terminal operation") - } -} - -func TestUpdatePollingState_ReturnsAnErrorIfOneOccurs(t *testing.T) { - resp := mocks.NewResponseWithContent(operationResourceIllegal) - err := updatePollingState(resp, &pollingState{}) - if err == nil { - t.Fatalf("azure: updatePollingState failed to return an error after a JSON parsing error") - } -} - -func TestUpdatePollingState_ReturnsTerminatedForKnownProvisioningStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, state)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if !ps.hasTerminated() { - t.Fatalf("azure: updatePollingState failed to return a terminating pollingState for the '%s' state", state) - } - } -} - -func TestUpdatePollingState_ReturnsSuccessForSuccessfulProvisioningState(t *testing.T) { - resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, operationSucceeded)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if !ps.hasSucceeded() { - t.Fatalf("azure: updatePollingState failed to return a successful pollingState for the '%s' state", operationSucceeded) - } -} - -func TestUpdatePollingState_ReturnsInProgressForAllOtherProvisioningStates(t *testing.T) { - s := "not a recognized state" - resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, s)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if ps.hasTerminated() { - t.Fatalf("azure: updatePollingState returned terminated for unknown state '%s'", s) - } -} - -func TestUpdatePollingState_ReturnsSuccessWhenProvisioningStateFieldIsAbsentForSuccessStatusCodes(t *testing.T) { - for _, sc := range []int{http.StatusOK, http.StatusCreated, http.StatusNoContent} { - resp := mocks.NewResponseWithContent(pollingStateEmpty) - resp.StatusCode = sc - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if !ps.hasSucceeded() { - t.Fatalf("azure: updatePollingState failed to return success when the provisionState field is absent for Status Code %d", sc) - } - } -} - -func TestUpdatePollingState_ReturnsInProgressWhenProvisioningStateFieldIsAbsentForAccepted(t *testing.T) { - resp := mocks.NewResponseWithContent(pollingStateEmpty) - resp.StatusCode = http.StatusAccepted - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if ps.hasTerminated() { - t.Fatalf("azure: updatePollingState returned terminated when the provisionState field is absent for Status Code Accepted") - } -} - -func TestUpdatePollingState_ReturnsFailedWhenProvisioningStateFieldIsAbsentForUnknownStatusCodes(t *testing.T) { - resp := mocks.NewResponseWithContent(pollingStateEmpty) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if !ps.hasTerminated() || ps.hasSucceeded() { - t.Fatalf("azure: updatePollingState did not return failed when the provisionState field is absent for an unknown Status Code") - } -} - -func TestUpdatePollingState_ReturnsTerminatedForKnownOperationResourceStates(t *testing.T) { - for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} { - resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, state)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingAsyncOperation} - updatePollingState(resp, ps) - if !ps.hasTerminated() { - t.Fatalf("azure: updatePollingState failed to return a terminating pollingState for the '%s' state", state) - } - } -} - -func TestUpdatePollingState_ReturnsSuccessForSuccessfulOperationResourceState(t *testing.T) { - resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, operationSucceeded)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingAsyncOperation} - updatePollingState(resp, ps) - if !ps.hasSucceeded() { - t.Fatalf("azure: updatePollingState failed to return a successful pollingState for the '%s' state", operationSucceeded) - } -} - -func TestUpdatePollingState_ReturnsInProgressForAllOtherOperationResourceStates(t *testing.T) { - s := "not a recognized state" - resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, s)) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingAsyncOperation} - updatePollingState(resp, ps) - if ps.hasTerminated() { - t.Fatalf("azure: updatePollingState returned terminated for unknown state '%s'", s) - } -} - -func TestUpdatePollingState_CopiesTheResponseBody(t *testing.T) { - s := fmt.Sprintf(pollingStateFormat, operationSucceeded) - resp := mocks.NewResponseWithContent(s) - resp.StatusCode = 42 - ps := &pollingState{PollingMethod: PollingAsyncOperation} - updatePollingState(resp, ps) - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("azure: updatePollingState failed to replace the http.Response Body -- Error='%v'", err) - } - if string(b) != s { - t.Fatalf("azure: updatePollingState failed to copy the http.Response Body -- Expected='%s' Received='%s'", s, string(b)) - } -} - -func TestUpdatePollingState_ClosesTheOriginalResponseBody(t *testing.T) { - resp := mocks.NewResponse() - b := resp.Body.(*mocks.Body) - ps := &pollingState{PollingMethod: PollingLocation} - updatePollingState(resp, ps) - if b.IsOpen() { - t.Fatal("azure: updatePollingState failed to close the original http.Response Body") - } -} - -func TestUpdatePollingState_FailsWhenResponseLacksRequest(t *testing.T) { - resp := newAsynchronousResponse() - resp.Request = nil - - ps := pollingState{} - err := updatePollingState(resp, &ps) - if err == nil { - t.Fatal("azure: updatePollingState failed to return an error when the http.Response lacked the original http.Request") - } -} - -func TestUpdatePollingState_SetsThePollingMethodWhenUsingTheAzureAsyncOperationHeader(t *testing.T) { - ps := pollingState{} - updatePollingState(newAsynchronousResponse(), &ps) - - if ps.PollingMethod != PollingAsyncOperation { - t.Fatal("azure: updatePollingState failed to set the correct response format when using the Azure-AsyncOperation header") - } -} - -func TestUpdatePollingState_SetsThePollingMethodWhenUsingTheAzureAsyncOperationHeaderIsMissing(t *testing.T) { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - ps := pollingState{} - updatePollingState(resp, &ps) - - if ps.PollingMethod != PollingLocation { - t.Fatal("azure: updatePollingState failed to set the correct response format when the Azure-AsyncOperation header is absent") - } -} - -func TestUpdatePollingState_DoesNotChangeAnExistingReponseFormat(t *testing.T) { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - ps := pollingState{PollingMethod: PollingAsyncOperation} - updatePollingState(resp, &ps) - - if ps.PollingMethod != PollingAsyncOperation { - t.Fatal("azure: updatePollingState failed to leave an existing response format setting") - } -} - -func TestUpdatePollingState_PrefersTheAzureAsyncOperationHeader(t *testing.T) { - resp := newAsynchronousResponse() - - ps := pollingState{} - updatePollingState(resp, &ps) - - if ps.URI != mocks.TestAzureAsyncURL { - t.Fatal("azure: updatePollingState failed to prefer the Azure-AsyncOperation header") - } -} - -func TestUpdatePollingState_PrefersLocationWhenTheAzureAsyncOperationHeaderMissing(t *testing.T) { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - ps := pollingState{} - updatePollingState(resp, &ps) - - if ps.URI != mocks.TestLocationURL { - t.Fatal("azure: updatePollingState failed to prefer the Location header when the Azure-AsyncOperation header is missing") - } -} - -func TestUpdatePollingState_UsesTheObjectLocationIfAsyncHeadersAreMissing(t *testing.T) { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - resp.Header.Del(http.CanonicalHeaderKey(autorest.HeaderLocation)) - resp.Request.Method = http.MethodPatch - - ps := pollingState{} - updatePollingState(resp, &ps) - - if ps.URI != mocks.TestURL { - t.Fatal("azure: updatePollingState failed to use the Object URL when the asynchronous headers are missing") - } -} - -func TestUpdatePollingState_RecognizesLowerCaseHTTPVerbs(t *testing.T) { - for _, m := range []string{strings.ToLower(http.MethodPatch), strings.ToLower(http.MethodPut), strings.ToLower(http.MethodGet)} { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - resp.Header.Del(http.CanonicalHeaderKey(autorest.HeaderLocation)) - resp.Request.Method = m - - ps := pollingState{} - updatePollingState(resp, &ps) - - if ps.URI != mocks.TestURL { - t.Fatalf("azure: updatePollingState failed to recognize the lower-case HTTP verb '%s'", m) - } - } -} - -func TestUpdatePollingState_ReturnsAnErrorIfAsyncHeadersAreMissingForANewOrDeletedObject(t *testing.T) { - resp := newAsynchronousResponse() - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - resp.Header.Del(http.CanonicalHeaderKey(autorest.HeaderLocation)) - - for _, m := range []string{http.MethodDelete, http.MethodPost} { - resp.Request.Method = m - err := updatePollingState(resp, &pollingState{}) - if err == nil { - t.Fatalf("azure: updatePollingState failed to return an error even though it could not determine the polling URL for Method '%s'", m) - } - } -} - -func TestNewPollingRequest_ReturnsAnErrorWhenPrepareFails(t *testing.T) { - _, err := newPollingRequest(pollingState{PollingMethod: PollingAsyncOperation, URI: mocks.TestBadURL}) - if err == nil { - t.Fatal("azure: newPollingRequest failed to return an error when Prepare fails") - } -} - -func TestNewPollingRequest_DoesNotReturnARequestWhenPrepareFails(t *testing.T) { - req, _ := newPollingRequest(pollingState{PollingMethod: PollingAsyncOperation, URI: mocks.TestBadURL}) - if req != nil { - t.Fatal("azure: newPollingRequest returned an http.Request when Prepare failed") - } -} - -func TestNewPollingRequest_ReturnsAGetRequest(t *testing.T) { - req, _ := newPollingRequest(pollingState{PollingMethod: PollingAsyncOperation, URI: mocks.TestAzureAsyncURL}) - if req.Method != "GET" { - t.Fatalf("azure: newPollingRequest did not create an HTTP GET request -- actual method %v", req.Method) - } -} - -func TestDoPollForAsynchronous_IgnoresUnspecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Duration(0))) - - if client.Attempts() != 1 { - t.Fatalf("azure: DoPollForAsynchronous polled for unspecified status code") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsForSpecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAsynchronousResponse()) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() != 2 { - t.Fatalf("azure: DoPollForAsynchronous failed to poll for specified status code") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_CanBeCanceled(t *testing.T) { - cancel := make(chan struct{}) - delay := 5 * time.Second - - r1 := newAsynchronousResponse() - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(newOperationResourceResponse("Busy"), -1) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - go func() { - req := mocks.NewRequest() - req.Cancel = cancel - - wg.Done() - - r, _ := autorest.SendWithSender(client, req, - DoPollForAsynchronous(10*time.Second)) - autorest.Respond(r, - autorest.ByClosing()) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(start) >= delay { - t.Fatalf("azure: DoPollForAsynchronous failed to cancel") - } -} - -func TestDoPollForAsynchronous_ClosesAllNonreturnedResponseBodiesWhenPolling(t *testing.T) { - r1 := newAsynchronousResponse() - b1 := r1.Body.(*mocks.Body) - r2 := newOperationResourceResponse("busy") - b2 := r2.Body.(*mocks.Body) - r3 := newOperationResourceResponse(operationSucceeded) - b3 := r3.Body.(*mocks.Body) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendResponse(r3) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if b1.IsOpen() || b2.IsOpen() || b3.IsOpen() { - t.Fatalf("azure: DoPollForAsynchronous did not close unreturned response bodies") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_LeavesLastResponseBodyOpen(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendResponse(r3) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - b, err := ioutil.ReadAll(r.Body) - if len(b) <= 0 || err != nil { - t.Fatalf("azure: DoPollForAsynchronous did not leave open the body of the last response - Error='%v'", err) - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_DoesNotPollIfOriginalRequestReturnedAnError(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendResponse(r2) - client.SetError(fmt.Errorf("Faux Error")) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() != 1 { - t.Fatalf("azure: DoPollForAsynchronous tried to poll after receiving an error") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_DoesNotPollIfCreatingOperationRequestFails(t *testing.T) { - r1 := newAsynchronousResponse() - mocks.SetResponseHeader(r1, http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestBadURL) - r2 := newOperationResourceResponse("busy") - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() > 1 { - t.Fatalf("azure: DoPollForAsynchronous polled with an invalidly formed operation request") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_StopsPollingAfterAnError(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(2) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() > 3 { - t.Fatalf("azure: DoPollForAsynchronous failed to stop polling after receiving an error") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsPollingError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(newAsynchronousResponse(), 5) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if err == nil { - t.Fatalf("azure: DoPollForAsynchronous failed to return error from polling") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsForStatusAccepted(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Status = "202 Accepted" - r1.StatusCode = http.StatusAccepted - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationCanceled) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsForStatusCreated(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Status = "201 Created" - r1.StatusCode = http.StatusCreated - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationCanceled) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsUntilProvisioningStatusTerminates(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newProvisioningStatusResponse(operationCanceled) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsUntilProvisioningStatusSucceeds(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newProvisioningStatusResponse(operationSucceeded) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsUntilOperationResourceHasTerminated(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationCanceled) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_PollsUntilOperationResourceHasSucceeded(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationSucceeded) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_StopsPollingWhenOperationResourceHasTerminated(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse(operationCanceled) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 2) - - r, _ := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() > 4 { - t.Fatalf("azure: DoPollForAsynchronous failed to stop after receiving a terminated OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsAnErrorForCanceledOperations(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationCanceled) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if err == nil || !strings.Contains(fmt.Sprintf("%v", err), "Canceled") { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error for a canceled OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsAnErrorForFailedOperations(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationFailed) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if err == nil || !strings.Contains(fmt.Sprintf("%v", err), "Failed") { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error for a canceled OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_WithNilURI(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r1.Header.Del(http.CanonicalHeaderKey(autorest.HeaderLocation)) - - r2 := newOperationResourceResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2.Header.Del(http.CanonicalHeaderKey(autorest.HeaderLocation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendResponse(r2) - - req, _ := http.NewRequest("POST", "https://microsoft.com/a/b/c/", mocks.NewBody("")) - r, err := autorest.SendWithSender(client, req, - DoPollForAsynchronous(time.Millisecond)) - - if err == nil { - t.Fatalf("azure: DoPollForAsynchronous failed to return error for nil URI. got: nil; want: Azure Polling Error - Unable to obtain polling URI for POST") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsAnUnknownErrorForFailedOperations(t *testing.T) { - // Return unknown error if error not present in last response - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newProvisioningStatusResponse(operationFailed) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - expected := makeLongRunningOperationErrorString("Unknown", "None") - if err.Error() != expected { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error message for an unknown error. \n expected=%q \n got=%q", - expected, err.Error()) - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsErrorForLastErrorResponse(t *testing.T) { - // Return error code and message if error present in last response - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newAsynchronousResponseWithError("400 Bad Request", http.StatusBadRequest) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - expected := makeLongRunningOperationErrorString("InvalidParameter", "tom-service-DISCOVERY-server-base-v1.core.local' is not a valid captured VHD blob name prefix.") - if err.Error() != expected { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error message for an unknown error. \n expected=%q \n got=%q", - expected, err.Error()) - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsOperationResourceErrorForFailedOperations(t *testing.T) { - // Return Operation resource response with error code and message in last operation resource response - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationFailed) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - expected := makeLongRunningOperationErrorString("BadArgument", "The provided database 'foo' has an invalid username.") - if err.Error() != expected { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error message for a failed Operations. \n expected=%q \n got=%q", - expected, err.Error()) - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_ReturnsErrorForFirstPutRequest(t *testing.T) { - // Return 400 bad response with error code and message in first put - r1 := newAsynchronousResponseWithError("400 Bad Request", http.StatusBadRequest) - client := mocks.NewSender() - client.AppendResponse(r1) - - res, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - if err != nil { - t.Fatalf("azure: DoPollForAsynchronous failed to return an appropriate error message for a failed Operations. \n expected=%q \n got=%q", - errorResponse, err.Error()) - } - - err = autorest.Respond(res, - WithErrorUnlessStatusCode(http.StatusAccepted, http.StatusCreated, http.StatusOK), - autorest.ByClosing()) - - reqError, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - expected := &RequestError{ - ServiceError: &ServiceError{ - Code: "InvalidParameter", - Message: "tom-service-DISCOVERY-server-base-v1.core.local' is not a valid captured VHD blob name prefix.", - }, - DetailedError: autorest.DetailedError{ - StatusCode: 400, - }, - } - if !reflect.DeepEqual(reqError, expected) { - t.Fatalf("azure: wrong error. expected=%q\ngot=%q", expected, reqError) - } - - defer res.Body.Close() - b, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != errorResponse { - t.Fatalf("azure: Response body is wrong. got=%q expected=%q", string(b), errorResponse) - } - -} - -func TestDoPollForAsynchronous_ReturnsNoErrorForSuccessfulOperations(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceErrorResponse(operationSucceeded) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if err != nil { - t.Fatalf("azure: DoPollForAsynchronous returned an error for a successful OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestDoPollForAsynchronous_StopsPollingIfItReceivesAnInvalidOperationResource(t *testing.T) { - r1 := newAsynchronousResponse() - r2 := newOperationResourceResponse("busy") - r3 := newOperationResourceResponse("busy") - r3.Body = mocks.NewBody(operationResourceIllegal) - r4 := newOperationResourceResponse(operationSucceeded) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendAndRepeatResponse(r3, 1) - client.AppendAndRepeatResponse(r4, 1) - - r, err := autorest.SendWithSender(client, mocks.NewRequest(), - DoPollForAsynchronous(time.Millisecond)) - - if client.Attempts() > 4 { - t.Fatalf("azure: DoPollForAsynchronous failed to stop polling after receiving an invalid OperationResource") - } - if err == nil { - t.Fatalf("azure: DoPollForAsynchronous failed to return an error after receving an invalid OperationResource") - } - - autorest.Respond(r, - autorest.ByClosing()) -} - -func TestFuture_PollsUntilProvisioningStatusSucceeds(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newProvisioningStatusResponse(operationSucceeded) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - client := mocks.NewSender() - client.AppendResponse(r1) - client.AppendAndRepeatResponse(r2, 2) - client.AppendResponse(r3) - - future := NewFuture(mocks.NewRequest()) - - for done, err := future.Done(client); !done; done, err = future.Done(client) { - if future.PollingMethod() != PollingLocation { - t.Fatalf("azure: wrong future polling method") - } - if err != nil { - t.Fatalf("azure: TestFuture polling Done failed") - } - delay, ok := future.GetPollingDelay() - if !ok { - t.Fatalf("expected Retry-After value") - } - time.Sleep(delay) - } - - if client.Attempts() < client.NumResponses() { - t.Fatalf("azure: TestFuture stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(future.Response(), - autorest.ByClosing()) -} - -func TestFuture_Marshalling(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAsynchronousResponse()) - - future := NewFuture(mocks.NewRequest()) - done, err := future.Done(client) - if err != nil { - t.Fatalf("azure: TestFuture marshalling Done failed") - } - if done { - t.Fatalf("azure: TestFuture marshalling shouldn't be done") - } - if future.PollingMethod() != PollingAsyncOperation { - t.Fatalf("azure: wrong future polling method") - } - - data, err := json.Marshal(future) - if err != nil { - t.Fatalf("azure: TestFuture failed to marshal") - } - - var future2 Future - err = json.Unmarshal(data, &future2) - if err != nil { - t.Fatalf("azure: TestFuture failed to unmarshal") - } - - if future.ps.Code != future2.ps.Code { - t.Fatalf("azure: TestFuture marshalling codes don't match") - } - if future.ps.Message != future2.ps.Message { - t.Fatalf("azure: TestFuture marshalling messages don't match") - } - if future.ps.PollingMethod != future2.ps.PollingMethod { - t.Fatalf("azure: TestFuture marshalling response formats don't match") - } - if future.ps.State != future2.ps.State { - t.Fatalf("azure: TestFuture marshalling states don't match") - } - if future.ps.URI != future2.ps.URI { - t.Fatalf("azure: TestFuture marshalling URIs don't match") - } -} - -func TestFuture_WaitForCompletion(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3 := newAsynchronousResponseWithError("Internal server error", http.StatusInternalServerError) - r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r3.Header.Del(http.CanonicalHeaderKey("Retry-After")) - r4 := newProvisioningStatusResponse(operationSucceeded) - r4.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendError(errors.New("transient network failure")) - sender.AppendAndRepeatResponse(r2, 2) - sender.AppendResponse(r3) - sender.AppendResponse(r4) - - future := NewFuture(mocks.NewRequest()) - - client := autorest.Client{ - PollingDelay: 1 * time.Second, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - err := future.WaitForCompletion(context.Background(), client) - if err != nil { - t.Fatalf("azure: WaitForCompletion returned non-nil error") - } - - if sender.Attempts() < sender.NumResponses() { - t.Fatalf("azure: TestFuture stopped polling before receiving a terminated OperationResource") - } - - autorest.Respond(future.Response(), - autorest.ByClosing()) -} - -func TestFuture_WaitForCompletionTimedOut(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatResponseWithDelay(r2, 1*time.Second, 5) - - future := NewFuture(mocks.NewRequest()) - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: 2 * time.Second, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 1 * time.Second, - Sender: sender, - } - - err := future.WaitForCompletion(context.Background(), client) - if err == nil { - t.Fatalf("azure: WaitForCompletion returned nil error, should have timed out") - } -} - -func TestFuture_WaitForCompletionRetriesExceeded(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatError(errors.New("transient network failure"), autorest.DefaultRetryAttempts+1) - - future := NewFuture(mocks.NewRequest()) - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: 100 * time.Millisecond, - Sender: sender, - } - - err := future.WaitForCompletion(context.Background(), client) - if err == nil { - t.Fatalf("azure: WaitForCompletion returned nil error, should have errored out") - } -} - -func TestFuture_WaitForCompletionCancelled(t *testing.T) { - r1 := newAsynchronousResponse() - r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - r2 := newProvisioningStatusResponse("busy") - r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - - sender := mocks.NewSender() - sender.AppendResponse(r1) - sender.AppendAndRepeatResponseWithDelay(r2, 1*time.Second, 5) - - future := NewFuture(mocks.NewRequest()) - - client := autorest.Client{ - PollingDelay: autorest.DefaultPollingDelay, - PollingDuration: autorest.DefaultPollingDuration, - RetryAttempts: autorest.DefaultRetryAttempts, - RetryDuration: autorest.DefaultRetryDuration, - Sender: sender, - } - - ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(2 * time.Second) - cancel() - }() - - err := future.WaitForCompletion(ctx, client) - if err == nil { - t.Fatalf("azure: WaitForCompletion returned nil error, should have been cancelled") - } -} - -const ( - operationResourceIllegal = ` - This is not JSON and should fail...badly. - ` - pollingStateFormat = ` - { - "unused" : { - "somefield" : 42 - }, - "properties" : { - "provisioningState": "%s" - } - } - ` - - errorResponse = ` - { - "error" : { - "code" : "InvalidParameter", - "message" : "tom-service-DISCOVERY-server-base-v1.core.local' is not a valid captured VHD blob name prefix." - } - } - ` - - pollingStateEmpty = ` - { - "unused" : { - "somefield" : 42 - }, - "properties" : { - } - } - ` - - operationResourceFormat = ` - { - "id": "/subscriptions/id/locations/westus/operationsStatus/sameguid", - "name": "sameguid", - "status" : "%s", - "startTime" : "2006-01-02T15:04:05Z", - "endTime" : "2006-01-02T16:04:05Z", - "percentComplete" : 50.00, - - "properties" : {} - } - ` - - operationResourceErrorFormat = ` - { - "id": "/subscriptions/id/locations/westus/operationsStatus/sameguid", - "name": "sameguid", - "status" : "%s", - "startTime" : "2006-01-02T15:04:05Z", - "endTime" : "2006-01-02T16:04:05Z", - "percentComplete" : 50.00, - - "properties" : {}, - "error" : { - "code" : "BadArgument", - "message" : "The provided database 'foo' has an invalid username." - } - } - ` -) - -func newAsynchronousResponse() *http.Response { - r := mocks.NewResponseWithStatus("201 Created", http.StatusCreated) - r.Body = mocks.NewBody(fmt.Sprintf(pollingStateFormat, operationInProgress)) - mocks.SetResponseHeader(r, http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestAzureAsyncURL) - mocks.SetResponseHeader(r, http.CanonicalHeaderKey(autorest.HeaderLocation), mocks.TestLocationURL) - mocks.SetRetryHeader(r, retryDelay) - r.Request = mocks.NewRequestForURL(mocks.TestURL) - return r -} - -func newAsynchronousResponseWithError(response string, status int) *http.Response { - r := mocks.NewResponseWithStatus(response, status) - mocks.SetRetryHeader(r, retryDelay) - r.Request = mocks.NewRequestForURL(mocks.TestURL) - r.Body = mocks.NewBody(errorResponse) - return r -} - -func newOperationResourceResponse(status string) *http.Response { - r := newAsynchronousResponse() - r.Body = mocks.NewBody(fmt.Sprintf(operationResourceFormat, status)) - return r -} - -func newOperationResourceErrorResponse(status string) *http.Response { - r := newAsynchronousResponse() - r.Body = mocks.NewBody(fmt.Sprintf(operationResourceErrorFormat, status)) - return r -} - -func newProvisioningStatusResponse(status string) *http.Response { - r := newAsynchronousResponse() - r.Body = mocks.NewBody(fmt.Sprintf(pollingStateFormat, status)) - return r -} - -func makeLongRunningOperationErrorString(code string, message string) string { - return fmt.Sprintf("Long running operation terminated with status 'Failed': Code=%q Message=%q", code, message) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile.go b/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile.go deleted file mode 100644 index 0e59cc77..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package auth - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "strings" - "unicode/utf16" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/azure" - "github.com/dimchansky/utfbom" -) - -// ClientSetup includes authentication details and cloud specific -// parameters for ARM clients -type ClientSetup struct { - *autorest.BearerAuthorizer - File - BaseURI string -} - -// File represents the authentication file -type File struct { - ClientID string `json:"clientId,omitempty"` - ClientSecret string `json:"clientSecret,omitempty"` - SubscriptionID string `json:"subscriptionId,omitempty"` - TenantID string `json:"tenantId,omitempty"` - ActiveDirectoryEndpoint string `json:"activeDirectoryEndpointUrl,omitempty"` - ResourceManagerEndpoint string `json:"resourceManagerEndpointUrl,omitempty"` - GraphResourceID string `json:"activeDirectoryGraphResourceId,omitempty"` - SQLManagementEndpoint string `json:"sqlManagementEndpointUrl,omitempty"` - GalleryEndpoint string `json:"galleryEndpointUrl,omitempty"` - ManagementEndpoint string `json:"managementEndpointUrl,omitempty"` -} - -// GetClientSetup provides an authorizer, base URI, subscriptionID and -// tenantID parameters from an Azure CLI auth file -func GetClientSetup(baseURI string) (auth ClientSetup, err error) { - fileLocation := os.Getenv("AZURE_AUTH_LOCATION") - if fileLocation == "" { - return auth, errors.New("auth file not found. Environment variable AZURE_AUTH_LOCATION is not set") - } - - contents, err := ioutil.ReadFile(fileLocation) - if err != nil { - return - } - - // Auth file might be encoded - decoded, err := decode(contents) - if err != nil { - return - } - - err = json.Unmarshal(decoded, &auth.File) - if err != nil { - return - } - - resource, err := getResourceForToken(auth.File, baseURI) - if err != nil { - return - } - auth.BaseURI = resource - - config, err := adal.NewOAuthConfig(auth.ActiveDirectoryEndpoint, auth.TenantID) - if err != nil { - return - } - - spToken, err := adal.NewServicePrincipalToken(*config, auth.ClientID, auth.ClientSecret, resource) - if err != nil { - return - } - - auth.BearerAuthorizer = autorest.NewBearerAuthorizer(spToken) - return -} - -func decode(b []byte) ([]byte, error) { - reader, enc := utfbom.Skip(bytes.NewReader(b)) - - switch enc { - case utfbom.UTF16LittleEndian: - u16 := make([]uint16, (len(b)/2)-1) - err := binary.Read(reader, binary.LittleEndian, &u16) - if err != nil { - return nil, err - } - return []byte(string(utf16.Decode(u16))), nil - case utfbom.UTF16BigEndian: - u16 := make([]uint16, (len(b)/2)-1) - err := binary.Read(reader, binary.BigEndian, &u16) - if err != nil { - return nil, err - } - return []byte(string(utf16.Decode(u16))), nil - } - return ioutil.ReadAll(reader) -} - -func getResourceForToken(f File, baseURI string) (string, error) { - // Compare dafault base URI from the SDK to the endpoints from the public cloud - // Base URI and token resource are the same string. This func finds the authentication - // file field that matches the SDK base URI. The SDK defines the public cloud - // endpoint as its default base URI - if !strings.HasSuffix(baseURI, "/") { - baseURI += "/" - } - switch baseURI { - case azure.PublicCloud.ServiceManagementEndpoint: - return f.ManagementEndpoint, nil - case azure.PublicCloud.ResourceManagerEndpoint: - return f.ResourceManagerEndpoint, nil - case azure.PublicCloud.ActiveDirectoryEndpoint: - return f.ActiveDirectoryEndpoint, nil - case azure.PublicCloud.GalleryEndpoint: - return f.GalleryEndpoint, nil - case azure.PublicCloud.GraphEndpoint: - return f.GraphResourceID, nil - } - return "", fmt.Errorf("auth: base URI not found in endpoints") -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile_test.go deleted file mode 100644 index c687cf03..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/auth/authfile_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package auth - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "reflect" - "testing" -) - -var ( - expectedFile = File{ - ClientID: "client-id-123", - ClientSecret: "client-secret-456", - SubscriptionID: "sub-id-789", - TenantID: "tenant-id-123", - ActiveDirectoryEndpoint: "https://login.microsoftonline.com", - ResourceManagerEndpoint: "https://management.azure.com/", - GraphResourceID: "https://graph.windows.net/", - SQLManagementEndpoint: "https://management.core.windows.net:8443/", - GalleryEndpoint: "https://gallery.azure.com/", - ManagementEndpoint: "https://management.core.windows.net/", - } -) - -func TestGetClientSetup(t *testing.T) { - os.Setenv("AZURE_AUTH_LOCATION", filepath.Join(getCredsPath(), "credsutf16le.json")) - setup, err := GetClientSetup("https://management.azure.com") - if err != nil { - t.Logf("GetClientSetup failed, got error %v", err) - t.Fail() - } - - if setup.BaseURI != "https://management.azure.com/" { - t.Logf("auth.BaseURI not set correctly, expected 'https://management.azure.com/', got '%s'", setup.BaseURI) - t.Fail() - } - - if !reflect.DeepEqual(expectedFile, setup.File) { - t.Logf("auth.File not set correctly, expected %v, got %v", expectedFile, setup.File) - t.Fail() - } - - if setup.BearerAuthorizer == nil { - t.Log("auth.Authorizer not set correctly, got nil") - t.Fail() - } -} - -func TestDecodeAndUnmarshal(t *testing.T) { - tests := []string{ - "credsutf8.json", - "credsutf16le.json", - "credsutf16be.json", - } - creds := getCredsPath() - for _, test := range tests { - b, err := ioutil.ReadFile(filepath.Join(creds, test)) - if err != nil { - t.Logf("error reading file '%s': %s", test, err) - t.Fail() - } - decoded, err := decode(b) - if err != nil { - t.Logf("error decoding file '%s': %s", test, err) - t.Fail() - } - var got File - err = json.Unmarshal(decoded, &got) - if err != nil { - t.Logf("error unmarshaling file '%s': %s", test, err) - t.Fail() - } - if !reflect.DeepEqual(expectedFile, got) { - t.Logf("unmarshaled map expected %v, got %v", expectedFile, got) - t.Fail() - } - } -} - -func getCredsPath() string { - gopath := os.Getenv("GOPATH") - return filepath.Join(gopath, "src", "github.com", "Azure", "go-autorest", "testdata") -} - -func areMapsEqual(a, b map[string]string) bool { - if len(a) != len(b) { - return false - } - for k := range a { - if a[k] != b[k] { - return false - } - } - return true -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go deleted file mode 100644 index fa183564..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -Package azure provides Azure-specific implementations used with AutoRest. - -See the included examples for more detail. -*/ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strconv" - - "github.com/Azure/go-autorest/autorest" -) - -const ( - // HeaderClientID is the Azure extension header to set a user-specified request ID. - HeaderClientID = "x-ms-client-request-id" - - // HeaderReturnClientID is the Azure extension header to set if the user-specified request ID - // should be included in the response. - HeaderReturnClientID = "x-ms-return-client-request-id" - - // HeaderRequestID is the Azure extension header of the service generated request ID returned - // in the response. - HeaderRequestID = "x-ms-request-id" -) - -// ServiceError encapsulates the error response from an Azure service. -type ServiceError struct { - Code string `json:"code"` - Message string `json:"message"` - Details *[]interface{} `json:"details"` -} - -func (se ServiceError) Error() string { - if se.Details != nil { - d, err := json.Marshal(*(se.Details)) - if err != nil { - return fmt.Sprintf("Code=%q Message=%q Details=%v", se.Code, se.Message, *se.Details) - } - return fmt.Sprintf("Code=%q Message=%q Details=%v", se.Code, se.Message, string(d)) - } - return fmt.Sprintf("Code=%q Message=%q", se.Code, se.Message) -} - -// RequestError describes an error response returned by Azure service. -type RequestError struct { - autorest.DetailedError - - // The error returned by the Azure service. - ServiceError *ServiceError `json:"error"` - - // The request id (from the x-ms-request-id-header) of the request. - RequestID string -} - -// Error returns a human-friendly error message from service error. -func (e RequestError) Error() string { - return fmt.Sprintf("autorest/azure: Service returned an error. Status=%v %v", - e.StatusCode, e.ServiceError) -} - -// IsAzureError returns true if the passed error is an Azure Service error; false otherwise. -func IsAzureError(e error) bool { - _, ok := e.(*RequestError) - return ok -} - -// NewErrorWithError creates a new Error conforming object from the -// passed packageType, method, statusCode of the given resp (UndefinedStatusCode -// if resp is nil), message, and original error. message is treated as a format -// string to which the optional args apply. -func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) RequestError { - if v, ok := original.(*RequestError); ok { - return *v - } - - statusCode := autorest.UndefinedStatusCode - if resp != nil { - statusCode = resp.StatusCode - } - return RequestError{ - DetailedError: autorest.DetailedError{ - Original: original, - PackageType: packageType, - Method: method, - StatusCode: statusCode, - Message: fmt.Sprintf(message, args...), - }, - } -} - -// WithReturningClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-client-request-id whose value is the passed, undecorated UUID (e.g., -// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). It also sets the x-ms-return-client-request-id -// header to true such that UUID accompanies the http.Response. -func WithReturningClientID(uuid string) autorest.PrepareDecorator { - preparer := autorest.CreatePreparer( - WithClientID(uuid), - WithReturnClientID(true)) - - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - return r, err - } - return preparer.Prepare(r) - }) - } -} - -// WithClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-client-request-id whose value is passed, undecorated UUID (e.g., -// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). -func WithClientID(uuid string) autorest.PrepareDecorator { - return autorest.WithHeader(HeaderClientID, uuid) -} - -// WithReturnClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-return-client-request-id whose boolean value indicates if the value of the -// x-ms-client-request-id header should be included in the http.Response. -func WithReturnClientID(b bool) autorest.PrepareDecorator { - return autorest.WithHeader(HeaderReturnClientID, strconv.FormatBool(b)) -} - -// ExtractClientID extracts the client identifier from the x-ms-client-request-id header set on the -// http.Request sent to the service (and returned in the http.Response) -func ExtractClientID(resp *http.Response) string { - return autorest.ExtractHeaderValue(HeaderClientID, resp) -} - -// ExtractRequestID extracts the Azure server generated request identifier from the -// x-ms-request-id header. -func ExtractRequestID(resp *http.Response) string { - return autorest.ExtractHeaderValue(HeaderRequestID, resp) -} - -// WithErrorUnlessStatusCode returns a RespondDecorator that emits an -// azure.RequestError by reading the response body unless the response HTTP status code -// is among the set passed. -// -// If there is a chance service may return responses other than the Azure error -// format and the response cannot be parsed into an error, a decoding error will -// be returned containing the response body. In any case, the Responder will -// return an error if the status code is not satisfied. -// -// If this Responder returns an error, the response body will be replaced with -// an in-memory reader, which needs no further closing. -func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { - return func(r autorest.Responder) autorest.Responder { - return autorest.ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { - var e RequestError - defer resp.Body.Close() - - // Copy and replace the Body in case it does not contain an error object. - // This will leave the Body available to the caller. - b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e) - resp.Body = ioutil.NopCloser(&b) - if decodeErr != nil { - return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr) - } else if e.ServiceError == nil { - // Check if error is unwrapped ServiceError - if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil || e.ServiceError.Message == "" { - e.ServiceError = &ServiceError{ - Code: "Unknown", - Message: "Unknown service error", - } - } - } - - e.RequestID = ExtractRequestID(resp) - if e.StatusCode == nil { - e.StatusCode = resp.StatusCode - } - err = &e - } - return err - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go deleted file mode 100644 index e8bddbbf..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/azure_test.go +++ /dev/null @@ -1,513 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strconv" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - headerAuthorization = "Authorization" - longDelay = 5 * time.Second - retryDelay = 10 * time.Millisecond - testLogPrefix = "azure:" -) - -// Use a Client Inspector to set the request identifier. -func ExampleWithClientID() { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - req, _ := autorest.Prepare(&http.Request{}, - autorest.AsGet(), - autorest.WithBaseURL("https://microsoft.com/a/b/c/")) - - c := autorest.Client{Sender: mocks.NewSender()} - c.RequestInspector = WithReturningClientID(uuid) - - autorest.SendWithSender(c, req) - fmt.Printf("Inspector added the %s header with the value %s\n", - HeaderClientID, req.Header.Get(HeaderClientID)) - fmt.Printf("Inspector added the %s header with the value %s\n", - HeaderReturnClientID, req.Header.Get(HeaderReturnClientID)) - // Output: - // Inspector added the x-ms-client-request-id header with the value 71FDB9F4-5E49-4C12-B266-DE7B4FD999A6 - // Inspector added the x-ms-return-client-request-id header with the value true -} - -func TestWithReturningClientIDReturnsError(t *testing.T) { - var errIn error - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - _, errOut := autorest.Prepare(&http.Request{}, - withErrorPrepareDecorator(&errIn), - WithReturningClientID(uuid)) - - if errOut == nil || errIn != errOut { - t.Fatalf("azure: WithReturningClientID failed to exit early when receiving an error -- expected (%v), received (%v)", - errIn, errOut) - } -} - -func TestWithClientID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - req, _ := autorest.Prepare(&http.Request{}, - WithClientID(uuid)) - - if req.Header.Get(HeaderClientID) != uuid { - t.Fatalf("azure: WithClientID failed to set %s -- expected %s, received %s", - HeaderClientID, uuid, req.Header.Get(HeaderClientID)) - } -} - -func TestWithReturnClientID(t *testing.T) { - b := false - req, _ := autorest.Prepare(&http.Request{}, - WithReturnClientID(b)) - - if req.Header.Get(HeaderReturnClientID) != strconv.FormatBool(b) { - t.Fatalf("azure: WithReturnClientID failed to set %s -- expected %s, received %s", - HeaderClientID, strconv.FormatBool(b), req.Header.Get(HeaderClientID)) - } -} - -func TestExtractClientID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - resp := mocks.NewResponse() - mocks.SetResponseHeader(resp, HeaderClientID, uuid) - - if ExtractClientID(resp) != uuid { - t.Fatalf("azure: ExtractClientID failed to extract the %s -- expected %s, received %s", - HeaderClientID, uuid, ExtractClientID(resp)) - } -} - -func TestExtractRequestID(t *testing.T) { - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - resp := mocks.NewResponse() - mocks.SetResponseHeader(resp, HeaderRequestID, uuid) - - if ExtractRequestID(resp) != uuid { - t.Fatalf("azure: ExtractRequestID failed to extract the %s -- expected %s, received %s", - HeaderRequestID, uuid, ExtractRequestID(resp)) - } -} - -func TestIsAzureError_ReturnsTrueForAzureError(t *testing.T) { - if !IsAzureError(&RequestError{}) { - t.Fatalf("azure: IsAzureError failed to return true for an Azure Service error") - } -} - -func TestIsAzureError_ReturnsFalseForNonAzureError(t *testing.T) { - if IsAzureError(fmt.Errorf("An Error")) { - t.Fatalf("azure: IsAzureError return true for an non-Azure Service error") - } -} - -func TestNewErrorWithError_UsesReponseStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("Error"), "packageType", "method", mocks.NewResponseWithStatus("Forbidden", http.StatusForbidden), "message") - if e.StatusCode != http.StatusForbidden { - t.Fatalf("azure: NewErrorWithError failed to use the Status Code of the passed Response -- expected %v, received %v", http.StatusForbidden, e.StatusCode) - } -} - -func TestNewErrorWithError_ReturnsUnwrappedError(t *testing.T) { - e1 := RequestError{} - e1.ServiceError = &ServiceError{Code: "42", Message: "A Message"} - e1.StatusCode = 200 - e1.RequestID = "A RequestID" - e2 := NewErrorWithError(&e1, "packageType", "method", nil, "message") - - if !reflect.DeepEqual(e1, e2) { - t.Fatalf("azure: NewErrorWithError wrapped an RequestError -- expected %T, received %T", e1, e2) - } -} - -func TestNewErrorWithError_WrapsAnError(t *testing.T) { - e1 := fmt.Errorf("Inner Error") - var e2 interface{} = NewErrorWithError(e1, "packageType", "method", nil, "message") - - if _, ok := e2.(RequestError); !ok { - t.Fatalf("azure: NewErrorWithError failed to wrap a standard error -- received %T", e2) - } -} - -func TestWithErrorUnlessStatusCode_NotAnAzureError(t *testing.T) { - body := ` - - IIS Error page - - Some non-JSON error page - ` - r := mocks.NewResponseWithContent(body) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusBadRequest - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - ok, _ := err.(*RequestError) - if ok != nil { - t.Fatalf("azure: azure.RequestError returned from malformed response: %v", err) - } - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != body { - t.Fatalf("response body is wrong. got=%q exptected=%q", string(b), body) - } -} - -func TestWithErrorUnlessStatusCode_FoundAzureErrorWithoutDetails(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Azure is having trouble right now." - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Azure is having trouble right now.\"" - if !reflect.DeepEqual(expected, azErr.Error()) { - t.Fatalf("azure: service error is not unmarshaled properly.\nexpected=%v\ngot=%v", expected, azErr.Error()) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%d Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_FoundAzureErrorWithDetails(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Azure is having trouble right now.", - "details": [{"code": "conflict1", "message":"error message1"}, - {"code": "conflict2", "message":"error message2"}] - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - if expected := "InternalError"; azErr.ServiceError.Code != expected { - t.Fatalf("azure: wrong error code. expected=%q; got=%q", expected, azErr.ServiceError.Code) - } - if azErr.ServiceError.Message == "" { - t.Fatalf("azure: error message is not unmarshaled properly") - } - b, _ := json.Marshal(*azErr.ServiceError.Details) - if string(b) != `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` { - t.Fatalf("azure: error details is not unmarshaled properly") - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err = ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_NoAzureError(t *testing.T) { - j := `{ - "Status":"NotFound" - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("azure: returned error is not azure.RequestError: %T", err) - } - - expected := &ServiceError{ - Code: "Unknown", - Message: "Unknown service error", - } - - if !reflect.DeepEqual(expected, azErr.ServiceError) { - t.Fatalf("azure: service error is not unmarshaled properly. expected=%q\ngot=%q", expected, azErr.ServiceError) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) - } - if expected := uuid; azErr.RequestID != expected { - t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) - } - - _ = azErr.Error() - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestWithErrorUnlessStatusCode_UnwrappedError(t *testing.T) { - j := `{ - "target": null, - "code": "InternalError", - "message": "Azure is having trouble right now.", - "details": [{"code": "conflict1", "message":"error message1"}, - {"code": "conflict2", "message":"error message2"}], - "innererror": [] -}` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatal("azure: returned nil error for proper error response") - } - - azErr, ok := err.(*RequestError) - if !ok { - t.Fatalf("returned error is not azure.RequestError: %T", err) - } - - if expected := http.StatusInternalServerError; azErr.StatusCode != expected { - t.Logf("Incorrect StatusCode got: %v want: %d", azErr.StatusCode, expected) - t.Fail() - } - - if expected := "Azure is having trouble right now."; azErr.ServiceError.Message != expected { - t.Logf("Incorrect Message\n\tgot: %q\n\twant: %q", azErr.Message, expected) - t.Fail() - } - - if expected := uuid; azErr.RequestID != expected { - t.Logf("Incorrect request ID\n\tgot: %q\n\twant: %q", azErr.RequestID, expected) - t.Fail() - } - - expectedServiceErrorDetails := `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` - if azErr.ServiceError == nil { - t.Logf("`ServiceError` was nil when it shouldn't have been.") - t.Fail() - } else if azErr.ServiceError.Details == nil { - t.Logf("`ServiceError.Details` was nil when it should have been %q", expectedServiceErrorDetails) - t.Fail() - } else if details, _ := json.Marshal(*azErr.ServiceError.Details); expectedServiceErrorDetails != string(details) { - t.Logf("Error detaisl was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(details), expectedServiceErrorDetails) - t.Fail() - } - - // the error body should still be there - defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Error(err) - } - if string(b) != j { - t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) - } - -} - -func TestRequestErrorString_WithError(t *testing.T) { - j := `{ - "error": { - "code": "InternalError", - "message": "Conflict", - "details": [{"code": "conflict1", "message":"error message1"}] - } - }` - uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" - r := mocks.NewResponseWithContent(j) - mocks.SetResponseHeader(r, HeaderRequestID, uuid) - r.Request = mocks.NewRequest() - r.StatusCode = http.StatusInternalServerError - r.Status = http.StatusText(r.StatusCode) - - err := autorest.Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByClosing()) - - if err == nil { - t.Fatalf("azure: returned nil error for proper error response") - } - azErr, _ := err.(*RequestError) - expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}]" - if expected != azErr.Error() { - t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error()) - } -} - -func withErrorPrepareDecorator(e *error) autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - *e = fmt.Errorf("azure: Faux Prepare Error") - return r, *e - }) - } -} - -func withAsyncResponseDecorator(n int) autorest.SendDecorator { - i := 0 - return func(s autorest.Sender) autorest.Sender { - return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil { - if i < n { - resp.StatusCode = http.StatusCreated - resp.Header = http.Header{} - resp.Header.Add(http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestURL) - i++ - } else { - resp.StatusCode = http.StatusOK - resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) - } - } - return resp, err - }) - } -} - -type mockAuthorizer struct{} - -func (ma mockAuthorizer) WithAuthorization() autorest.PrepareDecorator { - return autorest.WithHeader(headerAuthorization, mocks.TestAuthorizationHeader) -} - -type mockFailingAuthorizer struct{} - -func (mfa mockFailingAuthorizer) WithAuthorization() autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error") - }) - } -} - -type mockInspector struct { - wasInvoked bool -} - -func (mi *mockInspector) WithInspection() autorest.PrepareDecorator { - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - mi.wasInvoked = true - return p.Prepare(r) - }) - } -} - -func (mi *mockInspector) ByInspecting() autorest.RespondDecorator { - return func(r autorest.Responder) autorest.Responder { - return autorest.ResponderFunc(func(resp *http.Response) error { - mi.wasInvoked = true - return r.Respond(resp) - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/cli/profile.go b/vendor/github.com/Azure/go-autorest/autorest/azure/cli/profile.go deleted file mode 100644 index 3e226fe9..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/cli/profile.go +++ /dev/null @@ -1,65 +0,0 @@ -package cli - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - - "github.com/dimchansky/utfbom" - "github.com/mitchellh/go-homedir" -) - -// Profile represents a Profile from the Azure CLI -type Profile struct { - InstallationID string `json:"installationId"` - Subscriptions []Subscription `json:"subscriptions"` -} - -// Subscription represents a Subscription from the Azure CLI -type Subscription struct { - EnvironmentName string `json:"environmentName"` - ID string `json:"id"` - IsDefault bool `json:"isDefault"` - Name string `json:"name"` - State string `json:"state"` - TenantID string `json:"tenantId"` -} - -// ProfilePath returns the path where the Azure Profile is stored from the Azure CLI -func ProfilePath() (string, error) { - return homedir.Expand("~/.azure/azureProfile.json") -} - -// LoadProfile restores a Profile object from a file located at 'path'. -func LoadProfile(path string) (result Profile, err error) { - var contents []byte - contents, err = ioutil.ReadFile(path) - if err != nil { - err = fmt.Errorf("failed to open file (%s) while loading token: %v", path, err) - return - } - reader := utfbom.SkipOnly(bytes.NewReader(contents)) - - dec := json.NewDecoder(reader) - if err = dec.Decode(&result); err != nil { - err = fmt.Errorf("failed to decode contents of file (%s) into a Profile representation: %v", path, err) - return - } - - return -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/cli/token.go b/vendor/github.com/Azure/go-autorest/autorest/azure/cli/token.go deleted file mode 100644 index 83b81c34..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/cli/token.go +++ /dev/null @@ -1,114 +0,0 @@ -package cli - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "os" - "strconv" - "time" - - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/date" - "github.com/mitchellh/go-homedir" -) - -// Token represents an AccessToken from the Azure CLI -type Token struct { - AccessToken string `json:"accessToken"` - Authority string `json:"_authority"` - ClientID string `json:"_clientId"` - ExpiresOn string `json:"expiresOn"` - IdentityProvider string `json:"identityProvider"` - IsMRRT bool `json:"isMRRT"` - RefreshToken string `json:"refreshToken"` - Resource string `json:"resource"` - TokenType string `json:"tokenType"` - UserID string `json:"userId"` -} - -// ToADALToken converts an Azure CLI `Token`` to an `adal.Token`` -func (t Token) ToADALToken() (converted adal.Token, err error) { - tokenExpirationDate, err := ParseExpirationDate(t.ExpiresOn) - if err != nil { - err = fmt.Errorf("Error parsing Token Expiration Date %q: %+v", t.ExpiresOn, err) - return - } - - difference := tokenExpirationDate.Sub(date.UnixEpoch()) - - converted = adal.Token{ - AccessToken: t.AccessToken, - Type: t.TokenType, - ExpiresIn: "3600", - ExpiresOn: strconv.Itoa(int(difference.Seconds())), - RefreshToken: t.RefreshToken, - Resource: t.Resource, - } - return -} - -// AccessTokensPath returns the path where access tokens are stored from the Azure CLI -// TODO(#199): add unit test. -func AccessTokensPath() (string, error) { - // Azure-CLI allows user to customize the path of access tokens thorugh environment variable. - var accessTokenPath = os.Getenv("AZURE_ACCESS_TOKEN_FILE") - var err error - - // Fallback logic to default path on non-cloud-shell environment. - // TODO(#200): remove the dependency on hard-coding path. - if accessTokenPath == "" { - accessTokenPath, err = homedir.Expand("~/.azure/accessTokens.json") - } - - return accessTokenPath, err -} - -// ParseExpirationDate parses either a Azure CLI or CloudShell date into a time object -func ParseExpirationDate(input string) (*time.Time, error) { - // CloudShell (and potentially the Azure CLI in future) - expirationDate, cloudShellErr := time.Parse(time.RFC3339, input) - if cloudShellErr != nil { - // Azure CLI (Python) e.g. 2017-08-31 19:48:57.998857 (plus the local timezone) - const cliFormat = "2006-01-02 15:04:05.999999" - expirationDate, cliErr := time.ParseInLocation(cliFormat, input, time.Local) - if cliErr == nil { - return &expirationDate, nil - } - - return nil, fmt.Errorf("Error parsing expiration date %q.\n\nCloudShell Error: \n%+v\n\nCLI Error:\n%+v", input, cloudShellErr, cliErr) - } - - return &expirationDate, nil -} - -// LoadTokens restores a set of Token objects from a file located at 'path'. -func LoadTokens(path string) ([]Token, error) { - file, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("failed to open file (%s) while loading token: %v", path, err) - } - defer file.Close() - - var tokens []Token - - dec := json.NewDecoder(file) - if err = dec.Decode(&tokens); err != nil { - return nil, fmt.Errorf("failed to decode contents of file (%s) into a `cli.Token` representation: %v", path, err) - } - - return tokens, nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go deleted file mode 100644 index 0916b14f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go +++ /dev/null @@ -1,181 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "strings" -) - -// EnvironmentFilepathName captures the name of the environment variable containing the path to the file -// to be used while populating the Azure Environment. -const EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH" - -var environments = map[string]Environment{ - "AZURECHINACLOUD": ChinaCloud, - "AZUREGERMANCLOUD": GermanCloud, - "AZUREPUBLICCLOUD": PublicCloud, - "AZUREUSGOVERNMENTCLOUD": USGovernmentCloud, -} - -// Environment represents a set of endpoints for each of Azure's Clouds. -type Environment struct { - Name string `json:"name"` - ManagementPortalURL string `json:"managementPortalURL"` - PublishSettingsURL string `json:"publishSettingsURL"` - ServiceManagementEndpoint string `json:"serviceManagementEndpoint"` - ResourceManagerEndpoint string `json:"resourceManagerEndpoint"` - ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"` - GalleryEndpoint string `json:"galleryEndpoint"` - KeyVaultEndpoint string `json:"keyVaultEndpoint"` - GraphEndpoint string `json:"graphEndpoint"` - ServiceBusEndpoint string `json:"serviceBusEndpoint"` - StorageEndpointSuffix string `json:"storageEndpointSuffix"` - SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"` - TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"` - KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"` - ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"` - ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"` - ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"` - ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"` -} - -var ( - // PublicCloud is the default public Azure cloud environment - PublicCloud = Environment{ - Name: "AzurePublicCloud", - ManagementPortalURL: "https://manage.windowsazure.com/", - PublishSettingsURL: "https://manage.windowsazure.com/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.windows.net/", - ResourceManagerEndpoint: "https://management.azure.com/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.com/", - GalleryEndpoint: "https://gallery.azure.com/", - KeyVaultEndpoint: "https://vault.azure.net/", - GraphEndpoint: "https://graph.windows.net/", - ServiceBusEndpoint: "https://servicebus.windows.net/", - StorageEndpointSuffix: "core.windows.net", - SQLDatabaseDNSSuffix: "database.windows.net", - TrafficManagerDNSSuffix: "trafficmanager.net", - KeyVaultDNSSuffix: "vault.azure.net", - ServiceBusEndpointSuffix: "servicebus.windows.net", - ServiceManagementVMDNSSuffix: "cloudapp.net", - ResourceManagerVMDNSSuffix: "cloudapp.azure.com", - ContainerRegistryDNSSuffix: "azurecr.io", - } - - // USGovernmentCloud is the cloud environment for the US Government - USGovernmentCloud = Environment{ - Name: "AzureUSGovernmentCloud", - ManagementPortalURL: "https://manage.windowsazure.us/", - PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/", - ResourceManagerEndpoint: "https://management.usgovcloudapi.net/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.us/", - GalleryEndpoint: "https://gallery.usgovcloudapi.net/", - KeyVaultEndpoint: "https://vault.usgovcloudapi.net/", - GraphEndpoint: "https://graph.windows.net/", - ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/", - StorageEndpointSuffix: "core.usgovcloudapi.net", - SQLDatabaseDNSSuffix: "database.usgovcloudapi.net", - TrafficManagerDNSSuffix: "usgovtrafficmanager.net", - KeyVaultDNSSuffix: "vault.usgovcloudapi.net", - ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net", - ServiceManagementVMDNSSuffix: "usgovcloudapp.net", - ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us", - ContainerRegistryDNSSuffix: "azurecr.io", - } - - // ChinaCloud is the cloud environment operated in China - ChinaCloud = Environment{ - Name: "AzureChinaCloud", - ManagementPortalURL: "https://manage.chinacloudapi.com/", - PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/", - ResourceManagerEndpoint: "https://management.chinacloudapi.cn/", - ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/", - GalleryEndpoint: "https://gallery.chinacloudapi.cn/", - KeyVaultEndpoint: "https://vault.azure.cn/", - GraphEndpoint: "https://graph.chinacloudapi.cn/", - ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/", - StorageEndpointSuffix: "core.chinacloudapi.cn", - SQLDatabaseDNSSuffix: "database.chinacloudapi.cn", - TrafficManagerDNSSuffix: "trafficmanager.cn", - KeyVaultDNSSuffix: "vault.azure.cn", - ServiceBusEndpointSuffix: "servicebus.chinacloudapi.cn", - ServiceManagementVMDNSSuffix: "chinacloudapp.cn", - ResourceManagerVMDNSSuffix: "cloudapp.azure.cn", - ContainerRegistryDNSSuffix: "azurecr.io", - } - - // GermanCloud is the cloud environment operated in Germany - GermanCloud = Environment{ - Name: "AzureGermanCloud", - ManagementPortalURL: "http://portal.microsoftazure.de/", - PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.cloudapi.de/", - ResourceManagerEndpoint: "https://management.microsoftazure.de/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.de/", - GalleryEndpoint: "https://gallery.cloudapi.de/", - KeyVaultEndpoint: "https://vault.microsoftazure.de/", - GraphEndpoint: "https://graph.cloudapi.de/", - ServiceBusEndpoint: "https://servicebus.cloudapi.de/", - StorageEndpointSuffix: "core.cloudapi.de", - SQLDatabaseDNSSuffix: "database.cloudapi.de", - TrafficManagerDNSSuffix: "azuretrafficmanager.de", - KeyVaultDNSSuffix: "vault.microsoftazure.de", - ServiceBusEndpointSuffix: "servicebus.cloudapi.de", - ServiceManagementVMDNSSuffix: "azurecloudapp.de", - ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de", - ContainerRegistryDNSSuffix: "azurecr.io", - } -) - -// EnvironmentFromName returns an Environment based on the common name specified. -func EnvironmentFromName(name string) (Environment, error) { - // IMPORTANT - // As per @radhikagupta5: - // This is technical debt, fundamentally here because Kubernetes is not currently accepting - // contributions to the providers. Once that is an option, the provider should be updated to - // directly call `EnvironmentFromFile`. Until then, we rely on dispatching Azure Stack environment creation - // from this method based on the name that is provided to us. - if strings.EqualFold(name, "AZURESTACKCLOUD") { - return EnvironmentFromFile(os.Getenv(EnvironmentFilepathName)) - } - - name = strings.ToUpper(name) - env, ok := environments[name] - if !ok { - return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name) - } - - return env, nil -} - -// EnvironmentFromFile loads an Environment from a configuration file available on disk. -// This function is particularly useful in the Hybrid Cloud model, where one must define their own -// endpoints. -func EnvironmentFromFile(location string) (unmarshaled Environment, err error) { - fileContents, err := ioutil.ReadFile(location) - if err != nil { - return - } - - err = json.Unmarshal(fileContents, &unmarshaled) - - return -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go deleted file mode 100644 index 98162c3f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// test -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "os" - "path" - "path/filepath" - "runtime" - "testing" -) - -// This correlates to the expected contents of ./testdata/test_environment_1.json -var testEnvironment1 = Environment{ - Name: "--unit-test--", - ManagementPortalURL: "--management-portal-url", - PublishSettingsURL: "--publish-settings-url--", - ServiceManagementEndpoint: "--service-management-endpoint--", - ResourceManagerEndpoint: "--resource-management-endpoint--", - ActiveDirectoryEndpoint: "--active-directory-endpoint--", - GalleryEndpoint: "--gallery-endpoint--", - KeyVaultEndpoint: "--key-vault--endpoint--", - GraphEndpoint: "--graph-endpoint--", - StorageEndpointSuffix: "--storage-endpoint-suffix--", - SQLDatabaseDNSSuffix: "--sql-database-dns-suffix--", - TrafficManagerDNSSuffix: "--traffic-manager-dns-suffix--", - KeyVaultDNSSuffix: "--key-vault-dns-suffix--", - ServiceBusEndpointSuffix: "--service-bus-endpoint-suffix--", - ServiceManagementVMDNSSuffix: "--asm-vm-dns-suffix--", - ResourceManagerVMDNSSuffix: "--arm-vm-dns-suffix--", - ContainerRegistryDNSSuffix: "--container-registry-dns-suffix--", -} - -func TestEnvironment_EnvironmentFromFile(t *testing.T) { - got, err := EnvironmentFromFile(filepath.Join("testdata", "test_environment_1.json")) - if err != nil { - t.Error(err) - } - - if got != testEnvironment1 { - t.Logf("got: %v want: %v", got, testEnvironment1) - t.Fail() - } -} - -func TestEnvironment_EnvironmentFromName_Stack(t *testing.T) { - _, currentFile, _, _ := runtime.Caller(0) - prevEnvFilepathValue := os.Getenv(EnvironmentFilepathName) - os.Setenv(EnvironmentFilepathName, filepath.Join(path.Dir(currentFile), "testdata", "test_environment_1.json")) - defer os.Setenv(EnvironmentFilepathName, prevEnvFilepathValue) - - got, err := EnvironmentFromName("AZURESTACKCLOUD") - if err != nil { - t.Error(err) - } - - if got != testEnvironment1 { - t.Logf("got: %v want: %v", got, testEnvironment1) - t.Fail() - } -} - -func TestEnvironmentFromName(t *testing.T) { - name := "azurechinacloud" - if env, _ := EnvironmentFromName(name); env != ChinaCloud { - t.Errorf("Expected to get ChinaCloud for %q", name) - } - - name = "AzureChinaCloud" - if env, _ := EnvironmentFromName(name); env != ChinaCloud { - t.Errorf("Expected to get ChinaCloud for %q", name) - } - - name = "azuregermancloud" - if env, _ := EnvironmentFromName(name); env != GermanCloud { - t.Errorf("Expected to get GermanCloud for %q", name) - } - - name = "AzureGermanCloud" - if env, _ := EnvironmentFromName(name); env != GermanCloud { - t.Errorf("Expected to get GermanCloud for %q", name) - } - - name = "azurepubliccloud" - if env, _ := EnvironmentFromName(name); env != PublicCloud { - t.Errorf("Expected to get PublicCloud for %q", name) - } - - name = "AzurePublicCloud" - if env, _ := EnvironmentFromName(name); env != PublicCloud { - t.Errorf("Expected to get PublicCloud for %q", name) - } - - name = "azureusgovernmentcloud" - if env, _ := EnvironmentFromName(name); env != USGovernmentCloud { - t.Errorf("Expected to get USGovernmentCloud for %q", name) - } - - name = "AzureUSGovernmentCloud" - if env, _ := EnvironmentFromName(name); env != USGovernmentCloud { - t.Errorf("Expected to get USGovernmentCloud for %q", name) - } - - name = "thisisnotarealcloudenv" - if _, err := EnvironmentFromName(name); err == nil { - t.Errorf("Expected to get an error for %q", name) - } -} - -func TestDeserializeEnvironment(t *testing.T) { - env := `{ - "name": "--name--", - "ActiveDirectoryEndpoint": "--active-directory-endpoint--", - "galleryEndpoint": "--gallery-endpoint--", - "graphEndpoint": "--graph-endpoint--", - "serviceBusEndpoint": "--service-bus-endpoint--", - "keyVaultDNSSuffix": "--key-vault-dns-suffix--", - "keyVaultEndpoint": "--key-vault-endpoint--", - "managementPortalURL": "--management-portal-url--", - "publishSettingsURL": "--publish-settings-url--", - "resourceManagerEndpoint": "--resource-manager-endpoint--", - "serviceBusEndpointSuffix": "--service-bus-endpoint-suffix--", - "serviceManagementEndpoint": "--service-management-endpoint--", - "sqlDatabaseDNSSuffix": "--sql-database-dns-suffix--", - "storageEndpointSuffix": "--storage-endpoint-suffix--", - "trafficManagerDNSSuffix": "--traffic-manager-dns-suffix--", - "serviceManagementVMDNSSuffix": "--asm-vm-dns-suffix--", - "resourceManagerVMDNSSuffix": "--arm-vm-dns-suffix--", - "containerRegistryDNSSuffix": "--container-registry-dns-suffix--" - }` - - testSubject := Environment{} - err := json.Unmarshal([]byte(env), &testSubject) - if err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - - if "--name--" != testSubject.Name { - t.Errorf("Expected Name to be \"--name--\", but got %q", testSubject.Name) - } - if "--management-portal-url--" != testSubject.ManagementPortalURL { - t.Errorf("Expected ManagementPortalURL to be \"--management-portal-url--\", but got %q", testSubject.ManagementPortalURL) - } - if "--publish-settings-url--" != testSubject.PublishSettingsURL { - t.Errorf("Expected PublishSettingsURL to be \"--publish-settings-url--\", but got %q", testSubject.PublishSettingsURL) - } - if "--service-management-endpoint--" != testSubject.ServiceManagementEndpoint { - t.Errorf("Expected ServiceManagementEndpoint to be \"--service-management-endpoint--\", but got %q", testSubject.ServiceManagementEndpoint) - } - if "--resource-manager-endpoint--" != testSubject.ResourceManagerEndpoint { - t.Errorf("Expected ResourceManagerEndpoint to be \"--resource-manager-endpoint--\", but got %q", testSubject.ResourceManagerEndpoint) - } - if "--active-directory-endpoint--" != testSubject.ActiveDirectoryEndpoint { - t.Errorf("Expected ActiveDirectoryEndpoint to be \"--active-directory-endpoint--\", but got %q", testSubject.ActiveDirectoryEndpoint) - } - if "--gallery-endpoint--" != testSubject.GalleryEndpoint { - t.Errorf("Expected GalleryEndpoint to be \"--gallery-endpoint--\", but got %q", testSubject.GalleryEndpoint) - } - if "--key-vault-endpoint--" != testSubject.KeyVaultEndpoint { - t.Errorf("Expected KeyVaultEndpoint to be \"--key-vault-endpoint--\", but got %q", testSubject.KeyVaultEndpoint) - } - if "--service-bus-endpoint--" != testSubject.ServiceBusEndpoint { - t.Errorf("Expected ServiceBusEndpoint to be \"--service-bus-endpoint--\", but goet %q", testSubject.ServiceBusEndpoint) - } - if "--graph-endpoint--" != testSubject.GraphEndpoint { - t.Errorf("Expected GraphEndpoint to be \"--graph-endpoint--\", but got %q", testSubject.GraphEndpoint) - } - if "--storage-endpoint-suffix--" != testSubject.StorageEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--storage-endpoint-suffix--\", but got %q", testSubject.StorageEndpointSuffix) - } - if "--sql-database-dns-suffix--" != testSubject.SQLDatabaseDNSSuffix { - t.Errorf("Expected sql-database-dns-suffix to be \"--sql-database-dns-suffix--\", but got %q", testSubject.SQLDatabaseDNSSuffix) - } - if "--key-vault-dns-suffix--" != testSubject.KeyVaultDNSSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--key-vault-dns-suffix--\", but got %q", testSubject.KeyVaultDNSSuffix) - } - if "--service-bus-endpoint-suffix--" != testSubject.ServiceBusEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be \"--service-bus-endpoint-suffix--\", but got %q", testSubject.ServiceBusEndpointSuffix) - } - if "--asm-vm-dns-suffix--" != testSubject.ServiceManagementVMDNSSuffix { - t.Errorf("Expected ServiceManagementVMDNSSuffix to be \"--asm-vm-dns-suffix--\", but got %q", testSubject.ServiceManagementVMDNSSuffix) - } - if "--arm-vm-dns-suffix--" != testSubject.ResourceManagerVMDNSSuffix { - t.Errorf("Expected ResourceManagerVMDNSSuffix to be \"--arm-vm-dns-suffix--\", but got %q", testSubject.ResourceManagerVMDNSSuffix) - } - if "--container-registry-dns-suffix--" != testSubject.ContainerRegistryDNSSuffix { - t.Errorf("Expected ContainerRegistryDNSSuffix to be \"--container-registry-dns-suffix--\", but got %q", testSubject.ContainerRegistryDNSSuffix) - } -} - -func TestRoundTripSerialization(t *testing.T) { - env := Environment{ - Name: "--unit-test--", - ManagementPortalURL: "--management-portal-url", - PublishSettingsURL: "--publish-settings-url--", - ServiceManagementEndpoint: "--service-management-endpoint--", - ResourceManagerEndpoint: "--resource-management-endpoint--", - ActiveDirectoryEndpoint: "--active-directory-endpoint--", - GalleryEndpoint: "--gallery-endpoint--", - KeyVaultEndpoint: "--key-vault--endpoint--", - GraphEndpoint: "--graph-endpoint--", - ServiceBusEndpoint: "--service-bus-endpoint--", - StorageEndpointSuffix: "--storage-endpoint-suffix--", - SQLDatabaseDNSSuffix: "--sql-database-dns-suffix--", - TrafficManagerDNSSuffix: "--traffic-manager-dns-suffix--", - KeyVaultDNSSuffix: "--key-vault-dns-suffix--", - ServiceBusEndpointSuffix: "--service-bus-endpoint-suffix--", - ServiceManagementVMDNSSuffix: "--asm-vm-dns-suffix--", - ResourceManagerVMDNSSuffix: "--arm-vm-dns-suffix--", - ContainerRegistryDNSSuffix: "--container-registry-dns-suffix--", - } - - bytes, err := json.Marshal(env) - if err != nil { - t.Fatalf("failed to marshal: %s", err) - } - - testSubject := Environment{} - err = json.Unmarshal(bytes, &testSubject) - if err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - - if env.Name != testSubject.Name { - t.Errorf("Expected Name to be %q, but got %q", env.Name, testSubject.Name) - } - if env.ManagementPortalURL != testSubject.ManagementPortalURL { - t.Errorf("Expected ManagementPortalURL to be %q, but got %q", env.ManagementPortalURL, testSubject.ManagementPortalURL) - } - if env.PublishSettingsURL != testSubject.PublishSettingsURL { - t.Errorf("Expected PublishSettingsURL to be %q, but got %q", env.PublishSettingsURL, testSubject.PublishSettingsURL) - } - if env.ServiceManagementEndpoint != testSubject.ServiceManagementEndpoint { - t.Errorf("Expected ServiceManagementEndpoint to be %q, but got %q", env.ServiceManagementEndpoint, testSubject.ServiceManagementEndpoint) - } - if env.ResourceManagerEndpoint != testSubject.ResourceManagerEndpoint { - t.Errorf("Expected ResourceManagerEndpoint to be %q, but got %q", env.ResourceManagerEndpoint, testSubject.ResourceManagerEndpoint) - } - if env.ActiveDirectoryEndpoint != testSubject.ActiveDirectoryEndpoint { - t.Errorf("Expected ActiveDirectoryEndpoint to be %q, but got %q", env.ActiveDirectoryEndpoint, testSubject.ActiveDirectoryEndpoint) - } - if env.GalleryEndpoint != testSubject.GalleryEndpoint { - t.Errorf("Expected GalleryEndpoint to be %q, but got %q", env.GalleryEndpoint, testSubject.GalleryEndpoint) - } - if env.ServiceBusEndpoint != testSubject.ServiceBusEndpoint { - t.Errorf("Expected ServiceBusEnpoint to be %q, but got %q", env.ServiceBusEndpoint, testSubject.ServiceBusEndpoint) - } - if env.KeyVaultEndpoint != testSubject.KeyVaultEndpoint { - t.Errorf("Expected KeyVaultEndpoint to be %q, but got %q", env.KeyVaultEndpoint, testSubject.KeyVaultEndpoint) - } - if env.GraphEndpoint != testSubject.GraphEndpoint { - t.Errorf("Expected GraphEndpoint to be %q, but got %q", env.GraphEndpoint, testSubject.GraphEndpoint) - } - if env.StorageEndpointSuffix != testSubject.StorageEndpointSuffix { - t.Errorf("Expected StorageEndpointSuffix to be %q, but got %q", env.StorageEndpointSuffix, testSubject.StorageEndpointSuffix) - } - if env.SQLDatabaseDNSSuffix != testSubject.SQLDatabaseDNSSuffix { - t.Errorf("Expected SQLDatabaseDNSSuffix to be %q, but got %q", env.SQLDatabaseDNSSuffix, testSubject.SQLDatabaseDNSSuffix) - } - if env.TrafficManagerDNSSuffix != testSubject.TrafficManagerDNSSuffix { - t.Errorf("Expected TrafficManagerDNSSuffix to be %q, but got %q", env.TrafficManagerDNSSuffix, testSubject.TrafficManagerDNSSuffix) - } - if env.KeyVaultDNSSuffix != testSubject.KeyVaultDNSSuffix { - t.Errorf("Expected KeyVaultDNSSuffix to be %q, but got %q", env.KeyVaultDNSSuffix, testSubject.KeyVaultDNSSuffix) - } - if env.ServiceBusEndpointSuffix != testSubject.ServiceBusEndpointSuffix { - t.Errorf("Expected ServiceBusEndpointSuffix to be %q, but got %q", env.ServiceBusEndpointSuffix, testSubject.ServiceBusEndpointSuffix) - } - if env.ServiceManagementVMDNSSuffix != testSubject.ServiceManagementVMDNSSuffix { - t.Errorf("Expected ServiceManagementVMDNSSuffix to be %q, but got %q", env.ServiceManagementVMDNSSuffix, testSubject.ServiceManagementVMDNSSuffix) - } - if env.ResourceManagerVMDNSSuffix != testSubject.ResourceManagerVMDNSSuffix { - t.Errorf("Expected ResourceManagerVMDNSSuffix to be %q, but got %q", env.ResourceManagerVMDNSSuffix, testSubject.ResourceManagerVMDNSSuffix) - } - if env.ContainerRegistryDNSSuffix != testSubject.ContainerRegistryDNSSuffix { - t.Errorf("Expected ContainerRegistryDNSSuffix to be %q, but got %q", env.ContainerRegistryDNSSuffix, testSubject.ContainerRegistryDNSSuffix) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/example/README.md b/vendor/github.com/Azure/go-autorest/autorest/azure/example/README.md deleted file mode 100644 index b87e173f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/example/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# autorest azure example - -## Usage (device mode) - -This shows how to use the example for device auth. - -1. Execute this. It will save your token to /tmp/azure-example-token: - - ``` - ./example -tenantId "13de0a15-b5db-44b9-b682-b4ba82afbd29" -subscriptionId "aff271ee-e9be-4441-b9bb-42f5af4cbaeb" -mode "device" -tokenCachePath "/tmp/azure-example-token" - ``` - -2. Execute it again, it will load the token from cache and not prompt for auth again. - -## Usage (certificate mode) - -This example covers how to make an authenticated call to the Azure Resource Manager APIs, using certificate-based authentication. - -0. Export some required variables - - ``` - export SUBSCRIPTION_ID="aff271ee-e9be-4441-b9bb-42f5af4cbaeb" - export TENANT_ID="13de0a15-b5db-44b9-b682-b4ba82afbd29" - export RESOURCE_GROUP="someresourcegroup" - ``` - - * replace both values with your own - -1. Create a private key - - ``` - openssl genrsa -out "example.key" 2048 - ``` - - - -2. Create the certificate - - ``` - openssl req -new -key "example.key" -subj "/CN=example" -out "example.csr" - - openssl x509 -req -in "example.csr" -signkey "example.key" -out "example.crt" -days 10000 - ``` - - - -3. Create the PKCS12 version of the certificate (with no password) - - ``` - openssl pkcs12 -export -out "example.pfx" -inkey "example.key" -in "example.crt" -passout pass: - ``` - - - -4. Register a new Azure AD Application with the certificate contents - - ``` - certificateContents="$(tail -n+2 "example.key" | head -n-1)" - - azure ad app create \ - --name "example-azuread-app" \ - --home-page="http://example-azuread-app/home" \ - --identifier-uris "http://example-azuread-app/app" \ - --key-usage "Verify" \ - --end-date "2020-01-01" \ - --key-value "${certificateContents}" - ``` - - - -5. Create a new service principal using the "Application Id" from the previous step - - ``` - azure ad sp create "APPLICATION_ID" - ``` - - * Replace APPLICATION_ID with the "Application Id" returned in step 4 - - - -6. Grant your service principal necessary permissions - - ``` - azure role assignment create \ - --resource-group "${RESOURCE_GROUP}" \ - --roleName "Contributor" \ - --subscription "${SUBSCRIPTION_ID}" \ - --spn "http://example-azuread-app/app" - ``` - - * Replace SUBSCRIPTION_ID with your subscription id - * Replace RESOURCE_GROUP with the resource group for the assignment - * Ensure that the `spn` parameter matches an `identifier-url` from Step 4 - - - -7. Run this example app to see your resource groups - - ``` - go run main.go \ - --tenantId="${TENANT_ID}" \ - --subscriptionId="${SUBSCRIPTION_ID}" \ - --applicationId="http://example-azuread-app/app" \ - --certificatePath="certificate.pfx" - ``` - - -You should see something like this as output: - -``` -2015/11/08 18:28:39 Using these settings: -2015/11/08 18:28:39 * certificatePath: certificate.pfx -2015/11/08 18:28:39 * applicationID: http://example-azuread-app/app -2015/11/08 18:28:39 * tenantID: 13de0a15-b5db-44b9-b682-b4ba82afbd29 -2015/11/08 18:28:39 * subscriptionID: aff271ee-e9be-4441-b9bb-42f5af4cbaeb -2015/11/08 18:28:39 loading certificate... -2015/11/08 18:28:39 retrieve oauth token... -2015/11/08 18:28:39 querying the list of resource groups... -2015/11/08 18:28:50 -2015/11/08 18:28:50 Groups: {"value":[{"id":"/subscriptions/aff271ee-e9be-4441-b9bb-42f5af4cbaeb/resourceGroups/kube-66f30810","name":"kube-66f30810","location":"westus","tags":{},"properties":{"provisioningState":"Succeeded"}}]} -``` - - - -## Notes - -You may need to wait sometime between executing step 4, step 5 and step 6. If you issue those requests too quickly, you might hit an AD server that is not consistent with the server where the resource was created. diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/example/main.go b/vendor/github.com/Azure/go-autorest/autorest/azure/example/main.go deleted file mode 100644 index f887097f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/example/main.go +++ /dev/null @@ -1,272 +0,0 @@ -package main - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/json" - "flag" - "fmt" - "io/ioutil" - "log" - "net/http" - "strings" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/azure" - "golang.org/x/crypto/pkcs12" -) - -const ( - resourceGroupURLTemplate = "https://management.azure.com" - apiVersion = "2015-01-01" - nativeAppClientID = "a87032a7-203c-4bf7-913c-44c50d23409a" - resource = "https://management.core.windows.net/" -) - -var ( - mode string - tenantID string - subscriptionID string - applicationID string - - tokenCachePath string - forceRefresh bool - impatient bool - - certificatePath string -) - -func init() { - flag.StringVar(&mode, "mode", "device", "mode of operation for SPT creation") - flag.StringVar(&certificatePath, "certificatePath", "", "path to pk12/pfx certificate") - flag.StringVar(&applicationID, "applicationId", "", "application id") - flag.StringVar(&tenantID, "tenantId", "", "tenant id") - flag.StringVar(&subscriptionID, "subscriptionId", "", "subscription id") - flag.StringVar(&tokenCachePath, "tokenCachePath", "", "location of oauth token cache") - flag.BoolVar(&forceRefresh, "forceRefresh", false, "pass true to force a token refresh") - - flag.Parse() - - log.Printf("mode(%s) certPath(%s) appID(%s) tenantID(%s), subID(%s)\n", - mode, certificatePath, applicationID, tenantID, subscriptionID) - - if mode == "certificate" && - (strings.TrimSpace(tenantID) == "" || strings.TrimSpace(subscriptionID) == "") { - log.Fatalln("Bad usage. Using certificate mode. Please specify tenantID, subscriptionID") - } - - if mode != "certificate" && mode != "device" { - log.Fatalln("Bad usage. Mode must be one of 'certificate' or 'device'.") - } - - if mode == "device" && strings.TrimSpace(applicationID) == "" { - log.Println("Using device mode auth. Will use `azkube` clientID since none was specified on the comand line.") - applicationID = nativeAppClientID - } - - if mode == "certificate" && strings.TrimSpace(certificatePath) == "" { - log.Fatalln("Bad usage. Mode 'certificate' requires the 'certificatePath' argument.") - } - - if strings.TrimSpace(tenantID) == "" || strings.TrimSpace(subscriptionID) == "" || strings.TrimSpace(applicationID) == "" { - log.Fatalln("Bad usage. Must specify the 'tenantId' and 'subscriptionId'") - } -} - -func getSptFromCachedToken(oauthConfig adal.OAuthConfig, clientID, resource string, callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - token, err := adal.LoadToken(tokenCachePath) - if err != nil { - return nil, fmt.Errorf("failed to load token from cache: %v", err) - } - - spt, _ := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - clientID, - resource, - *token, - callbacks...) - - return spt, nil -} - -func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { - privateKey, certificate, err := pkcs12.Decode(pkcs, password) - if err != nil { - return nil, nil, err - } - - rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey) - if !isRsaKey { - return nil, nil, fmt.Errorf("PKCS#12 certificate must contain an RSA private key") - } - - return certificate, rsaPrivateKey, nil -} - -func getSptFromCertificate(oauthConfig adal.OAuthConfig, clientID, resource, certicatePath string, callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - certData, err := ioutil.ReadFile(certificatePath) - if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) - } - - certificate, rsaPrivateKey, err := decodePkcs12(certData, "") - if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) - } - - spt, _ := adal.NewServicePrincipalTokenFromCertificate( - oauthConfig, - clientID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - - return spt, nil -} - -func getSptFromDeviceFlow(oauthConfig adal.OAuthConfig, clientID, resource string, callbacks ...adal.TokenRefreshCallback) (*adal.ServicePrincipalToken, error) { - oauthClient := &autorest.Client{} - deviceCode, err := adal.InitiateDeviceAuth(oauthClient, oauthConfig, clientID, resource) - if err != nil { - return nil, fmt.Errorf("failed to start device auth flow: %s", err) - } - - fmt.Println(*deviceCode.Message) - - token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) - if err != nil { - return nil, fmt.Errorf("failed to finish device auth flow: %s", err) - } - - spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - clientID, - resource, - *token, - callbacks...) - if err != nil { - return nil, fmt.Errorf("failed to get oauth token from device flow: %v", err) - } - - return spt, nil -} - -func printResourceGroups(client *autorest.Client) error { - p := map[string]interface{}{"subscription-id": subscriptionID} - q := map[string]interface{}{"api-version": apiVersion} - - req, _ := autorest.Prepare(&http.Request{}, - autorest.AsGet(), - autorest.WithBaseURL(resourceGroupURLTemplate), - autorest.WithPathParameters("/subscriptions/{subscription-id}/resourcegroups", p), - autorest.WithQueryParameters(q)) - - resp, err := autorest.SendWithSender(client, req) - if err != nil { - return err - } - - value := struct { - ResourceGroups []struct { - Name string `json:"name"` - } `json:"value"` - }{} - - defer resp.Body.Close() - dec := json.NewDecoder(resp.Body) - err = dec.Decode(&value) - if err != nil { - return err - } - - var groupNames = make([]string, len(value.ResourceGroups)) - for i, name := range value.ResourceGroups { - groupNames[i] = name.Name - } - - log.Println("Groups:", strings.Join(groupNames, ", ")) - return err -} - -func saveToken(spt adal.Token) { - if tokenCachePath != "" { - err := adal.SaveToken(tokenCachePath, 0600, spt) - if err != nil { - log.Println("error saving token", err) - } else { - log.Println("saved token to", tokenCachePath) - } - } -} - -func main() { - var spt *adal.ServicePrincipalToken - var err error - - callback := func(t adal.Token) error { - log.Println("refresh callback was called") - saveToken(t) - return nil - } - - oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID) - if err != nil { - panic(err) - } - - if tokenCachePath != "" { - log.Println("tokenCachePath specified; attempting to load from", tokenCachePath) - spt, err = getSptFromCachedToken(*oauthConfig, applicationID, resource, callback) - if err != nil { - spt = nil // just in case, this is the condition below - log.Println("loading from cache failed:", err) - } - } - - if spt == nil { - log.Println("authenticating via 'mode'", mode) - switch mode { - case "device": - spt, err = getSptFromDeviceFlow(*oauthConfig, applicationID, resource, callback) - case "certificate": - spt, err = getSptFromCertificate(*oauthConfig, applicationID, resource, certificatePath, callback) - } - if err != nil { - log.Fatalln("failed to retrieve token:", err) - } - - // should save it as soon as you get it since Refresh won't be called for some time - if tokenCachePath != "" { - saveToken(spt.Token) - } - } - - client := &autorest.Client{} - client.Authorizer = autorest.NewBearerAuthorizer(spt) - - printResourceGroups(client) - - if forceRefresh { - err = spt.Refresh() - if err != nil { - panic(err) - } - printResourceGroups(client) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go b/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go deleted file mode 100644 index b6b95d6f..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package azure - -import ( - "errors" - "fmt" - "net/http" - "net/url" - "strings" - "time" - - "github.com/Azure/go-autorest/autorest" -) - -// DoRetryWithRegistration tries to register the resource provider in case it is unregistered. -// It also handles request retries -func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator { - return func(s autorest.Sender) autorest.Sender { - return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := autorest.NewRetriableRequest(r) - for currentAttempt := 0; currentAttempt < client.RetryAttempts; currentAttempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - - resp, err = autorest.SendWithSender(s, rr.Request(), - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return resp, err - } - - if resp.StatusCode != http.StatusConflict || client.SkipResourceProviderRegistration { - return resp, err - } - var re RequestError - err = autorest.Respond( - resp, - autorest.ByUnmarshallingJSON(&re), - ) - if err != nil { - return resp, err - } - err = re - - if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" { - regErr := register(client, r, re) - if regErr != nil { - return resp, fmt.Errorf("failed auto registering Resource Provider: %s. Original error: %s", regErr, err) - } - } - } - return resp, fmt.Errorf("failed request: %s", err) - }) - } -} - -func getProvider(re RequestError) (string, error) { - if re.ServiceError != nil { - if re.ServiceError.Details != nil && len(*re.ServiceError.Details) > 0 { - detail := (*re.ServiceError.Details)[0].(map[string]interface{}) - return detail["target"].(string), nil - } - } - return "", errors.New("provider was not found in the response") -} - -func register(client autorest.Client, originalReq *http.Request, re RequestError) error { - subID := getSubscription(originalReq.URL.Path) - if subID == "" { - return errors.New("missing parameter subscriptionID to register resource provider") - } - providerName, err := getProvider(re) - if err != nil { - return fmt.Errorf("missing parameter provider to register resource provider: %s", err) - } - newURL := url.URL{ - Scheme: originalReq.URL.Scheme, - Host: originalReq.URL.Host, - } - - // taken from the resources SDK - // with almost identical code, this sections are easier to mantain - // It is also not a good idea to import the SDK here - // https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L252 - pathParameters := map[string]interface{}{ - "resourceProviderNamespace": autorest.Encode("path", providerName), - "subscriptionId": autorest.Encode("path", subID), - } - - const APIVersion = "2016-09-01" - queryParameters := map[string]interface{}{ - "api-version": APIVersion, - } - - preparer := autorest.CreatePreparer( - autorest.AsPost(), - autorest.WithBaseURL(newURL.String()), - autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", pathParameters), - autorest.WithQueryParameters(queryParameters), - ) - - req, err := preparer.Prepare(&http.Request{}) - if err != nil { - return err - } - req.Cancel = originalReq.Cancel - - resp, err := autorest.SendWithSender(client, req, - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return err - } - - type Provider struct { - RegistrationState *string `json:"registrationState,omitempty"` - } - var provider Provider - - err = autorest.Respond( - resp, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByUnmarshallingJSON(&provider), - autorest.ByClosing(), - ) - if err != nil { - return err - } - - // poll for registered provisioning state - now := time.Now() - for err == nil && time.Since(now) < client.PollingDuration { - // taken from the resources SDK - // https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L45 - preparer := autorest.CreatePreparer( - autorest.AsGet(), - autorest.WithBaseURL(newURL.String()), - autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", pathParameters), - autorest.WithQueryParameters(queryParameters), - ) - req, err = preparer.Prepare(&http.Request{}) - if err != nil { - return err - } - req.Cancel = originalReq.Cancel - - resp, err := autorest.SendWithSender(client, req, - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return err - } - - err = autorest.Respond( - resp, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByUnmarshallingJSON(&provider), - autorest.ByClosing(), - ) - if err != nil { - return err - } - - if provider.RegistrationState != nil && - *provider.RegistrationState == "Registered" { - break - } - - delayed := autorest.DelayWithRetryAfter(resp, originalReq.Cancel) - if !delayed { - autorest.DelayForBackoff(client.PollingDelay, 0, originalReq.Cancel) - } - } - if !(time.Since(now) < client.PollingDuration) { - return errors.New("polling for resource provider registration has exceeded the polling duration") - } - return err -} - -func getSubscription(path string) string { - parts := strings.Split(path, "/") - for i, v := range parts { - if v == "subscriptions" && (i+1) < len(parts) { - return parts[i+1] - } - } - return "" -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go b/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go deleted file mode 100644 index 9bcebbb4..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/rp_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package azure - -import ( - "net/http" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestDoRetryWithRegistration(t *testing.T) { - client := mocks.NewSender() - // first response, should retry because it is a transient error - client.AppendResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError)) - // response indicates the resource provider has not been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "error":{ - "code":"MissingSubscriptionRegistration", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions.", - "details":[ - { - "code":"MissingSubscriptionRegistration", - "target":"Microsoft.EventGrid", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions." - } - ] - } -} -`), http.StatusConflict, "MissingSubscriptionRegistration")) - // first poll response, still not ready - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "registrationState": "Registering" -} -`), http.StatusOK, "200 OK")) - // last poll response, respurce provider has been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "registrationState": "Registered" -} -`), http.StatusOK, "200 OK")) - // retry original request, response is successful - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - req := mocks.NewRequestForURL("https://lol/subscriptions/rofl") - req.Body = mocks.NewBody("lolol") - r, err := autorest.SendWithSender(client, req, - DoRetryWithRegistration(autorest.Client{ - PollingDelay: time.Second, - PollingDuration: time.Second * 10, - RetryAttempts: 5, - RetryDuration: time.Second, - Sender: client, - }), - ) - if err != nil { - t.Fatalf("got error: %v", err) - } - - autorest.Respond(r, - autorest.ByDiscardingBody(), - autorest.ByClosing(), - ) - - if r.StatusCode != http.StatusOK { - t.Fatalf("azure: Sender#DoRetryWithRegistration -- Got: StatusCode %v; Want: StatusCode 200 OK", r.StatusCode) - } -} - -func TestDoRetrySkipRegistration(t *testing.T) { - client := mocks.NewSender() - // first response, should retry because it is a transient error - client.AppendResponse(mocks.NewResponseWithStatus("Internal server error", http.StatusInternalServerError)) - // response indicates the resource provider has not been registered - client.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(`{ - "error":{ - "code":"MissingSubscriptionRegistration", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions.", - "details":[ - { - "code":"MissingSubscriptionRegistration", - "target":"Microsoft.EventGrid", - "message":"The subscription registration is in 'Unregistered' state. The subscription must be registered to use namespace 'Microsoft.EventGrid'. See https://aka.ms/rps-not-found for how to register subscriptions." - } - ] - } -}`), http.StatusConflict, "MissingSubscriptionRegistration")) - - req := mocks.NewRequestForURL("https://lol/subscriptions/rofl") - req.Body = mocks.NewBody("lolol") - r, err := autorest.SendWithSender(client, req, - DoRetryWithRegistration(autorest.Client{ - PollingDelay: time.Second, - PollingDuration: time.Second * 10, - RetryAttempts: 5, - RetryDuration: time.Second, - Sender: client, - SkipResourceProviderRegistration: true, - }), - ) - if err != nil { - t.Fatalf("got error: %v", err) - } - - autorest.Respond(r, - autorest.ByDiscardingBody(), - autorest.ByClosing(), - ) - - if r.StatusCode != http.StatusConflict { - t.Fatalf("azure: Sender#DoRetryWithRegistration -- Got: StatusCode %v; Want: StatusCode 409 Conflict", r.StatusCode) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/testdata/test_environment_1.json b/vendor/github.com/Azure/go-autorest/autorest/azure/testdata/test_environment_1.json deleted file mode 100644 index f065a673..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/testdata/test_environment_1.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "--unit-test--", - "managementPortalURL": "--management-portal-url", - "publishSettingsURL": "--publish-settings-url--", - "serviceManagementEndpoint": "--service-management-endpoint--", - "resourceManagerEndpoint": "--resource-management-endpoint--", - "activeDirectoryEndpoint": "--active-directory-endpoint--", - "galleryEndpoint": "--gallery-endpoint--", - "keyVaultEndpoint": "--key-vault--endpoint--", - "graphEndpoint": "--graph-endpoint--", - "storageEndpointSuffix": "--storage-endpoint-suffix--", - "sqlDatabaseDNSSuffix": "--sql-database-dns-suffix--", - "trafficManagerDNSSuffix": "--traffic-manager-dns-suffix--", - "keyVaultDNSSuffix": "--key-vault-dns-suffix--", - "serviceBusEndpointSuffix": "--service-bus-endpoint-suffix--", - "serviceManagementVMDNSSuffix": "--asm-vm-dns-suffix--", - "resourceManagerVMDNSSuffix": "--arm-vm-dns-suffix--", - "containerRegistryDNSSuffix": "--container-registry-dns-suffix--" -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go deleted file mode 100644 index d329cb73..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/client.go +++ /dev/null @@ -1,263 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "net/http/cookiejar" - "runtime" - "time" -) - -const ( - // DefaultPollingDelay is a reasonable delay between polling requests. - DefaultPollingDelay = 60 * time.Second - - // DefaultPollingDuration is a reasonable total polling duration. - DefaultPollingDuration = 15 * time.Minute - - // DefaultRetryAttempts is number of attempts for retry status codes (5xx). - DefaultRetryAttempts = 3 - - // DefaultRetryDuration is the duration to wait between retries. - DefaultRetryDuration = 30 * time.Second -) - -var ( - // defaultUserAgent builds a string containing the Go version, system archityecture and OS, - // and the go-autorest version. - defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s", - runtime.Version(), - runtime.GOARCH, - runtime.GOOS, - Version(), - ) - - // StatusCodesForRetry are a defined group of status code for which the client will retry - StatusCodesForRetry = []int{ - http.StatusRequestTimeout, // 408 - http.StatusTooManyRequests, // 429 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 - } -) - -const ( - requestFormat = `HTTP Request Begin =================================================== -%s -===================================================== HTTP Request End -` - responseFormat = `HTTP Response Begin =================================================== -%s -===================================================== HTTP Response End -` -) - -// Response serves as the base for all responses from generated clients. It provides access to the -// last http.Response. -type Response struct { - *http.Response `json:"-"` -} - -// LoggingInspector implements request and response inspectors that log the full request and -// response to a supplied log. -type LoggingInspector struct { - Logger *log.Logger -} - -// WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The -// body is restored after being emitted. -// -// Note: Since it reads the entire Body, this decorator should not be used where body streaming is -// important. It is best used to trace JSON or similar body values. -func (li LoggingInspector) WithInspection() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - var body, b bytes.Buffer - - defer r.Body.Close() - - r.Body = ioutil.NopCloser(io.TeeReader(r.Body, &body)) - if err := r.Write(&b); err != nil { - return nil, fmt.Errorf("Failed to write response: %v", err) - } - - li.Logger.Printf(requestFormat, b.String()) - - r.Body = ioutil.NopCloser(&body) - return p.Prepare(r) - }) - } -} - -// ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The -// body is restored after being emitted. -// -// Note: Since it reads the entire Body, this decorator should not be used where body streaming is -// important. It is best used to trace JSON or similar body values. -func (li LoggingInspector) ByInspecting() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - var body, b bytes.Buffer - defer resp.Body.Close() - resp.Body = ioutil.NopCloser(io.TeeReader(resp.Body, &body)) - if err := resp.Write(&b); err != nil { - return fmt.Errorf("Failed to write response: %v", err) - } - - li.Logger.Printf(responseFormat, b.String()) - - resp.Body = ioutil.NopCloser(&body) - return r.Respond(resp) - }) - } -} - -// Client is the base for autorest generated clients. It provides default, "do nothing" -// implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the -// standard, undecorated http.Client as a default Sender. -// -// Generated clients should also use Error (see NewError and NewErrorWithError) for errors and -// return responses that compose with Response. -// -// Most customization of generated clients is best achieved by supplying a custom Authorizer, custom -// RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit -// breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence -// sending the request by providing a decorated Sender. -type Client struct { - Authorizer Authorizer - Sender Sender - RequestInspector PrepareDecorator - ResponseInspector RespondDecorator - - // PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header - PollingDelay time.Duration - - // PollingDuration sets the maximum polling time after which an error is returned. - PollingDuration time.Duration - - // RetryAttempts sets the default number of retry attempts for client. - RetryAttempts int - - // RetryDuration sets the delay duration for retries. - RetryDuration time.Duration - - // UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent - // through the Do method. - UserAgent string - - Jar http.CookieJar - - // Set to true to skip attempted registration of resource providers (false by default). - SkipResourceProviderRegistration bool -} - -// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed -// string. -func NewClientWithUserAgent(ua string) Client { - c := Client{ - PollingDelay: DefaultPollingDelay, - PollingDuration: DefaultPollingDuration, - RetryAttempts: DefaultRetryAttempts, - RetryDuration: DefaultRetryDuration, - UserAgent: defaultUserAgent, - } - c.Sender = c.sender() - c.AddToUserAgent(ua) - return c -} - -// AddToUserAgent adds an extension to the current user agent -func (c *Client) AddToUserAgent(extension string) error { - if extension != "" { - c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension) - return nil - } - return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent) -} - -// Do implements the Sender interface by invoking the active Sender after applying authorization. -// If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent -// is set, apply set the User-Agent header. -func (c Client) Do(r *http.Request) (*http.Response, error) { - if r.UserAgent() == "" { - r, _ = Prepare(r, - WithUserAgent(c.UserAgent)) - } - r, err := Prepare(r, - c.WithInspection(), - c.WithAuthorization()) - if err != nil { - var resp *http.Response - if detErr, ok := err.(DetailedError); ok { - // if the authorization failed (e.g. invalid credentials) there will - // be a response associated with the error, be sure to return it. - resp = detErr.Response - } - return resp, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed") - } - - resp, err := SendWithSender(c.sender(), r) - Respond(resp, c.ByInspecting()) - return resp, err -} - -// sender returns the Sender to which to send requests. -func (c Client) sender() Sender { - if c.Sender == nil { - j, _ := cookiejar.New(nil) - return &http.Client{Jar: j} - } - return c.Sender -} - -// WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator -// from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer. -func (c Client) WithAuthorization() PrepareDecorator { - return c.authorizer().WithAuthorization() -} - -// authorizer returns the Authorizer to use. -func (c Client) authorizer() Authorizer { - if c.Authorizer == nil { - return NullAuthorizer{} - } - return c.Authorizer -} - -// WithInspection is a convenience method that passes the request to the supplied RequestInspector, -// if present, or returns the WithNothing PrepareDecorator otherwise. -func (c Client) WithInspection() PrepareDecorator { - if c.RequestInspector == nil { - return WithNothing() - } - return c.RequestInspector -} - -// ByInspecting is a convenience method that passes the response to the supplied ResponseInspector, -// if present, or returns the ByIgnoring RespondDecorator otherwise. -func (c Client) ByInspecting() RespondDecorator { - if c.ResponseInspector == nil { - return ByIgnoring() - } - return c.ResponseInspector -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/client_test.go b/vendor/github.com/Azure/go-autorest/autorest/client_test.go deleted file mode 100644 index 151f8eed..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/client_test.go +++ /dev/null @@ -1,402 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "math/rand" - "net/http" - "net/http/httptest" - "reflect" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func TestLoggingInspectorWithInspection(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - Prepare(mocks.NewRequestWithContent("Content"), - c.WithInspection()) - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") - } -} - -func TestLoggingInspectorWithInspectionEmitsErrors(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewRequestWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - if _, err := Prepare(r, - c.WithInspection()); err != nil { - t.Error(err) - } - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") - } -} - -func TestLoggingInspectorWithInspectionRestoresBody(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewRequestWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.RequestInspector = li.WithInspection() - - Prepare(r, - c.WithInspection()) - - s, _ := ioutil.ReadAll(r.Body) - if len(s) <= 0 { - t.Fatal("autorest: LoggingInspector#WithInspection did not restore the Request body") - } -} - -func TestLoggingInspectorByInspecting(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - Respond(mocks.NewResponseWithContent("Content"), - c.ByInspecting()) - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") - } -} - -func TestLoggingInspectorByInspectingEmitsErrors(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewResponseWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - if err := Respond(r, - c.ByInspecting()); err != nil { - t.Fatal(err) - } - - if len(b.String()) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") - } -} - -func TestLoggingInspectorByInspectingRestoresBody(t *testing.T) { - b := bytes.Buffer{} - c := Client{} - r := mocks.NewResponseWithContent("Content") - li := LoggingInspector{Logger: log.New(&b, "", 0)} - c.ResponseInspector = li.ByInspecting() - - Respond(r, - c.ByInspecting()) - - s, _ := ioutil.ReadAll(r.Body) - if len(s) <= 0 { - t.Fatal("autorest: LoggingInspector#ByInspecting did not restore the Response body") - } -} - -func TestNewClientWithUserAgent(t *testing.T) { - ua := "UserAgent" - c := NewClientWithUserAgent(ua) - completeUA := fmt.Sprintf("%s %s", defaultUserAgent, ua) - - if c.UserAgent != completeUA { - t.Fatalf("autorest: NewClientWithUserAgent failed to set the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } -} - -func TestAddToUserAgent(t *testing.T) { - ua := "UserAgent" - c := NewClientWithUserAgent(ua) - ext := "extension" - err := c.AddToUserAgent(ext) - if err != nil { - t.Fatalf("autorest: AddToUserAgent returned error -- expected nil, received %s", err) - } - completeUA := fmt.Sprintf("%s %s %s", defaultUserAgent, ua, ext) - - if c.UserAgent != completeUA { - t.Fatalf("autorest: AddToUserAgent failed to add an extension to the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } - - err = c.AddToUserAgent("") - if err == nil { - t.Fatalf("autorest: AddToUserAgent didn't return error -- expected %s, received nil", - fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)) - } - if c.UserAgent != completeUA { - t.Fatalf("autorest: AddToUserAgent failed to not add an empty extension to the UserAgent -- expected %s, received %s", - completeUA, c.UserAgent) - } -} - -func TestClientSenderReturnsHttpClientByDefault(t *testing.T) { - c := Client{} - - if fmt.Sprintf("%T", c.sender()) != "*http.Client" { - t.Fatal("autorest: Client#sender failed to return http.Client by default") - } -} - -func TestClientSenderReturnsSetSender(t *testing.T) { - c := Client{} - - s := mocks.NewSender() - c.Sender = s - - if c.sender() != s { - t.Fatal("autorest: Client#sender failed to return set Sender") - } -} - -func TestClientDoInvokesSender(t *testing.T) { - c := Client{} - - s := mocks.NewSender() - c.Sender = s - - c.Do(&http.Request{}) - if s.Attempts() != 1 { - t.Fatal("autorest: Client#Do failed to invoke the Sender") - } -} - -func TestClientDoSetsUserAgent(t *testing.T) { - ua := "UserAgent" - c := Client{UserAgent: ua} - r := mocks.NewRequest() - s := mocks.NewSender() - c.Sender = s - - c.Do(r) - - if r.UserAgent() != ua { - t.Fatalf("autorest: Client#Do failed to correctly set User-Agent header: %s=%s", - http.CanonicalHeaderKey(headerUserAgent), r.UserAgent()) - } -} - -func TestClientDoSetsAuthorization(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - c := Client{Authorizer: mockAuthorizer{}, Sender: s} - - c.Do(r) - if len(r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) <= 0 { - t.Fatalf("autorest: Client#Send failed to set Authorization header -- %s=%s", - http.CanonicalHeaderKey(headerAuthorization), - r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) - } -} - -func TestClientDoInvokesRequestInspector(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - i := &mockInspector{} - c := Client{RequestInspector: i.WithInspection(), Sender: s} - - c.Do(r) - if !i.wasInvoked { - t.Fatal("autorest: Client#Send failed to invoke the RequestInspector") - } -} - -func TestClientDoInvokesResponseInspector(t *testing.T) { - r := mocks.NewRequest() - s := mocks.NewSender() - i := &mockInspector{} - c := Client{ResponseInspector: i.ByInspecting(), Sender: s} - - c.Do(r) - if !i.wasInvoked { - t.Fatal("autorest: Client#Send failed to invoke the ResponseInspector") - } -} - -func TestClientDoReturnsErrorIfPrepareFails(t *testing.T) { - c := Client{} - s := mocks.NewSender() - c.Authorizer = mockFailingAuthorizer{} - c.Sender = s - - _, err := c.Do(&http.Request{}) - if err == nil { - t.Fatalf("autorest: Client#Do failed to return an error when Prepare failed") - } -} - -func TestClientDoDoesNotSendIfPrepareFails(t *testing.T) { - c := Client{} - s := mocks.NewSender() - c.Authorizer = mockFailingAuthorizer{} - c.Sender = s - - c.Do(&http.Request{}) - if s.Attempts() > 0 { - t.Fatal("autorest: Client#Do failed to invoke the Sender") - } -} - -func TestClientAuthorizerReturnsNullAuthorizerByDefault(t *testing.T) { - c := Client{} - - if fmt.Sprintf("%T", c.authorizer()) != "autorest.NullAuthorizer" { - t.Fatal("autorest: Client#authorizer failed to return the NullAuthorizer by default") - } -} - -func TestClientAuthorizerReturnsSetAuthorizer(t *testing.T) { - c := Client{} - c.Authorizer = mockAuthorizer{} - - if fmt.Sprintf("%T", c.authorizer()) != "autorest.mockAuthorizer" { - t.Fatal("autorest: Client#authorizer failed to return the set Authorizer") - } -} - -func TestClientWithAuthorizer(t *testing.T) { - c := Client{} - c.Authorizer = mockAuthorizer{} - - req, _ := Prepare(&http.Request{}, - c.WithAuthorization()) - - if req.Header.Get(headerAuthorization) == "" { - t.Fatal("autorest: Client#WithAuthorizer failed to return the WithAuthorizer from the active Authorizer") - } -} - -func TestClientWithInspection(t *testing.T) { - c := Client{} - r := &mockInspector{} - c.RequestInspector = r.WithInspection() - - Prepare(&http.Request{}, - c.WithInspection()) - - if !r.wasInvoked { - t.Fatal("autorest: Client#WithInspection failed to invoke RequestInspector") - } -} - -func TestClientWithInspectionSetsDefault(t *testing.T) { - c := Client{} - - r1 := &http.Request{} - r2, _ := Prepare(r1, - c.WithInspection()) - - if !reflect.DeepEqual(r1, r2) { - t.Fatal("autorest: Client#WithInspection failed to provide a default RequestInspector") - } -} - -func TestClientByInspecting(t *testing.T) { - c := Client{} - r := &mockInspector{} - c.ResponseInspector = r.ByInspecting() - - Respond(&http.Response{}, - c.ByInspecting()) - - if !r.wasInvoked { - t.Fatal("autorest: Client#ByInspecting failed to invoke ResponseInspector") - } -} - -func TestClientByInspectingSetsDefault(t *testing.T) { - c := Client{} - - r := &http.Response{} - Respond(r, - c.ByInspecting()) - - if !reflect.DeepEqual(r, &http.Response{}) { - t.Fatal("autorest: Client#ByInspecting failed to provide a default ResponseInspector") - } -} - -func TestCookies(t *testing.T) { - second := "second" - expected := http.Cookie{ - Name: "tastes", - Value: "delicious", - } - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.SetCookie(w, &expected) - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: ioutil.ReadAll failed reading request body: %s", err) - } - if string(b) == second { - cookie, err := r.Cookie(expected.Name) - if err != nil { - t.Fatalf("autorest: r.Cookie could not get request cookie: %s", err) - } - if cookie == nil { - t.Fatalf("autorest: got nil cookie, expecting %v", expected) - } - if cookie.Value != expected.Value { - t.Fatalf("autorest: got cookie value '%s', expecting '%s'", cookie.Value, expected.Name) - } - } - })) - defer server.Close() - - client := NewClientWithUserAgent("") - _, err := SendWithSender(client, mocks.NewRequestForURL(server.URL)) - if err != nil { - t.Fatalf("autorest: first request failed: %s", err) - } - - r2, err := http.NewRequest(http.MethodGet, server.URL, mocks.NewBody(second)) - if err != nil { - t.Fatalf("autorest: failed creating second request: %s", err) - } - - _, err = SendWithSender(client, r2) - if err != nil { - t.Fatalf("autorest: second request failed: %s", err) - } -} - -func randomString(n int) string { - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) - s := make([]byte, n) - for i := range s { - s[i] = chars[r.Intn(len(chars))] - } - return string(s) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/date.go b/vendor/github.com/Azure/go-autorest/autorest/date/date.go deleted file mode 100644 index c4571065..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/date.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/) -defined date formats: Date and DateTime. Both types may, in most cases, be used in lieu of -time.Time types. And both convert to time.Time through a ToTime method. -*/ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "time" -) - -const ( - fullDate = "2006-01-02" - fullDateJSON = `"2006-01-02"` - dateFormat = "%04d-%02d-%02d" - jsonFormat = `"%04d-%02d-%02d"` -) - -// Date defines a type similar to time.Time but assumes a layout of RFC3339 full-date (i.e., -// 2006-01-02). -type Date struct { - time.Time -} - -// ParseDate create a new Date from the passed string. -func ParseDate(date string) (d Date, err error) { - return parseDate(date, fullDate) -} - -func parseDate(date string, format string) (Date, error) { - d, err := time.Parse(format, date) - return Date{Time: d}, err -} - -// MarshalBinary preserves the Date as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalBinary() ([]byte, error) { - return d.MarshalText() -} - -// UnmarshalBinary reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalBinary(data []byte) error { - return d.UnmarshalText(data) -} - -// MarshalJSON preserves the Date as a JSON string conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalJSON() (json []byte, err error) { - return []byte(fmt.Sprintf(jsonFormat, d.Year(), d.Month(), d.Day())), nil -} - -// UnmarshalJSON reconstitutes the Date from a JSON string conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalJSON(data []byte) (err error) { - d.Time, err = time.Parse(fullDateJSON, string(data)) - return err -} - -// MarshalText preserves the Date as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalText() (text []byte, err error) { - return []byte(fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())), nil -} - -// UnmarshalText reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalText(data []byte) (err error) { - d.Time, err = time.Parse(fullDate, string(data)) - return err -} - -// String returns the Date formatted as an RFC3339 full-date string (i.e., 2006-01-02). -func (d Date) String() string { - return fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day()) -} - -// ToTime returns a Date as a time.Time -func (d Date) ToTime() time.Time { - return d.Time -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go deleted file mode 100644 index 4a40bbc3..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/date_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleParseDate() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func ExampleDate() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - - t, err := time.Parse(time.RFC3339, "2001-02-04T00:00:00Z") - if err != nil { - fmt.Println(err) - } - - // Date acts as time.Time when the receiver - if d.Before(t) { - fmt.Printf("Before ") - } else { - fmt.Printf("After ") - } - - // Convert Date when needing a time.Time - if t.After(d.ToTime()) { - fmt.Printf("After") - } else { - fmt.Printf("Before") - } - // Output: Before After -} - -func ExampleDate_MarshalBinary() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03 -} - -func ExampleDate_UnmarshalBinary() { - d := Date{} - t := "2001-02-03" - - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func ExampleDate_MarshalJSON() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "2001-02-03" -} - -func ExampleDate_UnmarshalJSON() { - var d struct { - Date Date `json:"date"` - } - j := `{"date" : "2001-02-03"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Date) - // Output: 2001-02-03 -} - -func ExampleDate_MarshalText() { - d, err := ParseDate("2001-02-03") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03 -} - -func ExampleDate_UnmarshalText() { - d := Date{} - t := "2001-02-03" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03 -} - -func TestDateString(t *testing.T) { - d, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: String failed (%v)", err) - } - if d.String() != "2001-02-03" { - t.Fatalf("date: String failed (%v)", d.String()) - } -} - -func TestDateBinaryRoundTrip(t *testing.T) { - d1, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: MarshalBinary failed (%v)", err) - } - - d2 := Date{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestDateJSONRoundTrip(t *testing.T) { - type s struct { - Date Date `json:"date"` - } - var err error - d1 := s{} - d1.Date, err = ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestDateTextRoundTrip(t *testing.T) { - d1, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: MarshalText failed (%v)", err) - } - d2 := Date{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestDateToTime(t *testing.T) { - var d Date - d, err := ParseDate("2001-02-03") - if err != nil { - t.Fatalf("date: ParseDate failed (%v)", err) - } - var _ time.Time = d.ToTime() -} - -func TestDateUnmarshalJSONReturnsError(t *testing.T) { - var d struct { - Date Date `json:"date"` - } - j := `{"date" : "February 3, 2001"}` - - if err := json.Unmarshal([]byte(j), &d); err == nil { - t.Fatal("date: Date failed to return error for malformed JSON date") - } -} - -func TestDateUnmarshalTextReturnsError(t *testing.T) { - d := Date{} - txt := "February 3, 2001" - - if err := d.UnmarshalText([]byte(txt)); err == nil { - t.Fatal("date: Date failed to return error for malformed Text date") - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/time.go b/vendor/github.com/Azure/go-autorest/autorest/date/time.go deleted file mode 100644 index b453fad0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/time.go +++ /dev/null @@ -1,103 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "regexp" - "time" -) - -// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. -const ( - azureUtcFormatJSON = `"2006-01-02T15:04:05.999999999"` - azureUtcFormat = "2006-01-02T15:04:05.999999999" - rfc3339JSON = `"` + time.RFC3339Nano + `"` - rfc3339 = time.RFC3339Nano - tzOffsetRegex = `(Z|z|\+|-)(\d+:\d+)*"*$` -) - -// Time defines a type similar to time.Time but assumes a layout of RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -type Time struct { - time.Time -} - -// MarshalBinary preserves the Time as a byte array conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalBinary() ([]byte, error) { - return t.Time.MarshalText() -} - -// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalBinary(data []byte) error { - return t.UnmarshalText(data) -} - -// MarshalJSON preserves the Time as a JSON string conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalJSON() (json []byte, err error) { - return t.Time.MarshalJSON() -} - -// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalJSON(data []byte) (err error) { - timeFormat := azureUtcFormatJSON - match, err := regexp.Match(tzOffsetRegex, data) - if err != nil { - return err - } else if match { - timeFormat = rfc3339JSON - } - t.Time, err = ParseTime(timeFormat, string(data)) - return err -} - -// MarshalText preserves the Time as a byte array conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalText() (text []byte, err error) { - return t.Time.MarshalText() -} - -// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalText(data []byte) (err error) { - timeFormat := azureUtcFormat - match, err := regexp.Match(tzOffsetRegex, data) - if err != nil { - return err - } else if match { - timeFormat = rfc3339 - } - t.Time, err = ParseTime(timeFormat, string(data)) - return err -} - -// String returns the Time formatted as an RFC3339 date-time string (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) String() string { - // Note: time.Time.String does not return an RFC3339 compliant string, time.Time.MarshalText does. - b, err := t.MarshalText() - if err != nil { - return "" - } - return string(b) -} - -// ToTime returns a Time as a time.Time -func (t Time) ToTime() time.Time { - return t.Time -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go deleted file mode 100644 index d8c81170..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/time_test.go +++ /dev/null @@ -1,277 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleParseTime() { - d, _ := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - fmt.Println(d) - // Output: 2001-02-03 04:05:06 +0000 UTC -} - -func ExampleTime_MarshalBinary() { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := Time{ti} - t, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_UnmarshalBinary() { - d := Time{} - t := "2001-02-03T04:05:06Z" - - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_MarshalJSON() { - d, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "2001-02-03T04:05:06Z" -} - -func ExampleTime_UnmarshalJSON() { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "2001-02-03T04:05:06Z"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Time) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_MarshalText() { - d, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: 2001-02-03T04:05:06Z -} - -func ExampleTime_UnmarshalText() { - d := Time{} - t := "2001-02-03T04:05:06Z" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2001-02-03T04:05:06Z -} - -func TestUnmarshalTextforInvalidDate(t *testing.T) { - d := Time{} - dt := "2001-02-03T04:05:06AAA" - - if err := d.UnmarshalText([]byte(dt)); err == nil { - t.Fatalf("date: Time#Unmarshal was expecting error for invalid date") - } -} - -func TestUnmarshalJSONforInvalidDate(t *testing.T) { - d := Time{} - dt := `"2001-02-03T04:05:06AAA"` - - if err := d.UnmarshalJSON([]byte(dt)); err == nil { - t.Fatalf("date: Time#Unmarshal was expecting error for invalid date") - } -} - -func TestTimeString(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := Time{ti} - if d.String() != "2001-02-03T04:05:06Z" { - t.Fatalf("date: Time#String failed (%v)", d.String()) - } -} - -func TestTimeStringReturnsEmptyStringForError(t *testing.T) { - d := Time{Time: time.Date(20000, 01, 01, 01, 01, 01, 01, time.UTC)} - if d.String() != "" { - t.Fatalf("date: Time#String failed empty string for an error") - } -} - -func TestTimeBinaryRoundTrip(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - d1 := Time{ti} - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: Time#MarshalBinary failed (%v)", err) - } - - d2 := Time{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: Time#UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date:Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestTimeJSONRoundTrip(t *testing.T) { - type s struct { - Time Time `json:"datetime"` - } - - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - - d1 := s{Time: Time{ti}} - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: Time#MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: Time#UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestTimeTextRoundTrip(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - d1 := Time{Time: ti} - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: Time#MarshalText failed (%v)", err) - } - - d2 := Time{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestTimeToTime(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - d := Time{ti} - if err != nil { - t.Fatalf("date: Time#ParseTime failed (%v)", err) - } - var _ time.Time = d.ToTime() -} - -func TestUnmarshalJSONNoOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "2001-02-03T04:05:06.789"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalJSONPosOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "1980-01-02T00:11:35.01+01:00"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalJSONNegOffset(t *testing.T) { - var d struct { - Time Time `json:"datetime"` - } - j := `{"datetime" : "1492-10-12T10:15:01.789-08:00"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - t.Fatalf("date: Time#Unmarshal failed (%v)", err) - } -} - -func TestUnmarshalTextNoOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} - -func TestUnmarshalTextPosOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06+00:30" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} - -func TestUnmarshalTextNegOffset(t *testing.T) { - d := Time{} - t1 := "2001-02-03T04:05:06-11:00" - - if err := d.UnmarshalText([]byte(t1)); err != nil { - t.Fatalf("date: Time#UnmarshalText failed (%v)", err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go deleted file mode 100644 index 48fb39ba..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go +++ /dev/null @@ -1,100 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "errors" - "time" -) - -const ( - rfc1123JSON = `"` + time.RFC1123 + `"` - rfc1123 = time.RFC1123 -) - -// TimeRFC1123 defines a type similar to time.Time but assumes a layout of RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -type TimeRFC1123 struct { - time.Time -} - -// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalJSON(data []byte) (err error) { - t.Time, err = ParseTime(rfc1123JSON, string(data)) - if err != nil { - return err - } - return nil -} - -// MarshalJSON preserves the Time as a JSON string conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalJSON() ([]byte, error) { - if y := t.Year(); y < 0 || y >= 10000 { - return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]") - } - b := []byte(t.Format(rfc1123JSON)) - return b, nil -} - -// MarshalText preserves the Time as a byte array conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalText() ([]byte, error) { - if y := t.Year(); y < 0 || y >= 10000 { - return nil, errors.New("Time.MarshalText: year outside of range [0,9999]") - } - - b := []byte(t.Format(rfc1123)) - return b, nil -} - -// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalText(data []byte) (err error) { - t.Time, err = ParseTime(rfc1123, string(data)) - if err != nil { - return err - } - return nil -} - -// MarshalBinary preserves the Time as a byte array conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalBinary() ([]byte, error) { - return t.MarshalText() -} - -// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalBinary(data []byte) error { - return t.UnmarshalText(data) -} - -// ToTime returns a Time as a time.Time -func (t TimeRFC1123) ToTime() time.Time { - return t.Time -} - -// String returns the Time formatted as an RFC1123 date-time string (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) String() string { - // Note: time.Time.String does not return an RFC1123 compliant string, time.Time.MarshalText does. - b, err := t.MarshalText() - if err != nil { - return "" - } - return string(b) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go deleted file mode 100644 index dfd64051..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "reflect" - "testing" - "time" -) - -func ExampleTimeRFC1123() { - d, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: 2006-01-02 15:04:05 +0000 MST -} - -func ExampleTimeRFC1123_MarshalBinary() { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - b, err := d.MarshalBinary() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(b)) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_UnmarshalBinary() { - d := TimeRFC1123{} - t := "Mon, 02 Jan 2006 15:04:05 MST" - if err := d.UnmarshalBinary([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_MarshalJSON() { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - j, err := json.Marshal(d) - if err != nil { - fmt.Println(err) - } - fmt.Println(string(j)) - // Output: "Mon, 02 Jan 2006 15:04:05 MST" -} - -func TestTimeRFC1123MarshalJSONInvalid(t *testing.T) { - ti := time.Date(20000, 01, 01, 00, 00, 00, 00, time.UTC) - d := TimeRFC1123{ti} - if _, err := json.Marshal(d); err == nil { - t.Fatalf("date: TimeRFC1123#Marshal failed for invalid date") - } -} - -func ExampleTimeRFC1123_UnmarshalJSON() { - var d struct { - Time TimeRFC1123 `json:"datetime"` - } - j := `{"datetime" : "Mon, 02 Jan 2006 15:04:05 MST"}` - - if err := json.Unmarshal([]byte(j), &d); err != nil { - fmt.Println(err) - } - fmt.Println(d.Time) - // Output: Mon, 02 Jan 2006 15:04:05 MST -} - -func ExampleTimeRFC1123_MarshalText() { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - t, err := d.MarshalText() - if err != nil { - fmt.Println(err) - } - fmt.Println(string(t)) - // Output: Sat, 03 Feb 2001 04:05:06 UTC -} - -func ExampleTimeRFC1123_UnmarshalText() { - d := TimeRFC1123{} - t := "Sat, 03 Feb 2001 04:05:06 UTC" - - if err := d.UnmarshalText([]byte(t)); err != nil { - fmt.Println(err) - } - fmt.Println(d) - // Output: Sat, 03 Feb 2001 04:05:06 UTC -} - -func TestUnmarshalJSONforInvalidDateRfc1123(t *testing.T) { - dt := `"Mon, 02 Jan 2000000 15:05 MST"` - d := TimeRFC1123{} - if err := d.UnmarshalJSON([]byte(dt)); err == nil { - t.Fatalf("date: TimeRFC1123#Unmarshal failed for invalid date") - } -} - -func TestUnmarshalTextforInvalidDateRfc1123(t *testing.T) { - dt := "Mon, 02 Jan 2000000 15:05 MST" - d := TimeRFC1123{} - if err := d.UnmarshalText([]byte(dt)); err == nil { - t.Fatalf("date: TimeRFC1123#Unmarshal failed for invalid date") - } -} - -func TestTimeStringRfc1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - fmt.Println(err) - } - d := TimeRFC1123{ti} - if d.String() != "Mon, 02 Jan 2006 15:04:05 MST" { - t.Fatalf("date: TimeRFC1123#String failed (%v)", d.String()) - } -} - -func TestTimeStringReturnsEmptyStringForErrorRfc1123(t *testing.T) { - d := TimeRFC1123{Time: time.Date(20000, 01, 01, 01, 01, 01, 01, time.UTC)} - if d.String() != "" { - t.Fatalf("date: TimeRFC1123#String failed empty string for an error") - } -} - -func TestTimeBinaryRoundTripRfc1123(t *testing.T) { - ti, err := ParseTime(rfc3339, "2001-02-03T04:05:06Z") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := TimeRFC1123{ti} - t1, err := d1.MarshalBinary() - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalBinary failed (%v)", err) - } - - d2 := TimeRFC1123{} - if err = d2.UnmarshalBinary(t1); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalBinary failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Binary failed (%v, %v)", d1, d2) - } -} - -func TestTimeJSONRoundTripRfc1123(t *testing.T) { - type s struct { - Time TimeRFC1123 `json:"datetime"` - } - var err error - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := s{Time: TimeRFC1123{ti}} - j, err := json.Marshal(d1) - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalJSON failed (%v)", err) - } - - d2 := s{} - if err = json.Unmarshal(j, &d2); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalJSON failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip JSON failed (%v, %v)", d1, d2) - } -} - -func TestTimeTextRoundTripRfc1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - d1 := TimeRFC1123{Time: ti} - t1, err := d1.MarshalText() - if err != nil { - t.Fatalf("date: TimeRFC1123#MarshalText failed (%v)", err) - } - - d2 := TimeRFC1123{} - if err = d2.UnmarshalText(t1); err != nil { - t.Fatalf("date: TimeRFC1123#UnmarshalText failed (%v)", err) - } - - if !reflect.DeepEqual(d1, d2) { - t.Fatalf("date: Round-trip Text failed (%v, %v)", d1, d2) - } -} - -func TestTimeToTimeRFC1123(t *testing.T) { - ti, err := ParseTime(rfc1123, "Mon, 02 Jan 2006 15:04:05 MST") - d := TimeRFC1123{ti} - if err != nil { - t.Fatalf("date: TimeRFC1123#ParseTime failed (%v)", err) - } - var _ time.Time = d.ToTime() -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go b/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go deleted file mode 100644 index 7073959b..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go +++ /dev/null @@ -1,123 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "time" -) - -// unixEpoch is the moment in time that should be treated as timestamp 0. -var unixEpoch = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC) - -// UnixTime marshals and unmarshals a time that is represented as the number -// of seconds (ignoring skip-seconds) since the Unix Epoch. -type UnixTime time.Time - -// Duration returns the time as a Duration since the UnixEpoch. -func (t UnixTime) Duration() time.Duration { - return time.Time(t).Sub(unixEpoch) -} - -// NewUnixTimeFromSeconds creates a UnixTime as a number of seconds from the UnixEpoch. -func NewUnixTimeFromSeconds(seconds float64) UnixTime { - return NewUnixTimeFromDuration(time.Duration(seconds * float64(time.Second))) -} - -// NewUnixTimeFromNanoseconds creates a UnixTime as a number of nanoseconds from the UnixEpoch. -func NewUnixTimeFromNanoseconds(nanoseconds int64) UnixTime { - return NewUnixTimeFromDuration(time.Duration(nanoseconds)) -} - -// NewUnixTimeFromDuration creates a UnixTime as a duration of time since the UnixEpoch. -func NewUnixTimeFromDuration(dur time.Duration) UnixTime { - return UnixTime(unixEpoch.Add(dur)) -} - -// UnixEpoch retreives the moment considered the Unix Epoch. I.e. The time represented by '0' -func UnixEpoch() time.Time { - return unixEpoch -} - -// MarshalJSON preserves the UnixTime as a JSON number conforming to Unix Timestamp requirements. -// (i.e. the number of seconds since midnight January 1st, 1970 not considering leap seconds.) -func (t UnixTime) MarshalJSON() ([]byte, error) { - buffer := &bytes.Buffer{} - enc := json.NewEncoder(buffer) - err := enc.Encode(float64(time.Time(t).UnixNano()) / 1e9) - if err != nil { - return nil, err - } - return buffer.Bytes(), nil -} - -// UnmarshalJSON reconstitures a UnixTime saved as a JSON number of the number of seconds since -// midnight January 1st, 1970. -func (t *UnixTime) UnmarshalJSON(text []byte) error { - dec := json.NewDecoder(bytes.NewReader(text)) - - var secondsSinceEpoch float64 - if err := dec.Decode(&secondsSinceEpoch); err != nil { - return err - } - - *t = NewUnixTimeFromSeconds(secondsSinceEpoch) - - return nil -} - -// MarshalText stores the number of seconds since the Unix Epoch as a textual floating point number. -func (t UnixTime) MarshalText() ([]byte, error) { - cast := time.Time(t) - return cast.MarshalText() -} - -// UnmarshalText populates a UnixTime with a value stored textually as a floating point number of seconds since the Unix Epoch. -func (t *UnixTime) UnmarshalText(raw []byte) error { - var unmarshaled time.Time - - if err := unmarshaled.UnmarshalText(raw); err != nil { - return err - } - - *t = UnixTime(unmarshaled) - return nil -} - -// MarshalBinary converts a UnixTime into a binary.LittleEndian float64 of nanoseconds since the epoch. -func (t UnixTime) MarshalBinary() ([]byte, error) { - buf := &bytes.Buffer{} - - payload := int64(t.Duration()) - - if err := binary.Write(buf, binary.LittleEndian, &payload); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -// UnmarshalBinary converts a from a binary.LittleEndian float64 of nanoseconds since the epoch into a UnixTime. -func (t *UnixTime) UnmarshalBinary(raw []byte) error { - var nanosecondsSinceEpoch int64 - - if err := binary.Read(bytes.NewReader(raw), binary.LittleEndian, &nanosecondsSinceEpoch); err != nil { - return err - } - *t = NewUnixTimeFromNanoseconds(nanosecondsSinceEpoch) - return nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go b/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go deleted file mode 100644 index 3fa347c0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime_test.go +++ /dev/null @@ -1,283 +0,0 @@ -// +build go1.7 - -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "fmt" - "math" - "testing" - "time" -) - -func ExampleUnixTime_MarshalJSON() { - epoch := UnixTime(UnixEpoch()) - text, _ := json.Marshal(epoch) - fmt.Print(string(text)) - // Output: 0 -} - -func ExampleUnixTime_UnmarshalJSON() { - var myTime UnixTime - json.Unmarshal([]byte("1.3e2"), &myTime) - fmt.Printf("%v", time.Time(myTime)) - // Output: 1970-01-01 00:02:10 +0000 UTC -} - -func TestUnixTime_MarshalJSON(t *testing.T) { - testCases := []time.Time{ - UnixEpoch().Add(-1 * time.Second), // One second befote the Unix Epoch - time.Date(2017, time.April, 14, 20, 27, 47, 0, time.UTC), // The time this test was written - UnixEpoch(), - time.Date(1800, 01, 01, 0, 0, 0, 0, time.UTC), - time.Date(2200, 12, 29, 00, 01, 37, 82, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - var actual, expected float64 - var marshaled []byte - - target := UnixTime(tc) - expected = float64(target.Duration().Nanoseconds()) / 1e9 - - if temp, err := json.Marshal(target); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - dec := json.NewDecoder(bytes.NewReader(marshaled)) - if err := dec.Decode(&actual); err != nil { - subT.Error(err) - return - } - - diff := math.Abs(actual - expected) - subT.Logf("\ngot :\t%g\nwant:\t%g\ndiff:\t%g", actual, expected, diff) - if diff > 1e-9 { //Must be within 1 nanosecond of one another - subT.Fail() - } - }) - } -} - -func TestUnixTime_UnmarshalJSON(t *testing.T) { - testCases := []struct { - text string - expected time.Time - }{ - {"1", UnixEpoch().Add(time.Second)}, - {"0", UnixEpoch()}, - {"1492203742", time.Date(2017, time.April, 14, 21, 02, 22, 0, time.UTC)}, // The time this test was written - {"-1", time.Date(1969, time.December, 31, 23, 59, 59, 0, time.UTC)}, - {"1.5", UnixEpoch().Add(1500 * time.Millisecond)}, - {"0e1", UnixEpoch()}, // See http://json.org for 'number' format definition. - {"1.3e+2", UnixEpoch().Add(130 * time.Second)}, - {"1.6E-10", UnixEpoch()}, // This is so small, it should get truncated into the UnixEpoch - {"2E-6", UnixEpoch().Add(2 * time.Microsecond)}, - {"1.289345e9", UnixEpoch().Add(1289345000 * time.Second)}, - {"1e-9", UnixEpoch().Add(time.Nanosecond)}, - } - - for _, tc := range testCases { - t.Run(tc.text, func(subT *testing.T) { - var rehydrated UnixTime - if err := json.Unmarshal([]byte(tc.text), &rehydrated); err != nil { - subT.Error(err) - return - } - - if time.Time(rehydrated) != tc.expected { - subT.Logf("\ngot: \t%v\nwant:\t%v\ndiff:\t%v", time.Time(rehydrated), tc.expected, time.Time(rehydrated).Sub(tc.expected)) - subT.Fail() - } - }) - } -} - -func TestUnixTime_JSONRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - time.Date(2005, time.November, 5, 0, 0, 0, 0, time.UTC), // The day V for Vendetta (film) was released. - UnixEpoch().Add(-6 * time.Second), - UnixEpoch().Add(800 * time.Hour), - UnixEpoch().Add(time.Nanosecond), - time.Date(2015, time.September, 05, 4, 30, 12, 9992, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - subject := UnixTime(tc) - var marshaled []byte - if temp, err := json.Marshal(subject); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled UnixTime - if err := json.Unmarshal(marshaled, &unmarshaled); err != nil { - subT.Error(err) - } - - actual := time.Time(unmarshaled) - diff := actual.Sub(tc) - subT.Logf("\ngot :\t%s\nwant:\t%s\ndiff:\t%s", actual.String(), tc.String(), diff.String()) - - if diff > time.Duration(100) { // We lose some precision be working in floats. We shouldn't lose more than 100 nanoseconds. - subT.Fail() - } - }) - } -} - -func TestUnixTime_MarshalBinary(t *testing.T) { - testCases := []struct { - expected int64 - subject time.Time - }{ - {0, UnixEpoch()}, - {-15 * int64(time.Second), UnixEpoch().Add(-15 * time.Second)}, - {54, UnixEpoch().Add(54 * time.Nanosecond)}, - } - - for _, tc := range testCases { - t.Run("", func(subT *testing.T) { - var marshaled []byte - - if temp, err := UnixTime(tc.subject).MarshalBinary(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled int64 - if err := binary.Read(bytes.NewReader(marshaled), binary.LittleEndian, &unmarshaled); err != nil { - subT.Error(err) - return - } - - if unmarshaled != tc.expected { - subT.Logf("\ngot: \t%d\nwant:\t%d", unmarshaled, tc.expected) - subT.Fail() - } - }) - } -} - -func TestUnixTime_BinaryRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(800 * time.Minute), - UnixEpoch().Add(7 * time.Hour), - UnixEpoch().Add(-1 * time.Nanosecond), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - original := UnixTime(tc) - var marshaled []byte - - if temp, err := original.MarshalBinary(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var traveled UnixTime - if err := traveled.UnmarshalBinary(marshaled); err != nil { - subT.Error(err) - return - } - - if traveled != original { - subT.Logf("\ngot: \t%s\nwant:\t%s", time.Time(original).String(), time.Time(traveled).String()) - subT.Fail() - } - }) - } -} - -func TestUnixTime_MarshalText(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(45 * time.Second), - UnixEpoch().Add(time.Nanosecond), - UnixEpoch().Add(-100000 * time.Second), - } - - for _, tc := range testCases { - expected, _ := tc.MarshalText() - t.Run("", func(subT *testing.T) { - var marshaled []byte - - if temp, err := UnixTime(tc).MarshalText(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - if string(marshaled) != string(expected) { - subT.Logf("\ngot: \t%s\nwant:\t%s", string(marshaled), string(expected)) - subT.Fail() - } - }) - } -} - -func TestUnixTime_TextRoundTrip(t *testing.T) { - testCases := []time.Time{ - UnixEpoch(), - UnixEpoch().Add(-1 * time.Nanosecond), - UnixEpoch().Add(1 * time.Nanosecond), - time.Date(2017, time.April, 17, 21, 00, 00, 00, time.UTC), - } - - for _, tc := range testCases { - t.Run(tc.String(), func(subT *testing.T) { - unixTC := UnixTime(tc) - - var marshaled []byte - - if temp, err := unixTC.MarshalText(); err == nil { - marshaled = temp - } else { - subT.Error(err) - return - } - - var unmarshaled UnixTime - if err := unmarshaled.UnmarshalText(marshaled); err != nil { - subT.Error(err) - return - } - - if unmarshaled != unixTC { - t.Logf("\ngot: \t%s\nwant:\t%s", time.Time(unmarshaled).String(), tc.String()) - t.Fail() - } - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/utility.go b/vendor/github.com/Azure/go-autorest/autorest/date/utility.go deleted file mode 100644 index 12addf0e..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/utility.go +++ /dev/null @@ -1,25 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "strings" - "time" -) - -// ParseTime to parse Time string to specified format. -func ParseTime(format string, t string) (d time.Time, err error) { - return time.Parse(format, strings.ToUpper(t)) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/error.go b/vendor/github.com/Azure/go-autorest/autorest/error.go deleted file mode 100644 index f724f333..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/error.go +++ /dev/null @@ -1,98 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" -) - -const ( - // UndefinedStatusCode is used when HTTP status code is not available for an error. - UndefinedStatusCode = 0 -) - -// DetailedError encloses a error with details of the package, method, and associated HTTP -// status code (if any). -type DetailedError struct { - Original error - - // PackageType is the package type of the object emitting the error. For types, the value - // matches that produced the the '%T' format specifier of the fmt package. For other elements, - // such as functions, it is just the package name (e.g., "autorest"). - PackageType string - - // Method is the name of the method raising the error. - Method string - - // StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error. - StatusCode interface{} - - // Message is the error message. - Message string - - // Service Error is the response body of failed API in bytes - ServiceError []byte - - // Response is the response object that was returned during failure if applicable. - Response *http.Response -} - -// NewError creates a new Error conforming object from the passed packageType, method, and -// message. message is treated as a format string to which the optional args apply. -func NewError(packageType string, method string, message string, args ...interface{}) DetailedError { - return NewErrorWithError(nil, packageType, method, nil, message, args...) -} - -// NewErrorWithResponse creates a new Error conforming object from the passed -// packageType, method, statusCode of the given resp (UndefinedStatusCode if -// resp is nil), and message. message is treated as a format string to which the -// optional args apply. -func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { - return NewErrorWithError(nil, packageType, method, resp, message, args...) -} - -// NewErrorWithError creates a new Error conforming object from the -// passed packageType, method, statusCode of the given resp (UndefinedStatusCode -// if resp is nil), message, and original error. message is treated as a format -// string to which the optional args apply. -func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { - if v, ok := original.(DetailedError); ok { - return v - } - - statusCode := UndefinedStatusCode - if resp != nil { - statusCode = resp.StatusCode - } - - return DetailedError{ - Original: original, - PackageType: packageType, - Method: method, - StatusCode: statusCode, - Message: fmt.Sprintf(message, args...), - Response: resp, - } -} - -// Error returns a formatted containing all available details (i.e., PackageType, Method, -// StatusCode, Message, and original error (if any)). -func (e DetailedError) Error() string { - if e.Original == nil { - return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode) - } - return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/error_test.go b/vendor/github.com/Azure/go-autorest/autorest/error_test.go deleted file mode 100644 index f4f5d75e..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/error_test.go +++ /dev/null @@ -1,202 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "reflect" - "regexp" - "testing" -) - -func TestNewErrorWithError_AssignsPackageType(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.PackageType != "packageType" { - t.Fatalf("autorest: Error failed to set package type -- expected %v, received %v", "packageType", e.PackageType) - } -} - -func TestNewErrorWithError_AssignsMethod(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.Method != "method" { - t.Fatalf("autorest: Error failed to set method -- expected %v, received %v", "method", e.Method) - } -} - -func TestNewErrorWithError_AssignsMessage(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if e.Message != "message" { - t.Fatalf("autorest: Error failed to set message -- expected %v, received %v", "message", e.Message) - } -} - -func TestNewErrorWithError_AssignsUndefinedStatusCodeIfRespNil(t *testing.T) { - e := NewErrorWithError(nil, "packageType", "method", nil, "message") - if e.StatusCode != UndefinedStatusCode { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", UndefinedStatusCode, e.StatusCode) - } -} - -func TestNewErrorWithError_AssignsStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if e.StatusCode != http.StatusBadRequest { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", http.StatusBadRequest, e.StatusCode) - } -} - -func TestNewErrorWithError_AcceptsArgs(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message %s", "arg") - - if matched, _ := regexp.MatchString(`.*arg.*`, e.Message); !matched { - t.Fatalf("autorest: Error failed to apply message arguments -- expected %v, received %v", - `.*arg.*`, e.Message) - } -} - -func TestNewErrorWithError_AssignsError(t *testing.T) { - err := fmt.Errorf("original") - e := NewErrorWithError(err, "packageType", "method", nil, "message") - - if e.Original != err { - t.Fatalf("autorest: Error failed to set error -- expected %v, received %v", err, e.Original) - } -} - -func TestNewErrorWithResponse_ContainsStatusCode(t *testing.T) { - e := NewErrorWithResponse("packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if e.StatusCode != http.StatusBadRequest { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", http.StatusBadRequest, e.StatusCode) - } -} - -func TestNewErrorWithResponse_nilResponse_ReportsUndefinedStatusCode(t *testing.T) { - e := NewErrorWithResponse("packageType", "method", nil, "message") - - if e.StatusCode != UndefinedStatusCode { - t.Fatalf("autorest: Error failed to set status code -- expected %v, received %v", UndefinedStatusCode, e.StatusCode) - } -} - -func TestNewErrorWithResponse_Forwards(t *testing.T) { - e1 := NewError("packageType", "method", "message %s", "arg") - e2 := NewErrorWithResponse("packageType", "method", nil, "message %s", "arg") - - if !reflect.DeepEqual(e1, e2) { - t.Fatal("autorest: NewError did not return an error equivelent to NewErrorWithError") - } -} - -func TestNewErrorWithError_Forwards(t *testing.T) { - e1 := NewError("packageType", "method", "message %s", "arg") - e2 := NewErrorWithError(nil, "packageType", "method", nil, "message %s", "arg") - - if !reflect.DeepEqual(e1, e2) { - t.Fatal("autorest: NewError did not return an error equivelent to NewErrorWithError") - } -} - -func TestNewErrorWithError_DoesNotWrapADetailedError(t *testing.T) { - e1 := NewError("packageType1", "method1", "message1 %s", "arg1") - e2 := NewErrorWithError(e1, "packageType2", "method2", nil, "message2 %s", "arg2") - - if !reflect.DeepEqual(e1, e2) { - t.Fatalf("autorest: NewErrorWithError incorrectly wrapped a DetailedError -- expected %v, received %v", e1, e2) - } -} - -func TestNewErrorWithError_WrapsAnError(t *testing.T) { - e1 := fmt.Errorf("Inner Error") - var e2 interface{} = NewErrorWithError(e1, "packageType", "method", nil, "message") - - if _, ok := e2.(DetailedError); !ok { - t.Fatalf("autorest: NewErrorWithError failed to wrap a standard error -- received %T", e2) - } -} - -func TestDetailedError(t *testing.T) { - err := fmt.Errorf("original") - e := NewErrorWithError(err, "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*original.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#Error failed to return original error message -- expected %v, received %v", - `.*original.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsPackageType(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*packageType.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include PackageType -- expected %v, received %v", - `.*packageType.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsMethod(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*method.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Method -- expected %v, received %v", - `.*method.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsMessage(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*message.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Message -- expected %v, received %v", - `.*message.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsStatusCode(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", &http.Response{ - StatusCode: http.StatusBadRequest, - Status: http.StatusText(http.StatusBadRequest)}, "message") - - if matched, _ := regexp.MatchString(`.*400.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Status Code -- expected %v, received %v", - `.*400.*`, e.Error()) - } -} - -func TestDetailedErrorConstainsOriginal(t *testing.T) { - e := NewErrorWithError(fmt.Errorf("original"), "packageType", "method", nil, "message") - - if matched, _ := regexp.MatchString(`.*original.*`, e.Error()); !matched { - t.Fatalf("autorest: Error#String failed to include Original error -- expected %v, received %v", - `.*original.*`, e.Error()) - } -} - -func TestDetailedErrorSkipsOriginal(t *testing.T) { - e := NewError("packageType", "method", "message") - - if matched, _ := regexp.MatchString(`.*Original.*`, e.Error()); matched { - t.Fatalf("autorest: Error#String included missing Original error -- unexpected %v, received %v", - `.*Original.*`, e.Error()) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/mocks/helpers.go b/vendor/github.com/Azure/go-autorest/autorest/mocks/helpers.go deleted file mode 100644 index 7b1f00d3..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/mocks/helpers.go +++ /dev/null @@ -1,151 +0,0 @@ -package mocks - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "time" -) - -const ( - // TestAuthorizationHeader is a faux HTTP Authorization header value - TestAuthorizationHeader = "BEARER SECRETTOKEN" - - // TestBadURL is a malformed URL - TestBadURL = " " - - // TestDelay is the Retry-After delay used in tests. - TestDelay = 0 * time.Second - - // TestHeader is the header used in tests. - TestHeader = "x-test-header" - - // TestURL is the URL used in tests. - TestURL = "https://microsoft.com/a/b/c/" - - // TestAzureAsyncURL is a URL used in Azure asynchronous tests - TestAzureAsyncURL = "https://microsoft.com/a/b/c/async" - - // TestLocationURL is a URL used in Azure asynchronous tests - TestLocationURL = "https://microsoft.com/a/b/c/location" -) - -const ( - headerLocation = "Location" - headerRetryAfter = "Retry-After" -) - -// NewRequest instantiates a new request. -func NewRequest() *http.Request { - return NewRequestWithContent("") -} - -// NewRequestWithContent instantiates a new request using the passed string for the body content. -func NewRequestWithContent(c string) *http.Request { - r, _ := http.NewRequest("GET", "https://microsoft.com/a/b/c/", NewBody(c)) - return r -} - -// NewRequestWithCloseBody instantiates a new request. -func NewRequestWithCloseBody() *http.Request { - return NewRequestWithCloseBodyContent("request body") -} - -// NewRequestWithCloseBodyContent instantiates a new request using the passed string for the body content. -func NewRequestWithCloseBodyContent(c string) *http.Request { - r, _ := http.NewRequest("GET", "https://microsoft.com/a/b/c/", NewBodyClose(c)) - return r -} - -// NewRequestForURL instantiates a new request using the passed URL. -func NewRequestForURL(u string) *http.Request { - r, err := http.NewRequest("GET", u, NewBody("")) - if err != nil { - panic(fmt.Sprintf("mocks: ERROR (%v) parsing testing URL %s", err, u)) - } - return r -} - -// NewResponse instantiates a new response. -func NewResponse() *http.Response { - return NewResponseWithContent("") -} - -// NewResponseWithContent instantiates a new response with the passed string as the body content. -func NewResponseWithContent(c string) *http.Response { - return &http.Response{ - Status: "200 OK", - StatusCode: 200, - Proto: "HTTP/1.0", - ProtoMajor: 1, - ProtoMinor: 0, - Body: NewBody(c), - Request: NewRequest(), - } -} - -// NewResponseWithStatus instantiates a new response using the passed string and integer as the -// status and status code. -func NewResponseWithStatus(s string, c int) *http.Response { - resp := NewResponse() - resp.Status = s - resp.StatusCode = c - return resp -} - -// NewResponseWithBodyAndStatus instantiates a new response using the specified mock body, -// status and status code -func NewResponseWithBodyAndStatus(body *Body, c int, s string) *http.Response { - resp := NewResponse() - resp.Body = body - resp.Status = s - resp.StatusCode = c - return resp -} - -// SetResponseHeader adds a header to the passed response. -func SetResponseHeader(resp *http.Response, h string, v string) { - if resp.Header == nil { - resp.Header = make(http.Header) - } - resp.Header.Set(h, v) -} - -// SetResponseHeaderValues adds a header containing all the passed string values. -func SetResponseHeaderValues(resp *http.Response, h string, values []string) { - if resp.Header == nil { - resp.Header = make(http.Header) - } - for _, v := range values { - resp.Header.Add(h, v) - } -} - -// SetAcceptedHeaders adds the headers usually associated with a 202 Accepted response. -func SetAcceptedHeaders(resp *http.Response) { - SetLocationHeader(resp, TestURL) - SetRetryHeader(resp, TestDelay) -} - -// SetLocationHeader adds the Location header. -func SetLocationHeader(resp *http.Response, location string) { - SetResponseHeader(resp, http.CanonicalHeaderKey(headerLocation), location) -} - -// SetRetryHeader adds the Retry-After header. -func SetRetryHeader(resp *http.Response, delay time.Duration) { - SetResponseHeader(resp, http.CanonicalHeaderKey(headerRetryAfter), fmt.Sprintf("%v", delay.Seconds())) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/mocks/mocks.go b/vendor/github.com/Azure/go-autorest/autorest/mocks/mocks.go deleted file mode 100644 index 9557ab5e..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/mocks/mocks.go +++ /dev/null @@ -1,219 +0,0 @@ -/* -Package mocks provides mocks and helpers used in testing. -*/ -package mocks - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "io" - "net/http" - "time" -) - -// Body implements acceptable body over a string. -type Body struct { - s string - b []byte - isOpen bool - closeAttempts int -} - -// NewBody creates a new instance of Body. -func NewBody(s string) *Body { - return (&Body{s: s}).reset() -} - -// NewBodyClose creates a new instance of Body. -func NewBodyClose(s string) *Body { - return &Body{s: s} -} - -// Read reads into the passed byte slice and returns the bytes read. -func (body *Body) Read(b []byte) (n int, err error) { - if !body.IsOpen() { - return 0, fmt.Errorf("ERROR: Body has been closed") - } - if len(body.b) == 0 { - return 0, io.EOF - } - n = copy(b, body.b) - body.b = body.b[n:] - return n, nil -} - -// Close closes the body. -func (body *Body) Close() error { - if body.isOpen { - body.isOpen = false - body.closeAttempts++ - } - return nil -} - -// CloseAttempts returns the number of times Close was called. -func (body *Body) CloseAttempts() int { - return body.closeAttempts -} - -// IsOpen returns true if the Body has not been closed, false otherwise. -func (body *Body) IsOpen() bool { - return body.isOpen -} - -func (body *Body) reset() *Body { - body.isOpen = true - body.b = []byte(body.s) - return body -} - -type response struct { - r *http.Response - e error - d time.Duration -} - -// Sender implements a simple null sender. -type Sender struct { - attempts int - responses []response - numResponses int - repeatResponse []int - err error - repeatError int - emitErrorAfter int -} - -// NewSender creates a new instance of Sender. -func NewSender() *Sender { - return &Sender{} -} - -// Do accepts the passed request and, based on settings, emits a response and possible error. -func (c *Sender) Do(r *http.Request) (resp *http.Response, err error) { - c.attempts++ - - if len(c.responses) > 0 { - resp = c.responses[0].r - if resp != nil { - if b, ok := resp.Body.(*Body); ok { - b.reset() - } - } else { - err = c.responses[0].e - } - time.Sleep(c.responses[0].d) - c.repeatResponse[0]-- - if c.repeatResponse[0] == 0 { - c.responses = c.responses[1:] - c.repeatResponse = c.repeatResponse[1:] - } - } else { - resp = NewResponse() - } - if resp != nil { - resp.Request = r - } - - if c.emitErrorAfter > 0 { - c.emitErrorAfter-- - } else if c.err != nil { - err = c.err - c.repeatError-- - if c.repeatError == 0 { - c.err = nil - } - } - - return -} - -// AppendResponse adds the passed http.Response to the response stack. -func (c *Sender) AppendResponse(resp *http.Response) { - c.AppendAndRepeatResponse(resp, 1) -} - -// AppendResponseWithDelay adds the passed http.Response to the response stack with the specified delay. -func (c *Sender) AppendResponseWithDelay(resp *http.Response, delay time.Duration) { - c.AppendAndRepeatResponseWithDelay(resp, delay, 1) -} - -// AppendAndRepeatResponse adds the passed http.Response to the response stack along with a -// repeat count. A negative repeat count will return the response for all remaining calls to Do. -func (c *Sender) AppendAndRepeatResponse(resp *http.Response, repeat int) { - c.appendAndRepeat(response{r: resp}, repeat) -} - -// AppendAndRepeatResponseWithDelay adds the passed http.Response to the response stack with the specified -// delay along with a repeat count. A negative repeat count will return the response for all remaining calls to Do. -func (c *Sender) AppendAndRepeatResponseWithDelay(resp *http.Response, delay time.Duration, repeat int) { - c.appendAndRepeat(response{r: resp, d: delay}, repeat) -} - -// AppendError adds the passed error to the response stack. -func (c *Sender) AppendError(err error) { - c.AppendAndRepeatError(err, 1) -} - -// AppendAndRepeatError adds the passed error to the response stack along with a repeat -// count. A negative repeat count will return the response for all remaining calls to Do. -func (c *Sender) AppendAndRepeatError(err error, repeat int) { - c.appendAndRepeat(response{e: err}, repeat) -} - -func (c *Sender) appendAndRepeat(resp response, repeat int) { - if c.responses == nil { - c.responses = []response{resp} - c.repeatResponse = []int{repeat} - } else { - c.responses = append(c.responses, resp) - c.repeatResponse = append(c.repeatResponse, repeat) - } - c.numResponses++ -} - -// Attempts returns the number of times Do was called. -func (c *Sender) Attempts() int { - return c.attempts -} - -// SetError sets the error Do should return. -func (c *Sender) SetError(err error) { - c.SetAndRepeatError(err, 1) -} - -// SetAndRepeatError sets the error Do should return and how many calls to Do will return the error. -// A negative repeat value will return the error for all remaining calls to Do. -func (c *Sender) SetAndRepeatError(err error, repeat int) { - c.err = err - c.repeatError = repeat -} - -// SetEmitErrorAfter sets the number of attempts to be made before errors are emitted. -func (c *Sender) SetEmitErrorAfter(ea int) { - c.emitErrorAfter = ea -} - -// NumResponses returns the number of responses that have been added to the sender. -func (c *Sender) NumResponses() int { - return c.numResponses -} - -// T is a simple testing struct. -type T struct { - Name string `json:"name" xml:"Name"` - Age int `json:"age" xml:"Age"` -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go deleted file mode 100644 index 6d67bd73..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer.go +++ /dev/null @@ -1,480 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "mime/multipart" - "net/http" - "net/url" - "strings" -) - -const ( - mimeTypeJSON = "application/json" - mimeTypeOctetStream = "application/octet-stream" - mimeTypeFormPost = "application/x-www-form-urlencoded" - - headerAuthorization = "Authorization" - headerContentType = "Content-Type" - headerUserAgent = "User-Agent" -) - -// Preparer is the interface that wraps the Prepare method. -// -// Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations -// must ensure to not share or hold per-invocation state since Preparers may be shared and re-used. -type Preparer interface { - Prepare(*http.Request) (*http.Request, error) -} - -// PreparerFunc is a method that implements the Preparer interface. -type PreparerFunc func(*http.Request) (*http.Request, error) - -// Prepare implements the Preparer interface on PreparerFunc. -func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) { - return pf(r) -} - -// PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then affect the result. -type PrepareDecorator func(Preparer) Preparer - -// CreatePreparer creates, decorates, and returns a Preparer. -// Without decorators, the returned Preparer returns the passed http.Request unmodified. -// Preparers are safe to share and re-use. -func CreatePreparer(decorators ...PrepareDecorator) Preparer { - return DecoratePreparer( - Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })), - decorators...) -} - -// DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it -// applies to the Preparer. Decorators are applied in the order received, but their affect upon the -// request depends on whether they are a pre-decorator (change the http.Request and then pass it -// along) or a post-decorator (pass the http.Request along and alter it on return). -func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer { - for _, decorate := range decorators { - p = decorate(p) - } - return p -} - -// Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators. -// It creates a Preparer from the decorators which it then applies to the passed http.Request. -func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) { - if r == nil { - return nil, NewError("autorest", "Prepare", "Invoked without an http.Request") - } - return CreatePreparer(decorators...).Prepare(r) -} - -// WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed -// http.Request. -func WithNothing() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - return p.Prepare(r) - }) - } -} - -// WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to -// the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before -// adding the header. -func WithHeader(header string, value string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.Header == nil { - r.Header = make(http.Header) - } - r.Header.Set(http.CanonicalHeaderKey(header), value) - } - return r, err - }) - } -} - -// WithHeaders returns a PrepareDecorator that sets the specified HTTP headers of the http.Request to -// the passed value. It canonicalizes the passed headers name (via http.CanonicalHeaderKey) before -// adding them. -func WithHeaders(headers map[string]interface{}) PrepareDecorator { - h := ensureValueStrings(headers) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.Header == nil { - r.Header = make(http.Header) - } - - for name, value := range h { - r.Header.Set(http.CanonicalHeaderKey(name), value) - } - } - return r, err - }) - } -} - -// WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is "Bearer " followed by the supplied token. -func WithBearerAuthorization(token string) PrepareDecorator { - return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token)) -} - -// AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value -// is the passed contentType. -func AsContentType(contentType string) PrepareDecorator { - return WithHeader(headerContentType, contentType) -} - -// WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the -// passed string. -func WithUserAgent(ua string) PrepareDecorator { - return WithHeader(headerUserAgent, ua) -} - -// AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is -// "application/x-www-form-urlencoded". -func AsFormURLEncoded() PrepareDecorator { - return AsContentType(mimeTypeFormPost) -} - -// AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is -// "application/json". -func AsJSON() PrepareDecorator { - return AsContentType(mimeTypeJSON) -} - -// AsOctetStream returns a PrepareDecorator that adds the "application/octet-stream" Content-Type header. -func AsOctetStream() PrepareDecorator { - return AsContentType(mimeTypeOctetStream) -} - -// WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The -// decorator does not validate that the passed method string is a known HTTP method. -func WithMethod(method string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r.Method = method - return p.Prepare(r) - }) - } -} - -// AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE. -func AsDelete() PrepareDecorator { return WithMethod("DELETE") } - -// AsGet returns a PrepareDecorator that sets the HTTP method to GET. -func AsGet() PrepareDecorator { return WithMethod("GET") } - -// AsHead returns a PrepareDecorator that sets the HTTP method to HEAD. -func AsHead() PrepareDecorator { return WithMethod("HEAD") } - -// AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS. -func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") } - -// AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH. -func AsPatch() PrepareDecorator { return WithMethod("PATCH") } - -// AsPost returns a PrepareDecorator that sets the HTTP method to POST. -func AsPost() PrepareDecorator { return WithMethod("POST") } - -// AsPut returns a PrepareDecorator that sets the HTTP method to PUT. -func AsPut() PrepareDecorator { return WithMethod("PUT") } - -// WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed -// from the supplied baseUrl. -func WithBaseURL(baseURL string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - var u *url.URL - if u, err = url.Parse(baseURL); err != nil { - return r, err - } - if u.Scheme == "" { - err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL) - } - if err == nil { - r.URL = u - } - } - return r, err - }) - } -} - -// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the -// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map. -func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator { - parameters := ensureValueStrings(urlParameters) - for key, value := range parameters { - baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1) - } - return WithBaseURL(baseURL) -} - -// WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the -// http.Request body. -func WithFormData(v url.Values) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - s := v.Encode() - - if r.Header == nil { - r.Header = make(http.Header) - } - r.Header.Set(http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost) - r.ContentLength = int64(len(s)) - r.Body = ioutil.NopCloser(strings.NewReader(s)) - } - return r, err - }) - } -} - -// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters -// into the http.Request body. -func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - var body bytes.Buffer - writer := multipart.NewWriter(&body) - for key, value := range formDataParameters { - if rc, ok := value.(io.ReadCloser); ok { - var fd io.Writer - if fd, err = writer.CreateFormFile(key, key); err != nil { - return r, err - } - if _, err = io.Copy(fd, rc); err != nil { - return r, err - } - } else { - if err = writer.WriteField(key, ensureValueString(value)); err != nil { - return r, err - } - } - } - if err = writer.Close(); err != nil { - return r, err - } - if r.Header == nil { - r.Header = make(http.Header) - } - r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType()) - r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) - r.ContentLength = int64(body.Len()) - return r, err - } - return r, err - }) - } -} - -// WithFile returns a PrepareDecorator that sends file in request body. -func WithFile(f io.ReadCloser) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - b, err := ioutil.ReadAll(f) - if err != nil { - return r, err - } - r.Body = ioutil.NopCloser(bytes.NewReader(b)) - r.ContentLength = int64(len(b)) - } - return r, err - }) - } -} - -// WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request -// and sets the Content-Length header. -func WithBool(v bool) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the -// request and sets the Content-Length header. -func WithFloat32(v float32) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the -// request and sets the Content-Length header. -func WithFloat64(v float64) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request -// and sets the Content-Length header. -func WithInt32(v int32) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request -// and sets the Content-Length header. -func WithInt64(v int64) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithString returns a PrepareDecorator that encodes the passed string into the body of the request -// and sets the Content-Length header. -func WithString(v string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - r.ContentLength = int64(len(v)) - r.Body = ioutil.NopCloser(strings.NewReader(v)) - } - return r, err - }) - } -} - -// WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the -// request and sets the Content-Length header. -func WithJSON(v interface{}) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - b, err := json.Marshal(v) - if err == nil { - r.ContentLength = int64(len(b)) - r.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - } - return r, err - }) - } -} - -// WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path -// is absolute (that is, it begins with a "/"), it replaces the existing path. -func WithPath(path string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithPath", "Invoked with a nil URL") - } - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -// WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the -// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The -// values will be escaped (aka URL encoded) before insertion into the path. -func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator { - parameters := escapeValueStrings(ensureValueStrings(pathParameters)) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL") - } - for key, value := range parameters { - path = strings.Replace(path, "{"+key+"}", value, -1) - } - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -// WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the -// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. -func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator { - parameters := ensureValueStrings(pathParameters) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL") - } - for key, value := range parameters { - path = strings.Replace(path, "{"+key+"}", value, -1) - } - - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -func parseURL(u *url.URL, path string) (*url.URL, error) { - p := strings.TrimRight(u.String(), "/") - if !strings.HasPrefix(path, "/") { - path = "/" + path - } - return url.Parse(p + path) -} - -// WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters -// given in the supplied map (i.e., key=value). -func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator { - parameters := ensureValueStrings(queryParameters) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL") - } - - v := r.URL.Query() - for key, value := range parameters { - d, err := url.QueryUnescape(value) - if err != nil { - return r, err - } - v.Add(key, d) - } - r.URL.RawQuery = v.Encode() - } - return r, err - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go b/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go deleted file mode 100644 index b4d19967..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer_test.go +++ /dev/null @@ -1,802 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -// PrepareDecorators wrap and invoke a Preparer. Most often, the decorator invokes the passed -// Preparer and decorates the response. -func ExamplePrepareDecorator() { - path := "a/b/c/" - pd := func() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, fmt.Errorf("ERROR: URL is not set") - } - r.URL.Path += path - } - return r, err - }) - } - } - - r, _ := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - pd()) - - fmt.Printf("Path is %s\n", r.URL) - // Output: Path is https://microsoft.com/a/b/c/ -} - -// PrepareDecorators may also modify and then invoke the Preparer. -func ExamplePrepareDecorator_pre() { - pd := func() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r.Header.Add(http.CanonicalHeaderKey("ContentType"), "application/json") - return p.Prepare(r) - }) - } - } - - r, _ := Prepare(&http.Request{Header: http.Header{}}, - pd()) - - fmt.Printf("ContentType is %s\n", r.Header.Get("ContentType")) - // Output: ContentType is application/json -} - -// Create a sequence of three Preparers that build up the URL path. -func ExampleCreatePreparer() { - p := CreatePreparer( - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) - r, err := p.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c -} - -// Create and apply separate Preparers -func ExampleCreatePreparer_multiple() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - - p1 := CreatePreparer(WithBaseURL("https://microsoft.com/")) - p2 := CreatePreparer(WithPathParameters("/{param1}/b/{param2}/", params)) - - r, err := p1.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - r, err = p2.Prepare(r) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create and chain separate Preparers -func ExampleCreatePreparer_chain() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - - p := CreatePreparer(WithBaseURL("https://microsoft.com/")) - p = DecoratePreparer(p, WithPathParameters("/{param1}/b/{param2}/", params)) - - r, err := p.Prepare(&http.Request{}) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create and prepare an http.Request in one call -func ExamplePrepare() { - r, err := Prepare(&http.Request{}, - AsGet(), - WithBaseURL("https://microsoft.com/"), - WithPath("a/b/c/")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("%s %s", r.Method, r.URL) - } - // Output: GET https://microsoft.com/a/b/c/ -} - -// Create a request for a supplied base URL and path -func ExampleWithBaseURL() { - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/a/b/c/")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -func ExampleWithBaseURL_second() { - _, err := Prepare(&http.Request{}, WithBaseURL(":")) - fmt.Println(err) - // Output: parse :: missing protocol scheme -} - -func ExampleWithCustomBaseURL() { - r, err := Prepare(&http.Request{}, - WithCustomBaseURL("https://{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://myaccount.blob.core.windows.net/ -} - -func ExampleWithCustomBaseURL_second() { - _, err := Prepare(&http.Request{}, - WithCustomBaseURL(":", map[string]interface{}{})) - fmt.Println(err) - // Output: parse :: missing protocol scheme -} - -// Create a request with a custom HTTP header -func ExampleWithHeader() { - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/a/b/c/"), - WithHeader("x-foo", "bar")) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Header %s=%s\n", "x-foo", r.Header.Get("x-foo")) - } - // Output: Header x-foo=bar -} - -// Create a request whose Body is the JSON encoding of a structure -func ExampleWithFormData() { - v := url.Values{} - v.Add("name", "Rob Pike") - v.Add("age", "42") - - r, err := Prepare(&http.Request{}, - WithFormData(v)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Request Body contains %s\n", string(b)) - } - // Output: Request Body contains age=42&name=Rob+Pike -} - -// Create a request whose Body is the JSON encoding of a structure -func ExampleWithJSON() { - t := mocks.T{Name: "Rob Pike", Age: 42} - - r, err := Prepare(&http.Request{}, - WithJSON(&t)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Printf("Request Body contains %s\n", string(b)) - } - // Output: Request Body contains {"name":"Rob Pike","age":42} -} - -// Create a request from a path with escaped parameters -func ExampleWithEscapedPathParameters() { - params := map[string]interface{}{ - "param1": "a b c", - "param2": "d e f", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithEscapedPathParameters("/{param1}/b/{param2}/", params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a+b+c/b/d+e+f/ -} - -// Create a request from a path with parameters -func ExampleWithPathParameters() { - params := map[string]interface{}{ - "param1": "a", - "param2": "c", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPathParameters("/{param1}/b/{param2}/", params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/ -} - -// Create a request with query parameters -func ExampleWithQueryParameters() { - params := map[string]interface{}{ - "q1": "value1", - "q2": "value2", - } - r, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("/a/b/c/"), - WithQueryParameters(params)) - if err != nil { - fmt.Printf("ERROR: %v\n", err) - } else { - fmt.Println(r.URL) - } - // Output: https://microsoft.com/a/b/c/?q1=value1&q2=value2 -} - -func TestWithCustomBaseURL(t *testing.T) { - r, err := Prepare(&http.Request{}, WithCustomBaseURL("https://{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err != nil { - t.Fatalf("autorest: WithCustomBaseURL should not fail") - } - if r.URL.String() != "https://myaccount.blob.core.windows.net/" { - t.Fatalf("autorest: WithCustomBaseURL expected https://myaccount.blob.core.windows.net/, got %s", r.URL) - } -} - -func TestWithCustomBaseURLwithInvalidURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithCustomBaseURL("hello/{account}.{service}.core.windows.net/", - map[string]interface{}{ - "account": "myaccount", - "service": "blob", - })) - if err == nil { - t.Fatalf("autorest: WithCustomBaseURL should fail fo URL parse error") - } -} - -func TestWithPathWithInvalidPath(t *testing.T) { - p := "path%2*end" - if _, err := Prepare(&http.Request{}, WithBaseURL("https://microsoft.com/"), WithPath(p)); err == nil { - t.Fatalf("autorest: WithPath should fail for invalid URL escape error for path '%v' ", p) - } - -} - -func TestWithPathParametersWithInvalidPath(t *testing.T) { - p := "path%2*end" - m := map[string]interface{}{ - "path1": p, - } - if _, err := Prepare(&http.Request{}, WithBaseURL("https://microsoft.com/"), WithPathParameters("/{path1}/", m)); err == nil { - t.Fatalf("autorest: WithPath should fail for invalid URL escape for path '%v' ", p) - } - -} - -func TestCreatePreparerDoesNotModify(t *testing.T) { - r1 := &http.Request{} - p := CreatePreparer() - r2, err := p.Prepare(r1) - if err != nil { - t.Fatalf("autorest: CreatePreparer failed (%v)", err) - } - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: CreatePreparer without decorators modified the request") - } -} - -func TestCreatePreparerRunsDecoratorsInOrder(t *testing.T) { - p := CreatePreparer(WithBaseURL("https://microsoft.com/"), WithPath("1"), WithPath("2"), WithPath("3")) - r, err := p.Prepare(&http.Request{}) - if err != nil { - t.Fatalf("autorest: CreatePreparer failed (%v)", err) - } - if r.URL.String() != "https:/1/2/3" && r.URL.Host != "microsoft.com" { - t.Fatalf("autorest: CreatePreparer failed to run decorators in order") - } -} - -func TestAsContentType(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsContentType("application/text")) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != "application/text" { - t.Fatalf("autorest: AsContentType failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestAsFormURLEncoded(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsFormURLEncoded()) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != mimeTypeFormPost { - t.Fatalf("autorest: AsFormURLEncoded failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestAsJSON(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), AsJSON()) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerContentType) != mimeTypeJSON { - t.Fatalf("autorest: AsJSON failed to add header (%s=%s)", headerContentType, r.Header.Get(headerContentType)) - } -} - -func TestWithNothing(t *testing.T) { - r1 := mocks.NewRequest() - r2, err := Prepare(r1, WithNothing()) - if err != nil { - t.Fatalf("autorest: WithNothing returned an unexpected error (%v)", err) - } - - if !reflect.DeepEqual(r1, r2) { - t.Fatal("azure: WithNothing modified the passed HTTP Request") - } -} - -func TestWithBearerAuthorization(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), WithBearerAuthorization("SOME-TOKEN")) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.Header.Get(headerAuthorization) != "Bearer SOME-TOKEN" { - t.Fatalf("autorest: WithBearerAuthorization failed to add header (%s=%s)", headerAuthorization, r.Header.Get(headerAuthorization)) - } -} - -func TestWithUserAgent(t *testing.T) { - ua := "User Agent Go" - r, err := Prepare(mocks.NewRequest(), WithUserAgent(ua)) - if err != nil { - fmt.Printf("ERROR: %v", err) - } - if r.UserAgent() != ua || r.Header.Get(headerUserAgent) != ua { - t.Fatalf("autorest: WithUserAgent failed to add header (%s=%s)", headerUserAgent, r.Header.Get(headerUserAgent)) - } -} - -func TestWithMethod(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), WithMethod("HEAD")) - if r.Method != "HEAD" { - t.Fatal("autorest: WithMethod failed to set HTTP method header") - } -} - -func TestAsDelete(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsDelete()) - if r.Method != "DELETE" { - t.Fatal("autorest: AsDelete failed to set HTTP method header to DELETE") - } -} - -func TestAsGet(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsGet()) - if r.Method != "GET" { - t.Fatal("autorest: AsGet failed to set HTTP method header to GET") - } -} - -func TestAsHead(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsHead()) - if r.Method != "HEAD" { - t.Fatal("autorest: AsHead failed to set HTTP method header to HEAD") - } -} - -func TestAsOptions(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsOptions()) - if r.Method != "OPTIONS" { - t.Fatal("autorest: AsOptions failed to set HTTP method header to OPTIONS") - } -} - -func TestAsPatch(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPatch()) - if r.Method != "PATCH" { - t.Fatal("autorest: AsPatch failed to set HTTP method header to PATCH") - } -} - -func TestAsPost(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPost()) - if r.Method != "POST" { - t.Fatal("autorest: AsPost failed to set HTTP method header to POST") - } -} - -func TestAsPut(t *testing.T) { - r, _ := Prepare(mocks.NewRequest(), AsPut()) - if r.Method != "PUT" { - t.Fatal("autorest: AsPut failed to set HTTP method header to PUT") - } -} - -func TestPrepareWithNullRequest(t *testing.T) { - _, err := Prepare(nil) - if err == nil { - t.Fatal("autorest: Prepare failed to return an error when given a null http.Request") - } -} - -func TestWithFormData(t *testing.T) { - v := url.Values{} - v.Add("name", "Rob Pike") - v.Add("age", "42") - - r, err := Prepare(&http.Request{}, - WithFormData(v)) - if err != nil { - t.Fatalf("autorest: WithFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFormData failed with error (%v)", err) - } - - expected := "name=Rob+Pike&age=42" - if !(string(b) == "name=Rob+Pike&age=42" || string(b) == "age=42&name=Rob+Pike") { - t.Fatalf("autorest:WithFormData failed to return correct string got (%v), expected (%v)", string(b), expected) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } - - if expected, got := r.Header.Get(http.CanonicalHeaderKey(headerContentType)), mimeTypeFormPost; expected != got { - t.Fatalf("autorest:WithFormData Content Type not set or set to wrong value. Expected %v and got %v", expected, got) - } -} - -func TestWithMultiPartFormDataSetsContentLength(t *testing.T) { - v := map[string]interface{}{ - "file": ioutil.NopCloser(strings.NewReader("Hello Gopher")), - "age": "42", - } - - r, err := Prepare(&http.Request{}, - WithMultiPartFormData(v)) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithMultiPartFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithMultiPartFormDataWithNoFile(t *testing.T) { - v := map[string]interface{}{ - "file": "no file", - "age": "42", - } - - r, err := Prepare(&http.Request{}, - WithMultiPartFormData(v)) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithMultiPartFormData failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithMultiPartFormData set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithFile(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFile(ioutil.NopCloser(strings.NewReader("Hello Gopher")))) - if err != nil { - t.Fatalf("autorest: WithFile failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFile failed with error (%v)", err) - } - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithFile set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithBool_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithBool(false)) - if err != nil { - t.Fatalf("autorest: WithBool failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithBool failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", false))) { - t.Fatalf("autorest: WithBool set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", false)))) - } - - v, err := strconv.ParseBool(string(s)) - if err != nil || v { - t.Fatalf("autorest: WithBool incorrectly encoded the boolean as %v", s) - } -} - -func TestWithFloat32_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFloat32(42.0)) - if err != nil { - t.Fatalf("autorest: WithFloat32 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFloat32 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42.0))) { - t.Fatalf("autorest: WithFloat32 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42.0)))) - } - - v, err := strconv.ParseFloat(string(s), 32) - if err != nil || float32(v) != float32(42.0) { - t.Fatalf("autorest: WithFloat32 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithFloat64_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithFloat64(42.0)) - if err != nil { - t.Fatalf("autorest: WithFloat64 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithFloat64 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42.0))) { - t.Fatalf("autorest: WithFloat64 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42.0)))) - } - - v, err := strconv.ParseFloat(string(s), 64) - if err != nil || v != float64(42.0) { - t.Fatalf("autorest: WithFloat64 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithInt32_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithInt32(42)) - if err != nil { - t.Fatalf("autorest: WithInt32 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithInt32 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42))) { - t.Fatalf("autorest: WithInt32 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42)))) - } - - v, err := strconv.ParseInt(string(s), 10, 32) - if err != nil || int32(v) != int32(42) { - t.Fatalf("autorest: WithInt32 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithInt64_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithInt64(42)) - if err != nil { - t.Fatalf("autorest: WithInt64 failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithInt64 failed with error (%v)", err) - } - - if r.ContentLength != int64(len(fmt.Sprintf("%v", 42))) { - t.Fatalf("autorest: WithInt64 set Content-Length to %v, expected %v", r.ContentLength, int64(len(fmt.Sprintf("%v", 42)))) - } - - v, err := strconv.ParseInt(string(s), 10, 64) - if err != nil || v != int64(42) { - t.Fatalf("autorest: WithInt64 incorrectly encoded the boolean as %v", s) - } -} - -func TestWithString_SetsTheBody(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithString("value")) - if err != nil { - t.Fatalf("autorest: WithString failed with error (%v)", err) - } - - s, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithString failed with error (%v)", err) - } - - if r.ContentLength != int64(len("value")) { - t.Fatalf("autorest: WithString set Content-Length to %v, expected %v", r.ContentLength, int64(len("value"))) - } - - if string(s) != "value" { - t.Fatalf("autorest: WithString incorrectly encoded the string as %v", s) - } -} - -func TestWithJSONSetsContentLength(t *testing.T) { - r, err := Prepare(&http.Request{}, - WithJSON(&mocks.T{Name: "Rob Pike", Age: 42})) - if err != nil { - t.Fatalf("autorest: WithJSON failed with error (%v)", err) - } - - b, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: WithJSON failed with error (%v)", err) - } - - if r.ContentLength != int64(len(b)) { - t.Fatalf("autorest:WithJSON set Content-Length to %v, expected %v", r.ContentLength, len(b)) - } -} - -func TestWithHeaderAllocatesHeaders(t *testing.T) { - r, err := Prepare(mocks.NewRequest(), WithHeader("x-foo", "bar")) - if err != nil { - t.Fatalf("autorest: WithHeader failed (%v)", err) - } - if r.Header.Get("x-foo") != "bar" { - t.Fatalf("autorest: WithHeader failed to add header (%s=%s)", "x-foo", r.Header.Get("x-foo")) - } -} - -func TestWithPathCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithPath("a")) - if err == nil { - t.Fatalf("autorest: WithPath failed to catch a nil URL") - } -} - -func TestWithEscapedPathParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithEscapedPathParameters("", map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithEscapedPathParameters failed to catch a nil URL") - } -} - -func TestWithPathParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithPathParameters("", map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithPathParameters failed to catch a nil URL") - } -} - -func TestWithQueryParametersCatchesNilURL(t *testing.T) { - _, err := Prepare(&http.Request{}, WithQueryParameters(map[string]interface{}{"foo": "bar"})) - if err == nil { - t.Fatalf("autorest: WithQueryParameters failed to catch a nil URL") - } -} - -func TestModifyingExistingRequest(t *testing.T) { - r, err := Prepare(mocks.NewRequestForURL("https://bing.com"), WithPath("search"), WithQueryParameters(map[string]interface{}{"q": "golang"})) - if err != nil { - t.Fatalf("autorest: Preparing an existing request returned an error (%v)", err) - } - if r.URL.Host != "bing.com" { - t.Fatalf("autorest: Preparing an existing request failed when setting the host (%s)", r.URL) - } - - if r.URL.Path != "/search" { - t.Fatalf("autorest: Preparing an existing request failed when setting the path (%s)", r.URL.Path) - } - - if r.URL.RawQuery != "q=golang" { - t.Fatalf("autorest: Preparing an existing request failed when setting the query parameters (%s)", r.URL.RawQuery) - } -} - -func TestModifyingRequestWithExistingQueryParameters(t *testing.T) { - r, err := Prepare( - mocks.NewRequestForURL("https://bing.com"), - WithPath("search"), - WithQueryParameters(map[string]interface{}{"q": "golang the best"}), - WithQueryParameters(map[string]interface{}{"pq": "golang+encoded"}), - ) - if err != nil { - t.Fatalf("autorest: Preparing an existing request returned an error (%v)", err) - } - - if r.URL.Host != "bing.com" { - t.Fatalf("autorest: Preparing an existing request failed when setting the host (%s)", r.URL) - } - - if r.URL.Path != "/search" { - t.Fatalf("autorest: Preparing an existing request failed when setting the path (%s)", r.URL.Path) - } - - if r.URL.RawQuery != "pq=golang+encoded&q=golang+the+best" { - t.Fatalf("autorest: Preparing an existing request failed when setting the query parameters (%s)", r.URL.RawQuery) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder.go b/vendor/github.com/Azure/go-autorest/autorest/responder.go deleted file mode 100644 index a908a0ad..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/responder.go +++ /dev/null @@ -1,250 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "io/ioutil" - "net/http" - "strings" -) - -// Responder is the interface that wraps the Respond method. -// -// Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold -// state since Responders may be shared and re-used. -type Responder interface { - Respond(*http.Response) error -} - -// ResponderFunc is a method that implements the Responder interface. -type ResponderFunc func(*http.Response) error - -// Respond implements the Responder interface on ResponderFunc. -func (rf ResponderFunc) Respond(r *http.Response) error { - return rf(r) -} - -// RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to -// the http.Response and pass it along or, first, pass the http.Response along then react. -type RespondDecorator func(Responder) Responder - -// CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned -// Responder returns the passed http.Response unmodified. Responders may or may not be safe to share -// and re-used: It depends on the applied decorators. For example, a standard decorator that closes -// the response body is fine to share whereas a decorator that reads the body into a passed struct -// is not. -// -// To prevent memory leaks, ensure that at least one Responder closes the response body. -func CreateResponder(decorators ...RespondDecorator) Responder { - return DecorateResponder( - Responder(ResponderFunc(func(r *http.Response) error { return nil })), - decorators...) -} - -// DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it -// applies to the Responder. Decorators are applied in the order received, but their affect upon the -// request depends on whether they are a pre-decorator (react to the http.Response and then pass it -// along) or a post-decorator (pass the http.Response along and then react). -func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder { - for _, decorate := range decorators { - r = decorate(r) - } - return r -} - -// Respond accepts an http.Response and a, possibly empty, set of RespondDecorators. -// It creates a Responder from the decorators it then applies to the passed http.Response. -func Respond(r *http.Response, decorators ...RespondDecorator) error { - if r == nil { - return nil - } - return CreateResponder(decorators...).Respond(r) -} - -// ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined -// to the next RespondDecorator. -func ByIgnoring() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - return r.Respond(resp) - }) - } -} - -// ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as -// the Body is read. -func ByCopying(b *bytes.Buffer) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && resp != nil && resp.Body != nil { - resp.Body = TeeReadCloser(resp.Body, b) - } - return err - }) - } -} - -// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which -// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed -// Responder is invoked prior to discarding the response body, the decorator may occur anywhere -// within the set. -func ByDiscardingBody() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && resp != nil && resp.Body != nil { - if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { - return fmt.Errorf("Error discarding the response body: %v", err) - } - } - return err - }) - } -} - -// ByClosing returns a RespondDecorator that first invokes the passed Responder after which it -// closes the response body. Since the passed Responder is invoked prior to closing the response -// body, the decorator may occur anywhere within the set. -func ByClosing() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if resp != nil && resp.Body != nil { - if err := resp.Body.Close(); err != nil { - return fmt.Errorf("Error closing the response body: %v", err) - } - } - return err - }) - } -} - -// ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which -// it closes the response if the passed Responder returns an error and the response body exists. -func ByClosingIfError() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err != nil && resp != nil && resp.Body != nil { - if err := resp.Body.Close(); err != nil { - return fmt.Errorf("Error closing the response body: %v", err) - } - } - return err - }) - } -} - -// ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the -// response Body into the value pointed to by v. -func ByUnmarshallingJSON(v interface{}) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - b, errInner := ioutil.ReadAll(resp.Body) - // Some responses might include a BOM, remove for successful unmarshalling - b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf")) - if errInner != nil { - err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) - } else if len(strings.Trim(string(b), " ")) > 0 { - errInner = json.Unmarshal(b, v) - if errInner != nil { - err = fmt.Errorf("Error occurred unmarshalling JSON - Error = '%v' JSON = '%s'", errInner, string(b)) - } - } - } - return err - }) - } -} - -// ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the -// response Body into the value pointed to by v. -func ByUnmarshallingXML(v interface{}) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - b, errInner := ioutil.ReadAll(resp.Body) - if errInner != nil { - err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) - } else { - errInner = xml.Unmarshal(b, v) - if errInner != nil { - err = fmt.Errorf("Error occurred unmarshalling Xml - Error = '%v' Xml = '%s'", errInner, string(b)) - } - } - } - return err - }) - } -} - -// WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response -// StatusCode is among the set passed. On error, response body is fully read into a buffer and -// presented in the returned error, as well as in the response body. -func WithErrorUnlessStatusCode(codes ...int) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && !ResponseHasStatusCode(resp, codes...) { - derr := NewErrorWithResponse("autorest", "WithErrorUnlessStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - if resp.Body != nil { - defer resp.Body.Close() - b, _ := ioutil.ReadAll(resp.Body) - derr.ServiceError = b - resp.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - err = derr - } - return err - }) - } -} - -// WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is -// anything other than HTTP 200. -func WithErrorUnlessOK() RespondDecorator { - return WithErrorUnlessStatusCode(http.StatusOK) -} - -// ExtractHeader extracts all values of the specified header from the http.Response. It returns an -// empty string slice if the passed http.Response is nil or the header does not exist. -func ExtractHeader(header string, resp *http.Response) []string { - if resp != nil && resp.Header != nil { - return resp.Header[http.CanonicalHeaderKey(header)] - } - return nil -} - -// ExtractHeaderValue extracts the first value of the specified header from the http.Response. It -// returns an empty string if the passed http.Response is nil or the header does not exist. -func ExtractHeaderValue(header string, resp *http.Response) string { - h := ExtractHeader(header, resp) - if len(h) > 0 { - return h[0] - } - return "" -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder_test.go b/vendor/github.com/Azure/go-autorest/autorest/responder_test.go deleted file mode 100644 index 4a57b1e3..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/responder_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func ExampleWithErrorUnlessOK() { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - - // Respond and leave the response body open (for a subsequent responder to close) - err := Respond(r, - WithErrorUnlessOK(), - ByDiscardingBody(), - ByClosingIfError()) - - if err == nil { - fmt.Printf("%s of %s returned HTTP 200", r.Request.Method, r.Request.URL) - - // Complete handling the response and close the body - Respond(r, - ByDiscardingBody(), - ByClosing()) - } - // Output: GET of https://microsoft.com/a/b/c/ returned HTTP 200 -} - -func ExampleByUnmarshallingJSON() { - c := ` - { - "name" : "Rob Pike", - "age" : 42 - } - ` - - type V struct { - Name string `json:"name"` - Age int `json:"age"` - } - - v := &V{} - - Respond(mocks.NewResponseWithContent(c), - ByUnmarshallingJSON(v), - ByClosing()) - - fmt.Printf("%s is %d years old\n", v.Name, v.Age) - // Output: Rob Pike is 42 years old -} - -func ExampleByUnmarshallingXML() { - c := ` - - Rob Pike - 42 - ` - - type V struct { - Name string `xml:"Name"` - Age int `xml:"Age"` - } - - v := &V{} - - Respond(mocks.NewResponseWithContent(c), - ByUnmarshallingXML(v), - ByClosing()) - - fmt.Printf("%s is %d years old\n", v.Name, v.Age) - // Output: Rob Pike is 42 years old -} - -func TestCreateResponderDoesNotModify(t *testing.T) { - r1 := mocks.NewResponse() - r2 := mocks.NewResponse() - p := CreateResponder() - err := p.Respond(r1) - if err != nil { - t.Fatalf("autorest: CreateResponder failed (%v)", err) - } - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: CreateResponder without decorators modified the response") - } -} - -func TestCreateResponderRunsDecoratorsInOrder(t *testing.T) { - s := "" - - d := func(n int) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - s += fmt.Sprintf("%d", n) - } - return err - }) - } - } - - p := CreateResponder(d(1), d(2), d(3)) - err := p.Respond(&http.Response{}) - if err != nil { - t.Fatalf("autorest: Respond failed (%v)", err) - } - - if s != "123" { - t.Fatalf("autorest: CreateResponder invoked decorators in an incorrect order; expected '123', received '%s'", s) - } -} - -func TestByIgnoring(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(r2 *http.Response) error { - r1 := mocks.NewResponse() - if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: ByIgnoring modified the HTTP Response -- received %v, expected %v", r2, r1) - } - return nil - }) - } - })(), - ByIgnoring(), - ByClosing()) -} - -func TestByCopying_Copies(t *testing.T) { - r := mocks.NewResponseWithContent(jsonT) - b := &bytes.Buffer{} - - err := Respond(r, - ByCopying(b), - ByUnmarshallingJSON(&mocks.T{}), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByCopying returned an unexpected error -- %v", err) - } - if b.String() != jsonT { - t.Fatalf("autorest: ByCopying failed to copy the bytes read") - } -} - -func TestByCopying_ReturnsNestedErrors(t *testing.T) { - r := mocks.NewResponseWithContent(jsonT) - - r.Body.Close() - err := Respond(r, - ByCopying(&bytes.Buffer{}), - ByUnmarshallingJSON(&mocks.T{}), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByCopying failed to return the expected error") - } -} - -func TestByCopying_AcceptsNilReponse(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByCopying(&bytes.Buffer{})) -} - -func TestByCopying_AcceptsNilBody(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByCopying(&bytes.Buffer{})) -} - -func TestByClosing(t *testing.T) { - r := mocks.NewResponse() - err := Respond(r, ByClosing()) - if err != nil { - t.Fatalf("autorest: ByClosing failed (%v)", err) - } - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosing did not close the response body") - } -} - -func TestByClosingAcceptsNilResponse(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByClosing()) -} - -func TestByClosingAcceptsNilBody(t *testing.T) { - r := mocks.NewResponse() - - Respond(r, - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByClosing()) -} - -func TestByClosingClosesEvenAfterErrors(t *testing.T) { - var e error - - r := mocks.NewResponse() - Respond(r, - withErrorRespondDecorator(&e), - ByClosing()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosing did not close the response body after an error occurred") - } -} - -func TestByClosingClosesReturnsNestedErrors(t *testing.T) { - var e error - - r := mocks.NewResponse() - err := Respond(r, - withErrorRespondDecorator(&e), - ByClosing()) - - if err == nil || !reflect.DeepEqual(e, err) { - t.Fatalf("autorest: ByClosing failed to return a nested error") - } -} - -func TestByClosingIfErrorAcceptsNilResponse(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByClosingIfError()) -} - -func TestByClosingIfErrorAcceptsNilBody(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByClosingIfError()) -} - -func TestByClosingIfErrorClosesIfAnErrorOccurs(t *testing.T) { - var e error - - r := mocks.NewResponse() - Respond(r, - withErrorRespondDecorator(&e), - ByClosingIfError()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosingIfError did not close the response body after an error occurred") - } -} - -func TestByClosingIfErrorDoesNotClosesIfNoErrorOccurs(t *testing.T) { - r := mocks.NewResponse() - Respond(r, - ByClosingIfError()) - - if !r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: ByClosingIfError closed the response body even though no error occurred") - } -} - -func TestByDiscardingBody(t *testing.T) { - r := mocks.NewResponse() - err := Respond(r, - ByDiscardingBody()) - if err != nil { - t.Fatalf("autorest: ByDiscardingBody failed (%v)", err) - } - buf, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("autorest: Reading result of ByDiscardingBody failed (%v)", err) - } - - if len(buf) != 0 { - t.Logf("autorest: Body was not empty after calling ByDiscardingBody.") - t.Fail() - } -} - -func TestByDiscardingBodyAcceptsNilResponse(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - r.Respond(nil) - return nil - }) - } - })(), - ByDiscardingBody()) -} - -func TestByDiscardingBodyAcceptsNilBody(t *testing.T) { - var e error - - r := mocks.NewResponse() - - Respond(r, - withErrorRespondDecorator(&e), - (func() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - resp.Body.Close() - resp.Body = nil - r.Respond(resp) - return nil - }) - } - })(), - ByDiscardingBody()) -} - -func TestByUnmarshallingJSON(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed (%v)", err) - } - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: ByUnmarshallingJSON failed to properly unmarshal") - } -} - -func TestByUnmarshallingJSON_HandlesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - r.Body.(*mocks.Body).Close() - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed to receive / respond to read error") - } -} - -func TestByUnmarshallingJSONIncludesJSONInErrors(t *testing.T) { - v := &mocks.T{} - j := jsonT[0 : len(jsonT)-2] - r := mocks.NewResponseWithContent(j) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil || !strings.Contains(err.Error(), j) { - t.Fatalf("autorest: ByUnmarshallingJSON failed to return JSON in error (%v)", err) - } -} - -func TestByUnmarshallingJSONEmptyInput(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(``) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingJSON failed to return nil in case of empty JSON (%v)", err) - } -} - -func TestByUnmarshallingXML(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(xmlT) - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: ByUnmarshallingXML failed (%v)", err) - } - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: ByUnmarshallingXML failed to properly unmarshal") - } -} - -func TestByUnmarshallingXML_HandlesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(xmlT) - r.Body.(*mocks.Body).Close() - - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: ByUnmarshallingXML failed to receive / respond to read error") - } -} - -func TestByUnmarshallingXMLIncludesXMLInErrors(t *testing.T) { - v := &mocks.T{} - x := xmlT[0 : len(xmlT)-2] - r := mocks.NewResponseWithContent(x) - err := Respond(r, - ByUnmarshallingXML(v), - ByClosing()) - if err == nil || !strings.Contains(err.Error(), x) { - t.Fatalf("autorest: ByUnmarshallingXML failed to return XML in error (%v)", err) - } -} - -func TestRespondAcceptsNullResponse(t *testing.T) { - err := Respond(nil) - if err != nil { - t.Fatalf("autorest: Respond returned an unexpected error when given a null Response (%v)", err) - } -} - -func TestWithErrorUnlessStatusCodeOKResponse(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - ByUnmarshallingJSON(v), - ByClosing()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) failed on okay response. (%v)", err) - } - - if v.Name != "Rob Pike" || v.Age != 42 { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) corrupted the response body of okay response.") - } -} - -func TesWithErrorUnlessStatusCodeErrorResponse(t *testing.T) { - v := &mocks.T{} - e := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK), - ByUnmarshallingJSON(v), - ByClosing()) - - if err == nil { - t.Fatal("autorest: WithErrorUnlessStatusCode(http.StatusOK) did not return error, on a response to a bad request.") - } - - var errorRespBody []byte - if derr, ok := err.(DetailedError); !ok { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) got wrong error type : %T, expected: DetailedError, on a response to a bad request.", err) - } else { - errorRespBody = derr.ServiceError - } - - if errorRespBody == nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) ServiceError not returned in DetailedError on a response to a bad request.") - } - - err = json.Unmarshal(errorRespBody, e) - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) cannot parse error returned in ServiceError into json. %v", err) - } - - expected := &mocks.T{Name: "Rob Pike", Age: 42} - if e != expected { - t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK wrong value from parsed ServiceError: got=%#v expected=%#v", e, expected) - } -} - -func TestWithErrorUnlessStatusCode(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError), - ByClosingIfError()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode returned an error (%v) for an acceptable status code (%s)", err, r.Status) - } -} - -func TestWithErrorUnlessStatusCodeEmitsErrorForUnacceptableStatusCode(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessStatusCode(http.StatusOK, http.StatusUnauthorized, http.StatusInternalServerError), - ByClosingIfError()) - - if err == nil { - t.Fatalf("autorest: WithErrorUnlessStatusCode failed to return an error for an unacceptable status code (%s)", r.Status) - } -} - -func TestWithErrorUnlessOK(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - - err := Respond(r, - WithErrorUnlessOK(), - ByClosingIfError()) - - if err != nil { - t.Fatalf("autorest: WithErrorUnlessOK returned an error for OK status code (%v)", err) - } -} - -func TestWithErrorUnlessOKEmitsErrorIfNotOK(t *testing.T) { - r := mocks.NewResponse() - r.Request = mocks.NewRequest() - r.Status = "400 BadRequest" - r.StatusCode = http.StatusBadRequest - - err := Respond(r, - WithErrorUnlessOK(), - ByClosingIfError()) - - if err == nil { - t.Fatalf("autorest: WithErrorUnlessOK failed to return an error for a non-OK status code (%v)", err) - } -} - -func TestExtractHeader(t *testing.T) { - r := mocks.NewResponse() - v := []string{"v1", "v2", "v3"} - mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) - - if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeader(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderHandlesMissingHeader(t *testing.T) { - var v []string - r := mocks.NewResponse() - - if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { - t.Fatalf("autorest: ExtractHeader failed to handle a missing header -- expected %v, received %v", - v, ExtractHeader(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValue(t *testing.T) { - r := mocks.NewResponse() - v := "v1" - mocks.SetResponseHeader(r, mocks.TestHeader, v) - - if ExtractHeaderValue(mocks.TestHeader, r) != v { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValueHandlesMissingHeader(t *testing.T) { - r := mocks.NewResponse() - v := "" - - if ExtractHeaderValue(mocks.TestHeader, r) != v { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} - -func TestExtractHeaderValueRetrievesFirstValue(t *testing.T) { - r := mocks.NewResponse() - v := []string{"v1", "v2", "v3"} - mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) - - if ExtractHeaderValue(mocks.TestHeader, r) != v[0] { - t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", - mocks.TestHeader, v[0], mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go deleted file mode 100644 index fa11dbed..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go +++ /dev/null @@ -1,52 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "io" - "io/ioutil" - "net/http" -) - -// NewRetriableRequest returns a wrapper around an HTTP request that support retry logic. -func NewRetriableRequest(req *http.Request) *RetriableRequest { - return &RetriableRequest{req: req} -} - -// Request returns the wrapped HTTP request. -func (rr *RetriableRequest) Request() *http.Request { - return rr.req -} - -func (rr *RetriableRequest) prepareFromByteReader() (err error) { - // fall back to making a copy (only do this once) - b := []byte{} - if rr.req.ContentLength > 0 { - b = make([]byte, rr.req.ContentLength) - _, err = io.ReadFull(rr.req.Body, b) - if err != nil { - return err - } - } else { - b, err = ioutil.ReadAll(rr.req.Body) - if err != nil { - return err - } - } - rr.br = bytes.NewReader(b) - rr.req.Body = ioutil.NopCloser(rr.br) - return err -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go deleted file mode 100644 index 7143cc61..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !go1.8 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import ( - "bytes" - "io/ioutil" - "net/http" -) - -// RetriableRequest provides facilities for retrying an HTTP request. -type RetriableRequest struct { - req *http.Request - br *bytes.Reader -} - -// Prepare signals that the request is about to be sent. -func (rr *RetriableRequest) Prepare() (err error) { - // preserve the request body; this is to support retry logic as - // the underlying transport will always close the reqeust body - if rr.req.Body != nil { - if rr.br != nil { - _, err = rr.br.Seek(0, 0 /*io.SeekStart*/) - rr.req.Body = ioutil.NopCloser(rr.br) - } - if err != nil { - return err - } - if rr.br == nil { - // fall back to making a copy (only do this once) - err = rr.prepareFromByteReader() - } - } - return err -} - -func removeRequestBody(req *http.Request) { - req.Body = nil - req.ContentLength = 0 -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go deleted file mode 100644 index ae15c6bf..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go +++ /dev/null @@ -1,66 +0,0 @@ -// +build go1.8 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import ( - "bytes" - "io" - "io/ioutil" - "net/http" -) - -// RetriableRequest provides facilities for retrying an HTTP request. -type RetriableRequest struct { - req *http.Request - rc io.ReadCloser - br *bytes.Reader -} - -// Prepare signals that the request is about to be sent. -func (rr *RetriableRequest) Prepare() (err error) { - // preserve the request body; this is to support retry logic as - // the underlying transport will always close the reqeust body - if rr.req.Body != nil { - if rr.rc != nil { - rr.req.Body = rr.rc - } else if rr.br != nil { - _, err = rr.br.Seek(0, io.SeekStart) - rr.req.Body = ioutil.NopCloser(rr.br) - } - if err != nil { - return err - } - if rr.req.GetBody != nil { - // this will allow us to preserve the body without having to - // make a copy. note we need to do this on each iteration - rr.rc, err = rr.req.GetBody() - if err != nil { - return err - } - } else if rr.br == nil { - // fall back to making a copy (only do this once) - err = rr.prepareFromByteReader() - } - } - return err -} - -func removeRequestBody(req *http.Request) { - req.Body = nil - req.GetBody = nil - req.ContentLength = 0 -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender.go b/vendor/github.com/Azure/go-autorest/autorest/sender.go deleted file mode 100644 index c5efd59a..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/sender.go +++ /dev/null @@ -1,317 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "log" - "math" - "net/http" - "strconv" - "time" -) - -// Sender is the interface that wraps the Do method to send HTTP requests. -// -// The standard http.Client conforms to this interface. -type Sender interface { - Do(*http.Request) (*http.Response, error) -} - -// SenderFunc is a method that implements the Sender interface. -type SenderFunc func(*http.Request) (*http.Response, error) - -// Do implements the Sender interface on SenderFunc. -func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) { - return sf(r) -} - -// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then react to the -// http.Response result. -type SendDecorator func(Sender) Sender - -// CreateSender creates, decorates, and returns, as a Sender, the default http.Client. -func CreateSender(decorators ...SendDecorator) Sender { - return DecorateSender(&http.Client{}, decorators...) -} - -// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to -// the Sender. Decorators are applied in the order received, but their affect upon the request -// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a -// post-decorator (pass the http.Request along and react to the results in http.Response). -func DecorateSender(s Sender, decorators ...SendDecorator) Sender { - for _, decorate := range decorators { - s = decorate(s) - } - return s -} - -// Send sends, by means of the default http.Client, the passed http.Request, returning the -// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which -// it will apply the http.Client before invoking the Do method. -// -// Send is a convenience method and not recommended for production. Advanced users should use -// SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client). -// -// Send will not poll or retry requests. -func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) { - return SendWithSender(&http.Client{}, r, decorators...) -} - -// SendWithSender sends the passed http.Request, through the provided Sender, returning the -// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which -// it will apply the http.Client before invoking the Do method. -// -// SendWithSender will not poll or retry requests. -func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error) { - return DecorateSender(s, decorators...).Do(r) -} - -// AfterDelay returns a SendDecorator that delays for the passed time.Duration before -// invoking the Sender. The delay may be terminated by closing the optional channel on the -// http.Request. If canceled, no further Senders are invoked. -func AfterDelay(d time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if !DelayForBackoff(d, 0, r.Cancel) { - return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay") - } - return s.Do(r) - }) - } -} - -// AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request. -func AsIs() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return s.Do(r) - }) - } -} - -// DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which -// it closes the response if the passed Sender returns an error and the response body exists. -func DoCloseIfError() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - Respond(resp, ByDiscardingBody(), ByClosing()) - } - return resp, err - }) - } -} - -// DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is -// among the set passed. Since these are artificial errors, the response body may still require -// closing. -func DoErrorIfStatusCode(codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil && ResponseHasStatusCode(resp, codes...) { - err = NewErrorWithResponse("autorest", "DoErrorIfStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - } - return resp, err - }) - } -} - -// DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response -// StatusCode is among the set passed. Since these are artificial errors, the response body -// may still require closing. -func DoErrorUnlessStatusCode(codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil && !ResponseHasStatusCode(resp, codes...) { - err = NewErrorWithResponse("autorest", "DoErrorUnlessStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - } - return resp, err - }) - } -} - -// DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the -// passed status codes. It expects the http.Response to contain a Location header providing the -// URL at which to poll (using GET) and will poll until the time passed is equal to or greater than -// the supplied duration. It will delay between requests for the duration specified in the -// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by -// closing the optional channel on the http.Request. -func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - resp, err = s.Do(r) - - if err == nil && ResponseHasStatusCode(resp, codes...) { - r, err = NewPollingRequest(resp, r.Cancel) - - for err == nil && ResponseHasStatusCode(resp, codes...) { - Respond(resp, - ByDiscardingBody(), - ByClosing()) - resp, err = SendWithSender(s, r, - AfterDelay(GetRetryAfter(resp, delay))) - } - } - - return resp, err - }) - } -} - -// DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified -// number of attempts, exponentially backing off between requests using the supplied backoff -// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on -// the http.Request. -func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - for attempt := 0; attempt < attempts; attempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - resp, err = s.Do(rr.Request()) - if err == nil { - return resp, err - } - DelayForBackoff(backoff, attempt, r.Cancel) - } - return resp, err - }) - } -} - -// DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified -// number of attempts, exponentially backing off between requests using the supplied backoff -// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on -// the http.Request. -func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - // Increment to add the first call (attempts denotes number of retries) - attempts++ - for attempt := 0; attempt < attempts; { - err = rr.Prepare() - if err != nil { - return resp, err - } - resp, err = s.Do(rr.Request()) - // we want to retry if err is not nil (e.g. transient network failure). note that for failed authentication - // resp and err will both have a value, so in this case we don't want to retry as it will never succeed. - if err == nil && !ResponseHasStatusCode(resp, codes...) || IsTokenRefreshError(err) { - return resp, err - } - delayed := DelayWithRetryAfter(resp, r.Cancel) - if !delayed { - DelayForBackoff(backoff, attempt, r.Cancel) - } - // don't count a 429 against the number of attempts - // so that we continue to retry until it succeeds - if resp == nil || resp.StatusCode != http.StatusTooManyRequests { - attempt++ - } - } - return resp, err - }) - } -} - -// DelayWithRetryAfter invokes time.After for the duration specified in the "Retry-After" header in -// responses with status code 429 -func DelayWithRetryAfter(resp *http.Response, cancel <-chan struct{}) bool { - if resp == nil { - return false - } - retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After")) - if resp.StatusCode == http.StatusTooManyRequests && retryAfter > 0 { - select { - case <-time.After(time.Duration(retryAfter) * time.Second): - return true - case <-cancel: - return false - } - } - return false -} - -// DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal -// to or greater than the specified duration, exponentially backing off between requests using the -// supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the -// optional channel on the http.Request. -func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - end := time.Now().Add(d) - for attempt := 0; time.Now().Before(end); attempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - resp, err = s.Do(rr.Request()) - if err == nil { - return resp, err - } - DelayForBackoff(backoff, attempt, r.Cancel) - } - return resp, err - }) - } -} - -// WithLogging returns a SendDecorator that implements simple before and after logging of the -// request. -func WithLogging(logger *log.Logger) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - logger.Printf("Sending %s %s", r.Method, r.URL) - resp, err := s.Do(r) - if err != nil { - logger.Printf("%s %s received error '%v'", r.Method, r.URL, err) - } else { - logger.Printf("%s %s received %s", r.Method, r.URL, resp.Status) - } - return resp, err - }) - } -} - -// DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of -// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set -// to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early, -// returns false. -// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt -// count. -func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool { - select { - case <-time.After(time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second): - return true - case <-cancel: - return false - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender_test.go b/vendor/github.com/Azure/go-autorest/autorest/sender_test.go deleted file mode 100644 index c3083725..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/sender_test.go +++ /dev/null @@ -1,829 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "log" - "net/http" - "os" - "reflect" - "sync" - "testing" - "time" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -func ExampleSendWithSender() { - r := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(r) - - client := mocks.NewSender() - client.AppendAndRepeatResponse(r, 10) - - logger := log.New(os.Stdout, "autorest: ", 0) - na := NullAuthorizer{} - - req, _ := Prepare(&http.Request{}, - AsGet(), - WithBaseURL("https://microsoft.com/a/b/c/"), - na.WithAuthorization()) - - r, _ = SendWithSender(client, req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusAccepted), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - // Output: - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted - // autorest: Sending GET https://microsoft.com/a/b/c/ - // autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted -} - -func ExampleDoRetryForAttempts() { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), 10) - - // Retry with backoff -- ensure returned Bodies are closed - r, _ := SendWithSender(client, mocks.NewRequest(), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - fmt.Printf("Retry stopped after %d attempts", client.Attempts()) - // Output: Retry stopped after 5 attempts -} - -func ExampleDoErrorIfStatusCode() { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 NoContent", http.StatusNoContent), 10) - - // Chain decorators to retry the request, up to five times, if the status code is 204 - r, _ := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusNoContent), - DoCloseIfError(), - DoRetryForAttempts(5, time.Duration(0))) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - fmt.Printf("Retry stopped after %d attempts with code %s", client.Attempts(), r.Status) - // Output: Retry stopped after 5 attempts with code 204 NoContent -} - -func TestSendWithSenderRunsDecoratorsInOrder(t *testing.T) { - client := mocks.NewSender() - s := "" - - r, err := SendWithSender(client, mocks.NewRequest(), - withMessage(&s, "a"), - withMessage(&s, "b"), - withMessage(&s, "c")) - if err != nil { - t.Fatalf("autorest: SendWithSender returned an error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if s != "abc" { - t.Fatalf("autorest: SendWithSender invoke decorators out of order; expected 'abc', received '%s'", s) - } -} - -func TestCreateSender(t *testing.T) { - f := false - - s := CreateSender( - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return nil, nil - }) - } - })()) - s.Do(&http.Request{}) - - if !f { - t.Fatal("autorest: CreateSender failed to apply supplied decorator") - } -} - -func TestSend(t *testing.T) { - f := false - - Send(&http.Request{}, - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - f = true - return nil, nil - }) - } - })()) - - if !f { - t.Fatal("autorest: Send failed to apply supplied decorator") - } -} - -func TestAfterDelayWaits(t *testing.T) { - client := mocks.NewSender() - - d := 2 * time.Second - - tt := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - AfterDelay(d)) - s := time.Since(tt) - if s < d { - t.Fatal("autorest: AfterDelay failed to wait for at least the specified duration") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestAfterDelay_Cancels(t *testing.T) { - client := mocks.NewSender() - cancel := make(chan struct{}) - delay := 5 * time.Second - - var wg sync.WaitGroup - wg.Add(1) - tt := time.Now() - go func() { - req := mocks.NewRequest() - req.Cancel = cancel - wg.Done() - SendWithSender(client, req, - AfterDelay(delay)) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(tt) >= delay { - t.Fatal("autorest: AfterDelay failed to cancel") - } -} - -func TestAfterDelayDoesNotWaitTooLong(t *testing.T) { - client := mocks.NewSender() - - d := 5 * time.Millisecond - start := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - AfterDelay(d)) - - if time.Since(start) > (5 * d) { - t.Fatal("autorest: AfterDelay waited too long (exceeded 5 times specified duration)") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestAsIs(t *testing.T) { - client := mocks.NewSender() - - r1 := mocks.NewResponse() - client.AppendResponse(r1) - - r2, err := SendWithSender(client, mocks.NewRequest(), - AsIs()) - if err != nil { - t.Fatalf("autorest: AsIs returned an unexpected error (%v)", err) - } else if !reflect.DeepEqual(r1, r2) { - t.Fatalf("autorest: AsIs modified the response -- received %v, expected %v", r2, r1) - } - - Respond(r1, - ByDiscardingBody(), - ByClosing()) - Respond(r2, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoCloseIfError(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - - if r.Body.(*mocks.Body).IsOpen() { - t.Fatal("autorest: Expected DoCloseIfError to close response body -- it was left open") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoCloseIfErrorAcceptsNilResponse(t *testing.T) { - client := mocks.NewSender() - - SendWithSender(client, mocks.NewRequest(), - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - resp.Body.Close() - } - return nil, fmt.Errorf("Faux Error") - }) - } - })(), - DoCloseIfError()) -} - -func TestDoCloseIfErrorAcceptsNilBody(t *testing.T) { - client := mocks.NewSender() - - SendWithSender(client, mocks.NewRequest(), - (func() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - resp.Body.Close() - } - resp.Body = nil - return resp, fmt.Errorf("Faux Error") - }) - } - })(), - DoCloseIfError()) -} - -func TestDoErrorIfStatusCode(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: DoErrorIfStatusCode failed to emit an error for passed code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorIfStatusCodeIgnoresStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorIfStatusCode(http.StatusBadRequest), - DoCloseIfError()) - if err != nil { - t.Fatal("autorest: DoErrorIfStatusCode failed to ignore a status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorUnlessStatusCode(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(mocks.NewResponseWithStatus("400 BadRequest", http.StatusBadRequest)) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorUnlessStatusCode(http.StatusAccepted), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: DoErrorUnlessStatusCode failed to emit an error for an unknown status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoErrorUnlessStatusCodeIgnoresStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoErrorUnlessStatusCode(http.StatusAccepted), - DoCloseIfError()) - if err != nil { - t.Fatal("autorest: DoErrorUnlessStatusCode emitted an error for a knonwn status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForAttemptsStopsAfterSuccess(t *testing.T) { - client := mocks.NewSender() - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(5, time.Duration(0))) - if client.Attempts() != 1 { - t.Fatalf("autorest: DoRetryForAttempts failed to stop after success -- expected attempts %v, actual %v", - 1, client.Attempts()) - } - if err != nil { - t.Fatalf("autorest: DoRetryForAttempts returned an unexpected error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForAttemptsStopsAfterAttempts(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), 10) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(5, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 5 { - t.Fatal("autorest: DoRetryForAttempts failed to stop after specified number of attempts") - } -} - -func TestDoRetryForAttemptsReturnsResponse(t *testing.T) { - client := mocks.NewSender() - client.SetError(fmt.Errorf("Faux Error")) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForAttempts(1, time.Duration(0))) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if r == nil { - t.Fatal("autorest: DoRetryForAttempts failed to return the underlying response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsAfterSuccess(t *testing.T) { - client := mocks.NewSender() - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(10*time.Millisecond, time.Duration(0))) - if client.Attempts() != 1 { - t.Fatalf("autorest: DoRetryForDuration failed to stop after success -- expected attempts %v, actual %v", - 1, client.Attempts()) - } - if err != nil { - t.Fatalf("autorest: DoRetryForDuration returned an unexpected error (%v)", err) - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsAfterDuration(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - d := 5 * time.Millisecond - start := time.Now() - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(d, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if time.Since(start) < d { - t.Fatal("autorest: DoRetryForDuration failed stopped too soon") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationStopsWithinReason(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - d := 5 * time.Second - start := time.Now() - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(d, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if time.Since(start) > (5 * d) { - t.Fatal("autorest: DoRetryForDuration failed stopped soon enough (exceeded 5 times specified duration)") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForDurationReturnsResponse(t *testing.T) { - client := mocks.NewSender() - client.SetAndRepeatError(fmt.Errorf("Faux Error"), -1) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForDuration(10*time.Millisecond, time.Duration(0)), - DoCloseIfError()) - if err == nil { - t.Fatal("autorest: Mock client failed to emit errors") - } - - if r == nil { - t.Fatal("autorest: DoRetryForDuration failed to return the underlying response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDelayForBackoff(t *testing.T) { - d := 2 * time.Second - start := time.Now() - DelayForBackoff(d, 0, nil) - if time.Since(start) < d { - t.Fatal("autorest: DelayForBackoff did not delay as long as expected") - } -} - -func TestDelayForBackoff_Cancels(t *testing.T) { - cancel := make(chan struct{}) - delay := 5 * time.Second - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - go func() { - wg.Done() - DelayForBackoff(delay, 0, cancel) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(start) >= delay { - t.Fatal("autorest: DelayForBackoff failed to cancel") - } -} - -func TestDelayForBackoffWithinReason(t *testing.T) { - d := 5 * time.Second - maxCoefficient := 2 - start := time.Now() - DelayForBackoff(d, 0, nil) - if time.Since(start) > (time.Duration(maxCoefficient) * d) { - - t.Fatalf("autorest: DelayForBackoff delayed too long (exceeded %d times the specified duration)", maxCoefficient) - } -} - -func TestDoPollForStatusCodes_IgnoresUnspecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Duration(0), time.Duration(0))) - - if client.Attempts() != 1 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes polled for unspecified status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_PollsForSpecifiedStatusCodes(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if client.Attempts() != 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to poll for specified status code") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_CanBeCanceled(t *testing.T) { - cancel := make(chan struct{}) - delay := 5 * time.Second - - r := mocks.NewResponse() - mocks.SetAcceptedHeaders(r) - client := mocks.NewSender() - client.AppendAndRepeatResponse(r, 100) - - var wg sync.WaitGroup - wg.Add(1) - start := time.Now() - go func() { - wg.Done() - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - Respond(r, - ByDiscardingBody(), - ByClosing()) - }() - wg.Wait() - close(cancel) - time.Sleep(5 * time.Millisecond) - if time.Since(start) >= delay { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to cancel") - } -} - -func TestDoPollForStatusCodes_ClosesAllNonreturnedResponseBodiesWhenPolling(t *testing.T) { - resp := newAcceptedResponse() - - client := mocks.NewSender() - client.AppendAndRepeatResponse(resp, 2) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if resp.Body.(*mocks.Body).IsOpen() || resp.Body.(*mocks.Body).CloseAttempts() < 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes did not close unreturned response bodies") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_LeavesLastResponseBodyOpen(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(newAcceptedResponse()) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if !r.Body.(*mocks.Body).IsOpen() { - t.Fatalf("autorest: Sender#DoPollForStatusCodes did not leave open the body of the last response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_StopsPollingAfterAnError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(newAcceptedResponse(), 5) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(1) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if client.Attempts() > 2 { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to stop polling after receiving an error") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoPollForStatusCodes_ReturnsPollingError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(newAcceptedResponse(), 5) - client.SetError(fmt.Errorf("Faux Error")) - client.SetEmitErrorAfter(1) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoPollForStatusCodes(time.Millisecond, time.Millisecond, http.StatusAccepted)) - - if err == nil { - t.Fatalf("autorest: Sender#DoPollForStatusCodes failed to return error from polling") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestWithLogging_Logs(t *testing.T) { - buf := &bytes.Buffer{} - logger := log.New(buf, "autorest: ", 0) - client := mocks.NewSender() - - r, _ := SendWithSender(client, &http.Request{}, - WithLogging(logger)) - - if buf.String() == "" { - t.Fatal("autorest: Sender#WithLogging failed to log the request") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestWithLogging_HandlesMissingResponse(t *testing.T) { - buf := &bytes.Buffer{} - logger := log.New(buf, "autorest: ", 0) - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(fmt.Errorf("Faux Error")) - - r, err := SendWithSender(client, &http.Request{}, - WithLogging(logger)) - - if r != nil || err == nil { - t.Fatal("autorest: Sender#WithLogging returned a valid response -- expecting nil") - } - if buf.String() == "" { - t.Fatal("autorest: Sender#WithLogging failed to log the request for a nil response") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) -} - -func TestDoRetryForStatusCodesWithSuccess(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("408 Request Timeout", http.StatusRequestTimeout), 2) - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(5, time.Duration(2*time.Second), http.StatusRequestTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: StatusCode %v in %v attempts; Want: StatusCode 200 OK in 2 attempts -- ", - r.Status, client.Attempts()-1) - } -} - -func TestDoRetryForStatusCodesWithNoSuccess(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("504 Gateway Timeout", http.StatusGatewayTimeout), 5) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(2, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: failed stop after %v retry attempts; Want: Stop after 2 retry attempts", - client.Attempts()-1) - } -} - -func TestDoRetryForStatusCodes_CodeNotInRetryList(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 No Content", http.StatusNoContent), 1) - - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(6, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 1 || r.Status != "204 No Content" { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: Retry attempts %v for StatusCode %v; Want: 0 attempts for StatusCode 204", - client.Attempts(), r.Status) - } -} - -func TestDoRetryForStatusCodes_RequestBodyReadError(t *testing.T) { - client := mocks.NewSender() - client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 No Content", http.StatusNoContent), 2) - - r, err := SendWithSender(client, mocks.NewRequestWithCloseBody(), - DoRetryForStatusCodes(6, time.Duration(2*time.Second), http.StatusGatewayTimeout), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err == nil || client.Attempts() != 0 { - t.Fatalf("autorest: Sender#DoRetryForStatusCodes -- Got: Not failed for request body read error; Want: Failed for body read error - %v", err) - } -} - -func newAcceptedResponse() *http.Response { - resp := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted) - mocks.SetAcceptedHeaders(resp) - return resp -} - -func TestDelayWithRetryAfterWithSuccess(t *testing.T) { - after, retries := 2, 2 - totalSecs := after * retries - - client := mocks.NewSender() - resp := mocks.NewResponseWithStatus("429 Too many requests", http.StatusTooManyRequests) - mocks.SetResponseHeader(resp, "Retry-After", fmt.Sprintf("%v", after)) - client.AppendAndRepeatResponse(resp, retries) - client.AppendResponse(mocks.NewResponseWithStatus("200 OK", http.StatusOK)) - - d := time.Second * time.Duration(totalSecs) - start := time.Now() - r, _ := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(1, time.Duration(time.Second), http.StatusTooManyRequests), - ) - - if time.Since(start) < d { - t.Fatal("autorest: DelayWithRetryAfter failed stopped too soon") - } - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if client.Attempts() != 3 { - t.Fatalf("autorest: Sender#DelayWithRetryAfter -- Got: StatusCode %v in %v attempts; Want: StatusCode 200 OK in 2 attempts -- ", - r.Status, client.Attempts()-1) - } -} - -func TestDoRetryForStatusCodes_NilResponse(t *testing.T) { - client := mocks.NewSender() - client.AppendResponse(nil) - client.SetError(fmt.Errorf("faux error")) - - r, err := SendWithSender(client, mocks.NewRequest(), - DoRetryForStatusCodes(3, time.Duration(1*time.Second), StatusCodesForRetry...), - ) - - Respond(r, - ByDiscardingBody(), - ByClosing()) - - if err != nil || client.Attempts() != 2 { - t.Fatalf("autorest: Sender#TestDoRetryForStatusCodes_NilResponse -- Got: non-nil error or wrong number of attempts - %v", err) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/to/convert.go b/vendor/github.com/Azure/go-autorest/autorest/to/convert.go deleted file mode 100644 index fdda2ce1..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/to/convert.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Package to provides helpers to ease working with pointer values of marshalled structures. -*/ -package to - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// String returns a string value for the passed string pointer. It returns the empty string if the -// pointer is nil. -func String(s *string) string { - if s != nil { - return *s - } - return "" -} - -// StringPtr returns a pointer to the passed string. -func StringPtr(s string) *string { - return &s -} - -// StringSlice returns a string slice value for the passed string slice pointer. It returns a nil -// slice if the pointer is nil. -func StringSlice(s *[]string) []string { - if s != nil { - return *s - } - return nil -} - -// StringSlicePtr returns a pointer to the passed string slice. -func StringSlicePtr(s []string) *[]string { - return &s -} - -// StringMap returns a map of strings built from the map of string pointers. The empty string is -// used for nil pointers. -func StringMap(msp map[string]*string) map[string]string { - ms := make(map[string]string, len(msp)) - for k, sp := range msp { - if sp != nil { - ms[k] = *sp - } else { - ms[k] = "" - } - } - return ms -} - -// StringMapPtr returns a pointer to a map of string pointers built from the passed map of strings. -func StringMapPtr(ms map[string]string) *map[string]*string { - msp := make(map[string]*string, len(ms)) - for k, s := range ms { - msp[k] = StringPtr(s) - } - return &msp -} - -// Bool returns a bool value for the passed bool pointer. It returns false if the pointer is nil. -func Bool(b *bool) bool { - if b != nil { - return *b - } - return false -} - -// BoolPtr returns a pointer to the passed bool. -func BoolPtr(b bool) *bool { - return &b -} - -// Int returns an int value for the passed int pointer. It returns 0 if the pointer is nil. -func Int(i *int) int { - if i != nil { - return *i - } - return 0 -} - -// IntPtr returns a pointer to the passed int. -func IntPtr(i int) *int { - return &i -} - -// Int32 returns an int value for the passed int pointer. It returns 0 if the pointer is nil. -func Int32(i *int32) int32 { - if i != nil { - return *i - } - return 0 -} - -// Int32Ptr returns a pointer to the passed int32. -func Int32Ptr(i int32) *int32 { - return &i -} - -// Int64 returns an int value for the passed int pointer. It returns 0 if the pointer is nil. -func Int64(i *int64) int64 { - if i != nil { - return *i - } - return 0 -} - -// Int64Ptr returns a pointer to the passed int64. -func Int64Ptr(i int64) *int64 { - return &i -} - -// Float32 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil. -func Float32(i *float32) float32 { - if i != nil { - return *i - } - return 0.0 -} - -// Float32Ptr returns a pointer to the passed float32. -func Float32Ptr(i float32) *float32 { - return &i -} - -// Float64 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil. -func Float64(i *float64) float64 { - if i != nil { - return *i - } - return 0.0 -} - -// Float64Ptr returns a pointer to the passed float64. -func Float64Ptr(i float64) *float64 { - return &i -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go b/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go deleted file mode 100644 index f8177a16..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/to/convert_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package to - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "reflect" - "testing" -) - -func TestString(t *testing.T) { - v := "" - if String(&v) != v { - t.Fatalf("to: String failed to return the correct string -- expected %v, received %v", - v, String(&v)) - } -} - -func TestStringHandlesNil(t *testing.T) { - if String(nil) != "" { - t.Fatalf("to: String failed to correctly convert nil -- expected %v, received %v", - "", String(nil)) - } -} - -func TestStringPtr(t *testing.T) { - v := "" - if *StringPtr(v) != v { - t.Fatalf("to: StringPtr failed to return the correct string -- expected %v, received %v", - v, *StringPtr(v)) - } -} - -func TestStringSlice(t *testing.T) { - v := []string{} - if out := StringSlice(&v); !reflect.DeepEqual(out, v) { - t.Fatalf("to: StringSlice failed to return the correct slice -- expected %v, received %v", - v, out) - } -} - -func TestStringSliceHandlesNil(t *testing.T) { - if out := StringSlice(nil); out != nil { - t.Fatalf("to: StringSlice failed to correctly convert nil -- expected %v, received %v", - nil, out) - } -} - -func TestStringSlicePtr(t *testing.T) { - v := []string{"a", "b"} - if out := StringSlicePtr(v); !reflect.DeepEqual(*out, v) { - t.Fatalf("to: StringSlicePtr failed to return the correct slice -- expected %v, received %v", - v, *out) - } -} - -func TestStringMap(t *testing.T) { - msp := map[string]*string{"foo": StringPtr("foo"), "bar": StringPtr("bar"), "baz": StringPtr("baz")} - for k, v := range StringMap(msp) { - if *msp[k] != v { - t.Fatalf("to: StringMap incorrectly converted an entry -- expected [%s]%v, received[%s]%v", - k, v, k, *msp[k]) - } - } -} - -func TestStringMapHandlesNil(t *testing.T) { - msp := map[string]*string{"foo": StringPtr("foo"), "bar": nil, "baz": StringPtr("baz")} - for k, v := range StringMap(msp) { - if msp[k] == nil && v != "" { - t.Fatalf("to: StringMap incorrectly converted a nil entry -- expected [%s]%v, received[%s]%v", - k, v, k, *msp[k]) - } - } -} - -func TestStringMapPtr(t *testing.T) { - ms := map[string]string{"foo": "foo", "bar": "bar", "baz": "baz"} - for k, msp := range *StringMapPtr(ms) { - if ms[k] != *msp { - t.Fatalf("to: StringMapPtr incorrectly converted an entry -- expected [%s]%v, received[%s]%v", - k, ms[k], k, *msp) - } - } -} - -func TestBool(t *testing.T) { - v := false - if Bool(&v) != v { - t.Fatalf("to: Bool failed to return the correct string -- expected %v, received %v", - v, Bool(&v)) - } -} - -func TestBoolHandlesNil(t *testing.T) { - if Bool(nil) != false { - t.Fatalf("to: Bool failed to correctly convert nil -- expected %v, received %v", - false, Bool(nil)) - } -} - -func TestBoolPtr(t *testing.T) { - v := false - if *BoolPtr(v) != v { - t.Fatalf("to: BoolPtr failed to return the correct string -- expected %v, received %v", - v, *BoolPtr(v)) - } -} - -func TestInt(t *testing.T) { - v := 0 - if Int(&v) != v { - t.Fatalf("to: Int failed to return the correct string -- expected %v, received %v", - v, Int(&v)) - } -} - -func TestIntHandlesNil(t *testing.T) { - if Int(nil) != 0 { - t.Fatalf("to: Int failed to correctly convert nil -- expected %v, received %v", - 0, Int(nil)) - } -} - -func TestIntPtr(t *testing.T) { - v := 0 - if *IntPtr(v) != v { - t.Fatalf("to: IntPtr failed to return the correct string -- expected %v, received %v", - v, *IntPtr(v)) - } -} - -func TestInt32(t *testing.T) { - v := int32(0) - if Int32(&v) != v { - t.Fatalf("to: Int32 failed to return the correct string -- expected %v, received %v", - v, Int32(&v)) - } -} - -func TestInt32HandlesNil(t *testing.T) { - if Int32(nil) != int32(0) { - t.Fatalf("to: Int32 failed to correctly convert nil -- expected %v, received %v", - 0, Int32(nil)) - } -} - -func TestInt32Ptr(t *testing.T) { - v := int32(0) - if *Int32Ptr(v) != v { - t.Fatalf("to: Int32Ptr failed to return the correct string -- expected %v, received %v", - v, *Int32Ptr(v)) - } -} - -func TestInt64(t *testing.T) { - v := int64(0) - if Int64(&v) != v { - t.Fatalf("to: Int64 failed to return the correct string -- expected %v, received %v", - v, Int64(&v)) - } -} - -func TestInt64HandlesNil(t *testing.T) { - if Int64(nil) != int64(0) { - t.Fatalf("to: Int64 failed to correctly convert nil -- expected %v, received %v", - 0, Int64(nil)) - } -} - -func TestInt64Ptr(t *testing.T) { - v := int64(0) - if *Int64Ptr(v) != v { - t.Fatalf("to: Int64Ptr failed to return the correct string -- expected %v, received %v", - v, *Int64Ptr(v)) - } -} - -func TestFloat32(t *testing.T) { - v := float32(0) - if Float32(&v) != v { - t.Fatalf("to: Float32 failed to return the correct string -- expected %v, received %v", - v, Float32(&v)) - } -} - -func TestFloat32HandlesNil(t *testing.T) { - if Float32(nil) != float32(0) { - t.Fatalf("to: Float32 failed to correctly convert nil -- expected %v, received %v", - 0, Float32(nil)) - } -} - -func TestFloat32Ptr(t *testing.T) { - v := float32(0) - if *Float32Ptr(v) != v { - t.Fatalf("to: Float32Ptr failed to return the correct string -- expected %v, received %v", - v, *Float32Ptr(v)) - } -} - -func TestFloat64(t *testing.T) { - v := float64(0) - if Float64(&v) != v { - t.Fatalf("to: Float64 failed to return the correct string -- expected %v, received %v", - v, Float64(&v)) - } -} - -func TestFloat64HandlesNil(t *testing.T) { - if Float64(nil) != float64(0) { - t.Fatalf("to: Float64 failed to correctly convert nil -- expected %v, received %v", - 0, Float64(nil)) - } -} - -func TestFloat64Ptr(t *testing.T) { - v := float64(0) - if *Float64Ptr(v) != v { - t.Fatalf("to: Float64Ptr failed to return the correct string -- expected %v, received %v", - v, *Float64Ptr(v)) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility.go b/vendor/github.com/Azure/go-autorest/autorest/utility.go deleted file mode 100644 index afb3e4e1..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility.go +++ /dev/null @@ -1,218 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "net/http" - "net/url" - "reflect" - "strings" - - "github.com/Azure/go-autorest/autorest/adal" -) - -// EncodedAs is a series of constants specifying various data encodings -type EncodedAs string - -const ( - // EncodedAsJSON states that data is encoded as JSON - EncodedAsJSON EncodedAs = "JSON" - - // EncodedAsXML states that data is encoded as Xml - EncodedAsXML EncodedAs = "XML" -) - -// Decoder defines the decoding method json.Decoder and xml.Decoder share -type Decoder interface { - Decode(v interface{}) error -} - -// NewDecoder creates a new decoder appropriate to the passed encoding. -// encodedAs specifies the type of encoding and r supplies the io.Reader containing the -// encoded data. -func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder { - if encodedAs == EncodedAsJSON { - return json.NewDecoder(r) - } else if encodedAs == EncodedAsXML { - return xml.NewDecoder(r) - } - return nil -} - -// CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy -// is especially useful if there is a chance the data will fail to decode. -// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v -// is the decoding destination. -func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) { - b := bytes.Buffer{} - return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v) -} - -// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc. -// It utilizes io.TeeReader to copy the data read and has the same behavior when reading. -// Further, when it is closed, it ensures that rc is closed as well. -func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser { - return &teeReadCloser{rc, io.TeeReader(rc, w)} -} - -type teeReadCloser struct { - rc io.ReadCloser - r io.Reader -} - -func (t *teeReadCloser) Read(p []byte) (int, error) { - return t.r.Read(p) -} - -func (t *teeReadCloser) Close() error { - return t.rc.Close() -} - -func containsInt(ints []int, n int) bool { - for _, i := range ints { - if i == n { - return true - } - } - return false -} - -func escapeValueStrings(m map[string]string) map[string]string { - for key, value := range m { - m[key] = url.QueryEscape(value) - } - return m -} - -func ensureValueStrings(mapOfInterface map[string]interface{}) map[string]string { - mapOfStrings := make(map[string]string) - for key, value := range mapOfInterface { - mapOfStrings[key] = ensureValueString(value) - } - return mapOfStrings -} - -func ensureValueString(value interface{}) string { - if value == nil { - return "" - } - switch v := value.(type) { - case string: - return v - case []byte: - return string(v) - default: - return fmt.Sprintf("%v", v) - } -} - -// MapToValues method converts map[string]interface{} to url.Values. -func MapToValues(m map[string]interface{}) url.Values { - v := url.Values{} - for key, value := range m { - x := reflect.ValueOf(value) - if x.Kind() == reflect.Array || x.Kind() == reflect.Slice { - for i := 0; i < x.Len(); i++ { - v.Add(key, ensureValueString(x.Index(i))) - } - } else { - v.Add(key, ensureValueString(value)) - } - } - return v -} - -// AsStringSlice method converts interface{} to []string. This expects a -//that the parameter passed to be a slice or array of a type that has the underlying -//type a string. -func AsStringSlice(s interface{}) ([]string, error) { - v := reflect.ValueOf(s) - if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { - return nil, NewError("autorest", "AsStringSlice", "the value's type is not an array.") - } - stringSlice := make([]string, 0, v.Len()) - - for i := 0; i < v.Len(); i++ { - stringSlice = append(stringSlice, v.Index(i).String()) - } - return stringSlice, nil -} - -// String method converts interface v to string. If interface is a list, it -// joins list elements using the seperator. Note that only sep[0] will be used for -// joining if any separator is specified. -func String(v interface{}, sep ...string) string { - if len(sep) == 0 { - return ensureValueString(v) - } - stringSlice, ok := v.([]string) - if ok == false { - var err error - stringSlice, err = AsStringSlice(v) - if err != nil { - panic(fmt.Sprintf("autorest: Couldn't convert value to a string %s.", err)) - } - } - return ensureValueString(strings.Join(stringSlice, sep[0])) -} - -// Encode method encodes url path and query parameters. -func Encode(location string, v interface{}, sep ...string) string { - s := String(v, sep...) - switch strings.ToLower(location) { - case "path": - return pathEscape(s) - case "query": - return queryEscape(s) - default: - return s - } -} - -func pathEscape(s string) string { - return strings.Replace(url.QueryEscape(s), "+", "%20", -1) -} - -func queryEscape(s string) string { - return url.QueryEscape(s) -} - -// ChangeToGet turns the specified http.Request into a GET (it assumes it wasn't). -// This is mainly useful for long-running operations that use the Azure-AsyncOperation -// header, so we change the initial PUT into a GET to retrieve the final result. -func ChangeToGet(req *http.Request) *http.Request { - req.Method = "GET" - req.Body = nil - req.ContentLength = 0 - req.Header.Del("Content-Length") - return req -} - -// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError -// interface. If err is a DetailedError it will walk the chain of Original errors. -func IsTokenRefreshError(err error) bool { - if _, ok := err.(adal.TokenRefreshError); ok { - return true - } - if de, ok := err.(DetailedError); ok { - return IsTokenRefreshError(de.Original) - } - return false -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_test.go b/vendor/github.com/Azure/go-autorest/autorest/utility_test.go deleted file mode 100644 index cc4919b5..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility_test.go +++ /dev/null @@ -1,422 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" - "net/http" - "net/url" - "reflect" - "sort" - "strings" - "testing" - - "github.com/Azure/go-autorest/autorest/mocks" -) - -const ( - jsonT = ` - { - "name":"Rob Pike", - "age":42 - }` - xmlT = ` - - Rob Pike - 42 - ` -) - -func TestNewDecoderCreatesJSONDecoder(t *testing.T) { - d := NewDecoder(EncodedAsJSON, strings.NewReader(jsonT)) - _, ok := d.(*json.Decoder) - if d == nil || !ok { - t.Fatal("autorest: NewDecoder failed to create a JSON decoder when requested") - } -} - -func TestNewDecoderCreatesXMLDecoder(t *testing.T) { - d := NewDecoder(EncodedAsXML, strings.NewReader(xmlT)) - _, ok := d.(*xml.Decoder) - if d == nil || !ok { - t.Fatal("autorest: NewDecoder failed to create an XML decoder when requested") - } -} - -func TestNewDecoderReturnsNilForUnknownEncoding(t *testing.T) { - d := NewDecoder("unknown", strings.NewReader(xmlT)) - if d != nil { - t.Fatal("autorest: NewDecoder created a decoder for an unknown encoding") - } -} - -func TestCopyAndDecodeDecodesJSON(t *testing.T) { - _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{}) - if err != nil { - t.Fatalf("autorest: CopyAndDecode returned an error with valid JSON - %v", err) - } -} - -func TestCopyAndDecodeDecodesXML(t *testing.T) { - _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT), &mocks.T{}) - if err != nil { - t.Fatalf("autorest: CopyAndDecode returned an error with valid XML - %v", err) - } -} - -func TestCopyAndDecodeReturnsJSONDecodingErrors(t *testing.T) { - _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT[0:len(jsonT)-2]), &mocks.T{}) - if err == nil { - t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid JSON") - } -} - -func TestCopyAndDecodeReturnsXMLDecodingErrors(t *testing.T) { - _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT[0:len(xmlT)-2]), &mocks.T{}) - if err == nil { - t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid XML") - } -} - -func TestCopyAndDecodeAlwaysReturnsACopy(t *testing.T) { - b, _ := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{}) - if b.String() != jsonT { - t.Fatalf("autorest: CopyAndDecode failed to return a valid copy of the data - %v", b.String()) - } -} - -func TestTeeReadCloser_Copies(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - b := &bytes.Buffer{} - - r.Body = TeeReadCloser(r.Body, b) - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err) - } - if b.String() != jsonT { - t.Fatalf("autorest: TeeReadCloser failed to copy the bytes read") - } -} - -func TestTeeReadCloser_PassesReadErrors(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - - r.Body.(*mocks.Body).Close() - r.Body = TeeReadCloser(r.Body, &bytes.Buffer{}) - - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err == nil { - t.Fatalf("autorest: TeeReadCloser failed to return the expected error") - } -} - -func TestTeeReadCloser_ClosesWrappedReader(t *testing.T) { - v := &mocks.T{} - r := mocks.NewResponseWithContent(jsonT) - - b := r.Body.(*mocks.Body) - r.Body = TeeReadCloser(r.Body, &bytes.Buffer{}) - err := Respond(r, - ByUnmarshallingJSON(v), - ByClosing()) - if err != nil { - t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err) - } - if b.IsOpen() { - t.Fatalf("autorest: TeeReadCloser failed to close the nested io.ReadCloser") - } -} - -func TestContainsIntFindsValue(t *testing.T) { - ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - v := 5 - if !containsInt(ints, v) { - t.Fatalf("autorest: containsInt failed to find %v in %v", v, ints) - } -} - -func TestContainsIntDoesNotFindValue(t *testing.T) { - ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - v := 42 - if containsInt(ints, v) { - t.Fatalf("autorest: containsInt unexpectedly found %v in %v", v, ints) - } -} - -func TestContainsIntAcceptsEmptyList(t *testing.T) { - ints := make([]int, 10) - if containsInt(ints, 42) { - t.Fatalf("autorest: containsInt failed to handle an empty list") - } -} - -func TestContainsIntAcceptsNilList(t *testing.T) { - var ints []int - if containsInt(ints, 42) { - t.Fatalf("autorest: containsInt failed to handle an nil list") - } -} - -func TestEscapeStrings(t *testing.T) { - m := map[string]string{ - "string": "a long string with = odd characters", - "int": "42", - "nil": "", - } - r := map[string]string{ - "string": "a+long+string+with+%3D+odd+characters", - "int": "42", - "nil": "", - } - v := escapeValueStrings(m) - if !reflect.DeepEqual(v, r) { - t.Fatalf("autorest: ensureValueStrings returned %v\n", v) - } -} - -func TestEnsureStrings(t *testing.T) { - m := map[string]interface{}{ - "string": "string", - "int": 42, - "nil": nil, - "bytes": []byte{255, 254, 253}, - } - r := map[string]string{ - "string": "string", - "int": "42", - "nil": "", - "bytes": string([]byte{255, 254, 253}), - } - v := ensureValueStrings(m) - if !reflect.DeepEqual(v, r) { - t.Fatalf("autorest: ensureValueStrings returned %v\n", v) - } -} - -func ExampleString() { - m := []string{ - "string1", - "string2", - "string3", - } - - fmt.Println(String(m, ",")) - // Output: string1,string2,string3 -} - -func TestStringWithValidString(t *testing.T) { - i := 123 - if got, want := String(i), "123"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithStringSlice(t *testing.T) { - s := []string{"string1", "string2"} - if got, want := String(s, ","), "string1,string2"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithEnum(t *testing.T) { - type TestEnumType string - s := TestEnumType("string1") - if got, want := String(s), "string1"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func TestStringWithEnumSlice(t *testing.T) { - type TestEnumType string - s := []TestEnumType{"string1", "string2"} - if got, want := String(s, ","), "string1,string2"; got != want { - t.Logf("got: %q\nwant: %q", got, want) - t.Fail() - } -} - -func ExampleAsStringSlice() { - type TestEnumType string - - a := []TestEnumType{"value1", "value2"} - b, _ := AsStringSlice(a) - for _, c := range b { - fmt.Println(c) - } - // Output: - // value1 - // value2 -} - -func TestEncodeWithValidPath(t *testing.T) { - s := Encode("Path", "Hello Gopher") - if s != "Hello%20Gopher" { - t.Fatalf("autorest: Encode method failed for valid path encoding. Got: %v; Want: %v", s, "Hello%20Gopher") - } -} - -func TestEncodeWithValidQuery(t *testing.T) { - s := Encode("Query", "Hello Gopher") - if s != "Hello+Gopher" { - t.Fatalf("autorest: Encode method failed for valid query encoding. Got: '%v'; Want: 'Hello+Gopher'", s) - } -} - -func TestEncodeWithValidNotPathQuery(t *testing.T) { - s := Encode("Host", "Hello Gopher") - if s != "Hello Gopher" { - t.Fatalf("autorest: Encode method failed for parameter not query or path. Got: '%v'; Want: 'Hello Gopher'", s) - } -} - -func TestMapToValues(t *testing.T) { - m := map[string]interface{}{ - "a": "a", - "b": 2, - } - v := url.Values{} - v.Add("a", "a") - v.Add("b", "2") - if !isEqual(v, MapToValues(m)) { - t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m)) - } -} - -func TestMapToValuesWithArrayValues(t *testing.T) { - m := map[string]interface{}{ - "a": []string{"a", "b"}, - "b": 2, - "c": []int{3, 4}, - } - v := url.Values{} - v.Add("a", "a") - v.Add("a", "b") - v.Add("b", "2") - v.Add("c", "3") - v.Add("c", "4") - - if !isEqual(v, MapToValues(m)) { - t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m)) - } -} - -func isEqual(v, u url.Values) bool { - for key, value := range v { - if len(u[key]) == 0 { - return false - } - sort.Strings(value) - sort.Strings(u[key]) - for i := range value { - if value[i] != u[key][i] { - return false - } - } - u.Del(key) - } - if len(u) > 0 { - return false - } - return true -} - -func doEnsureBodyClosed(t *testing.T) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if resp != nil && resp.Body != nil && resp.Body.(*mocks.Body).IsOpen() { - t.Fatal("autorest: Expected Body to be closed -- it was left open") - } - return resp, err - }) - } -} - -type mockAuthorizer struct{} - -func (ma mockAuthorizer) WithAuthorization() PrepareDecorator { - return WithHeader(headerAuthorization, mocks.TestAuthorizationHeader) -} - -type mockFailingAuthorizer struct{} - -func (mfa mockFailingAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error") - }) - } -} - -type mockInspector struct { - wasInvoked bool -} - -func (mi *mockInspector) WithInspection() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - mi.wasInvoked = true - return p.Prepare(r) - }) - } -} - -func (mi *mockInspector) ByInspecting() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - mi.wasInvoked = true - return r.Respond(resp) - }) - } -} - -func withMessage(output *string, msg string) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil { - *output += msg - } - return resp, err - }) - } -} - -func withErrorRespondDecorator(e *error) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err != nil { - return err - } - *e = fmt.Errorf("autorest: Faux Respond Error") - return *e - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utils/auth.go b/vendor/github.com/Azure/go-autorest/autorest/utils/auth.go deleted file mode 100644 index 6dc2c3b0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utils/auth.go +++ /dev/null @@ -1,56 +0,0 @@ -package utils - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "os" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/adal" - "github.com/Azure/go-autorest/autorest/azure" -) - -// GetAuthorizer gets an Azure Service Principal authorizer. -// This func assumes "AZURE_TENANT_ID", "AZURE_CLIENT_ID", -// "AZURE_CLIENT_SECRET" are set as environment variables. -func GetAuthorizer(env azure.Environment) (*autorest.BearerAuthorizer, error) { - tenantID := GetEnvVarOrExit("AZURE_TENANT_ID") - - oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, tenantID) - if err != nil { - return nil, err - } - - clientID := GetEnvVarOrExit("AZURE_CLIENT_ID") - clientSecret := GetEnvVarOrExit("AZURE_CLIENT_SECRET") - - spToken, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, env.ResourceManagerEndpoint) - if err != nil { - return nil, err - } - - return autorest.NewBearerAuthorizer(spToken), nil -} - -// GetEnvVarOrExit returns the value of specified environment variable or terminates if it's not defined. -func GetEnvVarOrExit(varName string) string { - value := os.Getenv(varName) - if value == "" { - fmt.Printf("Missing environment variable %s\n", varName) - os.Exit(1) - } - return value -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utils/commit.go b/vendor/github.com/Azure/go-autorest/autorest/utils/commit.go deleted file mode 100644 index 9bc4e3e0..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utils/commit.go +++ /dev/null @@ -1,32 +0,0 @@ -package utils - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "os/exec" -) - -// GetCommit returns git HEAD (short) -func GetCommit() string { - cmd := exec.Command("git", "rev-parse", "HEAD") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return "" - } - return string(out.Bytes()[:7]) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go b/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go deleted file mode 100644 index 3fe62c93..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go +++ /dev/null @@ -1,395 +0,0 @@ -/* -Package validation provides methods for validating parameter value using reflection. -*/ -package validation - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "reflect" - "regexp" - "strings" -) - -// Constraint stores constraint name, target field name -// Rule and chain validations. -type Constraint struct { - - // Target field name for validation. - Target string - - // Constraint name e.g. minLength, MaxLength, Pattern, etc. - Name string - - // Rule for constraint e.g. greater than 10, less than 5 etc. - Rule interface{} - - // Chain Validations for struct type - Chain []Constraint -} - -// Validation stores parameter-wise validation. -type Validation struct { - TargetValue interface{} - Constraints []Constraint -} - -// Constraint list -const ( - Empty = "Empty" - Null = "Null" - ReadOnly = "ReadOnly" - Pattern = "Pattern" - MaxLength = "MaxLength" - MinLength = "MinLength" - MaxItems = "MaxItems" - MinItems = "MinItems" - MultipleOf = "MultipleOf" - UniqueItems = "UniqueItems" - InclusiveMaximum = "InclusiveMaximum" - ExclusiveMaximum = "ExclusiveMaximum" - ExclusiveMinimum = "ExclusiveMinimum" - InclusiveMinimum = "InclusiveMinimum" -) - -// Validate method validates constraints on parameter -// passed in validation array. -func Validate(m []Validation) error { - for _, item := range m { - v := reflect.ValueOf(item.TargetValue) - for _, constraint := range item.Constraints { - var err error - switch v.Kind() { - case reflect.Ptr: - err = validatePtr(v, constraint) - case reflect.String: - err = validateString(v, constraint) - case reflect.Struct: - err = validateStruct(v, constraint) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - err = validateInt(v, constraint) - case reflect.Float32, reflect.Float64: - err = validateFloat(v, constraint) - case reflect.Array, reflect.Slice, reflect.Map: - err = validateArrayMap(v, constraint) - default: - err = createError(v, constraint, fmt.Sprintf("unknown type %v", v.Kind())) - } - - if err != nil { - return err - } - } - } - return nil -} - -func validateStruct(x reflect.Value, v Constraint, name ...string) error { - //Get field name from target name which is in format a.b.c - s := strings.Split(v.Target, ".") - f := x.FieldByName(s[len(s)-1]) - if isZero(f) { - return createError(x, v, fmt.Sprintf("field %q doesn't exist", v.Target)) - } - - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(f), - Constraints: []Constraint{v}, - }, - }) -} - -func validatePtr(x reflect.Value, v Constraint) error { - if v.Name == ReadOnly { - if !x.IsNil() { - return createError(x.Elem(), v, "readonly parameter; must send as nil or empty in request") - } - return nil - } - if x.IsNil() { - return checkNil(x, v) - } - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x.Elem()), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func validateInt(x reflect.Value, v Constraint) error { - i := x.Int() - r, ok := v.Rule.(int) - if !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - switch v.Name { - case MultipleOf: - if i%int64(r) != 0 { - return createError(x, v, fmt.Sprintf("value must be a multiple of %v", r)) - } - case ExclusiveMinimum: - if i <= int64(r) { - return createError(x, v, fmt.Sprintf("value must be greater than %v", r)) - } - case ExclusiveMaximum: - if i >= int64(r) { - return createError(x, v, fmt.Sprintf("value must be less than %v", r)) - } - case InclusiveMinimum: - if i < int64(r) { - return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r)) - } - case InclusiveMaximum: - if i > int64(r) { - return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r)) - } - default: - return createError(x, v, fmt.Sprintf("constraint %v is not applicable for type integer", v.Name)) - } - return nil -} - -func validateFloat(x reflect.Value, v Constraint) error { - f := x.Float() - r, ok := v.Rule.(float64) - if !ok { - return createError(x, v, fmt.Sprintf("rule must be float value for %v constraint; got: %v", v.Name, v.Rule)) - } - switch v.Name { - case ExclusiveMinimum: - if f <= r { - return createError(x, v, fmt.Sprintf("value must be greater than %v", r)) - } - case ExclusiveMaximum: - if f >= r { - return createError(x, v, fmt.Sprintf("value must be less than %v", r)) - } - case InclusiveMinimum: - if f < r { - return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r)) - } - case InclusiveMaximum: - if f > r { - return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r)) - } - default: - return createError(x, v, fmt.Sprintf("constraint %s is not applicable for type float", v.Name)) - } - return nil -} - -func validateString(x reflect.Value, v Constraint) error { - s := x.String() - switch v.Name { - case Empty: - if len(s) == 0 { - return checkEmpty(x, v) - } - case Pattern: - reg, err := regexp.Compile(v.Rule.(string)) - if err != nil { - return createError(x, v, err.Error()) - } - if !reg.MatchString(s) { - return createError(x, v, fmt.Sprintf("value doesn't match pattern %v", v.Rule)) - } - case MaxLength: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - if len(s) > v.Rule.(int) { - return createError(x, v, fmt.Sprintf("value length must be less than or equal to %v", v.Rule)) - } - case MinLength: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - if len(s) < v.Rule.(int) { - return createError(x, v, fmt.Sprintf("value length must be greater than or equal to %v", v.Rule)) - } - case ReadOnly: - if len(s) > 0 { - return createError(reflect.ValueOf(s), v, "readonly parameter; must send as nil or empty in request") - } - default: - return createError(x, v, fmt.Sprintf("constraint %s is not applicable to string type", v.Name)) - } - - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func validateArrayMap(x reflect.Value, v Constraint) error { - switch v.Name { - case Null: - if x.IsNil() { - return checkNil(x, v) - } - case Empty: - if x.IsNil() || x.Len() == 0 { - return checkEmpty(x, v) - } - case MaxItems: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule)) - } - if x.Len() > v.Rule.(int) { - return createError(x, v, fmt.Sprintf("maximum item limit is %v; got: %v", v.Rule, x.Len())) - } - case MinItems: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule)) - } - if x.Len() < v.Rule.(int) { - return createError(x, v, fmt.Sprintf("minimum item limit is %v; got: %v", v.Rule, x.Len())) - } - case UniqueItems: - if x.Kind() == reflect.Array || x.Kind() == reflect.Slice { - if !checkForUniqueInArray(x) { - return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x)) - } - } else if x.Kind() == reflect.Map { - if !checkForUniqueInMap(x) { - return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x)) - } - } else { - return createError(x, v, fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", v.Name, x.Kind())) - } - case ReadOnly: - if x.Len() != 0 { - return createError(x, v, "readonly parameter; must send as nil or empty in request") - } - case Pattern: - reg, err := regexp.Compile(v.Rule.(string)) - if err != nil { - return createError(x, v, err.Error()) - } - keys := x.MapKeys() - for _, k := range keys { - if !reg.MatchString(k.String()) { - return createError(k, v, fmt.Sprintf("map key doesn't match pattern %v", v.Rule)) - } - } - default: - return createError(x, v, fmt.Sprintf("constraint %v is not applicable to array, slice and map type", v.Name)) - } - - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func checkNil(x reflect.Value, v Constraint) error { - if _, ok := v.Rule.(bool); !ok { - return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - } - if v.Rule.(bool) { - return createError(x, v, "value can not be null; required parameter") - } - return nil -} - -func checkEmpty(x reflect.Value, v Constraint) error { - if _, ok := v.Rule.(bool); !ok { - return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - } - - if v.Rule.(bool) { - return createError(x, v, "value can not be null or empty; required parameter") - } - return nil -} - -func checkForUniqueInArray(x reflect.Value) bool { - if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 { - return false - } - arrOfInterface := make([]interface{}, x.Len()) - - for i := 0; i < x.Len(); i++ { - arrOfInterface[i] = x.Index(i).Interface() - } - - m := make(map[interface{}]bool) - for _, val := range arrOfInterface { - if m[val] { - return false - } - m[val] = true - } - return true -} - -func checkForUniqueInMap(x reflect.Value) bool { - if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 { - return false - } - mapOfInterface := make(map[interface{}]interface{}, x.Len()) - - keys := x.MapKeys() - for _, k := range keys { - mapOfInterface[k.Interface()] = x.MapIndex(k).Interface() - } - - m := make(map[interface{}]bool) - for _, val := range mapOfInterface { - if m[val] { - return false - } - m[val] = true - } - return true -} - -func getInterfaceValue(x reflect.Value) interface{} { - if x.Kind() == reflect.Invalid { - return nil - } - return x.Interface() -} - -func isZero(x interface{}) bool { - return x == reflect.Zero(reflect.TypeOf(x)).Interface() -} - -func createError(x reflect.Value, v Constraint, err string) error { - return fmt.Errorf("autorest/validation: validation failed: parameter=%s constraint=%s value=%#v details: %s", - v.Target, v.Name, getInterfaceValue(x), err) -} - -// NewErrorWithValidationError appends package type and method name in -// validation error. -func NewErrorWithValidationError(err error, packageType, method string) error { - return fmt.Errorf("%s#%s: Invalid input: %v", packageType, method, err) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go b/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go deleted file mode 100644 index c86649d8..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/validation/validation_test.go +++ /dev/null @@ -1,2433 +0,0 @@ -package validation - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestCheckForUniqueInArrayTrue(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3})), true) -} - -func TestCheckForUniqueInArrayFalse(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3, 3})), false) -} - -func TestCheckForUniqueInArrayEmpty(t *testing.T) { - require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{})), false) -} - -func TestCheckForUniqueInMapTrue(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[string]int{"one": 1, "two": 2})), true) -} - -func TestCheckForUniqueInMapFalse(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{1: "one", 2: "one"})), false) -} - -func TestCheckForUniqueInMapEmpty(t *testing.T) { - require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{})), false) -} - -func TestCheckEmpty_WithValueEmptyRuleTrue(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter") - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckEmpty_WithEmptyStringRuleFalse(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, checkEmpty(reflect.ValueOf(x), v)) -} - -func TestCheckEmpty_IncorrectRule(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: 10, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckEmpty_WithErrorArray(t *testing.T) { - var x interface{} = []string{} - v := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter") - require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckNil_WithNilValueRuleTrue(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "x", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"x", MaxItems, 4, nil}, - }, - } - expected := createError(reflect.ValueOf(x), v, "value can not be null; required parameter") - require.Equal(t, checkNil(reflect.ValueOf(x), v).Error(), expected.Error()) -} - -func TestCheckNil_WithNilValueRuleFalse(t *testing.T) { - var x interface{} - v := Constraint{ - Target: "x", - Name: Null, - Rule: false, - Chain: []Constraint{ - {"x", MaxItems, 4, nil}, - }, - } - require.Nil(t, checkNil(reflect.ValueOf(x), v)) -} - -func TestCheckNil_IncorrectRule(t *testing.T) { - var x interface{} - c := Constraint{ - Target: "str", - Name: Null, - Rule: 10, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, checkNil(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_WithNilValueRuleTrue(t *testing.T) { - var a []string - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: Null, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, "value can not be null; required parameter") - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected) -} - -func TestValidateArrayMap_WithNilValueRuleFalse(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Null, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithValueRuleNullTrue(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: Null, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithEmptyValueRuleTrue(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: true, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, "value can not be null or empty; required parameter") - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected) -} - -func TestValidateArrayMap_WithEmptyValueRuleFalse(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_WithEmptyRuleEmptyTrue(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MaxItemsIncorrectRule(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: false, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MaxItemsNoError(t *testing.T) { - var x interface{} = []string{"1", "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MaxItemsWithError(t *testing.T) { - var x interface{} = []string{"1", "2", "3"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("maximum item limit is %v; got: 3", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MaxItemsWithEmpty(t *testing.T) { - var x interface{} = []string{} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_MinItemsIncorrectRule(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: false, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MinItemsNoError1(t *testing.T) { - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2}), c)) -} - -func TestValidateArrayMap_MinItemsNoError2(t *testing.T) { - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2, 3}), c)) -} - -func TestValidateArrayMap_MinItemsWithError(t *testing.T) { - var x interface{} = []int{1} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 1", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_MinItemsWithEmpty(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 0", c.Rule)) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_Map_MaxItemsIncorrectRule(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: false, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateArrayMap_Map_MaxItemsNoError(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MaxItemsWithError(t *testing.T) { - a := map[int]string{1: "1", 2: "2", 3: "3"} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", c.Rule, len(a))), true) -} - -func TestValidateArrayMap_Map_MaxItemsWithEmpty(t *testing.T) { - a := map[int]string{} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MaxItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MinItemsIncorrectRule(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: false, - Chain: nil, - } - require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateArrayMap_Map_MinItemsNoError1(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2"} - require.Nil(t, validateArrayMap(reflect.ValueOf(x), - Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - })) -} - -func TestValidateArrayMap_Map_MinItemsNoError2(t *testing.T) { - var x interface{} = map[int]string{1: "1", 2: "2", 3: "3"} - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_MinItemsWithError(t *testing.T) { - a := map[int]string{1: "1"} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a))) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -func TestValidateArrayMap_Map_MinItemsWithEmpty(t *testing.T) { - a := map[int]string{} - var x interface{} = a - c := Constraint{ - Target: "arr", - Name: MinItems, - Rule: 2, - Chain: nil, - } - expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a))) - require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error()) -} - -// func TestValidateArrayMap_Map_MinItemsNil(t *testing.T) { -// var a map[int]float64 -// var x interface{} = a -// c := Constraint{ -// Target: "str", -// Name: MinItems, -// Rule: true, -// Chain: nil, -// } -// expected := createError(reflect.Value(x), c, fmt.Sprintf("all items in parameter %v must be unique; got:%v", c.Target, x)) -// if z := validateArrayMap(reflect.ValueOf(x), c); strings.Contains(z.Error(), "all items in parameter str must be unique;") { -// t.Fatalf("autorest/validation: valiateArrayMap failed to return error \nexpect: %v;\ngot: %v", expected, z) -// } -// } - -func TestValidateArrayMap_Map_UniqueItemsTrue(t *testing.T) { - var x interface{} = map[float64]int{1.2: 1, 1.4: 2} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Map_UniqueItemsFalse(t *testing.T) { - var x interface{} = map[string]string{"1": "1", "2": "2", "3": "1"} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true) -} - -func TestValidateArrayMap_Map_UniqueItemsEmpty(t *testing.T) { - // Consider Empty map as not unique returns false - var x interface{} = map[int]float64{} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true) -} - -func TestValidateArrayMap_Map_UniqueItemsNil(t *testing.T) { - var a map[int]float64 - var x interface{} = a - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsTrue(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_Array_UniqueItemsFalse(t *testing.T) { - var x interface{} = []string{"1", "2", "1"} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsEmpty(t *testing.T) { - // Consider Empty array as not unique returns false - var x interface{} = []float64{} - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsNil(t *testing.T) { - // Consider nil array as not unique returns false - var a []float64 - var x interface{} = a - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true) -} - -func TestValidateArrayMap_Array_UniqueItemsInvalidType(t *testing.T) { - var x interface{} = "hello" - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", c.Name, reflect.ValueOf(x).Kind())), true) -} - -func TestValidateArrayMap_Array_UniqueItemsInvalidConstraint(t *testing.T) { - var x interface{} = "hello" - c := Constraint{ - Target: "str", - Name: "sdad", - Rule: true, - Chain: nil, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("constraint %v is not applicable to array, slice and map type", c.Name)), true) -} - -func TestValidateArrayMap_ValidateChainConstraint1(t *testing.T) { - a := []int{1, 2, 3, 4} - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true) -} - -func TestValidateArrayMap_ValidateChainConstraint2(t *testing.T) { - a := []int{1, 2, 3, 4} - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true) -} - -func TestValidateArrayMap_ValidateChainConstraint3(t *testing.T) { - var a []string - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("value can not be null; required parameter")), true) -} - -func TestValidateArrayMap_ValidateChainConstraint4(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("value can not be null or empty; required parameter")), true) -} - -func TestValidateArrayMap_ValidateChainConstraintNilNotRequired(t *testing.T) { - var a []int - var x interface{} = a - c := Constraint{ - Target: "str", - Name: Null, - Rule: false, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_ValidateChainConstraintEmptyNotRequired(t *testing.T) { - var x interface{} = map[string]int{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateArrayMap_ReadOnlyWithError(t *testing.T) { - var x interface{} = []int{1, 2} - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: []Constraint{ - {"str", MaxItems, 3, nil}, - }, - } - z := validateArrayMap(reflect.ValueOf(x), c) - require.Equal(t, strings.Contains(z.Error(), - fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true) -} - -func TestValidateArrayMap_ReadOnlyWithoutError(t *testing.T) { - var x interface{} = []int{} - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Nil(t, validateArrayMap(reflect.ValueOf(x), c)) -} - -func TestValidateString_ReadOnly(t *testing.T) { - var x interface{} = "Hello Gopher" - c := Constraint{ - Target: "str", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true) -} - -func TestValidateString_EmptyTrue(t *testing.T) { - // Empty true means parameter is required but Empty returns error - c := Constraint{ - Target: "str", - Name: Empty, - Rule: true, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(""), c).Error(), - fmt.Sprintf("value can not be null or empty; required parameter")), true) -} - -func TestValidateString_EmptyFalse(t *testing.T) { - // Empty false means parameter is not required and Empty return nil - var x interface{} - c := Constraint{ - Target: "str", - Name: Empty, - Rule: false, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf(x), c)) -} - -func TestValidateString_MaxLengthInvalid(t *testing.T) { - // Empty true means parameter is required but Empty returns error - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: 4, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value length must be less than or equal to %v", c.Rule)), true) -} - -func TestValidateString_MaxLengthValid(t *testing.T) { - // Empty false means parameter is not required and Empty return nil - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: 7, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("Hello"), c)) -} - -func TestValidateString_MaxLengthRuleInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MaxLength, - Rule: true, // must be int for maxLength - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateString_MinLengthInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: 10, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value length must be greater than or equal to %v", c.Rule)), true) -} - -func TestValidateString_MinLengthValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("Hello"), c)) -} - -func TestValidateString_MinLengthRuleInvalid(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: MinLength, - Rule: true, // must be int for minLength - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateString_PatternInvalidPattern(t *testing.T) { - var x interface{} = "Hello" - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[[:alnum:$`, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - "error parsing regexp: missing closing ]"), true) -} - -func TestValidateString_PatternMatch1(t *testing.T) { - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^http://\w+$`, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("http://masd"), c)) -} - -func TestValidateString_PatternMatch2(t *testing.T) { - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[a-zA-Z0-9]+$`, - Chain: nil, - } - require.Nil(t, validateString(reflect.ValueOf("asdadad2323sad"), c)) -} - -func TestValidateString_PatternNotMatch(t *testing.T) { - var x interface{} = "asdad@@ad2323sad" - c := Constraint{ - Target: "str", - Name: Pattern, - Rule: `^[a-zA-Z0-9]+$`, - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value doesn't match pattern %v", c.Rule)), true) -} - -func TestValidateString_InvalidConstraint(t *testing.T) { - var x interface{} = "asdad@@ad2323sad" - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: "^[a-zA-Z0-9]+$", - Chain: nil, - } - require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %s is not applicable to string type", c.Name)), true) -} - -func TestValidateFloat_InvalidConstraint(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: 3.0, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %v is not applicable for type float", c.Name)), true) -} - -func TestValidateFloat_InvalidRuleValue(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be float value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateFloat_ExclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_ExclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1.4 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.5, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than %v", c.Rule)), true) -} - -func TestValidateFloat_ExclusiveMinimumConstraintBoundary(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1.42, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than %v", c.Rule)), true) -} - -func TestValidateFloat_exclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 2.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_exclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1.2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than %v", c.Rule)), true) -} - -func TestValidateFloat_exclusiveMaximumConstraintBoundary(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1.42, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than %v", c.Rule)), true) -} - -func TestValidateFloat_inclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 2.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_inclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1.2, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be less than or equal to %v", c.Rule)), true) - -} - -func TestValidateFloat_inclusiveMaximumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1.42, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_InclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.0, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateFloat_InclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1.42 - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.5, - Chain: nil, - } - require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("value must be greater than or equal to %v", c.Rule)), true) - -} - -func TestValidateFloat_InclusiveMinimumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1.42, - Chain: nil, - } - require.Nil(t, validateFloat(reflect.ValueOf(1.42), c)) -} - -func TestValidateInt_InvalidConstraint(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: UniqueItems, - Rule: 3, - Chain: nil, - } - require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("constraint %s is not applicable for type integer", c.Name)), true) -} - -func TestValidateInt_InvalidRuleValue(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3.4, - Chain: nil, - } - require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true) -} - -func TestValidateInt_ExclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(3), c)) -} - -func TestValidateInt_ExclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error()) -} - -func TestValidateInt_ExclusiveMinimumConstraintBoundary(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error()) -} - -func TestValidateInt_exclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_exclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 2 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error()) -} - -func TestValidateInt_exclusiveMaximumConstraintBoundary(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: ExclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error()) -} - -func TestValidateInt_inclusiveMaximumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 2, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_inclusiveMaximumConstraintInvalid(t *testing.T) { - var x interface{} = 2 - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than or equal to %v", c.Rule)).Error()) -} - -func TestValidateInt_inclusiveMaximumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMaximum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_InclusiveMinimumConstraintValid(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_InclusiveMinimumConstraintInvalid(t *testing.T) { - var x interface{} = 1 - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 2, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than or equal to %v", c.Rule)).Error()) -} - -func TestValidateInt_InclusiveMinimumConstraintBoundary(t *testing.T) { - c := Constraint{ - Target: "str", - Name: InclusiveMinimum, - Rule: 1, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(1), c)) -} - -func TestValidateInt_MultipleOfWithoutError(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MultipleOf, - Rule: 10, - Chain: nil, - } - require.Nil(t, validateInt(reflect.ValueOf(2300), c)) -} - -func TestValidateInt_MultipleOfWithError(t *testing.T) { - c := Constraint{ - Target: "str", - Name: MultipleOf, - Rule: 11, - Chain: nil, - } - require.Equal(t, validateInt(reflect.ValueOf(2300), c).Error(), - createError(reflect.ValueOf(2300), c, fmt.Sprintf("value must be a multiple of %v", c.Rule)).Error()) -} - -func TestValidatePointer_NilTrue(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, // Required property - Chain: nil, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, "value can not be null; required parameter").Error()) -} - -func TestValidatePointer_NilFalse(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: false, // not required property - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_NilReadonlyValid(t *testing.T) { - var z *int - var x interface{} = z - c := Constraint{ - Target: "ptr", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_NilReadonlyInvalid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: ReadOnly, - Rule: true, - Chain: nil, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(z), c, "readonly parameter; must send as nil or empty in request").Error()) -} - -func TestValidatePointer_IntValid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3, - Chain: nil, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_IntInvalid(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 11, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], "value must be greater than or equal to 11").Error()) -} - -func TestValidatePointer_IntInvalidConstraint(t *testing.T) { - z := 10 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error()) -} - -func TestValidatePointer_ValidInt64(t *testing.T) { - z := int64(10) - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3, - Chain: nil, - }, - }} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_InvalidConstraintInt64(t *testing.T) { - z := int64(10) - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3, - Chain: nil, - }, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error()) -} - -func TestValidatePointer_ValidFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 3.0, - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_InvalidFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: InclusiveMinimum, - Rule: 12.0, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10.1), c.Chain[0], - "value must be greater than or equal to 12").Error()) -} - -func TestValidatePointer_InvalidConstraintFloat(t *testing.T) { - z := 10.1 - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxItems, - Rule: 3.0, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(10.1), c.Chain[0], - fmt.Sprintf("constraint %v is not applicable for type float", MaxItems)).Error()) -} - -func TestValidatePointer_StringValid(t *testing.T) { - z := "hello" - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: Pattern, - Rule: "^[a-z]+$", - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidatePointer_StringInvalid(t *testing.T) { - z := "hello" - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: MaxLength, - Rule: 2, - Chain: nil, - }}} - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("hello"), c.Chain[0], - "value length must be less than or equal to 2").Error()) -} - -func TestValidatePointer_ArrayValid(t *testing.T) { - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: UniqueItems, - Rule: "true", - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(&[]string{"1", "2"}), c)) -} - -func TestValidatePointer_ArrayInvalid(t *testing.T) { - z := []string{"1", "2", "2"} - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{{ - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(z), c.Chain[0], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, z)).Error()) -} - -func TestValidatePointer_MapValid(t *testing.T) { - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{ - { - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}} - require.Nil(t, validatePtr(reflect.ValueOf(&map[interface{}]string{1: "1", "1": "2"}), c)) -} - -func TestValidatePointer_MapInvalid(t *testing.T) { - z := map[interface{}]string{1: "1", "1": "2", 1.3: "2"} - var x interface{} = &z - c := Constraint{ - Target: "ptr", - Name: Null, - Rule: true, - Chain: []Constraint{{ - Target: "ptr", - Name: UniqueItems, - Rule: true, - Chain: nil, - }}, - } - require.Equal(t, strings.Contains(validatePtr(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("all items in parameter %q must be unique;", c.Target)), true) -} - -type Child struct { - I string -} -type Product struct { - C *Child - Str *string - Name string - Arr *[]string - M *map[string]string - Num *int32 -} - -type Sample struct { - M *map[string]*string - Name string -} - -func TestValidatePointer_StructWithError(t *testing.T) { - s := "hello" - var x interface{} = &Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "p", Null, "True", - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", MaxLength, 2, nil}, - }}, - {"Str", MaxLength, 2, nil}, - {"Name", MaxLength, 5, nil}, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("100"), c.Chain[0].Chain[0], - "value length must be less than or equal to 2").Error()) -} - -func TestValidatePointer_WithNilStruct(t *testing.T) { - var p *Product - var x interface{} = p - c := Constraint{ - "p", Null, true, - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 5, nil}, - }}, - }}, - {"Str", MaxLength, 2, nil}, - {"Name", MaxLength, 5, nil}, - }, - } - require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x), c, - fmt.Sprintf("value can not be null; required parameter")).Error()) -} - -func TestValidatePointer_StructWithNoError(t *testing.T) { - s := "hello" - var x interface{} = &Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "p", Null, true, - []Constraint{ - {"C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 5, nil}, - }}, - }}, - }, - } - require.Nil(t, validatePtr(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_FieldNotExist(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "C", Null, true, - []Constraint{ - {"Name", Empty, true, nil}, - }, - } - s = "Name" - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(Child{"100"}), c.Chain[0], - fmt.Sprintf("field %q doesn't exist", s)).Error()) -} - -func TestValidateStruct_WithChainConstraint(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{"100"}, - Str: &s, - Name: "Gopher", - } - c := Constraint{ - "C", Null, true, - []Constraint{ - {"I", Empty, true, - []Constraint{ - {"I", MaxLength, 2, nil}, - }}, - }, - } - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf("100"), c.Chain[0].Chain[0], "value length must be less than or equal to 2").Error()) -} - -func TestValidateStruct_WithoutChainConstraint(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{""}, - Str: &s, - Name: "Gopher", - } - c := Constraint{"C", Null, true, - []Constraint{ - {"I", Empty, true, nil}, // throw error for Empty - }} - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(""), c.Chain[0], "value can not be null or empty; required parameter").Error()) -} - -func TestValidateStruct_WithArrayNull(t *testing.T) { - s := "hello" - var x interface{} = Product{ - C: &Child{""}, - Str: &s, - Name: "Gopher", - Arr: nil, - } - c := Constraint{"Arr", Null, true, - []Constraint{ - {"Arr", MaxItems, 4, nil}, - {"Arr", MinItems, 2, nil}, - }, - } - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(x.(Product).Arr), c, "value can not be null; required parameter").Error()) -} - -func TestValidateStruct_WithArrayEmptyError(t *testing.T) { - // arr := []string{} - var x interface{} = Product{ - Arr: &[]string{}, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", MinItems, 2, nil}, - }} - - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[0], - fmt.Sprintf("value can not be null or empty; required parameter")).Error()) -} - -func TestValidateStruct_WithArrayEmptyWithoutError(t *testing.T) { - var x interface{} = Product{ - Arr: &[]string{}, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, false, nil}, - {"Arr", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_ArrayWithError(t *testing.T) { - arr := []string{"1", "1"} - var x interface{} = Product{ - Arr: &arr, - } - c := Constraint{ - "Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - } - s := "Arr" - require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(), - createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[2], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, *(x.(Product).Arr))).Error()) -} - -func TestValidateStruct_MapWithError(t *testing.T) { - m := map[string]string{ - "a": "hello", - "b": "hello", - } - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, true, - []Constraint{ - {"M", Empty, true, nil}, - {"M", MaxItems, 4, nil}, - {"M", UniqueItems, true, nil}, - }, - } - - s := "M" - require.Equal(t, strings.Contains(validateStruct(reflect.ValueOf(x), c).Error(), - fmt.Sprintf("all items in parameter %q must be unique;", s)), true) -} - -func TestValidateStruct_MapWithNoError(t *testing.T) { - m := map[string]string{} - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, true, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidateStruct_MapNilNoError(t *testing.T) { - var m map[string]string - var x interface{} = Product{ - M: &m, - } - c := Constraint{ - "M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MaxItems, 4, nil}, - }, - } - require.Nil(t, validateStruct(reflect.ValueOf(x), c)) -} - -func TestValidate_MapValidationWithError(t *testing.T) { - var x1 interface{} = &Product{ - Arr: &[]string{"1", "2"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = &Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"x1", Null, true, - []Constraint{ - {"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - }, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }, - }}}, - {x2, - []Constraint{ - {"x2", Null, true, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 2, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - - z := Validate(v).Error() - require.Equal(t, strings.Contains(z, "minimum item limit is 2; got: 1"), true) - require.Equal(t, strings.Contains(z, "MinItems"), true) -} - -func TestValidate_MapValidationWithoutError(t *testing.T) { - var x1 interface{} = &Product{ - Arr: &[]string{"1", "2"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = &Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"x1", Null, true, - []Constraint{ - {"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }, - }, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - {"M", Pattern, "^[a-z]+$", nil}, - }, - }, - }, - }}}, - {x2, - []Constraint{ - {"x2", Null, true, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - {"M", Pattern, "^[a-z]+$", nil}, - }, - }, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_UnknownType(t *testing.T) { - var c chan int - v := []Validation{ - {c, - []Constraint{{"c", Null, true, nil}}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(c), v[0].Constraints[0], - fmt.Sprintf("unknown type %v", reflect.ValueOf(c).Kind())).Error()) -} - -func TestValidate_example1(t *testing.T) { - var x1 interface{} = Product{ - Arr: &[]string{"1", "1"}, - M: &map[string]string{"a": "hello"}, - } - s := "hello" - var x2 interface{} = Sample{ - M: &map[string]*string{"a": &s}, - } - v := []Validation{ - {x1, - []Constraint{{"Arr", Null, true, - []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MaxItems, 4, nil}, - {"Arr", UniqueItems, true, nil}, - }}, - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - }}, - {x2, - []Constraint{ - {"M", Null, false, - []Constraint{ - {"M", Empty, false, nil}, - {"M", MinItems, 1, nil}, - {"M", UniqueItems, true, nil}, - }, - }, - {"Name", Empty, true, nil}, - }}, - } - s = "Arr" - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{"1", "1"}), v[0].Constraints[0].Chain[2], - fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, []string{"1", "1"})).Error()) -} - -func TestValidate_Int(t *testing.T) { - n := int32(100) - v := []Validation{ - {n, - []Constraint{ - {"n", MultipleOf, 10, nil}, - {"n", ExclusiveMinimum, 100, nil}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[1], - "value must be greater than 100").Error()) -} - -func TestValidate_IntPointer(t *testing.T) { - n := int32(100) - p := &n - v := []Validation{ - {p, - []Constraint{ - {"p", Null, true, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0], - "value must be greater than 100").Error()) - - // required paramter - p = nil - v = []Validation{ - {p, - []Constraint{ - {"p", Null, true, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(v[0].TargetValue), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // Not required - p = nil - v = []Validation{ - {p, - []Constraint{ - {"p", Null, false, []Constraint{ - {"p", ExclusiveMinimum, 100, nil}, - }}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_IntStruct(t *testing.T) { - n := int32(100) - p := &Product{ - Num: &n, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Num", Null, true, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0].Chain[0], - "value must be greater than 100").Error()) - - // required paramter - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Num", Null, true, []Constraint{ - {"p.Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Num), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Num", Null, false, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Num", Null, false, []Constraint{ - {"Num", ExclusiveMinimum, 100, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_String(t *testing.T) { - s := "hello" - v := []Validation{ - {s, - []Constraint{ - {"s", Empty, true, nil}, - {"s", Empty, true, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[1].Chain[0], - "value length must be less than or equal to 3").Error()) - - // required paramter - s = "" - v = []Validation{ - {s, - []Constraint{ - {"s", Empty, true, nil}, - {"s", Empty, true, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[1], - "value can not be null or empty; required parameter").Error()) - - // not required paramter - s = "" - v = []Validation{ - {s, - []Constraint{ - {"s", Empty, false, nil}, - {"s", Empty, false, - []Constraint{{"s", MaxLength, 3, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_StringStruct(t *testing.T) { - s := "hello" - p := &Product{ - Str: &s, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Str", Null, true, []Constraint{ - {"p.Str", Empty, true, nil}, - {"p.Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - // e := ValidationError{ - // Constraint: MaxLength, - // Target: "Str", - // TargetValue: s, - // Details: fmt.Sprintf("value length must be less than 3", s), - // } - // if z := Validate(v); !reflect.DeepEqual(e, z) { - // t.Fatalf("autorest/validation: Validate failed to return error \nexpect: %v\ngot: %v", e, z) - // } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1], - "value length must be less than or equal to 3").Error()) - - // required paramter - can't be Empty - s = "" - p = &Product{ - Str: &s, - } - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Str", Null, true, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required paramter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Str", Null, true, []Constraint{ - {"p.Str", Empty, true, nil}, - {"p.Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Str), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"Str", Null, false, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Str", Null, true, []Constraint{ - {"Str", Empty, true, nil}, - {"Str", MaxLength, 3, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_Array(t *testing.T) { - s := []string{"hello"} - v := []Validation{ - {s, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // Empty array - v = []Validation{ - {[]string{}, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // null array - var s1 []string - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, true, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s1), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // not required paramter - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, false, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_ArrayPointer(t *testing.T) { - s := []string{"hello"} - v := []Validation{ - {&s, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}, - }}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // Empty array - v = []Validation{ - {&[]string{}, - []Constraint{ - {"s", Null, true, - []Constraint{ - {"s", Empty, true, nil}, - {"s", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // null array - var s1 *[]string - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, true, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s1), v[0].Constraints[0], - "value can not be null; required parameter").Error()) - - // not required paramter - v = []Validation{ - {s1, - []Constraint{ - {"s1", Null, false, - []Constraint{ - {"s1", Empty, true, nil}, - {"s1", MinItems, 2, nil}}}, - }, - }, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_ArrayInStruct(t *testing.T) { - s := []string{"hello"} - p := &Product{ - Arr: &s, - } - - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1], - fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error()) - - // required paramter - can't be Empty - p = &Product{ - Arr: &[]string{}, - } - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required paramter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{ - {"p.Arr", Null, true, []Constraint{ - {"p.Arr", Empty, true, nil}, - {"p.Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.Arr), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - v = []Validation{ - {&Product{}, []Constraint{{"p", Null, true, - []Constraint{ - {"Arr", Null, false, []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{ - {"Arr", Null, true, []Constraint{ - {"Arr", Empty, true, nil}, - {"Arr", MinItems, 2, nil}, - }}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestValidate_StructInStruct(t *testing.T) { - p := &Product{ - C: &Child{I: "hello"}, - } - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", MinLength, 7, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0], - "value length must be greater than or equal to 7").Error()) - - // required paramter - can't be Empty - p = &Product{ - C: &Child{I: ""}, - } - - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", Empty, true, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0], - "value can not be null or empty; required parameter").Error()) - - // required paramter - can't be null - p = &Product{} - v = []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"C", Null, true, - []Constraint{{"I", Empty, true, nil}}}, - }, - }}}, - } - require.Equal(t, Validate(v).Error(), - createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], - "value can not be null; required parameter").Error()) - - // Not required - v = []Validation{ - {&Product{}, []Constraint{{"p", Null, true, - []Constraint{{"p.C", Null, false, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - require.Nil(t, Validate(v)) - - // Parent not required - p = nil - v = []Validation{ - {p, []Constraint{{"p", Null, false, - []Constraint{{"p.C", Null, false, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - require.Nil(t, Validate(v)) -} - -func TestNewErrorWithValidationError(t *testing.T) { - p := &Product{} - v := []Validation{ - {p, []Constraint{{"p", Null, true, - []Constraint{{"p.C", Null, true, - []Constraint{{"p.C.I", Empty, true, nil}}}, - }, - }}}, - } - err := createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], "value can not be null; required parameter") - z := fmt.Sprintf("batch.AccountClient#Create: Invalid input: %s", - err.Error()) - require.Equal(t, NewErrorWithValidationError(err, "batch.AccountClient", "Create").Error(), z) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/version.go b/vendor/github.com/Azure/go-autorest/autorest/version.go deleted file mode 100644 index a19c0d35..00000000 --- a/vendor/github.com/Azure/go-autorest/autorest/version.go +++ /dev/null @@ -1,49 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "strings" - "sync" -) - -const ( - major = 9 - minor = 8 - patch = 1 - tag = "" -) - -var once sync.Once -var version string - -// Version returns the semantic version (see http://semver.org). -func Version() string { - once.Do(func() { - semver := fmt.Sprintf("%d.%d.%d", major, minor, patch) - verBuilder := bytes.NewBufferString(semver) - if tag != "" && tag != "-" { - updated := strings.TrimPrefix(tag, "-") - _, err := verBuilder.WriteString("-" + updated) - if err == nil { - verBuilder = bytes.NewBufferString(semver) - } - } - version = verBuilder.String() - }) - return version -} diff --git a/vendor/github.com/Azure/go-autorest/glide.lock b/vendor/github.com/Azure/go-autorest/glide.lock deleted file mode 100644 index 695d58cf..00000000 --- a/vendor/github.com/Azure/go-autorest/glide.lock +++ /dev/null @@ -1,44 +0,0 @@ -hash: 6e0121d946623e7e609280b1b18627e1c8a767fdece54cb97c4447c1167cbc46 -updated: 2017-08-31T13:58:01.034822883+01:00 -imports: -- name: github.com/dgrijalva/jwt-go - version: 2268707a8f0843315e2004ee4f1d021dc08baedf - subpackages: - - . -- name: github.com/dimchansky/utfbom - version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f -- name: github.com/mitchellh/go-homedir - version: b8bc1bf767474819792c23f32d8286a45736f1c6 -- name: golang.org/x/crypto - version: 81e90905daefcd6fd217b62423c0908922eadb30 - repo: https://github.com/golang/crypto.git - vcs: git - subpackages: - - pkcs12 - - pkcs12/internal/rc2 -- name: golang.org/x/net - version: 66aacef3dd8a676686c7ae3716979581e8b03c47 - repo: https://github.com/golang/net.git - vcs: git - subpackages: - - . -- name: golang.org/x/text - version: 21e35d45962262c8ee80f6cb048dcf95ad0e9d79 - repo: https://github.com/golang/text.git - vcs: git - subpackages: - - . -testImports: -- name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 - subpackages: - - spew -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 890a5c3458b43e6104ff5da8dfa139d013d77544 - subpackages: - - assert - - require diff --git a/vendor/github.com/Azure/go-autorest/glide.yaml b/vendor/github.com/Azure/go-autorest/glide.yaml deleted file mode 100644 index 375dcfd1..00000000 --- a/vendor/github.com/Azure/go-autorest/glide.yaml +++ /dev/null @@ -1,22 +0,0 @@ -package: github.com/Azure/go-autorest -import: -- package: github.com/dgrijalva/jwt-go - subpackages: - - . -- package: golang.org/x/crypto - repo: https://github.com/golang/crypto.git - vcs: git - subpackages: - - pkcs12 -- package: golang.org/x/net - repo: https://github.com/golang/net.git - vcs: git - subpackages: - - . -- package: golang.org/x/text - repo: https://github.com/golang/text.git - vcs: git - subpackages: - - . -- package: github.com/mitchellh/go-homedir -- package: github.com/dimchansky/utfbom diff --git a/vendor/github.com/Azure/go-autorest/testdata/credsutf16be.json b/vendor/github.com/Azure/go-autorest/testdata/credsutf16be.json deleted file mode 100644 index 7fa689d5..00000000 Binary files a/vendor/github.com/Azure/go-autorest/testdata/credsutf16be.json and /dev/null differ diff --git a/vendor/github.com/Azure/go-autorest/testdata/credsutf16le.json b/vendor/github.com/Azure/go-autorest/testdata/credsutf16le.json deleted file mode 100644 index 7951923e..00000000 Binary files a/vendor/github.com/Azure/go-autorest/testdata/credsutf16le.json and /dev/null differ diff --git a/vendor/github.com/Azure/go-autorest/testdata/credsutf8.json b/vendor/github.com/Azure/go-autorest/testdata/credsutf8.json deleted file mode 100644 index 7d96bcfc..00000000 --- a/vendor/github.com/Azure/go-autorest/testdata/credsutf8.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "clientId": "client-id-123", - "clientSecret": "client-secret-456", - "subscriptionId": "sub-id-789", - "tenantId": "tenant-id-123", - "activeDirectoryEndpointUrl": "https://login.microsoftonline.com", - "resourceManagerEndpointUrl": "https://management.azure.com/", - "activeDirectoryGraphResourceId": "https://graph.windows.net/", - "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/", - "galleryEndpointUrl": "https://gallery.azure.com/", - "managementEndpointUrl": "https://management.core.windows.net/" -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/Gopkg.lock b/vendor/github.com/Peripli/service-broker-proxy/Gopkg.lock index 6be135a5..b84f9f8d 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/Gopkg.lock +++ b/vendor/github.com/Peripli/service-broker-proxy/Gopkg.lock @@ -5,18 +5,32 @@ branch = "master" name = "github.com/Peripli/service-manager" packages = [ + "api", + "api/broker", + "api/catalog", + "api/filters", + "api/filters/authn", + "api/healthcheck", + "api/info", + "api/osb", + "api/platform", "pkg/env", + "pkg/log", + "pkg/server", "pkg/types", "pkg/util", - "pkg/web" + "pkg/web", + "security", + "security/basic", + "security/oidc", + "storage" ] - revision = "6bbeba0c92ac3a6ff0fe64e7495f4a359ca88d07" + revision = "c48beef856f9f591d5724698daf786a5d5b4bb1f" [[projects]] - branch = "master" - name = "github.com/beorn7/perks" - packages = ["quantile"] - revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + name = "github.com/coreos/go-oidc" + packages = ["."] + revision = "1180514eaf4d9f38d0d19eef639a1d695e066e72" [[projects]] name = "github.com/fatih/structs" @@ -54,8 +68,8 @@ [[projects]] name = "github.com/golang/protobuf" packages = ["proto"] - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" [[projects]] name = "github.com/gorilla/context" @@ -63,6 +77,12 @@ revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" +[[projects]] + name = "github.com/gorilla/handlers" + packages = ["."] + revision = "90663712d74cb411cbef281bc1e08c19d1a76145" + version = "v1.3.0" + [[projects]] name = "github.com/gorilla/mux" packages = ["."] @@ -104,12 +124,6 @@ revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" -[[projects]] - name = "github.com/matttproud/golang_protobuf_extensions" - packages = ["pbutil"] - revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" - version = "v1.0.1" - [[projects]] branch = "master" name = "github.com/mitchellh/mapstructure" @@ -123,7 +137,7 @@ "filename", "formatter" ] - revision = "00f4ddfaeb23824ce8b9ce969095a9b2529b9eca" + revision = "ca0a758702be2ae04725ba88dcd27a71949faf33" [[projects]] name = "github.com/onsi/ginkgo" @@ -167,8 +181,8 @@ "matchers/support/goraph/util", "types" ] - revision = "b6ea1ea48f981d0f615a154a45eabb9dd466556d" - version = "v1.4.1" + revision = "003f63b7f4cff3fc95357005358af2de0f5fe152" + version = "v1.3.0" [[projects]] name = "github.com/pelletier/go-toml" @@ -185,55 +199,17 @@ [[projects]] name = "github.com/pmorie/go-open-service-broker-client" packages = ["v2"] - revision = "e8aa16c9036317bd59ced8921e9da6197ab577e3" - version = "0.0.5" - -[[projects]] - name = "github.com/pmorie/osb-broker-lib" - packages = [ - "pkg/broker", - "pkg/metrics", - "pkg/rest", - "pkg/server" - ] - revision = "f4ca270ef323318b363f986229bd10bccb2d28b1" + revision = "dca737037ce636eb282e84e3a1c7479c9692e884" version = "0.0.10" -[[projects]] - name = "github.com/prometheus/client_golang" - packages = [ - "prometheus", - "prometheus/promhttp" - ] - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" - -[[projects]] - branch = "master" - name = "github.com/prometheus/client_model" - packages = ["go"] - revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" - -[[projects]] - branch = "master" - name = "github.com/prometheus/common" - packages = [ - "expfmt", - "internal/bitbucket.org/ww/goautoneg", - "model" - ] - revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" - [[projects]] branch = "master" - name = "github.com/prometheus/procfs" + name = "github.com/pquerna/cachecontrol" packages = [ ".", - "internal/util", - "nfs", - "xfs" + "cacheobject" ] - revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" + revision = "1555304b9b35fdd2b425bccf1a5613677705e7d0" [[projects]] name = "github.com/robfig/cron" @@ -241,6 +217,11 @@ revision = "b41be1df696709bb6395fe435af20370037c0b4c" version = "v1.1" +[[projects]] + name = "github.com/satori/go.uuid" + packages = ["."] + revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" + [[projects]] name = "github.com/sirupsen/logrus" packages = ["."] @@ -266,7 +247,7 @@ branch = "master" name = "github.com/spf13/jwalterweatherman" packages = ["."] - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] name = "github.com/spf13/pflag" @@ -283,18 +264,34 @@ [[projects]] branch = "master" name = "golang.org/x/crypto" - packages = ["ssh/terminal"] - revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + packages = [ + "ed25519", + "ed25519/internal/edwards25519", + "pbkdf2", + "ssh/terminal" + ] + revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] branch = "master" name = "golang.org/x/net" packages = [ + "context", + "context/ctxhttp", "html", "html/atom", "html/charset" ] - revision = "49c15d80dfbc983ea25246ee959d970efe09ec09" + revision = "922f4815f713f213882e8ef45e0d315b164d705c" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "internal" + ] + revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" [[projects]] branch = "master" @@ -303,7 +300,7 @@ "unix", "windows" ] - revision = "bd9dbc187b6e1dacfdd2722a87e83093c2d7bd6e" + revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" [[projects]] name = "golang.org/x/text" @@ -332,6 +329,20 @@ revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" +[[projects]] + name = "google.golang.org/appengine" + packages = [ + "internal", + "internal/base", + "internal/datastore", + "internal/log", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] + revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" + version = "v1.1.0" + [[projects]] name = "gopkg.in/fsnotify.v1" packages = ["."] @@ -339,6 +350,16 @@ source = "https://github.com/fsnotify/fsnotify.git" version = "v1.4.7" +[[projects]] + name = "gopkg.in/square/go-jose.v2" + packages = [ + ".", + "cipher", + "json" + ] + revision = "8254d6c783765f38c8675fae4427a1fe73fbd09d" + version = "v2.1.8" + [[projects]] branch = "v1" name = "gopkg.in/tomb.v1" @@ -354,6 +375,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "a512b775b01edcec7446d08be6af494586fec5fbf338fcab166d0106e969f2d8" + inputs-digest = "a10976151af6c7d11483e96c7a82bd3049fb42c4a3d047d0e287b4cf3ec5d0a8" solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/Peripli/service-broker-proxy/Gopkg.toml b/vendor/github.com/Peripli/service-broker-proxy/Gopkg.toml index 5b56433d..ca32d366 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/Gopkg.toml +++ b/vendor/github.com/Peripli/service-broker-proxy/Gopkg.toml @@ -1,34 +1,14 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md for detailed Gopkg.toml documentation. [prune] go-tests = true unused-packages = true +[[prune.project]] + name = "github.com/Peripli/service-manager" + unused-packages = false + non-go = true + [[constraint]] name = "github.com/robfig/cron" branch = "master" @@ -37,14 +17,6 @@ name = "github.com/pkg/errors" version = "0.8.0" -[[constraint]] - name = "github.com/pmorie/go-open-service-broker-client" - version = "=0.0.5" - -[[constraint]] - name = "github.com/pmorie/osb-broker-lib" - version = "=0.0.10" - [[constraint]] name = "github.com/sirupsen/logrus" version = "=1.0.4" @@ -53,17 +25,13 @@ name = "github.com/onrik/logrus" branch = "master" -[[constraint]] - name = "github.com/gorilla/mux" - version = "=1.6.1" - [[constraint]] name = "github.com/onsi/ginkgo" version = "1.4.0" [[constraint]] name = "github.com/onsi/gomega" - version = "1.3.0" + version = "=1.3.0" [[constraint]] name = "github.com/spf13/pflag" diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/config/config.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/config/config.go index d915cfc2..16615518 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/config/config.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/config/config.go @@ -1,60 +1,58 @@ package config import ( - "github.com/Peripli/service-broker-proxy/pkg/osb" - "github.com/Peripli/service-broker-proxy/pkg/server" "github.com/Peripli/service-broker-proxy/pkg/sm" "github.com/Peripli/service-manager/pkg/env" + "github.com/Peripli/service-manager/pkg/log" + "github.com/Peripli/service-manager/pkg/server" "github.com/spf13/pflag" ) -// New builds an sbproxy.Config from the specified Environment -func New(env env.Environment) (*Config, error) { - serverConfig, err := server.NewConfig(env) - if err != nil { - return nil, err - } +// Settings type holds all config properties for the sbproxy +type Settings struct { + Server *server.Settings `mapstructure:"server"` + Log *log.Settings `mapstructure:"log"` + Sm *sm.Settings `mapstructure:"sm"` + SelfURL string `mapstructure:"self_url"` +} - smConfig, err := sm.NewConfig(env) - if err != nil { - return nil, err +// DefaultSettings returns default value for the proxy settings +func DefaultSettings() *Settings { + return &Settings{ + Server: server.DefaultSettings(), + Log: log.DefaultSettings(), + Sm: sm.DefaultSettings(), + SelfURL: "", } +} - osbConfig, err := osb.NewConfig(smConfig) - if err != nil { +// NewSettings creates new proxy settings from the specified environment +func NewSettings(env env.Environment) (*Settings, error) { + config := DefaultSettings() + if err := env.Unmarshal(config); err != nil { return nil, err } - config := &Config{ - Server: serverConfig, - Osb: osbConfig, - Sm: smConfig, - } - return config, nil } -// AddPFlags adds the pflags needed for the the proxy default config to the provided flag set. +// AddPFlags adds the SM config flags to the provided flag set func AddPFlags(set *pflag.FlagSet) { - defaultCfg := &Config{ - Server: server.DefaultConfig(), - Sm: sm.DefaultConfig(), - Osb: osb.DefaultConfig(), - } + env.CreatePFlags(set, DefaultSettings()) - env.CreatePFlags(set, defaultCfg) + env.CreatePFlagsForConfigFile(set) } -// Config type holds all config properties for the sbproxy -type Config struct { - Server *server.Config - Sm *sm.Config - Osb *osb.ClientConfig `structs:"-"` +// New builds an config.Settings from the specified Environment +func New(env env.Environment) (*Settings, error) { + return NewSettings(env) } -// Validate validates the configuration and returns appropriate errors in case it is invalid -func (c *Config) Validate() error { - validatable := []interface{ Validate() error }{c.Server, c.Osb, c.Sm} +// Validate validates that the configuration contains all mandatory properties +func (c *Settings) Validate() error { + validatable := []interface { + Validate() error + }{c.Server, c.Log, c.Sm} for _, item := range validatable { if err := item.Validate(); err != nil { diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/logging/logging.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/logging/logging.go index a89632a5..2763a5cb 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/logging/logging.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/logging/logging.go @@ -4,6 +4,7 @@ import ( "github.com/onrik/logrus/filename" "github.com/onrik/logrus/formatter" "github.com/sirupsen/logrus" + "github.com/Peripli/service-manager/pkg/log" ) const ( @@ -12,19 +13,19 @@ const ( ) // Setup sets up the logrus logging for the proxy based on the provided parameters. -func Setup(logLevel string, logFormat string) { +func Setup(settings *log.Settings) { logrus.AddHook(&ErrorLocationHook{}) hook := filename.NewHook() hook.Field = keyLogSource logrus.AddHook(hook) - level, err := logrus.ParseLevel(logLevel) + level, err := logrus.ParseLevel(settings.Level) if err != nil { logrus.SetLevel(logrus.DebugLevel) logrus.WithError(err).Error("Could not parse log level configuration") } else { logrus.SetLevel(level) } - if logFormat == logFormatJSON { + if settings.Format == logFormatJSON { logrus.SetFormatter(&logrus.JSONFormatter{}) } else { textFormatter := formatter.New() diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/middleware/logging.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/middleware/logging.go deleted file mode 100644 index 005c9dbc..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/middleware/logging.go +++ /dev/null @@ -1,17 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/sirupsen/logrus" -) - -// LogRequest provides a middleware for logging information about an incoming request -func LogRequest() func(handler http.Handler) http.Handler { - return func(handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - logrus.WithFields(map[string]interface{}{"path": r.RequestURI, "method": r.Method}).Info("Request: ") - handler.ServeHTTP(w, r) - }) - } -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/business_logic.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/business_logic.go deleted file mode 100644 index e4ca94e0..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/business_logic.go +++ /dev/null @@ -1,176 +0,0 @@ -package osb - -import ( - "net/http" - - "github.com/pmorie/osb-broker-lib/pkg/broker" - - "github.com/pkg/errors" - - "fmt" - - "github.com/gorilla/mux" - osbc "github.com/pmorie/go-open-service-broker-client/v2" - "github.com/sirupsen/logrus" -) - -// BusinessLogic provides an implementation of the pmorie/osb-broker-lib/pkg/broker/Interface interface. -type BusinessLogic struct { - createFunc osbc.CreateFunc - osbClientConfig *osbc.ClientConfiguration -} - -var _ broker.Interface = &BusinessLogic{} - -// NewBusinessLogic creates an OSB business logic containing logic to proxy OSB calls -func NewBusinessLogic(config *ClientConfig) (*BusinessLogic, error) { - return &BusinessLogic{ - osbClientConfig: config.ClientConfiguration, - createFunc: config.CreateFunc, - }, nil -} - -// GetCatalog implements pmorie/osb-broker-lib/pkg/broker/Interface.GetCatalog by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) GetCatalog(c *broker.RequestContext) (*broker.CatalogResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.GetCatalog() - if err != nil { - return nil, err - } - - return &broker.CatalogResponse{ - CatalogResponse: *response, - }, nil -} - -// Provision implements pmorie/osb-broker-lib/pkg/broker/Interface.Provision by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) Provision(request *osbc.ProvisionRequest, c *broker.RequestContext) (*broker.ProvisionResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.ProvisionInstance(request) - if err != nil { - return nil, err - } - - return &broker.ProvisionResponse{ - ProvisionResponse: *response, - }, nil -} - -// Deprovision implements pmorie/osb-broker-lib/pkg/broker/Interface.Deprovision by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) Deprovision(request *osbc.DeprovisionRequest, c *broker.RequestContext) (*broker.DeprovisionResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.DeprovisionInstance(request) - if err != nil { - return nil, err - } - - return &broker.DeprovisionResponse{ - DeprovisionResponse: *response, - }, nil -} - -// LastOperation implements pmorie/osb-broker-lib/pkg/broker/Interface.LastOperation by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) LastOperation(request *osbc.LastOperationRequest, c *broker.RequestContext) (*broker.LastOperationResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.PollLastOperation(request) - if err != nil { - return nil, err - } - - return &broker.LastOperationResponse{ - LastOperationResponse: *response, - }, nil -} - -// Bind implements pmorie/osb-broker-lib/pkg/broker/Interface.Bind by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) Bind(request *osbc.BindRequest, c *broker.RequestContext) (*broker.BindResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.Bind(request) - if err != nil { - return nil, err - } - - return &broker.BindResponse{ - BindResponse: *response, - }, nil - -} - -// Unbind implements pmorie/osb-broker-lib/pkg/broker/Interface.Unbind by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) Unbind(request *osbc.UnbindRequest, c *broker.RequestContext) (*broker.UnbindResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - - response, err := client.Unbind(request) - if err != nil { - return nil, err - } - - return &broker.UnbindResponse{ - UnbindResponse: *response, - }, nil -} - -// Update implements pmorie/osb-broker-lib/pkg/broker/Interface.Update by -// proxying the call to an underlying OSB compliant API -func (b *BusinessLogic) Update(request *osbc.UpdateInstanceRequest, c *broker.RequestContext) (*broker.UpdateInstanceResponse, error) { - client, err := osbClient(c.Request, *b.osbClientConfig, b.createFunc) - if err != nil { - return nil, err - } - response, err := client.UpdateInstance(request) - if err != nil { - return nil, err - } - - return &broker.UpdateInstanceResponse{ - UpdateInstanceResponse: *response, - }, nil -} - -// ValidateBrokerAPIVersion implements pmorie/osb-broker-lib/pkg/broker/Interface.ValidateBrokerAPIVersion by -// allowing all versions of the API -func (b *BusinessLogic) ValidateBrokerAPIVersion(version string) error { - return nil -} - -func osbClient(request *http.Request, config osbc.ClientConfiguration, createFunc osbc.CreateFunc) (osbc.Client, error) { - vars := mux.Vars(request) - brokerID, ok := vars["brokerID"] - if !ok { - errMsg := fmt.Sprintf("brokerId path parameter missing from %s", request.Host) - logrus.WithError(errors.New(errMsg)).Error("Error building OSB client for proxy business logic") - - return nil, osbc.HTTPStatusCodeError{ - StatusCode: http.StatusBadRequest, - Description: &errMsg, - } - } - config.URL = config.URL + "/" + brokerID - config.Name = config.Name + "-" + brokerID - logrus.Debug("Building OSB client for broker with name: ", config.Name, " accesible at: ", config.URL) - return createFunc(&config) -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/config.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/config.go deleted file mode 100644 index 737938c5..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/config.go +++ /dev/null @@ -1,71 +0,0 @@ -// Package osb contains logic for building the Service Broker Proxy OSB API -package osb - -import ( - "github.com/Peripli/service-broker-proxy/pkg/sm" - "github.com/pkg/errors" - osbc "github.com/pmorie/go-open-service-broker-client/v2" -) - -const name = "sbproxy" - -// ClientConfig type holds config info for building an OSB client -type ClientConfig struct { - *osbc.ClientConfiguration - - CreateFunc func(config *osbc.ClientConfiguration) (osbc.Client, error) -} - -// DefaultConfig returns default ClientConfig -func DefaultConfig() *ClientConfig { - return &ClientConfig{ - ClientConfiguration: osbc.DefaultClientConfiguration(), - CreateFunc: osbc.NewClient, - } -} - -// NewConfig creates ClientConfig from the provided settings -func NewConfig(settings *sm.Config) (*ClientConfig, error) { - clientConfig := DefaultConfig() - clientConfig.Name = name - - if len(settings.Host) != 0 { - clientConfig.URL = settings.Host + settings.OsbAPI - } - - if settings.RequestTimeout != 0 { - clientConfig.TimeoutSeconds = (int)(settings.RequestTimeout.Seconds()) - } - - if len(settings.User) != 0 && len(settings.Password) != 0 { - clientConfig.AuthConfig = &osbc.AuthConfig{ - BasicAuthConfig: &osbc.BasicAuthConfig{ - Username: settings.User, - Password: settings.Password, - }} - } - - clientConfig.Insecure = settings.SkipSslValidation - - return clientConfig, nil -} - -// Validate validates the configuration and returns appropriate errors in case it is invalid -func (c *ClientConfig) Validate() error { - if c.CreateFunc == nil { - return errors.New("OSB client configuration CreateFunc missing") - } - if c.ClientConfiguration == nil { - return errors.New("OSB client configuration missing") - } - if len(c.URL) == 0 { - return errors.New("OSB client configuration URL missing") - } - if c.AuthConfig == nil { - return errors.New("OSB client configuration AuthConfig missing") - } - if c.TimeoutSeconds == 0 { - return errors.New("OSB client configuration RequestTimeout missing") - } - return nil -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/transport.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/transport.go new file mode 100644 index 00000000..f8f98a3b --- /dev/null +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/osb/transport.go @@ -0,0 +1,36 @@ +package osb + +import ( + "net/http" + "github.com/Peripli/service-manager/api/osb" + "github.com/Peripli/service-manager/pkg/types" +) + +// BrokerTransport implements osb.BrokerRoundTripper +type BrokerTransport struct { + Username string + Password string + URL string + + Tr http.RoundTripper +} + +var _ osb.BrokerRoundTripper = &BrokerTransport{} + +// Broker implements osb.BrokerRoundTripper and returns the coordinates of the broker with the specified id +func (b *BrokerTransport) Broker(brokerID string) (*types.Broker, error) { + return &types.Broker{ + BrokerURL: b.URL + "/" + brokerID, + Credentials: &types.Credentials{ + Basic: &types.Basic{ + Username: b.Username, + Password: b.Password, + }, + }, + }, nil +} + +// RoundTrip implements http.RoundTripper by delegating to the provided RoundTripper +func (b *BrokerTransport) RoundTrip(request *http.Request) (*http.Response, error) { + return b.Tr.RoundTrip(request) +} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/reconcile_brokers.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/reconcile_brokers.go index 712f212f..d179e5e1 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/reconcile_brokers.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/reconcile_brokers.go @@ -72,7 +72,6 @@ func (r ReconcileBrokersTask) run() { // control logic - make sure current state matches desired state r.reconcileBrokers(brokersFromPlatform, brokersFromSM) - } // reconcileBrokers attempts to reconcile the current brokers state in the platform (existingBrokers) @@ -93,7 +92,6 @@ func (r ReconcileBrokersTask) reconcileBrokers(existingBrokers []serviceBrokerRe for _, existingBroker := range existingMap { r.deleteBrokerRegistration(&existingBroker.ServiceBroker) } - } func (r ReconcileBrokersTask) getBrokersFromPlatform() ([]serviceBrokerReg, error) { @@ -180,7 +178,6 @@ func (r ReconcileBrokersTask) deleteBrokerRegistration(broker *platform.ServiceB logrus.WithFields(logBroker(broker)).WithError(err).Error("Error during broker deletion") } else { logrus.WithFields(logBroker(broker)).Infof("ReconcileBrokersTask task SUCCESSFULLY deleted proxy broker from platform with name [%s]", deleteRequest.Name) - } } diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/sbproxy.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/sbproxy.go index 3bf528c1..5dc9fa0c 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/sbproxy.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/sbproxy/sbproxy.go @@ -3,38 +3,62 @@ package sbproxy import ( "sync" + "fmt" + + "context" + "time" + "github.com/Peripli/service-broker-proxy/pkg/config" + "github.com/Peripli/service-broker-proxy/pkg/logging" + "github.com/Peripli/service-broker-proxy/pkg/osb" "github.com/Peripli/service-broker-proxy/pkg/platform" - "github.com/Peripli/service-broker-proxy/pkg/server" "github.com/Peripli/service-broker-proxy/pkg/sm" + "github.com/Peripli/service-manager/api/filters" + smOsb "github.com/Peripli/service-manager/api/osb" "github.com/Peripli/service-manager/pkg/env" - "github.com/pkg/errors" + "github.com/Peripli/service-manager/pkg/server" + "github.com/Peripli/service-manager/pkg/web" "github.com/robfig/cron" "github.com/sirupsen/logrus" "github.com/spf13/pflag" - "fmt" ) const ( + // BrokerPathParam for the broker id + BrokerPathParam = "brokerID" + // APIPrefix for the Proxy OSB API APIPrefix = "/v1/osb" + + // Path for the Proxy OSB API + Path = APIPrefix + "/{" + BrokerPathParam + "}" ) -// SBProxy service broker proxy struct -type SBProxy struct { - Server *server.Server +// SMProxyBuilder type is an extension point that allows adding additional filters, plugins and +// controllers before running SMProxy. +type SMProxyBuilder struct { + *web.API + *cron.Cron - cronScheduler *cron.Cron - group *sync.WaitGroup + ctx context.Context + cfg *config.Settings + group *sync.WaitGroup +} + +// SMProxy struct +type SMProxy struct { + *server.Server + + scheduler *cron.Cron + ctx context.Context + group *sync.WaitGroup } // DefaultEnv creates a default environment that can be used to boot up a Service Manager func DefaultEnv(additionalPFlags ...func(set *pflag.FlagSet)) env.Environment { set := env.EmptyFlagSet() - env.CreatePFlagsForConfigFile(set) config.AddPFlags(set) - for _, addFlags := range additionalPFlags { addFlags(set) } @@ -46,50 +70,82 @@ func DefaultEnv(additionalPFlags ...func(set *pflag.FlagSet)) env.Environment { } // New creates service broker proxy that is configured from the provided environment and platform client. -func New(env env.Environment, client platform.Client) (*SBProxy, error) { +func New(ctx context.Context, env env.Environment, client platform.Client) *SMProxyBuilder { cronScheduler := cron.New() var group sync.WaitGroup cfg, err := config.New(env) if err != nil { - return nil, err + panic(err) } - proxyServer, err := server.New(cfg.Server, cfg.Osb) - if err != nil { - return nil, err + if err := cfg.Validate(); err != nil { + panic(err) + } + + logging.Setup(cfg.Log) + + api := &web.API{ + Controllers: []web.Controller{ + smOsb.NewController(&osb.BrokerTransport{ + Tr: sm.SkipSSLTransport{ + SkipSslValidation: cfg.Sm.SkipSSLValidation, + }, + URL: cfg.Sm.URL + cfg.Sm.OSBAPIPath, + Username: cfg.Sm.User, + Password: cfg.Sm.Password, + }), + }, } - sbProxy := &SBProxy{ - Server: proxyServer, - cronScheduler: cronScheduler, - group: &group, + sbProxy := &SMProxyBuilder{ + API: api, + Cron: cronScheduler, + ctx: ctx, + cfg: cfg, + group: &group, } - regJob, err := defaultRegJob(&group, client, cfg.Sm, cfg.Server.Host) + regJob, err := defaultRegJob(&group, client, cfg.Sm, cfg.SelfURL) if err != nil { - return nil, err + panic(err) } - resyncSchedule := "@every " + cfg.Server.ResyncPeriod.String() + resyncSchedule := "@every " + cfg.Sm.ResyncPeriod.String() logrus.Info("Brokers and Access resync schedule: ", resyncSchedule) if err := cronScheduler.AddJob(resyncSchedule, regJob); err != nil { - return nil, errors.Wrap(err, "error adding registration job") + panic(err) } - return sbProxy, nil + return sbProxy +} + +// Build builds the Service Manager +func (smb *SMProxyBuilder) Build() *SMProxy { + srv := server.New(smb.cfg.Server, smb.API) + srv.Use(filters.NewRecoveryMiddleware()) + + return &SMProxy{ + Server: srv, + scheduler: smb.Cron, + ctx: smb.ctx, + group: smb.group, + } } // Run starts the proxy -func (p *SBProxy) Run() { - p.cronScheduler.Start() - defer p.cronScheduler.Stop() +func (p *SMProxy) Run() { + p.scheduler.Start() + defer p.scheduler.Stop() + defer waitWithTimeout(p.group, p.Server.Config.ShutdownTimeout) + + logrus.Info("Running SBProxy...") - p.Server.Run(p.group) + p.Server.Run(p.ctx) } -func defaultRegJob(group *sync.WaitGroup, platformClient platform.Client, smConfig *sm.Config, proxyHost string) (cron.Job, error) { +func defaultRegJob(group *sync.WaitGroup, platformClient platform.Client, smConfig *sm.Settings, proxyHost string) (cron.Job, error) { smClient, err := smConfig.CreateFunc(smConfig) if err != nil { return nil, err @@ -98,3 +154,20 @@ func defaultRegJob(group *sync.WaitGroup, platformClient platform.Client, smConf return regTask, nil } + +// waitWithTimeout waits for a WaitGroup to finish for a certain duration and times out afterwards +// WaitGroup parameter should be pointer or else the copy won't get notified about .Done() calls +func waitWithTimeout(group *sync.WaitGroup, timeout time.Duration) { + c := make(chan struct{}) + go func() { + defer close(c) + group.Wait() + }() + select { + case <-c: + logrus.Debug(fmt.Sprintf("Timeout WaitGroup %+v finished successfully", group)) + case <-time.After(timeout): + logrus.Fatal("Shutdown took more than ", timeout) + close(c) + } +} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/server/config.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/server/config.go deleted file mode 100644 index f23c2902..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/server/config.go +++ /dev/null @@ -1,76 +0,0 @@ -package server - -import ( - "time" - - "github.com/Peripli/service-manager/pkg/env" - "github.com/pkg/errors" -) - -// DefaultConfig builds the default Config -func DefaultConfig() *Config { - return &Config{ - Port: 0, - LogLevel: "debug", - LogFormat: "text", - Timeout: 5 * time.Second, - ResyncPeriod: 10 * time.Minute, - TLSKey: "", - TLSCert: "", - Host: "", - } -} - -// NewConfig builds an Config from the given Environment -func NewConfig(env env.Environment) (*Config, error) { - config := struct { - Server *Config - }{Server: DefaultConfig()} - - if err := env.Unmarshal(&config); err != nil { - return nil, errors.Wrap(err, "error unmarshaling app configuration") - } - return config.Server, nil -} - -// Config type holds application config properties -type Config struct { - Port int - LogLevel string - LogFormat string - Timeout time.Duration - ResyncPeriod time.Duration - TLSKey string - TLSCert string - Host string -} - -// Validate validates the configuration and returns appropriate errors in case it is invalid -func (c *Config) Validate() error { - if c.Port == 0 { - return errors.New("application configuration Port missing") - } - if len(c.LogLevel) == 0 { - return errors.New("application configuration LogLevel missing") - } - if len(c.LogFormat) == 0 { - return errors.New("application configuration LogFormat missing") - } - if c.Timeout == 0 { - return errors.New("application configuration RequestTimeout missing") - } - if c.ResyncPeriod == 0 { - return errors.New("application configuration RequestTimeout missing") - } - if !tlsConfigOK(c.TLSCert, c.TLSKey) { - return errors.New("application configuration both TLSCert and TLSKey must be provided to use TLS") - } - if len(c.Host) == 0 { - return errors.New("application configuration Host missing") - } - return nil -} - -func tlsConfigOK(TLSCert, TLSKey string) bool { - return (TLSCert == "" && TLSKey == "") || (TLSCert != "" && TLSKey != "") -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/server/server.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/server/server.go deleted file mode 100644 index 178b3d53..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/server/server.go +++ /dev/null @@ -1,173 +0,0 @@ -package server - -import ( - "context" - "net/http" - "os" - "os/signal" - "strconv" - "sync" - "time" - - "github.com/Peripli/service-broker-proxy/pkg/logging" - "github.com/Peripli/service-broker-proxy/pkg/middleware" - "github.com/Peripli/service-broker-proxy/pkg/osb" - "github.com/gorilla/mux" - "github.com/pkg/errors" - "github.com/pmorie/osb-broker-lib/pkg/metrics" - "github.com/pmorie/osb-broker-lib/pkg/rest" - osbserver "github.com/pmorie/osb-broker-lib/pkg/server" - prom "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" -) - -const ( - // BrokerPathParam for the broker id - BrokerPathParam = "brokerID" - - // APIPrefix for the Proxy OSB API - APIPrefix = "/v1/osb" - - // Path for the Proxy OSB API - Path = APIPrefix + "/{" + BrokerPathParam + "}" -) - -// Server type is the starting point of the proxy application. It glues the proxy REST API and the timed -// jobs for broker registrations -type Server struct { - *osbserver.Server - - Config *Config -} - -// New builds a new Server from the provided configuration using the provided platform client. The -// platform client is used by the Server to call to the platform during broker creation and deletion. -func New(config *Config, osbConfig *osb.ClientConfig) (*Server, error) { - if err := config.Validate(); err != nil { - return nil, err - } - - if err := osbConfig.Validate(); err != nil { - return nil, err - } - - logging.Setup(config.LogLevel, config.LogFormat) - - server, err := osbServer(osbConfig) - if err != nil { - return nil, err - } - - server.Router.Use(middleware.LogRequest()) - - return &Server{ - Server: server, - Config: config, - }, nil -} - -// Use provides a way to plugin middleware in the Server -func (s Server) Use(middleware func(handler http.Handler) http.Handler) { - s.Server.Router.Use(middleware) -} - -// Run is the entrypoint of the Server. Run boots the application. -func (s Server) Run(group *sync.WaitGroup) { - var err error - ctx, cancel := context.WithCancel(context.Background()) - defer waitWithTimeout(group, s.Config.Timeout) - defer cancel() - - handleInterrupts(ctx, cancel) - - addr := ":" + strconv.Itoa(s.Config.Port) - - logrus.Info("Running Server...") - if s.Config.TLSKey != "" && s.Config.TLSCert != "" { - err = s.Server.RunTLS(ctx, addr, s.Config.TLSCert, s.Config.TLSKey) - } else { - err = s.Server.Run(ctx, addr) - } - - if err != nil && err != context.Canceled && err != context.DeadlineExceeded { - logrus.WithError(errors.WithStack(err)).Errorln("Error occurred while sbproxy was running") - } -} - -// handleInterrupts hannles OS interrupt signals by canceling the context -func handleInterrupts(ctx context.Context, cancel context.CancelFunc) { - term := make(chan os.Signal) - signal.Notify(term, os.Interrupt) - go func() { - select { - case <-term: - logrus.Error("Received OS interrupt, exiting gracefully...") - cancel() - case <-ctx.Done(): - return - } - }() -} - -// waitWithTimeout waits for a WaitGroup to finish for a certain duration and times out afterwards -// WaitGroup parameter should be pointer or else the copy won't get notified about .Done() calls -func waitWithTimeout(group *sync.WaitGroup, timeout time.Duration) { - c := make(chan struct{}) - go func() { - defer close(c) - group.Wait() - }() - select { - case <-c: - logrus.Debug("Timeout WaitGroup ", group, " finished successfully") - case <-time.After(timeout): - logrus.Fatal("Shutdown took more than ", timeout) - close(c) - } -} - -func osbServer(config *osb.ClientConfig) (*osbserver.Server, error) { - businessLogic, err := osb.NewBusinessLogic(config) - if err != nil { - return nil, err - } - - reg := prom.NewRegistry() - osbMetrics := metrics.New() - reg.MustRegister(osbMetrics) - - api, err := rest.NewAPISurface(businessLogic, osbMetrics) - if err != nil { - return nil, errors.Wrap(err, "error creating OSB API surface") - } - - osbServer := osbserver.New(api, reg) - router := mux.NewRouter() - - err = registerRoutes(Path, osbServer.Router, router) - if err != nil { - return nil, err - } - - osbServer.Router = router - return osbServer, nil -} - -func registerRoutes(prefix string, fromRouter *mux.Router, toRouter *mux.Router) error { - subRouter := toRouter.PathPrefix(prefix).Subrouter() - return fromRouter.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { - - path, err := route.GetPathTemplate() - if err != nil { - return errors.Wrap(err, "error getting path template") - } - - methods, err := route.GetMethods() - if err != nil { - return errors.Wrap(err, "error getting route methods") - } - logrus.Info("Registering route with methods: ", methods, " and path: ", prefix+path) - subRouter.Handle(path, route.GetHandler()).Methods(methods...) - return nil - }) -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/basic_auth_transport.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/basic_auth_transport.go deleted file mode 100644 index 3b2d33ae..00000000 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/basic_auth_transport.go +++ /dev/null @@ -1,24 +0,0 @@ -package sm - -import ( - "encoding/base64" - "fmt" - "net/http" -) - -// BasicAuthTransport implements http.RoundTripper interface and intercepts that request that is being sent, -// adding basic authorization and delegates back to the original transport. -type BasicAuthTransport struct { - username string - password string - rt http.RoundTripper -} - -// RoundTrip implements http.RoundTrip and adds basic authorization header before delegating to the -// underlying RoundTripper -func (b BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { - req.Header.Set("Authorization", fmt.Sprintf("Basic %s", - base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", - b.username, b.password))))) - return b.rt.RoundTrip(req) -} diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/client.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/client.go index b8b384f1..30bc4083 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/client.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/client.go @@ -1,7 +1,6 @@ package sm import ( - "crypto/tls" "fmt" "net/http" @@ -23,14 +22,14 @@ type Client interface { } type serviceManagerClient struct { - Config *Config + Config *Settings httpClient *http.Client } var _ Client = &serviceManagerClient{} // NewClient builds a new Service Manager Client from the provided configuration -func NewClient(config *Config) (Client, error) { +func NewClient(config *Settings) (Client, error) { if err := config.Validate(); err != nil { return nil, err } @@ -39,22 +38,12 @@ func NewClient(config *Config) (Client, error) { Timeout: time.Duration(config.RequestTimeout) * time.Second, } - defaultTransport := http.DefaultTransport.(*http.Transport) - t := &http.Transport{ - Proxy: defaultTransport.Proxy, - TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, - ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, - } - t.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: config.SkipSslValidation, - } - - if config.User != "" && config.Password != "" { - httpClient.Transport = BasicAuthTransport{ - username: config.User, - password: config.Password, - rt: t, - } + httpClient.Transport = BasicAuthTransport{ + Username: config.User, + Password: config.Password, + Rt: SkipSSLTransport{ + SkipSslValidation: config.SkipSSLValidation, + }, } client := &serviceManagerClient{ @@ -68,8 +57,8 @@ func NewClient(config *Config) (Client, error) { // GetBrokers calls the Service Manager in order to obtain all brokers t hat need to be registered // in the service broker proxy func (c *serviceManagerClient) GetBrokers() ([]platform.ServiceBroker, error) { - logrus.Debugf("Getting brokers for proxy from Service Manager at %s", c.Config.Host) - URL := fmt.Sprintf(APIInternalBrokers, c.Config.Host) + logrus.Debugf("Getting brokers for proxy from Service Manager at %s", c.Config.URL) + URL := fmt.Sprintf(APIInternalBrokers, c.Config.URL) response, err := util.SendRequest(c.httpClient.Do, http.MethodGet, URL, map[string]string{"catalog": "true"}, nil) if err != nil { return nil, errors.Wrap(err, "error getting brokers from Service Manager") diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/config.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/config.go index 279e9dac..dc6fe021 100644 --- a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/config.go +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/config.go @@ -7,23 +7,23 @@ import ( "github.com/pkg/errors" ) -// DefaultConfig builds a default Service Manager Config -func DefaultConfig() *Config { - return &Config{ +// DefaultSettings builds a default Service Manager Settings +func DefaultSettings() *Settings { + return &Settings{ User: "", Password: "", - Host: "", + URL: "", RequestTimeout: 5 * time.Second, CreateFunc: NewClient, - SkipSslValidation: false, + SkipSSLValidation: false, } } -// NewConfig builds a Service Manager Config from the provided Environment -func NewConfig(env env.Environment) (*Config, error) { +// NewSettings builds a Service Manager Settings from the provided Environment +func NewSettings(env env.Environment) (*Settings, error) { config := struct { - Sm *Config - }{DefaultConfig()} + Sm *Settings + }{DefaultSettings()} if err := env.Unmarshal(&config); err != nil { return nil, errors.Wrap(err, "error unmarshaling SM configuration") @@ -32,35 +32,39 @@ func NewConfig(env env.Environment) (*Config, error) { return config.Sm, nil } -// Config type holds SM Client config properties -type Config struct { +// Settings type holds SM Client config properties +type Settings struct { User string Password string - Host string - OsbAPI string - RequestTimeout time.Duration - SkipSslValidation bool + URL string + OSBAPIPath string `mapstructure:"osb_api_path"` + RequestTimeout time.Duration `mapstructure:"request_timeout"` + ResyncPeriod time.Duration `mapstructure:"resync_period"` + SkipSSLValidation bool `mapstructure:"skip_ssl_validation"` - CreateFunc func(config *Config) (Client, error) + CreateFunc func(config *Settings) (Client, error) } // Validate validates the configuration and returns appropriate errors in case it is invalid -func (c *Config) Validate() error { +func (c *Settings) Validate() error { if len(c.User) == 0 { return errors.New("SM configuration User missing") } if len(c.Password) == 0 { return errors.New("SM configuration Password missing") } - if len(c.Host) == 0 { - return errors.New("SM configuration Host missing") + if len(c.URL) == 0 { + return errors.New("SM configuration URL missing") } - if len(c.OsbAPI) == 0 { - return errors.New("SM configuration OSB API missing") + if len(c.OSBAPIPath) == 0 { + return errors.New("SM configuration OSB API Path missing") } if c.RequestTimeout == 0 { return errors.New("SM configuration RequestTimeout missing") } + if c.ResyncPeriod == 0 { + return errors.New("SM configuration RequestTimeout missing") + } if c.CreateFunc == nil { return errors.New("SM configuration CreateFunc missing") } diff --git a/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/transport.go b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/transport.go new file mode 100644 index 00000000..a263d656 --- /dev/null +++ b/vendor/github.com/Peripli/service-broker-proxy/pkg/sm/transport.go @@ -0,0 +1,49 @@ +package sm + +import ( + "net/http" + "crypto/tls" +) + +// BasicAuthTransport implements http.RoundTripper interface and intercepts that request that is being sent, +// adding basic authorization and delegates back to the original transport. +type BasicAuthTransport struct { + Username string + Password string + + Rt http.RoundTripper +} + +var _ http.RoundTripper = &BasicAuthTransport{} + +// RoundTrip implements http.RoundTrip and adds basic authorization header before delegating to the +// underlying RoundTripper +func (b BasicAuthTransport) RoundTrip(request *http.Request) (*http.Response, error) { + if b.Username != "" && b.Password != "" { + request.SetBasicAuth(b.Username, b.Password) + } + + return b.Rt.RoundTrip(request) +} + +// SkipSSLTransport implements http.RoundTripper and sets the SSL Validation to match the provided property +type SkipSSLTransport struct { + SkipSslValidation bool +} + +var _ http.RoundTripper = &SkipSSLTransport{} + +// RoundTrip implements http.RoundTrip and adds skip SSL validation logic +func (b SkipSSLTransport) RoundTrip(request *http.Request) (*http.Response, error) { + defaultTransport := http.DefaultTransport.(*http.Transport) + t := &http.Transport{ + Proxy: defaultTransport.Proxy, + TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, + ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, + } + + t.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: b.SkipSslValidation, + } + return t.RoundTrip(request) +} \ No newline at end of file diff --git a/vendor/github.com/Peripli/service-manager/.gitignore b/vendor/github.com/Peripli/service-manager/.gitignore index 6a45c7ea..88044657 100644 --- a/vendor/github.com/Peripli/service-manager/.gitignore +++ b/vendor/github.com/Peripli/service-manager/.gitignore @@ -23,3 +23,5 @@ debug # IDE specific .vscode/ /.idea + +local_dev \ No newline at end of file diff --git a/vendor/github.com/Peripli/service-manager/.gometalinter.json b/vendor/github.com/Peripli/service-manager/.gometalinter.json index fa900fe4..ea7a745c 100644 --- a/vendor/github.com/Peripli/service-manager/.gometalinter.json +++ b/vendor/github.com/Peripli/service-manager/.gometalinter.json @@ -5,5 +5,6 @@ "Deadline": "120s", "Aggregate": true, "Sort": ["severity", "path", "line", "message"], - "Checkstyle": false + "Checkstyle": false, + "Cyclo": 12 } \ No newline at end of file diff --git a/vendor/github.com/Peripli/service-manager/Dockerfile b/vendor/github.com/Peripli/service-manager/Dockerfile index a91db013..72db16ed 100644 --- a/vendor/github.com/Peripli/service-manager/Dockerfile +++ b/vendor/github.com/Peripli/service-manager/Dockerfile @@ -25,6 +25,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o /mai ######################################################## FROM alpine:3.7 AS package_step +RUN apk add --no-cache ca-certificates + WORKDIR /app # Copy the executable file diff --git a/vendor/github.com/Peripli/service-manager/Gopkg.lock b/vendor/github.com/Peripli/service-manager/Gopkg.lock index e9842384..c5722678 100644 --- a/vendor/github.com/Peripli/service-manager/Gopkg.lock +++ b/vendor/github.com/Peripli/service-manager/Gopkg.lock @@ -2,62 +2,83 @@ [[projects]] + digest = "1:03d575fe8ee6ad5336b6c7c89230b16c79d3ec44abdb308e2e6d8a8bbe14069c" + name = "github.com/DATA-DOG/go-sqlmock" + packages = ["."] + pruneopts = "UT" + revision = "852fc940e4b9b895dc144b88ee8f6e39228127b0" + +[[projects]] + digest = "1:2aff5edb9bccd2974090fddb17ca7ab05a3f5c983db567c30c7f0b53404f5783" name = "github.com/ajg/form" packages = ["."] + pruneopts = "UT" revision = "cc2954064ec9ea8d93917f0f87456e11d7b881ad" version = "v1.5" [[projects]] + digest = "1:d5fa6328bd281ac91e7b5d3f45b49f8ac36c30b6a530f633d91c6eaef50cd137" name = "github.com/cloudfoundry-community/go-cfenv" packages = ["."] + pruneopts = "UT" revision = "e84b5c116637ef174eb8c7d68a28bc7269b3b9cb" [[projects]] + digest = "1:f6e5e1bc64c2908167e6aa9a1fe0c084d515132a1c63ad5b6c84036aa06dc0c1" name = "github.com/coreos/go-oidc" packages = ["."] + pruneopts = "UT" revision = "1180514eaf4d9f38d0d19eef639a1d695e066e72" [[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" [[projects]] + digest = "1:ca82a3b99694824c627573c2a76d0e49719b4a9c02d1d85a2ac91f1c1f52ab9b" name = "github.com/fatih/structs" packages = ["."] + pruneopts = "UT" revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" version = "v1.0" [[projects]] + digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" name = "github.com/fsnotify/fsnotify" packages = ["."] + pruneopts = "UT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] + digest = "1:2d2a4b9fce4d0a808476e6388fc8ab4d43f1fe5da52fb3e9a088486cc745ed89" name = "github.com/gavv/httpexpect" packages = ["."] + pruneopts = "UT" revision = "c44a6d7bb636b17e880a53998a7f7061a56ffacb" -[[projects]] - name = "github.com/DATA-DOG/go-sqlmock" - packages = ["."] - revision = "852fc940e4b9b895dc144b88ee8f6e39228127b0" - [[projects]] branch = "master" + digest = "1:fbc02c2b3b78e6bc30228f3bae582f1fcea74a050cbdbf42f24eff12bef8eab4" name = "github.com/gavv/monotime" packages = ["."] + pruneopts = "UT" revision = "6f8212e8d10df7383609d3c377ca08884d8f3ec0" [[projects]] + digest = "1:d57cb1af013b165b6907abb4f844f9e751e37aa55f3c0156c60dd5028cf0a7c1" name = "github.com/gbrlsnchs/jwt" packages = ["."] + pruneopts = "UT" revision = "fd3b16eda068e8d51d245b07019854d63dc4b591" version = "v0.5.0" [[projects]] + digest = "1:9ae31ce33b4bab257668963e844d98765b44160be4ee98cafc44637a213e530d" name = "github.com/gobwas/glob" packages = [ ".", @@ -67,61 +88,85 @@ "syntax/ast", "syntax/lexer", "util/runes", - "util/strings" + "util/strings", ] + pruneopts = "UT" revision = "5ccd90ef52e1e632236f7326478d4faa74f99438" version = "v0.2.3" [[projects]] + digest = "1:26f2ad8a198a88c3605401186a6be538326e7fbf1f14cb3ef4e0027c4f755f2a" + name = "github.com/gofrs/uuid" + packages = ["."] + pruneopts = "UT" + revision = "d41eeda0759468834c84365a32d1b1ec4264c75f" + version = "v3.1.0" + +[[projects]] + digest = "1:2c42ca83bbb9bea0307416eedd38350ace4a67705fcb7a17eab352fd1529ee03" name = "github.com/golang-migrate/migrate" packages = [ ".", "database", "database/postgres", "source", - "source/file" + "source/file", ] + pruneopts = "UT" revision = "e968e8a5f0fd43301a2e0ef025ce6db56eedb205" version = "v3.4.0" [[projects]] branch = "master" + digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467" name = "github.com/golang/glog" packages = ["."] + pruneopts = "UT" revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" [[projects]] + digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d" name = "github.com/golang/protobuf" packages = ["proto"] - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" + pruneopts = "UT" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" [[projects]] branch = "master" + digest = "1:a63cff6b5d8b95638bfe300385d93b2a6d9d687734b863da8e09dc834510a690" name = "github.com/google/go-querystring" packages = ["query"] + pruneopts = "UT" revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a" [[projects]] + digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" name = "github.com/gorilla/context" packages = ["."] + pruneopts = "UT" revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" [[projects]] + digest = "1:185a43b59a1f4e7ad4e7ccafb8a1538193d897a2a75be16dda093ec42ad231cf" name = "github.com/gorilla/handlers" packages = ["."] + pruneopts = "UT" revision = "90663712d74cb411cbef281bc1e08c19d1a76145" version = "v1.3.0" [[projects]] + digest = "1:88aa9e326e2bd6045a46e00a922954b3e1a9ac5787109f49ac85366df370e1e5" name = "github.com/gorilla/mux" packages = ["."] + pruneopts = "UT" revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" version = "v1.6.1" [[projects]] branch = "master" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -133,82 +178,102 @@ "hcl/token", "json/parser", "json/scanner", - "json/token" + "json/token", ] + pruneopts = "UT" revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" [[projects]] + digest = "1:a1038ef593beb4771c8f0f9c26e8b00410acd800af5c6864651d9bf160ea1813" name = "github.com/hpcloud/tail" packages = [ ".", "ratelimiter", "util", "watch", - "winfile" + "winfile", ] + pruneopts = "UT" revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5" version = "v1.0.0" [[projects]] + digest = "1:a3ce4de79566c21e93cb6934797fdaa587ad3fc6a964708ab77babe54ea67188" name = "github.com/imkira/go-interpol" packages = ["."] + pruneopts = "UT" revision = "5accad8134979a6ac504d456a6c7f1c53da237ca" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:d75dfe3beea955b6cf5c3c75fd3ddebe48835951d205f359e69f68d7ff924ef1" name = "github.com/jmoiron/sqlx" packages = [ ".", "reflectx", - "types" + "types", ] + pruneopts = "UT" revision = "0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849" [[projects]] + digest = "1:cdbed6a7b574b13bbabcd8c36c5be56d6444789bab21fcd37d39655eab0b2141" name = "github.com/klauspost/compress" packages = [ "flate", "gzip", - "zlib" + "zlib", ] + pruneopts = "UT" revision = "b939724e787a27c0005cabe3f78e7ed7987ac74f" version = "v1.4.0" [[projects]] + digest = "1:4ea0668d490ca32a38366453a486e2e8c60fbdaf1f2607c96b4a093d8a5c8de7" name = "github.com/klauspost/cpuid" packages = ["."] + pruneopts = "UT" revision = "ae7887de9fa5d2db4eaa8174a7eff2c1ac00f2da" version = "v1.1" [[projects]] branch = "master" + digest = "1:8ef506fc2bb9ced9b151dafa592d4046063d744c646c1bbe801982ce87e4bc24" name = "github.com/lib/pq" packages = [ ".", - "oid" + "oid", ] - revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" + pruneopts = "UT" + revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79" [[projects]] + digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7" name = "github.com/magiconair/properties" packages = ["."] + pruneopts = "UT" revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" [[projects]] branch = "master" + digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" name = "github.com/mitchellh/mapstructure" packages = ["."] + pruneopts = "UT" revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] branch = "master" + digest = "1:7aefb397a53fc437c90f0fdb3e1419c751c5a3a165ced52325d5d797edf1aca6" name = "github.com/moul/http2curl" packages = ["."] + pruneopts = "UT" revision = "9ac6cf4d929b2fa8fd2d2e6dec5bb0feb4f4911d" [[projects]] + digest = "1:42e29deef12327a69123b9cb2cb45fee4af5c12c2a23c6e477338279a052703f" name = "github.com/onsi/ginkgo" packages = [ ".", @@ -228,12 +293,14 @@ "reporters/stenographer", "reporters/stenographer/support/go-colorable", "reporters/stenographer/support/go-isatty", - "types" + "types", ] + pruneopts = "UT" revision = "3774a09d95489ccaa16032e0770d08ea77ba6184" version = "v1.6.0" [[projects]] + digest = "1:e42321c3ec0ff36c0644da60c2c1469886b214134286f4610199b704619e11a3" name = "github.com/onsi/gomega" packages = [ ".", @@ -248,181 +315,227 @@ "matchers/support/goraph/edge", "matchers/support/goraph/node", "matchers/support/goraph/util", - "types" + "types", ] + pruneopts = "UT" revision = "003f63b7f4cff3fc95357005358af2de0f5fe152" version = "v1.3.0" [[projects]] + digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" name = "github.com/pelletier/go-toml" packages = ["."] + pruneopts = "UT" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" version = "v1.2.0" [[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "UT" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + digest = "1:8658f775ba5edb37ede96d8ec9eaecdfe06bc4aef1776152070185e6513dc0cc" name = "github.com/pmorie/go-open-service-broker-client" packages = ["v2"] + pruneopts = "UT" revision = "dca737037ce636eb282e84e3a1c7479c9692e884" version = "0.0.10" [[projects]] branch = "master" + digest = "1:bd9efe4e0b0f768302a1e2f0c22458149278de533e521206e5ddc71848c269a0" name = "github.com/pquerna/cachecontrol" packages = [ ".", - "cacheobject" + "cacheobject", ] + pruneopts = "UT" revision = "1555304b9b35fdd2b425bccf1a5613677705e7d0" [[projects]] - name = "github.com/satori/go.uuid" - packages = ["."] - revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" - -[[projects]] + digest = "1:d917313f309bda80d27274d53985bc65651f81a5b66b820749ac7f8ef061fd04" name = "github.com/sergi/go-diff" packages = ["diffmatchpatch"] + pruneopts = "UT" revision = "1744e2970ca51c86172c8190fadad617561ed6e7" version = "v1.0.0" [[projects]] + digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc" name = "github.com/sirupsen/logrus" packages = ["."] + pruneopts = "UT" revision = "3e01752db0189b9157070a0e1668a620f9a85da2" version = "v1.0.6" [[projects]] + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", - "mem" + "mem", ] + pruneopts = "UT" revision = "787d034dfe70e44075ccc060d346146ef53270ad" version = "v1.1.1" [[projects]] + digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" name = "github.com/spf13/cast" packages = ["."] + pruneopts = "UT" revision = "8965335b8c7107321228e3e3702cab9832751bac" version = "v1.2.0" [[projects]] branch = "master" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + pruneopts = "UT" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] + digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "UT" revision = "583c0c0531f06d5278b7d917446061adc344b5cd" version = "v1.0.1" [[projects]] + digest = "1:59e7dceb53b4a1e57eb1eb0bf9951ff0c25912df7660004a789b62b4e8cdca3b" name = "github.com/spf13/viper" packages = ["."] + pruneopts = "UT" revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736" version = "v1.0.2" [[projects]] + digest = "1:c40d65817cdd41fac9aa7af8bed56927bb2d6d47e4fea566a74880f5c2b1c41e" name = "github.com/stretchr/testify" packages = [ "assert", - "require" + "require", ] + pruneopts = "UT" revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" version = "v1.2.2" [[projects]] + digest = "1:2cab41f59638fdb77dda96ab4f9b5860ef30f48967557254eba127e43c756f2e" name = "github.com/tidwall/gjson" packages = ["."] - revision = "f123b340873a0084cb27267eddd8ff615115fbff" - version = "v1.1.2" + pruneopts = "UT" + revision = "1e3f6aeaa5bad08d777ea7807b279a07885dd8b2" + version = "v1.1.3" [[projects]] branch = "master" + digest = "1:d3f968e2a2c9f8506ed44b01b605ade0176ba6cf73ff679073e77cfdef2c0d55" name = "github.com/tidwall/match" packages = ["."] + pruneopts = "UT" revision = "1731857f09b1f38450e2c12409748407822dc6be" [[projects]] + digest = "1:0c1bd4e9b2d596d0d6e676f2764a40f3f39a12d85d65308ffadcd68fde3af5e4" name = "github.com/tidwall/sjson" packages = ["."] + pruneopts = "UT" revision = "6a22caf2fd45d5e2119bfc3717e984f15a7eb7ee" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:c468422f334a6b46a19448ad59aaffdfc0a36b08fdcc1c749a0b29b6453d7e59" name = "github.com/valyala/bytebufferpool" packages = ["."] + pruneopts = "UT" revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7" [[projects]] + digest = "1:15ad8a80098fcc7a194b9db6b26d74072a852e4faa957848c8118193d3c69230" name = "github.com/valyala/fasthttp" packages = [ ".", "fasthttputil", - "stackless" + "stackless", ] + pruneopts = "UT" revision = "e5f51c11919d4f66400334047b897ef0a94c6f3c" [[projects]] branch = "master" + digest = "1:f4e5276a3b356f4692107047fd2890f2fe534f4feeb6b1fd2f6dfbd87f1ccf54" name = "github.com/xeipuuv/gojsonpointer" packages = ["."] + pruneopts = "UT" revision = "4e3ac2762d5f479393488629ee9370b50873b3a6" [[projects]] branch = "master" + digest = "1:dc6a6c28ca45d38cfce9f7cb61681ee38c5b99ec1425339bfc1e1a7ba769c807" name = "github.com/xeipuuv/gojsonreference" packages = ["."] + pruneopts = "UT" revision = "bd5ef7bd5415a7ac448318e64f11a24cd21e594b" [[projects]] branch = "master" + digest = "1:41bd4de0a27c0b7affef4083bc8f86501b4c7d891f95809a0fb758a23eb5e78f" name = "github.com/xeipuuv/gojsonschema" packages = ["."] - revision = "b84684d0e066369f2a7a8a525f3080909ed4ea6b" + pruneopts = "UT" + revision = "da425ebb7609ba06a0f395fc8a254d1c303364a0" [[projects]] branch = "master" + digest = "1:ac3d942a027d57fbfc5c13791cfaaa4b30729674fea88f2e03190b777c2b674e" name = "github.com/yalp/jsonpath" packages = ["."] - revision = "91a5860ab683d85ac38cbb7cb466a17a673b6ae5" + pruneopts = "UT" + revision = "5cc68e5049a040829faef3a44c00ec4332f6dec7" [[projects]] + digest = "1:52ccbcf36804b0beb5677a8994bd4ac740b71d1d6fe38c02b113dabdda51bf6d" name = "github.com/yudai/gojsondiff" packages = [ ".", - "formatter" + "formatter", ] + pruneopts = "UT" revision = "7b1b7adf999dab73a6eb02669c3d82dbb27a3dd6" version = "1.0.0" [[projects]] branch = "master" + digest = "1:0d4822d3440c9b5992704bb357061fff7ab60daa85d92dec02b81b78e4908db7" name = "github.com/yudai/golcs" packages = ["."] + pruneopts = "UT" revision = "ecda9a501e8220fae3b4b600c3db4b0ba22cfc68" [[projects]] branch = "master" + digest = "1:8e241498e35f550e5192ee6b1f6ff2c0a7ffe81feff9541d297facffe1383979" name = "golang.org/x/crypto" packages = [ "ed25519", "ed25519/internal/edwards25519", - "ssh/terminal" + "pbkdf2", + "ssh/terminal", ] - revision = "c126467f60eb25f8f27e5a981f32a87e3965053f" + pruneopts = "UT" + revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] branch = "master" + digest = "1:3245eeb32b9e23f7ee41ce584ce75dca6f322c2be9ab2d9afcf8ca4758af7eff" name = "golang.org/x/net" packages = [ "context", @@ -431,29 +544,35 @@ "html/atom", "html/charset", "idna", - "publicsuffix" + "publicsuffix", ] - revision = "c4299a1a0d8524c11563db160fbf9bddbceadb21" + pruneopts = "UT" + revision = "922f4815f713f213882e8ef45e0d315b164d705c" [[projects]] branch = "master" + digest = "1:363b547c971a2b07474c598b6e9ebcb238d556d8a27f37b3895ad20cd50e7281" name = "golang.org/x/oauth2" packages = [ ".", - "internal" + "internal", ] - revision = "3d292e4d0cdc3a0113e6d207bb137145ef1de42f" + pruneopts = "UT" + revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" [[projects]] branch = "master" + digest = "1:48774faa158e9eaee1ba45aad66434bb0345927b43756a24d4fe4c44ad79e307" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] - revision = "bd9dbc187b6e1dacfdd2722a87e83093c2d7bd6e" + pruneopts = "UT" + revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" [[projects]] + digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73" name = "golang.org/x/text" packages = [ "collate", @@ -481,12 +600,14 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] + digest = "1:328b5e4f197d928c444a51a75385f4b978915c0e75521f0ad6a3db976c97a7d3" name = "google.golang.org/appengine" packages = [ "internal", @@ -495,43 +616,80 @@ "internal/log", "internal/remote_api", "internal/urlfetch", - "urlfetch" + "urlfetch", ] + pruneopts = "UT" revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" version = "v1.1.0" [[projects]] + digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" name = "gopkg.in/fsnotify.v1" packages = ["."] + pruneopts = "UT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" source = "https://github.com/fsnotify/fsnotify.git" version = "v1.4.7" [[projects]] + digest = "1:02d2c5be9a35ce750536e74af0d98aca806f225913a3ab28f285843d6283c70d" name = "gopkg.in/square/go-jose.v2" packages = [ ".", "cipher", - "json" + "json", ] - revision = "349dc03548930652802aadc09fb126e2b7cb6d80" - version = "v2.1.7" + pruneopts = "UT" + revision = "8254d6c783765f38c8675fae4427a1fe73fbd09d" + version = "v2.1.8" [[projects]] branch = "v1" + digest = "1:0caa92e17bc0b65a98c63e5bc76a9e844cd5e56493f8fdbb28fad101a16254d9" name = "gopkg.in/tomb.v1" packages = ["."] + pruneopts = "UT" revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8" [[projects]] + digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "UT" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "0c44545f797adb2e842ab02f1239b7380dc503514dab48d828b1da20c3c2de4f" + input-imports = [ + "github.com/DATA-DOG/go-sqlmock", + "github.com/cloudfoundry-community/go-cfenv", + "github.com/coreos/go-oidc", + "github.com/fatih/structs", + "github.com/gavv/httpexpect", + "github.com/gbrlsnchs/jwt", + "github.com/gobwas/glob", + "github.com/gofrs/uuid", + "github.com/golang-migrate/migrate", + "github.com/golang-migrate/migrate/database/postgres", + "github.com/golang-migrate/migrate/source/file", + "github.com/gorilla/handlers", + "github.com/gorilla/mux", + "github.com/jmoiron/sqlx", + "github.com/jmoiron/sqlx/types", + "github.com/lib/pq", + "github.com/mitchellh/mapstructure", + "github.com/onsi/ginkgo", + "github.com/onsi/gomega", + "github.com/onsi/gomega/ghttp", + "github.com/pmorie/go-open-service-broker-client/v2", + "github.com/sirupsen/logrus", + "github.com/spf13/cast", + "github.com/spf13/pflag", + "github.com/spf13/viper", + "github.com/tidwall/sjson", + "gopkg.in/yaml.v2", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/Peripli/service-manager/Gopkg.toml b/vendor/github.com/Peripli/service-manager/Gopkg.toml index b5214279..74d24ed3 100644 --- a/vendor/github.com/Peripli/service-manager/Gopkg.toml +++ b/vendor/github.com/Peripli/service-manager/Gopkg.toml @@ -38,8 +38,8 @@ branch = "master" [[constraint]] - name = "github.com/satori/go.uuid" - revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" + name = "github.com/gofrs/uuid" + version = "=3.1.0" [[constraint]] name = "github.com/golang-migrate/migrate" diff --git a/vendor/github.com/Peripli/service-manager/README.md b/vendor/github.com/Peripli/service-manager/README.md index ddf0189d..4859aad0 100644 --- a/vendor/github.com/Peripli/service-manager/README.md +++ b/vendor/github.com/Peripli/service-manager/README.md @@ -4,6 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/Peripli/service-manager)](https://goreportcard.com/report/github.com/Peripli/service-manager) [![Coverage Status](https://coveralls.io/repos/github/Peripli/service-manager/badge.svg)](https://coveralls.io/github/Peripli/service-manager) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/Peripli/service-manager/blob/master/LICENSE) +[![Docker Repository on Quay](https://quay.io/repository/service-manager/core/status "Docker Repository on Quay")](https://quay.io/repository/service-manager/core) ## What is Service Manager diff --git a/vendor/github.com/Peripli/service-manager/api/api.go b/vendor/github.com/Peripli/service-manager/api/api.go index de004910..71a967ad 100644 --- a/vendor/github.com/Peripli/service-manager/api/api.go +++ b/vendor/github.com/Peripli/service-manager/api/api.go @@ -18,9 +18,9 @@ package api import ( - "fmt" - "context" + "fmt" + "net/http" "github.com/Peripli/service-manager/api/broker" "github.com/Peripli/service-manager/api/catalog" @@ -51,9 +51,23 @@ func (s *Security) Validate() error { // Settings type to be loaded from the environment type Settings struct { - TokenIssuerURL string `mapstructure:"token_issuer_url"` - ClientID string `mapstructure:"client_id"` - Security Security `mapstructure:"security"` + TokenIssuerURL string `mapstructure:"token_issuer_url"` + ClientID string `mapstructure:"client_id"` + Security Security `mapstructure:"security"` + SkipSSLValidation bool `mapstructure:"skip_ssl_validation"` +} + +// DefaultSettings returns default values for API settings +func DefaultSettings() *Settings { + return &Settings{ + TokenIssuerURL: "", + ClientID: "", + Security: Security{ + EncryptionKey: "", + }, + SkipSSLValidation: false, + } + } // Validate validates the API settings @@ -61,9 +75,6 @@ func (s *Settings) Validate() error { if (len(s.TokenIssuerURL)) == 0 { return fmt.Errorf("validate Settings: APITokenIssuerURL missing") } - if (len(s.ClientID)) == 0 { - return fmt.Errorf("validate Settings: APIClientID missing") - } if err := s.Security.Validate(); err != nil { return err } @@ -71,7 +82,7 @@ func (s *Settings) Validate() error { } // New returns the minimum set of REST APIs needed for the Service Manager -func New(ctx context.Context, storage storage.Storage, settings Settings, encrypter security.Encrypter) (*web.API, error) { +func New(ctx context.Context, storage storage.Storage, settings *Settings, encrypter security.Encrypter) (*web.API, error) { bearerAuthnFilter, err := authn.NewBearerAuthnFilter(ctx, settings.TokenIssuerURL, settings.ClientID) if err != nil { return nil, err @@ -81,12 +92,12 @@ func New(ctx context.Context, storage storage.Storage, settings Settings, encryp Controllers: []web.Controller{ &broker.Controller{ BrokerStorage: storage.Broker(), - OSBClientCreateFunc: osbc.NewClient, + OSBClientCreateFunc: newOSBClient(settings.SkipSSLValidation), Encrypter: encrypter, }, &platform.Controller{ - PlatformStorage: storage.Platform(), - Encrypter: encrypter, + PlatformStorage: storage.Platform(), + Encrypter: encrypter, }, &info.Controller{ TokenIssuer: settings.TokenIssuerURL, @@ -94,10 +105,11 @@ func New(ctx context.Context, storage storage.Storage, settings Settings, encryp &catalog.Controller{ BrokerStorage: storage.Broker(), }, - &osb.Controller{ - BrokerStorage: storage.Broker(), - Encrypter: encrypter, - }, + osb.NewController(&osb.BrokerTransport{ + BrokerStorage: storage.Broker(), + Encrypter: encrypter, + Tr: http.DefaultTransport, + }), &healthcheck.Controller{ Storage: storage, }, @@ -110,3 +122,10 @@ func New(ctx context.Context, storage storage.Storage, settings Settings, encryp }, }, nil } + +func newOSBClient(skipSsl bool) osbc.CreateFunc { + return func(configuration *osbc.ClientConfiguration) (osbc.Client, error) { + configuration.Insecure = skipSsl + return osbc.NewClient(configuration) + } +} diff --git a/vendor/github.com/Peripli/service-manager/api/api_test.go b/vendor/github.com/Peripli/service-manager/api/api_test.go index e9998f29..d77aea61 100644 --- a/vendor/github.com/Peripli/service-manager/api/api_test.go +++ b/vendor/github.com/Peripli/service-manager/api/api_test.go @@ -49,7 +49,7 @@ var _ = Describe("API", func() { Describe("New", func() { It("returns no error if creation is successful", func() { server := common.SetupFakeOAuthServer() - API, err = api.New(context.TODO(), mockedStorage, api.Settings{ + API, err = api.New(context.TODO(), mockedStorage, &api.Settings{ TokenIssuerURL: server.URL, ClientID: "sm", }, nil) @@ -57,7 +57,7 @@ var _ = Describe("API", func() { }) It("returns an error if creation fails", func() { - API, err = api.New(context.TODO(), mockedStorage, api.Settings{ + API, err = api.New(context.TODO(), mockedStorage, &api.Settings{ TokenIssuerURL: "http://invalidurl.com", ClientID: "invalidclient", }, nil) diff --git a/vendor/github.com/Peripli/service-manager/api/broker/broker.go b/vendor/github.com/Peripli/service-manager/api/broker/broker.go index c6f83e9f..f7388bd1 100644 --- a/vendor/github.com/Peripli/service-manager/api/broker/broker.go +++ b/vendor/github.com/Peripli/service-manager/api/broker/broker.go @@ -23,47 +23,41 @@ import ( "github.com/Peripli/service-manager/pkg/web" ) -const ( - apiVersion = "v1" - root = "service_brokers" - url = "/" + apiVersion + "/" + root -) - // Routes returns slice of routes which handle broker operations func (c *Controller) Routes() []web.Route { return []web.Route{ { Endpoint: web.Endpoint{ Method: http.MethodPost, - Path: url, + Path: web.BrokersURL, }, Handler: c.createBroker, }, { Endpoint: web.Endpoint{ Method: http.MethodGet, - Path: url + "/{broker_id}", + Path: web.BrokersURL + "/{broker_id}", }, Handler: c.getBroker, }, { Endpoint: web.Endpoint{ Method: http.MethodGet, - Path: url, + Path: web.BrokersURL, }, Handler: c.getAllBrokers, }, { Endpoint: web.Endpoint{ Method: http.MethodDelete, - Path: url + "/{broker_id}", + Path: web.BrokersURL + "/{broker_id}", }, Handler: c.deleteBroker, }, { Endpoint: web.Endpoint{ Method: http.MethodPatch, - Path: url + "/{broker_id}", + Path: web.BrokersURL + "/{broker_id}", }, Handler: c.patchBroker, }, diff --git a/vendor/github.com/Peripli/service-manager/api/broker/broker_controller.go b/vendor/github.com/Peripli/service-manager/api/broker/broker_controller.go index cbb1b5c5..f650f433 100644 --- a/vendor/github.com/Peripli/service-manager/api/broker/broker_controller.go +++ b/vendor/github.com/Peripli/service-manager/api/broker/broker_controller.go @@ -30,7 +30,7 @@ import ( "github.com/Peripli/service-manager/pkg/util" "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/storage" - "github.com/satori/go.uuid" + "github.com/gofrs/uuid" "github.com/sirupsen/logrus" ) @@ -41,9 +41,9 @@ const ( // Controller broker controller type Controller struct { - BrokerStorage storage.Broker - OSBClientCreateFunc osbc.CreateFunc - Encrypter security.Encrypter + BrokerStorage storage.Broker + OSBClientCreateFunc osbc.CreateFunc + Encrypter security.Encrypter } var _ web.Controller = &Controller{} diff --git a/vendor/github.com/Peripli/service-manager/api/catalog/catalog.go b/vendor/github.com/Peripli/service-manager/api/catalog/catalog.go index 2e8e95ba..120e3815 100644 --- a/vendor/github.com/Peripli/service-manager/api/catalog/catalog.go +++ b/vendor/github.com/Peripli/service-manager/api/catalog/catalog.go @@ -23,12 +23,8 @@ import ( "github.com/Peripli/service-manager/pkg/web" ) -const ( - apiVersion = "v1" - root = "sm_catalog" - // URL is the path of the aggregated catalog endpoint - URL = "/" + apiVersion + "/" + root -) +// URL is the path of the aggregated catalog endpoint +const URL = web.SMCatalogURL // Routes returns slice of routes which handle catalog operations func (c *Controller) Routes() []web.Route { diff --git a/vendor/github.com/Peripli/service-manager/api/filters/authn/authn.go b/vendor/github.com/Peripli/service-manager/api/filters/authn/authn.go index 0f802443..a02886c1 100644 --- a/vendor/github.com/Peripli/service-manager/api/filters/authn/authn.go +++ b/vendor/github.com/Peripli/service-manager/api/filters/authn/authn.go @@ -3,8 +3,6 @@ package authn import ( "net/http" - "context" - "errors" "github.com/Peripli/service-manager/pkg/util" @@ -12,21 +10,6 @@ import ( "github.com/Peripli/service-manager/security" ) -// userKey represents the authenticated user from the request context -type contextKey string - -var userKey = contextKey("service-manager-authenticated-user") - -func (c contextKey) String() string { - return string(c) -} - -// UserFromContext gets the authenticated user from the context. -func UserFromContext(ctx context.Context) (*security.User, bool) { - userStr, ok := ctx.Value(userKey).(*security.User) - return userStr, ok -} - var ( errUnauthorized = &util.HTTPError{ ErrorType: "Unauthorized", @@ -44,34 +27,32 @@ type Middleware struct { // Run represents the authentication middleware function that delegates the authentication // to the provided authenticator -func (ba *Middleware) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - if _, ok := UserFromContext(request.Context()); ok { - return next.Handle(request) - } +func (ba *Middleware) Run(request *web.Request, next web.Handler) (*web.Response, error) { + if _, ok := web.UserFromContext(request.Context()); ok { + return next.Handle(request) + } - user, decision, err := ba.authenticator.Authenticate(request.Request) - if err != nil { - if decision == security.Deny { - return nil, &util.HTTPError{ - ErrorType: "Unauthorized", - Description: err.Error(), - StatusCode: http.StatusUnauthorized, - } + user, decision, err := ba.authenticator.Authenticate(request.Request) + if err != nil { + if decision == security.Deny { + return nil, &util.HTTPError{ + ErrorType: "Unauthorized", + Description: err.Error(), + StatusCode: http.StatusUnauthorized, } - return nil, err } + return nil, err + } - switch decision { - case security.Allow: - if user == nil { - return nil, errUserNotFound - } - request.Request = request.WithContext(context.WithValue(request.Context(), userKey, user)) - case security.Deny: - return nil, errUnauthorized + switch decision { + case security.Allow: + if user == nil { + return nil, errUserNotFound } + request.Request = request.WithContext(web.NewContextWithUser(request.Context(), user)) + case security.Deny: + return nil, errUnauthorized + } - return next.Handle(request) - }) + return next.Handle(request) } diff --git a/vendor/github.com/Peripli/service-manager/api/filters/authn/authn_test.go b/vendor/github.com/Peripli/service-manager/api/filters/authn/authn_test.go index 50351140..f7a7f50d 100644 --- a/vendor/github.com/Peripli/service-manager/api/filters/authn/authn_test.go +++ b/vendor/github.com/Peripli/service-manager/api/filters/authn/authn_test.go @@ -39,7 +39,7 @@ func TestHandler(t *testing.T) { } type testStructure struct { - authnResp *security.User + authnResp *web.User authnDecision security.AuthenticationDecision authnErr error request *web.Request @@ -71,7 +71,7 @@ var _ = Describe("Authn", func() { validateMiddlewareBehavesCorrectly := func(middleware web.Middleware, t *testStructure) { fakeAuthenticator.AuthenticateReturns(t.authnResp, t.authnDecision, t.authnErr) fakeHandler.HandleReturns(expectedWebResponse, nil) - resp, err := middleware.Run(fakeHandler).Handle(t.request) + resp, err := middleware.Run(t.request, fakeHandler) Expect(fakeHandler.HandleCallCount()).To(Equal(t.actualHandlerInvokations)) @@ -114,7 +114,7 @@ var _ = Describe("Authn", func() { Context("when user is already authenticated and present in context", func() { It("invokes the next handler", func() { validateAuthnMiddlewareBehavesCorrectly(&testStructure{ - request: reqWithContext(context.WithValue(context.Background(), userKey, &security.User{Name: "username"})), + request: reqWithContext(web.NewContextWithUser(context.Background(), &web.User{Name: "username"})), actualHandlerInvokations: 1, expectedResp: expectedWebResponse, }) @@ -178,7 +178,7 @@ var _ = Describe("Authn", func() { Context("and returns a user", func() { It("invokes the next handler and adds the user to the request context", func() { testStruct := &testStructure{ - authnResp: &security.User{ + authnResp: &web.User{ Name: "username", }, authnDecision: security.Allow, @@ -191,7 +191,7 @@ var _ = Describe("Authn", func() { validateAuthnMiddlewareBehavesCorrectly(testStruct) - _, ok := UserFromContext(testStruct.request.Context()) + _, ok := web.UserFromContext(testStruct.request.Context()) Expect(ok).To(BeTrue()) }) }) @@ -244,7 +244,7 @@ var _ = Describe("Authn", func() { Context("when user is in context", func() { It("invokes next handler", func() { validateRequiredMiddlewareBehavesCorrectly(&testStructure{ - request: reqWithContext(context.WithValue(context.Background(), userKey, &security.User{Name: "username"})), + request: reqWithContext(web.NewContextWithUser(context.Background(), &web.User{Name: "username"})), actualHandlerInvokations: 1, expectedErr: nil, expectedResp: expectedWebResponse, diff --git a/vendor/github.com/Peripli/service-manager/api/filters/authn/basic.go b/vendor/github.com/Peripli/service-manager/api/filters/authn/basic.go index cd97cf6e..f9b731a7 100644 --- a/vendor/github.com/Peripli/service-manager/api/filters/authn/basic.go +++ b/vendor/github.com/Peripli/service-manager/api/filters/authn/basic.go @@ -9,6 +9,9 @@ import ( "github.com/Peripli/service-manager/storage" ) +// BasicAuthnFilterName is the name of the basic authentication filter +const BasicAuthnFilterName string = "BasicAuthnFilter" + // BasicAuthnFilter performs Basic authentication by validating the Authorization header type BasicAuthnFilter struct { Middleware @@ -20,14 +23,14 @@ func NewBasicAuthnFilter(storage storage.Credentials, encrypter security.Encrypt return &BasicAuthnFilter{ Middleware: Middleware{ authenticator: basic.NewAuthenticator(storage, encrypter), - name: "BasicAuthenticationFilter", + name: BasicAuthnFilterName, }, } } // Name implements the web.Filter interface and returns the identifier of the filter func (ba *BasicAuthnFilter) Name() string { - return "BasicAuthenticationFilter" + return BasicAuthnFilterName } // FilterMatchers implements the web.Filter interface and returns the conditions on which the filter should be executed @@ -35,13 +38,13 @@ func (ba *BasicAuthnFilter) FilterMatchers() []web.FilterMatcher { return []web.FilterMatcher{ { Matchers: []web.Matcher{ - web.Path("/v1/osb/**"), + web.Path(web.OSBURL + "/**"), }, }, { Matchers: []web.Matcher{ web.Methods(http.MethodGet), - web.Path("/v1/service_brokers/**"), + web.Path(web.BrokersURL + "/**"), }, }, } diff --git a/vendor/github.com/Peripli/service-manager/api/filters/authn/bearer.go b/vendor/github.com/Peripli/service-manager/api/filters/authn/bearer.go index fe9ef688..a2e66d0a 100644 --- a/vendor/github.com/Peripli/service-manager/api/filters/authn/bearer.go +++ b/vendor/github.com/Peripli/service-manager/api/filters/authn/bearer.go @@ -1,14 +1,15 @@ package authn import ( - "net/http" - "context" "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/security/oidc" ) +// BearerAuthnFilterName is the name of the bearer authentication filter +const BearerAuthnFilterName string = "BearerAuthnFilter" + // BearerAuthnFilter performs Bearer authentication by validating the Authorization header type BearerAuthnFilter struct { Middleware @@ -16,7 +17,7 @@ type BearerAuthnFilter struct { // NewBearerAuthnFilter returns a BearerAuthnFilter func NewBearerAuthnFilter(ctx context.Context, tokenIssuer, clientID string) (*BearerAuthnFilter, error) { - authenticator, err := oidc.NewAuthenticator(ctx, oidc.Options{ + authenticator, err := oidc.NewAuthenticator(ctx, &oidc.Options{ IssuerURL: tokenIssuer, ClientID: clientID, }) @@ -26,14 +27,14 @@ func NewBearerAuthnFilter(ctx context.Context, tokenIssuer, clientID string) (*B return &BearerAuthnFilter{ Middleware: Middleware{ authenticator: authenticator, - name: "BearerAuthenticationFilter", + name: BearerAuthnFilterName, }, }, nil } // Name implements the web.Filter interface and returns the identifier of the filter func (ba *BearerAuthnFilter) Name() string { - return "BearerAuthenticationFilter" + return BearerAuthnFilterName } // FilterMatchers implements the web.Filter interface and returns the conditions on which the filter should be executed @@ -41,24 +42,11 @@ func (ba *BearerAuthnFilter) FilterMatchers() []web.FilterMatcher { return []web.FilterMatcher{ { Matchers: []web.Matcher{ - web.Methods(http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch), - web.Path("/v1/service_brokers/**"), - }, - }, - { - Matchers: []web.Matcher{ - web.Methods(http.MethodGet), - web.Path("/v1/service_brokers/**"), - }, - }, - { - Matchers: []web.Matcher{ - web.Path("/v1/platforms/**"), - }, - }, - { - Matchers: []web.Matcher{ - web.Path("/v1/sm_catalog"), + web.Path( + web.BrokersURL+"/**", + web.PlatformsURL+"/**", + web.SMCatalogURL, + ), }, }, } diff --git a/vendor/github.com/Peripli/service-manager/api/filters/authn/required.go b/vendor/github.com/Peripli/service-manager/api/filters/authn/required.go index d7219fc0..8da53b4d 100644 --- a/vendor/github.com/Peripli/service-manager/api/filters/authn/required.go +++ b/vendor/github.com/Peripli/service-manager/api/filters/authn/required.go @@ -21,15 +21,13 @@ func (raf *RequiredAuthnFilter) Name() string { // Run implements web.Filter and represents the authentication middleware function that verifies the user is // authenticated -func (raf *RequiredAuthnFilter) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - if _, ok := UserFromContext(request.Context()); !ok { - logrus.Error("No authenticated user found in request context during execution of filter ", raf.Name()) - return nil, errUnauthorized - } +func (raf *RequiredAuthnFilter) Run(request *web.Request, next web.Handler) (*web.Response, error) { + if _, ok := web.UserFromContext(request.Context()); !ok { + logrus.Error("No authenticated user found in request context during execution of filter ", raf.Name()) + return nil, errUnauthorized + } - return next.Handle(request) - }) + return next.Handle(request) } // FilterMatchers implements the web.Filter interface and returns the conditions on which the filter should be executed @@ -37,7 +35,12 @@ func (raf *RequiredAuthnFilter) FilterMatchers() []web.FilterMatcher { return []web.FilterMatcher{ { Matchers: []web.Matcher{ - web.Path("/v1/service_brokers/**", "/v1/platforms/**", "/v1/sm_catalog", "/v1/osb/**"), + web.Path( + web.BrokersURL+"/**", + web.PlatformsURL+"/**", + web.SMCatalogURL, + web.OSBURL+"/**", + ), }, }, } diff --git a/vendor/github.com/Peripli/service-manager/api/healthcheck/healthcheck.go b/vendor/github.com/Peripli/service-manager/api/healthcheck/healthcheck.go index d5e76c2c..063f2e76 100644 --- a/vendor/github.com/Peripli/service-manager/api/healthcheck/healthcheck.go +++ b/vendor/github.com/Peripli/service-manager/api/healthcheck/healthcheck.go @@ -23,12 +23,8 @@ import ( "github.com/Peripli/service-manager/pkg/web" ) -const ( - apiVersion = "v1" - root = "monitor/health" - // URL is the path of the healthcheck endpoint - URL = "/" + apiVersion + "/" + root -) +// URL is the path of the healthcheck endpoint +const URL = web.MonitorHealthURL // Routes returns slice of routes which handle healthcheck operation func (c *Controller) Routes() []web.Route { diff --git a/vendor/github.com/Peripli/service-manager/api/info/info.go b/vendor/github.com/Peripli/service-manager/api/info/info.go index 1674a8a1..0c8faed1 100644 --- a/vendor/github.com/Peripli/service-manager/api/info/info.go +++ b/vendor/github.com/Peripli/service-manager/api/info/info.go @@ -23,12 +23,8 @@ import ( "github.com/Peripli/service-manager/pkg/web" ) -const ( - apiVersion = "v1" - root = "info" - // URL is the path of the info endpoint - URL = "/" + apiVersion + "/" + root -) +// URL is the path of the info endpoint +const URL = web.InfoURL // Routes returns a slice of the routs that handle info operations func (c *Controller) Routes() []web.Route { diff --git a/vendor/github.com/Peripli/service-manager/api/osb/osb.go b/vendor/github.com/Peripli/service-manager/api/osb/osb.go index 8948ddea..97a5200b 100644 --- a/vendor/github.com/Peripli/service-manager/api/osb/osb.go +++ b/vendor/github.com/Peripli/service-manager/api/osb/osb.go @@ -24,26 +24,21 @@ import ( ) const ( - - // v1 is a prefix the first version of the OSB API - v1 = "/v1" - - // root is a prefix for the OSB API - root = "/osb" - - //BrokerIDPathParam is a service broker ID path parameter + // BrokerIDPathParam is a service broker ID path parameter BrokerIDPathParam = "brokerID" // baseURL is the OSB API controller path - baseURL = v1 + root + "/{" + BrokerIDPathParam + "}" + baseURL = web.OSBURL + "/{" + BrokerIDPathParam + "}" - catalogURL = baseURL + "/v2/catalog" - serviceInstanceURL = baseURL + "/v2/service_instances/{instance_id}" - serviceBindingURL = baseURL + "/v2/service_instances/{instance_id}/service_bindings/{binding_id}" + catalogURL = baseURL + "/v2/catalog" + serviceInstanceURL = baseURL + "/v2/service_instances/{instance_id}" + serviceInstanceLastOperationURL = baseURL + "/v2/service_instances/{instance_id}/last_operation" + serviceBindingURL = baseURL + "/v2/service_instances/{instance_id}/service_bindings/{binding_id}" + serviceBindingLastOperationURL = baseURL + "/v2/service_instances/{instance_id}/service_bindings/{binding_id}/last_operation" ) // Routes implements api.Controller.Routes by providing the routes for the OSB API -func (c *Controller) Routes() []web.Route { +func (c *controller) Routes() []web.Route { return []web.Route{ {Endpoint: web.Endpoint{Method: http.MethodGet, Path: catalogURL}, Handler: c.handler}, @@ -55,5 +50,8 @@ func (c *Controller) Routes() []web.Route { {Endpoint: web.Endpoint{Method: http.MethodGet, Path: serviceBindingURL}, Handler: c.handler}, {Endpoint: web.Endpoint{Method: http.MethodPut, Path: serviceBindingURL}, Handler: c.handler}, {Endpoint: web.Endpoint{Method: http.MethodDelete, Path: serviceBindingURL}, Handler: c.handler}, + + {Endpoint: web.Endpoint{Method: http.MethodGet, Path: serviceInstanceLastOperationURL}, Handler: c.handler}, + {Endpoint: web.Endpoint{Method: http.MethodGet, Path: serviceBindingLastOperationURL}, Handler: c.handler}, } } diff --git a/vendor/github.com/Peripli/service-manager/api/osb/osb_controller.go b/vendor/github.com/Peripli/service-manager/api/osb/osb_controller.go index fa78a766..80a774f7 100644 --- a/vendor/github.com/Peripli/service-manager/api/osb/osb_controller.go +++ b/vendor/github.com/Peripli/service-manager/api/osb/osb_controller.go @@ -17,103 +17,103 @@ package osb import ( - "bytes" "fmt" "io/ioutil" "net/http" - "net/http/httptest" - "net/http/httputil" "net/url" "regexp" + "net/http/httputil" + + "net/http/httptest" + + "bytes" + "github.com/Peripli/service-manager/pkg/types" "github.com/Peripli/service-manager/pkg/util" "github.com/Peripli/service-manager/pkg/web" - "github.com/Peripli/service-manager/security" - "github.com/Peripli/service-manager/storage" "github.com/sirupsen/logrus" ) -var osbPathPattern = regexp.MustCompile("^" + v1 + root + "/[^/]+(/.*)$") +var osbPathPattern = regexp.MustCompile("^" + web.OSBURL + "/[^/]+(/.*)$") -// Controller implements api.Controller by providing OSB API logic -type Controller struct { - BrokerStorage storage.Broker - Filters web.Filters - Encrypter security.Encrypter +// BrokerRoundTripper is implemented by OSB handler providers +type BrokerRoundTripper interface { + http.RoundTripper + + Broker(brokerID string) (*types.Broker, error) } -var _ web.Controller = &Controller{} +// Controller implements api.Controller by providing OSB API logic +type controller struct { + fetcher BrokerRoundTripper + proxy *httputil.ReverseProxy +} -func (c *Controller) handler(request *web.Request) (*web.Response, error) { - logrus.Debug("Executing OSB operation: ", request.URL.Path) - broker, err := c.fetchBroker(request) - if err != nil { - return nil, err - } - target, _ := url.Parse(broker.BrokerURL) +var _ web.Controller = &controller{} - reverseProxy := httputil.ReverseProxy{ - Director: func(req *http.Request) { - req.Host = target.Host +// NewController returns new OSB controller +func NewController(fetcher BrokerRoundTripper) web.Controller { + return &controller{ + proxy: &httputil.ReverseProxy{ + Transport: fetcher, + Director: func(req *http.Request) {}, }, + fetcher: fetcher, } +} - username, password := broker.Credentials.Basic.Username, broker.Credentials.Basic.Password +func (c *controller) handler(request *web.Request) (*web.Response, error) { + logrus.Debug("Executing OSB operation: ", request.URL.Path) - modifiedRequest := request.Request.WithContext(request.Context()) - plaintextPassword, err := c.Encrypter.Decrypt([]byte(password)) + brokerID, ok := request.PathParams[BrokerIDPathParam] + if !ok { + logrus.Debugf("error creating OSB client: brokerID path parameter not found") + return nil, &util.HTTPError{ + ErrorType: "BadRequest", + Description: "invalid broker id path parameter", + StatusCode: http.StatusBadRequest, + } + } + logrus.Debugf("Obtained path parameter [brokerID = %s] from path params", brokerID) + + broker, err := c.fetcher.Broker(brokerID) if err != nil { return nil, err } - modifiedRequest.SetBasicAuth(username, string(plaintextPassword)) - modifiedRequest.URL.Scheme = target.Scheme - modifiedRequest.URL.Host = target.Host - modifiedRequest.Body = ioutil.NopCloser(bytes.NewReader(request.Body)) - modifiedRequest.ContentLength = int64(len(request.Body)) + + targetBrokerURL, _ := url.Parse(broker.BrokerURL) m := osbPathPattern.FindStringSubmatch(request.URL.Path) if m == nil || len(m) < 2 { return nil, fmt.Errorf("could not get OSB path from URL %s", request.URL.Path) } + + modifiedRequest := request.Request.WithContext(request.Context()) + modifiedRequest.SetBasicAuth(broker.Credentials.Basic.Username, broker.Credentials.Basic.Password) + modifiedRequest.Body = ioutil.NopCloser(bytes.NewReader(request.Body)) + modifiedRequest.ContentLength = int64(len(request.Body)) + modifiedRequest.Host = targetBrokerURL.Host modifiedRequest.URL.Path = m[1] logrus.Debugf("Forwarding OSB request to %s", modifiedRequest.URL) + + proxy := httputil.NewSingleHostReverseProxy(targetBrokerURL) + proxy.Transport = c.fetcher recorder := httptest.NewRecorder() - reverseProxy.ServeHTTP(recorder, modifiedRequest) - body, err := ioutil.ReadAll(recorder.Body) + proxy.ServeHTTP(recorder, modifiedRequest) + + respBody, err := ioutil.ReadAll(recorder.Body) if err != nil { return nil, err } - headers := recorder.HeaderMap resp := &web.Response{ StatusCode: recorder.Code, - Body: body, - Header: headers, + Header: recorder.HeaderMap, + Body: respBody, } logrus.Debugf("Service broker replied with status %d", resp.StatusCode) return resp, nil } - -func (c *Controller) fetchBroker(request *web.Request) (*types.Broker, error) { - brokerID, ok := request.PathParams[BrokerIDPathParam] - if !ok { - logrus.Debugf("error creating OSB client: brokerID path parameter not found") - return nil, &util.HTTPError{ - ErrorType: "BadRequest", - Description: "invalid broker id path parameter", - StatusCode: http.StatusBadRequest, - } - } - logrus.Debugf("Obtained path parameter [brokerID = %s] from path params", brokerID) - - serviceBroker, err := c.BrokerStorage.Get(brokerID) - if err != nil { - logrus.Debugf("Broker with id %s not found in storage during OSB %s operation", brokerID, request.URL.Path) - return nil, util.HandleStorageError(err, "broker", brokerID) - } - - return serviceBroker, nil -} diff --git a/vendor/github.com/Peripli/service-manager/api/osb/transport.go b/vendor/github.com/Peripli/service-manager/api/osb/transport.go new file mode 100644 index 00000000..f86d3e8b --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/api/osb/transport.go @@ -0,0 +1,44 @@ +package osb + +import ( + "net/http" + + "github.com/Peripli/service-manager/pkg/types" + "github.com/Peripli/service-manager/pkg/util" + "github.com/Peripli/service-manager/security" + "github.com/Peripli/service-manager/storage" + "github.com/sirupsen/logrus" +) + +// BrokerTransport provides handler for the Service Manager OSB business logic +type BrokerTransport struct { + BrokerStorage storage.Broker + Encrypter security.Encrypter + Tr http.RoundTripper +} + +var _ BrokerRoundTripper = &BrokerTransport{} + +// RoundTrip implements http.RoundTripper and invokes the RoundTripper delegate +func (bt *BrokerTransport) RoundTrip(request *http.Request) (*http.Response, error) { + return bt.Tr.RoundTrip(request) +} + +// Broker obtains the broker coordinates (auth and URL) +func (bt *BrokerTransport) Broker(brokerID string) (*types.Broker, error) { + broker, err := bt.BrokerStorage.Get(brokerID) + if err != nil { + logrus.Debugf("Broker with id %s not found in storage", brokerID) + return nil, util.HandleStorageError(err, "broker", brokerID) + } + + password := broker.Credentials.Basic.Password + plaintextPassword, err := bt.Encrypter.Decrypt([]byte(password)) + if err != nil { + return nil, err + } + + broker.Credentials.Basic.Password = string(plaintextPassword) + + return broker, nil +} diff --git a/vendor/github.com/Peripli/service-manager/api/platform/platform.go b/vendor/github.com/Peripli/service-manager/api/platform/platform.go index e380b3d1..82c260ec 100644 --- a/vendor/github.com/Peripli/service-manager/api/platform/platform.go +++ b/vendor/github.com/Peripli/service-manager/api/platform/platform.go @@ -23,47 +23,41 @@ import ( "github.com/Peripli/service-manager/pkg/web" ) -const ( - apiVersion = "v1" - root = "platforms" - url = "/" + apiVersion + "/" + root -) - // Routes returns slice of routes which handle platform operations func (c *Controller) Routes() []web.Route { return []web.Route{ { Endpoint: web.Endpoint{ Method: http.MethodPost, - Path: url, + Path: web.PlatformsURL, }, Handler: c.createPlatform, }, { Endpoint: web.Endpoint{ Method: http.MethodGet, - Path: url + "/{platform_id}", + Path: web.PlatformsURL + "/{platform_id}", }, Handler: c.getPlatform, }, { Endpoint: web.Endpoint{ Method: http.MethodGet, - Path: url, + Path: web.PlatformsURL, }, Handler: c.getAllPlatforms, }, { Endpoint: web.Endpoint{ Method: http.MethodDelete, - Path: url + "/{platform_id}", + Path: web.PlatformsURL + "/{platform_id}", }, Handler: c.deletePlatform, }, { Endpoint: web.Endpoint{ Method: http.MethodPatch, - Path: url + "/{platform_id}", + Path: web.PlatformsURL + "/{platform_id}", }, Handler: c.patchPlatform, }, diff --git a/vendor/github.com/Peripli/service-manager/api/platform/platform_controller.go b/vendor/github.com/Peripli/service-manager/api/platform/platform_controller.go index 7d1b5a07..a5fda249 100644 --- a/vendor/github.com/Peripli/service-manager/api/platform/platform_controller.go +++ b/vendor/github.com/Peripli/service-manager/api/platform/platform_controller.go @@ -23,9 +23,9 @@ import ( "github.com/Peripli/service-manager/pkg/types" "github.com/Peripli/service-manager/pkg/util" "github.com/Peripli/service-manager/pkg/web" - "github.com/Peripli/service-manager/storage" "github.com/Peripli/service-manager/security" - "github.com/satori/go.uuid" + "github.com/Peripli/service-manager/storage" + "github.com/gofrs/uuid" "github.com/sirupsen/logrus" ) diff --git a/vendor/github.com/Peripli/service-manager/application.yml b/vendor/github.com/Peripli/service-manager/application.yml index b784d134..47adbb78 100644 --- a/vendor/github.com/Peripli/service-manager/application.yml +++ b/vendor/github.com/Peripli/service-manager/application.yml @@ -13,4 +13,6 @@ api: token_issuer_url: https://uaa.local.pcfdev.io client_id: sm security: - encryption_key: ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8 \ No newline at end of file + encryption_key: ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8 + skip_ssl_validation: false + diff --git a/vendor/github.com/Peripli/service-manager/config/config.go b/vendor/github.com/Peripli/service-manager/config/config.go index f3d84d72..096ee504 100644 --- a/vendor/github.com/Peripli/service-manager/config/config.go +++ b/vendor/github.com/Peripli/service-manager/config/config.go @@ -17,22 +17,20 @@ package config import ( - "time" - "github.com/Peripli/service-manager/api" "github.com/Peripli/service-manager/pkg/env" "github.com/Peripli/service-manager/pkg/log" - "github.com/Peripli/service-manager/server" + "github.com/Peripli/service-manager/pkg/server" "github.com/Peripli/service-manager/storage" "github.com/spf13/pflag" ) // Settings is used to setup the Service Manager type Settings struct { - Server server.Settings - Storage storage.Settings - Log log.Settings - API api.Settings + Server *server.Settings + Storage *storage.Settings + Log *log.Settings + API *api.Settings } // AddPFlags adds the SM config flags to the provided flag set @@ -44,32 +42,17 @@ func AddPFlags(set *pflag.FlagSet) { // DefaultSettings returns the default values for configuring the Service Manager func DefaultSettings() *Settings { config := &Settings{ - Server: server.Settings{ - Port: 8080, - RequestTimeout: time.Second * 3, - ShutdownTimeout: time.Second * 3, - }, - Storage: storage.Settings{ - URI: "", - }, - Log: log.Settings{ - Level: "debug", - Format: "text", - }, - API: api.Settings{ - TokenIssuerURL: "", - ClientID: "sm", - Security: api.Security{ - EncryptionKey: "", - }, - }, + Server: server.DefaultSettings(), + Storage: storage.DefaultSettings(), + Log: log.DefaultSettings(), + API: api.DefaultSettings(), } return config } // New creates a configuration from the provided env func New(env env.Environment) (*Settings, error) { - config := &Settings{} + config := DefaultSettings() if err := env.Unmarshal(config); err != nil { return nil, err } @@ -79,17 +62,14 @@ func New(env env.Environment) (*Settings, error) { // Validate validates that the configuration contains all mandatory properties func (c *Settings) Validate() error { - if err := c.Server.Validate(); err != nil { - return err - } - if err := c.Log.Validate(); err != nil { - return err - } - if err := c.API.Validate(); err != nil { - return err - } - if err := c.Storage.Validate(); err != nil { - return err + validatable := []interface { + Validate() error + }{c.Server, c.Storage, c.Log, c.API} + + for _, item := range validatable { + if err := item.Validate(); err != nil { + return err + } } return nil } diff --git a/vendor/github.com/Peripli/service-manager/config/config_test.go b/vendor/github.com/Peripli/service-manager/config/config_test.go index 97d47281..6e5c5650 100644 --- a/vendor/github.com/Peripli/service-manager/config/config_test.go +++ b/vendor/github.com/Peripli/service-manager/config/config_test.go @@ -24,7 +24,7 @@ import ( cfg "github.com/Peripli/service-manager/config" "github.com/Peripli/service-manager/pkg/env/envfakes" "github.com/Peripli/service-manager/pkg/log" - "github.com/Peripli/service-manager/server" + "github.com/Peripli/service-manager/pkg/server" "github.com/Peripli/service-manager/storage" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -54,6 +54,7 @@ var _ = Describe("config", func() { config.API.TokenIssuerURL = "http://example.com" config.API.ClientID = "sm" config.API.Security.EncryptionKey = "ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8" + config.API.SkipSSLValidation = true }) Context("when config is valid", func() { @@ -111,13 +112,6 @@ var _ = Describe("config", func() { assertErrorDuringValidate() }) }) - - Context("when CLI ClientID is missing", func() { - It("returns an error", func() { - config.API.ClientID = "" - assertErrorDuringValidate() - }) - }) }) Describe("New", func() { @@ -150,21 +144,22 @@ var _ = Describe("config", func() { configuration cfg.Settings envConfig = cfg.Settings{ - Server: server.Settings{ + Server: &server.Settings{ Port: 8080, ShutdownTimeout: 5000, RequestTimeout: 5000, }, - Storage: storage.Settings{ + Storage: &storage.Settings{ URI: "dbUri", }, - Log: log.Settings{ + Log: &log.Settings{ Format: "text", Level: "debug", }, - API: api.Settings{ - TokenIssuerURL: "http://example.com", - ClientID: "sm", + API: &api.Settings{ + TokenIssuerURL: "http://example.com", + ClientID: "sm", + SkipSSLValidation: false, }, } diff --git a/vendor/github.com/Peripli/service-manager/deployment/cf/manifest.yml b/vendor/github.com/Peripli/service-manager/deployment/cf/manifest.yml index 0961db96..755b747d 100644 --- a/vendor/github.com/Peripli/service-manager/deployment/cf/manifest.yml +++ b/vendor/github.com/Peripli/service-manager/deployment/cf/manifest.yml @@ -13,4 +13,5 @@ applications: STORAGE_NAME: API_TOKEN_ISSUER_URL: https://uaa.local.pcfdev.io API_CLIENT_ID: smctl - API_SECURITY_ENCRYPTION_KEY: ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8 \ No newline at end of file + API_SECURITY_ENCRYPTION_KEY: ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8 + API_SKIP_SSL_VALIDATION: false \ No newline at end of file diff --git a/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/templates/sm03-deployment.yaml b/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/templates/sm03-deployment.yaml index 1b5e4b77..1b7c31ae 100644 --- a/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/templates/sm03-deployment.yaml +++ b/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/templates/sm03-deployment.yaml @@ -38,10 +38,10 @@ spec: name: {{ template "service-manager.fullname" . }}-secret key: uri - name: API_SECURITY_ENCRYPTION_KEY - valueFrom: - secretKeyRef: - name: {{ template "service-manager.fullname" . }}-secret - key: encryption_key + valueFrom: + secretKeyRef: + name: {{ template "service-manager.fullname" . }}-secret + key: encryption_key args: - "--file.location={{ .Values.file.location }}" - "--file.name={{ .Values.file.name }}" diff --git a/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/values.yaml b/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/values.yaml index e3e725c0..a0e76cef 100644 --- a/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/values.yaml +++ b/vendor/github.com/Peripli/service-manager/deployment/k8s/charts/service-manager/values.yaml @@ -38,4 +38,5 @@ config: shutdown_timeout: 3000ms api: token_issuer_url: https://uaa.local.pcfdev.io - client_id: smctl + client_id: sm + skip_ssl_validation: false diff --git a/vendor/github.com/Peripli/service-manager/docs/plugins.md b/vendor/github.com/Peripli/service-manager/docs/plugins.md index 2b985428..a12baf36 100644 --- a/vendor/github.com/Peripli/service-manager/docs/plugins.md +++ b/vendor/github.com/Peripli/service-manager/docs/plugins.md @@ -30,19 +30,17 @@ type Filter struct{} func (f *Filter) Name() string { return "FilterName" } // Run implements web.Middleware -func (f *Filter) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(r *web.Request) (*web.Response, error) { - // pre processing logic - fmt.Printf("request with method %s to URL %s\n", r.Method, r.URL) +func (f *Filter) Run(r *web.Request, next web.Handler) (*web.Response, error) { + // pre processing logic + fmt.Printf("request with method %s to URL %s\n", r.Method, r.URL) - // call next filter in chain - resp, err := next.Handle(r) + // call next filter in chain + resp, err := next.Handle(r) - // add post processing logic - fmt.Printf("response with status code %d and error %v\n", resp.StatusCode, err) + // add post processing logic + fmt.Printf("response with status code %d and error %v\n", resp.StatusCode, err) - return resp, err - }) + return resp, err } // FilterMatchers that specify when the filter should run. Each @@ -94,16 +92,14 @@ type MyPlugin struct {} func (p *MyPlugin) Name() string { return "MyPlugin" } -func (p *MyPlugin) FetchCatalog(next web.Handler) web.Handler { - return web.HandlerFunc(req *web.Request)(*web.Response, error) { - res, err := next.Handle(req) - if err != nil { - return nil, err - } - serviceName := gjson.GetBytes(res.Body, "services.0.name").String() - res.Body, err = sjson.SetBytes(res.Body, "services.0.name", serviceName + "-suffix") - return res, err - } +func (p *MyPlugin) FetchCatalog(req *web.Request, next web.Handler) (*web.Response, error) { + res, err := next.Handle(req) + if err != nil { + return nil, err + } + serviceName := gjson.GetBytes(res.Body, "services.0.name").String() + res.Body, err = sjson.SetBytes(res.Body, "services.0.name", serviceName+"-suffix") + return res, err } ``` @@ -113,15 +109,13 @@ This plugin will implement another interface on the plugin from the previous sec It will modify the response status code for provision operation. ```go -func (p *MyPlugin) Provision(next web.Handler) web.Handler { - return web.HandlerFunc(req *web.Request)(*web.Response, error) { - if !checkCredentials(req) { - return &web.Response{ - StatusCode: 401 // Unauthorized - }, nil - } - return next.Handle(req) +func (p *MyPlugin) Provision(req *web.Request, next web.Handler) (*web.Response, error) { + if !checkCredentials(req) { + return &web.Response{ + StatusCode: 401 // Unauthorized + }, nil } + return next.Handle(req) } ``` diff --git a/vendor/github.com/Peripli/service-manager/main.go b/vendor/github.com/Peripli/service-manager/main.go index 2fa5ba0a..2ff454fa 100644 --- a/vendor/github.com/Peripli/service-manager/main.go +++ b/vendor/github.com/Peripli/service-manager/main.go @@ -17,16 +17,15 @@ package main import ( - "context" - "github.com/Peripli/service-manager/pkg/sm" + "github.com/Peripli/service-manager/pkg/util" ) func main() { - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := util.HandleInterrupts() defer cancel() env := sm.DefaultEnv() - serviceManager := sm.New(ctx, cancel, env).Build() + serviceManager := sm.New(ctx, env).Build() serviceManager.Run() } diff --git a/vendor/github.com/Peripli/service-manager/pkg/log/log.go b/vendor/github.com/Peripli/service-manager/pkg/log/log.go index 9954e441..811d471a 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/log/log.go +++ b/vendor/github.com/Peripli/service-manager/pkg/log/log.go @@ -20,6 +20,7 @@ package log import ( "fmt" + "github.com/Peripli/service-manager/pkg/env" "github.com/sirupsen/logrus" ) @@ -29,6 +30,24 @@ type Settings struct { Format string } +// DefaultSettings returns default values for Log settings +func DefaultSettings() *Settings { + return &Settings{ + Level: "debug", + Format: "text", + } +} + +// NewSettings returns Server settings for the given enrivonment +func NewSettings(env env.Environment) (*Settings, error) { + config := &Settings{} + if err := env.Unmarshal(config); err != nil { + return nil, err + } + + return config, nil +} + // Validate validates the logging settings func (s *Settings) Validate() error { if len(s.Level) == 0 { @@ -46,7 +65,7 @@ var supportedFormatters = map[string]logrus.Formatter{ } // SetupLogging configures logrus logging using the provided settings -func SetupLogging(settings Settings) { +func SetupLogging(settings *Settings) { level, err := logrus.ParseLevel(settings.Level) if err != nil { panic(fmt.Sprintf("Could not parse log level configuration: %s", err.Error())) diff --git a/vendor/github.com/Peripli/service-manager/pkg/log/log_test.go b/vendor/github.com/Peripli/service-manager/pkg/log/log_test.go index f3de0b01..be59077c 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/log/log_test.go +++ b/vendor/github.com/Peripli/service-manager/pkg/log/log_test.go @@ -37,7 +37,7 @@ var _ = Describe("log", func() { Context("with invalid log level", func() { It("should panic", func() { - expectPanic(Settings{ + expectPanic(&Settings{ Level: "invalid", Format: "text", }) @@ -46,7 +46,7 @@ var _ = Describe("log", func() { Context("with invalid log level", func() { It("should panic", func() { - expectPanic(Settings{ + expectPanic(&Settings{ Level: "debug", Format: "invalid", }) @@ -77,7 +77,7 @@ func (wr *MyWriter) Write(p []byte) (n int, err error) { return len(p), nil } -func expectPanic(settings Settings) { +func expectPanic(settings *Settings) { wrapper := func() { SetupLogging(settings) } @@ -86,7 +86,7 @@ func expectPanic(settings Settings) { func expectOutput(substring string, logFormat string) { w := &MyWriter{} - SetupLogging(Settings{ + SetupLogging(&Settings{ Level: "debug", Format: logFormat, }) diff --git a/vendor/github.com/Peripli/service-manager/pkg/server/server.go b/vendor/github.com/Peripli/service-manager/pkg/server/server.go new file mode 100644 index 00000000..d9eabf3f --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/server/server.go @@ -0,0 +1,145 @@ +/* + * Copyright 2018 The Service Manager Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Package server contains the logic of the Service Manager server and a mux router +package server + +import ( + "context" + "fmt" + "net/http" + "strconv" + "time" + + "github.com/Peripli/service-manager/api" + "github.com/Peripli/service-manager/pkg/env" + "github.com/Peripli/service-manager/pkg/web" + "github.com/gorilla/mux" + "github.com/sirupsen/logrus" +) + +// Settings type to be loaded from the environment +type Settings struct { + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + RequestTimeout time.Duration `mapstructure:"request_timeout"` + ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout"` +} + +// DefaultSettings returns the default values for configuring the Service Manager +func DefaultSettings() *Settings { + return &Settings{ + Port: 8080, + RequestTimeout: time.Second * 3, + ShutdownTimeout: time.Second * 3, + } +} + +// NewSettings returns Server settings for the given enrivonment +func NewSettings(env env.Environment) (*Settings, error) { + config := &Settings{} + if err := env.Unmarshal(config); err != nil { + return nil, err + } + + return config, nil +} + +// Validate validates the server settings +func (s *Settings) Validate() error { + if s.Port == 0 { + return fmt.Errorf("validate Settings: Port missing") + } + if s.RequestTimeout == 0 { + return fmt.Errorf("validate Settings: RequestTimeout missing") + } + if s.ShutdownTimeout == 0 { + return fmt.Errorf("validate Settings: ShutdownTimeout missing") + } + return nil +} + +// Server is the server to process incoming HTTP requests +type Server struct { + *mux.Router + + Config *Settings + api *web.API +} + +// New creates a new server with the provided REST api configuration and server configuration +// Returns the new server and an error if creation was not successful +func New(config *Settings, api *web.API) *Server { + router := mux.NewRouter().StrictSlash(true) + registerControllers(api, router) + + return &Server{ + Config: config, + Router: router, + api: api, + } +} + +// Run starts the server awaiting for incoming requests +func (s *Server) Run(ctx context.Context) { + if err := s.Config.Validate(); err != nil { + panic(fmt.Sprintf("invalid server config: %s", err)) + } + handler := &http.Server{ + Handler: s.Router, + Addr: s.Config.Host + ":" + strconv.Itoa(s.Config.Port), + WriteTimeout: s.Config.RequestTimeout, + ReadTimeout: s.Config.RequestTimeout, + } + startServer(ctx, handler, s.Config.ShutdownTimeout) +} + +func registerControllers(API *web.API, router *mux.Router) { + for _, ctrl := range API.Controllers { + for _, route := range ctrl.Routes() { + logrus.Debugf("Registering endpoint: %s %s", route.Endpoint.Method, route.Endpoint.Path) + handler := web.Filters(API.Filters).ChainMatching(route) + router.Handle(route.Endpoint.Path, api.NewHTTPHandler(handler)).Methods(route.Endpoint.Method) + } + } +} + +func startServer(ctx context.Context, server *http.Server, shutdownTimeout time.Duration) { + go gracefulShutdown(ctx, server, shutdownTimeout) + + logrus.Infof("Listening on %s", server.Addr) + + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + logrus.Fatal(err) + } +} + +func gracefulShutdown(ctx context.Context, server *http.Server, shutdownTimeout time.Duration) { + <-ctx.Done() + + c, cancel := context.WithTimeout(context.Background(), shutdownTimeout) + defer cancel() + logrus.Debugf("Shutdown with timeout: %s", shutdownTimeout) + + if err := server.Shutdown(c); err != nil { + logrus.Error("Error: ", err) + if err := server.Close(); err != nil { + logrus.Error("Error: ", err) + } + } else { + logrus.Debug("Server stopped") + } +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/server/server_test.go b/vendor/github.com/Peripli/service-manager/pkg/server/server_test.go new file mode 100644 index 00000000..3bad9914 --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/server/server_test.go @@ -0,0 +1,140 @@ +/* + * Copyright 2018 The Service Manager Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package server + +import ( + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/Peripli/service-manager/api/filters" + "github.com/Peripli/service-manager/pkg/web" + "github.com/gavv/httpexpect" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestServer(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Server Suite") +} + +var sm *httpexpect.Expect + +var _ = Describe("Server", func() { + + BeforeSuite(func() { + api := &web.API{} + route := web.Route{ + Endpoint: web.Endpoint{ + Path: "/", + Method: http.MethodGet, + }, + Handler: testHandler, + } + testCtl := &testController{} + testCtl.RegisterRoutes(route) + api.RegisterControllers(testCtl) + api.RegisterFilters(&testFilter{}) + serverSettings := &Settings{ + Port: 0, + RequestTimeout: time.Second * 3, + ShutdownTimeout: time.Second * 3, + } + server := New(serverSettings, api) + server.Router.Use(filters.NewRecoveryMiddleware()) + Expect(server).ToNot(BeNil()) + testServer := httptest.NewServer(server.Router) + sm = httpexpect.New(GinkgoT(), testServer.URL) + }) + + Describe("Panic Recovery", func() { + Context("when controller has panicing http.handler", func() { + It("should return 500", func() { + assertRecover("fail=true") + }) + }) + + Context("when controller has panicing filter before delegating to next handler", func() { + It("should return 500", func() { + assertRecover("filter_fail_before=true") + }) + }) + + Context("when controller has panicing filter after delegating to next handler", func() { + It("should return 500", func() { + assertRecover("filter_fail_after=true") + }) + }) + }) + +}) + +func assertRecover(query string) { + sm.GET("/").Expect().Status(http.StatusOK) + sm.GET("/").WithQueryString(query).Expect().Status(http.StatusInternalServerError) + sm.GET("/").Expect().Status(http.StatusOK) +} + +type testController struct { + testRoutes []web.Route +} + +func (t *testController) RegisterRoutes(routes ...web.Route) { + t.testRoutes = append(t.testRoutes, routes...) +} + +func (t *testController) Routes() []web.Route { + return t.testRoutes +} + +type testFilter struct { +} + +func (tf testFilter) Name() string { + return "testFilter" +} + +func (tf testFilter) Run(request *web.Request, next web.Handler) (*web.Response, error) { + if request.URL.Query().Get("filter_fail_before") == "true" { + panic("expected") + } + res, err := next.Handle(request) + if request.URL.Query().Get("filter_fail_after") == "true" { + panic("expected") + } + return res, err +} + +func (tf testFilter) FilterMatchers() []web.FilterMatcher { + return []web.FilterMatcher{ + { + Matchers: []web.Matcher{ + web.Path("**"), + }, + }, + } +} + +func testHandler(req *web.Request) (*web.Response, error) { + if req.URL.Query().Get("fail") == "true" { + panic("expected") + } + return &web.Response{ + StatusCode: http.StatusOK, + }, nil +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/sm/sm.go b/vendor/github.com/Peripli/service-manager/pkg/sm/sm.go index 0bce8055..818f823a 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/sm/sm.go +++ b/vendor/github.com/Peripli/service-manager/pkg/sm/sm.go @@ -19,14 +19,15 @@ package sm import ( "context" "crypto/rand" + "crypto/tls" "fmt" - "os" - "os/signal" + "net/http" + "time" "github.com/Peripli/service-manager/api" "github.com/Peripli/service-manager/config" + "github.com/Peripli/service-manager/pkg/server" "github.com/Peripli/service-manager/security" - "github.com/Peripli/service-manager/server" "github.com/Peripli/service-manager/storage" "github.com/Peripli/service-manager/storage/postgres" @@ -39,9 +40,25 @@ import ( "github.com/spf13/pflag" ) +// ServiceManagerBuilder type is an extension point that allows adding additional filters, plugins and +// controllers before running ServiceManager. +type ServiceManagerBuilder struct { + *web.API + + ctx context.Context + cfg *server.Settings +} + +// ServiceManager struct +type ServiceManager struct { + ctx context.Context + Server *server.Server +} + // DefaultEnv creates a default environment that can be used to boot up a Service Manager func DefaultEnv(additionalPFlags ...func(set *pflag.FlagSet)) env.Environment { set := env.EmptyFlagSet() + config.AddPFlags(set) for _, addFlags := range additionalPFlags { addFlags(set) @@ -58,19 +75,18 @@ func DefaultEnv(additionalPFlags ...func(set *pflag.FlagSet)) env.Environment { } // New returns service-manager Server with default setup. The function panics on bad configuration -func New(ctx context.Context, cancel context.CancelFunc, env env.Environment) *ServiceManagerBuilder { - // graceful shutdown and handle interrupts - handleInterrupts(ctx, cancel) - +func New(ctx context.Context, env env.Environment) *ServiceManagerBuilder { // setup config from env cfg, err := config.New(env) if err != nil { panic(fmt.Errorf("error loading configuration: %s", err)) } if err := cfg.Validate(); err != nil { - panic(fmt.Sprintf("error validating config: %s", err)) + panic(fmt.Sprintf("error validating configuration: %s", err)) } + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: cfg.API.SkipSSLValidation} + // setup logging log.SetupLogging(cfg.Log) @@ -81,7 +97,7 @@ func New(ctx context.Context, cancel context.CancelFunc, env env.Environment) *S } securityStorage := smStorage.Security() - if err := initializeSecureStorage(securityStorage); err != nil { + if err := initializeSecureStorage(ctx, securityStorage); err != nil { panic(fmt.Sprintf("error initialzing secure storage: %v", err)) } @@ -89,60 +105,24 @@ func New(ctx context.Context, cancel context.CancelFunc, env env.Environment) *S Fetcher: securityStorage.Fetcher(), } - // setup core API + // setup core api API, err := api.New(ctx, smStorage, cfg.API, encrypter) if err != nil { - panic(fmt.Sprintf("error creating core API: %s", err)) + panic(fmt.Sprintf("error creating core api: %s", err)) } return &ServiceManagerBuilder{ - ctx: ctx, - cancel: cancel, - cfg: cfg.Server, - API: API, + ctx: ctx, + cfg: cfg.Server, + API: API, } } -// ServiceManager struct -type ServiceManager struct { - ctx context.Context - Server *server.Server -} - -// Run starts the Service Manager -func (sm *ServiceManager) Run() { - sm.Server.Run(sm.ctx) -} - -// ServiceManagerBuilder type is an extension point that allows adding additional filters, plugins and -// controllers before running ServiceManager. -type ServiceManagerBuilder struct { - ctx context.Context - cancel context.CancelFunc - cfg server.Settings - API *web.API -} - -// RegisterPlugins adds plugins to the Service Manager -func (smb *ServiceManagerBuilder) RegisterPlugins(plugins ...web.Plugin) { - smb.API.RegisterPlugins(plugins...) -} - -// RegisterFilters adds filters to the Service Manager -func (smb *ServiceManagerBuilder) RegisterFilters(filters ...web.Filter) { - smb.API.RegisterFilters(filters...) -} - -// RegisterControllers adds controllers to the Service Manager -func (smb *ServiceManagerBuilder) RegisterControllers(controllers ...web.Controller) { - smb.API.RegisterControllers(controllers...) -} - // Build builds the Service Manager func (smb *ServiceManagerBuilder) Build() *ServiceManager { // setup server and add relevant global middleware srv := server.New(smb.cfg, smb.API) - srv.Router.Use(filters.NewRecoveryMiddleware()) + srv.Use(filters.NewRecoveryMiddleware()) return &ServiceManager{ ctx: smb.ctx, @@ -150,7 +130,17 @@ func (smb *ServiceManagerBuilder) Build() *ServiceManager { } } -func initializeSecureStorage(secureStorage storage.Security) error { +// Run starts the Service Manager +func (sm *ServiceManager) Run() { + sm.Server.Run(sm.ctx) +} + +func initializeSecureStorage(ctx context.Context, secureStorage storage.Security) error { + ctx, cancelFunc := context.WithTimeout(ctx, 2*time.Second) + defer cancelFunc() + if err := secureStorage.Lock(ctx); err != nil { + return err + } keyFetcher := secureStorage.Fetcher() encryptionKey, err := keyFetcher.GetEncryptionKey() if err != nil { @@ -168,19 +158,5 @@ func initializeSecureStorage(secureStorage storage.Security) error { } logrus.Debug("Successfully generated new encryption key") } - return nil -} - -func handleInterrupts(ctx context.Context, cancelFunc context.CancelFunc) { - term := make(chan os.Signal) - signal.Notify(term, os.Interrupt) - go func() { - select { - case <-term: - logrus.Error("Received OS interrupt, exiting gracefully...") - cancelFunc() - case <-ctx.Done(): - return - } - }() + return secureStorage.Unlock() } diff --git a/vendor/github.com/Peripli/service-manager/pkg/util/client.go b/vendor/github.com/Peripli/service-manager/pkg/util/client.go index 6900cf60..96863bf3 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/util/client.go +++ b/vendor/github.com/Peripli/service-manager/pkg/util/client.go @@ -27,10 +27,11 @@ import ( "github.com/sirupsen/logrus" ) -type doRequestFunc func(request *http.Request) (*http.Response, error) +// DoRequestFunc is an alias for any function that takes an http request and returns a response and error +type DoRequestFunc func(request *http.Request) (*http.Response, error) // SendRequest sends a request to the specified client and the provided URL with the specified parameters and body. -func SendRequest(doRequest doRequestFunc, method, url string, params map[string]string, body interface{}) (*http.Response, error) { +func SendRequest(doRequest DoRequestFunc, method, url string, params map[string]string, body interface{}) (*http.Response, error) { var bodyReader io.Reader if body != nil { @@ -54,6 +55,7 @@ func SendRequest(doRequest doRequestFunc, method, url string, params map[string] request.URL.RawQuery = q.Encode() } + logrus.Debugf("Sending a request to %s", request.URL) return doRequest(request) } diff --git a/vendor/github.com/Peripli/service-manager/pkg/util/interrupts.go b/vendor/github.com/Peripli/service-manager/pkg/util/interrupts.go new file mode 100644 index 00000000..520c009c --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/util/interrupts.go @@ -0,0 +1,26 @@ +package util + +import ( + "context" + "os" + "os/signal" + + "github.com/sirupsen/logrus" +) + +// HandleInterrupts handles process signal interrupts +func HandleInterrupts() (context.Context, context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) + term := make(chan os.Signal) + signal.Notify(term, os.Interrupt) + go func() { + select { + case <-term: + logrus.Error("Received OS interrupt, exiting gracefully...") + cancel() + case <-ctx.Done(): + return + } + }() + return ctx, cancel +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/util/slice/strings.go b/vendor/github.com/Peripli/service-manager/pkg/util/slice/strings.go new file mode 100644 index 00000000..a3987744 --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/util/slice/strings.go @@ -0,0 +1,65 @@ +/* + * Copyright 2018 The Service Manager Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package slice + +import "strings" + +// StringsIntersection returns the common elements in two string slices. +func StringsIntersection(str1, str2 []string) []string { + var intersection []string + strings := make(map[string]bool) + for _, v := range str1 { + strings[v] = true + } + for _, v := range str2 { + if strings[v] { + intersection = append(intersection, v) + } + } + return intersection +} + +// StringsContaining returns a slice of the strings containing the specified string. +func StringsContaining(stringSlice []string, str string) []string { + var result []string + for _, v := range stringSlice { + if strings.Contains(v, str) { + result = append(result, v) + } + } + return result +} + +// StringsAnyPrefix returns true if any of the strings in the slice have the given prefix. +func StringsAnyPrefix(stringSlice []string, prefix string) bool { + for _, v := range stringSlice { + if strings.HasPrefix(v, prefix) { + return true + } + } + return false +} + +// StringsAnyEquals returns true if any of the strings in the slice equal the given string. +func StringsAnyEquals(stringSlice []string, str string) bool { + for _, v := range stringSlice { + if v == str { + return true + } + } + return false +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/api.go b/vendor/github.com/Peripli/service-manager/pkg/web/api.go index 40061a8a..fa2740e5 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/api.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/api.go @@ -21,6 +21,7 @@ package web import ( "net/http" + "github.com/Peripli/service-manager/pkg/util/slice" "github.com/sirupsen/logrus" ) @@ -58,8 +59,8 @@ func newPluginSegment(name, method, pathPattern string, f Middleware) *pluginSeg } } -func (dp *pluginSegment) Run(next Handler) Handler { - return dp.PluginOp.Run(next) +func (dp *pluginSegment) Run(request *Request, next Handler) (*Response, error) { + return dp.PluginOp.Run(request, next) } func (dp *pluginSegment) Name() string { @@ -79,21 +80,118 @@ func (api *API) RegisterControllers(controllers ...Controller) { // RegisterFilters registers a set of filters func (api *API) RegisterFilters(filters ...Filter) { + api.validateFilters(filters...) api.Filters = append(api.Filters, filters...) } +// RegisterFilterBefore registers the specified filter before the one with the given name. +// If for some routes, the filter with the given name does not match the routes of the provided filter, then +// the filter will be registered at the place at which the filter with this name would have been, had it been +// configured to match route. +func (api *API) RegisterFilterBefore(beforeFilterName string, filter Filter) { + logrus.Debugf("Registering filter %s before %s", filter.Name(), beforeFilterName) + api.validateFilters(filter) + api.registerFilterRelatively(beforeFilterName, filter, func(beforeFilterPosition int) int { + return beforeFilterPosition + }) +} + +// RegisterFilterAfter registers the specified filter after the one with the given name. +// If for some routes, the filter with the given name does not match the routes of the provided filter, then +// the filter will be registered after the place at which the filter with this name would have been, had it been +// configured to match route. +func (api *API) RegisterFilterAfter(afterFilterName string, filter Filter) { + logrus.Debugf("Registering filter %s after %s", filter.Name(), afterFilterName) + api.validateFilters(filter) + api.registerFilterRelatively(afterFilterName, filter, func(filterPosition int) int { + return filterPosition + 1 + }) +} + +// ReplaceFilter registers the given filter in the place of the filter with the given name. +func (api *API) ReplaceFilter(replacedFilterName string, filter Filter) { + logrus.Debugf("Replacing filter %s with %s", replacedFilterName, filter.Name()) + api.validateFilters(filter) + registeredFilterPosition := api.findFilterPosition(replacedFilterName) + api.Filters[registeredFilterPosition] = filter +} + +// RemoveFilter removes the filter with the given name +func (api *API) RemoveFilter(name string) { + position := api.findFilterPosition(name) + copy(api.Filters[position:], api.Filters[position+1:]) + api.Filters[len(api.Filters)-1] = nil + api.Filters = api.Filters[:len(api.Filters)-1] +} + // RegisterPlugins registers a set of plugins func (api *API) RegisterPlugins(plugins ...Plugin) { for _, plugin := range plugins { - pluginSegments := api.decomposePlugin(plugin) - if len(pluginSegments) == 0 { - logrus.Panicf("%T does not implement any plugin operation", plugin) + registeredFilterNames := api.filterNames(api.Filters) + if slice.StringsAnyPrefix(registeredFilterNames, plugin.Name()+":") { + logrus.Panicf("Plugin %s is already registered", plugin.Name()) } + pluginSegments := api.decomposePluginOrDie(plugin) + api.Filters = append(api.Filters, pluginSegments...) + } +} - api.RegisterFilters(pluginSegments...) +func (api *API) validateFilters(filters ...Filter) { + newFilterNames := api.filterNames(filters) + if slice.StringsAnyEquals(newFilterNames, "") { + logrus.Panicf("Filters cannot have empty names") + } + registeredFilterNames := api.filterNames(api.Filters) + commonFilterNames := slice.StringsIntersection(registeredFilterNames, newFilterNames) + if len(commonFilterNames) > 0 { + logrus.Panicf("Filters %q are already registered", commonFilterNames) + } + filterNamesWithColon := slice.StringsContaining(newFilterNames, ":") + if len(filterNamesWithColon) > 0 { + logrus.Panicf("Cannot register filters with : in their names. Invalid filter names: %q", filterNamesWithColon) } } +func (api *API) registerFilterRelatively(filterName string, newFilter Filter, newFilterPosition func(filterPosition int) int) { + registeredFilterPosition := api.findFilterPosition(filterName) + filterPosition := newFilterPosition(registeredFilterPosition) + api.Filters = append(api.Filters, nil) + copy(api.Filters[filterPosition+1:], api.Filters[filterPosition:]) + api.Filters[filterPosition] = newFilter +} + +func (api *API) findFilterPosition(filterName string) int { + filterPosition := -1 + for i := range api.Filters { + registeredFilter := api.Filters[i] + if registeredFilter.Name() == filterName { + filterPosition = i + break + } + } + if filterPosition < 0 { + logrus.Panicf("Filter with name %s is not found", filterName) + } + return filterPosition +} + +func (api *API) filterNames(filters []Filter) []string { + var filterNames []string + for i := range filters { + filter := filters[i] + filterNames = append(filterNames, filter.Name()) + } + return filterNames +} + +func (api *API) decomposePluginOrDie(plugin Plugin) []Filter { + pluginSegments := api.decomposePlugin(plugin) + if len(pluginSegments) == 0 { + logrus.Panicf("%T does not implement any plugin operation", plugin) + } + return pluginSegments +} + // decomposePlugin decomposes a Plugin into multiple Filters func (api *API) decomposePlugin(plug Plugin) []Filter { filters := make([]Filter, 0) @@ -130,6 +228,14 @@ func (api *API) decomposePlugin(plug Plugin) []Filter { filter := newPluginSegment(plug.Name()+":Unbind", http.MethodDelete, "/v1/osb/*/v2/service_instances/*/service_bindings/*", MiddlewareFunc(p.Unbind)) filters = append(filters, filter) } + if p, ok := plug.(InstancePoller); ok { + filter := newPluginSegment(plug.Name()+":PollInstance", http.MethodGet, "/v1/osb/*/v2/service_instances/*/last_operation", MiddlewareFunc(p.PollInstance)) + filters = append(filters, filter) + } + if p, ok := plug.(BindingPoller); ok { + filter := newPluginSegment(plug.Name()+":PollBinding", http.MethodGet, "/v1/osb/*/v2/service_instances/*/service_bindings/*/last_operation", MiddlewareFunc(p.PollBinding)) + filters = append(filters, filter) + } return filters } diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/api_test.go b/vendor/github.com/Peripli/service-manager/pkg/web/api_test.go index cd5c33bb..29cde550 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/api_test.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/api_test.go @@ -17,7 +17,7 @@ package web_test import ( - "github.com/Peripli/service-manager/pkg/web" + "github.com/Peripli/service-manager/pkg/web" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -31,6 +31,14 @@ var _ = Describe("API", func() { api = &web.API{} }) + filterNames := func() []string { + var names []string + for i := range api.Filters { + names = append(names, api.Filters[i].Name()) + } + return names + } + Describe("RegisterControllers", func() { It("increases controllers count", func() { originalCount := len(api.Controllers) @@ -40,25 +48,156 @@ var _ = Describe("API", func() { }) Describe("RegisterPlugins", func() { - It("panics if argument is an empty plugin", func() { - Expect(func() { - api.RegisterPlugins(&invalidPlugin{}) - }).To(Panic()) + Context("When argument is empty plugin", func() { + It("Panics", func() { + Expect(func() { + api.RegisterPlugins(&invalidPlugin{}) + }).To(Panic()) + }) }) - It("increases filter count if successful", func() { - originalCount := len(api.Filters) - api.RegisterPlugins(&validPlugin{}) - Expect(len(api.Filters)).To(Equal(originalCount + 8)) + Context("When plugin is valid", func() { + It("Successfully registers plugin", func() { + originalCount := len(api.Filters) + api.RegisterPlugins(&validPlugin{}) + Expect(len(api.Filters)).To(Equal(originalCount + 8)) + }) }) + Context("When plugin with the same name is already registered", func() { + It("Panics", func() { + registerPlugin := func() { + api.RegisterPlugins(&validPlugin{}) + } + registerPlugin() + Expect(registerPlugin).To(Panic()) + }) + }) + }) + + Describe("Replace Filter", func() { + Context("When filter with such name does not exist", func() { + It("Panics", func() { + replaceFilter := func() { + api.ReplaceFilter("some-filter", &testFilter{"testFilter"}) + } + Expect(replaceFilter).To(Panic()) + }) + }) + Context("When filter with such name exists", func() { + It("Replaces the filter", func() { + filter := &testFilter{"testFilter"} + newFilter := &testFilter{"testFilter2"} + api.RegisterFilters(filter) + api.ReplaceFilter(filter.Name(), newFilter) + names := filterNames() + Expect(names).To(ConsistOf([]string{newFilter.Name()})) + }) + }) + }) + + Describe("Register Filter Before", func() { + Context("When filter with such name does not exist", func() { + It("Panics", func() { + replaceFilter := func() { + api.RegisterFilterBefore("some-filter", &testFilter{"testFilter"}) + } + Expect(replaceFilter).To(Panic()) + }) + }) + + Context("When filter with such name exists", func() { + It("Adds the filter before it", func() { + filter1 := &testFilter{"testFilter"} + filter2 := &testFilter{"testFilter2"} + filter3 := &testFilter{"testFilter3"} + api.RegisterFilters(filter1, filter2) + api.RegisterFilterBefore(filter2.Name(), filter3) + names := filterNames() + Expect(names).To(Equal([]string{filter1.Name(), filter3.Name(), filter2.Name()})) + }) + }) + }) + + Describe("Register Filter After", func() { + Context("When filter with such name does not exist", func() { + It("Panics", func() { + replaceFilter := func() { + api.RegisterFilterAfter("some-filter", &testFilter{"testFilter"}) + } + Expect(replaceFilter).To(Panic()) + }) + }) + Context("When filter with such name exists", func() { + It("Adds the filter before it", func() { + filter := &testFilter{"testFilter"} + newFilter := &testFilter{"testFilter2"} + api.RegisterFilters(filter) + api.RegisterFilterAfter(filter.Name(), newFilter) + names := filterNames() + Expect(names).To(Equal([]string{filter.Name(), newFilter.Name()})) + }) + }) + }) + + Describe("Remove Filter", func() { + Context("When filter with such name doest not exist", func() { + It("Panics", func() { + removeFilter := func() { + api.RemoveFilter("some-filter") + } + Expect(removeFilter).To(Panic()) + }) + }) + Context("When filter exists", func() { + It("Should remove it", func() { + filter := &testFilter{"testFilter"} + api.RegisterFilters(filter) + names := filterNames() + Expect(names).To(ConsistOf(filter.Name())) + + api.RemoveFilter(filter.Name()) + names = filterNames() + Expect(names).To(BeEmpty()) + }) + }) }) Describe("RegisterFilters", func() { - It("increases filter count if successful", func() { - originalCount := len(api.Filters) - api.RegisterFilters(&testFilter{}) - Expect(len(api.Filters)).To(Equal(originalCount + 1)) + Context("When filter with such name does not exist", func() { + It("increases filter count if successful", func() { + originalCount := len(api.Filters) + api.RegisterFilters(&testFilter{"testFilter"}) + Expect(len(api.Filters)).To(Equal(originalCount + 1)) + }) + }) + + Context("When filter with such name already exists", func() { + It("Panics", func() { + registerFilter := func() { + api.RegisterFilters(&testFilter{"testFilter"}) + } + registerFilter() + Expect(registerFilter).To(Panic()) + }) + }) + + Context("When filter name contains :", func() { + It("Panics", func() { + registerFilter := func() { + api.RegisterFilters(&testFilter{"name:"}) + } + Expect(registerFilter).To(Panic()) + }) + }) + + Context("When filter name is empty", func() { + It("Panics", func() { + registerFilter := func() { + api.RegisterFilters(&testFilter{""}) + } + Expect(registerFilter).To(Panic()) + }) }) }) }) @@ -71,16 +210,15 @@ func (c *testController) Routes() []web.Route { } type testFilter struct { + name string } func (tf testFilter) Name() string { - return "testFilter" + return tf.name } -func (tf testFilter) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (tf testFilter) Run(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } func (tf testFilter) FilterMatchers() []web.FilterMatcher { @@ -97,54 +235,36 @@ func (p *invalidPlugin) Name() string { type validPlugin struct { } -func (c *validPlugin) UpdateService(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) UpdateService(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) Unbind(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - - }) +func (c *validPlugin) Unbind(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) Bind(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - - }) +func (c *validPlugin) Bind(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) FetchBinding(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) FetchBinding(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) Deprovision(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) Deprovision(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) Provision(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) Provision(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) FetchService(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) FetchService(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } -func (c *validPlugin) FetchCatalog(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) +func (c *validPlugin) FetchCatalog(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } func (c *validPlugin) Name() string { diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/context_keys.go b/vendor/github.com/Peripli/service-manager/pkg/web/context_keys.go new file mode 100644 index 00000000..1f54b1bd --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/web/context_keys.go @@ -0,0 +1,22 @@ +package web + +import ( + "context" +) + +type contextKey int + +const ( + userKey contextKey = iota +) + +// UserFromContext gets the authenticated user from the context +func UserFromContext(ctx context.Context) (*User, bool) { + userStr, ok := ctx.Value(userKey).(*User) + return userStr, ok +} + +// NewContextWithUser sets the authenticated user in the context +func NewContextWithUser(ctx context.Context, user *User) context.Context { + return context.WithValue(ctx, userKey, user) +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/filter.go b/vendor/github.com/Peripli/service-manager/pkg/web/filter.go index 5a6804e9..3eac7c4a 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/filter.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/filter.go @@ -79,15 +79,15 @@ type Middleware interface { // Run returns a handler that contains the handling logic of the Middleware. The implementation of Run // should invoke next's Handle if the request should be chained to the next Handler. // It may also terminate the request by not invoking the next Handler. - Run(next Handler) Handler + Run(req *Request, next Handler) (*Response, error) } // MiddlewareFunc is an adapter that allows to use regular functions as Middleware -type MiddlewareFunc func(handler Handler) Handler +type MiddlewareFunc func(req *Request, next Handler) (*Response, error) // Run allows MiddlewareFunc to act as a Middleware -func (mf MiddlewareFunc) Run(handler Handler) Handler { - return mf(handler) +func (mf MiddlewareFunc) Run(req *Request, handler Handler) (*Response, error) { + return mf(req, handler) } // Matcher allows checking whether an Endpoint matches a particular condition @@ -143,9 +143,22 @@ func (fs Filters) Chain(h Handler) Handler { for i := len(fs) - 1; i >= 0; i-- { i := i wrappedFilters[i] = HandlerFunc(func(request *Request) (*Response, error) { - logrus.Debug("Entering Filter: ", fs[i].Name(), " Path: ", request.URL.Path, " Method: ", request.Method) - resp, err := fs[i].Run(wrappedFilters[i+1]).Handle(request) - logrus.Debug("Exiting Filter: ", fs[i].Name(), " Err: ", err, " Path: ", request.URL.Path, " Method: ", request.Method) + params := map[string]interface{}{ + "path": request.URL.Path, + "method": request.Method, + } + + logrus.WithFields(params).Debug("Entering Filter: ", fs[i].Name()) + + resp, err := fs[i].Run(request, wrappedFilters[i+1]) + + params["err"] = err + if resp != nil { + params["statusCode"] = resp.StatusCode + } + + logrus.WithFields(params).Debug("Exiting Filter: ", fs[i].Name()) + return resp, err }) } diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/matcher_test.go b/vendor/github.com/Peripli/service-manager/pkg/web/matcher_test.go index c54ad094..9a916ec1 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/matcher_test.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/matcher_test.go @@ -38,26 +38,22 @@ var _ = Describe("Filters", func() { return filter } - delegatingMiddleware := func(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - return next.Handle(request) - }) + delegatingMiddleware := func(request *web.Request, next web.Handler) (*web.Response, error) { + return next.Handle(request) } loggingValidationMiddleware := func(prevFilterName, currFilterName, nextFilterName string, hook *LoggingInterceptorHook) web.MiddlewareFunc { - return web.MiddlewareFunc(func(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - if prevFilterName != "" { - Expect(string(hook.data)).To(ContainSubstring("Entering Filter: " + prevFilterName)) - } - Expect(string(hook.data)).To(ContainSubstring("Entering Filter: " + currFilterName)) - resp, err := next.Handle(request) - if nextFilterName != "" { - Expect(string(hook.data)).To(ContainSubstring("Exiting Filter: " + nextFilterName)) - } - return resp, err - }) - }) + return func(request *web.Request, next web.Handler) (*web.Response, error) { + if prevFilterName != "" { + Expect(string(hook.data)).To(ContainSubstring("Entering Filter: " + prevFilterName)) + } + Expect(string(hook.data)).To(ContainSubstring("Entering Filter: " + currFilterName)) + resp, err := next.Handle(request) + if nextFilterName != "" { + Expect(string(hook.data)).To(ContainSubstring("Exiting Filter: " + nextFilterName)) + } + return resp, err + } } Describe("Matching", func() { diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/plugin.go b/vendor/github.com/Peripli/service-manager/pkg/web/plugin.go index 52a13283..2630cec2 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/plugin.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/plugin.go @@ -28,54 +28,68 @@ type Plugin interface { type CatalogFetcher interface { Plugin - FetchCatalog(next Handler) Handler + FetchCatalog(request *Request, next Handler) (*Response, error) } // Provisioner should be implemented by plugins that need to intercept OSB call for provision operation type Provisioner interface { Plugin - Provision(next Handler) Handler + Provision(request *Request, next Handler) (*Response, error) } // Deprovisioner should be implemented by plugins that need to intercept OSB call for deprovision operation type Deprovisioner interface { Plugin - Deprovision(next Handler) Handler + Deprovision(request *Request, next Handler) (*Response, error) } // ServiceUpdater should be implemented by plugins that need to intercept OSB call for update service operation type ServiceUpdater interface { Plugin - UpdateService(next Handler) Handler + UpdateService(request *Request, next Handler) (*Response, error) } // ServiceFetcher should be implemented by plugins that need to intercept OSB call for get service operation type ServiceFetcher interface { Plugin - FetchService(next Handler) Handler + FetchService(request *Request, next Handler) (*Response, error) } // Binder should be implemented by plugins that need to intercept OSB call for bind service operation type Binder interface { Plugin - Bind(next Handler) Handler + Bind(request *Request, next Handler) (*Response, error) } // Unbinder should be implemented by plugins that need to intercept OSB call for unbind service operation type Unbinder interface { Plugin - Unbind(next Handler) Handler + Unbind(request *Request, next Handler) (*Response, error) } // BindingFetcher should be implemented by plugins that need to intercept OSB call for unbind service operation type BindingFetcher interface { Plugin - FetchBinding(next Handler) Handler + FetchBinding(request *Request, next Handler) (*Response, error) +} + +// InstancePoller should be implemented by plugins that need to intercept OSB calls for polling last operation for service instances +type InstancePoller interface { + Plugin + + PollInstance(request *Request, next Handler) (*Response, error) +} + +// BindingPoller should be implemented by plugins that need to intercept OSB Calls for polling last operation for service bindings +type BindingPoller interface { + Plugin + + PollBinding(request *Request, next Handler) (*Response, error) } diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/routes.go b/vendor/github.com/Peripli/service-manager/pkg/web/routes.go new file mode 100644 index 00000000..bc4add8c --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/web/routes.go @@ -0,0 +1,23 @@ +package web + +const ( + apiVersion = "v1" + + // BrokersURL is the URL path to manage service brokers + BrokersURL = "/" + apiVersion + "/service_brokers" + + // PlatformsURL is the URL path to manage platforms + PlatformsURL = "/" + apiVersion + "/platforms" + + // SMCatalogURL is the URL path to the aggregated catalog + SMCatalogURL = "/" + apiVersion + "/sm_catalog" + + // OSBURL is the OSB API base URL path + OSBURL = "/" + apiVersion + "/osb" + + // MonitorHealthURL is the path of the healthcheck endpoint + MonitorHealthURL = "/" + apiVersion + "/monitor/health" + + // InfoURL is the path of the info endpoint + InfoURL = "/" + apiVersion + "/info" +) diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/user.go b/vendor/github.com/Peripli/service-manager/pkg/web/user.go new file mode 100644 index 00000000..dfcd0273 --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/web/user.go @@ -0,0 +1,14 @@ +package web + +// TokenData represents the authentication token +//go:generate counterfeiter . TokenData +type TokenData interface { + // Claims reads the claims from the token into the specified struct + Claims(v interface{}) error +} + +// User holds the information for the current user +type User struct { + Name string `json:"name"` + TokenData +} diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_filter.go b/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_filter.go index 4c7f1f8d..e40c2a82 100644 --- a/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_filter.go +++ b/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_filter.go @@ -17,16 +17,19 @@ type FakeFilter struct { nameReturnsOnCall map[int]struct { result1 string } - RunStub func(next web.Handler) web.Handler + RunStub func(req *web.Request, next web.Handler) (*web.Response, error) runMutex sync.RWMutex runArgsForCall []struct { + req *web.Request next web.Handler } runReturns struct { - result1 web.Handler + result1 *web.Response + result2 error } runReturnsOnCall map[int]struct { - result1 web.Handler + result1 *web.Response + result2 error } FilterMatchersStub func() []web.FilterMatcher filterMatchersMutex sync.RWMutex @@ -81,21 +84,22 @@ func (fake *FakeFilter) NameReturnsOnCall(i int, result1 string) { }{result1} } -func (fake *FakeFilter) Run(next web.Handler) web.Handler { +func (fake *FakeFilter) Run(req *web.Request, next web.Handler) (*web.Response, error) { fake.runMutex.Lock() ret, specificReturn := fake.runReturnsOnCall[len(fake.runArgsForCall)] fake.runArgsForCall = append(fake.runArgsForCall, struct { + req *web.Request next web.Handler - }{next}) - fake.recordInvocation("Run", []interface{}{next}) + }{req, next}) + fake.recordInvocation("Run", []interface{}{req, next}) fake.runMutex.Unlock() if fake.RunStub != nil { - return fake.RunStub(next) + return fake.RunStub(req, next) } if specificReturn { - return ret.result1 + return ret.result1, ret.result2 } - return fake.runReturns.result1 + return fake.runReturns.result1, fake.runReturns.result2 } func (fake *FakeFilter) RunCallCount() int { @@ -104,29 +108,32 @@ func (fake *FakeFilter) RunCallCount() int { return len(fake.runArgsForCall) } -func (fake *FakeFilter) RunArgsForCall(i int) web.Handler { +func (fake *FakeFilter) RunArgsForCall(i int) (*web.Request, web.Handler) { fake.runMutex.RLock() defer fake.runMutex.RUnlock() - return fake.runArgsForCall[i].next + return fake.runArgsForCall[i].req, fake.runArgsForCall[i].next } -func (fake *FakeFilter) RunReturns(result1 web.Handler) { +func (fake *FakeFilter) RunReturns(result1 *web.Response, result2 error) { fake.RunStub = nil fake.runReturns = struct { - result1 web.Handler - }{result1} + result1 *web.Response + result2 error + }{result1, result2} } -func (fake *FakeFilter) RunReturnsOnCall(i int, result1 web.Handler) { +func (fake *FakeFilter) RunReturnsOnCall(i int, result1 *web.Response, result2 error) { fake.RunStub = nil if fake.runReturnsOnCall == nil { fake.runReturnsOnCall = make(map[int]struct { - result1 web.Handler + result1 *web.Response + result2 error }) } fake.runReturnsOnCall[i] = struct { - result1 web.Handler - }{result1} + result1 *web.Response + result2 error + }{result1, result2} } func (fake *FakeFilter) FilterMatchers() []web.FilterMatcher { diff --git a/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_token_data.go b/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_token_data.go new file mode 100644 index 00000000..7e446a5f --- /dev/null +++ b/vendor/github.com/Peripli/service-manager/pkg/web/webfakes/fake_token_data.go @@ -0,0 +1,98 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package webfakes + +import ( + "sync" + + "github.com/Peripli/service-manager/pkg/web" +) + +type FakeTokenData struct { + ClaimsStub func(v interface{}) error + claimsMutex sync.RWMutex + claimsArgsForCall []struct { + v interface{} + } + claimsReturns struct { + result1 error + } + claimsReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeTokenData) Claims(v interface{}) error { + fake.claimsMutex.Lock() + ret, specificReturn := fake.claimsReturnsOnCall[len(fake.claimsArgsForCall)] + fake.claimsArgsForCall = append(fake.claimsArgsForCall, struct { + v interface{} + }{v}) + fake.recordInvocation("Claims", []interface{}{v}) + fake.claimsMutex.Unlock() + if fake.ClaimsStub != nil { + return fake.ClaimsStub(v) + } + if specificReturn { + return ret.result1 + } + return fake.claimsReturns.result1 +} + +func (fake *FakeTokenData) ClaimsCallCount() int { + fake.claimsMutex.RLock() + defer fake.claimsMutex.RUnlock() + return len(fake.claimsArgsForCall) +} + +func (fake *FakeTokenData) ClaimsArgsForCall(i int) interface{} { + fake.claimsMutex.RLock() + defer fake.claimsMutex.RUnlock() + return fake.claimsArgsForCall[i].v +} + +func (fake *FakeTokenData) ClaimsReturns(result1 error) { + fake.ClaimsStub = nil + fake.claimsReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeTokenData) ClaimsReturnsOnCall(i int, result1 error) { + fake.ClaimsStub = nil + if fake.claimsReturnsOnCall == nil { + fake.claimsReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.claimsReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeTokenData) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.claimsMutex.RLock() + defer fake.claimsMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeTokenData) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ web.TokenData = new(FakeTokenData) diff --git a/vendor/github.com/Peripli/service-manager/security/basic/authenticator.go b/vendor/github.com/Peripli/service-manager/security/basic/authenticator.go index 80e5dac6..cceca3d8 100644 --- a/vendor/github.com/Peripli/service-manager/security/basic/authenticator.go +++ b/vendor/github.com/Peripli/service-manager/security/basic/authenticator.go @@ -22,6 +22,7 @@ import ( "net/http" "github.com/Peripli/service-manager/pkg/util" + "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/security" "github.com/Peripli/service-manager/storage" ) @@ -38,7 +39,7 @@ func NewAuthenticator(storage storage.Credentials, encrypter security.Encrypter) } // Authenticate authenticates by using the provided Basic credentials -func (a *Authenticator) Authenticate(request *http.Request) (*security.User, security.AuthenticationDecision, error) { +func (a *Authenticator) Authenticate(request *http.Request) (*web.User, security.AuthenticationDecision, error) { username, password, ok := request.BasicAuth() if !ok { return nil, security.Abstain, nil @@ -61,7 +62,7 @@ func (a *Authenticator) Authenticate(request *http.Request) (*security.User, sec return nil, security.Deny, nil } - return &security.User{ + return &web.User{ Name: username, }, security.Allow, nil } diff --git a/vendor/github.com/Peripli/service-manager/security/interfaces.go b/vendor/github.com/Peripli/service-manager/security/interfaces.go index 8f4378c2..edc8b863 100644 --- a/vendor/github.com/Peripli/service-manager/security/interfaces.go +++ b/vendor/github.com/Peripli/service-manager/security/interfaces.go @@ -20,6 +20,8 @@ package security import ( "context" "net/http" + + "github.com/Peripli/service-manager/pkg/web" ) // AuthenticationDecision represents a Authenticator decision to allow or deny authentication or to abstain from @@ -44,32 +46,20 @@ func (a AuthenticationDecision) String() string { return decisions[a] } -// User holds the information for the current user -type User struct { - Name string `json:"name"` -} - // Authenticator extracts the authenticator information from the request and // returns information about the current user or an error if security was not successful //go:generate counterfeiter . Authenticator type Authenticator interface { // Authenticate returns information about the user if security is successful, a bool specifying // whether the authenticator ran or not and an error if one occurs - Authenticate(req *http.Request) (*User, AuthenticationDecision, error) -} - -// Token interface provides means to unmarshal the claims in a struct -//go:generate counterfeiter . Token -type Token interface { - // Claims unmarshals the claims into the specified struct - Claims(v interface{}) error + Authenticate(req *http.Request) (*web.User, AuthenticationDecision, error) } // TokenVerifier attempts to verify a token and returns it or an error if the verification was not successful //go:generate counterfeiter . TokenVerifier type TokenVerifier interface { // Verify verifies that the token is valid and returns a token if so, otherwise returns an error - Verify(ctx context.Context, token string) (Token, error) + Verify(ctx context.Context, token string) (web.TokenData, error) } // Encrypter provides functionality to encrypt and decrypt data @@ -89,4 +79,4 @@ type KeyFetcher interface { //go:generate counterfeiter . KeySetter type KeySetter interface { SetEncryptionKey(key []byte) error -} \ No newline at end of file +} diff --git a/vendor/github.com/Peripli/service-manager/security/oidc/authenticator.go b/vendor/github.com/Peripli/service-manager/security/oidc/authenticator.go index 2ece90a3..fa3a5d66 100644 --- a/vendor/github.com/Peripli/service-manager/security/oidc/authenticator.go +++ b/vendor/github.com/Peripli/service-manager/security/oidc/authenticator.go @@ -14,7 +14,7 @@ * limitations under the License. */ -// Package oidc contains logic for setting up an oidc authenticator +// Package oidc contains logic for setting up an Open ID Connect authenticator package oidc import ( @@ -27,14 +27,11 @@ import ( "fmt" "github.com/Peripli/service-manager/pkg/util" + "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/security" - "github.com/coreos/go-oidc" - "github.com/sirupsen/logrus" + goidc "github.com/coreos/go-oidc" ) -// DoRequestFunc is an alias for any function that takes an http request and returns a response and error -type DoRequestFunc func(request *http.Request) (*http.Response, error) - type claims struct { UserID string `json:"user_id"` Username string `json:"user_name"` @@ -56,7 +53,7 @@ type Options struct { ClientID string // ReadConfigurationFunc is the function used to call the token issuer. If one is not provided, http.DefaultClient.Do will be used - ReadConfigurationFunc DoRequestFunc + ReadConfigurationFunc util.DoRequestFunc } // Authenticator is the OpenID implementation of security.Authenticator @@ -65,10 +62,9 @@ type Authenticator struct { } // NewAuthenticator returns a new OpenID authenticator or an error if one couldn't be configured -func NewAuthenticator(ctx context.Context, options Options) (*Authenticator, error) { - if options.IssuerURL == "" || options.ClientID == "" { - logrus.Warn("Missing config for OIDC authenticator") - return nil, errors.New("missing config for OIDC Authenticator") +func NewAuthenticator(ctx context.Context, options *Options) (*Authenticator, error) { + if options.IssuerURL == "" { + return nil, errors.New("missing issuer URL") } resp, err := getOpenIDConfig(ctx, options) if err != nil { @@ -84,17 +80,21 @@ func NewAuthenticator(ctx context.Context, options Options) (*Authenticator, err return nil, fmt.Errorf("error decoding body of response with status %s: %s", resp.Status, err.Error()) } - keySet := oidc.NewRemoteKeySet(ctx, p.JWKSURL) - cfg := &oidc.Config{ - ClientID: options.ClientID, - } + keySet := goidc.NewRemoteKeySet(ctx, p.JWKSURL) return &Authenticator{Verifier: &oidcVerifier{ - IDTokenVerifier: oidc.NewVerifier(p.Issuer, keySet, cfg), + IDTokenVerifier: goidc.NewVerifier(p.Issuer, keySet, newOIDCConfig(options)), }}, nil } +func newOIDCConfig(options *Options) *goidc.Config { + return &goidc.Config{ + ClientID: options.ClientID, + SkipClientIDCheck: options.ClientID == "", + } +} + // Authenticate returns information about the user by obtaining it from the bearer token, or an error if security is unsuccessful -func (a *Authenticator) Authenticate(request *http.Request) (*security.User, security.AuthenticationDecision, error) { +func (a *Authenticator) Authenticate(request *http.Request) (*web.User, security.AuthenticationDecision, error) { authorizationHeader := request.Header.Get("Authorization") if authorizationHeader == "" || !strings.HasPrefix(strings.ToLower(authorizationHeader), "bearer") { return nil, security.Abstain, nil @@ -114,14 +114,15 @@ func (a *Authenticator) Authenticate(request *http.Request) (*security.User, sec if err := idToken.Claims(claims); err != nil { return nil, security.Deny, err } - return &security.User{ - Name: claims.Username, + return &web.User{ + Name: claims.Username, + TokenData: idToken, }, security.Allow, nil } -func getOpenIDConfig(ctx context.Context, options Options) (*http.Response, error) { +func getOpenIDConfig(ctx context.Context, options *Options) (*http.Response, error) { // Work around for UAA until https://github.com/cloudfoundry/uaa/issues/805 is fixed - // Then oidc.NewProvider(ctx, options.IssuerURL) should be used + // Then goidc.NewProvider(ctx, options.IssuerURL) should be used if _, err := url.ParseRequestURI(options.IssuerURL); err != nil { return nil, err } @@ -131,7 +132,7 @@ func getOpenIDConfig(ctx context.Context, options Options) (*http.Response, erro return nil, err } - var readConfigFunc DoRequestFunc + var readConfigFunc util.DoRequestFunc if options.ReadConfigurationFunc != nil { readConfigFunc = options.ReadConfigurationFunc } else { diff --git a/vendor/github.com/Peripli/service-manager/security/oidc/authenticator_test.go b/vendor/github.com/Peripli/service-manager/security/oidc/authenticator_test.go index 2078027b..2e01fe2c 100644 --- a/vendor/github.com/Peripli/service-manager/security/oidc/authenticator_test.go +++ b/vendor/github.com/Peripli/service-manager/security/oidc/authenticator_test.go @@ -28,6 +28,9 @@ import ( "errors" + "github.com/Peripli/service-manager/pkg/util" + "github.com/Peripli/service-manager/pkg/web" + "github.com/Peripli/service-manager/pkg/web/webfakes" "github.com/Peripli/service-manager/security" "github.com/Peripli/service-manager/security/securityfakes" . "github.com/onsi/ginkgo" @@ -88,8 +91,8 @@ var _ = Describe("OIDC Authenticator", func() { var openIdResponseBody providerJSON var openIdResponseBodyBytes []byte - var readConfigFunc DoRequestFunc - var options Options + var readConfigFunc util.DoRequestFunc + var options *Options issuerPath := "/oauth/token" jwksPath := "/public_keys" @@ -115,7 +118,7 @@ var _ = Describe("OIDC Authenticator", func() { }) JustBeforeEach(func() { - options = Options{ + options = &Options{ ReadConfigurationFunc: readConfigFunc, IssuerURL: openidServer.URL(), ClientID: "client-id", @@ -236,7 +239,6 @@ var _ = Describe("OIDC Authenticator", func() { }) Context("When configuration is correct", func() { - BeforeEach(func() { openIdResponseCode = http.StatusOK }) @@ -247,6 +249,18 @@ var _ = Describe("OIDC Authenticator", func() { Expect(authenticator).To(Not(BeNil())) }) }) + + Context("newOIDCConfig", func() { + It("Should not skip client id check when client id is not empty", func() { + config := newOIDCConfig(&Options{ClientID: "client1"}) + Expect(config.SkipClientIDCheck).To(BeFalse()) + }) + + It("Should skip client id check when client id is empty", func() { + config := newOIDCConfig(&Options{ClientID: ""}) + Expect(config.SkipClientIDCheck).To(BeTrue()) + }) + }) }) }) @@ -255,7 +269,7 @@ var _ = Describe("OIDC Authenticator", func() { request *http.Request err error ) - validateAuthenticationReturns := func(expectedUser *security.User, expectedDecision security.AuthenticationDecision, expectedErr error) { + validateAuthenticationReturns := func(expectedUser *web.User, expectedDecision security.AuthenticationDecision, expectedErr error) { authenticator, _ := NewAuthenticator(ctx, options) user, decision, err := authenticator.Authenticate(request) @@ -340,7 +354,7 @@ var _ = Describe("OIDC Authenticator", func() { verifier.VerifyReturns(nil, expectedError) }) - It("should deby with an error", func() { + It("should deny with an error", func() { user, decision, err := authenticator.Authenticate(request) Expect(user).To(BeNil()) @@ -350,12 +364,12 @@ var _ = Describe("OIDC Authenticator", func() { }) Context("when returned token cannot extract claims", func() { - var fakeToken *securityfakes.FakeToken + var fakeToken *webfakes.FakeTokenData BeforeEach(func() { expectedError = fmt.Errorf("Claims extraction error") - fakeToken = &securityfakes.FakeToken{} + fakeToken = &webfakes.FakeTokenData{} fakeToken.ClaimsReturns(expectedError) verifier.VerifyReturns(fakeToken, nil) @@ -375,8 +389,8 @@ var _ = Describe("OIDC Authenticator", func() { expectedUserName := "test_user" BeforeEach(func() { - tokenJson := fmt.Sprintf("{\"user_name\": \"%s\"}", expectedUserName) - token := &securityfakes.FakeToken{} + tokenJson := fmt.Sprintf(`{"user_name": "%s", "abc": "xyz"}`, expectedUserName) + token := &webfakes.FakeTokenData{} token.ClaimsStub = func(v interface{}) error { return json.Unmarshal([]byte(tokenJson), v) } @@ -390,6 +404,13 @@ var _ = Describe("OIDC Authenticator", func() { Expect(user.Name).To(Equal(expectedUserName)) Expect(decision).To(Equal(security.Allow)) Expect(err).To(BeNil()) + + claims := struct { + Abc string + }{} + err = user.Claims(&claims) + Expect(err).To(BeNil()) + Expect(claims.Abc).To(Equal("xyz")) }) }) }) diff --git a/vendor/github.com/Peripli/service-manager/security/oidc/verifier.go b/vendor/github.com/Peripli/service-manager/security/oidc/verifier.go index 13088107..fa0cd606 100644 --- a/vendor/github.com/Peripli/service-manager/security/oidc/verifier.go +++ b/vendor/github.com/Peripli/service-manager/security/oidc/verifier.go @@ -19,7 +19,7 @@ package oidc import ( "context" - "github.com/Peripli/service-manager/security" + "github.com/Peripli/service-manager/pkg/web" "github.com/coreos/go-oidc" ) @@ -28,6 +28,6 @@ type oidcVerifier struct { } // Verify implements security.TokenVerifier and delegates to oidc.IDTokenVerifier -func (v *oidcVerifier) Verify(ctx context.Context, idToken string) (security.Token, error) { +func (v *oidcVerifier) Verify(ctx context.Context, idToken string) (web.TokenData, error) { return v.IDTokenVerifier.Verify(ctx, idToken) } diff --git a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_authenticator.go b/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_authenticator.go index 2d95a4dd..b32dcc6b 100644 --- a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_authenticator.go +++ b/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_authenticator.go @@ -5,22 +5,23 @@ import ( "net/http" "sync" + "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/security" ) type FakeAuthenticator struct { - AuthenticateStub func(req *http.Request) (*security.User, security.AuthenticationDecision, error) + AuthenticateStub func(req *http.Request) (*web.User, security.AuthenticationDecision, error) authenticateMutex sync.RWMutex authenticateArgsForCall []struct { req *http.Request } authenticateReturns struct { - result1 *security.User + result1 *web.User result2 security.AuthenticationDecision result3 error } authenticateReturnsOnCall map[int]struct { - result1 *security.User + result1 *web.User result2 security.AuthenticationDecision result3 error } @@ -28,7 +29,7 @@ type FakeAuthenticator struct { invocationsMutex sync.RWMutex } -func (fake *FakeAuthenticator) Authenticate(req *http.Request) (*security.User, security.AuthenticationDecision, error) { +func (fake *FakeAuthenticator) Authenticate(req *http.Request) (*web.User, security.AuthenticationDecision, error) { fake.authenticateMutex.Lock() ret, specificReturn := fake.authenticateReturnsOnCall[len(fake.authenticateArgsForCall)] fake.authenticateArgsForCall = append(fake.authenticateArgsForCall, struct { @@ -57,26 +58,26 @@ func (fake *FakeAuthenticator) AuthenticateArgsForCall(i int) *http.Request { return fake.authenticateArgsForCall[i].req } -func (fake *FakeAuthenticator) AuthenticateReturns(result1 *security.User, result2 security.AuthenticationDecision, result3 error) { +func (fake *FakeAuthenticator) AuthenticateReturns(result1 *web.User, result2 security.AuthenticationDecision, result3 error) { fake.AuthenticateStub = nil fake.authenticateReturns = struct { - result1 *security.User + result1 *web.User result2 security.AuthenticationDecision result3 error }{result1, result2, result3} } -func (fake *FakeAuthenticator) AuthenticateReturnsOnCall(i int, result1 *security.User, result2 security.AuthenticationDecision, result3 error) { +func (fake *FakeAuthenticator) AuthenticateReturnsOnCall(i int, result1 *web.User, result2 security.AuthenticationDecision, result3 error) { fake.AuthenticateStub = nil if fake.authenticateReturnsOnCall == nil { fake.authenticateReturnsOnCall = make(map[int]struct { - result1 *security.User + result1 *web.User result2 security.AuthenticationDecision result3 error }) } fake.authenticateReturnsOnCall[i] = struct { - result1 *security.User + result1 *web.User result2 security.AuthenticationDecision result3 error }{result1, result2, result3} diff --git a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token.go b/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token.go deleted file mode 100644 index a60ebdc9..00000000 --- a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token.go +++ /dev/null @@ -1,98 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package securityfakes - -import ( - "sync" - - "github.com/Peripli/service-manager/security" -) - -type FakeToken struct { - ClaimsStub func(v interface{}) error - claimsMutex sync.RWMutex - claimsArgsForCall []struct { - v interface{} - } - claimsReturns struct { - result1 error - } - claimsReturnsOnCall map[int]struct { - result1 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakeToken) Claims(v interface{}) error { - fake.claimsMutex.Lock() - ret, specificReturn := fake.claimsReturnsOnCall[len(fake.claimsArgsForCall)] - fake.claimsArgsForCall = append(fake.claimsArgsForCall, struct { - v interface{} - }{v}) - fake.recordInvocation("Claims", []interface{}{v}) - fake.claimsMutex.Unlock() - if fake.ClaimsStub != nil { - return fake.ClaimsStub(v) - } - if specificReturn { - return ret.result1 - } - return fake.claimsReturns.result1 -} - -func (fake *FakeToken) ClaimsCallCount() int { - fake.claimsMutex.RLock() - defer fake.claimsMutex.RUnlock() - return len(fake.claimsArgsForCall) -} - -func (fake *FakeToken) ClaimsArgsForCall(i int) interface{} { - fake.claimsMutex.RLock() - defer fake.claimsMutex.RUnlock() - return fake.claimsArgsForCall[i].v -} - -func (fake *FakeToken) ClaimsReturns(result1 error) { - fake.ClaimsStub = nil - fake.claimsReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeToken) ClaimsReturnsOnCall(i int, result1 error) { - fake.ClaimsStub = nil - if fake.claimsReturnsOnCall == nil { - fake.claimsReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.claimsReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeToken) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.claimsMutex.RLock() - defer fake.claimsMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakeToken) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ security.Token = new(FakeToken) diff --git a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token_verifier.go b/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token_verifier.go index 08feb99f..f0958983 100644 --- a/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token_verifier.go +++ b/vendor/github.com/Peripli/service-manager/security/securityfakes/fake_token_verifier.go @@ -5,29 +5,30 @@ import ( "context" "sync" + "github.com/Peripli/service-manager/pkg/web" "github.com/Peripli/service-manager/security" ) type FakeTokenVerifier struct { - VerifyStub func(ctx context.Context, token string) (security.Token, error) + VerifyStub func(ctx context.Context, token string) (web.TokenData, error) verifyMutex sync.RWMutex verifyArgsForCall []struct { ctx context.Context token string } verifyReturns struct { - result1 security.Token + result1 web.TokenData result2 error } verifyReturnsOnCall map[int]struct { - result1 security.Token + result1 web.TokenData result2 error } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } -func (fake *FakeTokenVerifier) Verify(ctx context.Context, token string) (security.Token, error) { +func (fake *FakeTokenVerifier) Verify(ctx context.Context, token string) (web.TokenData, error) { fake.verifyMutex.Lock() ret, specificReturn := fake.verifyReturnsOnCall[len(fake.verifyArgsForCall)] fake.verifyArgsForCall = append(fake.verifyArgsForCall, struct { @@ -57,24 +58,24 @@ func (fake *FakeTokenVerifier) VerifyArgsForCall(i int) (context.Context, string return fake.verifyArgsForCall[i].ctx, fake.verifyArgsForCall[i].token } -func (fake *FakeTokenVerifier) VerifyReturns(result1 security.Token, result2 error) { +func (fake *FakeTokenVerifier) VerifyReturns(result1 web.TokenData, result2 error) { fake.VerifyStub = nil fake.verifyReturns = struct { - result1 security.Token + result1 web.TokenData result2 error }{result1, result2} } -func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 security.Token, result2 error) { +func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 web.TokenData, result2 error) { fake.VerifyStub = nil if fake.verifyReturnsOnCall == nil { fake.verifyReturnsOnCall = make(map[int]struct { - result1 security.Token + result1 web.TokenData result2 error }) } fake.verifyReturnsOnCall[i] = struct { - result1 security.Token + result1 web.TokenData result2 error }{result1, result2} } diff --git a/vendor/github.com/Peripli/service-manager/server/server.go b/vendor/github.com/Peripli/service-manager/server/server.go deleted file mode 100644 index 37cfb1c9..00000000 --- a/vendor/github.com/Peripli/service-manager/server/server.go +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2018 The Service Manager Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Package server contains the logic of the Service Manager server and a mux router -package server - -import ( - "context" - "fmt" - "net/http" - "strconv" - "time" - - "github.com/Peripli/service-manager/api" - "github.com/Peripli/service-manager/pkg/web" - "github.com/gorilla/mux" - "github.com/sirupsen/logrus" -) - -// Settings type to be loaded from the environment -type Settings struct { - Port int `mapstructure:"port"` - RequestTimeout time.Duration `mapstructure:"request_timeout"` - ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout"` -} - -// Validate validates the server settings -func (s *Settings) Validate() error { - if s.Port == 0 { - return fmt.Errorf("validate Settings: Port missing") - } - if s.RequestTimeout == 0 { - return fmt.Errorf("validate Settings: RequestTimeout missing") - } - if s.ShutdownTimeout == 0 { - return fmt.Errorf("validate Settings: ShutdownTimeout missing") - } - return nil -} - -// Server is the server to process incoming HTTP requests -type Server struct { - Config Settings - Router *mux.Router - API *web.API -} - -// New creates a new server with the provided REST API configuration and server configuration -// Returns the new server and an error if creation was not successful -func New(config Settings, api *web.API) *Server { - router := mux.NewRouter().StrictSlash(true) - registerControllers(api, router) - - return &Server{ - Config: config, - Router: router, - API: api, - } -} - -// Run starts the server awaiting for incoming requests -func (s *Server) Run(ctx context.Context) { - handler := &http.Server{ - Handler: s.Router, - Addr: ":" + strconv.Itoa(s.Config.Port), - WriteTimeout: s.Config.RequestTimeout, - ReadTimeout: s.Config.RequestTimeout, - } - startServer(ctx, handler, s.Config.ShutdownTimeout) -} - -func registerControllers(API *web.API, router *mux.Router) { - for _, ctrl := range API.Controllers { - for _, route := range ctrl.Routes() { - logrus.Debugf("Registering endpoint: %s %s", route.Endpoint.Method, route.Endpoint.Path) - handler := web.Filters(API.Filters).ChainMatching(route) - router.Handle(route.Endpoint.Path, api.NewHTTPHandler(handler)).Methods(route.Endpoint.Method) - } - } -} - -func startServer(ctx context.Context, server *http.Server, shutdownTimeout time.Duration) { - go gracefulShutdown(ctx, server, shutdownTimeout) - - logrus.Infof("Listening on %s", server.Addr) - - if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - logrus.Fatal(err) - } -} - -func gracefulShutdown(ctx context.Context, server *http.Server, shutdownTimeout time.Duration) { - <-ctx.Done() - - c, cancel := context.WithTimeout(context.Background(), shutdownTimeout) - defer cancel() - logrus.Debugf("Shutdown with timeout: %s", shutdownTimeout) - - if err := server.Shutdown(c); err != nil { - logrus.Error("Error: ", err) - if err := server.Close(); err != nil { - logrus.Error("Error: ", err) - } - } else { - logrus.Debug("Server stopped") - } -} diff --git a/vendor/github.com/Peripli/service-manager/server/server_test.go b/vendor/github.com/Peripli/service-manager/server/server_test.go deleted file mode 100644 index 1e936112..00000000 --- a/vendor/github.com/Peripli/service-manager/server/server_test.go +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018 The Service Manager Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package server - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/Peripli/service-manager/api/filters" - "github.com/Peripli/service-manager/pkg/web" - "github.com/gavv/httpexpect" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestServer(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Server Suite") -} - -var sm *httpexpect.Expect - -var _ = Describe("Server", func() { - - BeforeSuite(func() { - api := &web.API{} - route := web.Route{ - Endpoint: web.Endpoint{ - Path: "/", - Method: http.MethodGet, - }, - Handler: testHandler, - } - testCtl := &testController{} - testCtl.RegisterRoutes(route) - api.RegisterControllers(testCtl) - api.RegisterFilters(&testFilter{}) - serverSettings := Settings{ - Port: 0, - RequestTimeout: time.Second * 3, - ShutdownTimeout: time.Second * 3, - } - server := New(serverSettings, api) - server.Router.Use(filters.NewRecoveryMiddleware()) - Expect(server).ToNot(BeNil()) - testServer := httptest.NewServer(server.Router) - sm = httpexpect.New(GinkgoT(), testServer.URL) - }) - - Describe("Panic Recovery", func() { - Context("when controller has panicing http.handler", func() { - It("should return 500", func() { - assertRecover("fail=true") - }) - }) - - Context("when controller has panicing filter before delegating to next handler", func() { - It("should return 500", func() { - assertRecover("filter_fail_before=true") - }) - }) - - Context("when controller has panicing filter after delegating to next handler", func() { - It("should return 500", func() { - assertRecover("filter_fail_after=true") - }) - }) - }) - -}) - -func assertRecover(query string) { - sm.GET("/").Expect().Status(http.StatusOK) - sm.GET("/").WithQueryString(query).Expect().Status(http.StatusInternalServerError) - sm.GET("/").Expect().Status(http.StatusOK) -} - -type testController struct { - testRoutes []web.Route -} - -func (t *testController) RegisterRoutes(routes ...web.Route) { - t.testRoutes = append(t.testRoutes, routes...) -} - -func (t *testController) Routes() []web.Route { - return t.testRoutes -} - -type testFilter struct { -} - -func (tf testFilter) Name() string { - return "testFilter" -} - -func (tf testFilter) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - if request.URL.Query().Get("filter_fail_before") == "true" { - panic("expected") - } - res, err := next.Handle(request) - if request.URL.Query().Get("filter_fail_after") == "true" { - panic("expected") - } - return res, err - }) -} - -func (tf testFilter) FilterMatchers() []web.FilterMatcher { - return []web.FilterMatcher{ - { - Matchers: []web.Matcher{ - web.Path("**"), - }, - }, - } -} - -func testHandler(req *web.Request) (*web.Response, error) { - if req.URL.Query().Get("fail") == "true" { - panic("expected") - } - return &web.Response{ - StatusCode: http.StatusOK, - }, nil -} diff --git a/vendor/github.com/Peripli/service-manager/storage/interfaces.go b/vendor/github.com/Peripli/service-manager/storage/interfaces.go index a3f826a9..df3f1113 100644 --- a/vendor/github.com/Peripli/service-manager/storage/interfaces.go +++ b/vendor/github.com/Peripli/service-manager/storage/interfaces.go @@ -18,6 +18,7 @@ package storage import ( + "context" "fmt" "github.com/Peripli/service-manager/pkg/types" @@ -29,6 +30,13 @@ type Settings struct { URI string } +// DefaultSettings returns default values for storage settings +func DefaultSettings() *Settings { + return &Settings{ + URI: "", + } +} + // Validate validates the storage settings func (s *Settings) Validate() error { if len(s.URI) == 0 { @@ -63,7 +71,6 @@ type Storage interface { } // Broker interface for Broker db operations -//go:generate counterfeiter . Broker type Broker interface { // Create stores a broker in SM DB Create(broker *types.Broker) error @@ -82,7 +89,6 @@ type Broker interface { } // Platform interface for Platform db operations -//go:generate counterfeiter . Platform type Platform interface { // Create stores a platform in SM DB Create(platform *types.Platform) error @@ -107,9 +113,14 @@ type Credentials interface { } // Security interface for encryption key operations -type Security interface{ +type Security interface { + // Lock locks the storage so that only one process can manipulate the encryption key. + // Returns an error if the process has already acquired the lock + Lock(ctx context.Context) error + // Unlock releases the acquired lock. + Unlock() error // Fetcher provides means to obtain the encryption key Fetcher() security.KeyFetcher // Setter provides means to change the encryption key Setter() security.KeySetter -} \ No newline at end of file +} diff --git a/vendor/github.com/Peripli/service-manager/storage/postgres/broker.go b/vendor/github.com/Peripli/service-manager/storage/postgres/broker.go index b6aba2f0..99ede569 100644 --- a/vendor/github.com/Peripli/service-manager/storage/postgres/broker.go +++ b/vendor/github.com/Peripli/service-manager/storage/postgres/broker.go @@ -27,7 +27,6 @@ type brokerStorage struct { func (bs *brokerStorage) Create(broker *types.Broker) error { return create(bs.db, brokerTable, convertBrokerToDTO(broker)) - } func (bs *brokerStorage) Get(id string) (*types.Broker, error) { diff --git a/vendor/github.com/Peripli/service-manager/storage/postgres/security.go b/vendor/github.com/Peripli/service-manager/storage/postgres/security.go index 16d1bae7..43a64a8b 100644 --- a/vendor/github.com/Peripli/service-manager/storage/postgres/security.go +++ b/vendor/github.com/Peripli/service-manager/storage/postgres/security.go @@ -17,7 +17,9 @@ package postgres import ( + "context" "fmt" + "sync" "time" "github.com/Peripli/service-manager/security" @@ -25,9 +27,43 @@ import ( "github.com/sirupsen/logrus" ) +const securityLockIndex = 111 + type securityStorage struct { db *sqlx.DB encryptionKey []byte + isLocked bool + mutex *sync.Mutex +} + +// Lock acquires a database lock so that only one process can manipulate the encryption key. +// Returns an error if the process has already acquired the lock +func (s *securityStorage) Lock(ctx context.Context) error { + s.mutex.Lock() + defer s.mutex.Unlock() + if s.isLocked { + return fmt.Errorf("Lock is already acquired") + } + if _, err := s.db.ExecContext(ctx, "SELECT pg_advisory_lock($1)", securityLockIndex); err != nil { + return err + } + s.isLocked = true + return nil +} + +// Unlock releases the database lock. +func (s *securityStorage) Unlock() error { + s.mutex.Lock() + defer s.mutex.Unlock() + if !s.isLocked { + return nil + } + + if _, err := s.db.Exec("SELECT pg_advisory_unlock($1)", securityLockIndex); err != nil { + return err + } + s.isLocked = false + return nil } // Fetcher returns a KeyFetcher configured to fetch a key from the database diff --git a/vendor/github.com/Peripli/service-manager/storage/postgres/security_test.go b/vendor/github.com/Peripli/service-manager/storage/postgres/security_test.go index 04580b03..e4e87ec4 100644 --- a/vendor/github.com/Peripli/service-manager/storage/postgres/security_test.go +++ b/vendor/github.com/Peripli/service-manager/storage/postgres/security_test.go @@ -17,10 +17,12 @@ package postgres import ( + "context" "crypto/rand" "database/sql" "fmt" - "time" + "sync" + "time" "github.com/DATA-DOG/go-sqlmock" "github.com/Peripli/service-manager/security" @@ -159,4 +161,73 @@ var _ = Describe("Security", func() { }) }) }) + + Describe("Locking", func() { + var mockdb *sql.DB + var mock sqlmock.Sqlmock + var storage *securityStorage + envEncryptionKey := make([]byte, 32) + + JustBeforeEach(func() { + storage = &securityStorage{ + db: sqlx.NewDb(mockdb, "sqlmock"), + encryptionKey: envEncryptionKey, + isLocked: false, + mutex: &sync.Mutex{}, + } + }) + BeforeEach(func() { + mockdb, mock, _ = sqlmock.New() + rand.Read(envEncryptionKey) + }) + AfterEach(func() { + mockdb.Close() + }) + + Describe("Lock", func() { + + Context("When lock is already acquired", func() { + It("Should return an error", func() { + storage.isLocked = true + err := storage.Lock(context.TODO()) + Expect(err).ToNot(BeNil()) + }) + }) + + Context("When lock is not yet acquired", func() { + AfterEach(func() { + storage.Unlock() + }) + BeforeEach(func() { + mock.ExpectExec("SELECT").WillReturnResult(sqlmock.NewResult(int64(1), int64(1))) + }) + It("Should acquire lock", func() { + err := storage.Lock(context.TODO()) + Expect(err).To(BeNil()) + Expect(storage.isLocked).To(Equal(true)) + }) + }) + }) + + Describe("Unlock", func() { + Context("When lock is not acquired", func() { + It("Should return nil", func() { + storage.isLocked = false + err := storage.Unlock() + Expect(err).To(BeNil()) + }) + }) + Context("When lock is acquired", func() { + BeforeEach(func() { + mock.ExpectExec("SELECT").WillReturnResult(sqlmock.NewResult(int64(1), int64(1))) + }) + It("Should release lock", func() { + storage.isLocked = true + err := storage.Unlock() + Expect(err).To(BeNil()) + Expect(storage.isLocked).To(Equal(false)) + }) + }) + }) + }) }) diff --git a/vendor/github.com/Peripli/service-manager/storage/postgres/storage.go b/vendor/github.com/Peripli/service-manager/storage/postgres/storage.go index 8a1ea217..2621ffd9 100644 --- a/vendor/github.com/Peripli/service-manager/storage/postgres/storage.go +++ b/vendor/github.com/Peripli/service-manager/storage/postgres/storage.go @@ -18,11 +18,10 @@ package postgres import ( + "fmt" "sync" "time" - "fmt" - "github.com/Peripli/service-manager/storage" "github.com/golang-migrate/migrate" migratepg "github.com/golang-migrate/migrate/database/postgres" @@ -39,9 +38,10 @@ func init() { } type postgresStorage struct { - db *sqlx.DB - state *storageState + db *sqlx.DB + state *storageState encryptionKey []byte + mutex *sync.Mutex } func (storage *postgresStorage) checkOpen() { @@ -72,9 +72,9 @@ func (storage *postgresStorage) Credentials() storage.Credentials { return &credentialStorage{storage.db} } -func (storage *postgresStorage) Security() storage.Security{ +func (storage *postgresStorage) Security() storage.Security { storage.checkOpen() - return &securityStorage{storage.db, storage.encryptionKey} + return &securityStorage{storage.db, storage.encryptionKey, false, storage.mutex} } func (storage *postgresStorage) Open(uri string, encryptionKey []byte) error { @@ -94,6 +94,7 @@ func (storage *postgresStorage) Open(uri string, encryptionKey []byte) error { db: storage.db, storageCheckInterval: time.Second * 5, } + storage.mutex = &sync.Mutex{} storage.encryptionKey = encryptionKey logrus.Debug("Updating database schema") if err := updateSchema(storage.db); err != nil { diff --git a/vendor/github.com/Peripli/service-manager/storage/registry_test.go b/vendor/github.com/Peripli/service-manager/storage/registry_test.go index 2d013b17..beaa90da 100644 --- a/vendor/github.com/Peripli/service-manager/storage/registry_test.go +++ b/vendor/github.com/Peripli/service-manager/storage/registry_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + "sync" + "github.com/Peripli/service-manager/storage" "github.com/Peripli/service-manager/storage/storagefakes" "github.com/sirupsen/logrus" @@ -37,6 +39,7 @@ func TestStorage(t *testing.T) { type logInterceptor struct { data string + lock sync.RWMutex } func (*logInterceptor) Levels() []logrus.Level { @@ -44,11 +47,17 @@ func (*logInterceptor) Levels() []logrus.Level { } func (interceptor *logInterceptor) Fire(e *logrus.Entry) (err error) { + interceptor.lock.Lock() + defer interceptor.lock.Unlock() + interceptor.data, err = e.String() return } func (interceptor *logInterceptor) VerifyData(emptyData bool) { + interceptor.lock.Lock() + defer interceptor.lock.Unlock() + if emptyData { Eventually(interceptor.data).Should(BeEmpty()) } else { diff --git a/vendor/github.com/Peripli/service-manager/storage/storagefakes/fake_platform.go b/vendor/github.com/Peripli/service-manager/storage/storagefakes/fake_platform.go deleted file mode 100644 index 94b1856e..00000000 --- a/vendor/github.com/Peripli/service-manager/storage/storagefakes/fake_platform.go +++ /dev/null @@ -1,343 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package storagefakes - -import ( - "sync" - - "github.com/Peripli/service-manager/pkg/types" - "github.com/Peripli/service-manager/storage" -) - -type FakePlatform struct { - CreateStub func(platform *types.Platform) error - createMutex sync.RWMutex - createArgsForCall []struct { - platform *types.Platform - } - createReturns struct { - result1 error - } - createReturnsOnCall map[int]struct { - result1 error - } - GetStub func(id string) (*types.Platform, error) - getMutex sync.RWMutex - getArgsForCall []struct { - id string - } - getReturns struct { - result1 *types.Platform - result2 error - } - getReturnsOnCall map[int]struct { - result1 *types.Platform - result2 error - } - GetAllStub func() ([]*types.Platform, error) - getAllMutex sync.RWMutex - getAllArgsForCall []struct{} - getAllReturns struct { - result1 []*types.Platform - result2 error - } - getAllReturnsOnCall map[int]struct { - result1 []*types.Platform - result2 error - } - DeleteStub func(id string) error - deleteMutex sync.RWMutex - deleteArgsForCall []struct { - id string - } - deleteReturns struct { - result1 error - } - deleteReturnsOnCall map[int]struct { - result1 error - } - UpdateStub func(platform *types.Platform) error - updateMutex sync.RWMutex - updateArgsForCall []struct { - platform *types.Platform - } - updateReturns struct { - result1 error - } - updateReturnsOnCall map[int]struct { - result1 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakePlatform) Create(platform *types.Platform) error { - fake.createMutex.Lock() - ret, specificReturn := fake.createReturnsOnCall[len(fake.createArgsForCall)] - fake.createArgsForCall = append(fake.createArgsForCall, struct { - platform *types.Platform - }{platform}) - fake.recordInvocation("Create", []interface{}{platform}) - fake.createMutex.Unlock() - if fake.CreateStub != nil { - return fake.CreateStub(platform) - } - if specificReturn { - return ret.result1 - } - return fake.createReturns.result1 -} - -func (fake *FakePlatform) CreateCallCount() int { - fake.createMutex.RLock() - defer fake.createMutex.RUnlock() - return len(fake.createArgsForCall) -} - -func (fake *FakePlatform) CreateArgsForCall(i int) *types.Platform { - fake.createMutex.RLock() - defer fake.createMutex.RUnlock() - return fake.createArgsForCall[i].platform -} - -func (fake *FakePlatform) CreateReturns(result1 error) { - fake.CreateStub = nil - fake.createReturns = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) CreateReturnsOnCall(i int, result1 error) { - fake.CreateStub = nil - if fake.createReturnsOnCall == nil { - fake.createReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.createReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) Get(id string) (*types.Platform, error) { - fake.getMutex.Lock() - ret, specificReturn := fake.getReturnsOnCall[len(fake.getArgsForCall)] - fake.getArgsForCall = append(fake.getArgsForCall, struct { - id string - }{id}) - fake.recordInvocation("Get", []interface{}{id}) - fake.getMutex.Unlock() - if fake.GetStub != nil { - return fake.GetStub(id) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fake.getReturns.result1, fake.getReturns.result2 -} - -func (fake *FakePlatform) GetCallCount() int { - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - return len(fake.getArgsForCall) -} - -func (fake *FakePlatform) GetArgsForCall(i int) string { - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - return fake.getArgsForCall[i].id -} - -func (fake *FakePlatform) GetReturns(result1 *types.Platform, result2 error) { - fake.GetStub = nil - fake.getReturns = struct { - result1 *types.Platform - result2 error - }{result1, result2} -} - -func (fake *FakePlatform) GetReturnsOnCall(i int, result1 *types.Platform, result2 error) { - fake.GetStub = nil - if fake.getReturnsOnCall == nil { - fake.getReturnsOnCall = make(map[int]struct { - result1 *types.Platform - result2 error - }) - } - fake.getReturnsOnCall[i] = struct { - result1 *types.Platform - result2 error - }{result1, result2} -} - -func (fake *FakePlatform) GetAll() ([]*types.Platform, error) { - fake.getAllMutex.Lock() - ret, specificReturn := fake.getAllReturnsOnCall[len(fake.getAllArgsForCall)] - fake.getAllArgsForCall = append(fake.getAllArgsForCall, struct{}{}) - fake.recordInvocation("GetAll", []interface{}{}) - fake.getAllMutex.Unlock() - if fake.GetAllStub != nil { - return fake.GetAllStub() - } - if specificReturn { - return ret.result1, ret.result2 - } - return fake.getAllReturns.result1, fake.getAllReturns.result2 -} - -func (fake *FakePlatform) GetAllCallCount() int { - fake.getAllMutex.RLock() - defer fake.getAllMutex.RUnlock() - return len(fake.getAllArgsForCall) -} - -func (fake *FakePlatform) GetAllReturns(result1 []*types.Platform, result2 error) { - fake.GetAllStub = nil - fake.getAllReturns = struct { - result1 []*types.Platform - result2 error - }{result1, result2} -} - -func (fake *FakePlatform) GetAllReturnsOnCall(i int, result1 []*types.Platform, result2 error) { - fake.GetAllStub = nil - if fake.getAllReturnsOnCall == nil { - fake.getAllReturnsOnCall = make(map[int]struct { - result1 []*types.Platform - result2 error - }) - } - fake.getAllReturnsOnCall[i] = struct { - result1 []*types.Platform - result2 error - }{result1, result2} -} - -func (fake *FakePlatform) Delete(id string) error { - fake.deleteMutex.Lock() - ret, specificReturn := fake.deleteReturnsOnCall[len(fake.deleteArgsForCall)] - fake.deleteArgsForCall = append(fake.deleteArgsForCall, struct { - id string - }{id}) - fake.recordInvocation("Delete", []interface{}{id}) - fake.deleteMutex.Unlock() - if fake.DeleteStub != nil { - return fake.DeleteStub(id) - } - if specificReturn { - return ret.result1 - } - return fake.deleteReturns.result1 -} - -func (fake *FakePlatform) DeleteCallCount() int { - fake.deleteMutex.RLock() - defer fake.deleteMutex.RUnlock() - return len(fake.deleteArgsForCall) -} - -func (fake *FakePlatform) DeleteArgsForCall(i int) string { - fake.deleteMutex.RLock() - defer fake.deleteMutex.RUnlock() - return fake.deleteArgsForCall[i].id -} - -func (fake *FakePlatform) DeleteReturns(result1 error) { - fake.DeleteStub = nil - fake.deleteReturns = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) DeleteReturnsOnCall(i int, result1 error) { - fake.DeleteStub = nil - if fake.deleteReturnsOnCall == nil { - fake.deleteReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.deleteReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) Update(platform *types.Platform) error { - fake.updateMutex.Lock() - ret, specificReturn := fake.updateReturnsOnCall[len(fake.updateArgsForCall)] - fake.updateArgsForCall = append(fake.updateArgsForCall, struct { - platform *types.Platform - }{platform}) - fake.recordInvocation("Update", []interface{}{platform}) - fake.updateMutex.Unlock() - if fake.UpdateStub != nil { - return fake.UpdateStub(platform) - } - if specificReturn { - return ret.result1 - } - return fake.updateReturns.result1 -} - -func (fake *FakePlatform) UpdateCallCount() int { - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - return len(fake.updateArgsForCall) -} - -func (fake *FakePlatform) UpdateArgsForCall(i int) *types.Platform { - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - return fake.updateArgsForCall[i].platform -} - -func (fake *FakePlatform) UpdateReturns(result1 error) { - fake.UpdateStub = nil - fake.updateReturns = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) UpdateReturnsOnCall(i int, result1 error) { - fake.UpdateStub = nil - if fake.updateReturnsOnCall == nil { - fake.updateReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.updateReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakePlatform) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.createMutex.RLock() - defer fake.createMutex.RUnlock() - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - fake.getAllMutex.RLock() - defer fake.getAllMutex.RUnlock() - fake.deleteMutex.RLock() - defer fake.deleteMutex.RUnlock() - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakePlatform) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ storage.Platform = new(FakePlatform) diff --git a/vendor/github.com/Peripli/service-manager/test/auth_test/auth_test.go b/vendor/github.com/Peripli/service-manager/test/auth_test/auth_test.go index 6b6dd4cf..dbbba5f7 100644 --- a/vendor/github.com/Peripli/service-manager/test/auth_test/auth_test.go +++ b/vendor/github.com/Peripli/service-manager/test/auth_test/auth_test.go @@ -49,7 +49,7 @@ var _ = Describe("Service Manager Authentication", func() { BeforeSuite(func() { os.Chdir("../..") - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { diff --git a/vendor/github.com/Peripli/service-manager/test/broker_test/broker_test.go b/vendor/github.com/Peripli/service-manager/test/broker_test/broker_test.go index 2afe9c8a..e3b93cbe 100644 --- a/vendor/github.com/Peripli/service-manager/test/broker_test/broker_test.go +++ b/vendor/github.com/Peripli/service-manager/test/broker_test/broker_test.go @@ -27,6 +27,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/ghttp" + "github.com/spf13/cast" ) func TestBrokers(t *testing.T) { @@ -50,7 +51,7 @@ var _ = Describe("Service Manager Broker API", func() { BeforeSuite(func() { os.Chdir("../..") - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { @@ -277,15 +278,35 @@ var _ = Describe("Service Manager Broker API", func() { }) Context("when request is successful", func() { - It("returns 201", func() { - ctx.SMWithOAuth.POST("/v1/service_brokers").WithJSON(testBroker). - Expect(). - Status(http.StatusCreated). - JSON().Object(). - ContainsMap(expectedBroker). - Keys().NotContains("catalog", "credentials") + assertPOSTReturns201 := func() { + It("returns 201", func() { + ctx.SMWithOAuth.POST("/v1/service_brokers").WithJSON(testBroker). + Expect(). + Status(http.StatusCreated). + JSON().Object(). + ContainsMap(expectedBroker). + Keys().NotContains("catalog", "credentials") - common.VerifyBrokerCatalogEndpointInvoked(brokerServer, 1) + common.VerifyBrokerCatalogEndpointInvoked(brokerServer, 1) + }) + } + + Context("when broker URL does not end with trailing slash", func() { + BeforeEach(func() { + testBroker["broker_url"] = strings.TrimRight(cast.ToString(testBroker["broker_url"]), "/") + expectedBroker["broker_url"] = strings.TrimRight(cast.ToString(expectedBroker["broker_url"]), "/") + }) + + assertPOSTReturns201() + }) + + Context("when broker URL ends with trailing slash", func() { + BeforeEach(func() { + testBroker["broker_url"] = cast.ToString(testBroker["broker_url"]) + "/" + expectedBroker["broker_url"] = cast.ToString(expectedBroker["broker_url"]) + "/" + }) + + assertPOSTReturns201() }) }) diff --git a/vendor/github.com/Peripli/service-manager/test/catalog_test/catalog_test.go b/vendor/github.com/Peripli/service-manager/test/catalog_test/catalog_test.go index e32debe0..e59a41b5 100644 --- a/vendor/github.com/Peripli/service-manager/test/catalog_test/catalog_test.go +++ b/vendor/github.com/Peripli/service-manager/test/catalog_test/catalog_test.go @@ -51,7 +51,7 @@ var _ = Describe("Service Manager Aggregated Catalog API", func() { BeforeSuite(func() { os.Chdir("../..") - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { diff --git a/vendor/github.com/Peripli/service-manager/test/common/application.yml b/vendor/github.com/Peripli/service-manager/test/common/application.yml index 823d8925..0473c6f3 100644 --- a/vendor/github.com/Peripli/service-manager/test/common/application.yml +++ b/vendor/github.com/Peripli/service-manager/test/common/application.yml @@ -10,5 +10,6 @@ storage: api: # token_issuer_url: https://uaa.local.pcfdev.io client_id: sm + skip_ssl_validation: false security: encryption_key: ejHjRNHbS0NaqARSRvnweVV9zcmhQEa8 diff --git a/vendor/github.com/Peripli/service-manager/test/common/common.go b/vendor/github.com/Peripli/service-manager/test/common/common.go index d921d1e3..0e4b93ee 100644 --- a/vendor/github.com/Peripli/service-manager/test/common/common.go +++ b/vendor/github.com/Peripli/service-manager/test/common/common.go @@ -33,6 +33,9 @@ import ( "strings" "bytes" + "io" + "io/ioutil" + "github.com/Peripli/service-manager/pkg/types" "github.com/gavv/httpexpect" "github.com/gbrlsnchs/jwt" @@ -41,8 +44,6 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/ghttp" - "io" - "io/ioutil" ) type Object = map[string]interface{} @@ -136,30 +137,48 @@ func setResponse(rw http.ResponseWriter, status int, message, brokerID string) { rw.Write([]byte(message)) } -func SetupFakeServiceBrokerServer(brokerID string) *httptest.Server { +func SetupFakeServiceBrokerServerWithPrefix(brokerID, prefix string) *httptest.Server { router := mux.NewRouter() - router.HandleFunc("/v2/catalog", func(rw http.ResponseWriter, req *http.Request) { + router.HandleFunc(prefix+"/v2/catalog", func(rw http.ResponseWriter, req *http.Request) { setResponse(rw, http.StatusOK, Catalog, brokerID) }) - router.HandleFunc("/v2/service_instances/{instance_id}", func(rw http.ResponseWriter, req *http.Request) { + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}", func(rw http.ResponseWriter, req *http.Request) { setResponse(rw, http.StatusCreated, "{}", brokerID) }).Methods("PUT") - router.HandleFunc("/v2/service_instances/{instance_id}", func(rw http.ResponseWriter, req *http.Request) { + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}", func(rw http.ResponseWriter, req *http.Request) { setResponse(rw, http.StatusOK, "{}", brokerID) }).Methods("DELETE") - router.HandleFunc("/v2/service_instances/{instance_id}/service_bindings/{binding_id}", func(rw http.ResponseWriter, req *http.Request) { + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}/service_bindings/{binding_id}", func(rw http.ResponseWriter, req *http.Request) { response := fmt.Sprintf(`{"credentials": {"instance_id": "%s" , "binding_id": "%s"}}`, mux.Vars(req)["instance_id"], mux.Vars(req)["binding_id"]) setResponse(rw, http.StatusCreated, response, brokerID) }).Methods("PUT") - router.HandleFunc("/v2/service_instances/{instance_id}/service_bindings/{binding_id}", func(rw http.ResponseWriter, req *http.Request) { + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}/service_bindings/{binding_id}", func(rw http.ResponseWriter, req *http.Request) { setResponse(rw, http.StatusOK, "{}", brokerID) }).Methods("DELETE") - return httptest.NewServer(router) + + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}/last_operation", func(rw http.ResponseWriter, req *http.Request) { + setResponse(rw, http.StatusOK, `{"state": "succeeded"}`, brokerID) + }).Methods("GET") + + router.HandleFunc(prefix+"/v2/service_instances/{instance_id}/service_bindings/{binding_id}/last_operation", func(rw http.ResponseWriter, req *http.Request) { + setResponse(rw, http.StatusOK, `{"state": "succeeded"}`, brokerID) + }).Methods("GET") + + server := httptest.NewServer(router) + if prefix != "" { + server.URL = server.URL + prefix + } + + return server +} + +func SetupFakeServiceBrokerServer(brokerID string) *httptest.Server { + return SetupFakeServiceBrokerServerWithPrefix(brokerID, "") } func SetupFakeFailingBrokerServer(brokerID string) *httptest.Server { diff --git a/vendor/github.com/Peripli/service-manager/test/common/test_context.go b/vendor/github.com/Peripli/service-manager/test/common/test_context.go index 4e3f6a17..1269535f 100644 --- a/vendor/github.com/Peripli/service-manager/test/common/test_context.go +++ b/vendor/github.com/Peripli/service-manager/test/common/test_context.go @@ -70,8 +70,8 @@ func NewTestContext(smURL, tokenIssuerURL string) *TestContext { } } -func NewTestContextFromAPIs(additionalAPIs ...*web.API) *TestContext { - ctx, cancel := context.WithCancel(context.Background()) +func NewTestContextFromAPIs(plugins []web.Plugin, additionalAPIs ...*web.API) *TestContext { + ctx, _ := context.WithCancel(context.Background()) mockOauthServer := SetupFakeOAuthServer() env := sm.DefaultEnv(func(set *pflag.FlagSet) { @@ -79,11 +79,12 @@ func NewTestContextFromAPIs(additionalAPIs ...*web.API) *TestContext { set.Set("api.token_issuer_url", mockOauthServer.URL) }) - smanagerBuilder := sm.New(ctx, cancel, env) + smanagerBuilder := sm.New(ctx, env) for _, additionalAPI := range additionalAPIs { smanagerBuilder.RegisterControllers(additionalAPI.Controllers...) smanagerBuilder.RegisterFilters(additionalAPI.Filters...) } + smanagerBuilder.RegisterPlugins(plugins...) serviceManager := smanagerBuilder.Build() smServer := httptest.NewServer(serviceManager.Server.Router) @@ -94,7 +95,6 @@ type TestContext struct { SM *httpexpect.Expect SMWithOAuth *httpexpect.Expect SMWithBasic *httpexpect.Expect - SMServer *httptest.Server brokers map[string]*Broker } @@ -123,10 +123,9 @@ func (ctx *TestContext) Cleanup() { return } - if ctx.SMServer != nil { + if ctx.SMWithOAuth != nil { RemoveAllBrokers(ctx.SMWithOAuth) RemoveAllPlatforms(ctx.SMWithOAuth) - ctx.SMServer.Close() } for _, broker := range ctx.brokers { diff --git a/vendor/github.com/Peripli/service-manager/test/filter_test/filter_test.go b/vendor/github.com/Peripli/service-manager/test/filter_test/filter_test.go index 90828df4..0405464c 100644 --- a/vendor/github.com/Peripli/service-manager/test/filter_test/filter_test.go +++ b/vendor/github.com/Peripli/service-manager/test/filter_test/filter_test.go @@ -29,8 +29,8 @@ var _ = Describe("Service Manager Filters", func() { JustBeforeEach(func() { api := &web.API{} api.RegisterFilters(testFilters...) - ctx = common.NewTestContextFromAPIs(api) - testBroker = ctx.RegisterBroker("broker1", nil) + ctx = common.NewTestContextFromAPIs(nil, api) + testBroker = ctx.RegisterBroker("broker1", nil) order = "" }) @@ -115,15 +115,13 @@ func (tf osbTestFilter) FilterMatchers() []web.FilterMatcher { } } -func (tf osbTestFilter) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request)(*web.Response,error) { +func (tf osbTestFilter) Run(request *web.Request, next web.Handler) (*web.Response, error) { *tf.state += "osb1" res, err := next.Handle(request) if err == nil { *tf.state += "osb2" } return res, err - }) } type globalTestFilterA struct { @@ -144,15 +142,13 @@ func (gfa globalTestFilterA) FilterMatchers() []web.FilterMatcher { } } -func (gfa globalTestFilterA) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request)(*web.Response,error) { +func (gfa globalTestFilterA) Run(request *web.Request, next web.Handler) (*web.Response,error) { *gfa.state += "a1" res, err := next.Handle(request) if err == nil { *gfa.state += "a2" } return res, err - }) } type globalTestFilterB struct { @@ -173,14 +169,12 @@ func (gfb globalTestFilterB) FilterMatchers() []web.FilterMatcher { } } -func (gfb globalTestFilterB) Run(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request)(*web.Response,error) { +func (gfb globalTestFilterB) Run(request *web.Request, next web.Handler) (*web.Response,error) { *gfb.state += "b1" res, err := next.Handle(request) if err == nil { *gfb.state += "b2" } return res, err - }) } diff --git a/vendor/github.com/Peripli/service-manager/test/healthcheck_test/healthcheck_test.go b/vendor/github.com/Peripli/service-manager/test/healthcheck_test/healthcheck_test.go index b6e8df94..ad997a76 100644 --- a/vendor/github.com/Peripli/service-manager/test/healthcheck_test/healthcheck_test.go +++ b/vendor/github.com/Peripli/service-manager/test/healthcheck_test/healthcheck_test.go @@ -36,7 +36,7 @@ var _ = Describe("Healthcheck API", func() { var ctx *common.TestContext BeforeSuite(func() { - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { diff --git a/vendor/github.com/Peripli/service-manager/test/info_test/info_test.go b/vendor/github.com/Peripli/service-manager/test/info_test/info_test.go index 5ebc8bfb..9cc6487b 100644 --- a/vendor/github.com/Peripli/service-manager/test/info_test/info_test.go +++ b/vendor/github.com/Peripli/service-manager/test/info_test/info_test.go @@ -36,7 +36,7 @@ var _ = Describe("Info API", func() { var ctx *common.TestContext BeforeSuite(func() { - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { diff --git a/vendor/github.com/Peripli/service-manager/test/osb_test/osb_test.go b/vendor/github.com/Peripli/service-manager/test/osb_test/osb_test.go index 2db19615..d5663af5 100644 --- a/vendor/github.com/Peripli/service-manager/test/osb_test/osb_test.go +++ b/vendor/github.com/Peripli/service-manager/test/osb_test/osb_test.go @@ -17,17 +17,18 @@ package osb_test import ( "net/http" + "github.com/Peripli/service-manager/test/common" "github.com/gavv/httpexpect" - . "github.com/onsi/ginkgo" - "testing" "os" + "testing" + + . "github.com/onsi/ginkgo" ) type object = common.Object - // TestOSB tests for OSB API func TestOSB(t *testing.T) { os.Chdir("../..") @@ -67,7 +68,7 @@ var _ = Describe("Service Manager OSB API", func() { ) BeforeSuite(func() { - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) validBroker = ctx.RegisterBroker("broker1", common.SetupFakeServiceBrokerServer("broker1")) failingBroker = ctx.RegisterBroker("broker2", common.SetupFakeFailingBrokerServer("broker2")) }) @@ -209,4 +210,50 @@ var _ = Describe("Service Manager OSB API", func() { }) }) }) + + Describe("Get Last Operation", func() { + + assertLastOperationHasState := func(url string) { + resp := ctx.SMWithBasic.GET(url).WithHeader("X-Broker-API-Version", "oidc_authn.13"). + Expect().Status(http.StatusOK).JSON().Object() + + resp.ContainsKey("state") + } + + Context("For service instance", func() { + It("should return state", func() { + assertLastOperationHasState(validBroker.OSBURL + "/v2/service_instances/iid/last_operation") + }) + }) + + Context("For service binding", func() { + It("should return state", func() { + assertLastOperationHasState(validBroker.OSBURL + "/v2/service_instances/iid/service_bindings/bid/last_operation") + }) + }) + }) + + Describe("Prefixed broker path", func() { + + Describe("Catalog", func() { + + BeforeEach(func() { + ctx = common.NewTestContextFromAPIs(nil) + validBroker = ctx.RegisterBroker("broker1", common.SetupFakeServiceBrokerServerWithPrefix("broker1", "/sm")) + }) + + AfterEach(func() { + ctx.Cleanup() + }) + + Context("when call to working broker", func() { + It("should get catalog", func() { + resp := ctx.SMWithBasic.GET(validBroker.OSBURL+"/v2/catalog").WithHeader("X-Broker-API-Version", "oidc_authn.13"). + Expect().Status(http.StatusOK).JSON().Object() + + resp.ContainsKey("services") + }) + }) + }) + }) }) diff --git a/vendor/github.com/Peripli/service-manager/test/platform_test/platform_test.go b/vendor/github.com/Peripli/service-manager/test/platform_test/platform_test.go index 671a5666..d5c24a3d 100644 --- a/vendor/github.com/Peripli/service-manager/test/platform_test/platform_test.go +++ b/vendor/github.com/Peripli/service-manager/test/platform_test/platform_test.go @@ -38,7 +38,7 @@ var _ = Describe("Service Manager Platform API", func() { var ctx *common.TestContext BeforeSuite(func() { - ctx = common.NewTestContextFromAPIs() + ctx = common.NewTestContextFromAPIs(nil) }) AfterSuite(func() { diff --git a/vendor/github.com/Peripli/service-manager/test/plugin_test/plugin_test.go b/vendor/github.com/Peripli/service-manager/test/plugin_test/plugin_test.go index 2284b4ac..6cdd0b5f 100644 --- a/vendor/github.com/Peripli/service-manager/test/plugin_test/plugin_test.go +++ b/vendor/github.com/Peripli/service-manager/test/plugin_test/plugin_test.go @@ -34,9 +34,7 @@ var _ = Describe("Service Manager Plugins", func() { Describe("Partial plugin", func() { BeforeEach(func() { - api := &web.API{} - api.RegisterPlugins(&PartialPlugin{}) - ctx = common.NewTestContextFromAPIs(api) + ctx = common.NewTestContextFromAPIs([]web.Plugin{&PartialPlugin{}}) testBroker = ctx.RegisterBroker("broker1", nil) }) @@ -62,17 +60,13 @@ var _ = Describe("Service Manager Plugins", func() { }) JustBeforeEach(func() { - api := &web.API{} - api.RegisterPlugins(testPlugin) - ctx = common.NewTestContextFromAPIs(api) + ctx = common.NewTestContextFromAPIs([]web.Plugin{testPlugin}) testBroker = ctx.RegisterBroker("broker1", nil) }) - It("Plugin modifies the request & response body", func() { var resBodySize int - testPlugin["provision"] = web.MiddlewareFunc(func(next web.Handler) web.Handler { - return web.HandlerFunc(func(req *web.Request) (*web.Response, error) { + testPlugin["provision"] = web.MiddlewareFunc(func(req *web.Request, next web.Handler) (*web.Response, error) { var err error req.Body, err = sjson.SetBytes(req.Body, "extra", "request") if err != nil { @@ -90,7 +84,6 @@ var _ = Describe("Service Manager Plugins", func() { } resBodySize = len(res.Body) return res, nil - }) }) testBroker.StatusCode = http.StatusCreated @@ -114,8 +107,7 @@ var _ = Describe("Service Manager Plugins", func() { }) It("Plugin modifies the request & response headers", func() { - testPlugin["fetchCatalog"] = web.MiddlewareFunc(func(next web.Handler) web.Handler { - return web.HandlerFunc(func(req *web.Request) (*web.Response, error) { + testPlugin["fetchCatalog"] = web.MiddlewareFunc(func(req *web.Request, next web.Handler) (*web.Response, error) { h := req.Header.Get("extra") req.Header.Set("extra", h+"-request") @@ -126,7 +118,6 @@ var _ = Describe("Service Manager Plugins", func() { res.Header.Set("extra", h+"-response") return res, nil - }) }) testBroker.StatusCode = http.StatusOK @@ -137,14 +128,12 @@ var _ = Describe("Service Manager Plugins", func() { }) It("Plugin aborts the request", func() { - testPlugin["fetchCatalog"] = web.MiddlewareFunc(func(next web.Handler) web.Handler { - return web.HandlerFunc(func(req *web.Request) (*web.Response, error) { + testPlugin["fetchCatalog"] = web.MiddlewareFunc(func(req *web.Request, next web.Handler) (*web.Response, error) { return nil, &util.HTTPError{ ErrorType: "PluginErr", Description: "Plugin error", StatusCode: http.StatusBadRequest, } - }) }) ctx.SMWithBasic.GET(testBroker.OSBURL + "/v2/catalog"). @@ -163,34 +152,42 @@ var _ = Describe("Service Manager Plugins", func() { Expect(testBroker.Server.URL).To(ContainSubstring(testBroker.Request.Host)) }) - osbOperations := []struct{ name, method, path string }{ - {"fetchCatalog", "GET", "/v2/catalog"}, - {"provision", "PUT", "/v2/service_instances/1234"}, - {"deprovision", "DELETE", "/v2/service_instances/1234"}, - {"updateService", "PATCH", "/v2/service_instances/1234"}, - {"fetchService", "GET", "/v2/service_instances/1234"}, - {"bind", "PUT", "/v2/service_instances/1234/service_bindings/111"}, - {"unbind", "DELETE", "/v2/service_instances/1234/service_bindings/111"}, - {"fetchBinding", "GET", "/v2/service_instances/1234/service_bindings/111"}, + osbOperations := []struct { + name string + method string + path string + queries []string + }{ + {"fetchCatalog", "GET", "/v2/catalog", []string{""}}, + {"provision", "PUT", "/v2/service_instances/1234", []string{"", "accepts_incomplete=true"}}, + {"deprovision", "DELETE", "/v2/service_instances/1234", []string{""}}, + {"updateService", "PATCH", "/v2/service_instances/1234", []string{""}}, + {"fetchService", "GET", "/v2/service_instances/1234", []string{""}}, + {"bind", "PUT", "/v2/service_instances/1234/service_bindings/111", []string{""}}, + {"unbind", "DELETE", "/v2/service_instances/1234/service_bindings/111", []string{""}}, + {"fetchBinding", "GET", "/v2/service_instances/1234/service_bindings/111", []string{""}}, + {"pollInstance", "GET", "/v2/service_instances/1234/last_operation", []string{"", "service_id=serviceId", "plan_id=planId", "operation=provision", "service_id=serviceId&plan_id=planId&operation=provision"}}, + {"pollBinding", "GET", "/v2/service_instances/1234/service_bindings/111/last_operation", []string{"", "service_id=serviceId", "plan_id=planId", "operation=provision", "service_id=serviceId&plan_id=planId&operation=provision"}}, } for _, op := range osbOperations { op := op It(fmt.Sprintf("Plugin intercepts %s operation", op.name), func() { - testPlugin[op.name] = web.MiddlewareFunc(func(next web.Handler) web.Handler { - return web.HandlerFunc(func(req *web.Request) (*web.Response, error) { + testPlugin[op.name] = web.MiddlewareFunc(func(req *web.Request, next web.Handler) (*web.Response, error) { res, err := next.Handle(req) if err == nil { res.Header.Set("X-Plugin", op.name) } return res, err - }) }) - ctx.SMWithBasic.Request(op.method, testBroker.OSBURL+op.path). - WithHeader("Content-Type", "application/json"). - WithJSON(object{}). - Expect().Status(http.StatusOK).Header("X-Plugin").Equal(op.name) + for _, query := range op.queries { + ctx.SMWithBasic.Request(op.method, testBroker.OSBURL+op.path). + WithHeader("Content-Type", "application/json"). + WithJSON(object{}). + WithQueryString(query). + Expect().Status(http.StatusOK).Header("X-Plugin").Equal(op.name) + } }) } @@ -202,56 +199,60 @@ type TestPlugin map[string]web.Middleware func (p TestPlugin) Name() string { return "TestPlugin" } -func (p TestPlugin) call(middleware web.Middleware, next web.Handler) web.Handler { - return web.HandlerFunc(func(r *web.Request) (*web.Response, error) { - if middleware == nil { - return next.Handle(r) +func (p TestPlugin) call(middleware web.Middleware, req *web.Request, next web.Handler) (*web.Response, error) { + if middleware == nil { + return next.Handle(req) } - return middleware.Run(next).Handle(r) - }) + return middleware.Run(req, next) } -func (p TestPlugin) FetchCatalog(next web.Handler) web.Handler { - return p.call(p["fetchCatalog"], next) +func (p TestPlugin) FetchCatalog(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["fetchCatalog"], request, next) } -func (p TestPlugin) Provision(next web.Handler) web.Handler { - return p.call(p["provision"], next) +func (p TestPlugin) Provision(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["provision"], request,next) } -func (p TestPlugin) Deprovision(next web.Handler) web.Handler { - return p.call(p["deprovision"], next) +func (p TestPlugin) Deprovision(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["deprovision"], request,next) } -func (p TestPlugin) UpdateService(next web.Handler) web.Handler { - return p.call(p["updateService"], next) +func (p TestPlugin) UpdateService(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["updateService"],request, next) } -func (p TestPlugin) FetchService(next web.Handler) web.Handler { - return p.call(p["fetchService"], next) +func (p TestPlugin) FetchService(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["fetchService"],request, next) } -func (p TestPlugin) Bind(next web.Handler) web.Handler { - return p.call(p["bind"], next) +func (p TestPlugin) Bind(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["bind"], request,next) } -func (p TestPlugin) Unbind(next web.Handler) web.Handler { - return p.call(p["unbind"], next) +func (p TestPlugin) Unbind(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["unbind"],request, next) } -func (p TestPlugin) FetchBinding(next web.Handler) web.Handler { - return p.call(p["fetchBinding"], next) +func (p TestPlugin) FetchBinding(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["fetchBinding"],request, next) +} + +func (p TestPlugin) PollInstance(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["pollInstance"], request,next) +} + +func (p TestPlugin) PollBinding(request *web.Request, next web.Handler) (*web.Response, error) { + return p.call(p["pollBinding"],request, next) } type PartialPlugin struct{} func (p PartialPlugin) Name() string { return "PartialPlugin" } -func (p PartialPlugin) Provision(next web.Handler) web.Handler { - return web.HandlerFunc(func(request *web.Request) (*web.Response, error) { - res, err := next.Handle(request) - if err == nil { - res.Header.Set("X-Plugin", "provision") - } - return res, err - }) +func (p PartialPlugin) Provision(request *web.Request, next web.Handler) (*web.Response, error) { + res, err := next.Handle(request) + if err == nil { + res.Header.Set("X-Plugin", "provision") + } + return res, err } diff --git a/vendor/github.com/Peripli/service-manager/test/sm/sm_test.go b/vendor/github.com/Peripli/service-manager/test/sm/sm_test.go index b9a0184c..9a62389b 100644 --- a/vendor/github.com/Peripli/service-manager/test/sm/sm_test.go +++ b/vendor/github.com/Peripli/service-manager/test/sm/sm_test.go @@ -81,7 +81,7 @@ var _ = Describe("SM", func() { fakeEnv.UnmarshalReturns(errors.New("error")) Expect(func() { - sm.New(ctx, cancel, fakeEnv) + sm.New(ctx, fakeEnv) }).To(Panic()) }) }) @@ -89,7 +89,7 @@ var _ = Describe("SM", func() { Context("when validating config fails", func() { It("should panic", func() { Expect(func() { - sm.New(ctx, cancel, sm.DefaultEnv(func(set *pflag.FlagSet) { + sm.New(ctx, sm.DefaultEnv(func(set *pflag.FlagSet) { set.Set("log.level", "") })) }).To(Panic()) @@ -99,7 +99,7 @@ var _ = Describe("SM", func() { Context("when setting up storage fails", func() { It("should panic", func() { Expect(func() { - sm.New(ctx, cancel, sm.DefaultEnv(func(set *pflag.FlagSet) { + sm.New(ctx, sm.DefaultEnv(func(set *pflag.FlagSet) { set.Set("storage.uri", "invalid") })) }).To(Panic()) @@ -109,7 +109,7 @@ var _ = Describe("SM", func() { Context("when setting up API fails", func() { It("should panic", func() { Expect(func() { - sm.New(ctx, cancel, sm.DefaultEnv(func(set *pflag.FlagSet) { + sm.New(ctx, sm.DefaultEnv(func(set *pflag.FlagSet) { set.Set("api.token_issuer_url", "") })) }).To(Panic()) @@ -118,7 +118,7 @@ var _ = Describe("SM", func() { Context("when no API extensions are registered", func() { It("should return working service manager", func() { - smanager := sm.New(ctx, cancel, sm.DefaultEnv()) + smanager := sm.New(ctx, sm.DefaultEnv()) verifyServiceManagerStartsSuccessFully(httptest.NewServer(smanager.Build().Server.Router)) @@ -127,7 +127,7 @@ var _ = Describe("SM", func() { Context("when additional filter is registered", func() { It("should return working service manager with a new filter", func() { - smanager := sm.New(ctx, cancel, sm.DefaultEnv()) + smanager := sm.New(ctx, sm.DefaultEnv()) smanager.RegisterFilters(testFilter{}) SM := verifyServiceManagerStartsSuccessFully(httptest.NewServer(smanager.Build().Server.Router)) @@ -140,7 +140,7 @@ var _ = Describe("SM", func() { Context("when additional controller is registered", func() { It("should return working service manager with additional controller", func() { - smanager := sm.New(ctx, cancel, sm.DefaultEnv()) + smanager := sm.New(ctx, sm.DefaultEnv()) smanager.RegisterControllers(testController{}) SM := verifyServiceManagerStartsSuccessFully(httptest.NewServer(smanager.Build().Server.Router)) @@ -186,8 +186,8 @@ func (tf testFilter) Name() string { return "testFilter" } -func (tf testFilter) Run(next web.Handler) web.Handler { - return testHandler("filter") +func (tf testFilter) Run(request *web.Request, next web.Handler) (*web.Response, error) { + return testHandler("filter")(request) } func (tf testFilter) FilterMatchers() []web.FilterMatcher { diff --git a/vendor/github.com/beorn7/perks/.gitignore b/vendor/github.com/beorn7/perks/.gitignore deleted file mode 100644 index 1bd9209a..00000000 --- a/vendor/github.com/beorn7/perks/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.test -*.prof diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE deleted file mode 100644 index 339177be..00000000 --- a/vendor/github.com/beorn7/perks/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013 Blake Mizerany - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/beorn7/perks/README.md b/vendor/github.com/beorn7/perks/README.md deleted file mode 100644 index fc057777..00000000 --- a/vendor/github.com/beorn7/perks/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Perks for Go (golang.org) - -Perks contains the Go package quantile that computes approximate quantiles over -an unbounded data stream within low memory and CPU bounds. - -For more information and examples, see: -http://godoc.org/github.com/bmizerany/perks - -A very special thank you and shout out to Graham Cormode (Rutgers University), -Flip Korn (AT&T Labs–Research), S. Muthukrishnan (Rutgers University), and -Divesh Srivastava (AT&T Labs–Research) for their research and publication of -[Effective Computation of Biased Quantiles over Data Streams](http://www.cs.rutgers.edu/~muthu/bquant.pdf) - -Thank you, also: -* Armon Dadgar (@armon) -* Andrew Gerrand (@nf) -* Brad Fitzpatrick (@bradfitz) -* Keith Rarick (@kr) - -FAQ: - -Q: Why not move the quantile package into the project root? -A: I want to add more packages to perks later. - -Copyright (C) 2013 Blake Mizerany - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/beorn7/perks/histogram/bench_test.go b/vendor/github.com/beorn7/perks/histogram/bench_test.go deleted file mode 100644 index 56c7e551..00000000 --- a/vendor/github.com/beorn7/perks/histogram/bench_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package histogram - -import ( - "math/rand" - "testing" -) - -func BenchmarkInsert10Bins(b *testing.B) { - b.StopTimer() - h := New(10) - b.StartTimer() - for i := 0; i < b.N; i++ { - f := rand.ExpFloat64() - h.Insert(f) - } -} - -func BenchmarkInsert100Bins(b *testing.B) { - b.StopTimer() - h := New(100) - b.StartTimer() - for i := 0; i < b.N; i++ { - f := rand.ExpFloat64() - h.Insert(f) - } -} diff --git a/vendor/github.com/beorn7/perks/histogram/histogram.go b/vendor/github.com/beorn7/perks/histogram/histogram.go deleted file mode 100644 index bef05c70..00000000 --- a/vendor/github.com/beorn7/perks/histogram/histogram.go +++ /dev/null @@ -1,108 +0,0 @@ -// Package histogram provides a Go implementation of BigML's histogram package -// for Clojure/Java. It is currently experimental. -package histogram - -import ( - "container/heap" - "math" - "sort" -) - -type Bin struct { - Count int - Sum float64 -} - -func (b *Bin) Update(x *Bin) { - b.Count += x.Count - b.Sum += x.Sum -} - -func (b *Bin) Mean() float64 { - return b.Sum / float64(b.Count) -} - -type Bins []*Bin - -func (bs Bins) Len() int { return len(bs) } -func (bs Bins) Less(i, j int) bool { return bs[i].Mean() < bs[j].Mean() } -func (bs Bins) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] } - -func (bs *Bins) Push(x interface{}) { - *bs = append(*bs, x.(*Bin)) -} - -func (bs *Bins) Pop() interface{} { - return bs.remove(len(*bs) - 1) -} - -func (bs *Bins) remove(n int) *Bin { - if n < 0 || len(*bs) < n { - return nil - } - x := (*bs)[n] - *bs = append((*bs)[:n], (*bs)[n+1:]...) - return x -} - -type Histogram struct { - res *reservoir -} - -func New(maxBins int) *Histogram { - return &Histogram{res: newReservoir(maxBins)} -} - -func (h *Histogram) Insert(f float64) { - h.res.insert(&Bin{1, f}) - h.res.compress() -} - -func (h *Histogram) Bins() Bins { - return h.res.bins -} - -type reservoir struct { - n int - maxBins int - bins Bins -} - -func newReservoir(maxBins int) *reservoir { - return &reservoir{maxBins: maxBins} -} - -func (r *reservoir) insert(bin *Bin) { - r.n += bin.Count - i := sort.Search(len(r.bins), func(i int) bool { - return r.bins[i].Mean() >= bin.Mean() - }) - if i < 0 || i == r.bins.Len() { - // TODO(blake): Maybe use an .insert(i, bin) instead of - // performing the extra work of a heap.Push. - heap.Push(&r.bins, bin) - return - } - r.bins[i].Update(bin) -} - -func (r *reservoir) compress() { - for r.bins.Len() > r.maxBins { - minGapIndex := -1 - minGap := math.MaxFloat64 - for i := 0; i < r.bins.Len()-1; i++ { - gap := gapWeight(r.bins[i], r.bins[i+1]) - if minGap > gap { - minGap = gap - minGapIndex = i - } - } - prev := r.bins[minGapIndex] - next := r.bins.remove(minGapIndex + 1) - prev.Update(next) - } -} - -func gapWeight(prev, next *Bin) float64 { - return next.Mean() - prev.Mean() -} diff --git a/vendor/github.com/beorn7/perks/histogram/histogram_test.go b/vendor/github.com/beorn7/perks/histogram/histogram_test.go deleted file mode 100644 index 0575ebee..00000000 --- a/vendor/github.com/beorn7/perks/histogram/histogram_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package histogram - -import ( - "math/rand" - "testing" -) - -func TestHistogram(t *testing.T) { - const numPoints = 1e6 - const maxBins = 3 - - h := New(maxBins) - for i := 0; i < numPoints; i++ { - f := rand.ExpFloat64() - h.Insert(f) - } - - bins := h.Bins() - if g := len(bins); g > maxBins { - t.Fatalf("got %d bins, wanted <= %d", g, maxBins) - } - - for _, b := range bins { - t.Logf("%+v", b) - } - - if g := count(h.Bins()); g != numPoints { - t.Fatalf("binned %d points, wanted %d", g, numPoints) - } -} - -func count(bins Bins) int { - binCounts := 0 - for _, b := range bins { - binCounts += b.Count - } - return binCounts -} diff --git a/vendor/github.com/beorn7/perks/quantile/bench_test.go b/vendor/github.com/beorn7/perks/quantile/bench_test.go deleted file mode 100644 index 0bd0e4e7..00000000 --- a/vendor/github.com/beorn7/perks/quantile/bench_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package quantile - -import ( - "testing" -) - -func BenchmarkInsertTargeted(b *testing.B) { - b.ReportAllocs() - - s := NewTargeted(Targets) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiased(b *testing.B) { - s := NewLowBiased(0.01) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) { - s := NewLowBiased(0.0001) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkQuery(b *testing.B) { - s := NewTargeted(Targets) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} - -func BenchmarkQuerySmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} diff --git a/vendor/github.com/beorn7/perks/quantile/example_test.go b/vendor/github.com/beorn7/perks/quantile/example_test.go deleted file mode 100644 index ab3293aa..00000000 --- a/vendor/github.com/beorn7/perks/quantile/example_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// +build go1.1 - -package quantile_test - -import ( - "bufio" - "fmt" - "log" - "os" - "strconv" - "time" - - "github.com/beorn7/perks/quantile" -) - -func Example_simple() { - ch := make(chan float64) - go sendFloats(ch) - - // Compute the 50th, 90th, and 99th percentile. - q := quantile.NewTargeted(map[float64]float64{ - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - }) - for v := range ch { - q.Insert(v) - } - - fmt.Println("perc50:", q.Query(0.50)) - fmt.Println("perc90:", q.Query(0.90)) - fmt.Println("perc99:", q.Query(0.99)) - fmt.Println("count:", q.Count()) - // Output: - // perc50: 5 - // perc90: 16 - // perc99: 223 - // count: 2388 -} - -func Example_mergeMultipleStreams() { - // Scenario: - // We have multiple database shards. On each shard, there is a process - // collecting query response times from the database logs and inserting - // them into a Stream (created via NewTargeted(0.90)), much like the - // Simple example. These processes expose a network interface for us to - // ask them to serialize and send us the results of their - // Stream.Samples so we may Merge and Query them. - // - // NOTES: - // * These sample sets are small, allowing us to get them - // across the network much faster than sending the entire list of data - // points. - // - // * For this to work correctly, we must supply the same quantiles - // a priori the process collecting the samples supplied to NewTargeted, - // even if we do not plan to query them all here. - ch := make(chan quantile.Samples) - getDBQuerySamples(ch) - q := quantile.NewTargeted(map[float64]float64{0.90: 0.001}) - for samples := range ch { - q.Merge(samples) - } - fmt.Println("perc90:", q.Query(0.90)) -} - -func Example_window() { - // Scenario: We want the 90th, 95th, and 99th percentiles for each - // minute. - - ch := make(chan float64) - go sendStreamValues(ch) - - tick := time.NewTicker(1 * time.Minute) - q := quantile.NewTargeted(map[float64]float64{ - 0.90: 0.001, - 0.95: 0.0005, - 0.99: 0.0001, - }) - for { - select { - case t := <-tick.C: - flushToDB(t, q.Samples()) - q.Reset() - case v := <-ch: - q.Insert(v) - } - } -} - -func sendStreamValues(ch chan float64) { - // Use your imagination -} - -func flushToDB(t time.Time, samples quantile.Samples) { - // Use your imagination -} - -// This is a stub for the above example. In reality this would hit the remote -// servers via http or something like it. -func getDBQuerySamples(ch chan quantile.Samples) {} - -func sendFloats(ch chan<- float64) { - f, err := os.Open("exampledata.txt") - if err != nil { - log.Fatal(err) - } - sc := bufio.NewScanner(f) - for sc.Scan() { - b := sc.Bytes() - v, err := strconv.ParseFloat(string(b), 64) - if err != nil { - log.Fatal(err) - } - ch <- v - } - if sc.Err() != nil { - log.Fatal(sc.Err()) - } - close(ch) -} diff --git a/vendor/github.com/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt deleted file mode 100644 index 1602287d..00000000 --- a/vendor/github.com/beorn7/perks/quantile/exampledata.txt +++ /dev/null @@ -1,2388 +0,0 @@ -8 -5 -26 -12 -5 -235 -13 -6 -28 -30 -3 -3 -3 -3 -5 -2 -33 -7 -2 -4 -7 -12 -14 -5 -8 -3 -10 -4 -5 -3 -6 -6 -209 -20 -3 -10 -14 -3 -4 -6 -8 -5 -11 -7 -3 -2 -3 -3 -212 -5 -222 -4 -10 -10 -5 -6 -3 -8 -3 -10 -254 -220 -2 -3 -5 -24 -5 -4 -222 -7 -3 -3 -223 -8 -15 -12 -14 -14 -3 -2 -2 -3 -13 -3 -11 -4 -4 -6 -5 -7 -13 -5 -3 -5 -2 -5 -3 -5 -2 -7 -15 -17 -14 -3 -6 -6 -3 -17 -5 -4 -7 -6 -4 -4 -8 -6 -8 -3 -9 -3 -6 -3 -4 -5 -3 -3 -660 -4 -6 -10 -3 -6 -3 -2 -5 -13 -2 -4 -4 -10 -4 -8 -4 -3 -7 -9 -9 -3 -10 -37 -3 -13 -4 -12 -3 -6 -10 -8 -5 -21 -2 -3 -8 -3 -2 -3 -3 -4 -12 -2 -4 -8 -8 -4 -3 -2 -20 -1 -6 -32 -2 -11 -6 -18 -3 -8 -11 -3 -212 -3 -4 -2 -6 -7 -12 -11 -3 -2 -16 -10 -6 -4 -6 -3 -2 -7 -3 -2 -2 -2 -2 -5 -6 -4 -3 -10 -3 -4 -6 -5 -3 -4 -4 -5 -6 -4 -3 -4 -4 -5 -7 -5 -5 -3 -2 -7 -2 -4 -12 -4 -5 -6 -2 -4 -4 -8 -4 -15 -13 -7 -16 -5 -3 -23 -5 -5 -7 -3 -2 -9 -8 -7 -5 -8 -11 -4 -10 -76 -4 -47 -4 -3 -2 -7 -4 -2 -3 -37 -10 -4 -2 -20 -5 -4 -4 -10 -10 -4 -3 -7 -23 -240 -7 -13 -5 -5 -3 -3 -2 -5 -4 -2 -8 -7 -19 -2 -23 -8 -7 -2 -5 -3 -8 -3 -8 -13 -5 -5 -5 -2 -3 -23 -4 -9 -8 -4 -3 -3 -5 -220 -2 -3 -4 -6 -14 -3 -53 -6 -2 -5 -18 -6 -3 -219 -6 -5 -2 -5 -3 -6 -5 -15 -4 -3 -17 -3 -2 -4 -7 -2 -3 -3 -4 -4 -3 -2 -664 -6 -3 -23 -5 -5 -16 -5 -8 -2 -4 -2 -24 -12 -3 -2 -3 -5 -8 -3 -5 -4 -3 -14 -3 -5 -8 -2 -3 -7 -9 -4 -2 -3 -6 -8 -4 -3 -4 -6 -5 -3 -3 -6 -3 -19 -4 -4 -6 -3 -6 -3 -5 -22 -5 -4 -4 -3 -8 -11 -4 -9 -7 -6 -13 -4 -4 -4 -6 -17 -9 -3 -3 -3 -4 -3 -221 -5 -11 -3 -4 -2 -12 -6 -3 -5 -7 -5 -7 -4 -9 -7 -14 -37 -19 -217 -16 -3 -5 -2 -2 -7 -19 -7 -6 -7 -4 -24 -5 -11 -4 -7 -7 -9 -13 -3 -4 -3 -6 -28 -4 -4 -5 -5 -2 -5 -6 -4 -4 -6 -10 -5 -4 -3 -2 -3 -3 -6 -5 -5 -4 -3 -2 -3 -7 -4 -6 -18 -16 -8 -16 -4 -5 -8 -6 -9 -13 -1545 -6 -215 -6 -5 -6 -3 -45 -31 -5 -2 -2 -4 -3 -3 -2 -5 -4 -3 -5 -7 -7 -4 -5 -8 -5 -4 -749 -2 -31 -9 -11 -2 -11 -5 -4 -4 -7 -9 -11 -4 -5 -4 -7 -3 -4 -6 -2 -15 -3 -4 -3 -4 -3 -5 -2 -13 -5 -5 -3 -3 -23 -4 -4 -5 -7 -4 -13 -2 -4 -3 -4 -2 -6 -2 -7 -3 -5 -5 -3 -29 -5 -4 -4 -3 -10 -2 -3 -79 -16 -6 -6 -7 -7 -3 -5 -5 -7 -4 -3 -7 -9 -5 -6 -5 -9 -6 -3 -6 -4 -17 -2 -10 -9 -3 -6 -2 -3 -21 -22 -5 -11 -4 -2 -17 -2 -224 -2 -14 -3 -4 -4 -2 -4 -4 -4 -4 -5 -3 -4 -4 -10 -2 -6 -3 -3 -5 -7 -2 -7 -5 -6 -3 -218 -2 -2 -5 -2 -6 -3 -5 -222 -14 -6 -33 -3 -2 -5 -3 -3 -3 -9 -5 -3 -3 -2 -7 -4 -3 -4 -3 -5 -6 -5 -26 -4 -13 -9 -7 -3 -221 -3 -3 -4 -4 -4 -4 -2 -18 -5 -3 -7 -9 -6 -8 -3 -10 -3 -11 -9 -5 -4 -17 -5 -5 -6 -6 -3 -2 -4 -12 -17 -6 -7 -218 -4 -2 -4 -10 -3 -5 -15 -3 -9 -4 -3 -3 -6 -29 -3 -3 -4 -5 -5 -3 -8 -5 -6 -6 -7 -5 -3 -5 -3 -29 -2 -31 -5 -15 -24 -16 -5 -207 -4 -3 -3 -2 -15 -4 -4 -13 -5 -5 -4 -6 -10 -2 -7 -8 -4 -6 -20 -5 -3 -4 -3 -12 -12 -5 -17 -7 -3 -3 -3 -6 -10 -3 -5 -25 -80 -4 -9 -3 -2 -11 -3 -3 -2 -3 -8 -7 -5 -5 -19 -5 -3 -3 -12 -11 -2 -6 -5 -5 -5 -3 -3 -3 -4 -209 -14 -3 -2 -5 -19 -4 -4 -3 -4 -14 -5 -6 -4 -13 -9 -7 -4 -7 -10 -2 -9 -5 -7 -2 -8 -4 -6 -5 -5 -222 -8 -7 -12 -5 -216 -3 -4 -4 -6 -3 -14 -8 -7 -13 -4 -3 -3 -3 -3 -17 -5 -4 -3 -33 -6 -6 -33 -7 -5 -3 -8 -7 -5 -2 -9 -4 -2 -233 -24 -7 -4 -8 -10 -3 -4 -15 -2 -16 -3 -3 -13 -12 -7 -5 -4 -207 -4 -2 -4 -27 -15 -2 -5 -2 -25 -6 -5 -5 -6 -13 -6 -18 -6 -4 -12 -225 -10 -7 -5 -2 -2 -11 -4 -14 -21 -8 -10 -3 -5 -4 -232 -2 -5 -5 -3 -7 -17 -11 -6 -6 -23 -4 -6 -3 -5 -4 -2 -17 -3 -6 -5 -8 -3 -2 -2 -14 -9 -4 -4 -2 -5 -5 -3 -7 -6 -12 -6 -10 -3 -6 -2 -2 -19 -5 -4 -4 -9 -2 -4 -13 -3 -5 -6 -3 -6 -5 -4 -9 -6 -3 -5 -7 -3 -6 -6 -4 -3 -10 -6 -3 -221 -3 -5 -3 -6 -4 -8 -5 -3 -6 -4 -4 -2 -54 -5 -6 -11 -3 -3 -4 -4 -4 -3 -7 -3 -11 -11 -7 -10 -6 -13 -223 -213 -15 -231 -7 -3 -7 -228 -2 -3 -4 -4 -5 -6 -7 -4 -13 -3 -4 -5 -3 -6 -4 -6 -7 -2 -4 -3 -4 -3 -3 -6 -3 -7 -3 -5 -18 -5 -6 -8 -10 -3 -3 -3 -2 -4 -2 -4 -4 -5 -6 -6 -4 -10 -13 -3 -12 -5 -12 -16 -8 -4 -19 -11 -2 -4 -5 -6 -8 -5 -6 -4 -18 -10 -4 -2 -216 -6 -6 -6 -2 -4 -12 -8 -3 -11 -5 -6 -14 -5 -3 -13 -4 -5 -4 -5 -3 -28 -6 -3 -7 -219 -3 -9 -7 -3 -10 -6 -3 -4 -19 -5 -7 -11 -6 -15 -19 -4 -13 -11 -3 -7 -5 -10 -2 -8 -11 -2 -6 -4 -6 -24 -6 -3 -3 -3 -3 -6 -18 -4 -11 -4 -2 -5 -10 -8 -3 -9 -5 -3 -4 -5 -6 -2 -5 -7 -4 -4 -14 -6 -4 -4 -5 -5 -7 -2 -4 -3 -7 -3 -3 -6 -4 -5 -4 -4 -4 -3 -3 -3 -3 -8 -14 -2 -3 -5 -3 -2 -4 -5 -3 -7 -3 -3 -18 -3 -4 -4 -5 -7 -3 -3 -3 -13 -5 -4 -8 -211 -5 -5 -3 -5 -2 -5 -4 -2 -655 -6 -3 -5 -11 -2 -5 -3 -12 -9 -15 -11 -5 -12 -217 -2 -6 -17 -3 -3 -207 -5 -5 -4 -5 -9 -3 -2 -8 -5 -4 -3 -2 -5 -12 -4 -14 -5 -4 -2 -13 -5 -8 -4 -225 -4 -3 -4 -5 -4 -3 -3 -6 -23 -9 -2 -6 -7 -233 -4 -4 -6 -18 -3 -4 -6 -3 -4 -4 -2 -3 -7 -4 -13 -227 -4 -3 -5 -4 -2 -12 -9 -17 -3 -7 -14 -6 -4 -5 -21 -4 -8 -9 -2 -9 -25 -16 -3 -6 -4 -7 -8 -5 -2 -3 -5 -4 -3 -3 -5 -3 -3 -3 -2 -3 -19 -2 -4 -3 -4 -2 -3 -4 -4 -2 -4 -3 -3 -3 -2 -6 -3 -17 -5 -6 -4 -3 -13 -5 -3 -3 -3 -4 -9 -4 -2 -14 -12 -4 -5 -24 -4 -3 -37 -12 -11 -21 -3 -4 -3 -13 -4 -2 -3 -15 -4 -11 -4 -4 -3 -8 -3 -4 -4 -12 -8 -5 -3 -3 -4 -2 -220 -3 -5 -223 -3 -3 -3 -10 -3 -15 -4 -241 -9 -7 -3 -6 -6 -23 -4 -13 -7 -3 -4 -7 -4 -9 -3 -3 -4 -10 -5 -5 -1 -5 -24 -2 -4 -5 -5 -6 -14 -3 -8 -2 -3 -5 -13 -13 -3 -5 -2 -3 -15 -3 -4 -2 -10 -4 -4 -4 -5 -5 -3 -5 -3 -4 -7 -4 -27 -3 -6 -4 -15 -3 -5 -6 -6 -5 -4 -8 -3 -9 -2 -6 -3 -4 -3 -7 -4 -18 -3 -11 -3 -3 -8 -9 -7 -24 -3 -219 -7 -10 -4 -5 -9 -12 -2 -5 -4 -4 -4 -3 -3 -19 -5 -8 -16 -8 -6 -22 -3 -23 -3 -242 -9 -4 -3 -3 -5 -7 -3 -3 -5 -8 -3 -7 -5 -14 -8 -10 -3 -4 -3 -7 -4 -6 -7 -4 -10 -4 -3 -11 -3 -7 -10 -3 -13 -6 -8 -12 -10 -5 -7 -9 -3 -4 -7 -7 -10 -8 -30 -9 -19 -4 -3 -19 -15 -4 -13 -3 -215 -223 -4 -7 -4 -8 -17 -16 -3 -7 -6 -5 -5 -4 -12 -3 -7 -4 -4 -13 -4 -5 -2 -5 -6 -5 -6 -6 -7 -10 -18 -23 -9 -3 -3 -6 -5 -2 -4 -2 -7 -3 -3 -2 -5 -5 -14 -10 -224 -6 -3 -4 -3 -7 -5 -9 -3 -6 -4 -2 -5 -11 -4 -3 -3 -2 -8 -4 -7 -4 -10 -7 -3 -3 -18 -18 -17 -3 -3 -3 -4 -5 -3 -3 -4 -12 -7 -3 -11 -13 -5 -4 -7 -13 -5 -4 -11 -3 -12 -3 -6 -4 -4 -21 -4 -6 -9 -5 -3 -10 -8 -4 -6 -4 -4 -6 -5 -4 -8 -6 -4 -6 -4 -4 -5 -9 -6 -3 -4 -2 -9 -3 -18 -2 -4 -3 -13 -3 -6 -6 -8 -7 -9 -3 -2 -16 -3 -4 -6 -3 -2 -33 -22 -14 -4 -9 -12 -4 -5 -6 -3 -23 -9 -4 -3 -5 -5 -3 -4 -5 -3 -5 -3 -10 -4 -5 -5 -8 -4 -4 -6 -8 -5 -4 -3 -4 -6 -3 -3 -3 -5 -9 -12 -6 -5 -9 -3 -5 -3 -2 -2 -2 -18 -3 -2 -21 -2 -5 -4 -6 -4 -5 -10 -3 -9 -3 -2 -10 -7 -3 -6 -6 -4 -4 -8 -12 -7 -3 -7 -3 -3 -9 -3 -4 -5 -4 -4 -5 -5 -10 -15 -4 -4 -14 -6 -227 -3 -14 -5 -216 -22 -5 -4 -2 -2 -6 -3 -4 -2 -9 -9 -4 -3 -28 -13 -11 -4 -5 -3 -3 -2 -3 -3 -5 -3 -4 -3 -5 -23 -26 -3 -4 -5 -6 -4 -6 -3 -5 -5 -3 -4 -3 -2 -2 -2 -7 -14 -3 -6 -7 -17 -2 -2 -15 -14 -16 -4 -6 -7 -13 -6 -4 -5 -6 -16 -3 -3 -28 -3 -6 -15 -3 -9 -2 -4 -6 -3 -3 -22 -4 -12 -6 -7 -2 -5 -4 -10 -3 -16 -6 -9 -2 -5 -12 -7 -5 -5 -5 -5 -2 -11 -9 -17 -4 -3 -11 -7 -3 -5 -15 -4 -3 -4 -211 -8 -7 -5 -4 -7 -6 -7 -6 -3 -6 -5 -6 -5 -3 -4 -4 -26 -4 -6 -10 -4 -4 -3 -2 -3 -3 -4 -5 -9 -3 -9 -4 -4 -5 -5 -8 -2 -4 -2 -3 -8 -4 -11 -19 -5 -8 -6 -3 -5 -6 -12 -3 -2 -4 -16 -12 -3 -4 -4 -8 -6 -5 -6 -6 -219 -8 -222 -6 -16 -3 -13 -19 -5 -4 -3 -11 -6 -10 -4 -7 -7 -12 -5 -3 -3 -5 -6 -10 -3 -8 -2 -5 -4 -7 -2 -4 -4 -2 -12 -9 -6 -4 -2 -40 -2 -4 -10 -4 -223 -4 -2 -20 -6 -7 -24 -5 -4 -5 -2 -20 -16 -6 -5 -13 -2 -3 -3 -19 -3 -2 -4 -5 -6 -7 -11 -12 -5 -6 -7 -7 -3 -5 -3 -5 -3 -14 -3 -4 -4 -2 -11 -1 -7 -3 -9 -6 -11 -12 -5 -8 -6 -221 -4 -2 -12 -4 -3 -15 -4 -5 -226 -7 -218 -7 -5 -4 -5 -18 -4 -5 -9 -4 -4 -2 -9 -18 -18 -9 -5 -6 -6 -3 -3 -7 -3 -5 -4 -4 -4 -12 -3 -6 -31 -5 -4 -7 -3 -6 -5 -6 -5 -11 -2 -2 -11 -11 -6 -7 -5 -8 -7 -10 -5 -23 -7 -4 -3 -5 -34 -2 -5 -23 -7 -3 -6 -8 -4 -4 -4 -2 -5 -3 -8 -5 -4 -8 -25 -2 -3 -17 -8 -3 -4 -8 -7 -3 -15 -6 -5 -7 -21 -9 -5 -6 -6 -5 -3 -2 -3 -10 -3 -6 -3 -14 -7 -4 -4 -8 -7 -8 -2 -6 -12 -4 -213 -6 -5 -21 -8 -2 -5 -23 -3 -11 -2 -3 -6 -25 -2 -3 -6 -7 -6 -6 -4 -4 -6 -3 -17 -9 -7 -6 -4 -3 -10 -7 -2 -3 -3 -3 -11 -8 -3 -7 -6 -4 -14 -36 -3 -4 -3 -3 -22 -13 -21 -4 -2 -7 -4 -4 -17 -15 -3 -7 -11 -2 -4 -7 -6 -209 -6 -3 -2 -2 -24 -4 -9 -4 -3 -3 -3 -29 -2 -2 -4 -3 -3 -5 -4 -6 -3 -3 -2 -4 diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go deleted file mode 100644 index d7d14f8e..00000000 --- a/vendor/github.com/beorn7/perks/quantile/stream.go +++ /dev/null @@ -1,316 +0,0 @@ -// Package quantile computes approximate quantiles over an unbounded data -// stream within low memory and CPU bounds. -// -// A small amount of accuracy is traded to achieve the above properties. -// -// Multiple streams can be merged before calling Query to generate a single set -// of results. This is meaningful when the streams represent the same type of -// data. See Merge and Samples. -// -// For more detailed information about the algorithm used, see: -// -// Effective Computation of Biased Quantiles over Data Streams -// -// http://www.cs.rutgers.edu/~muthu/bquant.pdf -package quantile - -import ( - "math" - "sort" -) - -// Sample holds an observed value and meta information for compression. JSON -// tags have been added for convenience. -type Sample struct { - Value float64 `json:",string"` - Width float64 `json:",string"` - Delta float64 `json:",string"` -} - -// Samples represents a slice of samples. It implements sort.Interface. -type Samples []Sample - -func (a Samples) Len() int { return len(a) } -func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value } -func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -type invariant func(s *stream, r float64) float64 - -// NewLowBiased returns an initialized Stream for low-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the lower ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within (1±Epsilon)*Quantile. -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewLowBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * r - } - return newStream(ƒ) -} - -// NewHighBiased returns an initialized Stream for high-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the higher ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewHighBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * (s.n - r) - } - return newStream(ƒ) -} - -// NewTargeted returns an initialized Stream concerned with a particular set of -// quantile values that are supplied a priori. Knowing these a priori reduces -// space and computation time. The targets map maps the desired quantiles to -// their absolute errors, i.e. the true quantile of a value returned by a query -// is guaranteed to be within (Quantile±Epsilon). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. -func NewTargeted(targetMap map[float64]float64) *Stream { - // Convert map to slice to avoid slow iterations on a map. - // ƒ is called on the hot path, so converting the map to a slice - // beforehand results in significant CPU savings. - targets := targetMapToSlice(targetMap) - - ƒ := func(s *stream, r float64) float64 { - var m = math.MaxFloat64 - var f float64 - for _, t := range targets { - if t.quantile*s.n <= r { - f = (2 * t.epsilon * r) / t.quantile - } else { - f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile) - } - if f < m { - m = f - } - } - return m - } - return newStream(ƒ) -} - -type target struct { - quantile float64 - epsilon float64 -} - -func targetMapToSlice(targetMap map[float64]float64) []target { - targets := make([]target, 0, len(targetMap)) - - for quantile, epsilon := range targetMap { - t := target{ - quantile: quantile, - epsilon: epsilon, - } - targets = append(targets, t) - } - - return targets -} - -// Stream computes quantiles for a stream of float64s. It is not thread-safe by -// design. Take care when using across multiple goroutines. -type Stream struct { - *stream - b Samples - sorted bool -} - -func newStream(ƒ invariant) *Stream { - x := &stream{ƒ: ƒ} - return &Stream{x, make(Samples, 0, 500), true} -} - -// Insert inserts v into the stream. -func (s *Stream) Insert(v float64) { - s.insert(Sample{Value: v, Width: 1}) -} - -func (s *Stream) insert(sample Sample) { - s.b = append(s.b, sample) - s.sorted = false - if len(s.b) == cap(s.b) { - s.flush() - } -} - -// Query returns the computed qth percentiles value. If s was created with -// NewTargeted, and q is not in the set of quantiles provided a priori, Query -// will return an unspecified result. -func (s *Stream) Query(q float64) float64 { - if !s.flushed() { - // Fast path when there hasn't been enough data for a flush; - // this also yields better accuracy for small sets of data. - l := len(s.b) - if l == 0 { - return 0 - } - i := int(math.Ceil(float64(l) * q)) - if i > 0 { - i -= 1 - } - s.maybeSort() - return s.b[i].Value - } - s.flush() - return s.stream.query(q) -} - -// Merge merges samples into the underlying streams samples. This is handy when -// merging multiple streams from separate threads, database shards, etc. -// -// ATTENTION: This method is broken and does not yield correct results. The -// underlying algorithm is not capable of merging streams correctly. -func (s *Stream) Merge(samples Samples) { - sort.Sort(samples) - s.stream.merge(samples) -} - -// Reset reinitializes and clears the list reusing the samples buffer memory. -func (s *Stream) Reset() { - s.stream.reset() - s.b = s.b[:0] -} - -// Samples returns stream samples held by s. -func (s *Stream) Samples() Samples { - if !s.flushed() { - return s.b - } - s.flush() - return s.stream.samples() -} - -// Count returns the total number of samples observed in the stream -// since initialization. -func (s *Stream) Count() int { - return len(s.b) + s.stream.count() -} - -func (s *Stream) flush() { - s.maybeSort() - s.stream.merge(s.b) - s.b = s.b[:0] -} - -func (s *Stream) maybeSort() { - if !s.sorted { - s.sorted = true - sort.Sort(s.b) - } -} - -func (s *Stream) flushed() bool { - return len(s.stream.l) > 0 -} - -type stream struct { - n float64 - l []Sample - ƒ invariant -} - -func (s *stream) reset() { - s.l = s.l[:0] - s.n = 0 -} - -func (s *stream) insert(v float64) { - s.merge(Samples{{v, 1, 0}}) -} - -func (s *stream) merge(samples Samples) { - // TODO(beorn7): This tries to merge not only individual samples, but - // whole summaries. The paper doesn't mention merging summaries at - // all. Unittests show that the merging is inaccurate. Find out how to - // do merges properly. - var r float64 - i := 0 - for _, sample := range samples { - for ; i < len(s.l); i++ { - c := s.l[i] - if c.Value > sample.Value { - // Insert at position i. - s.l = append(s.l, Sample{}) - copy(s.l[i+1:], s.l[i:]) - s.l[i] = Sample{ - sample.Value, - sample.Width, - math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1), - // TODO(beorn7): How to calculate delta correctly? - } - i++ - goto inserted - } - r += c.Width - } - s.l = append(s.l, Sample{sample.Value, sample.Width, 0}) - i++ - inserted: - s.n += sample.Width - r += sample.Width - } - s.compress() -} - -func (s *stream) count() int { - return int(s.n) -} - -func (s *stream) query(q float64) float64 { - t := math.Ceil(q * s.n) - t += math.Ceil(s.ƒ(s, t) / 2) - p := s.l[0] - var r float64 - for _, c := range s.l[1:] { - r += p.Width - if r+c.Width+c.Delta > t { - return p.Value - } - p = c - } - return p.Value -} - -func (s *stream) compress() { - if len(s.l) < 2 { - return - } - x := s.l[len(s.l)-1] - xi := len(s.l) - 1 - r := s.n - 1 - x.Width - - for i := len(s.l) - 2; i >= 0; i-- { - c := s.l[i] - if c.Width+x.Width+x.Delta <= s.ƒ(s, r) { - x.Width += c.Width - s.l[xi] = x - // Remove element at i. - copy(s.l[i:], s.l[i+1:]) - s.l = s.l[:len(s.l)-1] - xi -= 1 - } else { - x = c - xi = i - } - r -= c.Width - } -} - -func (s *stream) samples() Samples { - samples := make(Samples, len(s.l)) - copy(samples, s.l) - return samples -} diff --git a/vendor/github.com/beorn7/perks/quantile/stream_test.go b/vendor/github.com/beorn7/perks/quantile/stream_test.go deleted file mode 100644 index 85519509..00000000 --- a/vendor/github.com/beorn7/perks/quantile/stream_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package quantile - -import ( - "math" - "math/rand" - "sort" - "testing" -) - -var ( - Targets = map[float64]float64{ - 0.01: 0.001, - 0.10: 0.01, - 0.50: 0.05, - 0.90: 0.01, - 0.99: 0.001, - } - TargetsSmallEpsilon = map[float64]float64{ - 0.01: 0.0001, - 0.10: 0.001, - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - } - LowQuantiles = []float64{0.01, 0.1, 0.5} - HighQuantiles = []float64{0.99, 0.9, 0.5} -) - -const RelativeEpsilon = 0.01 - -func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for quantile, epsilon := range Targets { - n := float64(len(a)) - k := int(quantile * n) - if k < 1 { - k = 1 - } - lower := int((quantile - epsilon) * n) - if lower < 1 { - lower = 1 - } - upper := int(math.Ceil((quantile + epsilon) * n)) - if upper > len(a) { - upper = len(a) - } - w, min, max := a[k-1], a[lower-1], a[upper-1] - if g := s.Query(quantile); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g) - } - } -} - -func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range LowQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - RelativeEpsilon) * qu * n) - upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range HighQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n) - upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func populateStream(s *Stream) []float64 { - a := make([]float64, 0, 1e5+100) - for i := 0; i < cap(a); i++ { - v := rand.NormFloat64() - // Add 5% asymmetric outliers. - if i%20 == 0 { - v = v*v + 1 - } - s.Insert(v) - a = append(a, v) - } - return a -} - -func TestTargetedQuery(t *testing.T) { - rand.Seed(42) - s := NewTargeted(Targets) - a := populateStream(s) - verifyPercsWithAbsoluteEpsilon(t, a, s) -} - -func TestTargetedQuerySmallSampleSize(t *testing.T) { - rand.Seed(42) - s := NewTargeted(TargetsSmallEpsilon) - a := []float64{1, 2, 3, 4, 5} - for _, v := range a { - s.Insert(v) - } - verifyPercsWithAbsoluteEpsilon(t, a, s) - // If not yet flushed, results should be precise: - if !s.flushed() { - for φ, want := range map[float64]float64{ - 0.01: 1, - 0.10: 1, - 0.50: 3, - 0.90: 5, - 0.99: 5, - } { - if got := s.Query(φ); got != want { - t.Errorf("want %f for φ=%f, got %f", want, φ, got) - } - } - } -} - -func TestLowBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewLowBiased(RelativeEpsilon) - a := populateStream(s) - verifyLowPercsWithRelativeEpsilon(t, a, s) -} - -func TestHighBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewHighBiased(RelativeEpsilon) - a := populateStream(s) - verifyHighPercsWithRelativeEpsilon(t, a, s) -} - -// BrokenTestTargetedMerge is broken, see Merge doc comment. -func BrokenTestTargetedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewTargeted(Targets) - s2 := NewTargeted(Targets) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyPercsWithAbsoluteEpsilon(t, a, s1) -} - -// BrokenTestLowBiasedMerge is broken, see Merge doc comment. -func BrokenTestLowBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewLowBiased(RelativeEpsilon) - s2 := NewLowBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyLowPercsWithRelativeEpsilon(t, a, s2) -} - -// BrokenTestHighBiasedMerge is broken, see Merge doc comment. -func BrokenTestHighBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewHighBiased(RelativeEpsilon) - s2 := NewHighBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyHighPercsWithRelativeEpsilon(t, a, s2) -} - -func TestUncompressed(t *testing.T) { - q := NewTargeted(Targets) - for i := 100; i > 0; i-- { - q.Insert(float64(i)) - } - if g := q.Count(); g != 100 { - t.Errorf("want count 100, got %d", g) - } - // Before compression, Query should have 100% accuracy. - for quantile := range Targets { - w := quantile * 100 - if g := q.Query(quantile); g != w { - t.Errorf("want %f, got %f", w, g) - } - } -} - -func TestUncompressedSamples(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.001}) - for i := 1; i <= 100; i++ { - q.Insert(float64(i)) - } - if g := q.Samples().Len(); g != 100 { - t.Errorf("want count 100, got %d", g) - } -} - -func TestUncompressedOne(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.01}) - q.Insert(3.14) - if g := q.Query(0.90); g != 3.14 { - t.Error("want PI, got", g) - } -} - -func TestDefaults(t *testing.T) { - if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 { - t.Errorf("want 0, got %f", g) - } -} diff --git a/vendor/github.com/beorn7/perks/topk/topk.go b/vendor/github.com/beorn7/perks/topk/topk.go deleted file mode 100644 index 5ac3d990..00000000 --- a/vendor/github.com/beorn7/perks/topk/topk.go +++ /dev/null @@ -1,90 +0,0 @@ -package topk - -import ( - "sort" -) - -// http://www.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf - -type Element struct { - Value string - Count int -} - -type Samples []*Element - -func (sm Samples) Len() int { - return len(sm) -} - -func (sm Samples) Less(i, j int) bool { - return sm[i].Count < sm[j].Count -} - -func (sm Samples) Swap(i, j int) { - sm[i], sm[j] = sm[j], sm[i] -} - -type Stream struct { - k int - mon map[string]*Element - - // the minimum Element - min *Element -} - -func New(k int) *Stream { - s := new(Stream) - s.k = k - s.mon = make(map[string]*Element) - s.min = &Element{} - - // Track k+1 so that less frequenet items contended for that spot, - // resulting in k being more accurate. - return s -} - -func (s *Stream) Insert(x string) { - s.insert(&Element{x, 1}) -} - -func (s *Stream) Merge(sm Samples) { - for _, e := range sm { - s.insert(e) - } -} - -func (s *Stream) insert(in *Element) { - e := s.mon[in.Value] - if e != nil { - e.Count++ - } else { - if len(s.mon) < s.k+1 { - e = &Element{in.Value, in.Count} - s.mon[in.Value] = e - } else { - e = s.min - delete(s.mon, e.Value) - e.Value = in.Value - e.Count += in.Count - s.min = e - } - } - if e.Count < s.min.Count { - s.min = e - } -} - -func (s *Stream) Query() Samples { - var sm Samples - for _, e := range s.mon { - sm = append(sm, e) - } - sort.Sort(sort.Reverse(sm)) - - if len(sm) < s.k { - return sm - } - - return sm[:s.k] -} diff --git a/vendor/github.com/beorn7/perks/topk/topk_test.go b/vendor/github.com/beorn7/perks/topk/topk_test.go deleted file mode 100644 index c24f0f72..00000000 --- a/vendor/github.com/beorn7/perks/topk/topk_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package topk - -import ( - "fmt" - "math/rand" - "sort" - "testing" -) - -func TestTopK(t *testing.T) { - stream := New(10) - ss := []*Stream{New(10), New(10), New(10)} - m := make(map[string]int) - for _, s := range ss { - for i := 0; i < 1e6; i++ { - v := fmt.Sprintf("%x", int8(rand.ExpFloat64())) - s.Insert(v) - m[v]++ - } - stream.Merge(s.Query()) - } - - var sm Samples - for x, s := range m { - sm = append(sm, &Element{x, s}) - } - sort.Sort(sort.Reverse(sm)) - - g := stream.Query() - if len(g) != 10 { - t.Fatalf("got %d, want 10", len(g)) - } - for i, e := range g { - if sm[i].Value != e.Value { - t.Errorf("at %d: want %q, got %q", i, sm[i].Value, e.Value) - } - } -} - -func TestQuery(t *testing.T) { - queryTests := []struct { - value string - expected int - }{ - {"a", 1}, - {"b", 2}, - {"c", 2}, - } - - stream := New(2) - for _, tt := range queryTests { - stream.Insert(tt.value) - if n := len(stream.Query()); n != tt.expected { - t.Errorf("want %d, got %d", tt.expected, n) - } - } -} diff --git a/vendor/github.com/coreos/go-oidc/.gitignore b/vendor/github.com/coreos/go-oidc/.gitignore new file mode 100644 index 00000000..c96f2f47 --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/.gitignore @@ -0,0 +1,2 @@ +/bin +/gopath diff --git a/vendor/github.com/coreos/go-oidc/.travis.yml b/vendor/github.com/coreos/go-oidc/.travis.yml new file mode 100644 index 00000000..f2f3c9c8 --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.7.5 + - 1.8 + +install: + - go get -v -t github.com/coreos/go-oidc/... + - go get golang.org/x/tools/cmd/cover + - go get github.com/golang/lint/golint + +script: + - ./test + +notifications: + email: false diff --git a/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md b/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md new file mode 100644 index 00000000..6662073a --- /dev/null +++ b/vendor/github.com/coreos/go-oidc/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# How to Contribute + +CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via +GitHub pull requests. This document outlines some of the conventions on +development workflow, commit message formatting, contact points and other +resources to make it easier to get your contribution accepted. + +# Certificate of Origin + +By contributing to this project you agree to the Developer Certificate of +Origin (DCO). This document was created by the Linux Kernel community and is a +simple statement that you, as a contributor, have the legal right to make the +contribution. See the [DCO](DCO) file for details. + +# Email and Chat + +The project currently uses the general CoreOS email list and IRC channel: +- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev) +- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org + +Please avoid emailing maintainers found in the MAINTAINERS file directly. They +are very busy and read the mailing lists. + +## Getting Started + +- Fork the repository on GitHub +- Read the [README](README.md) for build and test instructions +- Play with the project, submit bugs, submit patches! + +## Contribution Flow + +This is a rough outline of what a contributor's workflow looks like: + +- Create a topic branch from where you want to base your work (usually master). +- Make commits of logical units. +- Make sure your commit messages are in the proper format (see below). +- Push your changes to a topic branch in your fork of the repository. +- Make sure the tests pass, and add any new tests as appropriate. +- Submit a pull request to the original repository. + +Thanks for your contributions! + +### Format of the Commit Message + +We follow a rough convention for commit messages that is designed to answer two +questions: what changed and why. The subject line should feature the what and +the body of the commit should describe the why. + +``` +scripts: add the test-cluster command + +this uses tmux to setup a test cluster that you can easily kill and +start for debugging. + +Fixes #38 +``` + +The format can be described more formally as follows: + +``` +: + + + +