Update go dependencies
This commit is contained in:
parent
a858c549d9
commit
f3bde94d68
643 changed files with 14296 additions and 19354 deletions
82
Gopkg.lock
generated
82
Gopkg.lock
generated
|
@ -4,14 +4,14 @@
|
|||
[[projects]]
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
revision = "eaddaf6dd7ee35fd3c2420c8d27478db176b0485"
|
||||
version = "v0.15.0"
|
||||
revision = "2d3a6656c17a60b0815b7e06ab0be04eacb6e613"
|
||||
version = "v0.16.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Azure/go-autorest"
|
||||
packages = ["autorest","autorest/adal","autorest/azure","autorest/date"]
|
||||
revision = "7aa5b8a6f18b5c15910c767ab005fc4585221177"
|
||||
version = "v9.1.1"
|
||||
revision = "ab5671379918d9af294b6f0e3d8aaa98c829416d"
|
||||
version = "v9.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/PuerkitoBio/purell"
|
||||
|
@ -66,6 +66,12 @@
|
|||
revision = "5741799b275a3c4a5a9623a993576d7545cf7b5c"
|
||||
version = "v2.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/emicklei/go-restful-swagger12"
|
||||
packages = ["."]
|
||||
revision = "dcef7f55730566d41eae5db10e7d6981829720f6"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
packages = ["."]
|
||||
|
@ -100,13 +106,13 @@
|
|||
branch = "master"
|
||||
name = "github.com/go-openapi/spec"
|
||||
packages = ["."]
|
||||
revision = "84b5bee7bcb76f3d17bcbaf421bac44bd5709ca6"
|
||||
revision = "a4fa9574c7aa73b2fc54e251eb9524d0482bb592"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/go-openapi/swag"
|
||||
packages = ["."]
|
||||
revision = "f3f9494671f93fcff853e3c6e9e948b3eb71e590"
|
||||
revision = "cf0bdb963811675a4d7e74901cefc7411a1df939"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
|
@ -124,13 +130,13 @@
|
|||
branch = "master"
|
||||
name = "github.com/golang/groupcache"
|
||||
packages = ["lru"]
|
||||
revision = "b710c8433bd175204919eb38776e944233235d03"
|
||||
revision = "84a468cf14b4376def5d68c722b139b881c450a4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"]
|
||||
revision = "130e6b02ab059e7b717a096f397c5b60111cae74"
|
||||
revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -154,13 +160,13 @@
|
|||
branch = "master"
|
||||
name = "github.com/gophercloud/gophercloud"
|
||||
packages = [".","openstack","openstack/identity/v2/tenants","openstack/identity/v2/tokens","openstack/identity/v3/tokens","openstack/utils","pagination"]
|
||||
revision = "443743e88335413103dcf1997e46d401b264fbcd"
|
||||
revision = "0b6b13c4dd9e07a89f83cbe4617c13ad646d6362"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [".","diskcache"]
|
||||
revision = "c1f8028e62adb3d518b823a2f8e6a95c38bdd3aa"
|
||||
revision = "22a0b1feae53974ed4cfe27bcce70dba061cc5fd"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -190,7 +196,7 @@
|
|||
branch = "master"
|
||||
name = "github.com/juju/ratelimit"
|
||||
packages = ["."]
|
||||
revision = "5b9ff866471762aa2ab2dced63c9fb6f53921342"
|
||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/kr/pty"
|
||||
|
@ -208,7 +214,7 @@
|
|||
branch = "master"
|
||||
name = "github.com/mailru/easyjson"
|
||||
packages = ["buffer","jlexer","jwriter"]
|
||||
revision = "efb36c3268025336c3cdd805e3be5f88d1f62b73"
|
||||
revision = "5f62e4f3afa2f576dc86531b7df4d966b19ef8f8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
|
@ -311,7 +317,7 @@
|
|||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
|
||||
revision = "1bab55dd05dbff384524a6a1c99006d9eb5f139b"
|
||||
revision = "e3fb1a1acd7605367a2b378bc2e2f893c05174b7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -320,10 +326,10 @@
|
|||
revision = "a6e9df898b1336106c743392c48ee0b71f5c4efa"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/spf13/afero"
|
||||
packages = [".","mem"]
|
||||
revision = "5660eeed305fe5f69c8fc6cf899132a459a97064"
|
||||
revision = "8d919cbe7e2627e417f3e45c3c0e489a5b7e2536"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
|
@ -341,31 +347,31 @@
|
|||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "541b9d50ad47e36efd8fb423e938e59ff1691f68"
|
||||
revision = "6a293f2d4b14b8e6d3f0539e383f6d0d30fce3fd"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","context/ctxhttp","html","html/atom","html/charset","http2","http2/hpack","idna","internal/timeseries","lex/httplex","publicsuffix","trace"]
|
||||
revision = "cd69bc3fc700721b709c3a59e16e24c67b58f6ff"
|
||||
revision = "a337091b0525af65de94df2eb7e98bd9962dcbe2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [".","google","internal","jws","jwt"]
|
||||
revision = "bb50c06baba3d0c76f9d125c0719093e315b5b44"
|
||||
revision = "9ff8ebcc8e241d46f52ecc5bff0e5a2f2dbef402"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix","windows"]
|
||||
revision = "8dbc5d05d6edcc104950cc299a1ce6641235bc86"
|
||||
revision = "1e2299c37cc91a509f1b12369872d27be0ce98a6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = ["collate","collate/build","encoding","encoding/charmap","encoding/htmlindex","encoding/internal","encoding/internal/identifier","encoding/japanese","encoding/korean","encoding/simplifiedchinese","encoding/traditionalchinese","encoding/unicode","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","internal/utf8internal","language","runes","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable","width"]
|
||||
revision = "c01e4764d870b77f8abe5096ee19ad20d80e8075"
|
||||
revision = "88f656faf3f37f690df1a32515b479415e1a6769"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
|
@ -377,13 +383,13 @@
|
|||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "f676e0f3ac6395ff1a529ae59a6670878a8371a6"
|
||||
revision = "11c7f9e547da6db876260ce49ea7536985904c9b"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [".","balancer","codes","connectivity","credentials","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","stats","status","tap","transport"]
|
||||
revision = "f7bf885db0b7479a537ec317c6e48ce53145f3db"
|
||||
version = "v1.7.0"
|
||||
revision = "5ffe3083946d5603a0578721101dc8165b1d5b5f"
|
||||
version = "v1.7.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/fsnotify.v1"
|
||||
|
@ -410,52 +416,56 @@
|
|||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
||||
|
||||
[[projects]]
|
||||
branch = "release-1.8"
|
||||
name = "k8s.io/api"
|
||||
packages = ["admissionregistration/v1alpha1","apps/v1","apps/v1beta1","apps/v1beta2","authentication/v1","authentication/v1beta1","authorization/v1","authorization/v1beta1","autoscaling/v1","autoscaling/v2beta1","batch/v1","batch/v1beta1","batch/v2alpha1","certificates/v1beta1","core/v1","extensions/v1beta1","networking/v1","policy/v1beta1","rbac/v1","rbac/v1alpha1","rbac/v1beta1","scheduling/v1alpha1","settings/v1alpha1","storage/v1","storage/v1beta1"]
|
||||
revision = "409c3b2393cd3359f275bd8b883b4d9c5aec41f6"
|
||||
packages = ["admissionregistration/v1alpha1","apps/v1beta1","apps/v1beta2","authentication/v1","authentication/v1beta1","authorization/v1","authorization/v1beta1","autoscaling/v1","autoscaling/v2beta1","batch/v1","batch/v1beta1","batch/v2alpha1","certificates/v1beta1","core/v1","extensions/v1beta1","networking/v1","policy/v1beta1","rbac/v1","rbac/v1alpha1","rbac/v1beta1","scheduling/v1alpha1","settings/v1alpha1","storage/v1","storage/v1beta1"]
|
||||
revision = "4df58c811fe2e65feb879227b2b245e4dc26e7ad"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiextensions-apiserver"
|
||||
packages = ["pkg/apis/apiextensions","pkg/apis/apiextensions/v1beta1","pkg/client/clientset/clientset","pkg/client/clientset/clientset/scheme","pkg/client/clientset/clientset/typed/apiextensions/v1beta1","pkg/features"]
|
||||
revision = "83f1a7e2b8384c17fb102b6616e08825ad12992d"
|
||||
revision = "51a1910459f074162eb4e25233e461fe91e99405"
|
||||
|
||||
[[projects]]
|
||||
branch = "release-1.8"
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = ["pkg/api/equality","pkg/api/errors","pkg/api/meta","pkg/api/resource","pkg/api/validation","pkg/apimachinery","pkg/apimachinery/announced","pkg/apimachinery/registered","pkg/apis/meta/internalversion","pkg/apis/meta/v1","pkg/apis/meta/v1/unstructured","pkg/apis/meta/v1/validation","pkg/apis/meta/v1alpha1","pkg/conversion","pkg/conversion/queryparams","pkg/conversion/unstructured","pkg/fields","pkg/labels","pkg/runtime","pkg/runtime/schema","pkg/runtime/serializer","pkg/runtime/serializer/json","pkg/runtime/serializer/protobuf","pkg/runtime/serializer/recognizer","pkg/runtime/serializer/streaming","pkg/runtime/serializer/versioning","pkg/selection","pkg/types","pkg/util/cache","pkg/util/clock","pkg/util/diff","pkg/util/errors","pkg/util/framer","pkg/util/httpstream","pkg/util/httpstream/spdy","pkg/util/intstr","pkg/util/json","pkg/util/mergepatch","pkg/util/net","pkg/util/remotecommand","pkg/util/runtime","pkg/util/sets","pkg/util/strategicpatch","pkg/util/uuid","pkg/util/validation","pkg/util/validation/field","pkg/util/wait","pkg/util/yaml","pkg/version","pkg/watch","third_party/forked/golang/json","third_party/forked/golang/netutil","third_party/forked/golang/reflect"]
|
||||
revision = "e9a29eff7d472df0f7da9ead5ab59b74e74a07ec"
|
||||
packages = ["pkg/api/equality","pkg/api/errors","pkg/api/meta","pkg/api/resource","pkg/api/validation","pkg/apimachinery","pkg/apimachinery/announced","pkg/apimachinery/registered","pkg/apis/meta/internalversion","pkg/apis/meta/v1","pkg/apis/meta/v1/unstructured","pkg/apis/meta/v1/validation","pkg/apis/meta/v1alpha1","pkg/conversion","pkg/conversion/queryparams","pkg/conversion/unstructured","pkg/fields","pkg/labels","pkg/runtime","pkg/runtime/schema","pkg/runtime/serializer","pkg/runtime/serializer/json","pkg/runtime/serializer/protobuf","pkg/runtime/serializer/recognizer","pkg/runtime/serializer/streaming","pkg/runtime/serializer/versioning","pkg/selection","pkg/types","pkg/util/cache","pkg/util/clock","pkg/util/diff","pkg/util/errors","pkg/util/framer","pkg/util/httpstream","pkg/util/httpstream/spdy","pkg/util/intstr","pkg/util/json","pkg/util/mergepatch","pkg/util/net","pkg/util/rand","pkg/util/remotecommand","pkg/util/runtime","pkg/util/sets","pkg/util/strategicpatch","pkg/util/uuid","pkg/util/validation","pkg/util/validation/field","pkg/util/wait","pkg/util/yaml","pkg/version","pkg/watch","third_party/forked/golang/json","third_party/forked/golang/netutil","third_party/forked/golang/reflect"]
|
||||
revision = "019ae5ada31de202164b118aee88ee2d14075c31"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apiserver"
|
||||
packages = ["pkg/authentication/authenticator","pkg/authentication/serviceaccount","pkg/authentication/user","pkg/features","pkg/server/healthz","pkg/util/feature","pkg/util/logs"]
|
||||
revision = "d299c880c4e33854f8c45bdd7ab599fb54cbe575"
|
||||
revision = "7001bc4df8883d4a0ec84cd4b2117655a0009b6c"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/client-go"
|
||||
packages = ["discovery","discovery/fake","kubernetes","kubernetes/fake","kubernetes/scheme","kubernetes/typed/admissionregistration/v1alpha1","kubernetes/typed/admissionregistration/v1alpha1/fake","kubernetes/typed/apps/v1","kubernetes/typed/apps/v1/fake","kubernetes/typed/apps/v1beta1","kubernetes/typed/apps/v1beta1/fake","kubernetes/typed/apps/v1beta2","kubernetes/typed/apps/v1beta2/fake","kubernetes/typed/authentication/v1","kubernetes/typed/authentication/v1/fake","kubernetes/typed/authentication/v1beta1","kubernetes/typed/authentication/v1beta1/fake","kubernetes/typed/authorization/v1","kubernetes/typed/authorization/v1/fake","kubernetes/typed/authorization/v1beta1","kubernetes/typed/authorization/v1beta1/fake","kubernetes/typed/autoscaling/v1","kubernetes/typed/autoscaling/v1/fake","kubernetes/typed/autoscaling/v2beta1","kubernetes/typed/autoscaling/v2beta1/fake","kubernetes/typed/batch/v1","kubernetes/typed/batch/v1/fake","kubernetes/typed/batch/v1beta1","kubernetes/typed/batch/v1beta1/fake","kubernetes/typed/batch/v2alpha1","kubernetes/typed/batch/v2alpha1/fake","kubernetes/typed/certificates/v1beta1","kubernetes/typed/certificates/v1beta1/fake","kubernetes/typed/core/v1","kubernetes/typed/core/v1/fake","kubernetes/typed/extensions/v1beta1","kubernetes/typed/extensions/v1beta1/fake","kubernetes/typed/networking/v1","kubernetes/typed/networking/v1/fake","kubernetes/typed/policy/v1beta1","kubernetes/typed/policy/v1beta1/fake","kubernetes/typed/rbac/v1","kubernetes/typed/rbac/v1/fake","kubernetes/typed/rbac/v1alpha1","kubernetes/typed/rbac/v1alpha1/fake","kubernetes/typed/rbac/v1beta1","kubernetes/typed/rbac/v1beta1/fake","kubernetes/typed/scheduling/v1alpha1","kubernetes/typed/scheduling/v1alpha1/fake","kubernetes/typed/settings/v1alpha1","kubernetes/typed/settings/v1alpha1/fake","kubernetes/typed/storage/v1","kubernetes/typed/storage/v1/fake","kubernetes/typed/storage/v1beta1","kubernetes/typed/storage/v1beta1/fake","pkg/version","plugin/pkg/client/auth","plugin/pkg/client/auth/azure","plugin/pkg/client/auth/gcp","plugin/pkg/client/auth/oidc","plugin/pkg/client/auth/openstack","rest","rest/watch","testing","third_party/forked/golang/template","tools/auth","tools/cache","tools/clientcmd","tools/clientcmd/api","tools/clientcmd/api/latest","tools/clientcmd/api/v1","tools/leaderelection","tools/leaderelection/resourcelock","tools/metrics","tools/pager","tools/record","tools/reference","tools/remotecommand","transport","transport/spdy","util/buffer","util/cert","util/cert/triple","util/exec","util/flowcontrol","util/homedir","util/integer","util/jsonpath","util/retry","util/workqueue"]
|
||||
revision = "076e344c86e52f088b78615f815b245f6d613537"
|
||||
packages = ["discovery","discovery/fake","kubernetes","kubernetes/fake","kubernetes/scheme","kubernetes/typed/admissionregistration/v1alpha1","kubernetes/typed/admissionregistration/v1alpha1/fake","kubernetes/typed/apps/v1beta1","kubernetes/typed/apps/v1beta1/fake","kubernetes/typed/apps/v1beta2","kubernetes/typed/apps/v1beta2/fake","kubernetes/typed/authentication/v1","kubernetes/typed/authentication/v1/fake","kubernetes/typed/authentication/v1beta1","kubernetes/typed/authentication/v1beta1/fake","kubernetes/typed/authorization/v1","kubernetes/typed/authorization/v1/fake","kubernetes/typed/authorization/v1beta1","kubernetes/typed/authorization/v1beta1/fake","kubernetes/typed/autoscaling/v1","kubernetes/typed/autoscaling/v1/fake","kubernetes/typed/autoscaling/v2beta1","kubernetes/typed/autoscaling/v2beta1/fake","kubernetes/typed/batch/v1","kubernetes/typed/batch/v1/fake","kubernetes/typed/batch/v1beta1","kubernetes/typed/batch/v1beta1/fake","kubernetes/typed/batch/v2alpha1","kubernetes/typed/batch/v2alpha1/fake","kubernetes/typed/certificates/v1beta1","kubernetes/typed/certificates/v1beta1/fake","kubernetes/typed/core/v1","kubernetes/typed/core/v1/fake","kubernetes/typed/extensions/v1beta1","kubernetes/typed/extensions/v1beta1/fake","kubernetes/typed/networking/v1","kubernetes/typed/networking/v1/fake","kubernetes/typed/policy/v1beta1","kubernetes/typed/policy/v1beta1/fake","kubernetes/typed/rbac/v1","kubernetes/typed/rbac/v1/fake","kubernetes/typed/rbac/v1alpha1","kubernetes/typed/rbac/v1alpha1/fake","kubernetes/typed/rbac/v1beta1","kubernetes/typed/rbac/v1beta1/fake","kubernetes/typed/scheduling/v1alpha1","kubernetes/typed/scheduling/v1alpha1/fake","kubernetes/typed/settings/v1alpha1","kubernetes/typed/settings/v1alpha1/fake","kubernetes/typed/storage/v1","kubernetes/typed/storage/v1/fake","kubernetes/typed/storage/v1beta1","kubernetes/typed/storage/v1beta1/fake","pkg/version","plugin/pkg/client/auth","plugin/pkg/client/auth/azure","plugin/pkg/client/auth/gcp","plugin/pkg/client/auth/oidc","plugin/pkg/client/auth/openstack","rest","rest/watch","testing","third_party/forked/golang/template","tools/auth","tools/cache","tools/clientcmd","tools/clientcmd/api","tools/clientcmd/api/latest","tools/clientcmd/api/v1","tools/leaderelection","tools/leaderelection/resourcelock","tools/metrics","tools/pager","tools/record","tools/reference","tools/remotecommand","transport","transport/spdy","util/cert","util/cert/triple","util/exec","util/flowcontrol","util/homedir","util/integer","util/jsonpath","util/retry","util/workqueue"]
|
||||
revision = "2ae454230481a7cb5544325e12ad7658ecccd19b"
|
||||
version = "v5.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/kube-openapi"
|
||||
packages = ["pkg/common"]
|
||||
revision = "89ae48fe8691077463af5b7fb3b6f194632c5946"
|
||||
revision = "39a7bf85c140f972372c2a0d1ee40adbf0c8bfe1"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/kubernetes"
|
||||
packages = ["pkg/api","pkg/api/helper","pkg/api/install","pkg/api/service","pkg/api/v1","pkg/api/v1/helper","pkg/api/v1/pod","pkg/api/validation","pkg/apis/extensions","pkg/apis/networking","pkg/capabilities","pkg/cloudprovider","pkg/controller","pkg/features","pkg/kubelet/apis","pkg/kubelet/apis/cri/v1alpha1/runtime","pkg/kubelet/container","pkg/kubelet/types","pkg/kubelet/util/format","pkg/kubelet/util/ioutils","pkg/kubelet/util/sliceutils","pkg/security/apparmor","pkg/serviceaccount","pkg/util/file","pkg/util/filesystem","pkg/util/hash","pkg/util/io","pkg/util/mount","pkg/util/net/sets","pkg/util/nsenter","pkg/util/parsers","pkg/util/pointer","pkg/util/sysctl","pkg/util/taints","pkg/volume","pkg/volume/util","third_party/forked/golang/expansion"]
|
||||
revision = "88975e98d6f4a84929a243abeb772de16399a4e9"
|
||||
packages = ["pkg/api","pkg/api/helper","pkg/api/install","pkg/api/service","pkg/api/util","pkg/api/v1","pkg/api/v1/helper","pkg/api/v1/pod","pkg/api/validation","pkg/apis/extensions","pkg/apis/networking","pkg/capabilities","pkg/cloudprovider","pkg/controller","pkg/features","pkg/kubelet/apis","pkg/kubelet/apis/cri/v1alpha1/runtime","pkg/kubelet/container","pkg/kubelet/types","pkg/kubelet/util/format","pkg/kubelet/util/ioutils","pkg/kubelet/util/sliceutils","pkg/security/apparmor","pkg/serviceaccount","pkg/util/file","pkg/util/filesystem","pkg/util/hash","pkg/util/io","pkg/util/mount","pkg/util/net/sets","pkg/util/parsers","pkg/util/pointer","pkg/util/sysctl","pkg/util/taints","pkg/volume","pkg/volume/util","third_party/forked/golang/expansion"]
|
||||
revision = "f0efb3cb883751c5ffdbe6d515f3cb4fbe7b7acd"
|
||||
version = "v1.8.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/utils"
|
||||
packages = ["exec"]
|
||||
revision = "4fe312863be2155a7b68acd2aff1c9221b24e68c"
|
||||
revision = "bf963466fd3fea33c428098b12a89d8ecd012f25"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "6afb98c9a0bdde143167e3ad0ac1735954c2aa4ca5c60402198afbf57a0f953f"
|
||||
inputs-digest = "cb7f34d9108be87b2601c0d4acbd6faa41bdf211a082760fa1b4d4300bf3e959"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -95,16 +95,16 @@
|
|||
|
||||
[[constraint]]
|
||||
name = "k8s.io/api"
|
||||
revision = "409c3b2393cd3359f275bd8b883b4d9c5aec41f6"
|
||||
branch = "release-1.8"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/apimachinery"
|
||||
revision = "e9a29eff7d472df0f7da9ead5ab59b74e74a07ec"
|
||||
branch = "release-1.8"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/client-go"
|
||||
revision = "076e344c86e52f088b78615f815b245f6d613537"
|
||||
version = "v5.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/kubernetes"
|
||||
revision = "88975e98d6f4a84929a243abeb772de16399a4e9"
|
||||
version = "v1.8.3"
|
||||
|
|
9
vendor/cloud.google.com/go/.travis.yml
generated
vendored
9
vendor/cloud.google.com/go/.travis.yml
generated
vendored
|
@ -4,11 +4,16 @@ go:
|
|||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
install:
|
||||
- go get -v cloud.google.com/go/...
|
||||
script:
|
||||
- openssl aes-256-cbc -K $encrypted_a8b3f4fc85f4_key -iv $encrypted_a8b3f4fc85f4_iv -in key.json.enc -out key.json -d
|
||||
- GCLOUD_TESTS_GOLANG_PROJECT_ID="dulcet-port-762" GCLOUD_TESTS_GOLANG_KEY="$(pwd)/key.json"
|
||||
- openssl aes-256-cbc -K $encrypted_a8b3f4fc85f4_key -iv $encrypted_a8b3f4fc85f4_iv -in keys.tar.enc -out keys.tar -d
|
||||
- tar xvf keys.tar
|
||||
- GCLOUD_TESTS_GOLANG_PROJECT_ID="dulcet-port-762"
|
||||
GCLOUD_TESTS_GOLANG_KEY="$(pwd)/dulcet-port-762-key.json"
|
||||
GCLOUD_TESTS_GOLANG_FIRESTORE_PROJECT_ID="gcloud-golang-firestore-tests"
|
||||
GCLOUD_TESTS_GOLANG_FIRESTORE_KEY="$(pwd)/gcloud-golang-firestore-tests-key.json"
|
||||
./run-tests.sh $TRAVIS_COMMIT
|
||||
env:
|
||||
matrix:
|
||||
|
|
20
vendor/cloud.google.com/go/CONTRIBUTING.md
generated
vendored
20
vendor/cloud.google.com/go/CONTRIBUTING.md
generated
vendored
|
@ -31,9 +31,12 @@ To run the integrations tests, creating and configuration of a project in the
|
|||
Google Developers Console is required.
|
||||
|
||||
After creating a project, you must [create a service account](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount).
|
||||
Ensure the project-level **Owner** [IAM role](console.cloud.google.com/iam-admin/iam/project)
|
||||
(or **Editor** and **Logs Configuration Writer** roles) are added to the
|
||||
service account.
|
||||
Ensure the project-level **Owner**
|
||||
[IAM role](console.cloud.google.com/iam-admin/iam/project) role is added to the
|
||||
service account. Alternatively, the account can be granted all of the following roles:
|
||||
- **Editor**
|
||||
- **Logs Configuration Writer**
|
||||
- **PubSub Admin**
|
||||
|
||||
Once you create a project, set the following environment variables to be able to
|
||||
run the against the actual APIs.
|
||||
|
@ -69,10 +72,15 @@ $ gcloud preview datastore create-indexes datastore/testdata/index.yaml
|
|||
$ gsutil mb gs://$GCLOUD_TESTS_GOLANG_PROJECT_ID
|
||||
$ gsutil acl ch -g cloud-logs@google.com:O gs://$GCLOUD_TESTS_GOLANG_PROJECT_ID
|
||||
|
||||
# Create a PubSub topic for integration tests of storage notifications.
|
||||
$ gcloud beta pubsub topics create go-storage-notification-test
|
||||
|
||||
# Create a Spanner instance for the spanner integration tests.
|
||||
$ gcloud beta spanner instances create go-integration-test --config regional-us-central1 --nodes 1 --description 'Instance for go client test'
|
||||
# NOTE: Spanner instances are priced by the node-hour, so you may want to delete
|
||||
# the instance after testing with 'gcloud beta spanner instances delete'.
|
||||
|
||||
|
||||
```
|
||||
|
||||
Once you've set the environment variables, you can run the integration tests by
|
||||
|
@ -88,9 +96,9 @@ Before we can accept your pull requests you'll need to sign a Contributor
|
|||
License Agreement (CLA):
|
||||
|
||||
- **If you are an individual writing original source code** and **you own the
|
||||
- intellectual property**, then you'll need to sign an [individual CLA][indvcla].
|
||||
- **If you work for a company that wants to allow you to contribute your work**,
|
||||
then you'll need to sign a [corporate CLA][corpcla].
|
||||
intellectual property**, then you'll need to sign an [individual CLA][indvcla].
|
||||
- **If you work for a company that wants to allow you to contribute your
|
||||
work**, then you'll need to sign a [corporate CLA][corpcla].
|
||||
|
||||
You can sign these electronically (just scroll to the bottom). After that,
|
||||
we'll be able to accept your pull requests.
|
||||
|
|
29
vendor/cloud.google.com/go/README.md
generated
vendored
29
vendor/cloud.google.com/go/README.md
generated
vendored
|
@ -33,10 +33,37 @@ make backwards-incompatible changes.
|
|||
|
||||
## News
|
||||
|
||||
*v0.15.0*
|
||||
_October 30, 2017_
|
||||
|
||||
*v0.16.0*
|
||||
|
||||
- Other bigquery changes:
|
||||
- `JobIterator.Next` returns `*Job`; removed `JobInfo` (BREAKING CHANGE).
|
||||
- UseStandardSQL is deprecated; set UseLegacySQL to true if you need
|
||||
Legacy SQL.
|
||||
- Uploader.Put will generate a random insert ID if you do not provide one.
|
||||
- Support time partitioning for load jobs.
|
||||
- Support dry-run queries.
|
||||
- A `Job` remembers its last retrieved status.
|
||||
- Support retrieving job configuration.
|
||||
- Support labels for jobs and tables.
|
||||
- Support dataset access lists.
|
||||
- Improve support for external data sources, including data from Bigtable and
|
||||
Google Sheets, and tables with external data.
|
||||
- Support updating a table's view configuration.
|
||||
- Fix uploading civil times with nanoseconds.
|
||||
|
||||
- storage:
|
||||
- Support PubSub notifications.
|
||||
- Support Requester Pays buckets.
|
||||
|
||||
- profiler: Support goroutine and mutex profile types.
|
||||
|
||||
|
||||
_October 3, 2017_
|
||||
|
||||
*v0.15.0*
|
||||
|
||||
- firestore: beta release. See the
|
||||
[announcement](https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html).
|
||||
|
||||
|
|
BIN
vendor/cloud.google.com/go/key.json.enc
generated
vendored
BIN
vendor/cloud.google.com/go/key.json.enc
generated
vendored
Binary file not shown.
BIN
vendor/cloud.google.com/go/keys.tar.enc
generated
vendored
Normal file
BIN
vendor/cloud.google.com/go/keys.tar.enc
generated
vendored
Normal file
Binary file not shown.
1
vendor/github.com/Azure/go-autorest/.travis.yml
generated
vendored
1
vendor/github.com/Azure/go-autorest/.travis.yml
generated
vendored
|
@ -6,7 +6,6 @@ go:
|
|||
- 1.9
|
||||
- 1.8
|
||||
- 1.7
|
||||
- 1.6
|
||||
|
||||
install:
|
||||
- go get -u github.com/golang/lint/golint
|
||||
|
|
33
vendor/github.com/Azure/go-autorest/CHANGELOG.md
generated
vendored
33
vendor/github.com/Azure/go-autorest/CHANGELOG.md
generated
vendored
|
@ -1,5 +1,38 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 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
|
||||
|
||||
|
|
3
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
3
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
|
@ -87,6 +87,9 @@ const (
|
|||
// 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)
|
||||
}
|
||||
|
||||
|
|
245
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
245
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
|
@ -16,6 +16,8 @@ package azure
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -37,6 +39,152 @@ const (
|
|||
operationSucceeded string = "Succeeded"
|
||||
)
|
||||
|
||||
var pollingCodes = [...]int{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
|
||||
|
@ -48,8 +196,7 @@ func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
|
|||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
pollingCodes := []int{http.StatusAccepted, http.StatusCreated, http.StatusOK}
|
||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes...) {
|
||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
@ -66,10 +213,11 @@ func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
|
|||
break
|
||||
}
|
||||
|
||||
r, err = newPollingRequest(resp, ps)
|
||||
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,
|
||||
|
@ -160,36 +308,42 @@ func (ps provisioningStatus) hasProvisioningError() bool {
|
|||
return ps.ProvisioningError != ServiceError{}
|
||||
}
|
||||
|
||||
type pollingResponseFormat string
|
||||
// PollingMethodType defines a type used for enumerating polling mechanisms.
|
||||
type PollingMethodType string
|
||||
|
||||
const (
|
||||
usesOperationResponse pollingResponseFormat = "OperationResponse"
|
||||
usesProvisioningStatus pollingResponseFormat = "ProvisioningStatus"
|
||||
formatIsUnknown pollingResponseFormat = ""
|
||||
// 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 {
|
||||
responseFormat pollingResponseFormat
|
||||
uri string
|
||||
state string
|
||||
code string
|
||||
message string
|
||||
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)
|
||||
return hasSucceeded(ps.State)
|
||||
}
|
||||
|
||||
func (ps pollingState) hasTerminated() bool {
|
||||
return hasTerminated(ps.state)
|
||||
return hasTerminated(ps.State)
|
||||
}
|
||||
|
||||
func (ps pollingState) hasFailed() bool {
|
||||
return hasFailed(ps.state)
|
||||
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)
|
||||
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
|
||||
|
@ -204,7 +358,7 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
|
|||
// -- 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.responseFormat == usesOperationResponse {
|
||||
if ps.PollingMethod == PollingAsyncOperation {
|
||||
pt = &operationResource{}
|
||||
} else {
|
||||
pt = &provisioningStatus{}
|
||||
|
@ -212,30 +366,30 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
|
|||
|
||||
// If this is the first request (that is, the polling response shape is unknown), determine how
|
||||
// to poll and what to expect
|
||||
if ps.responseFormat == formatIsUnknown {
|
||||
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.responseFormat = usesOperationResponse
|
||||
ps.URI = getAsyncOperation(resp)
|
||||
if ps.URI != "" {
|
||||
ps.PollingMethod = PollingAsyncOperation
|
||||
} else {
|
||||
ps.responseFormat = usesProvisioningStatus
|
||||
ps.PollingMethod = PollingLocation
|
||||
}
|
||||
|
||||
// Else, use the Location header
|
||||
if ps.uri == "" {
|
||||
ps.uri = autorest.GetLocation(resp)
|
||||
if ps.URI == "" {
|
||||
ps.URI = autorest.GetLocation(resp)
|
||||
}
|
||||
|
||||
// Lastly, requests against an existing resource, use the last request URI
|
||||
if ps.uri == "" {
|
||||
if ps.URI == "" {
|
||||
m := strings.ToUpper(req.Method)
|
||||
if m == http.MethodPatch || m == http.MethodPut || m == http.MethodGet {
|
||||
ps.uri = req.URL.String()
|
||||
ps.URI = req.URL.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,23 +410,23 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
|
|||
// -- Unknown states are per-service inprogress states
|
||||
// -- Otherwise, infer state from HTTP status code
|
||||
if pt.hasTerminated() {
|
||||
ps.state = pt.state()
|
||||
ps.State = pt.state()
|
||||
} else if pt.state() != "" {
|
||||
ps.state = operationInProgress
|
||||
ps.State = operationInProgress
|
||||
} else {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusAccepted:
|
||||
ps.state = operationInProgress
|
||||
ps.State = operationInProgress
|
||||
|
||||
case http.StatusNoContent, http.StatusCreated, http.StatusOK:
|
||||
ps.state = operationSucceeded
|
||||
ps.State = operationSucceeded
|
||||
|
||||
default:
|
||||
ps.state = operationFailed
|
||||
ps.State = operationFailed
|
||||
}
|
||||
}
|
||||
|
||||
if ps.state == operationInProgress && ps.uri == "" {
|
||||
if 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)
|
||||
}
|
||||
|
||||
|
@ -281,35 +435,30 @@ func updatePollingState(resp *http.Response, ps *pollingState) error {
|
|||
// -- Response
|
||||
// -- Otherwise, Unknown
|
||||
if ps.hasFailed() {
|
||||
if ps.responseFormat == usesOperationResponse {
|
||||
if ps.PollingMethod == PollingAsyncOperation {
|
||||
or := pt.(*operationResource)
|
||||
ps.code = or.OperationError.Code
|
||||
ps.message = or.OperationError.Message
|
||||
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
|
||||
ps.Code = p.ProvisioningError.Code
|
||||
ps.Message = p.ProvisioningError.Message
|
||||
} else {
|
||||
ps.code = "Unknown"
|
||||
ps.message = "None"
|
||||
ps.Code = "Unknown"
|
||||
ps.Message = "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newPollingRequest(resp *http.Response, ps pollingState) (*http.Request, error) {
|
||||
req := resp.Request
|
||||
if req == nil {
|
||||
return nil, autorest.NewError("azure", "newPollingRequest", "Azure Polling Error - Original HTTP request is missing")
|
||||
}
|
||||
|
||||
reqPoll, err := autorest.Prepare(&http.Request{Cancel: req.Cancel},
|
||||
func newPollingRequest(ps pollingState) (*http.Request, error) {
|
||||
reqPoll, err := autorest.Prepare(&http.Request{},
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(ps.uri))
|
||||
autorest.WithBaseURL(ps.URI))
|
||||
if err != nil {
|
||||
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.uri)
|
||||
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.URI)
|
||||
}
|
||||
|
||||
return reqPoll, nil
|
||||
|
|
293
vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go
generated
vendored
293
vendor/github.com/Azure/go-autorest/autorest/azure/async_test.go
generated
vendored
|
@ -15,6 +15,9 @@ package azure
|
|||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -145,27 +148,27 @@ func TestProvisioningStatus_HasTerminatedReturnsFalseForUnknownStates(t *testing
|
|||
}
|
||||
|
||||
func TestPollingState_HasSucceededReturnsFalseIfNotSuccess(t *testing.T) {
|
||||
if (pollingState{state: "not a success string"}).hasSucceeded() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
if (pollingState{State: "not a known state"}).hasTerminated() {
|
||||
t.Fatalf("azure: pollingState#hasTerminated returned true for a non-terminal operation")
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +185,7 @@ func TestUpdatePollingState_ReturnsTerminatedForKnownProvisioningStates(t *testi
|
|||
for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} {
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, state))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
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)
|
||||
|
@ -193,7 +196,7 @@ func TestUpdatePollingState_ReturnsTerminatedForKnownProvisioningStates(t *testi
|
|||
func TestUpdatePollingState_ReturnsSuccessForSuccessfulProvisioningState(t *testing.T) {
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, operationSucceeded))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
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)
|
||||
|
@ -204,7 +207,7 @@ func TestUpdatePollingState_ReturnsInProgressForAllOtherProvisioningStates(t *te
|
|||
s := "not a recognized state"
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(pollingStateFormat, s))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
ps := &pollingState{PollingMethod: PollingLocation}
|
||||
updatePollingState(resp, ps)
|
||||
if ps.hasTerminated() {
|
||||
t.Fatalf("azure: updatePollingState returned terminated for unknown state '%s'", s)
|
||||
|
@ -215,7 +218,7 @@ func TestUpdatePollingState_ReturnsSuccessWhenProvisioningStateFieldIsAbsentForS
|
|||
for _, sc := range []int{http.StatusOK, http.StatusCreated, http.StatusNoContent} {
|
||||
resp := mocks.NewResponseWithContent(pollingStateEmpty)
|
||||
resp.StatusCode = sc
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
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)
|
||||
|
@ -226,7 +229,7 @@ func TestUpdatePollingState_ReturnsSuccessWhenProvisioningStateFieldIsAbsentForS
|
|||
func TestUpdatePollingState_ReturnsInProgressWhenProvisioningStateFieldIsAbsentForAccepted(t *testing.T) {
|
||||
resp := mocks.NewResponseWithContent(pollingStateEmpty)
|
||||
resp.StatusCode = http.StatusAccepted
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
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")
|
||||
|
@ -236,7 +239,7 @@ func TestUpdatePollingState_ReturnsInProgressWhenProvisioningStateFieldIsAbsentF
|
|||
func TestUpdatePollingState_ReturnsFailedWhenProvisioningStateFieldIsAbsentForUnknownStatusCodes(t *testing.T) {
|
||||
resp := mocks.NewResponseWithContent(pollingStateEmpty)
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
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")
|
||||
|
@ -247,7 +250,7 @@ func TestUpdatePollingState_ReturnsTerminatedForKnownOperationResourceStates(t *
|
|||
for _, state := range []string{operationSucceeded, operationCanceled, operationFailed} {
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, state))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesOperationResponse}
|
||||
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)
|
||||
|
@ -258,7 +261,7 @@ func TestUpdatePollingState_ReturnsTerminatedForKnownOperationResourceStates(t *
|
|||
func TestUpdatePollingState_ReturnsSuccessForSuccessfulOperationResourceState(t *testing.T) {
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, operationSucceeded))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesOperationResponse}
|
||||
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)
|
||||
|
@ -269,7 +272,7 @@ func TestUpdatePollingState_ReturnsInProgressForAllOtherOperationResourceStates(
|
|||
s := "not a recognized state"
|
||||
resp := mocks.NewResponseWithContent(fmt.Sprintf(operationResourceFormat, s))
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesOperationResponse}
|
||||
ps := &pollingState{PollingMethod: PollingAsyncOperation}
|
||||
updatePollingState(resp, ps)
|
||||
if ps.hasTerminated() {
|
||||
t.Fatalf("azure: updatePollingState returned terminated for unknown state '%s'", s)
|
||||
|
@ -280,7 +283,7 @@ func TestUpdatePollingState_CopiesTheResponseBody(t *testing.T) {
|
|||
s := fmt.Sprintf(pollingStateFormat, operationSucceeded)
|
||||
resp := mocks.NewResponseWithContent(s)
|
||||
resp.StatusCode = 42
|
||||
ps := &pollingState{responseFormat: usesOperationResponse}
|
||||
ps := &pollingState{PollingMethod: PollingAsyncOperation}
|
||||
updatePollingState(resp, ps)
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
|
@ -294,7 +297,7 @@ func TestUpdatePollingState_CopiesTheResponseBody(t *testing.T) {
|
|||
func TestUpdatePollingState_ClosesTheOriginalResponseBody(t *testing.T) {
|
||||
resp := mocks.NewResponse()
|
||||
b := resp.Body.(*mocks.Body)
|
||||
ps := &pollingState{responseFormat: usesProvisioningStatus}
|
||||
ps := &pollingState{PollingMethod: PollingLocation}
|
||||
updatePollingState(resp, ps)
|
||||
if b.IsOpen() {
|
||||
t.Fatal("azure: updatePollingState failed to close the original http.Response Body")
|
||||
|
@ -312,23 +315,23 @@ func TestUpdatePollingState_FailsWhenResponseLacksRequest(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUpdatePollingState_SetsTheResponseFormatWhenUsingTheAzureAsyncOperationHeader(t *testing.T) {
|
||||
func TestUpdatePollingState_SetsThePollingMethodWhenUsingTheAzureAsyncOperationHeader(t *testing.T) {
|
||||
ps := pollingState{}
|
||||
updatePollingState(newAsynchronousResponse(), &ps)
|
||||
|
||||
if ps.responseFormat != usesOperationResponse {
|
||||
if ps.PollingMethod != PollingAsyncOperation {
|
||||
t.Fatal("azure: updatePollingState failed to set the correct response format when using the Azure-AsyncOperation header")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePollingState_SetsTheResponseFormatWhenUsingTheAzureAsyncOperationHeaderIsMissing(t *testing.T) {
|
||||
func TestUpdatePollingState_SetsThePollingMethodWhenUsingTheAzureAsyncOperationHeaderIsMissing(t *testing.T) {
|
||||
resp := newAsynchronousResponse()
|
||||
resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
|
||||
ps := pollingState{}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.responseFormat != usesProvisioningStatus {
|
||||
if ps.PollingMethod != PollingLocation {
|
||||
t.Fatal("azure: updatePollingState failed to set the correct response format when the Azure-AsyncOperation header is absent")
|
||||
}
|
||||
}
|
||||
|
@ -337,10 +340,10 @@ func TestUpdatePollingState_DoesNotChangeAnExistingReponseFormat(t *testing.T) {
|
|||
resp := newAsynchronousResponse()
|
||||
resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
|
||||
ps := pollingState{responseFormat: usesOperationResponse}
|
||||
ps := pollingState{PollingMethod: PollingAsyncOperation}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.responseFormat != usesOperationResponse {
|
||||
if ps.PollingMethod != PollingAsyncOperation {
|
||||
t.Fatal("azure: updatePollingState failed to leave an existing response format setting")
|
||||
}
|
||||
}
|
||||
|
@ -351,7 +354,7 @@ func TestUpdatePollingState_PrefersTheAzureAsyncOperationHeader(t *testing.T) {
|
|||
ps := pollingState{}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.uri != mocks.TestAzureAsyncURL {
|
||||
if ps.URI != mocks.TestAzureAsyncURL {
|
||||
t.Fatal("azure: updatePollingState failed to prefer the Azure-AsyncOperation header")
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +366,7 @@ func TestUpdatePollingState_PrefersLocationWhenTheAzureAsyncOperationHeaderMissi
|
|||
ps := pollingState{}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.uri != mocks.TestLocationURL {
|
||||
if ps.URI != mocks.TestLocationURL {
|
||||
t.Fatal("azure: updatePollingState failed to prefer the Location header when the Azure-AsyncOperation header is missing")
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +380,7 @@ func TestUpdatePollingState_UsesTheObjectLocationIfAsyncHeadersAreMissing(t *tes
|
|||
ps := pollingState{}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.uri != mocks.TestURL {
|
||||
if ps.URI != mocks.TestURL {
|
||||
t.Fatal("azure: updatePollingState failed to use the Object URL when the asynchronous headers are missing")
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +395,7 @@ func TestUpdatePollingState_RecognizesLowerCaseHTTPVerbs(t *testing.T) {
|
|||
ps := pollingState{}
|
||||
updatePollingState(resp, &ps)
|
||||
|
||||
if ps.uri != mocks.TestURL {
|
||||
if ps.URI != mocks.TestURL {
|
||||
t.Fatalf("azure: updatePollingState failed to recognize the lower-case HTTP verb '%s'", m)
|
||||
}
|
||||
}
|
||||
|
@ -412,32 +415,22 @@ func TestUpdatePollingState_ReturnsAnErrorIfAsyncHeadersAreMissingForANewOrDelet
|
|||
}
|
||||
}
|
||||
|
||||
func TestNewPollingRequest_FailsWhenResponseLacksRequest(t *testing.T) {
|
||||
resp := newAsynchronousResponse()
|
||||
resp.Request = nil
|
||||
|
||||
_, err := newPollingRequest(resp, pollingState{})
|
||||
if err == nil {
|
||||
t.Fatal("azure: newPollingRequest failed to return an error when the http.Response lacked the original http.Request")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPollingRequest_ReturnsAnErrorWhenPrepareFails(t *testing.T) {
|
||||
_, err := newPollingRequest(newAsynchronousResponse(), pollingState{responseFormat: usesOperationResponse, uri: mocks.TestBadURL})
|
||||
_, 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(newAsynchronousResponse(), pollingState{responseFormat: usesOperationResponse, uri: mocks.TestBadURL})
|
||||
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(newAsynchronousResponse(), pollingState{responseFormat: usesOperationResponse, uri: mocks.TestAzureAsyncURL})
|
||||
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)
|
||||
}
|
||||
|
@ -643,7 +636,7 @@ func TestDoPollForAsynchronous_PollsForStatusAccepted(t *testing.T) {
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -666,7 +659,7 @@ func TestDoPollForAsynchronous_PollsForStatusCreated(t *testing.T) {
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -690,7 +683,7 @@ func TestDoPollForAsynchronous_PollsUntilProvisioningStatusTerminates(t *testing
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -714,7 +707,7 @@ func TestDoPollForAsynchronous_PollsUntilProvisioningStatusSucceeds(t *testing.T
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -735,7 +728,7 @@ func TestDoPollForAsynchronous_PollsUntilOperationResourceHasTerminated(t *testi
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -756,7 +749,7 @@ func TestDoPollForAsynchronous_PollsUntilOperationResourceHasSucceeded(t *testin
|
|||
r, _ := autorest.SendWithSender(client, mocks.NewRequest(),
|
||||
DoPollForAsynchronous(time.Millisecond))
|
||||
|
||||
if client.Attempts() < 4 {
|
||||
if client.Attempts() < client.NumResponses() {
|
||||
t.Fatalf("azure: DoPollForAsynchronous stopped polling before receiving a terminated OperationResource")
|
||||
}
|
||||
|
||||
|
@ -885,7 +878,7 @@ func TestDoPollForAsynchronous_ReturnsErrorForLastErrorResponse(t *testing.T) {
|
|||
r1.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
r2 := newProvisioningStatusResponse("busy")
|
||||
r2.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
r3 := newAsynchronousResponseWithError()
|
||||
r3 := newAsynchronousResponseWithError("400 Bad Request", http.StatusBadRequest)
|
||||
r3.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
|
||||
client := mocks.NewSender()
|
||||
|
@ -932,7 +925,7 @@ func TestDoPollForAsynchronous_ReturnsOperationResourceErrorForFailedOperations(
|
|||
|
||||
func TestDoPollForAsynchronous_ReturnsErrorForFirstPutRequest(t *testing.T) {
|
||||
// Return 400 bad response with error code and message in first put
|
||||
r1 := newAsynchronousResponseWithError()
|
||||
r1 := newAsynchronousResponseWithError("400 Bad Request", http.StatusBadRequest)
|
||||
client := mocks.NewSender()
|
||||
client.AppendResponse(r1)
|
||||
|
||||
|
@ -1024,6 +1017,210 @@ func TestDoPollForAsynchronous_StopsPollingIfItReceivesAnInvalidOperationResourc
|
|||
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.
|
||||
|
@ -1099,8 +1296,8 @@ func newAsynchronousResponse() *http.Response {
|
|||
return r
|
||||
}
|
||||
|
||||
func newAsynchronousResponseWithError() *http.Response {
|
||||
r := mocks.NewResponseWithStatus("400 Bad Request", http.StatusBadRequest)
|
||||
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)
|
||||
|
|
34
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
34
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
|
@ -15,10 +15,17 @@ package azure
|
|||
// 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,
|
||||
|
@ -133,12 +140,37 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// EnvironmentFromName returns an Environment based on the common name specified
|
||||
// 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
|
||||
}
|
||||
|
|
54
vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go
generated
vendored
54
vendor/github.com/Azure/go-autorest/autorest/azure/environments_test.go
generated
vendored
|
@ -17,9 +17,63 @@ package azure
|
|||
|
||||
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 {
|
||||
|
|
9
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
9
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
|
@ -55,15 +55,16 @@ func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator {
|
|||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
err = re
|
||||
|
||||
if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" {
|
||||
err = register(client, r, re)
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("failed auto registering Resource Provider: %s", err)
|
||||
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, errors.New("failed request and resource provider registration")
|
||||
return resp, fmt.Errorf("failed request: %s", err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
5
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
5
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
|
@ -35,6 +35,9 @@ const (
|
|||
|
||||
// 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 (
|
||||
|
@ -172,7 +175,7 @@ func NewClientWithUserAgent(ua string) Client {
|
|||
PollingDelay: DefaultPollingDelay,
|
||||
PollingDuration: DefaultPollingDuration,
|
||||
RetryAttempts: DefaultRetryAttempts,
|
||||
RetryDuration: 30 * time.Second,
|
||||
RetryDuration: DefaultRetryDuration,
|
||||
UserAgent: defaultUserAgent,
|
||||
}
|
||||
c.Sender = c.sender()
|
||||
|
|
6
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
6
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
|
@ -221,7 +221,8 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
|
|||
return resp, err
|
||||
}
|
||||
resp, err = s.Do(rr.Request())
|
||||
if err != nil || !ResponseHasStatusCode(resp, codes...) {
|
||||
// we want to retry if err is not nil (e.g. transient network failure)
|
||||
if err == nil && !ResponseHasStatusCode(resp, codes...) {
|
||||
return resp, err
|
||||
}
|
||||
delayed := DelayWithRetryAfter(resp, r.Cancel)
|
||||
|
@ -237,6 +238,9 @@ func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) Se
|
|||
// 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 {
|
||||
|
|
12
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
12
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
|
@ -20,6 +20,7 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
@ -190,3 +191,14 @@ func createQuery(v url.Values) string {
|
|||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
4
vendor/github.com/emicklei/go-restful-swagger12/.travis.yml
generated
vendored
Normal file
4
vendor/github.com/emicklei/go-restful-swagger12/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
46
vendor/github.com/emicklei/go-restful-swagger12/CHANGES.md
generated
vendored
Normal file
46
vendor/github.com/emicklei/go-restful-swagger12/CHANGES.md
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
Change history of swagger
|
||||
=
|
||||
2017-01-30
|
||||
- moved from go-restful/swagger to go-restful-swagger12
|
||||
|
||||
2015-10-16
|
||||
- add type override mechanism for swagger models (MR 254, nathanejohnson)
|
||||
- replace uses of wildcard in generated apidocs (issue 251)
|
||||
|
||||
2015-05-25
|
||||
- (api break) changed the type of Properties in Model
|
||||
- (api break) changed the type of Models in ApiDeclaration
|
||||
- (api break) changed the parameter type of PostBuildDeclarationMapFunc
|
||||
|
||||
2015-04-09
|
||||
- add ModelBuildable interface for customization of Model
|
||||
|
||||
2015-03-17
|
||||
- preserve order of Routes per WebService in Swagger listing
|
||||
- fix use of $ref and type in Swagger models
|
||||
- add api version to listing
|
||||
|
||||
2014-11-14
|
||||
- operation parameters are now sorted using ordering path,query,form,header,body
|
||||
|
||||
2014-11-12
|
||||
- respect omitempty tag value for embedded structs
|
||||
- expose ApiVersion of WebService to Swagger ApiDeclaration
|
||||
|
||||
2014-05-29
|
||||
- (api add) Ability to define custom http.Handler to serve swagger-ui static files
|
||||
|
||||
2014-05-04
|
||||
- (fix) include model for array element type of response
|
||||
|
||||
2014-01-03
|
||||
- (fix) do not add primitive type to the Api models
|
||||
|
||||
2013-11-27
|
||||
- (fix) make Swagger work for WebServices with root ("/" or "") paths
|
||||
|
||||
2013-10-29
|
||||
- (api add) package variable LogInfo to customize logging function
|
||||
|
||||
2013-10-15
|
||||
- upgraded to spec version 1.2 (https://github.com/wordnik/swagger-core/wiki/1.2-transition)
|
22
vendor/github.com/emicklei/go-restful-swagger12/LICENSE
generated
vendored
Normal file
22
vendor/github.com/emicklei/go-restful-swagger12/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2017 Ernest Micklei
|
||||
|
||||
MIT License
|
||||
|
||||
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.
|
83
vendor/github.com/emicklei/go-restful-swagger12/README.md
generated
vendored
Normal file
83
vendor/github.com/emicklei/go-restful-swagger12/README.md
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
# go-restful-swagger12
|
||||
|
||||
[](https://travis-ci.org/emicklei/go-restful-swagger12)
|
||||
[](https://godoc.org/github.com/emicklei/go-restful-swagger12)
|
||||
|
||||
How to use Swagger UI with go-restful
|
||||
=
|
||||
|
||||
Get the Swagger UI sources (version 1.2 only)
|
||||
|
||||
git clone https://github.com/wordnik/swagger-ui.git
|
||||
|
||||
The project contains a "dist" folder.
|
||||
Its contents has all the Swagger UI files you need.
|
||||
|
||||
The `index.html` has an `url` set to `http://petstore.swagger.wordnik.com/api/api-docs`.
|
||||
You need to change that to match your WebService JSON endpoint e.g. `http://localhost:8080/apidocs.json`
|
||||
|
||||
Now, you can install the Swagger WebService for serving the Swagger specification in JSON.
|
||||
|
||||
config := swagger.Config{
|
||||
WebServices: restful.RegisteredWebServices(),
|
||||
ApiPath: "/apidocs.json",
|
||||
SwaggerPath: "/apidocs/",
|
||||
SwaggerFilePath: "/Users/emicklei/Projects/swagger-ui/dist"}
|
||||
swagger.InstallSwaggerService(config)
|
||||
|
||||
|
||||
Documenting Structs
|
||||
--
|
||||
|
||||
Currently there are 2 ways to document your structs in the go-restful Swagger.
|
||||
|
||||
###### By using struct tags
|
||||
- Use tag "description" to annotate a struct field with a description to show in the UI
|
||||
- Use tag "modelDescription" to annotate the struct itself with a description to show in the UI. The tag can be added in an field of the struct and in case that there are multiple definition, they will be appended with an empty line.
|
||||
|
||||
###### By using the SwaggerDoc method
|
||||
Here is an example with an `Address` struct and the documentation for each of the fields. The `""` is a special entry for **documenting the struct itself**.
|
||||
|
||||
type Address struct {
|
||||
Country string `json:"country,omitempty"`
|
||||
PostCode int `json:"postcode,omitempty"`
|
||||
}
|
||||
|
||||
func (Address) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "Address doc",
|
||||
"country": "Country doc",
|
||||
"postcode": "PostCode doc",
|
||||
}
|
||||
}
|
||||
|
||||
This example will generate a JSON like this
|
||||
|
||||
{
|
||||
"Address": {
|
||||
"id": "Address",
|
||||
"description": "Address doc",
|
||||
"properties": {
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Country doc"
|
||||
},
|
||||
"postcode": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "PostCode doc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
**Very Important Notes:**
|
||||
- `SwaggerDoc()` is using a **NON-Pointer** receiver (e.g. func (Address) and not func (*Address))
|
||||
- The returned map should use as key the name of the field as defined in the JSON parameter (e.g. `"postcode"` and not `"PostCode"`)
|
||||
|
||||
Notes
|
||||
--
|
||||
- The Nickname of an Operation is automatically set by finding the name of the function. You can override it using RouteBuilder.Operation(..)
|
||||
- The WebServices field of swagger.Config can be used to control which service you want to expose and document ; you can have multiple configs and therefore multiple endpoints.
|
||||
|
||||
© 2017, ernestmicklei.com. MIT License. Contributions welcome.
|
64
vendor/github.com/emicklei/go-restful-swagger12/api_declaration_list.go
generated
vendored
Normal file
64
vendor/github.com/emicklei/go-restful-swagger12/api_declaration_list.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
package swagger
|
||||
|
||||
// Copyright 2015 Ernest Micklei. All rights reserved.
|
||||
// Use of this source code is governed by a license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// ApiDeclarationList maintains an ordered list of ApiDeclaration.
|
||||
type ApiDeclarationList struct {
|
||||
List []ApiDeclaration
|
||||
}
|
||||
|
||||
// At returns the ApiDeclaration by its path unless absent, then ok is false
|
||||
func (l *ApiDeclarationList) At(path string) (a ApiDeclaration, ok bool) {
|
||||
for _, each := range l.List {
|
||||
if each.ResourcePath == path {
|
||||
return each, true
|
||||
}
|
||||
}
|
||||
return a, false
|
||||
}
|
||||
|
||||
// Put adds or replaces a ApiDeclaration with this name
|
||||
func (l *ApiDeclarationList) Put(path string, a ApiDeclaration) {
|
||||
// maybe replace existing
|
||||
for i, each := range l.List {
|
||||
if each.ResourcePath == path {
|
||||
// replace
|
||||
l.List[i] = a
|
||||
return
|
||||
}
|
||||
}
|
||||
// add
|
||||
l.List = append(l.List, a)
|
||||
}
|
||||
|
||||
// Do enumerates all the properties, each with its assigned name
|
||||
func (l *ApiDeclarationList) Do(block func(path string, decl ApiDeclaration)) {
|
||||
for _, each := range l.List {
|
||||
block(each.ResourcePath, each)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON writes the ModelPropertyList as if it was a map[string]ModelProperty
|
||||
func (l ApiDeclarationList) MarshalJSON() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
buf.WriteString("{\n")
|
||||
for i, each := range l.List {
|
||||
buf.WriteString("\"")
|
||||
buf.WriteString(each.ResourcePath)
|
||||
buf.WriteString("\": ")
|
||||
encoder.Encode(each)
|
||||
if i < len(l.List)-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.Bytes(), nil
|
||||
}
|
46
vendor/github.com/emicklei/go-restful-swagger12/config.go
generated
vendored
Normal file
46
vendor/github.com/emicklei/go-restful-swagger12/config.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
||||
// PostBuildDeclarationMapFunc can be used to modify the api declaration map.
|
||||
type PostBuildDeclarationMapFunc func(apiDeclarationMap *ApiDeclarationList)
|
||||
|
||||
// MapSchemaFormatFunc can be used to modify typeName at definition time.
|
||||
type MapSchemaFormatFunc func(typeName string) string
|
||||
|
||||
// MapModelTypeNameFunc can be used to return the desired typeName for a given
|
||||
// type. It will return false if the default name should be used.
|
||||
type MapModelTypeNameFunc func(t reflect.Type) (string, bool)
|
||||
|
||||
type Config struct {
|
||||
// url where the services are available, e.g. http://localhost:8080
|
||||
// if left empty then the basePath of Swagger is taken from the actual request
|
||||
WebServicesUrl string
|
||||
// path where the JSON api is avaiable , e.g. /apidocs
|
||||
ApiPath string
|
||||
// [optional] path where the swagger UI will be served, e.g. /swagger
|
||||
SwaggerPath string
|
||||
// [optional] location of folder containing Swagger HTML5 application index.html
|
||||
SwaggerFilePath string
|
||||
// api listing is constructed from this list of restful WebServices.
|
||||
WebServices []*restful.WebService
|
||||
// will serve all static content (scripts,pages,images)
|
||||
StaticHandler http.Handler
|
||||
// [optional] on default CORS (Cross-Origin-Resource-Sharing) is enabled.
|
||||
DisableCORS bool
|
||||
// Top-level API version. Is reflected in the resource listing.
|
||||
ApiVersion string
|
||||
// If set then call this handler after building the complete ApiDeclaration Map
|
||||
PostBuildHandler PostBuildDeclarationMapFunc
|
||||
// Swagger global info struct
|
||||
Info Info
|
||||
// [optional] If set, model builder should call this handler to get addition typename-to-swagger-format-field conversion.
|
||||
SchemaFormatHandler MapSchemaFormatFunc
|
||||
// [optional] If set, model builder should call this handler to retrieve the name for a given type.
|
||||
ModelTypeNameHandler MapModelTypeNameFunc
|
||||
}
|
467
vendor/github.com/emicklei/go-restful-swagger12/model_builder.go
generated
vendored
Normal file
467
vendor/github.com/emicklei/go-restful-swagger12/model_builder.go
generated
vendored
Normal file
|
@ -0,0 +1,467 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ModelBuildable is used for extending Structs that need more control over
|
||||
// how the Model appears in the Swagger api declaration.
|
||||
type ModelBuildable interface {
|
||||
PostBuildModel(m *Model) *Model
|
||||
}
|
||||
|
||||
type modelBuilder struct {
|
||||
Models *ModelList
|
||||
Config *Config
|
||||
}
|
||||
|
||||
type documentable interface {
|
||||
SwaggerDoc() map[string]string
|
||||
}
|
||||
|
||||
// Check if this structure has a method with signature func (<theModel>) SwaggerDoc() map[string]string
|
||||
// If it exists, retrive the documentation and overwrite all struct tag descriptions
|
||||
func getDocFromMethodSwaggerDoc2(model reflect.Type) map[string]string {
|
||||
if docable, ok := reflect.New(model).Elem().Interface().(documentable); ok {
|
||||
return docable.SwaggerDoc()
|
||||
}
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
// addModelFrom creates and adds a Model to the builder and detects and calls
|
||||
// the post build hook for customizations
|
||||
func (b modelBuilder) addModelFrom(sample interface{}) {
|
||||
if modelOrNil := b.addModel(reflect.TypeOf(sample), ""); modelOrNil != nil {
|
||||
// allow customizations
|
||||
if buildable, ok := sample.(ModelBuildable); ok {
|
||||
modelOrNil = buildable.PostBuildModel(modelOrNil)
|
||||
b.Models.Put(modelOrNil.Id, *modelOrNil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
||||
// Turn pointers into simpler types so further checks are
|
||||
// correct.
|
||||
if st.Kind() == reflect.Ptr {
|
||||
st = st.Elem()
|
||||
}
|
||||
|
||||
modelName := b.keyFrom(st)
|
||||
if nameOverride != "" {
|
||||
modelName = nameOverride
|
||||
}
|
||||
// no models needed for primitive types
|
||||
if b.isPrimitiveType(modelName) {
|
||||
return nil
|
||||
}
|
||||
// golang encoding/json packages says array and slice values encode as
|
||||
// JSON arrays, except that []byte encodes as a base64-encoded string.
|
||||
// If we see a []byte here, treat it at as a primitive type (string)
|
||||
// and deal with it in buildArrayTypeProperty.
|
||||
if (st.Kind() == reflect.Slice || st.Kind() == reflect.Array) &&
|
||||
st.Elem().Kind() == reflect.Uint8 {
|
||||
return nil
|
||||
}
|
||||
// see if we already have visited this model
|
||||
if _, ok := b.Models.At(modelName); ok {
|
||||
return nil
|
||||
}
|
||||
sm := Model{
|
||||
Id: modelName,
|
||||
Required: []string{},
|
||||
Properties: ModelPropertyList{}}
|
||||
|
||||
// reference the model before further initializing (enables recursive structs)
|
||||
b.Models.Put(modelName, sm)
|
||||
|
||||
// check for slice or array
|
||||
if st.Kind() == reflect.Slice || st.Kind() == reflect.Array {
|
||||
b.addModel(st.Elem(), "")
|
||||
return &sm
|
||||
}
|
||||
// check for structure or primitive type
|
||||
if st.Kind() != reflect.Struct {
|
||||
return &sm
|
||||
}
|
||||
|
||||
fullDoc := getDocFromMethodSwaggerDoc2(st)
|
||||
modelDescriptions := []string{}
|
||||
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
field := st.Field(i)
|
||||
jsonName, modelDescription, prop := b.buildProperty(field, &sm, modelName)
|
||||
if len(modelDescription) > 0 {
|
||||
modelDescriptions = append(modelDescriptions, modelDescription)
|
||||
}
|
||||
|
||||
// add if not omitted
|
||||
if len(jsonName) != 0 {
|
||||
// update description
|
||||
if fieldDoc, ok := fullDoc[jsonName]; ok {
|
||||
prop.Description = fieldDoc
|
||||
}
|
||||
// update Required
|
||||
if b.isPropertyRequired(field) {
|
||||
sm.Required = append(sm.Required, jsonName)
|
||||
}
|
||||
sm.Properties.Put(jsonName, prop)
|
||||
}
|
||||
}
|
||||
|
||||
// We always overwrite documentation if SwaggerDoc method exists
|
||||
// "" is special for documenting the struct itself
|
||||
if modelDoc, ok := fullDoc[""]; ok {
|
||||
sm.Description = modelDoc
|
||||
} else if len(modelDescriptions) != 0 {
|
||||
sm.Description = strings.Join(modelDescriptions, "\n")
|
||||
}
|
||||
|
||||
// update model builder with completed model
|
||||
b.Models.Put(modelName, sm)
|
||||
|
||||
return &sm
|
||||
}
|
||||
|
||||
func (b modelBuilder) isPropertyRequired(field reflect.StructField) bool {
|
||||
required := true
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "omitempty" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return required
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, modelName string) (jsonName, modelDescription string, prop ModelProperty) {
|
||||
jsonName = b.jsonNameOfField(field)
|
||||
if len(jsonName) == 0 {
|
||||
// empty name signals skip property
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if field.Name == "XMLName" && field.Type.String() == "xml.Name" {
|
||||
// property is metadata for the xml.Name attribute, can be skipped
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if tag := field.Tag.Get("modelDescription"); tag != "" {
|
||||
modelDescription = tag
|
||||
}
|
||||
|
||||
prop.setPropertyMetadata(field)
|
||||
if prop.Type != nil {
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
|
||||
// check if type is doing its own marshalling
|
||||
marshalerType := reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
if fieldType.Implements(marshalerType) {
|
||||
var pType = "string"
|
||||
if prop.Type == nil {
|
||||
prop.Type = &pType
|
||||
}
|
||||
if prop.Format == "" {
|
||||
prop.Format = b.jsonSchemaFormat(b.keyFrom(fieldType))
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
// check if annotation says it is a string
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "string" {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
}
|
||||
|
||||
fieldKind := fieldType.Kind()
|
||||
switch {
|
||||
case fieldKind == reflect.Struct:
|
||||
jsonName, prop := b.buildStructTypeProperty(field, jsonName, model)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Slice || fieldKind == reflect.Array:
|
||||
jsonName, prop := b.buildArrayTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Ptr:
|
||||
jsonName, prop := b.buildPointerTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.String:
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Map:
|
||||
// if it's a map, it's unstructured, and swagger 1.2 can't handle it
|
||||
objectType := "object"
|
||||
prop.Type = &objectType
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
fieldTypeName := b.keyFrom(fieldType)
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
mapped := b.jsonSchemaType(fieldTypeName)
|
||||
prop.Type = &mapped
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
modelType := b.keyFrom(fieldType)
|
||||
prop.Ref = &modelType
|
||||
|
||||
if fieldType.Name() == "" { // override type of anonymous structs
|
||||
nestedTypeName := modelName + "." + jsonName
|
||||
prop.Ref = &nestedTypeName
|
||||
b.addModel(fieldType, nestedTypeName)
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
func hasNamedJSONTag(field reflect.StructField) bool {
|
||||
parts := strings.Split(field.Tag.Get("json"), ",")
|
||||
if len(parts) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, s := range parts[1:] {
|
||||
if s == "inline" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(parts[0]) > 0
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonName string, model *Model) (nameJson string, prop ModelProperty) {
|
||||
prop.setPropertyMetadata(field)
|
||||
// Check for type override in tag
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
// check for anonymous
|
||||
if len(fieldType.Name()) == 0 {
|
||||
// anonymous
|
||||
anonType := model.Id + "." + jsonName
|
||||
b.addModel(fieldType, anonType)
|
||||
prop.Ref = &anonType
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
if field.Name == fieldType.Name() && field.Anonymous && !hasNamedJSONTag(field) {
|
||||
// embedded struct
|
||||
sub := modelBuilder{new(ModelList), b.Config}
|
||||
sub.addModel(fieldType, "")
|
||||
subKey := sub.keyFrom(fieldType)
|
||||
// merge properties from sub
|
||||
subModel, _ := sub.Models.At(subKey)
|
||||
subModel.Properties.Do(func(k string, v ModelProperty) {
|
||||
model.Properties.Put(k, v)
|
||||
// if subModel says this property is required then include it
|
||||
required := false
|
||||
for _, each := range subModel.Required {
|
||||
if k == each {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if required {
|
||||
model.Required = append(model.Required, k)
|
||||
}
|
||||
})
|
||||
// add all new referenced models
|
||||
sub.Models.Do(func(key string, sub Model) {
|
||||
if key != subKey {
|
||||
if _, ok := b.Models.At(key); !ok {
|
||||
b.Models.Put(key, sub)
|
||||
}
|
||||
}
|
||||
})
|
||||
// empty name signals skip property
|
||||
return "", prop
|
||||
}
|
||||
// simple struct
|
||||
b.addModel(fieldType, "")
|
||||
var pType = b.keyFrom(fieldType)
|
||||
prop.Ref = &pType
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
// check for type override in tags
|
||||
prop.setPropertyMetadata(field)
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, prop
|
||||
}
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Name())
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
|
||||
prop.Items = new(Item)
|
||||
if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName)
|
||||
prop.Items.Type = &mapped
|
||||
} else {
|
||||
prop.Items.Ref = &elemTypeName
|
||||
}
|
||||
// add|overwrite model for element type
|
||||
if fieldType.Elem().Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
}
|
||||
if !isPrimitive {
|
||||
b.addModel(fieldType.Elem(), elemTypeName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
prop.setPropertyMetadata(field)
|
||||
// Check for type override in tags
|
||||
if prop.Type != nil {
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
|
||||
// override type of pointer to list-likes
|
||||
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Elem().Name())
|
||||
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
|
||||
if isPrimitive {
|
||||
primName := b.jsonSchemaType(elemName)
|
||||
prop.Items = &Item{Ref: &primName}
|
||||
} else {
|
||||
prop.Items = &Item{Ref: &elemName}
|
||||
}
|
||||
if !isPrimitive {
|
||||
// add|overwrite model for element type
|
||||
b.addModel(fieldType.Elem().Elem(), elemName)
|
||||
}
|
||||
} else {
|
||||
// non-array, pointer type
|
||||
fieldTypeName := b.keyFrom(fieldType.Elem())
|
||||
var pType = b.jsonSchemaType(fieldTypeName) // no star, include pkg path
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
prop.Type = &pType
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, prop
|
||||
}
|
||||
prop.Ref = &pType
|
||||
elemName := ""
|
||||
if fieldType.Elem().Name() == "" {
|
||||
elemName = modelName + "." + jsonName
|
||||
prop.Ref = &elemName
|
||||
}
|
||||
b.addModel(fieldType.Elem(), elemName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b modelBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Name() == "" {
|
||||
return modelName + "." + jsonName
|
||||
}
|
||||
return b.keyFrom(t)
|
||||
}
|
||||
|
||||
func (b modelBuilder) keyFrom(st reflect.Type) string {
|
||||
key := st.String()
|
||||
if b.Config != nil && b.Config.ModelTypeNameHandler != nil {
|
||||
if name, ok := b.Config.ModelTypeNameHandler(st); ok {
|
||||
key = name
|
||||
}
|
||||
}
|
||||
if len(st.Name()) == 0 { // unnamed type
|
||||
// Swagger UI has special meaning for [
|
||||
key = strings.Replace(key, "[]", "||", -1)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// see also https://golang.org/ref/spec#Numeric_types
|
||||
func (b modelBuilder) isPrimitiveType(modelName string) bool {
|
||||
if len(modelName) == 0 {
|
||||
return false
|
||||
}
|
||||
return strings.Contains("uint uint8 uint16 uint32 uint64 int int8 int16 int32 int64 float32 float64 bool string byte rune time.Time", modelName)
|
||||
}
|
||||
|
||||
// jsonNameOfField returns the name of the field as it should appear in JSON format
|
||||
// An empty string indicates that this field is not part of the JSON representation
|
||||
func (b modelBuilder) jsonNameOfField(field reflect.StructField) string {
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if s[0] == "-" {
|
||||
// empty name signals skip property
|
||||
return ""
|
||||
} else if s[0] != "" {
|
||||
return s[0]
|
||||
}
|
||||
}
|
||||
return field.Name
|
||||
}
|
||||
|
||||
// see also http://json-schema.org/latest/json-schema-core.html#anchor8
|
||||
func (b modelBuilder) jsonSchemaType(modelName string) string {
|
||||
schemaMap := map[string]string{
|
||||
"uint": "integer",
|
||||
"uint8": "integer",
|
||||
"uint16": "integer",
|
||||
"uint32": "integer",
|
||||
"uint64": "integer",
|
||||
|
||||
"int": "integer",
|
||||
"int8": "integer",
|
||||
"int16": "integer",
|
||||
"int32": "integer",
|
||||
"int64": "integer",
|
||||
|
||||
"byte": "integer",
|
||||
"float64": "number",
|
||||
"float32": "number",
|
||||
"bool": "boolean",
|
||||
"time.Time": "string",
|
||||
}
|
||||
mapped, ok := schemaMap[modelName]
|
||||
if !ok {
|
||||
return modelName // use as is (custom or struct)
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
||||
func (b modelBuilder) jsonSchemaFormat(modelName string) string {
|
||||
if b.Config != nil && b.Config.SchemaFormatHandler != nil {
|
||||
if mapped := b.Config.SchemaFormatHandler(modelName); mapped != "" {
|
||||
return mapped
|
||||
}
|
||||
}
|
||||
schemaMap := map[string]string{
|
||||
"int": "int32",
|
||||
"int32": "int32",
|
||||
"int64": "int64",
|
||||
"byte": "byte",
|
||||
"uint": "integer",
|
||||
"uint8": "byte",
|
||||
"float64": "double",
|
||||
"float32": "float",
|
||||
"time.Time": "date-time",
|
||||
"*time.Time": "date-time",
|
||||
}
|
||||
mapped, ok := schemaMap[modelName]
|
||||
if !ok {
|
||||
return "" // no format
|
||||
}
|
||||
return mapped
|
||||
}
|
1283
vendor/github.com/emicklei/go-restful-swagger12/model_builder_test.go
generated
vendored
Normal file
1283
vendor/github.com/emicklei/go-restful-swagger12/model_builder_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
86
vendor/github.com/emicklei/go-restful-swagger12/model_list.go
generated
vendored
Normal file
86
vendor/github.com/emicklei/go-restful-swagger12/model_list.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package swagger
|
||||
|
||||
// Copyright 2015 Ernest Micklei. All rights reserved.
|
||||
// Use of this source code is governed by a license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// NamedModel associates a name with a Model (not using its Id)
|
||||
type NamedModel struct {
|
||||
Name string
|
||||
Model Model
|
||||
}
|
||||
|
||||
// ModelList encapsulates a list of NamedModel (association)
|
||||
type ModelList struct {
|
||||
List []NamedModel
|
||||
}
|
||||
|
||||
// Put adds or replaces a Model by its name
|
||||
func (l *ModelList) Put(name string, model Model) {
|
||||
for i, each := range l.List {
|
||||
if each.Name == name {
|
||||
// replace
|
||||
l.List[i] = NamedModel{name, model}
|
||||
return
|
||||
}
|
||||
}
|
||||
// add
|
||||
l.List = append(l.List, NamedModel{name, model})
|
||||
}
|
||||
|
||||
// At returns a Model by its name, ok is false if absent
|
||||
func (l *ModelList) At(name string) (m Model, ok bool) {
|
||||
for _, each := range l.List {
|
||||
if each.Name == name {
|
||||
return each.Model, true
|
||||
}
|
||||
}
|
||||
return m, false
|
||||
}
|
||||
|
||||
// Do enumerates all the models, each with its assigned name
|
||||
func (l *ModelList) Do(block func(name string, value Model)) {
|
||||
for _, each := range l.List {
|
||||
block(each.Name, each.Model)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON writes the ModelList as if it was a map[string]Model
|
||||
func (l ModelList) MarshalJSON() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
buf.WriteString("{\n")
|
||||
for i, each := range l.List {
|
||||
buf.WriteString("\"")
|
||||
buf.WriteString(each.Name)
|
||||
buf.WriteString("\": ")
|
||||
encoder.Encode(each.Model)
|
||||
if i < len(l.List)-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads back a ModelList. This is an expensive operation.
|
||||
func (l *ModelList) UnmarshalJSON(data []byte) error {
|
||||
raw := map[string]interface{}{}
|
||||
json.NewDecoder(bytes.NewReader(data)).Decode(&raw)
|
||||
for k, v := range raw {
|
||||
// produces JSON bytes for each value
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var m Model
|
||||
json.NewDecoder(bytes.NewReader(data)).Decode(&m)
|
||||
l.Put(k, m)
|
||||
}
|
||||
return nil
|
||||
}
|
48
vendor/github.com/emicklei/go-restful-swagger12/model_list_test.go
generated
vendored
Normal file
48
vendor/github.com/emicklei/go-restful-swagger12/model_list_test.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestModelList(t *testing.T) {
|
||||
m := Model{}
|
||||
m.Id = "m"
|
||||
l := ModelList{}
|
||||
l.Put("m", m)
|
||||
k, ok := l.At("m")
|
||||
if !ok {
|
||||
t.Error("want model back")
|
||||
}
|
||||
if got, want := k.Id, "m"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelList_Marshal(t *testing.T) {
|
||||
l := ModelList{}
|
||||
m := Model{Id: "myid"}
|
||||
l.Put("myid", m)
|
||||
data, err := json.Marshal(l)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if got, want := string(data), `{"myid":{"id":"myid","properties":{}}}`; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelList_Unmarshal(t *testing.T) {
|
||||
data := `{"myid":{"id":"myid","properties":{}}}`
|
||||
l := ModelList{}
|
||||
if err := json.Unmarshal([]byte(data), &l); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
m, ok := l.At("myid")
|
||||
if !ok {
|
||||
t.Error("expected myid")
|
||||
}
|
||||
if got, want := m.Id, "myid"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
81
vendor/github.com/emicklei/go-restful-swagger12/model_property_ext.go
generated
vendored
Normal file
81
vendor/github.com/emicklei/go-restful-swagger12/model_property_ext.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (prop *ModelProperty) setDescription(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("description"); tag != "" {
|
||||
prop.Description = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setDefaultValue(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("default"); tag != "" {
|
||||
prop.DefaultValue = Special(tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setEnumValues(field reflect.StructField) {
|
||||
// We use | to separate the enum values. This value is chosen
|
||||
// since its unlikely to be useful in actual enumeration values.
|
||||
if tag := field.Tag.Get("enum"); tag != "" {
|
||||
prop.Enum = strings.Split(tag, "|")
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setMaximum(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("maximum"); tag != "" {
|
||||
prop.Maximum = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setType(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("type"); tag != "" {
|
||||
// Check if the first two characters of the type tag are
|
||||
// intended to emulate slice/array behaviour.
|
||||
//
|
||||
// If type is intended to be a slice/array then add the
|
||||
// overriden type to the array item instead of the main property
|
||||
if len(tag) > 2 && tag[0:2] == "[]" {
|
||||
pType := "array"
|
||||
prop.Type = &pType
|
||||
prop.Items = new(Item)
|
||||
|
||||
iType := tag[2:]
|
||||
prop.Items.Type = &iType
|
||||
return
|
||||
}
|
||||
|
||||
prop.Type = &tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setMinimum(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("minimum"); tag != "" {
|
||||
prop.Minimum = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setUniqueItems(field reflect.StructField) {
|
||||
tag := field.Tag.Get("unique")
|
||||
switch tag {
|
||||
case "true":
|
||||
v := true
|
||||
prop.UniqueItems = &v
|
||||
case "false":
|
||||
v := false
|
||||
prop.UniqueItems = &v
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setPropertyMetadata(field reflect.StructField) {
|
||||
prop.setDescription(field)
|
||||
prop.setEnumValues(field)
|
||||
prop.setMinimum(field)
|
||||
prop.setMaximum(field)
|
||||
prop.setUniqueItems(field)
|
||||
prop.setDefaultValue(field)
|
||||
prop.setType(field)
|
||||
}
|
70
vendor/github.com/emicklei/go-restful-swagger12/model_property_ext_test.go
generated
vendored
Normal file
70
vendor/github.com/emicklei/go-restful-swagger12/model_property_ext_test.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// clear && go test -v -test.run TestThatExtraTagsAreReadIntoModel ...swagger
|
||||
func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
|
||||
type fakeint int
|
||||
type fakearray string
|
||||
type Anything struct {
|
||||
Name string `description:"name" modelDescription:"a test"`
|
||||
Size int `minimum:"0" maximum:"10"`
|
||||
Stati string `enum:"off|on" default:"on" modelDescription:"more description"`
|
||||
ID string `unique:"true"`
|
||||
FakeInt fakeint `type:"integer"`
|
||||
FakeArray fakearray `type:"[]string"`
|
||||
IP net.IP `type:"string"`
|
||||
Password string
|
||||
}
|
||||
m := modelsFromStruct(Anything{})
|
||||
props, _ := m.At("swagger.Anything")
|
||||
p1, _ := props.Properties.At("Name")
|
||||
if got, want := p1.Description, "name"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p2, _ := props.Properties.At("Size")
|
||||
if got, want := p2.Minimum, "0"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
if got, want := p2.Maximum, "10"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p3, _ := props.Properties.At("Stati")
|
||||
if got, want := p3.Enum[0], "off"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
if got, want := p3.Enum[1], "on"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p4, _ := props.Properties.At("ID")
|
||||
if got, want := *p4.UniqueItems, true; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p5, _ := props.Properties.At("Password")
|
||||
if got, want := *p5.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p6, _ := props.Properties.At("FakeInt")
|
||||
if got, want := *p6.Type, "integer"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p7, _ := props.Properties.At("FakeArray")
|
||||
if got, want := *p7.Type, "array"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p7p, _ := props.Properties.At("FakeArray")
|
||||
if got, want := *p7p.Items.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p8, _ := props.Properties.At("IP")
|
||||
if got, want := *p8.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := props.Description, "a test\nmore description"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
87
vendor/github.com/emicklei/go-restful-swagger12/model_property_list.go
generated
vendored
Normal file
87
vendor/github.com/emicklei/go-restful-swagger12/model_property_list.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
package swagger
|
||||
|
||||
// Copyright 2015 Ernest Micklei. All rights reserved.
|
||||
// Use of this source code is governed by a license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// NamedModelProperty associates a name to a ModelProperty
|
||||
type NamedModelProperty struct {
|
||||
Name string
|
||||
Property ModelProperty
|
||||
}
|
||||
|
||||
// ModelPropertyList encapsulates a list of NamedModelProperty (association)
|
||||
type ModelPropertyList struct {
|
||||
List []NamedModelProperty
|
||||
}
|
||||
|
||||
// At returns the ModelPropety by its name unless absent, then ok is false
|
||||
func (l *ModelPropertyList) At(name string) (p ModelProperty, ok bool) {
|
||||
for _, each := range l.List {
|
||||
if each.Name == name {
|
||||
return each.Property, true
|
||||
}
|
||||
}
|
||||
return p, false
|
||||
}
|
||||
|
||||
// Put adds or replaces a ModelProperty with this name
|
||||
func (l *ModelPropertyList) Put(name string, prop ModelProperty) {
|
||||
// maybe replace existing
|
||||
for i, each := range l.List {
|
||||
if each.Name == name {
|
||||
// replace
|
||||
l.List[i] = NamedModelProperty{Name: name, Property: prop}
|
||||
return
|
||||
}
|
||||
}
|
||||
// add
|
||||
l.List = append(l.List, NamedModelProperty{Name: name, Property: prop})
|
||||
}
|
||||
|
||||
// Do enumerates all the properties, each with its assigned name
|
||||
func (l *ModelPropertyList) Do(block func(name string, value ModelProperty)) {
|
||||
for _, each := range l.List {
|
||||
block(each.Name, each.Property)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON writes the ModelPropertyList as if it was a map[string]ModelProperty
|
||||
func (l ModelPropertyList) MarshalJSON() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
buf.WriteString("{\n")
|
||||
for i, each := range l.List {
|
||||
buf.WriteString("\"")
|
||||
buf.WriteString(each.Name)
|
||||
buf.WriteString("\": ")
|
||||
encoder.Encode(each.Property)
|
||||
if i < len(l.List)-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads back a ModelPropertyList. This is an expensive operation.
|
||||
func (l *ModelPropertyList) UnmarshalJSON(data []byte) error {
|
||||
raw := map[string]interface{}{}
|
||||
json.NewDecoder(bytes.NewReader(data)).Decode(&raw)
|
||||
for k, v := range raw {
|
||||
// produces JSON bytes for each value
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var m ModelProperty
|
||||
json.NewDecoder(bytes.NewReader(data)).Decode(&m)
|
||||
l.Put(k, m)
|
||||
}
|
||||
return nil
|
||||
}
|
47
vendor/github.com/emicklei/go-restful-swagger12/model_property_list_test.go
generated
vendored
Normal file
47
vendor/github.com/emicklei/go-restful-swagger12/model_property_list_test.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestModelPropertyList(t *testing.T) {
|
||||
l := ModelPropertyList{}
|
||||
p := ModelProperty{Description: "d"}
|
||||
l.Put("p", p)
|
||||
q, ok := l.At("p")
|
||||
if !ok {
|
||||
t.Error("expected p")
|
||||
}
|
||||
if got, want := q.Description, "d"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelPropertyList_Marshal(t *testing.T) {
|
||||
l := ModelPropertyList{}
|
||||
p := ModelProperty{Description: "d"}
|
||||
l.Put("p", p)
|
||||
data, err := json.Marshal(l)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if got, want := string(data), `{"p":{"description":"d"}}`; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelPropertyList_Unmarshal(t *testing.T) {
|
||||
data := `{"p":{"description":"d"}}`
|
||||
l := ModelPropertyList{}
|
||||
if err := json.Unmarshal([]byte(data), &l); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
m, ok := l.At("p")
|
||||
if !ok {
|
||||
t.Error("expected p")
|
||||
}
|
||||
if got, want := m.Description, "d"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
36
vendor/github.com/emicklei/go-restful-swagger12/ordered_route_map.go
generated
vendored
Normal file
36
vendor/github.com/emicklei/go-restful-swagger12/ordered_route_map.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
package swagger
|
||||
|
||||
// Copyright 2015 Ernest Micklei. All rights reserved.
|
||||
// Use of this source code is governed by a license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import "github.com/emicklei/go-restful"
|
||||
|
||||
type orderedRouteMap struct {
|
||||
elements map[string][]restful.Route
|
||||
keys []string
|
||||
}
|
||||
|
||||
func newOrderedRouteMap() *orderedRouteMap {
|
||||
return &orderedRouteMap{
|
||||
elements: map[string][]restful.Route{},
|
||||
keys: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *orderedRouteMap) Add(key string, route restful.Route) {
|
||||
routes, ok := o.elements[key]
|
||||
if ok {
|
||||
routes = append(routes, route)
|
||||
o.elements[key] = routes
|
||||
return
|
||||
}
|
||||
o.elements[key] = []restful.Route{route}
|
||||
o.keys = append(o.keys, key)
|
||||
}
|
||||
|
||||
func (o *orderedRouteMap) Do(block func(key string, routes []restful.Route)) {
|
||||
for _, k := range o.keys {
|
||||
block(k, o.elements[k])
|
||||
}
|
||||
}
|
29
vendor/github.com/emicklei/go-restful-swagger12/ordered_route_map_test.go
generated
vendored
Normal file
29
vendor/github.com/emicklei/go-restful-swagger12/ordered_route_map_test.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
||||
// go test -v -test.run TestOrderedRouteMap ...swagger
|
||||
func TestOrderedRouteMap(t *testing.T) {
|
||||
m := newOrderedRouteMap()
|
||||
r1 := restful.Route{Path: "/r1"}
|
||||
r2 := restful.Route{Path: "/r2"}
|
||||
m.Add("a", r1)
|
||||
m.Add("b", r2)
|
||||
m.Add("b", r1)
|
||||
m.Add("d", r2)
|
||||
m.Add("c", r2)
|
||||
order := ""
|
||||
m.Do(func(k string, routes []restful.Route) {
|
||||
order += k
|
||||
if len(routes) == 0 {
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
if order != "abdc" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
42
vendor/github.com/emicklei/go-restful-swagger12/postbuild_model_test.go
generated
vendored
Normal file
42
vendor/github.com/emicklei/go-restful-swagger12/postbuild_model_test.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package swagger
|
||||
|
||||
import "testing"
|
||||
|
||||
type Boat struct {
|
||||
Length int `json:"-"` // on default, this makes the fields not required
|
||||
Weight int `json:"-"`
|
||||
}
|
||||
|
||||
// PostBuildModel is from swagger.ModelBuildable
|
||||
func (b Boat) PostBuildModel(m *Model) *Model {
|
||||
// override required
|
||||
m.Required = []string{"Length", "Weight"}
|
||||
|
||||
// add model property (just to test is can be added; is this a real usecase?)
|
||||
extraType := "string"
|
||||
m.Properties.Put("extra", ModelProperty{
|
||||
Description: "extra description",
|
||||
DataTypeFields: DataTypeFields{
|
||||
Type: &extraType,
|
||||
},
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
func TestCustomPostModelBuilde(t *testing.T) {
|
||||
testJsonFromStruct(t, Boat{}, `{
|
||||
"swagger.Boat": {
|
||||
"id": "swagger.Boat",
|
||||
"required": [
|
||||
"Length",
|
||||
"Weight"
|
||||
],
|
||||
"properties": {
|
||||
"extra": {
|
||||
"type": "string",
|
||||
"description": "extra description"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
}
|
185
vendor/github.com/emicklei/go-restful-swagger12/swagger.go
generated
vendored
Normal file
185
vendor/github.com/emicklei/go-restful-swagger12/swagger.go
generated
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
// Package swagger implements the structures of the Swagger
|
||||
// https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md
|
||||
package swagger
|
||||
|
||||
const swaggerVersion = "1.2"
|
||||
|
||||
// 4.3.3 Data Type Fields
|
||||
type DataTypeFields struct {
|
||||
Type *string `json:"type,omitempty"` // if Ref not used
|
||||
Ref *string `json:"$ref,omitempty"` // if Type not used
|
||||
Format string `json:"format,omitempty"`
|
||||
DefaultValue Special `json:"defaultValue,omitempty"`
|
||||
Enum []string `json:"enum,omitempty"`
|
||||
Minimum string `json:"minimum,omitempty"`
|
||||
Maximum string `json:"maximum,omitempty"`
|
||||
Items *Item `json:"items,omitempty"`
|
||||
UniqueItems *bool `json:"uniqueItems,omitempty"`
|
||||
}
|
||||
|
||||
type Special string
|
||||
|
||||
// 4.3.4 Items Object
|
||||
type Item struct {
|
||||
Type *string `json:"type,omitempty"`
|
||||
Ref *string `json:"$ref,omitempty"`
|
||||
Format string `json:"format,omitempty"`
|
||||
}
|
||||
|
||||
// 5.1 Resource Listing
|
||||
type ResourceListing struct {
|
||||
SwaggerVersion string `json:"swaggerVersion"` // e.g 1.2
|
||||
Apis []Resource `json:"apis"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Info Info `json:"info"`
|
||||
Authorizations []Authorization `json:"authorizations,omitempty"`
|
||||
}
|
||||
|
||||
// 5.1.2 Resource Object
|
||||
type Resource struct {
|
||||
Path string `json:"path"` // relative or absolute, must start with /
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// 5.1.3 Info Object
|
||||
type Info struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
TermsOfServiceUrl string `json:"termsOfServiceUrl,omitempty"`
|
||||
Contact string `json:"contact,omitempty"`
|
||||
License string `json:"license,omitempty"`
|
||||
LicenseUrl string `json:"licenseUrl,omitempty"`
|
||||
}
|
||||
|
||||
// 5.1.5
|
||||
type Authorization struct {
|
||||
Type string `json:"type"`
|
||||
PassAs string `json:"passAs"`
|
||||
Keyname string `json:"keyname"`
|
||||
Scopes []Scope `json:"scopes"`
|
||||
GrantTypes []GrantType `json:"grandTypes"`
|
||||
}
|
||||
|
||||
// 5.1.6, 5.2.11
|
||||
type Scope struct {
|
||||
// Required. The name of the scope.
|
||||
Scope string `json:"scope"`
|
||||
// Recommended. A short description of the scope.
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// 5.1.7
|
||||
type GrantType struct {
|
||||
Implicit Implicit `json:"implicit"`
|
||||
AuthorizationCode AuthorizationCode `json:"authorization_code"`
|
||||
}
|
||||
|
||||
// 5.1.8 Implicit Object
|
||||
type Implicit struct {
|
||||
// Required. The login endpoint definition.
|
||||
loginEndpoint LoginEndpoint `json:"loginEndpoint"`
|
||||
// An optional alternative name to standard "access_token" OAuth2 parameter.
|
||||
TokenName string `json:"tokenName"`
|
||||
}
|
||||
|
||||
// 5.1.9 Authorization Code Object
|
||||
type AuthorizationCode struct {
|
||||
TokenRequestEndpoint TokenRequestEndpoint `json:"tokenRequestEndpoint"`
|
||||
TokenEndpoint TokenEndpoint `json:"tokenEndpoint"`
|
||||
}
|
||||
|
||||
// 5.1.10 Login Endpoint Object
|
||||
type LoginEndpoint struct {
|
||||
// Required. The URL of the authorization endpoint for the implicit grant flow. The value SHOULD be in a URL format.
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
// 5.1.11 Token Request Endpoint Object
|
||||
type TokenRequestEndpoint struct {
|
||||
// Required. The URL of the authorization endpoint for the authentication code grant flow. The value SHOULD be in a URL format.
|
||||
Url string `json:"url"`
|
||||
// An optional alternative name to standard "client_id" OAuth2 parameter.
|
||||
ClientIdName string `json:"clientIdName"`
|
||||
// An optional alternative name to the standard "client_secret" OAuth2 parameter.
|
||||
ClientSecretName string `json:"clientSecretName"`
|
||||
}
|
||||
|
||||
// 5.1.12 Token Endpoint Object
|
||||
type TokenEndpoint struct {
|
||||
// Required. The URL of the token endpoint for the authentication code grant flow. The value SHOULD be in a URL format.
|
||||
Url string `json:"url"`
|
||||
// An optional alternative name to standard "access_token" OAuth2 parameter.
|
||||
TokenName string `json:"tokenName"`
|
||||
}
|
||||
|
||||
// 5.2 API Declaration
|
||||
type ApiDeclaration struct {
|
||||
SwaggerVersion string `json:"swaggerVersion"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
BasePath string `json:"basePath"`
|
||||
ResourcePath string `json:"resourcePath"` // must start with /
|
||||
Info Info `json:"info"`
|
||||
Apis []Api `json:"apis,omitempty"`
|
||||
Models ModelList `json:"models,omitempty"`
|
||||
Produces []string `json:"produces,omitempty"`
|
||||
Consumes []string `json:"consumes,omitempty"`
|
||||
Authorizations []Authorization `json:"authorizations,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.2 API Object
|
||||
type Api struct {
|
||||
Path string `json:"path"` // relative or absolute, must start with /
|
||||
Description string `json:"description"`
|
||||
Operations []Operation `json:"operations,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.3 Operation Object
|
||||
type Operation struct {
|
||||
DataTypeFields
|
||||
Method string `json:"method"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
Notes string `json:"notes,omitempty"`
|
||||
Nickname string `json:"nickname"`
|
||||
Authorizations []Authorization `json:"authorizations,omitempty"`
|
||||
Parameters []Parameter `json:"parameters"`
|
||||
ResponseMessages []ResponseMessage `json:"responseMessages,omitempty"` // optional
|
||||
Produces []string `json:"produces,omitempty"`
|
||||
Consumes []string `json:"consumes,omitempty"`
|
||||
Deprecated string `json:"deprecated,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.4 Parameter Object
|
||||
type Parameter struct {
|
||||
DataTypeFields
|
||||
ParamType string `json:"paramType"` // path,query,body,header,form
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
AllowMultiple bool `json:"allowMultiple"`
|
||||
}
|
||||
|
||||
// 5.2.5 Response Message Object
|
||||
type ResponseMessage struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
ResponseModel string `json:"responseModel,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.6, 5.2.7 Models Object
|
||||
type Model struct {
|
||||
Id string `json:"id"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Required []string `json:"required,omitempty"`
|
||||
Properties ModelPropertyList `json:"properties"`
|
||||
SubTypes []string `json:"subTypes,omitempty"`
|
||||
Discriminator string `json:"discriminator,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.8 Properties Object
|
||||
type ModelProperty struct {
|
||||
DataTypeFields
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// 5.2.10
|
||||
type Authorizations map[string]Authorization
|
21
vendor/github.com/emicklei/go-restful-swagger12/swagger_builder.go
generated
vendored
Normal file
21
vendor/github.com/emicklei/go-restful-swagger12/swagger_builder.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package swagger
|
||||
|
||||
type SwaggerBuilder struct {
|
||||
SwaggerService
|
||||
}
|
||||
|
||||
func NewSwaggerBuilder(config Config) *SwaggerBuilder {
|
||||
return &SwaggerBuilder{*newSwaggerService(config)}
|
||||
}
|
||||
|
||||
func (sb SwaggerBuilder) ProduceListing() ResourceListing {
|
||||
return sb.SwaggerService.produceListing()
|
||||
}
|
||||
|
||||
func (sb SwaggerBuilder) ProduceAllDeclarations() map[string]ApiDeclaration {
|
||||
return sb.SwaggerService.produceAllDeclarations()
|
||||
}
|
||||
|
||||
func (sb SwaggerBuilder) ProduceDeclarations(route string) (*ApiDeclaration, bool) {
|
||||
return sb.SwaggerService.produceDeclarations(route)
|
||||
}
|
318
vendor/github.com/emicklei/go-restful-swagger12/swagger_test.go
generated
vendored
Normal file
318
vendor/github.com/emicklei/go-restful-swagger12/swagger_test.go
generated
vendored
Normal file
|
@ -0,0 +1,318 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-swagger12/test_package"
|
||||
)
|
||||
|
||||
func TestInfoStruct_Issue231(t *testing.T) {
|
||||
config := Config{
|
||||
Info: Info{
|
||||
Title: "Title",
|
||||
Description: "Description",
|
||||
TermsOfServiceUrl: "http://example.com",
|
||||
Contact: "example@example.com",
|
||||
License: "License",
|
||||
LicenseUrl: "http://example.com/license.txt",
|
||||
},
|
||||
}
|
||||
sws := newSwaggerService(config)
|
||||
str, err := json.MarshalIndent(sws.produceListing(), "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
compareJson(t, string(str), `
|
||||
{
|
||||
"apiVersion": "",
|
||||
"swaggerVersion": "1.2",
|
||||
"apis": null,
|
||||
"info": {
|
||||
"title": "Title",
|
||||
"description": "Description",
|
||||
"termsOfServiceUrl": "http://example.com",
|
||||
"contact": "example@example.com",
|
||||
"license": "License",
|
||||
"licenseUrl": "http://example.com/license.txt"
|
||||
}
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
// go test -v -test.run TestThatMultiplePathsOnRootAreHandled ...swagger
|
||||
func TestThatMultiplePathsOnRootAreHandled(t *testing.T) {
|
||||
ws1 := new(restful.WebService)
|
||||
ws1.Route(ws1.GET("/_ping").To(dummy))
|
||||
ws1.Route(ws1.GET("/version").To(dummy))
|
||||
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws1},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
decl := sws.composeDeclaration(ws1, "/")
|
||||
if got, want := len(decl.Apis), 2; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteSamples(t *testing.T) {
|
||||
ws1 := new(restful.WebService)
|
||||
ws1.Route(ws1.GET("/object").To(dummy).Writes(test_package.TestStruct{}))
|
||||
ws1.Route(ws1.GET("/array").To(dummy).Writes([]test_package.TestStruct{}))
|
||||
ws1.Route(ws1.GET("/object_and_array").To(dummy).Writes(struct{ Abc test_package.TestStruct }{}))
|
||||
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws1},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
|
||||
decl := sws.composeDeclaration(ws1, "/")
|
||||
|
||||
str, err := json.MarshalIndent(decl.Apis, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
compareJson(t, string(str), `
|
||||
[
|
||||
{
|
||||
"path": "/object",
|
||||
"description": "",
|
||||
"operations": [
|
||||
{
|
||||
"type": "test_package.TestStruct",
|
||||
"method": "GET",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/array",
|
||||
"description": "",
|
||||
"operations": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "test_package.TestStruct"
|
||||
},
|
||||
"method": "GET",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/object_and_array",
|
||||
"description": "",
|
||||
"operations": [
|
||||
{
|
||||
"type": "struct { Abc test_package.TestStruct }",
|
||||
"method": "GET",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]`)
|
||||
|
||||
str, err = json.MarshalIndent(decl.Models, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
compareJson(t, string(str), `
|
||||
{
|
||||
"test_package.TestStruct": {
|
||||
"id": "test_package.TestStruct",
|
||||
"required": [
|
||||
"TestField"
|
||||
],
|
||||
"properties": {
|
||||
"TestField": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"||test_package.TestStruct": {
|
||||
"id": "||test_package.TestStruct",
|
||||
"properties": {}
|
||||
},
|
||||
"struct { Abc test_package.TestStruct }": {
|
||||
"id": "struct { Abc test_package.TestStruct }",
|
||||
"required": [
|
||||
"Abc"
|
||||
],
|
||||
"properties": {
|
||||
"Abc": {
|
||||
"$ref": "test_package.TestStruct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestRoutesWithCommonPart(t *testing.T) {
|
||||
ws1 := new(restful.WebService)
|
||||
ws1.Path("/")
|
||||
ws1.Route(ws1.GET("/foobar").To(dummy).Writes(test_package.TestStruct{}))
|
||||
ws1.Route(ws1.HEAD("/foobar").To(dummy).Writes(test_package.TestStruct{}))
|
||||
ws1.Route(ws1.GET("/foo").To(dummy).Writes([]test_package.TestStruct{}))
|
||||
ws1.Route(ws1.HEAD("/foo").To(dummy).Writes(test_package.TestStruct{}))
|
||||
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws1},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
|
||||
decl := sws.composeDeclaration(ws1, "/foo")
|
||||
|
||||
str, err := json.MarshalIndent(decl.Apis, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
compareJson(t, string(str), `[
|
||||
{
|
||||
"path": "/foo",
|
||||
"description": "",
|
||||
"operations": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "test_package.TestStruct"
|
||||
},
|
||||
"method": "GET",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
},
|
||||
{
|
||||
"type": "test_package.TestStruct",
|
||||
"method": "HEAD",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]`)
|
||||
}
|
||||
|
||||
// go test -v -test.run TestServiceToApi ...swagger
|
||||
func TestServiceToApi(t *testing.T) {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path("/tests")
|
||||
ws.Consumes(restful.MIME_JSON)
|
||||
ws.Produces(restful.MIME_XML)
|
||||
ws.Route(ws.GET("/a").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.PUT("/b").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.POST("/c").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.DELETE("/d").To(dummy).Writes(sample{}))
|
||||
|
||||
ws.Route(ws.GET("/d").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.PUT("/c").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.POST("/b").To(dummy).Writes(sample{}))
|
||||
ws.Route(ws.DELETE("/a").To(dummy).Writes(sample{}))
|
||||
ws.ApiVersion("1.2.3")
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws},
|
||||
PostBuildHandler: func(in *ApiDeclarationList) {},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
decl := sws.composeDeclaration(ws, "/tests")
|
||||
// checks
|
||||
if decl.ApiVersion != "1.2.3" {
|
||||
t.Errorf("got %v want %v", decl.ApiVersion, "1.2.3")
|
||||
}
|
||||
if decl.BasePath != "http://here.com" {
|
||||
t.Errorf("got %v want %v", decl.BasePath, "http://here.com")
|
||||
}
|
||||
if len(decl.Apis) != 4 {
|
||||
t.Errorf("got %v want %v", len(decl.Apis), 4)
|
||||
}
|
||||
pathOrder := ""
|
||||
for _, each := range decl.Apis {
|
||||
pathOrder += each.Path
|
||||
for _, other := range each.Operations {
|
||||
pathOrder += other.Method
|
||||
}
|
||||
}
|
||||
|
||||
if pathOrder != "/tests/aGETDELETE/tests/bPUTPOST/tests/cPOSTPUT/tests/dDELETEGET" {
|
||||
t.Errorf("got %v want %v", pathOrder, "see test source")
|
||||
}
|
||||
}
|
||||
|
||||
func dummy(i *restful.Request, o *restful.Response) {}
|
||||
|
||||
// go test -v -test.run TestIssue78 ...swagger
|
||||
type Response struct {
|
||||
Code int
|
||||
Users *[]User
|
||||
Items *[]TestItem
|
||||
}
|
||||
type User struct {
|
||||
Id, Name string
|
||||
}
|
||||
type TestItem struct {
|
||||
Id, Name string
|
||||
}
|
||||
|
||||
// clear && go test -v -test.run TestComposeResponseMessages ...swagger
|
||||
func TestComposeResponseMessages(t *testing.T) {
|
||||
responseErrors := map[int]restful.ResponseError{}
|
||||
responseErrors[400] = restful.ResponseError{Code: 400, Message: "Bad Request", Model: TestItem{}}
|
||||
route := restful.Route{ResponseErrors: responseErrors}
|
||||
decl := new(ApiDeclaration)
|
||||
decl.Models = ModelList{}
|
||||
msgs := composeResponseMessages(route, decl, &Config{})
|
||||
if msgs[0].ResponseModel != "swagger.TestItem" {
|
||||
t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue78(t *testing.T) {
|
||||
sws := newSwaggerService(Config{})
|
||||
models := new(ModelList)
|
||||
sws.addModelFromSampleTo(&Operation{}, true, Response{Items: &[]TestItem{}}, models)
|
||||
model, ok := models.At("swagger.Response")
|
||||
if !ok {
|
||||
t.Fatal("missing response model")
|
||||
}
|
||||
if "swagger.Response" != model.Id {
|
||||
t.Fatal("wrong model id:" + model.Id)
|
||||
}
|
||||
code, ok := model.Properties.At("Code")
|
||||
if !ok {
|
||||
t.Fatal("missing code")
|
||||
}
|
||||
if "integer" != *code.Type {
|
||||
t.Fatal("wrong code type:" + *code.Type)
|
||||
}
|
||||
items, ok := model.Properties.At("Items")
|
||||
if !ok {
|
||||
t.Fatal("missing items")
|
||||
}
|
||||
if "array" != *items.Type {
|
||||
t.Fatal("wrong items type:" + *items.Type)
|
||||
}
|
||||
items_items := items.Items
|
||||
if items_items == nil {
|
||||
t.Fatal("missing items->items")
|
||||
}
|
||||
ref := items_items.Ref
|
||||
if ref == nil {
|
||||
t.Fatal("missing $ref")
|
||||
}
|
||||
if *ref != "swagger.TestItem" {
|
||||
t.Fatal("wrong $ref:" + *ref)
|
||||
}
|
||||
}
|
443
vendor/github.com/emicklei/go-restful-swagger12/swagger_webservice.go
generated
vendored
Normal file
443
vendor/github.com/emicklei/go-restful-swagger12/swagger_webservice.go
generated
vendored
Normal file
|
@ -0,0 +1,443 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
// "github.com/emicklei/hopwatch"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful/log"
|
||||
)
|
||||
|
||||
type SwaggerService struct {
|
||||
config Config
|
||||
apiDeclarationMap *ApiDeclarationList
|
||||
}
|
||||
|
||||
func newSwaggerService(config Config) *SwaggerService {
|
||||
sws := &SwaggerService{
|
||||
config: config,
|
||||
apiDeclarationMap: new(ApiDeclarationList)}
|
||||
|
||||
// Build all ApiDeclarations
|
||||
for _, each := range config.WebServices {
|
||||
rootPath := each.RootPath()
|
||||
// skip the api service itself
|
||||
if rootPath != config.ApiPath {
|
||||
if rootPath == "" || rootPath == "/" {
|
||||
// use routes
|
||||
for _, route := range each.Routes() {
|
||||
entry := staticPathFromRoute(route)
|
||||
_, exists := sws.apiDeclarationMap.At(entry)
|
||||
if !exists {
|
||||
sws.apiDeclarationMap.Put(entry, sws.composeDeclaration(each, entry))
|
||||
}
|
||||
}
|
||||
} else { // use root path
|
||||
sws.apiDeclarationMap.Put(each.RootPath(), sws.composeDeclaration(each, each.RootPath()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if specified then call the PostBuilderHandler
|
||||
if config.PostBuildHandler != nil {
|
||||
config.PostBuildHandler(sws.apiDeclarationMap)
|
||||
}
|
||||
return sws
|
||||
}
|
||||
|
||||
// LogInfo is the function that is called when this package needs to log. It defaults to log.Printf
|
||||
var LogInfo = func(format string, v ...interface{}) {
|
||||
// use the restful package-wide logger
|
||||
log.Printf(format, v...)
|
||||
}
|
||||
|
||||
// InstallSwaggerService add the WebService that provides the API documentation of all services
|
||||
// conform the Swagger documentation specifcation. (https://github.com/wordnik/swagger-core/wiki).
|
||||
func InstallSwaggerService(aSwaggerConfig Config) {
|
||||
RegisterSwaggerService(aSwaggerConfig, restful.DefaultContainer)
|
||||
}
|
||||
|
||||
// RegisterSwaggerService add the WebService that provides the API documentation of all services
|
||||
// conform the Swagger documentation specifcation. (https://github.com/wordnik/swagger-core/wiki).
|
||||
func RegisterSwaggerService(config Config, wsContainer *restful.Container) {
|
||||
sws := newSwaggerService(config)
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(config.ApiPath)
|
||||
ws.Produces(restful.MIME_JSON)
|
||||
if config.DisableCORS {
|
||||
ws.Filter(enableCORS)
|
||||
}
|
||||
ws.Route(ws.GET("/").To(sws.getListing))
|
||||
ws.Route(ws.GET("/{a}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}/{c}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}/{c}/{d}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}/{c}/{d}/{e}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}/{c}/{d}/{e}/{f}").To(sws.getDeclarations))
|
||||
ws.Route(ws.GET("/{a}/{b}/{c}/{d}/{e}/{f}/{g}").To(sws.getDeclarations))
|
||||
LogInfo("[restful/swagger] listing is available at %v%v", config.WebServicesUrl, config.ApiPath)
|
||||
wsContainer.Add(ws)
|
||||
|
||||
// Check paths for UI serving
|
||||
if config.StaticHandler == nil && config.SwaggerFilePath != "" && config.SwaggerPath != "" {
|
||||
swaggerPathSlash := config.SwaggerPath
|
||||
// path must end with slash /
|
||||
if "/" != config.SwaggerPath[len(config.SwaggerPath)-1:] {
|
||||
LogInfo("[restful/swagger] use corrected SwaggerPath ; must end with slash (/)")
|
||||
swaggerPathSlash += "/"
|
||||
}
|
||||
|
||||
LogInfo("[restful/swagger] %v%v is mapped to folder %v", config.WebServicesUrl, swaggerPathSlash, config.SwaggerFilePath)
|
||||
wsContainer.Handle(swaggerPathSlash, http.StripPrefix(swaggerPathSlash, http.FileServer(http.Dir(config.SwaggerFilePath))))
|
||||
|
||||
//if we define a custom static handler use it
|
||||
} else if config.StaticHandler != nil && config.SwaggerPath != "" {
|
||||
swaggerPathSlash := config.SwaggerPath
|
||||
// path must end with slash /
|
||||
if "/" != config.SwaggerPath[len(config.SwaggerPath)-1:] {
|
||||
LogInfo("[restful/swagger] use corrected SwaggerFilePath ; must end with slash (/)")
|
||||
swaggerPathSlash += "/"
|
||||
|
||||
}
|
||||
LogInfo("[restful/swagger] %v%v is mapped to custom Handler %T", config.WebServicesUrl, swaggerPathSlash, config.StaticHandler)
|
||||
wsContainer.Handle(swaggerPathSlash, config.StaticHandler)
|
||||
|
||||
} else {
|
||||
LogInfo("[restful/swagger] Swagger(File)Path is empty ; no UI is served")
|
||||
}
|
||||
}
|
||||
|
||||
func staticPathFromRoute(r restful.Route) string {
|
||||
static := r.Path
|
||||
bracket := strings.Index(static, "{")
|
||||
if bracket <= 1 { // result cannot be empty
|
||||
return static
|
||||
}
|
||||
if bracket != -1 {
|
||||
static = r.Path[:bracket]
|
||||
}
|
||||
if strings.HasSuffix(static, "/") {
|
||||
return static[:len(static)-1]
|
||||
} else {
|
||||
return static
|
||||
}
|
||||
}
|
||||
|
||||
func enableCORS(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
if origin := req.HeaderParameter(restful.HEADER_Origin); origin != "" {
|
||||
// prevent duplicate header
|
||||
if len(resp.Header().Get(restful.HEADER_AccessControlAllowOrigin)) == 0 {
|
||||
resp.AddHeader(restful.HEADER_AccessControlAllowOrigin, origin)
|
||||
}
|
||||
}
|
||||
chain.ProcessFilter(req, resp)
|
||||
}
|
||||
|
||||
func (sws SwaggerService) getListing(req *restful.Request, resp *restful.Response) {
|
||||
listing := sws.produceListing()
|
||||
resp.WriteAsJson(listing)
|
||||
}
|
||||
|
||||
func (sws SwaggerService) produceListing() ResourceListing {
|
||||
listing := ResourceListing{SwaggerVersion: swaggerVersion, ApiVersion: sws.config.ApiVersion, Info: sws.config.Info}
|
||||
sws.apiDeclarationMap.Do(func(k string, v ApiDeclaration) {
|
||||
ref := Resource{Path: k}
|
||||
if len(v.Apis) > 0 { // use description of first (could still be empty)
|
||||
ref.Description = v.Apis[0].Description
|
||||
}
|
||||
listing.Apis = append(listing.Apis, ref)
|
||||
})
|
||||
return listing
|
||||
}
|
||||
|
||||
func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Response) {
|
||||
decl, ok := sws.produceDeclarations(composeRootPath(req))
|
||||
if !ok {
|
||||
resp.WriteErrorString(http.StatusNotFound, "ApiDeclaration not found")
|
||||
return
|
||||
}
|
||||
// unless WebServicesUrl is given
|
||||
if len(sws.config.WebServicesUrl) == 0 {
|
||||
// update base path from the actual request
|
||||
// TODO how to detect https? assume http for now
|
||||
var host string
|
||||
// X-Forwarded-Host or Host or Request.Host
|
||||
hostvalues, ok := req.Request.Header["X-Forwarded-Host"] // apache specific?
|
||||
if !ok || len(hostvalues) == 0 {
|
||||
forwarded, ok := req.Request.Header["Host"] // without reverse-proxy
|
||||
if !ok || len(forwarded) == 0 {
|
||||
// fallback to Host field
|
||||
host = req.Request.Host
|
||||
} else {
|
||||
host = forwarded[0]
|
||||
}
|
||||
} else {
|
||||
host = hostvalues[0]
|
||||
}
|
||||
// inspect Referer for the scheme (http vs https)
|
||||
scheme := "http"
|
||||
if referer := req.Request.Header["Referer"]; len(referer) > 0 {
|
||||
if strings.HasPrefix(referer[0], "https") {
|
||||
scheme = "https"
|
||||
}
|
||||
}
|
||||
decl.BasePath = fmt.Sprintf("%s://%s", scheme, host)
|
||||
}
|
||||
resp.WriteAsJson(decl)
|
||||
}
|
||||
|
||||
func (sws SwaggerService) produceAllDeclarations() map[string]ApiDeclaration {
|
||||
decls := map[string]ApiDeclaration{}
|
||||
sws.apiDeclarationMap.Do(func(k string, v ApiDeclaration) {
|
||||
decls[k] = v
|
||||
})
|
||||
return decls
|
||||
}
|
||||
|
||||
func (sws SwaggerService) produceDeclarations(route string) (*ApiDeclaration, bool) {
|
||||
decl, ok := sws.apiDeclarationMap.At(route)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
decl.BasePath = sws.config.WebServicesUrl
|
||||
return &decl, true
|
||||
}
|
||||
|
||||
// composeDeclaration uses all routes and parameters to create a ApiDeclaration
|
||||
func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix string) ApiDeclaration {
|
||||
decl := ApiDeclaration{
|
||||
SwaggerVersion: swaggerVersion,
|
||||
BasePath: sws.config.WebServicesUrl,
|
||||
ResourcePath: pathPrefix,
|
||||
Models: ModelList{},
|
||||
ApiVersion: ws.Version()}
|
||||
|
||||
// collect any path parameters
|
||||
rootParams := []Parameter{}
|
||||
for _, param := range ws.PathParameters() {
|
||||
rootParams = append(rootParams, asSwaggerParameter(param.Data()))
|
||||
}
|
||||
// aggregate by path
|
||||
pathToRoutes := newOrderedRouteMap()
|
||||
for _, other := range ws.Routes() {
|
||||
if strings.HasPrefix(other.Path, pathPrefix) {
|
||||
if len(pathPrefix) > 1 && len(other.Path) > len(pathPrefix) && other.Path[len(pathPrefix)] != '/' {
|
||||
continue
|
||||
}
|
||||
pathToRoutes.Add(other.Path, other)
|
||||
}
|
||||
}
|
||||
pathToRoutes.Do(func(path string, routes []restful.Route) {
|
||||
api := Api{Path: strings.TrimSuffix(withoutWildcard(path), "/"), Description: ws.Documentation()}
|
||||
voidString := "void"
|
||||
for _, route := range routes {
|
||||
operation := Operation{
|
||||
Method: route.Method,
|
||||
Summary: route.Doc,
|
||||
Notes: route.Notes,
|
||||
// Type gets overwritten if there is a write sample
|
||||
DataTypeFields: DataTypeFields{Type: &voidString},
|
||||
Parameters: []Parameter{},
|
||||
Nickname: route.Operation,
|
||||
ResponseMessages: composeResponseMessages(route, &decl, &sws.config)}
|
||||
|
||||
operation.Consumes = route.Consumes
|
||||
operation.Produces = route.Produces
|
||||
|
||||
// share root params if any
|
||||
for _, swparam := range rootParams {
|
||||
operation.Parameters = append(operation.Parameters, swparam)
|
||||
}
|
||||
// route specific params
|
||||
for _, param := range route.ParameterDocs {
|
||||
operation.Parameters = append(operation.Parameters, asSwaggerParameter(param.Data()))
|
||||
}
|
||||
|
||||
sws.addModelsFromRouteTo(&operation, route, &decl)
|
||||
api.Operations = append(api.Operations, operation)
|
||||
}
|
||||
decl.Apis = append(decl.Apis, api)
|
||||
})
|
||||
return decl
|
||||
}
|
||||
|
||||
func withoutWildcard(path string) string {
|
||||
if strings.HasSuffix(path, ":*}") {
|
||||
return path[0:len(path)-3] + "}"
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// composeResponseMessages takes the ResponseErrors (if any) and creates ResponseMessages from them.
|
||||
func composeResponseMessages(route restful.Route, decl *ApiDeclaration, config *Config) (messages []ResponseMessage) {
|
||||
if route.ResponseErrors == nil {
|
||||
return messages
|
||||
}
|
||||
// sort by code
|
||||
codes := sort.IntSlice{}
|
||||
for code := range route.ResponseErrors {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
codes.Sort()
|
||||
for _, code := range codes {
|
||||
each := route.ResponseErrors[code]
|
||||
message := ResponseMessage{
|
||||
Code: code,
|
||||
Message: each.Message,
|
||||
}
|
||||
if each.Model != nil {
|
||||
st := reflect.TypeOf(each.Model)
|
||||
isCollection, st := detectCollectionType(st)
|
||||
// collection cannot be in responsemodel
|
||||
if !isCollection {
|
||||
modelName := modelBuilder{}.keyFrom(st)
|
||||
modelBuilder{Models: &decl.Models, Config: config}.addModel(st, "")
|
||||
message.ResponseModel = modelName
|
||||
}
|
||||
}
|
||||
messages = append(messages, message)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// addModelsFromRoute takes any read or write sample from the Route and creates a Swagger model from it.
|
||||
func (sws SwaggerService) addModelsFromRouteTo(operation *Operation, route restful.Route, decl *ApiDeclaration) {
|
||||
if route.ReadSample != nil {
|
||||
sws.addModelFromSampleTo(operation, false, route.ReadSample, &decl.Models)
|
||||
}
|
||||
if route.WriteSample != nil {
|
||||
sws.addModelFromSampleTo(operation, true, route.WriteSample, &decl.Models)
|
||||
}
|
||||
}
|
||||
|
||||
func detectCollectionType(st reflect.Type) (bool, reflect.Type) {
|
||||
isCollection := false
|
||||
if st.Kind() == reflect.Slice || st.Kind() == reflect.Array {
|
||||
st = st.Elem()
|
||||
isCollection = true
|
||||
} else {
|
||||
if st.Kind() == reflect.Ptr {
|
||||
if st.Elem().Kind() == reflect.Slice || st.Elem().Kind() == reflect.Array {
|
||||
st = st.Elem().Elem()
|
||||
isCollection = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return isCollection, st
|
||||
}
|
||||
|
||||
// addModelFromSample creates and adds (or overwrites) a Model from a sample resource
|
||||
func (sws SwaggerService) addModelFromSampleTo(operation *Operation, isResponse bool, sample interface{}, models *ModelList) {
|
||||
mb := modelBuilder{Models: models, Config: &sws.config}
|
||||
if isResponse {
|
||||
sampleType, items := asDataType(sample, &sws.config)
|
||||
operation.Type = sampleType
|
||||
operation.Items = items
|
||||
}
|
||||
mb.addModelFrom(sample)
|
||||
}
|
||||
|
||||
func asSwaggerParameter(param restful.ParameterData) Parameter {
|
||||
return Parameter{
|
||||
DataTypeFields: DataTypeFields{
|
||||
Type: ¶m.DataType,
|
||||
Format: asFormat(param.DataType, param.DataFormat),
|
||||
DefaultValue: Special(param.DefaultValue),
|
||||
},
|
||||
Name: param.Name,
|
||||
Description: param.Description,
|
||||
ParamType: asParamType(param.Kind),
|
||||
|
||||
Required: param.Required}
|
||||
}
|
||||
|
||||
// Between 1..7 path parameters is supported
|
||||
func composeRootPath(req *restful.Request) string {
|
||||
path := "/" + req.PathParameter("a")
|
||||
b := req.PathParameter("b")
|
||||
if b == "" {
|
||||
return path
|
||||
}
|
||||
path = path + "/" + b
|
||||
c := req.PathParameter("c")
|
||||
if c == "" {
|
||||
return path
|
||||
}
|
||||
path = path + "/" + c
|
||||
d := req.PathParameter("d")
|
||||
if d == "" {
|
||||
return path
|
||||
}
|
||||
path = path + "/" + d
|
||||
e := req.PathParameter("e")
|
||||
if e == "" {
|
||||
return path
|
||||
}
|
||||
path = path + "/" + e
|
||||
f := req.PathParameter("f")
|
||||
if f == "" {
|
||||
return path
|
||||
}
|
||||
path = path + "/" + f
|
||||
g := req.PathParameter("g")
|
||||
if g == "" {
|
||||
return path
|
||||
}
|
||||
return path + "/" + g
|
||||
}
|
||||
|
||||
func asFormat(dataType string, dataFormat string) string {
|
||||
if dataFormat != "" {
|
||||
return dataFormat
|
||||
}
|
||||
return "" // TODO
|
||||
}
|
||||
|
||||
func asParamType(kind int) string {
|
||||
switch {
|
||||
case kind == restful.PathParameterKind:
|
||||
return "path"
|
||||
case kind == restful.QueryParameterKind:
|
||||
return "query"
|
||||
case kind == restful.BodyParameterKind:
|
||||
return "body"
|
||||
case kind == restful.HeaderParameterKind:
|
||||
return "header"
|
||||
case kind == restful.FormParameterKind:
|
||||
return "form"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func asDataType(any interface{}, config *Config) (*string, *Item) {
|
||||
// If it's not a collection, return the suggested model name
|
||||
st := reflect.TypeOf(any)
|
||||
isCollection, st := detectCollectionType(st)
|
||||
modelName := modelBuilder{}.keyFrom(st)
|
||||
// if it's not a collection we are done
|
||||
if !isCollection {
|
||||
return &modelName, nil
|
||||
}
|
||||
|
||||
// XXX: This is not very elegant
|
||||
// We create an Item object referring to the given model
|
||||
models := ModelList{}
|
||||
mb := modelBuilder{Models: &models, Config: config}
|
||||
mb.addModelFrom(any)
|
||||
|
||||
elemTypeName := mb.getElementTypeName(modelName, "", st)
|
||||
item := new(Item)
|
||||
if mb.isPrimitiveType(elemTypeName) {
|
||||
mapped := mb.jsonSchemaType(elemTypeName)
|
||||
item.Type = &mapped
|
||||
} else {
|
||||
item.Ref = &elemTypeName
|
||||
}
|
||||
tmp := "array"
|
||||
return &tmp, item
|
||||
}
|
86
vendor/github.com/emicklei/go-restful-swagger12/utils_test.go
generated
vendored
Normal file
86
vendor/github.com/emicklei/go-restful-swagger12/utils_test.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testJsonFromStructWithConfig(t *testing.T, sample interface{}, expectedJson string, config *Config) bool {
|
||||
m := modelsFromStructWithConfig(sample, config)
|
||||
data, _ := json.MarshalIndent(m, " ", " ")
|
||||
return compareJson(t, string(data), expectedJson)
|
||||
}
|
||||
|
||||
func modelsFromStructWithConfig(sample interface{}, config *Config) *ModelList {
|
||||
models := new(ModelList)
|
||||
builder := modelBuilder{Models: models, Config: config}
|
||||
builder.addModelFrom(sample)
|
||||
return models
|
||||
}
|
||||
|
||||
func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool {
|
||||
return testJsonFromStructWithConfig(t, sample, expectedJson, &Config{})
|
||||
}
|
||||
|
||||
func modelsFromStruct(sample interface{}) *ModelList {
|
||||
return modelsFromStructWithConfig(sample, &Config{})
|
||||
}
|
||||
|
||||
func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString string) bool {
|
||||
success := false
|
||||
var actualMap map[string]interface{}
|
||||
json.Unmarshal([]byte(actualJsonAsString), &actualMap)
|
||||
var expectedMap map[string]interface{}
|
||||
err := json.Unmarshal([]byte(expectedJsonAsString), &expectedMap)
|
||||
if err != nil {
|
||||
var actualArray []interface{}
|
||||
json.Unmarshal([]byte(actualJsonAsString), &actualArray)
|
||||
var expectedArray []interface{}
|
||||
err := json.Unmarshal([]byte(expectedJsonAsString), &expectedArray)
|
||||
success = reflect.DeepEqual(actualArray, expectedArray)
|
||||
if err != nil {
|
||||
t.Fatalf("Unparsable expected JSON: %s, actual: %v, expected: %v", err, actualJsonAsString, expectedJsonAsString)
|
||||
}
|
||||
} else {
|
||||
success = reflect.DeepEqual(actualMap, expectedMap)
|
||||
}
|
||||
if !success {
|
||||
t.Log("---- expected -----")
|
||||
t.Log(withLineNumbers(expectedJsonAsString))
|
||||
t.Log("---- actual -----")
|
||||
t.Log(withLineNumbers(actualJsonAsString))
|
||||
t.Log("---- raw -----")
|
||||
t.Log(actualJsonAsString)
|
||||
t.Error("there are differences")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func indexOfNonMatchingLine(actual, expected string) int {
|
||||
a := strings.Split(actual, "\n")
|
||||
e := strings.Split(expected, "\n")
|
||||
size := len(a)
|
||||
if len(e) < len(a) {
|
||||
size = len(e)
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
if a[i] != e[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func withLineNumbers(content string) string {
|
||||
var buffer bytes.Buffer
|
||||
lines := strings.Split(content, "\n")
|
||||
for i, each := range lines {
|
||||
buffer.WriteString(fmt.Sprintf("%d:%s\n", i, each))
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
1
vendor/github.com/go-openapi/spec/items.go
generated
vendored
1
vendor/github.com/go-openapi/spec/items.go
generated
vendored
|
@ -28,6 +28,7 @@ type SimpleSchema struct {
|
|||
Items *Items `json:"items,omitempty"`
|
||||
CollectionFormat string `json:"collectionFormat,omitempty"`
|
||||
Default interface{} `json:"default,omitempty"`
|
||||
Example interface{} `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
func (s *SimpleSchema) TypeName() string {
|
||||
|
|
2
vendor/github.com/go-openapi/swag/.gitignore
generated
vendored
2
vendor/github.com/go-openapi/swag/.gitignore
generated
vendored
|
@ -1 +1,3 @@
|
|||
secrets.yml
|
||||
vendor
|
||||
Godeps
|
||||
|
|
4
vendor/github.com/go-openapi/swag/path_test.go
generated
vendored
4
vendor/github.com/go-openapi/swag/path_test.go
generated
vendored
|
@ -17,8 +17,8 @@ package swag
|
|||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
|
@ -75,7 +75,7 @@ func TestFindPackage(t *testing.T) {
|
|||
os.RemoveAll(pth2)
|
||||
}()
|
||||
|
||||
searchPath := pth + string(filepath.ListSeparator) + pth2
|
||||
searchPath := pth + string(filepath.ListSeparator) + pth2
|
||||
// finds package when real name mentioned
|
||||
pkg := FindInSearchPath(searchPath, "foo/bar")
|
||||
assert.NotEmpty(t, pkg)
|
||||
|
|
42
vendor/github.com/go-openapi/swag/util.go
generated
vendored
42
vendor/github.com/go-openapi/swag/util.go
generated
vendored
|
@ -40,6 +40,7 @@ var commonInitialisms = map[string]bool{
|
|||
"IP": true,
|
||||
"JSON": true,
|
||||
"LHS": true,
|
||||
"OAI": true,
|
||||
"QPS": true,
|
||||
"RAM": true,
|
||||
"RHS": true,
|
||||
|
@ -163,8 +164,8 @@ func split(str string) (words []string) {
|
|||
|
||||
// Split when uppercase is found (needed for Snake)
|
||||
str = rex1.ReplaceAllString(str, " $1")
|
||||
// check if consecutive single char things make up an initialism
|
||||
|
||||
// check if consecutive single char things make up an initialism
|
||||
for _, k := range initialisms {
|
||||
str = strings.Replace(str, rex1.ReplaceAllString(k, " $1"), " "+k, -1)
|
||||
}
|
||||
|
@ -189,10 +190,47 @@ func lower(str string) string {
|
|||
return strings.ToLower(trim(str))
|
||||
}
|
||||
|
||||
// Camelize an uppercased word
|
||||
func Camelize(word string) (camelized string) {
|
||||
for pos, ru := range word {
|
||||
if pos > 0 {
|
||||
camelized += string(unicode.ToLower(ru))
|
||||
} else {
|
||||
camelized += string(unicode.ToUpper(ru))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ToFileName lowercases and underscores a go type name
|
||||
func ToFileName(name string) string {
|
||||
var out []string
|
||||
for _, w := range split(name) {
|
||||
cml := trim(name)
|
||||
|
||||
// Camelize any capital word preceding a reserved keyword ("initialism")
|
||||
// thus, upper-cased words preceding a common initialism will get separated
|
||||
// e.g: ELBHTTPLoadBalancer becomes elb_http_load_balancer
|
||||
rexPrevious := regexp.MustCompile(`(?P<word>\p{Lu}{2,})(?:HTTP|OAI)`)
|
||||
cml = rexPrevious.ReplaceAllStringFunc(cml, func(match string) (replaceInMatch string) {
|
||||
for _, m := range rexPrevious.FindAllStringSubmatch(match, -1) { // [ match submatch ]
|
||||
if m[1] != "" {
|
||||
replaceInMatch = strings.Replace(m[0], m[1], Camelize(m[1]), -1)
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
// Pre-camelize reserved keywords ("initialisms") to avoid unnecessary hyphenization
|
||||
for _, k := range initialisms {
|
||||
cml = strings.Replace(cml, k, Camelize(k), -1)
|
||||
}
|
||||
|
||||
// Camelize other capital words to avoid unnecessary hyphenization
|
||||
rexCase := regexp.MustCompile(`(\p{Lu}{2,})`)
|
||||
cml = rexCase.ReplaceAllStringFunc(cml, Camelize)
|
||||
|
||||
// Final split with hyphens
|
||||
for _, w := range split(cml) {
|
||||
out = append(out, lower(w))
|
||||
}
|
||||
return strings.Join(out, "_")
|
||||
|
|
11
vendor/github.com/go-openapi/swag/util_test.go
generated
vendored
11
vendor/github.com/go-openapi/swag/util_test.go
generated
vendored
|
@ -39,6 +39,7 @@ func TestToGoName(t *testing.T) {
|
|||
{"findThingById", "FindThingByID"},
|
||||
{"日本語sample 2 Text", "X日本語sample2Text"},
|
||||
{"日本語findThingById", "X日本語findThingByID"},
|
||||
{"findTHINGSbyID", "FindTHINGSbyID"},
|
||||
}
|
||||
|
||||
for k := range commonInitialisms {
|
||||
|
@ -122,8 +123,16 @@ func TestToFileName(t *testing.T) {
|
|||
samples := []translationSample{
|
||||
{"SampleText", "sample_text"},
|
||||
{"FindThingByID", "find_thing_by_id"},
|
||||
{"CAPWD.folwdBYlc", "capwd_folwd_bylc"},
|
||||
{"CAPWDfolwdBYlc", "capwdfolwd_bylc"},
|
||||
{"CAP_WD_folwdBYlc", "cap_wd_folwd_bylc"},
|
||||
{"TypeOAI_alias", "type_oai_alias"},
|
||||
{"Type_OAI_alias", "type_oai_alias"},
|
||||
{"Type_OAIAlias", "type_oai_alias"},
|
||||
{"ELB.HTTPLoadBalancer", "elb_http_load_balancer"},
|
||||
{"elbHTTPLoadBalancer", "elb_http_load_balancer"},
|
||||
{"ELBHTTPLoadBalancer", "elb_http_load_balancer"},
|
||||
}
|
||||
|
||||
for k := range commonInitialisms {
|
||||
samples = append(samples,
|
||||
translationSample{"Sample" + k + "Text", "sample_" + lower(k) + "_text"},
|
||||
|
|
24
vendor/github.com/golang/groupcache/lru/lru_test.go
generated
vendored
24
vendor/github.com/golang/groupcache/lru/lru_test.go
generated
vendored
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package lru
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -71,3 +72,26 @@ func TestRemove(t *testing.T) {
|
|||
t.Fatal("TestRemove returned a removed entry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvict(t *testing.T) {
|
||||
evictedKeys := make([]Key, 0)
|
||||
onEvictedFun := func(key Key, value interface{}) {
|
||||
evictedKeys = append(evictedKeys, key)
|
||||
}
|
||||
|
||||
lru := New(20)
|
||||
lru.OnEvicted = onEvictedFun
|
||||
for i := 0; i < 22; i++ {
|
||||
lru.Add(fmt.Sprintf("myKey%d", i), 1234)
|
||||
}
|
||||
|
||||
if len(evictedKeys) != 2 {
|
||||
t.Fatalf("got %d evicted keys; want 2", len(evictedKeys))
|
||||
}
|
||||
if evictedKeys[0] != Key("myKey0") {
|
||||
t.Fatalf("got %v in first evicted key; want %s", evictedKeys[0], "myKey0")
|
||||
}
|
||||
if evictedKeys[1] != Key("myKey1") {
|
||||
t.Fatalf("got %v in second evicted key; want %s", evictedKeys[1], "myKey1")
|
||||
}
|
||||
}
|
||||
|
|
1
vendor/github.com/golang/protobuf/README.md
generated
vendored
1
vendor/github.com/golang/protobuf/README.md
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
# Go support for Protocol Buffers
|
||||
|
||||
[](https://travis-ci.org/golang/protobuf)
|
||||
[](https://godoc.org/github.com/golang/protobuf)
|
||||
|
||||
Google's data interchange format.
|
||||
Copyright 2010 The Go Authors.
|
||||
|
|
1
vendor/github.com/gophercloud/gophercloud/.gitignore
generated
vendored
1
vendor/github.com/gophercloud/gophercloud/.gitignore
generated
vendored
|
@ -1 +1,2 @@
|
|||
**/*.swp
|
||||
.idea
|
||||
|
|
12
vendor/github.com/gophercloud/gophercloud/.zuul.yaml
generated
vendored
Normal file
12
vendor/github.com/gophercloud/gophercloud/.zuul.yaml
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
- project:
|
||||
name: gophercloud/gophercloud
|
||||
check:
|
||||
jobs:
|
||||
- gophercloud-unittest
|
||||
- gophercloud-acceptance-test
|
||||
recheck-mitaka:
|
||||
jobs:
|
||||
- gophercloud-acceptance-test-mitaka
|
||||
recheck-pike:
|
||||
jobs:
|
||||
- gophercloud-acceptance-test-pike
|
8
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
8
vendor/github.com/gophercloud/gophercloud/openstack/client.go
generated
vendored
|
@ -346,3 +346,11 @@ func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
|
|||
sc.ResourceBase = sc.Endpoint + "v2/"
|
||||
return sc, err
|
||||
}
|
||||
|
||||
// NewLoadBalancerV2 creates a ServiceClient that may be used to access the v2
|
||||
// load balancer service.
|
||||
func NewLoadBalancerV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||
sc, err := initClientOpts(client, eo, "load-balancer")
|
||||
sc.ResourceBase = sc.Endpoint + "v2.0/"
|
||||
return sc, err
|
||||
}
|
||||
|
|
1
vendor/github.com/gophercloud/gophercloud/pagination/pager.go
generated
vendored
1
vendor/github.com/gophercloud/gophercloud/pagination/pager.go
generated
vendored
|
@ -22,7 +22,6 @@ var (
|
|||
// Depending on the pagination strategy of a particular resource, there may be an additional subinterface that the result type
|
||||
// will need to implement.
|
||||
type Page interface {
|
||||
|
||||
// NextPageURL generates the URL for the page of data that follows this collection.
|
||||
// Return "" if no such page exists.
|
||||
NextPageURL() (string, error)
|
||||
|
|
9
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
9
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
|
@ -145,10 +145,6 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
|||
}
|
||||
req.Header.Set("Accept", applicationJSON)
|
||||
|
||||
for k, v := range client.AuthenticatedHeaders() {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
// Set the User-Agent header
|
||||
req.Header.Set("User-Agent", client.UserAgent.Join())
|
||||
|
||||
|
@ -162,6 +158,11 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
|
|||
}
|
||||
}
|
||||
|
||||
// get latest token from client
|
||||
for k, v := range client.AuthenticatedHeaders() {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
// Set connection parameter to close the connection immediately when we've got the response
|
||||
req.Close = true
|
||||
|
||||
|
|
1
vendor/github.com/gregjones/httpcache/README.md
generated
vendored
1
vendor/github.com/gregjones/httpcache/README.md
generated
vendored
|
@ -17,6 +17,7 @@ Cache Backends
|
|||
- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb).
|
||||
- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries.
|
||||
- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache.
|
||||
- [`github.com/birkelund/boltdbcache`](https://github.com/birkelund/boltdbcache) provides a BoltDB implementation (based on the [bbolt](https://github.com/coreos/bbolt) fork).
|
||||
|
||||
License
|
||||
-------
|
||||
|
|
192
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
192
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
|
@ -14,43 +14,62 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// The algorithm that this implementation uses does computational work
|
||||
// only when tokens are removed from the bucket, and that work completes
|
||||
// in short, bounded-constant time (Bucket.Wait benchmarks at 175ns on
|
||||
// my laptop).
|
||||
//
|
||||
// Time is measured in equal measured ticks, a given interval
|
||||
// (fillInterval) apart. On each tick a number of tokens (quantum) are
|
||||
// added to the bucket.
|
||||
//
|
||||
// When any of the methods are called the bucket updates the number of
|
||||
// tokens that are in the bucket, and it records the current tick
|
||||
// number too. Note that it doesn't record the current time - by
|
||||
// keeping things in units of whole ticks, it's easy to dish out tokens
|
||||
// at exactly the right intervals as measured from the start time.
|
||||
//
|
||||
// This allows us to calculate the number of tokens that will be
|
||||
// available at some time in the future with a few simple arithmetic
|
||||
// operations.
|
||||
//
|
||||
// The main reason for being able to transfer multiple tokens on each tick
|
||||
// is so that we can represent rates greater than 1e9 (the resolution of the Go
|
||||
// time package) tokens per second, but it's also useful because
|
||||
// it means we can easily represent situations like "a person gets
|
||||
// five tokens an hour, replenished on the hour".
|
||||
|
||||
// Bucket represents a token bucket that fills at a predetermined rate.
|
||||
// Methods on Bucket may be called concurrently.
|
||||
type Bucket struct {
|
||||
startTime time.Time
|
||||
capacity int64
|
||||
quantum int64
|
||||
fillInterval time.Duration
|
||||
clock Clock
|
||||
clock Clock
|
||||
|
||||
// The mutex guards the fields following it.
|
||||
// startTime holds the moment when the bucket was
|
||||
// first created and ticks began.
|
||||
startTime time.Time
|
||||
|
||||
// capacity holds the overall capacity of the bucket.
|
||||
capacity int64
|
||||
|
||||
// quantum holds how many tokens are added on
|
||||
// each tick.
|
||||
quantum int64
|
||||
|
||||
// fillInterval holds the interval between each tick.
|
||||
fillInterval time.Duration
|
||||
|
||||
// mu guards the fields below it.
|
||||
mu sync.Mutex
|
||||
|
||||
// avail holds the number of available tokens
|
||||
// in the bucket, as of availTick ticks from startTime.
|
||||
// availableTokens holds the number of available
|
||||
// tokens as of the associated latestTick.
|
||||
// It will be negative when there are consumers
|
||||
// waiting for tokens.
|
||||
avail int64
|
||||
availTick int64
|
||||
}
|
||||
availableTokens int64
|
||||
|
||||
// Clock is used to inject testable fakes.
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
Sleep(d time.Duration)
|
||||
}
|
||||
|
||||
// realClock implements Clock in terms of standard time functions.
|
||||
type realClock struct{}
|
||||
|
||||
// Now is identical to time.Now.
|
||||
func (realClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Sleep is identical to time.Sleep.
|
||||
func (realClock) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
// latestTick holds the latest tick for which
|
||||
// we know the number of tokens in the bucket.
|
||||
latestTick int64
|
||||
}
|
||||
|
||||
// NewBucket returns a new token bucket that fills at the
|
||||
|
@ -58,7 +77,7 @@ func (realClock) Sleep(d time.Duration) {
|
|||
// maximum capacity. Both arguments must be
|
||||
// positive. The bucket is initially full.
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket {
|
||||
return NewBucketWithClock(fillInterval, capacity, realClock{})
|
||||
return NewBucketWithClock(fillInterval, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithClock is identical to NewBucket but injects a testable clock
|
||||
|
@ -77,18 +96,22 @@ const rateMargin = 0.01
|
|||
// at high rates, the actual rate may be up to 1% different from the
|
||||
// specified rate.
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket {
|
||||
return NewBucketWithRateAndClock(rate, capacity, realClock{})
|
||||
return NewBucketWithRateAndClock(rate, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithRateAndClock is identical to NewBucketWithRate but injects a
|
||||
// testable clock interface.
|
||||
func NewBucketWithRateAndClock(rate float64, capacity int64, clock Clock) *Bucket {
|
||||
// Use the same bucket each time through the loop
|
||||
// to save allocations.
|
||||
tb := NewBucketWithQuantumAndClock(1, capacity, 1, clock)
|
||||
for quantum := int64(1); quantum < 1<<50; quantum = nextQuantum(quantum) {
|
||||
fillInterval := time.Duration(1e9 * float64(quantum) / rate)
|
||||
if fillInterval <= 0 {
|
||||
continue
|
||||
}
|
||||
tb := NewBucketWithQuantumAndClock(fillInterval, capacity, quantum, clock)
|
||||
tb.fillInterval = fillInterval
|
||||
tb.quantum = quantum
|
||||
if diff := math.Abs(tb.Rate() - rate); diff/rate <= rateMargin {
|
||||
return tb
|
||||
}
|
||||
|
@ -111,12 +134,16 @@ func nextQuantum(q int64) int64 {
|
|||
// the specification of the quantum size - quantum tokens
|
||||
// are added every fillInterval.
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket {
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, quantum, realClock{})
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, quantum, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithQuantumAndClock is identical to NewBucketWithQuantum but injects
|
||||
// a testable clock interface.
|
||||
// NewBucketWithQuantumAndClock is like NewBucketWithQuantum, but
|
||||
// also has a clock argument that allows clients to fake the passing
|
||||
// of time. If clock is nil, the system clock will be used.
|
||||
func NewBucketWithQuantumAndClock(fillInterval time.Duration, capacity, quantum int64, clock Clock) *Bucket {
|
||||
if clock == nil {
|
||||
clock = realClock{}
|
||||
}
|
||||
if fillInterval <= 0 {
|
||||
panic("token bucket fill interval is not > 0")
|
||||
}
|
||||
|
@ -127,12 +154,13 @@ func NewBucketWithQuantumAndClock(fillInterval time.Duration, capacity, quantum
|
|||
panic("token bucket quantum is not > 0")
|
||||
}
|
||||
return &Bucket{
|
||||
clock: clock,
|
||||
startTime: clock.Now(),
|
||||
capacity: capacity,
|
||||
quantum: quantum,
|
||||
avail: capacity,
|
||||
fillInterval: fillInterval,
|
||||
clock: clock,
|
||||
startTime: clock.Now(),
|
||||
latestTick: 0,
|
||||
fillInterval: fillInterval,
|
||||
capacity: capacity,
|
||||
quantum: quantum,
|
||||
availableTokens: capacity,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +194,8 @@ const infinityDuration time.Duration = 0x7fffffffffffffff
|
|||
// Note that if the request is irrevocable - there is no way to return
|
||||
// tokens to the bucket once this method commits us to taking them.
|
||||
func (tb *Bucket) Take(count int64) time.Duration {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
d, _ := tb.take(tb.clock.Now(), count, infinityDuration)
|
||||
return d
|
||||
}
|
||||
|
@ -180,6 +210,8 @@ func (tb *Bucket) Take(count int64) time.Duration {
|
|||
// wait until the tokens are actually available, and reports
|
||||
// true.
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.take(tb.clock.Now(), count, maxWait)
|
||||
}
|
||||
|
||||
|
@ -187,6 +219,8 @@ func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Dura
|
|||
// bucket. It returns the number of tokens removed, or zero if there are
|
||||
// no available tokens. It does not block.
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.takeAvailable(tb.clock.Now(), count)
|
||||
}
|
||||
|
||||
|
@ -196,17 +230,14 @@ func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {
|
|||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
|
||||
tb.adjust(now)
|
||||
if tb.avail <= 0 {
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
if tb.availableTokens <= 0 {
|
||||
return 0
|
||||
}
|
||||
if count > tb.avail {
|
||||
count = tb.avail
|
||||
if count > tb.availableTokens {
|
||||
count = tb.availableTokens
|
||||
}
|
||||
tb.avail -= count
|
||||
tb.availableTokens -= count
|
||||
return count
|
||||
}
|
||||
|
||||
|
@ -225,8 +256,8 @@ func (tb *Bucket) Available() int64 {
|
|||
func (tb *Bucket) available(now time.Time) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
tb.adjust(now)
|
||||
return tb.avail
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
return tb.availableTokens
|
||||
}
|
||||
|
||||
// Capacity returns the capacity that the bucket was created with.
|
||||
|
@ -245,40 +276,69 @@ func (tb *Bucket) take(now time.Time, count int64, maxWait time.Duration) (time.
|
|||
if count <= 0 {
|
||||
return 0, true
|
||||
}
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
|
||||
currentTick := tb.adjust(now)
|
||||
avail := tb.avail - count
|
||||
tick := tb.currentTick(now)
|
||||
tb.adjustavailableTokens(tick)
|
||||
avail := tb.availableTokens - count
|
||||
if avail >= 0 {
|
||||
tb.avail = avail
|
||||
tb.availableTokens = avail
|
||||
return 0, true
|
||||
}
|
||||
// Round up the missing tokens to the nearest multiple
|
||||
// of quantum - the tokens won't be available until
|
||||
// that tick.
|
||||
endTick := currentTick + (-avail+tb.quantum-1)/tb.quantum
|
||||
|
||||
// endTick holds the tick when all the requested tokens will
|
||||
// become available.
|
||||
endTick := tick + (-avail+tb.quantum-1)/tb.quantum
|
||||
endTime := tb.startTime.Add(time.Duration(endTick) * tb.fillInterval)
|
||||
waitTime := endTime.Sub(now)
|
||||
if waitTime > maxWait {
|
||||
return 0, false
|
||||
}
|
||||
tb.avail = avail
|
||||
tb.availableTokens = avail
|
||||
return waitTime, true
|
||||
}
|
||||
|
||||
// adjust adjusts the current bucket capacity based on the current time.
|
||||
// It returns the current tick.
|
||||
func (tb *Bucket) adjust(now time.Time) (currentTick int64) {
|
||||
currentTick = int64(now.Sub(tb.startTime) / tb.fillInterval)
|
||||
// currentTick returns the current time tick, measured
|
||||
// from tb.startTime.
|
||||
func (tb *Bucket) currentTick(now time.Time) int64 {
|
||||
return int64(now.Sub(tb.startTime) / tb.fillInterval)
|
||||
}
|
||||
|
||||
if tb.avail >= tb.capacity {
|
||||
// adjustavailableTokens adjusts the current number of tokens
|
||||
// available in the bucket at the given time, which must
|
||||
// be in the future (positive) with respect to tb.latestTick.
|
||||
func (tb *Bucket) adjustavailableTokens(tick int64) {
|
||||
if tb.availableTokens >= tb.capacity {
|
||||
return
|
||||
}
|
||||
tb.avail += (currentTick - tb.availTick) * tb.quantum
|
||||
if tb.avail > tb.capacity {
|
||||
tb.avail = tb.capacity
|
||||
tb.availableTokens += (tick - tb.latestTick) * tb.quantum
|
||||
if tb.availableTokens > tb.capacity {
|
||||
tb.availableTokens = tb.capacity
|
||||
}
|
||||
tb.availTick = currentTick
|
||||
tb.latestTick = tick
|
||||
return
|
||||
}
|
||||
|
||||
// Clock represents the passage of time in a way that
|
||||
// can be faked out for tests.
|
||||
type Clock interface {
|
||||
// Now returns the current time.
|
||||
Now() time.Time
|
||||
// Sleep sleeps for at least the given duration.
|
||||
Sleep(d time.Duration)
|
||||
}
|
||||
|
||||
// realClock implements Clock in terms of standard time functions.
|
||||
type realClock struct{}
|
||||
|
||||
// Now implements Clock.Now by calling time.Now.
|
||||
func (realClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Now implements Clock.Sleep by calling time.Sleep.
|
||||
func (realClock) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
|
9
vendor/github.com/juju/ratelimit/ratelimit_test.go
generated
vendored
9
vendor/github.com/juju/ratelimit/ratelimit_test.go
generated
vendored
|
@ -344,7 +344,7 @@ func checkRate(c *gc.C, rate float64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (rateLimitSuite) TestNewWithRate(c *gc.C) {
|
||||
func (rateLimitSuite) NewBucketWithRate(c *gc.C) {
|
||||
for rate := float64(1); rate < 1e6; rate += 7 {
|
||||
checkRate(c, rate)
|
||||
}
|
||||
|
@ -357,6 +357,7 @@ func (rateLimitSuite) TestNewWithRate(c *gc.C) {
|
|||
0.9e8,
|
||||
3e12,
|
||||
4e18,
|
||||
float64(1<<63 - 1),
|
||||
} {
|
||||
checkRate(c, rate)
|
||||
checkRate(c, rate/3)
|
||||
|
@ -387,3 +388,9 @@ func BenchmarkWait(b *testing.B) {
|
|||
tb.Wait(1)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNewBucket(b *testing.B) {
|
||||
for i := b.N - 1; i >= 0; i-- {
|
||||
NewBucketWithRate(4e18, 1<<62)
|
||||
}
|
||||
}
|
||||
|
|
1
vendor/github.com/mailru/easyjson/Makefile
generated
vendored
1
vendor/github.com/mailru/easyjson/Makefile
generated
vendored
|
@ -12,6 +12,7 @@ root: .root/src/$(PKG)
|
|||
|
||||
clean:
|
||||
rm -rf .root
|
||||
rm -rf tests/*_easyjson.go
|
||||
|
||||
build:
|
||||
go build -i -o .root/bin/easyjson $(PKG)/easyjson
|
||||
|
|
4
vendor/github.com/mailru/easyjson/jlexer/lexer.go
generated
vendored
4
vendor/github.com/mailru/easyjson/jlexer/lexer.go
generated
vendored
|
@ -904,6 +904,10 @@ func (r *Lexer) UintStr() uint {
|
|||
return uint(r.Uint64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) UintptrStr() uintptr {
|
||||
return uintptr(r.Uint64Str())
|
||||
}
|
||||
|
||||
func (r *Lexer) Int8Str() int8 {
|
||||
s, b := r.unsafeString()
|
||||
if !r.Ok() {
|
||||
|
|
7
vendor/github.com/mailru/easyjson/jwriter/writer.go
generated
vendored
7
vendor/github.com/mailru/easyjson/jwriter/writer.go
generated
vendored
|
@ -196,6 +196,13 @@ func (w *Writer) Uint64Str(n uint64) {
|
|||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) UintptrStr(n uintptr) {
|
||||
w.Buffer.EnsureSpace(20)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
}
|
||||
|
||||
func (w *Writer) Int8Str(n int8) {
|
||||
w.Buffer.EnsureSpace(4)
|
||||
w.Buffer.Buf = append(w.Buffer.Buf, '"')
|
||||
|
|
2
vendor/github.com/spf13/afero/copyOnWriteFs.go
generated
vendored
2
vendor/github.com/spf13/afero/copyOnWriteFs.go
generated
vendored
|
@ -80,7 +80,7 @@ func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
|
|||
if e, ok := err.(*os.PathError); ok {
|
||||
err = e.Err
|
||||
}
|
||||
if err == syscall.ENOENT || err == syscall.ENOTDIR {
|
||||
if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
|
||||
return u.base.Stat(name)
|
||||
}
|
||||
return nil, origErr
|
||||
|
|
16
vendor/github.com/spf13/afero/copyOnWriteFs_test.go
generated
vendored
16
vendor/github.com/spf13/afero/copyOnWriteFs_test.go
generated
vendored
|
@ -21,3 +21,19 @@ func TestCopyOnWrite(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCopyOnWriteFileInMemMapBase(t *testing.T) {
|
||||
base := &MemMapFs{}
|
||||
layer := &MemMapFs{}
|
||||
|
||||
if err := WriteFile(base, "base.txt", []byte("base"), 0755); err != nil {
|
||||
t.Fatalf("Failed to write file: %s", err)
|
||||
}
|
||||
|
||||
ufs := NewCopyOnWriteFs(base, layer)
|
||||
|
||||
_, err := ufs.Stat("base.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
|
@ -304,7 +304,7 @@ type gcmCipher struct {
|
|||
buf []byte
|
||||
}
|
||||
|
||||
func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) {
|
||||
func newGCMCipher(iv, key []byte) (packetCipher, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
21
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
21
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
|
@ -9,7 +9,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -188,10 +187,6 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
|
|||
// net.Conn underlying the the SSH connection.
|
||||
type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||
|
||||
// BannerCallback is the function type used for treat the banner sent by
|
||||
// the server. A BannerCallback receives the message sent by the remote server.
|
||||
type BannerCallback func(message string) error
|
||||
|
||||
// A ClientConfig structure is used to configure a Client. It must not be
|
||||
// modified after having been passed to an SSH function.
|
||||
type ClientConfig struct {
|
||||
|
@ -214,12 +209,6 @@ type ClientConfig struct {
|
|||
// FixedHostKey can be used for simplistic host key checks.
|
||||
HostKeyCallback HostKeyCallback
|
||||
|
||||
// BannerCallback is called during the SSH dance to display a custom
|
||||
// server's message. The client configuration can supply this callback to
|
||||
// handle it as wished. The function BannerDisplayStderr can be used for
|
||||
// simplistic display on Stderr.
|
||||
BannerCallback BannerCallback
|
||||
|
||||
// ClientVersion contains the version identification string that will
|
||||
// be used for the connection. If empty, a reasonable default is used.
|
||||
ClientVersion string
|
||||
|
@ -266,13 +255,3 @@ func FixedHostKey(key PublicKey) HostKeyCallback {
|
|||
hk := &fixedHostKey{key}
|
||||
return hk.check
|
||||
}
|
||||
|
||||
// BannerDisplayStderr returns a function that can be used for
|
||||
// ClientConfig.BannerCallback to display banners on os.Stderr.
|
||||
func BannerDisplayStderr() BannerCallback {
|
||||
return func(banner string) error {
|
||||
_, err := os.Stderr.WriteString(banner)
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
30
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
30
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
|
@ -283,9 +283,7 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
|
|||
}
|
||||
switch packet[0] {
|
||||
case msgUserAuthBanner:
|
||||
if err := handleBannerResponse(c, packet); err != nil {
|
||||
return false, err
|
||||
}
|
||||
// TODO(gpaul): add callback to present the banner to the user
|
||||
case msgUserAuthPubKeyOk:
|
||||
var msg userAuthPubKeyOkMsg
|
||||
if err := Unmarshal(packet, &msg); err != nil {
|
||||
|
@ -327,9 +325,7 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
|
|||
|
||||
switch packet[0] {
|
||||
case msgUserAuthBanner:
|
||||
if err := handleBannerResponse(c, packet); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
// TODO: add callback to present the banner to the user
|
||||
case msgUserAuthFailure:
|
||||
var msg userAuthFailureMsg
|
||||
if err := Unmarshal(packet, &msg); err != nil {
|
||||
|
@ -344,24 +340,6 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func handleBannerResponse(c packetConn, packet []byte) error {
|
||||
var msg userAuthBannerMsg
|
||||
if err := Unmarshal(packet, &msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
transport, ok := c.(*handshakeTransport)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if transport.bannerCallback != nil {
|
||||
return transport.bannerCallback(msg.Message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// KeyboardInteractiveChallenge should print questions, optionally
|
||||
// disabling echoing (e.g. for passwords), and return all the answers.
|
||||
// Challenge may be called multiple times in a single session. After
|
||||
|
@ -407,9 +385,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||
// like handleAuthResponse, but with less options.
|
||||
switch packet[0] {
|
||||
case msgUserAuthBanner:
|
||||
if err := handleBannerResponse(c, packet); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
// TODO: Print banners during userauth.
|
||||
continue
|
||||
case msgUserAuthInfoRequest:
|
||||
// OK
|
||||
|
|
37
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
37
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
|
@ -79,40 +79,3 @@ func TestHostKeyCheck(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
func TestBannerCallback(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
serverConf := &ServerConfig{
|
||||
NoClientAuth: true,
|
||||
BannerCallback: func(conn ConnMetadata) string {
|
||||
return "Hello World"
|
||||
},
|
||||
}
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
go NewServerConn(c1, serverConf)
|
||||
|
||||
var receivedBanner string
|
||||
clientConf := ClientConfig{
|
||||
User: "user",
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
BannerCallback: func(message string) error {
|
||||
receivedBanner = message
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
_, _, _, err = NewClientConn(c2, "", &clientConf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expected := "Hello World"
|
||||
if receivedBanner != expected {
|
||||
t.Fatalf("got %s; want %s", receivedBanner, expected)
|
||||
}
|
||||
}
|
||||
|
|
6
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
6
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
|
@ -78,11 +78,6 @@ type handshakeTransport struct {
|
|||
dialAddress string
|
||||
remoteAddr net.Addr
|
||||
|
||||
// bannerCallback is non-empty if we are the client and it has been set in
|
||||
// ClientConfig. In that case it is called during the user authentication
|
||||
// dance to handle a custom server's message.
|
||||
bannerCallback BannerCallback
|
||||
|
||||
// Algorithms agreed in the last key exchange.
|
||||
algorithms *algorithms
|
||||
|
||||
|
@ -125,7 +120,6 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
|||
t.dialAddress = dialAddr
|
||||
t.remoteAddr = addr
|
||||
t.hostKeyCallback = config.HostKeyCallback
|
||||
t.bannerCallback = config.BannerCallback
|
||||
if config.HostKeyAlgorithms != nil {
|
||||
t.hostKeyAlgorithms = config.HostKeyAlgorithms
|
||||
} else {
|
||||
|
|
14
vendor/golang.org/x/crypto/ssh/messages.go
generated
vendored
14
vendor/golang.org/x/crypto/ssh/messages.go
generated
vendored
|
@ -23,6 +23,10 @@ const (
|
|||
msgUnimplemented = 3
|
||||
msgDebug = 4
|
||||
msgNewKeys = 21
|
||||
|
||||
// Standard authentication messages
|
||||
msgUserAuthSuccess = 52
|
||||
msgUserAuthBanner = 53
|
||||
)
|
||||
|
||||
// SSH messages:
|
||||
|
@ -133,16 +137,6 @@ type userAuthFailureMsg struct {
|
|||
PartialSuccess bool
|
||||
}
|
||||
|
||||
// See RFC 4252, section 5.1
|
||||
const msgUserAuthSuccess = 52
|
||||
|
||||
// See RFC 4252, section 5.4
|
||||
const msgUserAuthBanner = 53
|
||||
|
||||
type userAuthBannerMsg struct {
|
||||
Message string `sshtype:"53"`
|
||||
}
|
||||
|
||||
// See RFC 4256, section 3.2
|
||||
const msgUserAuthInfoRequest = 60
|
||||
const msgUserAuthInfoResponse = 61
|
||||
|
|
17
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
17
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
|
@ -95,10 +95,6 @@ type ServerConfig struct {
|
|||
// Note that RFC 4253 section 4.2 requires that this string start with
|
||||
// "SSH-2.0-".
|
||||
ServerVersion string
|
||||
|
||||
// BannerCallback, if present, is called and the return string is sent to
|
||||
// the client after key exchange completed but before authentication.
|
||||
BannerCallback func(conn ConnMetadata) string
|
||||
}
|
||||
|
||||
// AddHostKey adds a private key as a host key. If an existing host
|
||||
|
@ -347,19 +343,6 @@ userAuthLoop:
|
|||
}
|
||||
|
||||
s.user = userAuthReq.User
|
||||
|
||||
if authFailures == 0 && config.BannerCallback != nil {
|
||||
msg := config.BannerCallback(s)
|
||||
if msg != "" {
|
||||
bannerMsg := &userAuthBannerMsg{
|
||||
Message: msg,
|
||||
}
|
||||
if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
perms = nil
|
||||
authErr := errors.New("no auth passed yet")
|
||||
|
||||
|
|
69
vendor/golang.org/x/crypto/ssh/terminal/util.go
generated
vendored
69
vendor/golang.org/x/crypto/ssh/terminal/util.go
generated
vendored
|
@ -17,44 +17,41 @@
|
|||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// State contains the state of a terminal.
|
||||
type State struct {
|
||||
termios syscall.Termios
|
||||
termios unix.Termios
|
||||
}
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(fd int) bool {
|
||||
var termios syscall.Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||
// mode and returns the previous state of the terminal so that it can be
|
||||
// restored.
|
||||
func MakeRaw(fd int) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
||||
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState.termios
|
||||
oldState := State{termios: *termios}
|
||||
|
||||
// This attempts to replicate the behaviour documented for cfmakeraw in
|
||||
// the termios(3) manpage.
|
||||
newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
||||
newState.Oflag &^= syscall.OPOST
|
||||
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
||||
newState.Cflag &^= syscall.CSIZE | syscall.PARENB
|
||||
newState.Cflag |= syscall.CS8
|
||||
newState.Cc[unix.VMIN] = 1
|
||||
newState.Cc[unix.VTIME] = 0
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
||||
termios.Oflag &^= unix.OPOST
|
||||
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
||||
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
||||
termios.Cflag |= unix.CS8
|
||||
termios.Cc[unix.VMIN] = 1
|
||||
termios.Cc[unix.VTIME] = 0
|
||||
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -64,59 +61,55 @@ func MakeRaw(fd int) (*State, error) {
|
|||
// GetState returns the current state of a terminal which may be useful to
|
||||
// restore the terminal after a signal.
|
||||
func GetState(fd int) (*State, error) {
|
||||
var oldState State
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
||||
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oldState, nil
|
||||
return &State{termios: *termios}, nil
|
||||
}
|
||||
|
||||
// Restore restores the terminal connected to the given file descriptor to a
|
||||
// previous state.
|
||||
func Restore(fd int, state *State) error {
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
|
||||
}
|
||||
|
||||
// GetSize returns the dimensions of the given terminal.
|
||||
func GetSize(fd int) (width, height int, err error) {
|
||||
var dimensions [4]uint16
|
||||
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
|
||||
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
return int(dimensions[1]), int(dimensions[0]), nil
|
||||
return int(ws.Col), int(ws.Row), nil
|
||||
}
|
||||
|
||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
||||
type passwordReader int
|
||||
|
||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||
return syscall.Read(int(r), buf)
|
||||
return unix.Read(int(r), buf)
|
||||
}
|
||||
|
||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||
// returned does not include the \n.
|
||||
func ReadPassword(fd int) ([]byte, error) {
|
||||
var oldState syscall.Termios
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
|
||||
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newState := oldState
|
||||
newState.Lflag &^= syscall.ECHO
|
||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
||||
newState.Iflag |= syscall.ICRNL
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
newState := *termios
|
||||
newState.Lflag &^= unix.ECHO
|
||||
newState.Lflag |= unix.ICANON | unix.ISIG
|
||||
newState.Iflag |= unix.ICRNL
|
||||
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
|
||||
unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
|
||||
}()
|
||||
|
||||
return readPasswordLine(passwordReader(fd))
|
||||
|
|
2
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
|
@ -254,7 +254,7 @@ func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (pac
|
|||
iv, key, macKey := generateKeys(d, algs, kex)
|
||||
|
||||
if algs.Cipher == gcmCipherID {
|
||||
return newGCMCipher(iv, key, macKey)
|
||||
return newGCMCipher(iv, key)
|
||||
}
|
||||
|
||||
if algs.Cipher == aes128cbcID {
|
||||
|
|
2
vendor/golang.org/x/net/context/context.go
generated
vendored
2
vendor/golang.org/x/net/context/context.go
generated
vendored
|
@ -5,6 +5,8 @@
|
|||
// Package context defines the Context type, which carries deadlines,
|
||||
// cancelation signals, and other request-scoped values across API boundaries
|
||||
// and between processes.
|
||||
// As of Go 1.7 this package is available in the standard library under the
|
||||
// name context. https://golang.org/pkg/context.
|
||||
//
|
||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
||||
// servers should accept a Context. The chain of function calls between must
|
||||
|
|
11
vendor/golang.org/x/net/http2/server.go
generated
vendored
11
vendor/golang.org/x/net/http2/server.go
generated
vendored
|
@ -220,12 +220,15 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
|||
} else if s.TLSConfig.CipherSuites != nil {
|
||||
// If they already provided a CipherSuite list, return
|
||||
// an error if it has a bad order or is missing
|
||||
// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
|
||||
const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||
// ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
|
||||
haveRequired := false
|
||||
sawBad := false
|
||||
for i, cs := range s.TLSConfig.CipherSuites {
|
||||
if cs == requiredCipher {
|
||||
switch cs {
|
||||
case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
// Alternative MTI cipher to not discourage ECDSA-only servers.
|
||||
// See http://golang.org/cl/30721 for further information.
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||
haveRequired = true
|
||||
}
|
||||
if isBadCipher(cs) {
|
||||
|
@ -235,7 +238,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
|
|||
}
|
||||
}
|
||||
if !haveRequired {
|
||||
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
|
||||
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
8
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
8
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
|
@ -3189,12 +3189,18 @@ func TestConfigureServer(t *testing.T) {
|
|||
CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "just the alternative required cipher suite",
|
||||
tlsConfig: &tls.Config{
|
||||
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing required cipher suite",
|
||||
tlsConfig: &tls.Config{
|
||||
CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
|
||||
},
|
||||
wantErr: "is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
wantErr: "is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.",
|
||||
},
|
||||
{
|
||||
name: "required after bad",
|
||||
|
|
75
vendor/golang.org/x/net/http2/transport.go
generated
vendored
75
vendor/golang.org/x/net/http2/transport.go
generated
vendored
|
@ -274,6 +274,13 @@ func (cs *clientStream) checkResetOrDone() error {
|
|||
}
|
||||
}
|
||||
|
||||
func (cs *clientStream) getStartedWrite() bool {
|
||||
cc := cs.cc
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
return cs.startedWrite
|
||||
}
|
||||
|
||||
func (cs *clientStream) abortRequestBodyWrite(err error) {
|
||||
if err == nil {
|
||||
panic("nil error")
|
||||
|
@ -349,14 +356,9 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
|||
return nil, err
|
||||
}
|
||||
traceGotConn(req, cc)
|
||||
res, err := cc.RoundTrip(req)
|
||||
res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
|
||||
if err != nil && retry <= 6 {
|
||||
afterBodyWrite := false
|
||||
if e, ok := err.(afterReqBodyWriteError); ok {
|
||||
err = e
|
||||
afterBodyWrite = true
|
||||
}
|
||||
if req, err = shouldRetryRequest(req, err, afterBodyWrite); err == nil {
|
||||
if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
|
||||
// After the first retry, do exponential backoff with 10% jitter.
|
||||
if retry == 0 {
|
||||
continue
|
||||
|
@ -394,16 +396,6 @@ var (
|
|||
errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
|
||||
)
|
||||
|
||||
// afterReqBodyWriteError is a wrapper around errors returned by ClientConn.RoundTrip.
|
||||
// It is used to signal that err happened after part of Request.Body was sent to the server.
|
||||
type afterReqBodyWriteError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e afterReqBodyWriteError) Error() string {
|
||||
return e.err.Error() + "; some request body already written"
|
||||
}
|
||||
|
||||
// shouldRetryRequest is called by RoundTrip when a request fails to get
|
||||
// response headers. It is always called with a non-nil error.
|
||||
// It returns either a request to retry (either the same request, or a
|
||||
|
@ -752,8 +744,13 @@ func actualContentLength(req *http.Request) int64 {
|
|||
}
|
||||
|
||||
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
resp, _, err := cc.roundTrip(req)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
|
||||
if err := checkConnHeaders(req); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
if cc.idleTimer != nil {
|
||||
cc.idleTimer.Stop()
|
||||
|
@ -761,14 +758,14 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
|
||||
trailers, err := commaSeparatedTrailers(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
hasTrailers := trailers != ""
|
||||
|
||||
cc.mu.Lock()
|
||||
if err := cc.awaitOpenSlotForRequest(req); err != nil {
|
||||
cc.mu.Unlock()
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
body := req.Body
|
||||
|
@ -802,7 +799,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
|
||||
if err != nil {
|
||||
cc.mu.Unlock()
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
cs := cc.newStream()
|
||||
|
@ -828,7 +825,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
// Don't bother sending a RST_STREAM (our write already failed;
|
||||
// no need to keep writing)
|
||||
traceWroteRequest(cs.trace, werr)
|
||||
return nil, werr
|
||||
return nil, false, werr
|
||||
}
|
||||
|
||||
var respHeaderTimer <-chan time.Time
|
||||
|
@ -847,7 +844,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
bodyWritten := false
|
||||
ctx := reqContext(req)
|
||||
|
||||
handleReadLoopResponse := func(re resAndError) (*http.Response, error) {
|
||||
handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
|
||||
res := re.res
|
||||
if re.err != nil || res.StatusCode > 299 {
|
||||
// On error or status code 3xx, 4xx, 5xx, etc abort any
|
||||
|
@ -863,18 +860,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
cs.abortRequestBodyWrite(errStopReqBodyWrite)
|
||||
}
|
||||
if re.err != nil {
|
||||
cc.mu.Lock()
|
||||
afterBodyWrite := cs.startedWrite
|
||||
cc.mu.Unlock()
|
||||
cc.forgetStreamID(cs.ID)
|
||||
if afterBodyWrite {
|
||||
return nil, afterReqBodyWriteError{re.err}
|
||||
}
|
||||
return nil, re.err
|
||||
return nil, cs.getStartedWrite(), re.err
|
||||
}
|
||||
res.Request = req
|
||||
res.TLS = cc.tlsState
|
||||
return res, nil
|
||||
return res, false, nil
|
||||
}
|
||||
|
||||
for {
|
||||
|
@ -889,7 +880,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, errTimeout
|
||||
return nil, cs.getStartedWrite(), errTimeout
|
||||
case <-ctx.Done():
|
||||
if !hasBody || bodyWritten {
|
||||
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||
|
@ -898,7 +889,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, ctx.Err()
|
||||
return nil, cs.getStartedWrite(), ctx.Err()
|
||||
case <-req.Cancel:
|
||||
if !hasBody || bodyWritten {
|
||||
cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
|
||||
|
@ -907,12 +898,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, errRequestCanceled
|
||||
return nil, cs.getStartedWrite(), errRequestCanceled
|
||||
case <-cs.peerReset:
|
||||
// processResetStream already removed the
|
||||
// stream from the streams map; no need for
|
||||
// forgetStreamID.
|
||||
return nil, cs.resetErr
|
||||
return nil, cs.getStartedWrite(), cs.resetErr
|
||||
case err := <-bodyWriter.resc:
|
||||
// Prefer the read loop's response, if available. Issue 16102.
|
||||
select {
|
||||
|
@ -921,7 +912,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
default:
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, cs.getStartedWrite(), err
|
||||
}
|
||||
bodyWritten = true
|
||||
if d := cc.responseHeaderTimeout(); d != 0 {
|
||||
|
@ -1851,6 +1842,14 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||
return nil
|
||||
}
|
||||
if f.Length > 0 {
|
||||
if cs.req.Method == "HEAD" && len(data) > 0 {
|
||||
cc.logf("protocol error: received DATA on a HEAD request")
|
||||
rl.endStreamError(cs, StreamError{
|
||||
StreamID: f.StreamID,
|
||||
Code: ErrCodeProtocol,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
// Check connection-level flow control.
|
||||
cc.mu.Lock()
|
||||
if cs.inflow.available() >= int32(f.Length) {
|
||||
|
@ -1912,11 +1911,11 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
|
|||
err = io.EOF
|
||||
code = cs.copyTrailers
|
||||
}
|
||||
cs.bufPipe.closeWithErrorAndCode(err, code)
|
||||
delete(rl.activeRes, cs.ID)
|
||||
if isConnectionCloseRequest(cs.req) {
|
||||
rl.closeWhenIdle = true
|
||||
}
|
||||
cs.bufPipe.closeWithErrorAndCode(err, code)
|
||||
delete(rl.activeRes, cs.ID)
|
||||
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
|
|
82
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
82
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
|
@ -2290,6 +2290,60 @@ func TestTransportReadHeadResponse(t *testing.T) {
|
|||
ct.run()
|
||||
}
|
||||
|
||||
func TestTransportReadHeadResponseWithBody(t *testing.T) {
|
||||
response := "redirecting to /elsewhere"
|
||||
ct := newClientTester(t)
|
||||
clientDone := make(chan struct{})
|
||||
ct.client = func() error {
|
||||
defer close(clientDone)
|
||||
req, _ := http.NewRequest("HEAD", "https://dummy.tld/", nil)
|
||||
res, err := ct.tr.RoundTrip(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.ContentLength != int64(len(response)) {
|
||||
return fmt.Errorf("Content-Length = %d; want %d", res.ContentLength, len(response))
|
||||
}
|
||||
slurp, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ReadAll: %v", err)
|
||||
}
|
||||
if len(slurp) > 0 {
|
||||
return fmt.Errorf("Unexpected non-empty ReadAll body: %q", slurp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
ct.server = func() error {
|
||||
ct.greet()
|
||||
for {
|
||||
f, err := ct.fr.ReadFrame()
|
||||
if err != nil {
|
||||
t.Logf("ReadFrame: %v", err)
|
||||
return nil
|
||||
}
|
||||
hf, ok := f.(*HeadersFrame)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
enc := hpack.NewEncoder(&buf)
|
||||
enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"})
|
||||
enc.WriteField(hpack.HeaderField{Name: "content-length", Value: strconv.Itoa(len(response))})
|
||||
ct.fr.WriteHeaders(HeadersFrameParam{
|
||||
StreamID: hf.StreamID,
|
||||
EndHeaders: true,
|
||||
EndStream: false,
|
||||
BlockFragment: buf.Bytes(),
|
||||
})
|
||||
ct.fr.WriteData(hf.StreamID, true, []byte(response))
|
||||
|
||||
<-clientDone
|
||||
return nil
|
||||
}
|
||||
}
|
||||
ct.run()
|
||||
}
|
||||
|
||||
type neverEnding byte
|
||||
|
||||
func (b neverEnding) Read(p []byte) (int, error) {
|
||||
|
@ -3043,6 +3097,34 @@ func TestTransportCancelDataResponseRace(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Issue 21316: It should be safe to reuse an http.Request after the
|
||||
// request has completed.
|
||||
func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) {
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
io.WriteString(w, "body")
|
||||
}, optOnlyServer)
|
||||
defer st.Close()
|
||||
|
||||
tr := &Transport{TLSClientConfig: tlsConfigInsecure}
|
||||
defer tr.CloseIdleConnections()
|
||||
|
||||
req, _ := http.NewRequest("GET", st.ts.URL, nil)
|
||||
resp, err := tr.RoundTrip(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = io.Copy(ioutil.Discard, resp.Body); err != nil {
|
||||
t.Fatalf("error reading response body: %v", err)
|
||||
}
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
t.Fatalf("error closing response body: %v", err)
|
||||
}
|
||||
|
||||
// This access of req.Header should not race with code in the transport.
|
||||
req.Header = http.Header{}
|
||||
}
|
||||
|
||||
func TestTransportRetryAfterGOAWAY(t *testing.T) {
|
||||
var dialer struct {
|
||||
sync.Mutex
|
||||
|
|
124
vendor/golang.org/x/net/idna/idna.go
generated
vendored
124
vendor/golang.org/x/net/idna/idna.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
|||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
"golang.org/x/text/unicode/bidi"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
|
@ -68,7 +69,7 @@ func VerifyDNSLength(verify bool) Option {
|
|||
}
|
||||
|
||||
// RemoveLeadingDots removes leading label separators. Leading runes that map to
|
||||
// dots, such as U+3002, are removed as well.
|
||||
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
|
||||
//
|
||||
// This is the behavior suggested by the UTS #46 and is adopted by some
|
||||
// browsers.
|
||||
|
@ -92,7 +93,7 @@ func ValidateLabels(enable bool) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// StrictDomainName limits the set of permissable ASCII characters to those
|
||||
// StrictDomainName limits the set of permissible ASCII characters to those
|
||||
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
||||
//
|
||||
|
@ -142,7 +143,6 @@ func MapForLookup() Option {
|
|||
o.mapping = validateAndMap
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
RemoveLeadingDots(true)(o)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ type options struct {
|
|||
|
||||
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||
mapping func(p *Profile, s string) (string, error)
|
||||
mapping func(p *Profile, s string) (mapped string, isBidi bool, err error)
|
||||
|
||||
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||
// defined in RFC 5893.
|
||||
|
@ -251,23 +251,21 @@ var (
|
|||
|
||||
punycode = &Profile{}
|
||||
lookup = &Profile{options{
|
||||
transitional: true,
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
removeLeadingDots: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
transitional: true,
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
display = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
removeLeadingDots: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
registration = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
|
@ -302,14 +300,16 @@ func (e runeError) Error() string {
|
|||
// see http://www.unicode.org/reports/tr46.
|
||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
var err error
|
||||
var isBidi bool
|
||||
if p.mapping != nil {
|
||||
s, err = p.mapping(p, s)
|
||||
s, isBidi, err = p.mapping(p, s)
|
||||
}
|
||||
// Remove leading empty labels.
|
||||
if p.removeLeadingDots {
|
||||
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||
}
|
||||
}
|
||||
// TODO: allow for a quick check of the tables data.
|
||||
// It seems like we should only create this error on ToASCII, but the
|
||||
// UTS 46 conformance tests suggests we should always check this.
|
||||
if err == nil && p.verifyDNSLength && s == "" {
|
||||
|
@ -335,6 +335,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
|||
// Spec says keep the old label.
|
||||
continue
|
||||
}
|
||||
isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
|
||||
labels.set(u)
|
||||
if err == nil && p.validateLabels {
|
||||
err = p.fromPuny(p, u)
|
||||
|
@ -349,6 +350,14 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
|||
err = p.validateLabel(label)
|
||||
}
|
||||
}
|
||||
if isBidi && p.bidirule != nil && err == nil {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
if !p.bidirule(labels.label()) {
|
||||
err = &labelError{s, "B"}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if toASCII {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
|
@ -380,16 +389,26 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
|
|||
return s, err
|
||||
}
|
||||
|
||||
func normalize(p *Profile, s string) (string, error) {
|
||||
return norm.NFC.String(s), nil
|
||||
func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
|
||||
// TODO: consider first doing a quick check to see if any of these checks
|
||||
// need to be done. This will make it slower in the general case, but
|
||||
// faster in the common case.
|
||||
mapped = norm.NFC.String(s)
|
||||
isBidi = bidirule.DirectionString(mapped) == bidi.RightToLeft
|
||||
return mapped, isBidi, nil
|
||||
}
|
||||
|
||||
func validateRegistration(p *Profile, s string) (string, error) {
|
||||
func validateRegistration(p *Profile, s string) (idem string, bidi bool, err error) {
|
||||
// TODO: filter need for normalization in loop below.
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return s, &labelError{s, "V1"}
|
||||
return s, false, &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return s, bidi, runeError(utf8.RuneError)
|
||||
}
|
||||
bidi = bidi || info(v).isBidi(s[i:])
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||
|
@ -397,21 +416,50 @@ func validateRegistration(p *Profile, s string) (string, error) {
|
|||
case valid, deviation:
|
||||
case disallowed, mapped, unknown, ignored:
|
||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||
return s, runeError(r)
|
||||
return s, bidi, runeError(r)
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return s, nil
|
||||
return s, bidi, nil
|
||||
}
|
||||
|
||||
func validateAndMap(p *Profile, s string) (string, error) {
|
||||
func (c info) isBidi(s string) bool {
|
||||
if !c.isMapped() {
|
||||
return c&attributesMask == rtl
|
||||
}
|
||||
// TODO: also store bidi info for mapped data. This is possible, but a bit
|
||||
// cumbersome and not for the common case.
|
||||
p, _ := bidi.LookupString(s)
|
||||
switch p.Class() {
|
||||
case bidi.R, bidi.AL, bidi.AN:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
|
||||
var (
|
||||
err error
|
||||
b []byte
|
||||
k int
|
||||
b []byte
|
||||
k int
|
||||
)
|
||||
// combinedInfoBits contains the or-ed bits of all runes. We use this
|
||||
// to derive the mayNeedNorm bit later. This may trigger normalization
|
||||
// overeagerly, but it will not do so in the common case. The end result
|
||||
// is another 10% saving on BenchmarkProfile for the common case.
|
||||
var combinedInfoBits info
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
b = append(b, s[k:i]...)
|
||||
b = append(b, "\ufffd"...)
|
||||
k = len(s)
|
||||
if err == nil {
|
||||
err = runeError(utf8.RuneError)
|
||||
}
|
||||
break
|
||||
}
|
||||
combinedInfoBits |= info(v)
|
||||
bidi = bidi || info(v).isBidi(s[i:])
|
||||
start := i
|
||||
i += sz
|
||||
// Copy bytes not copied so far.
|
||||
|
@ -438,7 +486,9 @@ func validateAndMap(p *Profile, s string) (string, error) {
|
|||
}
|
||||
if k == 0 {
|
||||
// No changes so far.
|
||||
s = norm.NFC.String(s)
|
||||
if combinedInfoBits&mayNeedNorm != 0 {
|
||||
s = norm.NFC.String(s)
|
||||
}
|
||||
} else {
|
||||
b = append(b, s[k:]...)
|
||||
if norm.NFC.QuickSpan(b) != len(b) {
|
||||
|
@ -447,7 +497,7 @@ func validateAndMap(p *Profile, s string) (string, error) {
|
|||
// TODO: the punycode converters require strings as input.
|
||||
s = string(b)
|
||||
}
|
||||
return s, err
|
||||
return s, bidi, err
|
||||
}
|
||||
|
||||
// A labelIter allows iterating over domain name labels.
|
||||
|
@ -542,8 +592,13 @@ func validateFromPunycode(p *Profile, s string) error {
|
|||
if !norm.NFC.IsNormalString(s) {
|
||||
return &labelError{s, "V1"}
|
||||
}
|
||||
// TODO: detect whether string may have to be normalized in the following
|
||||
// loop.
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return runeError(utf8.RuneError)
|
||||
}
|
||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||
return &labelError{s, "V6"}
|
||||
}
|
||||
|
@ -616,16 +671,13 @@ var joinStates = [][numJoinTypes]joinState{
|
|||
|
||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||
// already implicitly satisfied by the overall implementation.
|
||||
func (p *Profile) validateLabel(s string) error {
|
||||
func (p *Profile) validateLabel(s string) (err error) {
|
||||
if s == "" {
|
||||
if p.verifyDNSLength {
|
||||
return &labelError{s, "A4"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if p.bidirule != nil && !p.bidirule(s) {
|
||||
return &labelError{s, "B"}
|
||||
}
|
||||
if !p.validateLabels {
|
||||
return nil
|
||||
}
|
||||
|
|
4396
vendor/golang.org/x/net/idna/tables.go
generated
vendored
4396
vendor/golang.org/x/net/idna/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
17
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
17
vendor/golang.org/x/net/idna/trieval.go
generated
vendored
|
@ -26,9 +26,9 @@ package idna
|
|||
// 15..3 index into xor or mapping table
|
||||
// }
|
||||
// } else {
|
||||
// 15..13 unused
|
||||
// 12 modifier (including virama)
|
||||
// 11 virama modifier
|
||||
// 15..14 unused
|
||||
// 13 mayNeedNorm
|
||||
// 12..11 attributes
|
||||
// 10..8 joining type
|
||||
// 7..3 category type
|
||||
// }
|
||||
|
@ -49,15 +49,20 @@ const (
|
|||
joinShift = 8
|
||||
joinMask = 0x07
|
||||
|
||||
viramaModifier = 0x0800
|
||||
// Attributes
|
||||
attributesMask = 0x1800
|
||||
viramaModifier = 0x1800
|
||||
modifier = 0x1000
|
||||
rtl = 0x0800
|
||||
|
||||
mayNeedNorm = 0x2000
|
||||
)
|
||||
|
||||
// A category corresponds to a category defined in the IDNA mapping table.
|
||||
type category uint16
|
||||
|
||||
const (
|
||||
unknown category = 0 // not defined currently in unicode.
|
||||
unknown category = 0 // not currently defined in unicode.
|
||||
mapped category = 1
|
||||
disallowedSTD3Mapped category = 2
|
||||
deviation category = 3
|
||||
|
@ -110,5 +115,5 @@ func (c info) isModifier() bool {
|
|||
}
|
||||
|
||||
func (c info) isViramaModifier() bool {
|
||||
return c&(viramaModifier|catSmallMask) == viramaModifier
|
||||
return c&(attributesMask|catSmallMask) == viramaModifier
|
||||
}
|
||||
|
|
2
vendor/golang.org/x/oauth2/internal/token.go
generated
vendored
2
vendor/golang.org/x/oauth2/internal/token.go
generated
vendored
|
@ -20,7 +20,7 @@ import (
|
|||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
// Token represents the crendentials used to authorize
|
||||
// Token represents the credentials used to authorize
|
||||
// the requests to access protected resources on the OAuth 2.0
|
||||
// provider's backend.
|
||||
//
|
||||
|
|
2
vendor/golang.org/x/oauth2/token.go
generated
vendored
2
vendor/golang.org/x/oauth2/token.go
generated
vendored
|
@ -20,7 +20,7 @@ import (
|
|||
// expirations due to client-server time mismatches.
|
||||
const expiryDelta = 10 * time.Second
|
||||
|
||||
// Token represents the crendentials used to authorize
|
||||
// Token represents the credentials used to authorize
|
||||
// the requests to access protected resources on the OAuth 2.0
|
||||
// provider's backend.
|
||||
//
|
||||
|
|
2
vendor/golang.org/x/sys/unix/creds_test.go
generated
vendored
2
vendor/golang.org/x/sys/unix/creds_test.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
2
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/env_unset.go
generated
vendored
2
vendor/golang.org/x/sys/unix/env_unset.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/export_test.go
generated
vendored
2
vendor/golang.org/x/sys/unix/export_test.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
27
vendor/golang.org/x/sys/unix/file_unix.go
generated
vendored
27
vendor/golang.org/x/sys/unix/file_unix.go
generated
vendored
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// FIXME: unexported function from os
|
||||
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
|
||||
func syscallMode(i os.FileMode) (o uint32) {
|
||||
o |= uint32(i.Perm())
|
||||
if i&os.ModeSetuid != 0 {
|
||||
o |= syscall.S_ISUID
|
||||
}
|
||||
if i&os.ModeSetgid != 0 {
|
||||
o |= syscall.S_ISGID
|
||||
}
|
||||
if i&os.ModeSticky != 0 {
|
||||
o |= syscall.S_ISVTX
|
||||
}
|
||||
// No mapping for Go's ModeTemporary (plan9 only).
|
||||
return
|
||||
}
|
4
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
4
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -8,7 +8,7 @@ package unix
|
|||
|
||||
import "syscall"
|
||||
|
||||
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
||||
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
||||
// much of the functionality can be written directly in Go.
|
||||
|
||||
//extern gccgoRealSyscall
|
||||
|
|
2
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
2
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
8
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
8
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
|
@ -38,6 +38,8 @@ includes_Darwin='
|
|||
#define _DARWIN_C_SOURCE
|
||||
#define KERNEL
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#include <stdint.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/ptrace.h>
|
||||
|
@ -184,6 +186,7 @@ struct ltchars {
|
|||
#include <linux/vm_sockets.h>
|
||||
#include <linux/taskstats.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <net/route.h>
|
||||
#include <asm/termbits.h>
|
||||
|
||||
|
@ -418,9 +421,14 @@ ccflags="$@"
|
|||
$2 ~ /^SECCOMP_MODE_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^(VM|VMADDR)_/ ||
|
||||
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
|
||||
$2 ~ /^(TASKSTATS|TS)_/ ||
|
||||
$2 ~ /^GENL_/ ||
|
||||
$2 ~ /^UTIME_/ ||
|
||||
$2 ~ /^XATTR_(CREATE|REPLACE)/ ||
|
||||
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
|
||||
$2 ~ /^FSOPT_/ ||
|
||||
$2 ~ /^WDIOC_/ ||
|
||||
$2 !~ "WMESGLEN" &&
|
||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||
|
|
5
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
5
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
|
@ -56,6 +56,11 @@ func main() {
|
|||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
||||
// conversion to string; see golang.org/issue/20753
|
||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
||||
|
||||
// We refuse to export private fields on s390x
|
||||
if goarch == "s390x" && goos == "linux" {
|
||||
// Remove cgo padding fields
|
||||
|
|
2
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
2
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/race.go
generated
vendored
2
vendor/golang.org/x/sys/unix/race.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
2
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
2
vendor/golang.org/x/sys/unix/sockcmsg_linux.go
generated
vendored
2
vendor/golang.org/x/sys/unix/sockcmsg_linux.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
24
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
24
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
|
@ -5,10 +5,10 @@
|
|||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
// Package unix contains an interface to the low-level operating system
|
||||
// primitives. OS details vary depending on the underlying system, and
|
||||
// primitives. OS details vary depending on the underlying system, and
|
||||
// by default, godoc will display OS-specific documentation for the current
|
||||
// system. If you want godoc to display OS documentation for another
|
||||
// system, set $GOOS and $GOARCH to the desired system. For example, if
|
||||
// system. If you want godoc to display OS documentation for another
|
||||
// system, set $GOOS and $GOARCH to the desired system. For example, if
|
||||
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
|
||||
// to freebsd and $GOARCH to arm.
|
||||
// The primary use of this package is inside other packages that provide a more
|
||||
|
@ -49,21 +49,3 @@ func BytePtrFromString(s string) (*byte, error) {
|
|||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||
// See mkunix.pl.
|
||||
var _zero uintptr
|
||||
|
||||
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||
return int64(ts.Sec), int64(ts.Nsec)
|
||||
}
|
||||
|
||||
func (tv *Timeval) Unix() (sec int64, nsec int64) {
|
||||
return int64(tv.Sec), int64(tv.Usec) * 1000
|
||||
}
|
||||
|
||||
func (ts *Timespec) Nano() int64 {
|
||||
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
|
||||
}
|
||||
|
||||
func (tv *Timeval) Nano() int64 {
|
||||
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
|
||||
}
|
||||
|
||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||
|
|
22
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
22
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
|
@ -34,7 +34,7 @@ func Getgroups() (gids []int, err error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Sanity check group count. Max is 16 on BSD.
|
||||
// Sanity check group count. Max is 16 on BSD.
|
||||
if n < 0 || n > 1000 {
|
||||
return nil, EINVAL
|
||||
}
|
||||
|
@ -570,7 +570,12 @@ func UtimesNano(path string, ts []Timespec) error {
|
|||
if len(ts) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
// Darwin setattrlist can set nanosecond timestamps
|
||||
err := setattrlistTimes(path, ts, 0)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
|
@ -590,6 +595,10 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
|
|||
if len(ts) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
err := setattrlistTimes(path, ts, flags)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
|
||||
}
|
||||
|
||||
|
@ -607,6 +616,15 @@ func Futimes(fd int, tv []Timeval) error {
|
|||
|
||||
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
// TODO: wrap
|
||||
// Acct(name nil-string) (err error)
|
||||
// Gethostuuid(uuid *byte, timeout *Timespec) (err error)
|
||||
|
|
34
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
34
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
|
@ -54,7 +54,7 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
|
||||
// NOTE(rsc): It seems strange to set the buffer to have
|
||||
// size CTL_MAXNAME+2 but use only CTL_MAXNAME
|
||||
// as the size. I don't know why the +2 is here, but the
|
||||
// as the size. I don't know why the +2 is here, but the
|
||||
// kernel uses +2 for its own implementation of this function.
|
||||
// I am scared that if we don't include the +2 here, the kernel
|
||||
// will silently write 2 words farther than we specify
|
||||
|
@ -187,6 +187,37 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||
_p0, err := BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var attrList attrList
|
||||
attrList.bitmapCount = ATTR_BIT_MAP_COUNT
|
||||
attrList.CommonAttr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME
|
||||
|
||||
// order is mtime, atime: the opposite of Chtimes
|
||||
attributes := [2]Timespec{times[1], times[0]}
|
||||
options := 0
|
||||
if flags&AT_SYMLINK_NOFOLLOW != 0 {
|
||||
options |= FSOPT_NOFOLLOW
|
||||
}
|
||||
_, _, e1 := Syscall6(
|
||||
SYS_SETATTRLIST,
|
||||
uintptr(unsafe.Pointer(_p0)),
|
||||
uintptr(unsafe.Pointer(&attrList)),
|
||||
uintptr(unsafe.Pointer(&attributes)),
|
||||
uintptr(unsafe.Sizeof(attributes)),
|
||||
uintptr(options),
|
||||
0,
|
||||
)
|
||||
if e1 != 0 {
|
||||
return e1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
|
||||
// Darwin doesn't support SYS_UTIMENSAT
|
||||
return ENOSYS
|
||||
|
@ -377,7 +408,6 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|||
// Searchfs
|
||||
// Delete
|
||||
// Copyfile
|
||||
// Poll
|
||||
// Watchevent
|
||||
// Waitevent
|
||||
// Modwatch
|
||||
|
|
17
vendor/golang.org/x/sys/unix/syscall_darwin_386.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_darwin_386.go
generated
vendored
|
@ -11,25 +11,18 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = int32(nsec / 1e9)
|
||||
ts.Nsec = int32(nsec % 1e9)
|
||||
return
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
tv.Sec = int32(nsec / 1e9)
|
||||
return
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: int32(sec), Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
// The tv passed to gettimeofday must be non-nil
|
||||
// but is otherwise unused. The answers come back
|
||||
// but is otherwise unused. The answers come back
|
||||
// in the two registers.
|
||||
sec, usec, err := gettimeofday(tv)
|
||||
tv.Sec = int32(sec)
|
||||
|
|
17
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
generated
vendored
|
@ -11,25 +11,18 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = nsec / 1e9
|
||||
ts.Nsec = nsec % 1e9
|
||||
return
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
tv.Sec = int64(nsec / 1e9)
|
||||
return
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
// The tv passed to gettimeofday must be non-nil
|
||||
// but is otherwise unused. The answers come back
|
||||
// but is otherwise unused. The answers come back
|
||||
// in the two registers.
|
||||
sec, usec, err := gettimeofday(tv)
|
||||
tv.Sec = sec
|
||||
|
|
17
vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
generated
vendored
|
@ -9,25 +9,18 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = int32(nsec / 1e9)
|
||||
ts.Nsec = int32(nsec % 1e9)
|
||||
return
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
tv.Sec = int32(nsec / 1e9)
|
||||
return
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: int32(sec), Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
// The tv passed to gettimeofday must be non-nil
|
||||
// but is otherwise unused. The answers come back
|
||||
// but is otherwise unused. The answers come back
|
||||
// in the two registers.
|
||||
sec, usec, err := gettimeofday(tv)
|
||||
tv.Sec = int32(sec)
|
||||
|
|
17
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go
generated
vendored
|
@ -11,25 +11,18 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = nsec / 1e9
|
||||
ts.Nsec = nsec % 1e9
|
||||
return
|
||||
func setTimespec(sec, nsec int64) Timespec {
|
||||
return Timespec{Sec: sec, Nsec: nsec}
|
||||
}
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
nsec += 999 // round up to microsecond
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
tv.Sec = int64(nsec / 1e9)
|
||||
return
|
||||
func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
|
||||
func Gettimeofday(tv *Timeval) (err error) {
|
||||
// The tv passed to gettimeofday must be non-nil
|
||||
// but is otherwise unused. The answers come back
|
||||
// but is otherwise unused. The answers come back
|
||||
// in the two registers.
|
||||
sec, usec, err := gettimeofday(tv)
|
||||
tv.Sec = sec
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue