kill: the vendor.
This commit is contained in:
parent
9024f1b444
commit
306e86c9c6
5193 changed files with 0 additions and 1205437 deletions
2402
Gopkg.lock
generated
2402
Gopkg.lock
generated
File diff suppressed because it is too large
Load diff
289
Gopkg.toml
289
Gopkg.toml
|
@ -1,289 +0,0 @@
|
||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
|
|
||||||
required = [
|
|
||||||
"k8s.io/code-generator/cmd/client-gen",
|
|
||||||
"k8s.io/code-generator/cmd/deepcopy-gen",
|
|
||||||
"k8s.io/code-generator/cmd/defaulter-gen",
|
|
||||||
"k8s.io/code-generator/cmd/lister-gen",
|
|
||||||
"k8s.io/code-generator/cmd/informer-gen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[prune]
|
|
||||||
non-go = true
|
|
||||||
go-tests = true
|
|
||||||
unused-packages = true
|
|
||||||
[[prune.project]]
|
|
||||||
name = "k8s.io/code-generator"
|
|
||||||
non-go = false
|
|
||||||
unused-packages = false
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# branch = "master"
|
|
||||||
# name = "github.com/ArthurHlt/go-eureka-client"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/BurntSushi/toml"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# branch = "master"
|
|
||||||
# name = "github.com/BurntSushi/ty"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/NYTimes/gziphandler"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "containous-fork"
|
|
||||||
name = "github.com/abbot/go-http-auth"
|
|
||||||
source = "github.com/containous/go-http-auth"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/armon/go-proxyproto"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# name = "github.com/aws/aws-sdk-go"
|
|
||||||
# version = "1.13.11"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/cenkalti/backoff"
|
|
||||||
version = "2.1.1"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/containous/mux"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "containous-fork"
|
|
||||||
name = "github.com/containous/alice"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# name = "github.com/thoas/stats"
|
|
||||||
# # related to https://github.com/thoas/stats/pull/32
|
|
||||||
# revision = "4975baf6a358ed3ddaa42133996e1959f96c9300"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/coreos/go-systemd"
|
|
||||||
version = "14.0.0"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# branch = "master"
|
|
||||||
# name = "github.com/docker/leadership"
|
|
||||||
# source = "github.com/containous/leadership"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/eapache/channels"
|
|
||||||
version = "1.1.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/elazarl/go-bindata-assetfs"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "fork-containous"
|
|
||||||
name = "github.com/go-check/check"
|
|
||||||
source = "github.com/containous/check"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "fork-containous"
|
|
||||||
name = "github.com/go-check/check"
|
|
||||||
source = "github.com/containous/check"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/go-kit/kit"
|
|
||||||
version = "v0.9.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/prometheus/client_golang"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/gorilla/websocket"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# name = "github.com/hashicorp/consul"
|
|
||||||
# version = "1.0.6"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# branch = "master"
|
|
||||||
# name = "github.com/jjcollinge/servicefabric"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# branch = "master"
|
|
||||||
# name = "github.com/abronan/valkeyrie"
|
|
||||||
|
|
||||||
#[[constraint]]
|
|
||||||
# name = "github.com/mesosphere/mesos-dns"
|
|
||||||
# source = "https://github.com/containous/mesos-dns.git"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/opentracing/opentracing-go"
|
|
||||||
version = "1.0.2"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "containous-fork"
|
|
||||||
name = "github.com/rancher/go-rancher-metadata"
|
|
||||||
source = "github.com/containous/go-rancher-metadata"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/Masterminds/sprig"
|
|
||||||
version = "2.19.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/stvp/go-udp-testing"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/stretchr/testify"
|
|
||||||
version = "1.2.1"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/uber/jaeger-client-go"
|
|
||||||
source = "github.com/jaegertracing/jaeger-client-go"
|
|
||||||
version = "2.16.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/uber/jaeger-lib"
|
|
||||||
source = "github.com/jaegertracing/jaeger-lib"
|
|
||||||
version = "2.0.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "v1"
|
|
||||||
name = "github.com/unrolled/secure"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/vdemeester/shakers"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/vulcand/oxy"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/go-acme/lego"
|
|
||||||
version = "2.6.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "google.golang.org/grpc"
|
|
||||||
version = "1.13.0"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/golang/protobuf"
|
|
||||||
version = "v1.3.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "gopkg.in/fsnotify.v1"
|
|
||||||
source = "github.com/fsnotify/fsnotify"
|
|
||||||
version = "1.4.2"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "k8s.io/client-go"
|
|
||||||
version = "kubernetes-1.15.1" # kubernetes-1.15.1
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "k8s.io/code-generator"
|
|
||||||
version = "kubernetes-1.15.1" # "kubernetes-1.15.1"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "k8s.io/api"
|
|
||||||
version = "kubernetes-1.15.1" # "kubernetes-1.15.1"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "k8s.io/apimachinery"
|
|
||||||
version = "kubernetes-1.15.1" # "kubernetes-1.15.1"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/json-iterator/go"
|
|
||||||
version = "1.1.6"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/libkermit/docker"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/libkermit/docker-check"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/libkermit/compose"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/docker/docker"
|
|
||||||
source = "github.com/docker/engine"
|
|
||||||
version = "v19.03.1"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/docker/docker"
|
|
||||||
source = "github.com/docker/engine"
|
|
||||||
version = "v19.03.1"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/docker/cli"
|
|
||||||
version = "v19.03.1"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/docker/distribution"
|
|
||||||
version = "v2.7.1"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/docker/libcompose"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
name = "github.com/xeipuuv/gojsonschema"
|
|
||||||
version = "v1.1.0"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
# ALWAYS keep this override
|
|
||||||
name = "github.com/mailgun/timetools"
|
|
||||||
revision = "7e6055773c5137efbeb3bd2410d705fe10ab6bfd"
|
|
||||||
|
|
||||||
[[override]]
|
|
||||||
version = "v1.1.1"
|
|
||||||
name = "github.com/miekg/dns"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/patrickmn/go-cache"
|
|
||||||
version = "2.1.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "gopkg.in/DataDog/dd-trace-go.v1"
|
|
||||||
version = "1.15.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/instana/go-sensor"
|
|
||||||
version = "1.4.12"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/ExpediaDotCom/haystack-client-go"
|
|
||||||
version = "0.2.3"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
||||||
version = "v2.2.2"
|
|
202
vendor/cloud.google.com/go/LICENSE
generated
vendored
202
vendor/cloud.google.com/go/LICENSE
generated
vendored
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
437
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
437
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
|
@ -1,437 +0,0 @@
|
||||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Package metadata provides access to Google Compute Engine (GCE)
|
|
||||||
// metadata and API service accounts.
|
|
||||||
//
|
|
||||||
// This package is a wrapper around the GCE metadata service,
|
|
||||||
// as documented at https://developers.google.com/compute/docs/metadata.
|
|
||||||
package metadata // import "cloud.google.com/go/compute/metadata"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// metadataIP is the documented metadata server IP address.
|
|
||||||
metadataIP = "169.254.169.254"
|
|
||||||
|
|
||||||
// metadataHostEnv is the environment variable specifying the
|
|
||||||
// GCE metadata hostname. If empty, the default value of
|
|
||||||
// metadataIP ("169.254.169.254") is used instead.
|
|
||||||
// This is variable name is not defined by any spec, as far as
|
|
||||||
// I know; it was made up for the Go package.
|
|
||||||
metadataHostEnv = "GCE_METADATA_HOST"
|
|
||||||
|
|
||||||
userAgent = "gcloud-golang/0.1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type cachedValue struct {
|
|
||||||
k string
|
|
||||||
trim bool
|
|
||||||
mu sync.Mutex
|
|
||||||
v string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
projID = &cachedValue{k: "project/project-id", trim: true}
|
|
||||||
projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
|
|
||||||
instID = &cachedValue{k: "instance/id", trim: true}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
metaClient = &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Dial: (&net.Dialer{
|
|
||||||
Timeout: 2 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
ResponseHeaderTimeout: 2 * time.Second,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
subscribeClient = &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Dial: (&net.Dialer{
|
|
||||||
Timeout: 2 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// NotDefinedError is returned when requested metadata is not defined.
|
|
||||||
//
|
|
||||||
// The underlying string is the suffix after "/computeMetadata/v1/".
|
|
||||||
//
|
|
||||||
// This error is not returned if the value is defined to be the empty
|
|
||||||
// string.
|
|
||||||
type NotDefinedError string
|
|
||||||
|
|
||||||
func (suffix NotDefinedError) Error() string {
|
|
||||||
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns a value from the metadata service.
|
|
||||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
|
||||||
//
|
|
||||||
// If the GCE_METADATA_HOST environment variable is not defined, a default of
|
|
||||||
// 169.254.169.254 will be used instead.
|
|
||||||
//
|
|
||||||
// If the requested metadata is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
func Get(suffix string) (string, error) {
|
|
||||||
val, _, err := getETag(metaClient, suffix)
|
|
||||||
return val, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// getETag returns a value from the metadata service as well as the associated
|
|
||||||
// ETag using the provided client. This func is otherwise equivalent to Get.
|
|
||||||
func getETag(client *http.Client, suffix string) (value, etag string, err error) {
|
|
||||||
// Using a fixed IP makes it very difficult to spoof the metadata service in
|
|
||||||
// a container, which is an important use-case for local testing of cloud
|
|
||||||
// deployments. To enable spoofing of the metadata service, the environment
|
|
||||||
// variable GCE_METADATA_HOST is first inspected to decide where metadata
|
|
||||||
// requests shall go.
|
|
||||||
host := os.Getenv(metadataHostEnv)
|
|
||||||
if host == "" {
|
|
||||||
// Using 169.254.169.254 instead of "metadata" here because Go
|
|
||||||
// binaries built with the "netgo" tag and without cgo won't
|
|
||||||
// know the search suffix for "metadata" is
|
|
||||||
// ".google.internal", and this IP address is documented as
|
|
||||||
// being stable anyway.
|
|
||||||
host = metadataIP
|
|
||||||
}
|
|
||||||
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
|
||||||
req, _ := http.NewRequest("GET", url, nil)
|
|
||||||
req.Header.Set("Metadata-Flavor", "Google")
|
|
||||||
req.Header.Set("User-Agent", userAgent)
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode == http.StatusNotFound {
|
|
||||||
return "", "", NotDefinedError(suffix)
|
|
||||||
}
|
|
||||||
if res.StatusCode != 200 {
|
|
||||||
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
|
|
||||||
}
|
|
||||||
all, err := ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return string(all), res.Header.Get("Etag"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTrimmed(suffix string) (s string, err error) {
|
|
||||||
s, err = Get(suffix)
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cachedValue) get() (v string, err error) {
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
c.mu.Lock()
|
|
||||||
if c.v != "" {
|
|
||||||
return c.v, nil
|
|
||||||
}
|
|
||||||
if c.trim {
|
|
||||||
v, err = getTrimmed(c.k)
|
|
||||||
} else {
|
|
||||||
v, err = Get(c.k)
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
c.v = v
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
onGCEOnce sync.Once
|
|
||||||
onGCE bool
|
|
||||||
)
|
|
||||||
|
|
||||||
// OnGCE reports whether this process is running on Google Compute Engine.
|
|
||||||
func OnGCE() bool {
|
|
||||||
onGCEOnce.Do(initOnGCE)
|
|
||||||
return onGCE
|
|
||||||
}
|
|
||||||
|
|
||||||
func initOnGCE() {
|
|
||||||
onGCE = testOnGCE()
|
|
||||||
}
|
|
||||||
|
|
||||||
func testOnGCE() bool {
|
|
||||||
// The user explicitly said they're on GCE, so trust them.
|
|
||||||
if os.Getenv(metadataHostEnv) != "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
resc := make(chan bool, 2)
|
|
||||||
|
|
||||||
// Try two strategies in parallel.
|
|
||||||
// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
|
|
||||||
go func() {
|
|
||||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
|
||||||
req.Header.Set("User-Agent", userAgent)
|
|
||||||
res, err := ctxhttp.Do(ctx, metaClient, req)
|
|
||||||
if err != nil {
|
|
||||||
resc <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
resc <- res.Header.Get("Metadata-Flavor") == "Google"
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
addrs, err := net.LookupHost("metadata.google.internal")
|
|
||||||
if err != nil || len(addrs) == 0 {
|
|
||||||
resc <- false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resc <- strsContains(addrs, metadataIP)
|
|
||||||
}()
|
|
||||||
|
|
||||||
tryHarder := systemInfoSuggestsGCE()
|
|
||||||
if tryHarder {
|
|
||||||
res := <-resc
|
|
||||||
if res {
|
|
||||||
// The first strategy succeeded, so let's use it.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Wait for either the DNS or metadata server probe to
|
|
||||||
// contradict the other one and say we are running on
|
|
||||||
// GCE. Give it a lot of time to do so, since the system
|
|
||||||
// info already suggests we're running on a GCE BIOS.
|
|
||||||
timer := time.NewTimer(5 * time.Second)
|
|
||||||
defer timer.Stop()
|
|
||||||
select {
|
|
||||||
case res = <-resc:
|
|
||||||
return res
|
|
||||||
case <-timer.C:
|
|
||||||
// Too slow. Who knows what this system is.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// There's no hint from the system info that we're running on
|
|
||||||
// GCE, so use the first probe's result as truth, whether it's
|
|
||||||
// true or false. The goal here is to optimize for speed for
|
|
||||||
// users who are NOT running on GCE. We can't assume that
|
|
||||||
// either a DNS lookup or an HTTP request to a blackholed IP
|
|
||||||
// address is fast. Worst case this should return when the
|
|
||||||
// metaClient's Transport.ResponseHeaderTimeout or
|
|
||||||
// Transport.Dial.Timeout fires (in two seconds).
|
|
||||||
return <-resc
|
|
||||||
}
|
|
||||||
|
|
||||||
// systemInfoSuggestsGCE reports whether the local system (without
|
|
||||||
// doing network requests) suggests that we're running on GCE. If this
|
|
||||||
// returns true, testOnGCE tries a bit harder to reach its metadata
|
|
||||||
// server.
|
|
||||||
func systemInfoSuggestsGCE() bool {
|
|
||||||
if runtime.GOOS != "linux" {
|
|
||||||
// We don't have any non-Linux clues available, at least yet.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
|
||||||
name := strings.TrimSpace(string(slurp))
|
|
||||||
return name == "Google" || name == "Google Compute Engine"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribe subscribes to a value from the metadata service.
|
|
||||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
|
||||||
// The suffix may contain query parameters.
|
|
||||||
//
|
|
||||||
// Subscribe calls fn with the latest metadata value indicated by the provided
|
|
||||||
// suffix. If the metadata value is deleted, fn is called with the empty string
|
|
||||||
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
|
|
||||||
// is deleted. Subscribe returns the error value returned from the last call to
|
|
||||||
// fn, which may be nil when ok == false.
|
|
||||||
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
|
||||||
const failedSubscribeSleep = time.Second * 5
|
|
||||||
|
|
||||||
// First check to see if the metadata value exists at all.
|
|
||||||
val, lastETag, err := getETag(subscribeClient, suffix)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := fn(val, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ok := true
|
|
||||||
if strings.ContainsRune(suffix, '?') {
|
|
||||||
suffix += "&wait_for_change=true&last_etag="
|
|
||||||
} else {
|
|
||||||
suffix += "?wait_for_change=true&last_etag="
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
val, etag, err := getETag(subscribeClient, suffix+url.QueryEscape(lastETag))
|
|
||||||
if err != nil {
|
|
||||||
if _, deleted := err.(NotDefinedError); !deleted {
|
|
||||||
time.Sleep(failedSubscribeSleep)
|
|
||||||
continue // Retry on other errors.
|
|
||||||
}
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
lastETag = etag
|
|
||||||
|
|
||||||
if err := fn(val, ok); err != nil || !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProjectID returns the current instance's project ID string.
|
|
||||||
func ProjectID() (string, error) { return projID.get() }
|
|
||||||
|
|
||||||
// NumericProjectID returns the current instance's numeric project ID.
|
|
||||||
func NumericProjectID() (string, error) { return projNum.get() }
|
|
||||||
|
|
||||||
// InternalIP returns the instance's primary internal IP address.
|
|
||||||
func InternalIP() (string, error) {
|
|
||||||
return getTrimmed("instance/network-interfaces/0/ip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExternalIP returns the instance's primary external (public) IP address.
|
|
||||||
func ExternalIP() (string, error) {
|
|
||||||
return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hostname returns the instance's hostname. This will be of the form
|
|
||||||
// "<instanceID>.c.<projID>.internal".
|
|
||||||
func Hostname() (string, error) {
|
|
||||||
return getTrimmed("instance/hostname")
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceTags returns the list of user-defined instance tags,
|
|
||||||
// assigned when initially creating a GCE instance.
|
|
||||||
func InstanceTags() ([]string, error) {
|
|
||||||
var s []string
|
|
||||||
j, err := Get("instance/tags")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceID returns the current VM's numeric instance ID.
|
|
||||||
func InstanceID() (string, error) {
|
|
||||||
return instID.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceName returns the current VM's instance ID string.
|
|
||||||
func InstanceName() (string, error) {
|
|
||||||
host, err := Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.Split(host, ".")[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zone returns the current VM's zone, such as "us-central1-b".
|
|
||||||
func Zone() (string, error) {
|
|
||||||
zone, err := getTrimmed("instance/zone")
|
|
||||||
// zone is of the form "projects/<projNum>/zones/<zoneName>".
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return zone[strings.LastIndex(zone, "/")+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceAttributes returns the list of user-defined attributes,
|
|
||||||
// assigned when initially creating a GCE VM instance. The value of an
|
|
||||||
// attribute can be obtained with InstanceAttributeValue.
|
|
||||||
func InstanceAttributes() ([]string, error) { return lines("instance/attributes/") }
|
|
||||||
|
|
||||||
// ProjectAttributes returns the list of user-defined attributes
|
|
||||||
// applying to the project as a whole, not just this VM. The value of
|
|
||||||
// an attribute can be obtained with ProjectAttributeValue.
|
|
||||||
func ProjectAttributes() ([]string, error) { return lines("project/attributes/") }
|
|
||||||
|
|
||||||
func lines(suffix string) ([]string, error) {
|
|
||||||
j, err := Get(suffix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s := strings.Split(strings.TrimSpace(j), "\n")
|
|
||||||
for i := range s {
|
|
||||||
s[i] = strings.TrimSpace(s[i])
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceAttributeValue returns the value of the provided VM
|
|
||||||
// instance attribute.
|
|
||||||
//
|
|
||||||
// If the requested attribute is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
//
|
|
||||||
// InstanceAttributeValue may return ("", nil) if the attribute was
|
|
||||||
// defined to be the empty string.
|
|
||||||
func InstanceAttributeValue(attr string) (string, error) {
|
|
||||||
return Get("instance/attributes/" + attr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProjectAttributeValue returns the value of the provided
|
|
||||||
// project attribute.
|
|
||||||
//
|
|
||||||
// If the requested attribute is not defined, the returned error will
|
|
||||||
// be of type NotDefinedError.
|
|
||||||
//
|
|
||||||
// ProjectAttributeValue may return ("", nil) if the attribute was
|
|
||||||
// defined to be the empty string.
|
|
||||||
func ProjectAttributeValue(attr string) (string, error) {
|
|
||||||
return Get("project/attributes/" + attr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scopes returns the service account scopes for the given account.
|
|
||||||
// The account may be empty or the string "default" to use the instance's
|
|
||||||
// main account.
|
|
||||||
func Scopes(serviceAccount string) ([]string, error) {
|
|
||||||
if serviceAccount == "" {
|
|
||||||
serviceAccount = "default"
|
|
||||||
}
|
|
||||||
return lines("instance/service-accounts/" + serviceAccount + "/scopes")
|
|
||||||
}
|
|
||||||
|
|
||||||
func strsContains(ss []string, s string) bool {
|
|
||||||
for _, v := range ss {
|
|
||||||
if v == s {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
202
vendor/github.com/Azure/azure-sdk-for-go/LICENSE
generated
vendored
202
vendor/github.com/Azure/azure-sdk-for-go/LICENSE
generated
vendored
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2016 Microsoft Corporation
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
5
vendor/github.com/Azure/azure-sdk-for-go/NOTICE
generated
vendored
5
vendor/github.com/Azure/azure-sdk-for-go/NOTICE
generated
vendored
|
@ -1,5 +0,0 @@
|
||||||
Microsoft Azure-SDK-for-Go
|
|
||||||
Copyright 2014-2017 Microsoft
|
|
||||||
|
|
||||||
This product includes software developed at
|
|
||||||
the Microsoft Corporation (https://www.microsoft.com).
|
|
51
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/client.go
generated
vendored
51
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/client.go
generated
vendored
|
@ -1,51 +0,0 @@
|
||||||
// Package dns implements the Azure ARM Dns service API version 2017-09-01.
|
|
||||||
//
|
|
||||||
// The DNS Management Client.
|
|
||||||
package dns
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DefaultBaseURI is the default URI used for the service Dns
|
|
||||||
DefaultBaseURI = "https://management.azure.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BaseClient is the base client for Dns.
|
|
||||||
type BaseClient struct {
|
|
||||||
autorest.Client
|
|
||||||
BaseURI string
|
|
||||||
SubscriptionID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates an instance of the BaseClient client.
|
|
||||||
func New(subscriptionID string) BaseClient {
|
|
||||||
return NewWithBaseURI(DefaultBaseURI, subscriptionID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWithBaseURI creates an instance of the BaseClient client.
|
|
||||||
func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient {
|
|
||||||
return BaseClient{
|
|
||||||
Client: autorest.NewClientWithUserAgent(UserAgent()),
|
|
||||||
BaseURI: baseURI,
|
|
||||||
SubscriptionID: subscriptionID,
|
|
||||||
}
|
|
||||||
}
|
|
763
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/models.go
generated
vendored
763
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/models.go
generated
vendored
|
@ -1,763 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
|
||||||
"github.com/Azure/go-autorest/autorest/to"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RecordType enumerates the values for record type.
|
|
||||||
type RecordType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// A ...
|
|
||||||
A RecordType = "A"
|
|
||||||
// AAAA ...
|
|
||||||
AAAA RecordType = "AAAA"
|
|
||||||
// CAA ...
|
|
||||||
CAA RecordType = "CAA"
|
|
||||||
// CNAME ...
|
|
||||||
CNAME RecordType = "CNAME"
|
|
||||||
// MX ...
|
|
||||||
MX RecordType = "MX"
|
|
||||||
// NS ...
|
|
||||||
NS RecordType = "NS"
|
|
||||||
// PTR ...
|
|
||||||
PTR RecordType = "PTR"
|
|
||||||
// SOA ...
|
|
||||||
SOA RecordType = "SOA"
|
|
||||||
// SRV ...
|
|
||||||
SRV RecordType = "SRV"
|
|
||||||
// TXT ...
|
|
||||||
TXT RecordType = "TXT"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PossibleRecordTypeValues returns an array of possible values for the RecordType const type.
|
|
||||||
func PossibleRecordTypeValues() []RecordType {
|
|
||||||
return []RecordType{A, AAAA, CAA, CNAME, MX, NS, PTR, SOA, SRV, TXT}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AaaaRecord an AAAA record.
|
|
||||||
type AaaaRecord struct {
|
|
||||||
// Ipv6Address - The IPv6 address of this AAAA record.
|
|
||||||
Ipv6Address *string `json:"ipv6Address,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ARecord an A record.
|
|
||||||
type ARecord struct {
|
|
||||||
// Ipv4Address - The IPv4 address of this A record.
|
|
||||||
Ipv4Address *string `json:"ipv4Address,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CaaRecord a CAA record.
|
|
||||||
type CaaRecord struct {
|
|
||||||
// Flags - The flags for this CAA record as an integer between 0 and 255.
|
|
||||||
Flags *int32 `json:"flags,omitempty"`
|
|
||||||
// Tag - The tag for this CAA record.
|
|
||||||
Tag *string `json:"tag,omitempty"`
|
|
||||||
// Value - The value for this CAA record.
|
|
||||||
Value *string `json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloudError an error message
|
|
||||||
type CloudError struct {
|
|
||||||
// Error - The error message body
|
|
||||||
Error *CloudErrorBody `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloudErrorBody the body of an error message
|
|
||||||
type CloudErrorBody struct {
|
|
||||||
// Code - The error code
|
|
||||||
Code *string `json:"code,omitempty"`
|
|
||||||
// Message - A description of what caused the error
|
|
||||||
Message *string `json:"message,omitempty"`
|
|
||||||
// Target - The target resource of the error message
|
|
||||||
Target *string `json:"target,omitempty"`
|
|
||||||
// Details - Extra error information
|
|
||||||
Details *[]CloudErrorBody `json:"details,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CnameRecord a CNAME record.
|
|
||||||
type CnameRecord struct {
|
|
||||||
// Cname - The canonical name for this CNAME record.
|
|
||||||
Cname *string `json:"cname,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MxRecord an MX record.
|
|
||||||
type MxRecord struct {
|
|
||||||
// Preference - The preference value for this MX record.
|
|
||||||
Preference *int32 `json:"preference,omitempty"`
|
|
||||||
// Exchange - The domain name of the mail host for this MX record.
|
|
||||||
Exchange *string `json:"exchange,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NsRecord an NS record.
|
|
||||||
type NsRecord struct {
|
|
||||||
// Nsdname - The name server name for this NS record.
|
|
||||||
Nsdname *string `json:"nsdname,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PtrRecord a PTR record.
|
|
||||||
type PtrRecord struct {
|
|
||||||
// Ptrdname - The PTR target domain name for this PTR record.
|
|
||||||
Ptrdname *string `json:"ptrdname,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSet describes a DNS record set (a collection of DNS records with the same name and type).
|
|
||||||
type RecordSet struct {
|
|
||||||
autorest.Response `json:"-"`
|
|
||||||
// ID - The ID of the record set.
|
|
||||||
ID *string `json:"id,omitempty"`
|
|
||||||
// Name - The name of the record set.
|
|
||||||
Name *string `json:"name,omitempty"`
|
|
||||||
// Type - The type of the record set.
|
|
||||||
Type *string `json:"type,omitempty"`
|
|
||||||
// Etag - The etag of the record set.
|
|
||||||
Etag *string `json:"etag,omitempty"`
|
|
||||||
// RecordSetProperties - The properties of the record set.
|
|
||||||
*RecordSetProperties `json:"properties,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON is the custom marshaler for RecordSet.
|
|
||||||
func (rs RecordSet) MarshalJSON() ([]byte, error) {
|
|
||||||
objectMap := make(map[string]interface{})
|
|
||||||
if rs.ID != nil {
|
|
||||||
objectMap["id"] = rs.ID
|
|
||||||
}
|
|
||||||
if rs.Name != nil {
|
|
||||||
objectMap["name"] = rs.Name
|
|
||||||
}
|
|
||||||
if rs.Type != nil {
|
|
||||||
objectMap["type"] = rs.Type
|
|
||||||
}
|
|
||||||
if rs.Etag != nil {
|
|
||||||
objectMap["etag"] = rs.Etag
|
|
||||||
}
|
|
||||||
if rs.RecordSetProperties != nil {
|
|
||||||
objectMap["properties"] = rs.RecordSetProperties
|
|
||||||
}
|
|
||||||
return json.Marshal(objectMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON is the custom unmarshaler for RecordSet struct.
|
|
||||||
func (rs *RecordSet) UnmarshalJSON(body []byte) error {
|
|
||||||
var m map[string]*json.RawMessage
|
|
||||||
err := json.Unmarshal(body, &m)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for k, v := range m {
|
|
||||||
switch k {
|
|
||||||
case "id":
|
|
||||||
if v != nil {
|
|
||||||
var ID string
|
|
||||||
err = json.Unmarshal(*v, &ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rs.ID = &ID
|
|
||||||
}
|
|
||||||
case "name":
|
|
||||||
if v != nil {
|
|
||||||
var name string
|
|
||||||
err = json.Unmarshal(*v, &name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rs.Name = &name
|
|
||||||
}
|
|
||||||
case "type":
|
|
||||||
if v != nil {
|
|
||||||
var typeVar string
|
|
||||||
err = json.Unmarshal(*v, &typeVar)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rs.Type = &typeVar
|
|
||||||
}
|
|
||||||
case "etag":
|
|
||||||
if v != nil {
|
|
||||||
var etag string
|
|
||||||
err = json.Unmarshal(*v, &etag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rs.Etag = &etag
|
|
||||||
}
|
|
||||||
case "properties":
|
|
||||||
if v != nil {
|
|
||||||
var recordSetProperties RecordSetProperties
|
|
||||||
err = json.Unmarshal(*v, &recordSetProperties)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rs.RecordSetProperties = &recordSetProperties
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSetListResult the response to a record set List operation.
|
|
||||||
type RecordSetListResult struct {
|
|
||||||
autorest.Response `json:"-"`
|
|
||||||
// Value - Information about the record sets in the response.
|
|
||||||
Value *[]RecordSet `json:"value,omitempty"`
|
|
||||||
// NextLink - The continuation token for the next page of results.
|
|
||||||
NextLink *string `json:"nextLink,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSetListResultIterator provides access to a complete listing of RecordSet values.
|
|
||||||
type RecordSetListResultIterator struct {
|
|
||||||
i int
|
|
||||||
page RecordSetListResultPage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next advances to the next value. If there was an error making
|
|
||||||
// the request the iterator does not advance and the error is returned.
|
|
||||||
func (iter *RecordSetListResultIterator) Next() error {
|
|
||||||
iter.i++
|
|
||||||
if iter.i < len(iter.page.Values()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := iter.page.Next()
|
|
||||||
if err != nil {
|
|
||||||
iter.i--
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
iter.i = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotDone returns true if the enumeration should be started or is not yet complete.
|
|
||||||
func (iter RecordSetListResultIterator) NotDone() bool {
|
|
||||||
return iter.page.NotDone() && iter.i < len(iter.page.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response returns the raw server response from the last page request.
|
|
||||||
func (iter RecordSetListResultIterator) Response() RecordSetListResult {
|
|
||||||
return iter.page.Response()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the current value or a zero-initialized value if the
|
|
||||||
// iterator has advanced beyond the end of the collection.
|
|
||||||
func (iter RecordSetListResultIterator) Value() RecordSet {
|
|
||||||
if !iter.page.NotDone() {
|
|
||||||
return RecordSet{}
|
|
||||||
}
|
|
||||||
return iter.page.Values()[iter.i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if the ListResult contains no values.
|
|
||||||
func (rslr RecordSetListResult) IsEmpty() bool {
|
|
||||||
return rslr.Value == nil || len(*rslr.Value) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// recordSetListResultPreparer prepares a request to retrieve the next set of results.
|
|
||||||
// It returns nil if no more results exist.
|
|
||||||
func (rslr RecordSetListResult) recordSetListResultPreparer() (*http.Request, error) {
|
|
||||||
if rslr.NextLink == nil || len(to.String(rslr.NextLink)) < 1 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return autorest.Prepare(&http.Request{},
|
|
||||||
autorest.AsJSON(),
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(to.String(rslr.NextLink)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSetListResultPage contains a page of RecordSet values.
|
|
||||||
type RecordSetListResultPage struct {
|
|
||||||
fn func(RecordSetListResult) (RecordSetListResult, error)
|
|
||||||
rslr RecordSetListResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next advances to the next page of values. If there was an error making
|
|
||||||
// the request the page does not advance and the error is returned.
|
|
||||||
func (page *RecordSetListResultPage) Next() error {
|
|
||||||
next, err := page.fn(page.rslr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
page.rslr = next
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotDone returns true if the page enumeration should be started or is not yet complete.
|
|
||||||
func (page RecordSetListResultPage) NotDone() bool {
|
|
||||||
return !page.rslr.IsEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response returns the raw server response from the last page request.
|
|
||||||
func (page RecordSetListResultPage) Response() RecordSetListResult {
|
|
||||||
return page.rslr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns the slice of values for the current page or nil if there are no values.
|
|
||||||
func (page RecordSetListResultPage) Values() []RecordSet {
|
|
||||||
if page.rslr.IsEmpty() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return *page.rslr.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSetProperties represents the properties of the records in the record set.
|
|
||||||
type RecordSetProperties struct {
|
|
||||||
// Metadata - The metadata attached to the record set.
|
|
||||||
Metadata map[string]*string `json:"metadata"`
|
|
||||||
// TTL - The TTL (time-to-live) of the records in the record set.
|
|
||||||
TTL *int64 `json:"TTL,omitempty"`
|
|
||||||
// Fqdn - Fully qualified domain name of the record set.
|
|
||||||
Fqdn *string `json:"fqdn,omitempty"`
|
|
||||||
// ARecords - The list of A records in the record set.
|
|
||||||
ARecords *[]ARecord `json:"ARecords,omitempty"`
|
|
||||||
// AaaaRecords - The list of AAAA records in the record set.
|
|
||||||
AaaaRecords *[]AaaaRecord `json:"AAAARecords,omitempty"`
|
|
||||||
// MxRecords - The list of MX records in the record set.
|
|
||||||
MxRecords *[]MxRecord `json:"MXRecords,omitempty"`
|
|
||||||
// NsRecords - The list of NS records in the record set.
|
|
||||||
NsRecords *[]NsRecord `json:"NSRecords,omitempty"`
|
|
||||||
// PtrRecords - The list of PTR records in the record set.
|
|
||||||
PtrRecords *[]PtrRecord `json:"PTRRecords,omitempty"`
|
|
||||||
// SrvRecords - The list of SRV records in the record set.
|
|
||||||
SrvRecords *[]SrvRecord `json:"SRVRecords,omitempty"`
|
|
||||||
// TxtRecords - The list of TXT records in the record set.
|
|
||||||
TxtRecords *[]TxtRecord `json:"TXTRecords,omitempty"`
|
|
||||||
// CnameRecord - The CNAME record in the record set.
|
|
||||||
CnameRecord *CnameRecord `json:"CNAMERecord,omitempty"`
|
|
||||||
// SoaRecord - The SOA record in the record set.
|
|
||||||
SoaRecord *SoaRecord `json:"SOARecord,omitempty"`
|
|
||||||
// CaaRecords - The list of CAA records in the record set.
|
|
||||||
CaaRecords *[]CaaRecord `json:"caaRecords,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON is the custom marshaler for RecordSetProperties.
|
|
||||||
func (rsp RecordSetProperties) MarshalJSON() ([]byte, error) {
|
|
||||||
objectMap := make(map[string]interface{})
|
|
||||||
if rsp.Metadata != nil {
|
|
||||||
objectMap["metadata"] = rsp.Metadata
|
|
||||||
}
|
|
||||||
if rsp.TTL != nil {
|
|
||||||
objectMap["TTL"] = rsp.TTL
|
|
||||||
}
|
|
||||||
if rsp.Fqdn != nil {
|
|
||||||
objectMap["fqdn"] = rsp.Fqdn
|
|
||||||
}
|
|
||||||
if rsp.ARecords != nil {
|
|
||||||
objectMap["ARecords"] = rsp.ARecords
|
|
||||||
}
|
|
||||||
if rsp.AaaaRecords != nil {
|
|
||||||
objectMap["AAAARecords"] = rsp.AaaaRecords
|
|
||||||
}
|
|
||||||
if rsp.MxRecords != nil {
|
|
||||||
objectMap["MXRecords"] = rsp.MxRecords
|
|
||||||
}
|
|
||||||
if rsp.NsRecords != nil {
|
|
||||||
objectMap["NSRecords"] = rsp.NsRecords
|
|
||||||
}
|
|
||||||
if rsp.PtrRecords != nil {
|
|
||||||
objectMap["PTRRecords"] = rsp.PtrRecords
|
|
||||||
}
|
|
||||||
if rsp.SrvRecords != nil {
|
|
||||||
objectMap["SRVRecords"] = rsp.SrvRecords
|
|
||||||
}
|
|
||||||
if rsp.TxtRecords != nil {
|
|
||||||
objectMap["TXTRecords"] = rsp.TxtRecords
|
|
||||||
}
|
|
||||||
if rsp.CnameRecord != nil {
|
|
||||||
objectMap["CNAMERecord"] = rsp.CnameRecord
|
|
||||||
}
|
|
||||||
if rsp.SoaRecord != nil {
|
|
||||||
objectMap["SOARecord"] = rsp.SoaRecord
|
|
||||||
}
|
|
||||||
if rsp.CaaRecords != nil {
|
|
||||||
objectMap["caaRecords"] = rsp.CaaRecords
|
|
||||||
}
|
|
||||||
return json.Marshal(objectMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordSetUpdateParameters parameters supplied to update a record set.
|
|
||||||
type RecordSetUpdateParameters struct {
|
|
||||||
// RecordSet - Specifies information about the record set being updated.
|
|
||||||
RecordSet *RecordSet `json:"RecordSet,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource common properties of an Azure Resource Manager resource
|
|
||||||
type Resource struct {
|
|
||||||
// ID - Resource ID.
|
|
||||||
ID *string `json:"id,omitempty"`
|
|
||||||
// Name - Resource name.
|
|
||||||
Name *string `json:"name,omitempty"`
|
|
||||||
// Type - Resource type.
|
|
||||||
Type *string `json:"type,omitempty"`
|
|
||||||
// Location - Resource location.
|
|
||||||
Location *string `json:"location,omitempty"`
|
|
||||||
// Tags - Resource tags.
|
|
||||||
Tags map[string]*string `json:"tags"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON is the custom marshaler for Resource.
|
|
||||||
func (r Resource) MarshalJSON() ([]byte, error) {
|
|
||||||
objectMap := make(map[string]interface{})
|
|
||||||
if r.ID != nil {
|
|
||||||
objectMap["id"] = r.ID
|
|
||||||
}
|
|
||||||
if r.Name != nil {
|
|
||||||
objectMap["name"] = r.Name
|
|
||||||
}
|
|
||||||
if r.Type != nil {
|
|
||||||
objectMap["type"] = r.Type
|
|
||||||
}
|
|
||||||
if r.Location != nil {
|
|
||||||
objectMap["location"] = r.Location
|
|
||||||
}
|
|
||||||
if r.Tags != nil {
|
|
||||||
objectMap["tags"] = r.Tags
|
|
||||||
}
|
|
||||||
return json.Marshal(objectMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SoaRecord an SOA record.
|
|
||||||
type SoaRecord struct {
|
|
||||||
// Host - The domain name of the authoritative name server for this SOA record.
|
|
||||||
Host *string `json:"host,omitempty"`
|
|
||||||
// Email - The email contact for this SOA record.
|
|
||||||
Email *string `json:"email,omitempty"`
|
|
||||||
// SerialNumber - The serial number for this SOA record.
|
|
||||||
SerialNumber *int64 `json:"serialNumber,omitempty"`
|
|
||||||
// RefreshTime - The refresh value for this SOA record.
|
|
||||||
RefreshTime *int64 `json:"refreshTime,omitempty"`
|
|
||||||
// RetryTime - The retry time for this SOA record.
|
|
||||||
RetryTime *int64 `json:"retryTime,omitempty"`
|
|
||||||
// ExpireTime - The expire time for this SOA record.
|
|
||||||
ExpireTime *int64 `json:"expireTime,omitempty"`
|
|
||||||
// MinimumTTL - The minimum value for this SOA record. By convention this is used to determine the negative caching duration.
|
|
||||||
MinimumTTL *int64 `json:"minimumTTL,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SrvRecord an SRV record.
|
|
||||||
type SrvRecord struct {
|
|
||||||
// Priority - The priority value for this SRV record.
|
|
||||||
Priority *int32 `json:"priority,omitempty"`
|
|
||||||
// Weight - The weight value for this SRV record.
|
|
||||||
Weight *int32 `json:"weight,omitempty"`
|
|
||||||
// Port - The port value for this SRV record.
|
|
||||||
Port *int32 `json:"port,omitempty"`
|
|
||||||
// Target - The target domain name for this SRV record.
|
|
||||||
Target *string `json:"target,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubResource a reference to a another resource
|
|
||||||
type SubResource struct {
|
|
||||||
// ID - Resource Id.
|
|
||||||
ID *string `json:"id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TxtRecord a TXT record.
|
|
||||||
type TxtRecord struct {
|
|
||||||
// Value - The text value of this TXT record.
|
|
||||||
Value *[]string `json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zone describes a DNS zone.
|
|
||||||
type Zone struct {
|
|
||||||
autorest.Response `json:"-"`
|
|
||||||
// Etag - The etag of the zone.
|
|
||||||
Etag *string `json:"etag,omitempty"`
|
|
||||||
// ZoneProperties - The properties of the zone.
|
|
||||||
*ZoneProperties `json:"properties,omitempty"`
|
|
||||||
// ID - Resource ID.
|
|
||||||
ID *string `json:"id,omitempty"`
|
|
||||||
// Name - Resource name.
|
|
||||||
Name *string `json:"name,omitempty"`
|
|
||||||
// Type - Resource type.
|
|
||||||
Type *string `json:"type,omitempty"`
|
|
||||||
// Location - Resource location.
|
|
||||||
Location *string `json:"location,omitempty"`
|
|
||||||
// Tags - Resource tags.
|
|
||||||
Tags map[string]*string `json:"tags"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON is the custom marshaler for Zone.
|
|
||||||
func (z Zone) MarshalJSON() ([]byte, error) {
|
|
||||||
objectMap := make(map[string]interface{})
|
|
||||||
if z.Etag != nil {
|
|
||||||
objectMap["etag"] = z.Etag
|
|
||||||
}
|
|
||||||
if z.ZoneProperties != nil {
|
|
||||||
objectMap["properties"] = z.ZoneProperties
|
|
||||||
}
|
|
||||||
if z.ID != nil {
|
|
||||||
objectMap["id"] = z.ID
|
|
||||||
}
|
|
||||||
if z.Name != nil {
|
|
||||||
objectMap["name"] = z.Name
|
|
||||||
}
|
|
||||||
if z.Type != nil {
|
|
||||||
objectMap["type"] = z.Type
|
|
||||||
}
|
|
||||||
if z.Location != nil {
|
|
||||||
objectMap["location"] = z.Location
|
|
||||||
}
|
|
||||||
if z.Tags != nil {
|
|
||||||
objectMap["tags"] = z.Tags
|
|
||||||
}
|
|
||||||
return json.Marshal(objectMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON is the custom unmarshaler for Zone struct.
|
|
||||||
func (z *Zone) UnmarshalJSON(body []byte) error {
|
|
||||||
var m map[string]*json.RawMessage
|
|
||||||
err := json.Unmarshal(body, &m)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for k, v := range m {
|
|
||||||
switch k {
|
|
||||||
case "etag":
|
|
||||||
if v != nil {
|
|
||||||
var etag string
|
|
||||||
err = json.Unmarshal(*v, &etag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.Etag = &etag
|
|
||||||
}
|
|
||||||
case "properties":
|
|
||||||
if v != nil {
|
|
||||||
var zoneProperties ZoneProperties
|
|
||||||
err = json.Unmarshal(*v, &zoneProperties)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.ZoneProperties = &zoneProperties
|
|
||||||
}
|
|
||||||
case "id":
|
|
||||||
if v != nil {
|
|
||||||
var ID string
|
|
||||||
err = json.Unmarshal(*v, &ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.ID = &ID
|
|
||||||
}
|
|
||||||
case "name":
|
|
||||||
if v != nil {
|
|
||||||
var name string
|
|
||||||
err = json.Unmarshal(*v, &name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.Name = &name
|
|
||||||
}
|
|
||||||
case "type":
|
|
||||||
if v != nil {
|
|
||||||
var typeVar string
|
|
||||||
err = json.Unmarshal(*v, &typeVar)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.Type = &typeVar
|
|
||||||
}
|
|
||||||
case "location":
|
|
||||||
if v != nil {
|
|
||||||
var location string
|
|
||||||
err = json.Unmarshal(*v, &location)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.Location = &location
|
|
||||||
}
|
|
||||||
case "tags":
|
|
||||||
if v != nil {
|
|
||||||
var tags map[string]*string
|
|
||||||
err = json.Unmarshal(*v, &tags)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
z.Tags = tags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneListResult the response to a Zone List or ListAll operation.
|
|
||||||
type ZoneListResult struct {
|
|
||||||
autorest.Response `json:"-"`
|
|
||||||
// Value - Information about the DNS zones.
|
|
||||||
Value *[]Zone `json:"value,omitempty"`
|
|
||||||
// NextLink - The continuation token for the next page of results.
|
|
||||||
NextLink *string `json:"nextLink,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneListResultIterator provides access to a complete listing of Zone values.
|
|
||||||
type ZoneListResultIterator struct {
|
|
||||||
i int
|
|
||||||
page ZoneListResultPage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next advances to the next value. If there was an error making
|
|
||||||
// the request the iterator does not advance and the error is returned.
|
|
||||||
func (iter *ZoneListResultIterator) Next() error {
|
|
||||||
iter.i++
|
|
||||||
if iter.i < len(iter.page.Values()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := iter.page.Next()
|
|
||||||
if err != nil {
|
|
||||||
iter.i--
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
iter.i = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotDone returns true if the enumeration should be started or is not yet complete.
|
|
||||||
func (iter ZoneListResultIterator) NotDone() bool {
|
|
||||||
return iter.page.NotDone() && iter.i < len(iter.page.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response returns the raw server response from the last page request.
|
|
||||||
func (iter ZoneListResultIterator) Response() ZoneListResult {
|
|
||||||
return iter.page.Response()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the current value or a zero-initialized value if the
|
|
||||||
// iterator has advanced beyond the end of the collection.
|
|
||||||
func (iter ZoneListResultIterator) Value() Zone {
|
|
||||||
if !iter.page.NotDone() {
|
|
||||||
return Zone{}
|
|
||||||
}
|
|
||||||
return iter.page.Values()[iter.i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if the ListResult contains no values.
|
|
||||||
func (zlr ZoneListResult) IsEmpty() bool {
|
|
||||||
return zlr.Value == nil || len(*zlr.Value) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// zoneListResultPreparer prepares a request to retrieve the next set of results.
|
|
||||||
// It returns nil if no more results exist.
|
|
||||||
func (zlr ZoneListResult) zoneListResultPreparer() (*http.Request, error) {
|
|
||||||
if zlr.NextLink == nil || len(to.String(zlr.NextLink)) < 1 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return autorest.Prepare(&http.Request{},
|
|
||||||
autorest.AsJSON(),
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(to.String(zlr.NextLink)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneListResultPage contains a page of Zone values.
|
|
||||||
type ZoneListResultPage struct {
|
|
||||||
fn func(ZoneListResult) (ZoneListResult, error)
|
|
||||||
zlr ZoneListResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next advances to the next page of values. If there was an error making
|
|
||||||
// the request the page does not advance and the error is returned.
|
|
||||||
func (page *ZoneListResultPage) Next() error {
|
|
||||||
next, err := page.fn(page.zlr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
page.zlr = next
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotDone returns true if the page enumeration should be started or is not yet complete.
|
|
||||||
func (page ZoneListResultPage) NotDone() bool {
|
|
||||||
return !page.zlr.IsEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response returns the raw server response from the last page request.
|
|
||||||
func (page ZoneListResultPage) Response() ZoneListResult {
|
|
||||||
return page.zlr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns the slice of values for the current page or nil if there are no values.
|
|
||||||
func (page ZoneListResultPage) Values() []Zone {
|
|
||||||
if page.zlr.IsEmpty() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return *page.zlr.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneProperties represents the properties of the zone.
|
|
||||||
type ZoneProperties struct {
|
|
||||||
// MaxNumberOfRecordSets - The maximum number of record sets that can be created in this DNS zone. This is a read-only property and any attempt to set this value will be ignored.
|
|
||||||
MaxNumberOfRecordSets *int64 `json:"maxNumberOfRecordSets,omitempty"`
|
|
||||||
// NumberOfRecordSets - The current number of record sets in this DNS zone. This is a read-only property and any attempt to set this value will be ignored.
|
|
||||||
NumberOfRecordSets *int64 `json:"numberOfRecordSets,omitempty"`
|
|
||||||
// NameServers - The name servers for this DNS zone. This is a read-only property and any attempt to set this value will be ignored.
|
|
||||||
NameServers *[]string `json:"nameServers,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZonesDeleteFuture an abstraction for monitoring and retrieving the results of a long-running operation.
|
|
||||||
type ZonesDeleteFuture struct {
|
|
||||||
azure.Future
|
|
||||||
req *http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
// Result returns the result of the asynchronous operation.
|
|
||||||
// If the operation has not completed it will return an error.
|
|
||||||
func (future ZonesDeleteFuture) Result(client ZonesClient) (ar autorest.Response, err error) {
|
|
||||||
var done bool
|
|
||||||
done, err = future.Done(client)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesDeleteFuture", "Result", future.Response(), "Polling failure")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !done {
|
|
||||||
return ar, azure.NewAsyncOpIncompleteError("dns.ZonesDeleteFuture")
|
|
||||||
}
|
|
||||||
if future.PollingMethod() == azure.PollingLocation {
|
|
||||||
ar, err = client.DeleteResponder(future.Response())
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesDeleteFuture", "Result", future.Response(), "Failure responding to request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var req *http.Request
|
|
||||||
var resp *http.Response
|
|
||||||
if future.PollingURL() != "" {
|
|
||||||
req, err = http.NewRequest(http.MethodGet, future.PollingURL(), nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
req = autorest.ChangeToGet(future.req)
|
|
||||||
}
|
|
||||||
resp, err = autorest.SendWithSender(client, req,
|
|
||||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesDeleteFuture", "Result", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ar, err = client.DeleteResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesDeleteFuture", "Result", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
556
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/recordsets.go
generated
vendored
556
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/recordsets.go
generated
vendored
|
@ -1,556 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RecordSetsClient is the the DNS Management Client.
|
|
||||||
type RecordSetsClient struct {
|
|
||||||
BaseClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRecordSetsClient creates an instance of the RecordSetsClient client.
|
|
||||||
func NewRecordSetsClient(subscriptionID string) RecordSetsClient {
|
|
||||||
return NewRecordSetsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRecordSetsClientWithBaseURI creates an instance of the RecordSetsClient client.
|
|
||||||
func NewRecordSetsClientWithBaseURI(baseURI string, subscriptionID string) RecordSetsClient {
|
|
||||||
return RecordSetsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdate creates or updates a record set within a DNS zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). relativeRecordSetName is the name of the record set, relative to the name of the zone. recordType is the
|
|
||||||
// type of DNS record in this record set. Record sets of type SOA can be updated but not created (they are created
|
|
||||||
// when the DNS zone is created). parameters is parameters supplied to the CreateOrUpdate operation. ifMatch is the
|
|
||||||
// etag of the record set. Omit this value to always overwrite the current record set. Specify the last-seen etag
|
|
||||||
// value to prevent accidentally overwritting any concurrent changes. ifNoneMatch is set to '*' to allow a new
|
|
||||||
// record set to be created, but to prevent updating an existing record set. Other values will be ignored.
|
|
||||||
func (client RecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string, ifNoneMatch string) (result RecordSet, err error) {
|
|
||||||
req, err := client.CreateOrUpdatePreparer(ctx, resourceGroupName, zoneName, relativeRecordSetName, recordType, parameters, ifMatch, ifNoneMatch)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "CreateOrUpdate", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.CreateOrUpdateSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "CreateOrUpdate", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.CreateOrUpdateResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "CreateOrUpdate", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
|
|
||||||
func (client RecordSetsClient) CreateOrUpdatePreparer(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string, ifNoneMatch string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"recordType": autorest.Encode("path", recordType),
|
|
||||||
"relativeRecordSetName": relativeRecordSetName,
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsContentType("application/json; charset=utf-8"),
|
|
||||||
autorest.AsPut(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/{recordType}/{relativeRecordSetName}", pathParameters),
|
|
||||||
autorest.WithJSON(parameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
if len(ifMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-Match", autorest.String(ifMatch)))
|
|
||||||
}
|
|
||||||
if len(ifNoneMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
|
|
||||||
}
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) CreateOrUpdateResponder(resp *http.Response) (result RecordSet, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes a record set from a DNS zone. This operation cannot be undone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). relativeRecordSetName is the name of the record set, relative to the name of the zone. recordType is the
|
|
||||||
// type of DNS record in this record set. Record sets of type SOA cannot be deleted (they are deleted when the DNS
|
|
||||||
// zone is deleted). ifMatch is the etag of the record set. Omit this value to always delete the current record
|
|
||||||
// set. Specify the last-seen etag value to prevent accidentally deleting any concurrent changes.
|
|
||||||
func (client RecordSetsClient) Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, ifMatch string) (result autorest.Response, err error) {
|
|
||||||
req, err := client.DeletePreparer(ctx, resourceGroupName, zoneName, relativeRecordSetName, recordType, ifMatch)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Delete", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.DeleteSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = resp
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Delete", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.DeleteResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Delete", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeletePreparer prepares the Delete request.
|
|
||||||
func (client RecordSetsClient) DeletePreparer(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, ifMatch string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"recordType": autorest.Encode("path", recordType),
|
|
||||||
"relativeRecordSetName": relativeRecordSetName,
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsDelete(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/{recordType}/{relativeRecordSetName}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
if len(ifMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-Match", autorest.String(ifMatch)))
|
|
||||||
}
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSender sends the Delete request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) DeleteSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResponder handles the response to the Delete request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = resp
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets a record set.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). relativeRecordSetName is the name of the record set, relative to the name of the zone. recordType is the
|
|
||||||
// type of DNS record in this record set.
|
|
||||||
func (client RecordSetsClient) Get(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType) (result RecordSet, err error) {
|
|
||||||
req, err := client.GetPreparer(ctx, resourceGroupName, zoneName, relativeRecordSetName, recordType)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Get", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.GetSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Get", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.GetResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Get", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPreparer prepares the Get request.
|
|
||||||
func (client RecordSetsClient) GetPreparer(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"recordType": autorest.Encode("path", recordType),
|
|
||||||
"relativeRecordSetName": relativeRecordSetName,
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/{recordType}/{relativeRecordSetName}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSender sends the Get request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) GetSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResponder handles the response to the Get request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) GetResponder(resp *http.Response) (result RecordSet, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByDNSZone lists all record sets in a DNS zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). top is the maximum number of record sets to return. If not specified, returns up to 100 record sets.
|
|
||||||
// recordsetnamesuffix is the suffix label of the record set name that has to be used to filter the record set
|
|
||||||
// enumerations. If this parameter is specified, Enumeration will return only records that end with
|
|
||||||
// .<recordSetNameSuffix>
|
|
||||||
func (client RecordSetsClient) ListByDNSZone(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordsetnamesuffix string) (result RecordSetListResultPage, err error) {
|
|
||||||
result.fn = client.listByDNSZoneNextResults
|
|
||||||
req, err := client.ListByDNSZonePreparer(ctx, resourceGroupName, zoneName, top, recordsetnamesuffix)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByDNSZone", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.ListByDNSZoneSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.rslr.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByDNSZone", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result.rslr, err = client.ListByDNSZoneResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByDNSZone", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByDNSZonePreparer prepares the ListByDNSZone request.
|
|
||||||
func (client RecordSetsClient) ListByDNSZonePreparer(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordsetnamesuffix string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
if top != nil {
|
|
||||||
queryParameters["$top"] = autorest.Encode("query", *top)
|
|
||||||
}
|
|
||||||
if len(recordsetnamesuffix) > 0 {
|
|
||||||
queryParameters["$recordsetnamesuffix"] = autorest.Encode("query", recordsetnamesuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/recordsets", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByDNSZoneSender sends the ListByDNSZone request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) ListByDNSZoneSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByDNSZoneResponder handles the response to the ListByDNSZone request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) ListByDNSZoneResponder(resp *http.Response) (result RecordSetListResult, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// listByDNSZoneNextResults retrieves the next set of results, if any.
|
|
||||||
func (client RecordSetsClient) listByDNSZoneNextResults(lastResults RecordSetListResult) (result RecordSetListResult, err error) {
|
|
||||||
req, err := lastResults.recordSetListResultPreparer()
|
|
||||||
if err != nil {
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByDNSZoneNextResults", nil, "Failure preparing next results request")
|
|
||||||
}
|
|
||||||
if req == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, err := client.ListByDNSZoneSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByDNSZoneNextResults", resp, "Failure sending next results request")
|
|
||||||
}
|
|
||||||
result, err = client.ListByDNSZoneResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByDNSZoneNextResults", resp, "Failure responding to next results request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByDNSZoneComplete enumerates all values, automatically crossing page boundaries as required.
|
|
||||||
func (client RecordSetsClient) ListByDNSZoneComplete(ctx context.Context, resourceGroupName string, zoneName string, top *int32, recordsetnamesuffix string) (result RecordSetListResultIterator, err error) {
|
|
||||||
result.page, err = client.ListByDNSZone(ctx, resourceGroupName, zoneName, top, recordsetnamesuffix)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByType lists the record sets of a specified type in a DNS zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). recordType is the type of record sets to enumerate. top is the maximum number of record sets to return. If
|
|
||||||
// not specified, returns up to 100 record sets. recordsetnamesuffix is the suffix label of the record set name
|
|
||||||
// that has to be used to filter the record set enumerations. If this parameter is specified, Enumeration will
|
|
||||||
// return only records that end with .<recordSetNameSuffix>
|
|
||||||
func (client RecordSetsClient) ListByType(ctx context.Context, resourceGroupName string, zoneName string, recordType RecordType, top *int32, recordsetnamesuffix string) (result RecordSetListResultPage, err error) {
|
|
||||||
result.fn = client.listByTypeNextResults
|
|
||||||
req, err := client.ListByTypePreparer(ctx, resourceGroupName, zoneName, recordType, top, recordsetnamesuffix)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByType", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.ListByTypeSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.rslr.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByType", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result.rslr, err = client.ListByTypeResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "ListByType", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByTypePreparer prepares the ListByType request.
|
|
||||||
func (client RecordSetsClient) ListByTypePreparer(ctx context.Context, resourceGroupName string, zoneName string, recordType RecordType, top *int32, recordsetnamesuffix string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"recordType": autorest.Encode("path", recordType),
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
if top != nil {
|
|
||||||
queryParameters["$top"] = autorest.Encode("query", *top)
|
|
||||||
}
|
|
||||||
if len(recordsetnamesuffix) > 0 {
|
|
||||||
queryParameters["$recordsetnamesuffix"] = autorest.Encode("query", recordsetnamesuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/{recordType}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByTypeSender sends the ListByType request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) ListByTypeSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByTypeResponder handles the response to the ListByType request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) ListByTypeResponder(resp *http.Response) (result RecordSetListResult, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// listByTypeNextResults retrieves the next set of results, if any.
|
|
||||||
func (client RecordSetsClient) listByTypeNextResults(lastResults RecordSetListResult) (result RecordSetListResult, err error) {
|
|
||||||
req, err := lastResults.recordSetListResultPreparer()
|
|
||||||
if err != nil {
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByTypeNextResults", nil, "Failure preparing next results request")
|
|
||||||
}
|
|
||||||
if req == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, err := client.ListByTypeSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByTypeNextResults", resp, "Failure sending next results request")
|
|
||||||
}
|
|
||||||
result, err = client.ListByTypeResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "listByTypeNextResults", resp, "Failure responding to next results request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByTypeComplete enumerates all values, automatically crossing page boundaries as required.
|
|
||||||
func (client RecordSetsClient) ListByTypeComplete(ctx context.Context, resourceGroupName string, zoneName string, recordType RecordType, top *int32, recordsetnamesuffix string) (result RecordSetListResultIterator, err error) {
|
|
||||||
result.page, err = client.ListByType(ctx, resourceGroupName, zoneName, recordType, top, recordsetnamesuffix)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates a record set within a DNS zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). relativeRecordSetName is the name of the record set, relative to the name of the zone. recordType is the
|
|
||||||
// type of DNS record in this record set. parameters is parameters supplied to the Update operation. ifMatch is the
|
|
||||||
// etag of the record set. Omit this value to always overwrite the current record set. Specify the last-seen etag
|
|
||||||
// value to prevent accidentally overwritting concurrent changes.
|
|
||||||
func (client RecordSetsClient) Update(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string) (result RecordSet, err error) {
|
|
||||||
req, err := client.UpdatePreparer(ctx, resourceGroupName, zoneName, relativeRecordSetName, recordType, parameters, ifMatch)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Update", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.UpdateSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Update", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.UpdateResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.RecordSetsClient", "Update", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatePreparer prepares the Update request.
|
|
||||||
func (client RecordSetsClient) UpdatePreparer(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"recordType": autorest.Encode("path", recordType),
|
|
||||||
"relativeRecordSetName": relativeRecordSetName,
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsContentType("application/json; charset=utf-8"),
|
|
||||||
autorest.AsPatch(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}/{recordType}/{relativeRecordSetName}", pathParameters),
|
|
||||||
autorest.WithJSON(parameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
if len(ifMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-Match", autorest.String(ifMatch)))
|
|
||||||
}
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateSender sends the Update request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client RecordSetsClient) UpdateSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateResponder handles the response to the Update request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client RecordSetsClient) UpdateResponder(resp *http.Response) (result RecordSet, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
30
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/version.go
generated
vendored
30
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/version.go
generated
vendored
|
@ -1,30 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
import "github.com/Azure/azure-sdk-for-go/version"
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
// UserAgent returns the UserAgent string to use when sending http.Requests.
|
|
||||||
func UserAgent() string {
|
|
||||||
return "Azure-SDK-For-Go/" + version.Number + " dns/2017-09-01"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the semantic version (see http://semver.org) of the client.
|
|
||||||
func Version() string {
|
|
||||||
return version.Number
|
|
||||||
}
|
|
453
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/zones.go
generated
vendored
453
vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2017-09-01/dns/zones.go
generated
vendored
|
@ -1,453 +0,0 @@
|
||||||
package dns
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ZonesClient is the the DNS Management Client.
|
|
||||||
type ZonesClient struct {
|
|
||||||
BaseClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewZonesClient creates an instance of the ZonesClient client.
|
|
||||||
func NewZonesClient(subscriptionID string) ZonesClient {
|
|
||||||
return NewZonesClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewZonesClientWithBaseURI creates an instance of the ZonesClient client.
|
|
||||||
func NewZonesClientWithBaseURI(baseURI string, subscriptionID string) ZonesClient {
|
|
||||||
return ZonesClient{NewWithBaseURI(baseURI, subscriptionID)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdate creates or updates a DNS zone. Does not modify DNS records within the zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). parameters is parameters supplied to the CreateOrUpdate operation. ifMatch is the etag of the DNS zone.
|
|
||||||
// Omit this value to always overwrite the current zone. Specify the last-seen etag value to prevent accidentally
|
|
||||||
// overwritting any concurrent changes. ifNoneMatch is set to '*' to allow a new DNS zone to be created, but to
|
|
||||||
// prevent updating an existing zone. Other values will be ignored.
|
|
||||||
func (client ZonesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, parameters Zone, ifMatch string, ifNoneMatch string) (result Zone, err error) {
|
|
||||||
req, err := client.CreateOrUpdatePreparer(ctx, resourceGroupName, zoneName, parameters, ifMatch, ifNoneMatch)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "CreateOrUpdate", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.CreateOrUpdateSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "CreateOrUpdate", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.CreateOrUpdateResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "CreateOrUpdate", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
|
|
||||||
func (client ZonesClient) CreateOrUpdatePreparer(ctx context.Context, resourceGroupName string, zoneName string, parameters Zone, ifMatch string, ifNoneMatch string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsContentType("application/json; charset=utf-8"),
|
|
||||||
autorest.AsPut(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}", pathParameters),
|
|
||||||
autorest.WithJSON(parameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
if len(ifMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-Match", autorest.String(ifMatch)))
|
|
||||||
}
|
|
||||||
if len(ifNoneMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-None-Match", autorest.String(ifNoneMatch)))
|
|
||||||
}
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client ZonesClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client ZonesClient) CreateOrUpdateResponder(resp *http.Response) (result Zone, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes a DNS zone. WARNING: All DNS records in the zone will also be deleted. This operation cannot be
|
|
||||||
// undone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot). ifMatch is the etag of the DNS zone. Omit this value to always delete the current zone. Specify the
|
|
||||||
// last-seen etag value to prevent accidentally deleting any concurrent changes.
|
|
||||||
func (client ZonesClient) Delete(ctx context.Context, resourceGroupName string, zoneName string, ifMatch string) (result ZonesDeleteFuture, err error) {
|
|
||||||
req, err := client.DeletePreparer(ctx, resourceGroupName, zoneName, ifMatch)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "Delete", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.DeleteSender(req)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "Delete", result.Response(), "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeletePreparer prepares the Delete request.
|
|
||||||
func (client ZonesClient) DeletePreparer(ctx context.Context, resourceGroupName string, zoneName string, ifMatch string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsDelete(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
if len(ifMatch) > 0 {
|
|
||||||
preparer = autorest.DecoratePreparer(preparer,
|
|
||||||
autorest.WithHeader("If-Match", autorest.String(ifMatch)))
|
|
||||||
}
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSender sends the Delete request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client ZonesClient) DeleteSender(req *http.Request) (future ZonesDeleteFuture, err error) {
|
|
||||||
sender := autorest.DecorateSender(client, azure.DoRetryWithRegistration(client.Client))
|
|
||||||
future.Future = azure.NewFuture(req)
|
|
||||||
future.req = req
|
|
||||||
_, err = future.Done(sender)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = autorest.Respond(future.Response(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted, http.StatusNoContent))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteResponder handles the response to the Delete request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client ZonesClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted, http.StatusNoContent),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = resp
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets a DNS zone. Retrieves the zone properties, but not the record sets within the zone.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. zoneName is the name of the DNS zone (without a terminating
|
|
||||||
// dot).
|
|
||||||
func (client ZonesClient) Get(ctx context.Context, resourceGroupName string, zoneName string) (result Zone, err error) {
|
|
||||||
req, err := client.GetPreparer(ctx, resourceGroupName, zoneName)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "Get", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.GetSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "Get", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = client.GetResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "Get", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPreparer prepares the Get request.
|
|
||||||
func (client ZonesClient) GetPreparer(ctx context.Context, resourceGroupName string, zoneName string) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
"zoneName": autorest.Encode("path", zoneName),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones/{zoneName}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSender sends the Get request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client ZonesClient) GetSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResponder handles the response to the Get request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client ZonesClient) GetResponder(resp *http.Response) (result Zone, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// List lists the DNS zones in all resource groups in a subscription.
|
|
||||||
//
|
|
||||||
// top is the maximum number of DNS zones to return. If not specified, returns up to 100 zones.
|
|
||||||
func (client ZonesClient) List(ctx context.Context, top *int32) (result ZoneListResultPage, err error) {
|
|
||||||
result.fn = client.listNextResults
|
|
||||||
req, err := client.ListPreparer(ctx, top)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "List", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.ListSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.zlr.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "List", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result.zlr, err = client.ListResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "List", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListPreparer prepares the List request.
|
|
||||||
func (client ZonesClient) ListPreparer(ctx context.Context, top *int32) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
if top != nil {
|
|
||||||
queryParameters["$top"] = autorest.Encode("query", *top)
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Network/dnszones", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListSender sends the List request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client ZonesClient) ListSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListResponder handles the response to the List request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client ZonesClient) ListResponder(resp *http.Response) (result ZoneListResult, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// listNextResults retrieves the next set of results, if any.
|
|
||||||
func (client ZonesClient) listNextResults(lastResults ZoneListResult) (result ZoneListResult, err error) {
|
|
||||||
req, err := lastResults.zoneListResultPreparer()
|
|
||||||
if err != nil {
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.ZonesClient", "listNextResults", nil, "Failure preparing next results request")
|
|
||||||
}
|
|
||||||
if req == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, err := client.ListSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.ZonesClient", "listNextResults", resp, "Failure sending next results request")
|
|
||||||
}
|
|
||||||
result, err = client.ListResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "listNextResults", resp, "Failure responding to next results request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListComplete enumerates all values, automatically crossing page boundaries as required.
|
|
||||||
func (client ZonesClient) ListComplete(ctx context.Context, top *int32) (result ZoneListResultIterator, err error) {
|
|
||||||
result.page, err = client.List(ctx, top)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByResourceGroup lists the DNS zones within a resource group.
|
|
||||||
//
|
|
||||||
// resourceGroupName is the name of the resource group. top is the maximum number of record sets to return. If not
|
|
||||||
// specified, returns up to 100 record sets.
|
|
||||||
func (client ZonesClient) ListByResourceGroup(ctx context.Context, resourceGroupName string, top *int32) (result ZoneListResultPage, err error) {
|
|
||||||
result.fn = client.listByResourceGroupNextResults
|
|
||||||
req, err := client.ListByResourceGroupPreparer(ctx, resourceGroupName, top)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "ListByResourceGroup", nil, "Failure preparing request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.ListByResourceGroupSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.zlr.Response = autorest.Response{Response: resp}
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "ListByResourceGroup", resp, "Failure sending request")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result.zlr, err = client.ListByResourceGroupResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "ListByResourceGroup", resp, "Failure responding to request")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByResourceGroupPreparer prepares the ListByResourceGroup request.
|
|
||||||
func (client ZonesClient) ListByResourceGroupPreparer(ctx context.Context, resourceGroupName string, top *int32) (*http.Request, error) {
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
|
||||||
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2017-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
if top != nil {
|
|
||||||
queryParameters["$top"] = autorest.Encode("query", *top)
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(client.BaseURI),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/dnsZones", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters))
|
|
||||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByResourceGroupSender sends the ListByResourceGroup request. The method will close the
|
|
||||||
// http.Response Body if it receives an error.
|
|
||||||
func (client ZonesClient) ListByResourceGroupSender(req *http.Request) (*http.Response, error) {
|
|
||||||
return autorest.SendWithSender(client, req,
|
|
||||||
azure.DoRetryWithRegistration(client.Client))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByResourceGroupResponder handles the response to the ListByResourceGroup request. The method always
|
|
||||||
// closes the http.Response Body.
|
|
||||||
func (client ZonesClient) ListByResourceGroupResponder(resp *http.Response) (result ZoneListResult, err error) {
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
client.ByInspecting(),
|
|
||||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&result),
|
|
||||||
autorest.ByClosing())
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// listByResourceGroupNextResults retrieves the next set of results, if any.
|
|
||||||
func (client ZonesClient) listByResourceGroupNextResults(lastResults ZoneListResult) (result ZoneListResult, err error) {
|
|
||||||
req, err := lastResults.zoneListResultPreparer()
|
|
||||||
if err != nil {
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.ZonesClient", "listByResourceGroupNextResults", nil, "Failure preparing next results request")
|
|
||||||
}
|
|
||||||
if req == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, err := client.ListByResourceGroupSender(req)
|
|
||||||
if err != nil {
|
|
||||||
result.Response = autorest.Response{Response: resp}
|
|
||||||
return result, autorest.NewErrorWithError(err, "dns.ZonesClient", "listByResourceGroupNextResults", resp, "Failure sending next results request")
|
|
||||||
}
|
|
||||||
result, err = client.ListByResourceGroupResponder(resp)
|
|
||||||
if err != nil {
|
|
||||||
err = autorest.NewErrorWithError(err, "dns.ZonesClient", "listByResourceGroupNextResults", resp, "Failure responding to next results request")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListByResourceGroupComplete enumerates all values, automatically crossing page boundaries as required.
|
|
||||||
func (client ZonesClient) ListByResourceGroupComplete(ctx context.Context, resourceGroupName string, top *int32) (result ZoneListResultIterator, err error) {
|
|
||||||
result.page, err = client.ListByResourceGroup(ctx, resourceGroupName, top)
|
|
||||||
return
|
|
||||||
}
|
|
21
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
21
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
package version
|
|
||||||
|
|
||||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
|
||||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
|
||||||
|
|
||||||
// Number contains the semantic version of this SDK.
|
|
||||||
const Number = "v15.0.1"
|
|
21
vendor/github.com/Azure/go-ansiterm/LICENSE
generated
vendored
21
vendor/github.com/Azure/go-ansiterm/LICENSE
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 Microsoft Corporation
|
|
||||||
|
|
||||||
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.
|
|
188
vendor/github.com/Azure/go-ansiterm/constants.go
generated
vendored
188
vendor/github.com/Azure/go-ansiterm/constants.go
generated
vendored
|
@ -1,188 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
const LogEnv = "DEBUG_TERMINAL"
|
|
||||||
|
|
||||||
// ANSI constants
|
|
||||||
// References:
|
|
||||||
// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm
|
|
||||||
// -- http://man7.org/linux/man-pages/man4/console_codes.4.html
|
|
||||||
// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html
|
|
||||||
// -- http://en.wikipedia.org/wiki/ANSI_escape_code
|
|
||||||
// -- http://vt100.net/emu/dec_ansi_parser
|
|
||||||
// -- http://vt100.net/emu/vt500_parser.svg
|
|
||||||
// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
|
||||||
// -- http://www.inwap.com/pdp10/ansicode.txt
|
|
||||||
const (
|
|
||||||
// ECMA-48 Set Graphics Rendition
|
|
||||||
// Note:
|
|
||||||
// -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved
|
|
||||||
// -- Fonts could possibly be supported via SetCurrentConsoleFontEx
|
|
||||||
// -- Windows does not expose the per-window cursor (i.e., caret) blink times
|
|
||||||
ANSI_SGR_RESET = 0
|
|
||||||
ANSI_SGR_BOLD = 1
|
|
||||||
ANSI_SGR_DIM = 2
|
|
||||||
_ANSI_SGR_ITALIC = 3
|
|
||||||
ANSI_SGR_UNDERLINE = 4
|
|
||||||
_ANSI_SGR_BLINKSLOW = 5
|
|
||||||
_ANSI_SGR_BLINKFAST = 6
|
|
||||||
ANSI_SGR_REVERSE = 7
|
|
||||||
_ANSI_SGR_INVISIBLE = 8
|
|
||||||
_ANSI_SGR_LINETHROUGH = 9
|
|
||||||
_ANSI_SGR_FONT_00 = 10
|
|
||||||
_ANSI_SGR_FONT_01 = 11
|
|
||||||
_ANSI_SGR_FONT_02 = 12
|
|
||||||
_ANSI_SGR_FONT_03 = 13
|
|
||||||
_ANSI_SGR_FONT_04 = 14
|
|
||||||
_ANSI_SGR_FONT_05 = 15
|
|
||||||
_ANSI_SGR_FONT_06 = 16
|
|
||||||
_ANSI_SGR_FONT_07 = 17
|
|
||||||
_ANSI_SGR_FONT_08 = 18
|
|
||||||
_ANSI_SGR_FONT_09 = 19
|
|
||||||
_ANSI_SGR_FONT_10 = 20
|
|
||||||
_ANSI_SGR_DOUBLEUNDERLINE = 21
|
|
||||||
ANSI_SGR_BOLD_DIM_OFF = 22
|
|
||||||
_ANSI_SGR_ITALIC_OFF = 23
|
|
||||||
ANSI_SGR_UNDERLINE_OFF = 24
|
|
||||||
_ANSI_SGR_BLINK_OFF = 25
|
|
||||||
_ANSI_SGR_RESERVED_00 = 26
|
|
||||||
ANSI_SGR_REVERSE_OFF = 27
|
|
||||||
_ANSI_SGR_INVISIBLE_OFF = 28
|
|
||||||
_ANSI_SGR_LINETHROUGH_OFF = 29
|
|
||||||
ANSI_SGR_FOREGROUND_BLACK = 30
|
|
||||||
ANSI_SGR_FOREGROUND_RED = 31
|
|
||||||
ANSI_SGR_FOREGROUND_GREEN = 32
|
|
||||||
ANSI_SGR_FOREGROUND_YELLOW = 33
|
|
||||||
ANSI_SGR_FOREGROUND_BLUE = 34
|
|
||||||
ANSI_SGR_FOREGROUND_MAGENTA = 35
|
|
||||||
ANSI_SGR_FOREGROUND_CYAN = 36
|
|
||||||
ANSI_SGR_FOREGROUND_WHITE = 37
|
|
||||||
_ANSI_SGR_RESERVED_01 = 38
|
|
||||||
ANSI_SGR_FOREGROUND_DEFAULT = 39
|
|
||||||
ANSI_SGR_BACKGROUND_BLACK = 40
|
|
||||||
ANSI_SGR_BACKGROUND_RED = 41
|
|
||||||
ANSI_SGR_BACKGROUND_GREEN = 42
|
|
||||||
ANSI_SGR_BACKGROUND_YELLOW = 43
|
|
||||||
ANSI_SGR_BACKGROUND_BLUE = 44
|
|
||||||
ANSI_SGR_BACKGROUND_MAGENTA = 45
|
|
||||||
ANSI_SGR_BACKGROUND_CYAN = 46
|
|
||||||
ANSI_SGR_BACKGROUND_WHITE = 47
|
|
||||||
_ANSI_SGR_RESERVED_02 = 48
|
|
||||||
ANSI_SGR_BACKGROUND_DEFAULT = 49
|
|
||||||
// 50 - 65: Unsupported
|
|
||||||
|
|
||||||
ANSI_MAX_CMD_LENGTH = 4096
|
|
||||||
|
|
||||||
MAX_INPUT_EVENTS = 128
|
|
||||||
DEFAULT_WIDTH = 80
|
|
||||||
DEFAULT_HEIGHT = 24
|
|
||||||
|
|
||||||
ANSI_BEL = 0x07
|
|
||||||
ANSI_BACKSPACE = 0x08
|
|
||||||
ANSI_TAB = 0x09
|
|
||||||
ANSI_LINE_FEED = 0x0A
|
|
||||||
ANSI_VERTICAL_TAB = 0x0B
|
|
||||||
ANSI_FORM_FEED = 0x0C
|
|
||||||
ANSI_CARRIAGE_RETURN = 0x0D
|
|
||||||
ANSI_ESCAPE_PRIMARY = 0x1B
|
|
||||||
ANSI_ESCAPE_SECONDARY = 0x5B
|
|
||||||
ANSI_OSC_STRING_ENTRY = 0x5D
|
|
||||||
ANSI_COMMAND_FIRST = 0x40
|
|
||||||
ANSI_COMMAND_LAST = 0x7E
|
|
||||||
DCS_ENTRY = 0x90
|
|
||||||
CSI_ENTRY = 0x9B
|
|
||||||
OSC_STRING = 0x9D
|
|
||||||
ANSI_PARAMETER_SEP = ";"
|
|
||||||
ANSI_CMD_G0 = '('
|
|
||||||
ANSI_CMD_G1 = ')'
|
|
||||||
ANSI_CMD_G2 = '*'
|
|
||||||
ANSI_CMD_G3 = '+'
|
|
||||||
ANSI_CMD_DECPNM = '>'
|
|
||||||
ANSI_CMD_DECPAM = '='
|
|
||||||
ANSI_CMD_OSC = ']'
|
|
||||||
ANSI_CMD_STR_TERM = '\\'
|
|
||||||
|
|
||||||
KEY_CONTROL_PARAM_2 = ";2"
|
|
||||||
KEY_CONTROL_PARAM_3 = ";3"
|
|
||||||
KEY_CONTROL_PARAM_4 = ";4"
|
|
||||||
KEY_CONTROL_PARAM_5 = ";5"
|
|
||||||
KEY_CONTROL_PARAM_6 = ";6"
|
|
||||||
KEY_CONTROL_PARAM_7 = ";7"
|
|
||||||
KEY_CONTROL_PARAM_8 = ";8"
|
|
||||||
KEY_ESC_CSI = "\x1B["
|
|
||||||
KEY_ESC_N = "\x1BN"
|
|
||||||
KEY_ESC_O = "\x1BO"
|
|
||||||
|
|
||||||
FILL_CHARACTER = ' '
|
|
||||||
)
|
|
||||||
|
|
||||||
func getByteRange(start byte, end byte) []byte {
|
|
||||||
bytes := make([]byte, 0, 32)
|
|
||||||
for i := start; i <= end; i++ {
|
|
||||||
bytes = append(bytes, byte(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
var toGroundBytes = getToGroundBytes()
|
|
||||||
var executors = getExecuteBytes()
|
|
||||||
|
|
||||||
// SPACE 20+A0 hex Always and everywhere a blank space
|
|
||||||
// Intermediate 20-2F hex !"#$%&'()*+,-./
|
|
||||||
var intermeds = getByteRange(0x20, 0x2F)
|
|
||||||
|
|
||||||
// Parameters 30-3F hex 0123456789:;<=>?
|
|
||||||
// CSI Parameters 30-39, 3B hex 0123456789;
|
|
||||||
var csiParams = getByteRange(0x30, 0x3F)
|
|
||||||
|
|
||||||
var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...)
|
|
||||||
|
|
||||||
// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
|
|
||||||
var upperCase = getByteRange(0x40, 0x5F)
|
|
||||||
|
|
||||||
// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~
|
|
||||||
var lowerCase = getByteRange(0x60, 0x7E)
|
|
||||||
|
|
||||||
// Alphabetics 40-7E hex (all of upper and lower case)
|
|
||||||
var alphabetics = append(upperCase, lowerCase...)
|
|
||||||
|
|
||||||
var printables = getByteRange(0x20, 0x7F)
|
|
||||||
|
|
||||||
var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E)
|
|
||||||
var escapeToGroundBytes = getEscapeToGroundBytes()
|
|
||||||
|
|
||||||
// See http://www.vt100.net/emu/vt500_parser.png for description of the complex
|
|
||||||
// byte ranges below
|
|
||||||
|
|
||||||
func getEscapeToGroundBytes() []byte {
|
|
||||||
escapeToGroundBytes := getByteRange(0x30, 0x4F)
|
|
||||||
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...)
|
|
||||||
escapeToGroundBytes = append(escapeToGroundBytes, 0x59)
|
|
||||||
escapeToGroundBytes = append(escapeToGroundBytes, 0x5A)
|
|
||||||
escapeToGroundBytes = append(escapeToGroundBytes, 0x5C)
|
|
||||||
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...)
|
|
||||||
return escapeToGroundBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func getExecuteBytes() []byte {
|
|
||||||
executeBytes := getByteRange(0x00, 0x17)
|
|
||||||
executeBytes = append(executeBytes, 0x19)
|
|
||||||
executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...)
|
|
||||||
return executeBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func getToGroundBytes() []byte {
|
|
||||||
groundBytes := []byte{0x18}
|
|
||||||
groundBytes = append(groundBytes, 0x1A)
|
|
||||||
groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...)
|
|
||||||
groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...)
|
|
||||||
groundBytes = append(groundBytes, 0x99)
|
|
||||||
groundBytes = append(groundBytes, 0x9A)
|
|
||||||
groundBytes = append(groundBytes, 0x9C)
|
|
||||||
return groundBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 7F hex Always and everywhere ignored
|
|
||||||
// C1 Control 80-9F hex 32 additional control characters
|
|
||||||
// G1 Displayable A1-FE hex 94 additional displayable characters
|
|
||||||
// Special A0+FF hex Same as SPACE and DELETE
|
|
7
vendor/github.com/Azure/go-ansiterm/context.go
generated
vendored
7
vendor/github.com/Azure/go-ansiterm/context.go
generated
vendored
|
@ -1,7 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type ansiContext struct {
|
|
||||||
currentChar byte
|
|
||||||
paramBuffer []byte
|
|
||||||
interBuffer []byte
|
|
||||||
}
|
|
49
vendor/github.com/Azure/go-ansiterm/csi_entry_state.go
generated
vendored
49
vendor/github.com/Azure/go-ansiterm/csi_entry_state.go
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type csiEntryState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (csiState csiEntryState) Handle(b byte) (s state, e error) {
|
|
||||||
csiState.parser.logf("CsiEntry::Handle %#x", b)
|
|
||||||
|
|
||||||
nextState, err := csiState.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case sliceContains(alphabetics, b):
|
|
||||||
return csiState.parser.ground, nil
|
|
||||||
case sliceContains(csiCollectables, b):
|
|
||||||
return csiState.parser.csiParam, nil
|
|
||||||
case sliceContains(executors, b):
|
|
||||||
return csiState, csiState.parser.execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
return csiState, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (csiState csiEntryState) Transition(s state) error {
|
|
||||||
csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
|
|
||||||
csiState.baseState.Transition(s)
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case csiState.parser.ground:
|
|
||||||
return csiState.parser.csiDispatch()
|
|
||||||
case csiState.parser.csiParam:
|
|
||||||
switch {
|
|
||||||
case sliceContains(csiParams, csiState.parser.context.currentChar):
|
|
||||||
csiState.parser.collectParam()
|
|
||||||
case sliceContains(intermeds, csiState.parser.context.currentChar):
|
|
||||||
csiState.parser.collectInter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (csiState csiEntryState) Enter() error {
|
|
||||||
csiState.parser.clear()
|
|
||||||
return nil
|
|
||||||
}
|
|
38
vendor/github.com/Azure/go-ansiterm/csi_param_state.go
generated
vendored
38
vendor/github.com/Azure/go-ansiterm/csi_param_state.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type csiParamState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (csiState csiParamState) Handle(b byte) (s state, e error) {
|
|
||||||
csiState.parser.logf("CsiParam::Handle %#x", b)
|
|
||||||
|
|
||||||
nextState, err := csiState.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case sliceContains(alphabetics, b):
|
|
||||||
return csiState.parser.ground, nil
|
|
||||||
case sliceContains(csiCollectables, b):
|
|
||||||
csiState.parser.collectParam()
|
|
||||||
return csiState, nil
|
|
||||||
case sliceContains(executors, b):
|
|
||||||
return csiState, csiState.parser.execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
return csiState, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (csiState csiParamState) Transition(s state) error {
|
|
||||||
csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
|
|
||||||
csiState.baseState.Transition(s)
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case csiState.parser.ground:
|
|
||||||
return csiState.parser.csiDispatch()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
36
vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go
generated
vendored
36
vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go
generated
vendored
|
@ -1,36 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type escapeIntermediateState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
|
|
||||||
escState.parser.logf("escapeIntermediateState::Handle %#x", b)
|
|
||||||
nextState, err := escState.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case sliceContains(intermeds, b):
|
|
||||||
return escState, escState.parser.collectInter()
|
|
||||||
case sliceContains(executors, b):
|
|
||||||
return escState, escState.parser.execute()
|
|
||||||
case sliceContains(escapeIntermediateToGroundBytes, b):
|
|
||||||
return escState.parser.ground, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return escState, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (escState escapeIntermediateState) Transition(s state) error {
|
|
||||||
escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
|
|
||||||
escState.baseState.Transition(s)
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case escState.parser.ground:
|
|
||||||
return escState.parser.escDispatch()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
47
vendor/github.com/Azure/go-ansiterm/escape_state.go
generated
vendored
47
vendor/github.com/Azure/go-ansiterm/escape_state.go
generated
vendored
|
@ -1,47 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type escapeState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (escState escapeState) Handle(b byte) (s state, e error) {
|
|
||||||
escState.parser.logf("escapeState::Handle %#x", b)
|
|
||||||
nextState, err := escState.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case b == ANSI_ESCAPE_SECONDARY:
|
|
||||||
return escState.parser.csiEntry, nil
|
|
||||||
case b == ANSI_OSC_STRING_ENTRY:
|
|
||||||
return escState.parser.oscString, nil
|
|
||||||
case sliceContains(executors, b):
|
|
||||||
return escState, escState.parser.execute()
|
|
||||||
case sliceContains(escapeToGroundBytes, b):
|
|
||||||
return escState.parser.ground, nil
|
|
||||||
case sliceContains(intermeds, b):
|
|
||||||
return escState.parser.escapeIntermediate, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return escState, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (escState escapeState) Transition(s state) error {
|
|
||||||
escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name())
|
|
||||||
escState.baseState.Transition(s)
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case escState.parser.ground:
|
|
||||||
return escState.parser.escDispatch()
|
|
||||||
case escState.parser.escapeIntermediate:
|
|
||||||
return escState.parser.collectInter()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (escState escapeState) Enter() error {
|
|
||||||
escState.parser.clear()
|
|
||||||
return nil
|
|
||||||
}
|
|
90
vendor/github.com/Azure/go-ansiterm/event_handler.go
generated
vendored
90
vendor/github.com/Azure/go-ansiterm/event_handler.go
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type AnsiEventHandler interface {
|
|
||||||
// Print
|
|
||||||
Print(b byte) error
|
|
||||||
|
|
||||||
// Execute C0 commands
|
|
||||||
Execute(b byte) error
|
|
||||||
|
|
||||||
// CUrsor Up
|
|
||||||
CUU(int) error
|
|
||||||
|
|
||||||
// CUrsor Down
|
|
||||||
CUD(int) error
|
|
||||||
|
|
||||||
// CUrsor Forward
|
|
||||||
CUF(int) error
|
|
||||||
|
|
||||||
// CUrsor Backward
|
|
||||||
CUB(int) error
|
|
||||||
|
|
||||||
// Cursor to Next Line
|
|
||||||
CNL(int) error
|
|
||||||
|
|
||||||
// Cursor to Previous Line
|
|
||||||
CPL(int) error
|
|
||||||
|
|
||||||
// Cursor Horizontal position Absolute
|
|
||||||
CHA(int) error
|
|
||||||
|
|
||||||
// Vertical line Position Absolute
|
|
||||||
VPA(int) error
|
|
||||||
|
|
||||||
// CUrsor Position
|
|
||||||
CUP(int, int) error
|
|
||||||
|
|
||||||
// Horizontal and Vertical Position (depends on PUM)
|
|
||||||
HVP(int, int) error
|
|
||||||
|
|
||||||
// Text Cursor Enable Mode
|
|
||||||
DECTCEM(bool) error
|
|
||||||
|
|
||||||
// Origin Mode
|
|
||||||
DECOM(bool) error
|
|
||||||
|
|
||||||
// 132 Column Mode
|
|
||||||
DECCOLM(bool) error
|
|
||||||
|
|
||||||
// Erase in Display
|
|
||||||
ED(int) error
|
|
||||||
|
|
||||||
// Erase in Line
|
|
||||||
EL(int) error
|
|
||||||
|
|
||||||
// Insert Line
|
|
||||||
IL(int) error
|
|
||||||
|
|
||||||
// Delete Line
|
|
||||||
DL(int) error
|
|
||||||
|
|
||||||
// Insert Character
|
|
||||||
ICH(int) error
|
|
||||||
|
|
||||||
// Delete Character
|
|
||||||
DCH(int) error
|
|
||||||
|
|
||||||
// Set Graphics Rendition
|
|
||||||
SGR([]int) error
|
|
||||||
|
|
||||||
// Pan Down
|
|
||||||
SU(int) error
|
|
||||||
|
|
||||||
// Pan Up
|
|
||||||
SD(int) error
|
|
||||||
|
|
||||||
// Device Attributes
|
|
||||||
DA([]string) error
|
|
||||||
|
|
||||||
// Set Top and Bottom Margins
|
|
||||||
DECSTBM(int, int) error
|
|
||||||
|
|
||||||
// Index
|
|
||||||
IND() error
|
|
||||||
|
|
||||||
// Reverse Index
|
|
||||||
RI() error
|
|
||||||
|
|
||||||
// Flush updates from previous commands
|
|
||||||
Flush() error
|
|
||||||
}
|
|
24
vendor/github.com/Azure/go-ansiterm/ground_state.go
generated
vendored
24
vendor/github.com/Azure/go-ansiterm/ground_state.go
generated
vendored
|
@ -1,24 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type groundState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gs groundState) Handle(b byte) (s state, e error) {
|
|
||||||
gs.parser.context.currentChar = b
|
|
||||||
|
|
||||||
nextState, err := gs.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case sliceContains(printables, b):
|
|
||||||
return gs, gs.parser.print()
|
|
||||||
|
|
||||||
case sliceContains(executors, b):
|
|
||||||
return gs, gs.parser.execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
return gs, nil
|
|
||||||
}
|
|
31
vendor/github.com/Azure/go-ansiterm/osc_string_state.go
generated
vendored
31
vendor/github.com/Azure/go-ansiterm/osc_string_state.go
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type oscStringState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (oscState oscStringState) Handle(b byte) (s state, e error) {
|
|
||||||
oscState.parser.logf("OscString::Handle %#x", b)
|
|
||||||
nextState, err := oscState.baseState.Handle(b)
|
|
||||||
if nextState != nil || err != nil {
|
|
||||||
return nextState, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case isOscStringTerminator(b):
|
|
||||||
return oscState.parser.ground, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return oscState, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// See below for OSC string terminators for linux
|
|
||||||
// http://man7.org/linux/man-pages/man4/console_codes.4.html
|
|
||||||
func isOscStringTerminator(b byte) bool {
|
|
||||||
|
|
||||||
if b == ANSI_BEL || b == 0x5C {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
151
vendor/github.com/Azure/go-ansiterm/parser.go
generated
vendored
151
vendor/github.com/Azure/go-ansiterm/parser.go
generated
vendored
|
@ -1,151 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AnsiParser struct {
|
|
||||||
currState state
|
|
||||||
eventHandler AnsiEventHandler
|
|
||||||
context *ansiContext
|
|
||||||
csiEntry state
|
|
||||||
csiParam state
|
|
||||||
dcsEntry state
|
|
||||||
escape state
|
|
||||||
escapeIntermediate state
|
|
||||||
error state
|
|
||||||
ground state
|
|
||||||
oscString state
|
|
||||||
stateMap []state
|
|
||||||
|
|
||||||
logf func(string, ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(*AnsiParser)
|
|
||||||
|
|
||||||
func WithLogf(f func(string, ...interface{})) Option {
|
|
||||||
return func(ap *AnsiParser) {
|
|
||||||
ap.logf = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser {
|
|
||||||
ap := &AnsiParser{
|
|
||||||
eventHandler: evtHandler,
|
|
||||||
context: &ansiContext{},
|
|
||||||
}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(ap)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
|
|
||||||
logFile, _ := os.Create("ansiParser.log")
|
|
||||||
logger := log.New(logFile, "", log.LstdFlags)
|
|
||||||
if ap.logf != nil {
|
|
||||||
l := ap.logf
|
|
||||||
ap.logf = func(s string, v ...interface{}) {
|
|
||||||
l(s, v...)
|
|
||||||
logger.Printf(s, v...)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ap.logf = logger.Printf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ap.logf == nil {
|
|
||||||
ap.logf = func(string, ...interface{}) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
|
|
||||||
ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}}
|
|
||||||
ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}}
|
|
||||||
ap.escape = escapeState{baseState{name: "Escape", parser: ap}}
|
|
||||||
ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}}
|
|
||||||
ap.error = errorState{baseState{name: "Error", parser: ap}}
|
|
||||||
ap.ground = groundState{baseState{name: "Ground", parser: ap}}
|
|
||||||
ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}}
|
|
||||||
|
|
||||||
ap.stateMap = []state{
|
|
||||||
ap.csiEntry,
|
|
||||||
ap.csiParam,
|
|
||||||
ap.dcsEntry,
|
|
||||||
ap.escape,
|
|
||||||
ap.escapeIntermediate,
|
|
||||||
ap.error,
|
|
||||||
ap.ground,
|
|
||||||
ap.oscString,
|
|
||||||
}
|
|
||||||
|
|
||||||
ap.currState = getState(initialState, ap.stateMap)
|
|
||||||
|
|
||||||
ap.logf("CreateParser: parser %p", ap)
|
|
||||||
return ap
|
|
||||||
}
|
|
||||||
|
|
||||||
func getState(name string, states []state) state {
|
|
||||||
for _, el := range states {
|
|
||||||
if el.Name() == name {
|
|
||||||
return el
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) Parse(bytes []byte) (int, error) {
|
|
||||||
for i, b := range bytes {
|
|
||||||
if err := ap.handle(b); err != nil {
|
|
||||||
return i, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(bytes), ap.eventHandler.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) handle(b byte) error {
|
|
||||||
ap.context.currentChar = b
|
|
||||||
newState, err := ap.currState.Handle(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if newState == nil {
|
|
||||||
ap.logf("WARNING: newState is nil")
|
|
||||||
return errors.New("New state of 'nil' is invalid.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if newState != ap.currState {
|
|
||||||
if err := ap.changeState(newState); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) changeState(newState state) error {
|
|
||||||
ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
|
|
||||||
|
|
||||||
// Exit old state
|
|
||||||
if err := ap.currState.Exit(); err != nil {
|
|
||||||
ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform transition action
|
|
||||||
if err := ap.currState.Transition(newState); err != nil {
|
|
||||||
ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enter new state
|
|
||||||
if err := newState.Enter(); err != nil {
|
|
||||||
ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ap.currState = newState
|
|
||||||
return nil
|
|
||||||
}
|
|
99
vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go
generated
vendored
99
vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go
generated
vendored
|
@ -1,99 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseParams(bytes []byte) ([]string, error) {
|
|
||||||
paramBuff := make([]byte, 0, 0)
|
|
||||||
params := []string{}
|
|
||||||
|
|
||||||
for _, v := range bytes {
|
|
||||||
if v == ';' {
|
|
||||||
if len(paramBuff) > 0 {
|
|
||||||
// Completed parameter, append it to the list
|
|
||||||
s := string(paramBuff)
|
|
||||||
params = append(params, s)
|
|
||||||
paramBuff = make([]byte, 0, 0)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
paramBuff = append(paramBuff, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last parameter may not be terminated with ';'
|
|
||||||
if len(paramBuff) > 0 {
|
|
||||||
s := string(paramBuff)
|
|
||||||
params = append(params, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
return params, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseCmd(context ansiContext) (string, error) {
|
|
||||||
return string(context.currentChar), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInt(params []string, dflt int) int {
|
|
||||||
i := getInts(params, 1, dflt)[0]
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInts(params []string, minCount int, dflt int) []int {
|
|
||||||
ints := []int{}
|
|
||||||
|
|
||||||
for _, v := range params {
|
|
||||||
i, _ := strconv.Atoi(v)
|
|
||||||
// Zero is mapped to the default value in VT100.
|
|
||||||
if i == 0 {
|
|
||||||
i = dflt
|
|
||||||
}
|
|
||||||
ints = append(ints, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ints) < minCount {
|
|
||||||
remaining := minCount - len(ints)
|
|
||||||
for i := 0; i < remaining; i++ {
|
|
||||||
ints = append(ints, dflt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ints
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) modeDispatch(param string, set bool) error {
|
|
||||||
switch param {
|
|
||||||
case "?3":
|
|
||||||
return ap.eventHandler.DECCOLM(set)
|
|
||||||
case "?6":
|
|
||||||
return ap.eventHandler.DECOM(set)
|
|
||||||
case "?25":
|
|
||||||
return ap.eventHandler.DECTCEM(set)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) hDispatch(params []string) error {
|
|
||||||
if len(params) == 1 {
|
|
||||||
return ap.modeDispatch(params[0], true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) lDispatch(params []string) error {
|
|
||||||
if len(params) == 1 {
|
|
||||||
return ap.modeDispatch(params[0], false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEraseParam(params []string) int {
|
|
||||||
param := getInt(params, 0)
|
|
||||||
if param < 0 || 3 < param {
|
|
||||||
param = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return param
|
|
||||||
}
|
|
119
vendor/github.com/Azure/go-ansiterm/parser_actions.go
generated
vendored
119
vendor/github.com/Azure/go-ansiterm/parser_actions.go
generated
vendored
|
@ -1,119 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
func (ap *AnsiParser) collectParam() error {
|
|
||||||
currChar := ap.context.currentChar
|
|
||||||
ap.logf("collectParam %#x", currChar)
|
|
||||||
ap.context.paramBuffer = append(ap.context.paramBuffer, currChar)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) collectInter() error {
|
|
||||||
currChar := ap.context.currentChar
|
|
||||||
ap.logf("collectInter %#x", currChar)
|
|
||||||
ap.context.paramBuffer = append(ap.context.interBuffer, currChar)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) escDispatch() error {
|
|
||||||
cmd, _ := parseCmd(*ap.context)
|
|
||||||
intermeds := ap.context.interBuffer
|
|
||||||
ap.logf("escDispatch currentChar: %#x", ap.context.currentChar)
|
|
||||||
ap.logf("escDispatch: %v(%v)", cmd, intermeds)
|
|
||||||
|
|
||||||
switch cmd {
|
|
||||||
case "D": // IND
|
|
||||||
return ap.eventHandler.IND()
|
|
||||||
case "E": // NEL, equivalent to CRLF
|
|
||||||
err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN)
|
|
||||||
if err == nil {
|
|
||||||
err = ap.eventHandler.Execute(ANSI_LINE_FEED)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
case "M": // RI
|
|
||||||
return ap.eventHandler.RI()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) csiDispatch() error {
|
|
||||||
cmd, _ := parseCmd(*ap.context)
|
|
||||||
params, _ := parseParams(ap.context.paramBuffer)
|
|
||||||
ap.logf("Parsed params: %v with length: %d", params, len(params))
|
|
||||||
|
|
||||||
ap.logf("csiDispatch: %v(%v)", cmd, params)
|
|
||||||
|
|
||||||
switch cmd {
|
|
||||||
case "@":
|
|
||||||
return ap.eventHandler.ICH(getInt(params, 1))
|
|
||||||
case "A":
|
|
||||||
return ap.eventHandler.CUU(getInt(params, 1))
|
|
||||||
case "B":
|
|
||||||
return ap.eventHandler.CUD(getInt(params, 1))
|
|
||||||
case "C":
|
|
||||||
return ap.eventHandler.CUF(getInt(params, 1))
|
|
||||||
case "D":
|
|
||||||
return ap.eventHandler.CUB(getInt(params, 1))
|
|
||||||
case "E":
|
|
||||||
return ap.eventHandler.CNL(getInt(params, 1))
|
|
||||||
case "F":
|
|
||||||
return ap.eventHandler.CPL(getInt(params, 1))
|
|
||||||
case "G":
|
|
||||||
return ap.eventHandler.CHA(getInt(params, 1))
|
|
||||||
case "H":
|
|
||||||
ints := getInts(params, 2, 1)
|
|
||||||
x, y := ints[0], ints[1]
|
|
||||||
return ap.eventHandler.CUP(x, y)
|
|
||||||
case "J":
|
|
||||||
param := getEraseParam(params)
|
|
||||||
return ap.eventHandler.ED(param)
|
|
||||||
case "K":
|
|
||||||
param := getEraseParam(params)
|
|
||||||
return ap.eventHandler.EL(param)
|
|
||||||
case "L":
|
|
||||||
return ap.eventHandler.IL(getInt(params, 1))
|
|
||||||
case "M":
|
|
||||||
return ap.eventHandler.DL(getInt(params, 1))
|
|
||||||
case "P":
|
|
||||||
return ap.eventHandler.DCH(getInt(params, 1))
|
|
||||||
case "S":
|
|
||||||
return ap.eventHandler.SU(getInt(params, 1))
|
|
||||||
case "T":
|
|
||||||
return ap.eventHandler.SD(getInt(params, 1))
|
|
||||||
case "c":
|
|
||||||
return ap.eventHandler.DA(params)
|
|
||||||
case "d":
|
|
||||||
return ap.eventHandler.VPA(getInt(params, 1))
|
|
||||||
case "f":
|
|
||||||
ints := getInts(params, 2, 1)
|
|
||||||
x, y := ints[0], ints[1]
|
|
||||||
return ap.eventHandler.HVP(x, y)
|
|
||||||
case "h":
|
|
||||||
return ap.hDispatch(params)
|
|
||||||
case "l":
|
|
||||||
return ap.lDispatch(params)
|
|
||||||
case "m":
|
|
||||||
return ap.eventHandler.SGR(getInts(params, 1, 0))
|
|
||||||
case "r":
|
|
||||||
ints := getInts(params, 2, 1)
|
|
||||||
top, bottom := ints[0], ints[1]
|
|
||||||
return ap.eventHandler.DECSTBM(top, bottom)
|
|
||||||
default:
|
|
||||||
ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) print() error {
|
|
||||||
return ap.eventHandler.Print(ap.context.currentChar)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) clear() error {
|
|
||||||
ap.context = &ansiContext{}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ap *AnsiParser) execute() error {
|
|
||||||
return ap.eventHandler.Execute(ap.context.currentChar)
|
|
||||||
}
|
|
71
vendor/github.com/Azure/go-ansiterm/states.go
generated
vendored
71
vendor/github.com/Azure/go-ansiterm/states.go
generated
vendored
|
@ -1,71 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
type stateID int
|
|
||||||
|
|
||||||
type state interface {
|
|
||||||
Enter() error
|
|
||||||
Exit() error
|
|
||||||
Handle(byte) (state, error)
|
|
||||||
Name() string
|
|
||||||
Transition(state) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type baseState struct {
|
|
||||||
name string
|
|
||||||
parser *AnsiParser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (base baseState) Enter() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (base baseState) Exit() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (base baseState) Handle(b byte) (s state, e error) {
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case b == CSI_ENTRY:
|
|
||||||
return base.parser.csiEntry, nil
|
|
||||||
case b == DCS_ENTRY:
|
|
||||||
return base.parser.dcsEntry, nil
|
|
||||||
case b == ANSI_ESCAPE_PRIMARY:
|
|
||||||
return base.parser.escape, nil
|
|
||||||
case b == OSC_STRING:
|
|
||||||
return base.parser.oscString, nil
|
|
||||||
case sliceContains(toGroundBytes, b):
|
|
||||||
return base.parser.ground, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (base baseState) Name() string {
|
|
||||||
return base.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (base baseState) Transition(s state) error {
|
|
||||||
if s == base.parser.ground {
|
|
||||||
execBytes := []byte{0x18}
|
|
||||||
execBytes = append(execBytes, 0x1A)
|
|
||||||
execBytes = append(execBytes, getByteRange(0x80, 0x8F)...)
|
|
||||||
execBytes = append(execBytes, getByteRange(0x91, 0x97)...)
|
|
||||||
execBytes = append(execBytes, 0x99)
|
|
||||||
execBytes = append(execBytes, 0x9A)
|
|
||||||
|
|
||||||
if sliceContains(execBytes, base.parser.context.currentChar) {
|
|
||||||
return base.parser.execute()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type dcsEntryState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorState struct {
|
|
||||||
baseState
|
|
||||||
}
|
|
21
vendor/github.com/Azure/go-ansiterm/utilities.go
generated
vendored
21
vendor/github.com/Azure/go-ansiterm/utilities.go
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
package ansiterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func sliceContains(bytes []byte, b byte) bool {
|
|
||||||
for _, v := range bytes {
|
|
||||||
if v == b {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertBytesToInteger(bytes []byte) int {
|
|
||||||
s := string(bytes)
|
|
||||||
i, _ := strconv.Atoi(s)
|
|
||||||
return i
|
|
||||||
}
|
|
182
vendor/github.com/Azure/go-ansiterm/winterm/ansi.go
generated
vendored
182
vendor/github.com/Azure/go-ansiterm/winterm/ansi.go
generated
vendored
|
@ -1,182 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/Azure/go-ansiterm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Windows keyboard constants
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx.
|
|
||||||
const (
|
|
||||||
VK_PRIOR = 0x21 // PAGE UP key
|
|
||||||
VK_NEXT = 0x22 // PAGE DOWN key
|
|
||||||
VK_END = 0x23 // END key
|
|
||||||
VK_HOME = 0x24 // HOME key
|
|
||||||
VK_LEFT = 0x25 // LEFT ARROW key
|
|
||||||
VK_UP = 0x26 // UP ARROW key
|
|
||||||
VK_RIGHT = 0x27 // RIGHT ARROW key
|
|
||||||
VK_DOWN = 0x28 // DOWN ARROW key
|
|
||||||
VK_SELECT = 0x29 // SELECT key
|
|
||||||
VK_PRINT = 0x2A // PRINT key
|
|
||||||
VK_EXECUTE = 0x2B // EXECUTE key
|
|
||||||
VK_SNAPSHOT = 0x2C // PRINT SCREEN key
|
|
||||||
VK_INSERT = 0x2D // INS key
|
|
||||||
VK_DELETE = 0x2E // DEL key
|
|
||||||
VK_HELP = 0x2F // HELP key
|
|
||||||
VK_F1 = 0x70 // F1 key
|
|
||||||
VK_F2 = 0x71 // F2 key
|
|
||||||
VK_F3 = 0x72 // F3 key
|
|
||||||
VK_F4 = 0x73 // F4 key
|
|
||||||
VK_F5 = 0x74 // F5 key
|
|
||||||
VK_F6 = 0x75 // F6 key
|
|
||||||
VK_F7 = 0x76 // F7 key
|
|
||||||
VK_F8 = 0x77 // F8 key
|
|
||||||
VK_F9 = 0x78 // F9 key
|
|
||||||
VK_F10 = 0x79 // F10 key
|
|
||||||
VK_F11 = 0x7A // F11 key
|
|
||||||
VK_F12 = 0x7B // F12 key
|
|
||||||
|
|
||||||
RIGHT_ALT_PRESSED = 0x0001
|
|
||||||
LEFT_ALT_PRESSED = 0x0002
|
|
||||||
RIGHT_CTRL_PRESSED = 0x0004
|
|
||||||
LEFT_CTRL_PRESSED = 0x0008
|
|
||||||
SHIFT_PRESSED = 0x0010
|
|
||||||
NUMLOCK_ON = 0x0020
|
|
||||||
SCROLLLOCK_ON = 0x0040
|
|
||||||
CAPSLOCK_ON = 0x0080
|
|
||||||
ENHANCED_KEY = 0x0100
|
|
||||||
)
|
|
||||||
|
|
||||||
type ansiCommand struct {
|
|
||||||
CommandBytes []byte
|
|
||||||
Command string
|
|
||||||
Parameters []string
|
|
||||||
IsSpecial bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newAnsiCommand(command []byte) *ansiCommand {
|
|
||||||
|
|
||||||
if isCharacterSelectionCmdChar(command[1]) {
|
|
||||||
// Is Character Set Selection commands
|
|
||||||
return &ansiCommand{
|
|
||||||
CommandBytes: command,
|
|
||||||
Command: string(command),
|
|
||||||
IsSpecial: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// last char is command character
|
|
||||||
lastCharIndex := len(command) - 1
|
|
||||||
|
|
||||||
ac := &ansiCommand{
|
|
||||||
CommandBytes: command,
|
|
||||||
Command: string(command[lastCharIndex]),
|
|
||||||
IsSpecial: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// more than a single escape
|
|
||||||
if lastCharIndex != 0 {
|
|
||||||
start := 1
|
|
||||||
// skip if double char escape sequence
|
|
||||||
if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY {
|
|
||||||
start++
|
|
||||||
}
|
|
||||||
// convert this to GetNextParam method
|
|
||||||
ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ac
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 {
|
|
||||||
if index < 0 || index >= len(ac.Parameters) {
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
param, err := strconv.ParseInt(ac.Parameters[index], 10, 16)
|
|
||||||
if err != nil {
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return int16(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ac *ansiCommand) String() string {
|
|
||||||
return fmt.Sprintf("0x%v \"%v\" (\"%v\")",
|
|
||||||
bytesToHex(ac.CommandBytes),
|
|
||||||
ac.Command,
|
|
||||||
strings.Join(ac.Parameters, "\",\""))
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands.
|
|
||||||
// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html.
|
|
||||||
func isAnsiCommandChar(b byte) bool {
|
|
||||||
switch {
|
|
||||||
case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY:
|
|
||||||
return true
|
|
||||||
case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM:
|
|
||||||
// non-CSI escape sequence terminator
|
|
||||||
return true
|
|
||||||
case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL:
|
|
||||||
// String escape sequence terminator
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isXtermOscSequence(command []byte, current byte) bool {
|
|
||||||
return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isCharacterSelectionCmdChar(b byte) bool {
|
|
||||||
return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// bytesToHex converts a slice of bytes to a human-readable string.
|
|
||||||
func bytesToHex(b []byte) string {
|
|
||||||
hex := make([]string, len(b))
|
|
||||||
for i, ch := range b {
|
|
||||||
hex[i] = fmt.Sprintf("%X", ch)
|
|
||||||
}
|
|
||||||
return strings.Join(hex, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensureInRange adjusts the passed value, if necessary, to ensure it is within
|
|
||||||
// the passed min / max range.
|
|
||||||
func ensureInRange(n int16, min int16, max int16) int16 {
|
|
||||||
if n < min {
|
|
||||||
return min
|
|
||||||
} else if n > max {
|
|
||||||
return max
|
|
||||||
} else {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStdFile(nFile int) (*os.File, uintptr) {
|
|
||||||
var file *os.File
|
|
||||||
switch nFile {
|
|
||||||
case syscall.STD_INPUT_HANDLE:
|
|
||||||
file = os.Stdin
|
|
||||||
case syscall.STD_OUTPUT_HANDLE:
|
|
||||||
file = os.Stdout
|
|
||||||
case syscall.STD_ERROR_HANDLE:
|
|
||||||
file = os.Stderr
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
fd, err := syscall.GetStdHandle(nFile)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return file, uintptr(fd)
|
|
||||||
}
|
|
327
vendor/github.com/Azure/go-ansiterm/winterm/api.go
generated
vendored
327
vendor/github.com/Azure/go-ansiterm/winterm/api.go
generated
vendored
|
@ -1,327 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
//===========================================================================================================
|
|
||||||
// IMPORTANT NOTE:
|
|
||||||
//
|
|
||||||
// The methods below make extensive use of the "unsafe" package to obtain the required pointers.
|
|
||||||
// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack
|
|
||||||
// variables) the pointers reference *before* the API completes.
|
|
||||||
//
|
|
||||||
// As a result, in those cases, the code must hint that the variables remain in active by invoking the
|
|
||||||
// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer
|
|
||||||
// require unsafe pointers.
|
|
||||||
//
|
|
||||||
// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform
|
|
||||||
// the garbage collector the variables remain in use if:
|
|
||||||
//
|
|
||||||
// -- The value is not a pointer (e.g., int32, struct)
|
|
||||||
// -- The value is not referenced by the method after passing the pointer to Windows
|
|
||||||
//
|
|
||||||
// See http://golang.org/doc/go1.3.
|
|
||||||
//===========================================================================================================
|
|
||||||
|
|
||||||
var (
|
|
||||||
kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo")
|
|
||||||
setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo")
|
|
||||||
setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition")
|
|
||||||
setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
|
|
||||||
getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
|
|
||||||
setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
|
|
||||||
scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA")
|
|
||||||
setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
|
|
||||||
setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo")
|
|
||||||
writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW")
|
|
||||||
readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW")
|
|
||||||
waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Windows Console constants
|
|
||||||
const (
|
|
||||||
// Console modes
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
|
|
||||||
ENABLE_PROCESSED_INPUT = 0x0001
|
|
||||||
ENABLE_LINE_INPUT = 0x0002
|
|
||||||
ENABLE_ECHO_INPUT = 0x0004
|
|
||||||
ENABLE_WINDOW_INPUT = 0x0008
|
|
||||||
ENABLE_MOUSE_INPUT = 0x0010
|
|
||||||
ENABLE_INSERT_MODE = 0x0020
|
|
||||||
ENABLE_QUICK_EDIT_MODE = 0x0040
|
|
||||||
ENABLE_EXTENDED_FLAGS = 0x0080
|
|
||||||
ENABLE_AUTO_POSITION = 0x0100
|
|
||||||
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
|
|
||||||
|
|
||||||
ENABLE_PROCESSED_OUTPUT = 0x0001
|
|
||||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
|
|
||||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
|
||||||
DISABLE_NEWLINE_AUTO_RETURN = 0x0008
|
|
||||||
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
|
|
||||||
|
|
||||||
// Character attributes
|
|
||||||
// Note:
|
|
||||||
// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
|
|
||||||
// Clearing all foreground or background colors results in black; setting all creates white.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
|
|
||||||
FOREGROUND_BLUE uint16 = 0x0001
|
|
||||||
FOREGROUND_GREEN uint16 = 0x0002
|
|
||||||
FOREGROUND_RED uint16 = 0x0004
|
|
||||||
FOREGROUND_INTENSITY uint16 = 0x0008
|
|
||||||
FOREGROUND_MASK uint16 = 0x000F
|
|
||||||
|
|
||||||
BACKGROUND_BLUE uint16 = 0x0010
|
|
||||||
BACKGROUND_GREEN uint16 = 0x0020
|
|
||||||
BACKGROUND_RED uint16 = 0x0040
|
|
||||||
BACKGROUND_INTENSITY uint16 = 0x0080
|
|
||||||
BACKGROUND_MASK uint16 = 0x00F0
|
|
||||||
|
|
||||||
COMMON_LVB_MASK uint16 = 0xFF00
|
|
||||||
COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000
|
|
||||||
COMMON_LVB_UNDERSCORE uint16 = 0x8000
|
|
||||||
|
|
||||||
// Input event types
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
|
|
||||||
KEY_EVENT = 0x0001
|
|
||||||
MOUSE_EVENT = 0x0002
|
|
||||||
WINDOW_BUFFER_SIZE_EVENT = 0x0004
|
|
||||||
MENU_EVENT = 0x0008
|
|
||||||
FOCUS_EVENT = 0x0010
|
|
||||||
|
|
||||||
// WaitForSingleObject return codes
|
|
||||||
WAIT_ABANDONED = 0x00000080
|
|
||||||
WAIT_FAILED = 0xFFFFFFFF
|
|
||||||
WAIT_SIGNALED = 0x0000000
|
|
||||||
WAIT_TIMEOUT = 0x00000102
|
|
||||||
|
|
||||||
// WaitForSingleObject wait duration
|
|
||||||
WAIT_INFINITE = 0xFFFFFFFF
|
|
||||||
WAIT_ONE_SECOND = 1000
|
|
||||||
WAIT_HALF_SECOND = 500
|
|
||||||
WAIT_QUARTER_SECOND = 250
|
|
||||||
)
|
|
||||||
|
|
||||||
// Windows API Console types
|
|
||||||
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD)
|
|
||||||
// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment
|
|
||||||
type (
|
|
||||||
CHAR_INFO struct {
|
|
||||||
UnicodeChar uint16
|
|
||||||
Attributes uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSOLE_CURSOR_INFO struct {
|
|
||||||
Size uint32
|
|
||||||
Visible int32
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO struct {
|
|
||||||
Size COORD
|
|
||||||
CursorPosition COORD
|
|
||||||
Attributes uint16
|
|
||||||
Window SMALL_RECT
|
|
||||||
MaximumWindowSize COORD
|
|
||||||
}
|
|
||||||
|
|
||||||
COORD struct {
|
|
||||||
X int16
|
|
||||||
Y int16
|
|
||||||
}
|
|
||||||
|
|
||||||
SMALL_RECT struct {
|
|
||||||
Left int16
|
|
||||||
Top int16
|
|
||||||
Right int16
|
|
||||||
Bottom int16
|
|
||||||
}
|
|
||||||
|
|
||||||
// INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
|
|
||||||
INPUT_RECORD struct {
|
|
||||||
EventType uint16
|
|
||||||
KeyEvent KEY_EVENT_RECORD
|
|
||||||
}
|
|
||||||
|
|
||||||
KEY_EVENT_RECORD struct {
|
|
||||||
KeyDown int32
|
|
||||||
RepeatCount uint16
|
|
||||||
VirtualKeyCode uint16
|
|
||||||
VirtualScanCode uint16
|
|
||||||
UnicodeChar uint16
|
|
||||||
ControlKeyState uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
WINDOW_BUFFER_SIZE struct {
|
|
||||||
Size COORD
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// boolToBOOL converts a Go bool into a Windows int32.
|
|
||||||
func boolToBOOL(f bool) int32 {
|
|
||||||
if f {
|
|
||||||
return int32(1)
|
|
||||||
} else {
|
|
||||||
return int32(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx.
|
|
||||||
func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
|
|
||||||
r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleCursorInfo sets the size and visiblity of the console cursor.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx.
|
|
||||||
func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
|
|
||||||
r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleCursorPosition location of the console cursor.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx.
|
|
||||||
func SetConsoleCursorPosition(handle uintptr, coord COORD) error {
|
|
||||||
r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord))
|
|
||||||
use(coord)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConsoleMode gets the console mode for given file descriptor
|
|
||||||
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx.
|
|
||||||
func GetConsoleMode(handle uintptr) (mode uint32, err error) {
|
|
||||||
err = syscall.GetConsoleMode(syscall.Handle(handle), &mode)
|
|
||||||
return mode, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleMode sets the console mode for given file descriptor
|
|
||||||
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
|
|
||||||
func SetConsoleMode(handle uintptr, mode uint32) error {
|
|
||||||
r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0)
|
|
||||||
use(mode)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
|
|
||||||
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx.
|
|
||||||
func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
|
|
||||||
info := CONSOLE_SCREEN_BUFFER_INFO{}
|
|
||||||
err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &info, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error {
|
|
||||||
r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char)))
|
|
||||||
use(scrollRect)
|
|
||||||
use(clipRect)
|
|
||||||
use(destOrigin)
|
|
||||||
use(char)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleScreenBufferSize sets the size of the console screen buffer.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx.
|
|
||||||
func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
|
|
||||||
r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord))
|
|
||||||
use(coord)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleTextAttribute sets the attributes of characters written to the
|
|
||||||
// console screen buffer by the WriteFile or WriteConsole function.
|
|
||||||
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
|
|
||||||
func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
|
|
||||||
r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
|
|
||||||
use(attribute)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConsoleWindowInfo sets the size and position of the console screen buffer's window.
|
|
||||||
// Note that the size and location must be within and no larger than the backing console screen buffer.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx.
|
|
||||||
func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error {
|
|
||||||
r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect)))
|
|
||||||
use(isAbsolute)
|
|
||||||
use(rect)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx.
|
|
||||||
func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error {
|
|
||||||
r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))
|
|
||||||
use(buffer)
|
|
||||||
use(bufferSize)
|
|
||||||
use(bufferCoord)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadConsoleInput reads (and removes) data from the console input buffer.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx.
|
|
||||||
func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error {
|
|
||||||
r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count)))
|
|
||||||
use(buffer)
|
|
||||||
return checkError(r1, r2, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitForSingleObject waits for the passed handle to be signaled.
|
|
||||||
// It returns true if the handle was signaled; false otherwise.
|
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx.
|
|
||||||
func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) {
|
|
||||||
r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait)))
|
|
||||||
switch r1 {
|
|
||||||
case WAIT_ABANDONED, WAIT_TIMEOUT:
|
|
||||||
return false, nil
|
|
||||||
case WAIT_SIGNALED:
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
use(msWait)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// String helpers
|
|
||||||
func (info CONSOLE_SCREEN_BUFFER_INFO) String() string {
|
|
||||||
return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (coord COORD) String() string {
|
|
||||||
return fmt.Sprintf("%v,%v", coord.X, coord.Y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rect SMALL_RECT) String() string {
|
|
||||||
return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkError evaluates the results of a Windows API call and returns the error if it failed.
|
|
||||||
func checkError(r1, r2 uintptr, err error) error {
|
|
||||||
// Windows APIs return non-zero to indicate success
|
|
||||||
if r1 != 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the error if provided, otherwise default to EINVAL
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return syscall.EINVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
// coordToPointer converts a COORD into a uintptr (by fooling the type system).
|
|
||||||
func coordToPointer(c COORD) uintptr {
|
|
||||||
// Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass.
|
|
||||||
return uintptr(*((*uint32)(unsafe.Pointer(&c))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// use is a no-op, but the compiler cannot see that it is.
|
|
||||||
// Calling use(p) ensures that p is kept live until that point.
|
|
||||||
func use(p interface{}) {}
|
|
100
vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go
generated
vendored
100
vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go
generated
vendored
|
@ -1,100 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
import "github.com/Azure/go-ansiterm"
|
|
||||||
|
|
||||||
const (
|
|
||||||
FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
|
|
||||||
BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
|
|
||||||
)
|
|
||||||
|
|
||||||
// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the
|
|
||||||
// request represented by the passed ANSI mode.
|
|
||||||
func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) {
|
|
||||||
switch ansiMode {
|
|
||||||
|
|
||||||
// Mode styles
|
|
||||||
case ansiterm.ANSI_SGR_BOLD:
|
|
||||||
windowsMode = windowsMode | FOREGROUND_INTENSITY
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF:
|
|
||||||
windowsMode &^= FOREGROUND_INTENSITY
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_UNDERLINE:
|
|
||||||
windowsMode = windowsMode | COMMON_LVB_UNDERSCORE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_REVERSE:
|
|
||||||
inverted = true
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_REVERSE_OFF:
|
|
||||||
inverted = false
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_UNDERLINE_OFF:
|
|
||||||
windowsMode &^= COMMON_LVB_UNDERSCORE
|
|
||||||
|
|
||||||
// Foreground colors
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK)
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_BLACK:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK)
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_RED:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_GREEN:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_YELLOW:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_BLUE:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_CYAN:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_FOREGROUND_WHITE:
|
|
||||||
windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
|
|
||||||
|
|
||||||
// Background colors
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT:
|
|
||||||
// Black with no intensity
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK)
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_BLACK:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK)
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_RED:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_GREEN:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_YELLOW:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_BLUE:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_CYAN:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE
|
|
||||||
|
|
||||||
case ansiterm.ANSI_SGR_BACKGROUND_WHITE:
|
|
||||||
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
|
|
||||||
}
|
|
||||||
|
|
||||||
return windowsMode, inverted
|
|
||||||
}
|
|
||||||
|
|
||||||
// invertAttributes inverts the foreground and background colors of a Windows attributes value
|
|
||||||
func invertAttributes(windowsMode uint16) uint16 {
|
|
||||||
return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4)
|
|
||||||
}
|
|
101
vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go
generated
vendored
101
vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go
generated
vendored
|
@ -1,101 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
const (
|
|
||||||
horizontal = iota
|
|
||||||
vertical
|
|
||||||
)
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT {
|
|
||||||
if h.originMode {
|
|
||||||
sr := h.effectiveSr(info.Window)
|
|
||||||
return SMALL_RECT{
|
|
||||||
Top: sr.top,
|
|
||||||
Bottom: sr.bottom,
|
|
||||||
Left: 0,
|
|
||||||
Right: info.Size.X - 1,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return SMALL_RECT{
|
|
||||||
Top: info.Window.Top,
|
|
||||||
Bottom: info.Window.Bottom,
|
|
||||||
Left: 0,
|
|
||||||
Right: info.Size.X - 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setCursorPosition sets the cursor to the specified position, bounded to the screen size
|
|
||||||
func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error {
|
|
||||||
position.X = ensureInRange(position.X, window.Left, window.Right)
|
|
||||||
position.Y = ensureInRange(position.Y, window.Top, window.Bottom)
|
|
||||||
err := SetConsoleCursorPosition(h.fd, position)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("Cursor position set: (%d, %d)", position.X, position.Y)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error {
|
|
||||||
return h.moveCursor(vertical, param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error {
|
|
||||||
return h.moveCursor(horizontal, param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
position := info.CursorPosition
|
|
||||||
switch moveMode {
|
|
||||||
case horizontal:
|
|
||||||
position.X += int16(param)
|
|
||||||
case vertical:
|
|
||||||
position.Y += int16(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) moveCursorLine(param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
position := info.CursorPosition
|
|
||||||
position.X = 0
|
|
||||||
position.Y += int16(param)
|
|
||||||
|
|
||||||
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
position := info.CursorPosition
|
|
||||||
position.X = int16(param) - 1
|
|
||||||
|
|
||||||
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
84
vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go
generated
vendored
84
vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go
generated
vendored
|
@ -1,84 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
import "github.com/Azure/go-ansiterm"
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error {
|
|
||||||
// Ignore an invalid (negative area) request
|
|
||||||
if toCoord.Y < fromCoord.Y {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
var coordStart = COORD{}
|
|
||||||
var coordEnd = COORD{}
|
|
||||||
|
|
||||||
xCurrent, yCurrent := fromCoord.X, fromCoord.Y
|
|
||||||
xEnd, yEnd := toCoord.X, toCoord.Y
|
|
||||||
|
|
||||||
// Clear any partial initial line
|
|
||||||
if xCurrent > 0 {
|
|
||||||
coordStart.X, coordStart.Y = xCurrent, yCurrent
|
|
||||||
coordEnd.X, coordEnd.Y = xEnd, yCurrent
|
|
||||||
|
|
||||||
err = h.clearRect(attributes, coordStart, coordEnd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
xCurrent = 0
|
|
||||||
yCurrent += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear intervening rectangular section
|
|
||||||
if yCurrent < yEnd {
|
|
||||||
coordStart.X, coordStart.Y = xCurrent, yCurrent
|
|
||||||
coordEnd.X, coordEnd.Y = xEnd, yEnd-1
|
|
||||||
|
|
||||||
err = h.clearRect(attributes, coordStart, coordEnd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
xCurrent = 0
|
|
||||||
yCurrent = yEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear remaining partial ending line
|
|
||||||
coordStart.X, coordStart.Y = xCurrent, yCurrent
|
|
||||||
coordEnd.X, coordEnd.Y = xEnd, yEnd
|
|
||||||
|
|
||||||
err = h.clearRect(attributes, coordStart, coordEnd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error {
|
|
||||||
region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X}
|
|
||||||
width := toCoord.X - fromCoord.X + 1
|
|
||||||
height := toCoord.Y - fromCoord.Y + 1
|
|
||||||
size := uint32(width) * uint32(height)
|
|
||||||
|
|
||||||
if size <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]CHAR_INFO, size)
|
|
||||||
|
|
||||||
char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes}
|
|
||||||
for i := 0; i < int(size); i++ {
|
|
||||||
buffer[i] = char
|
|
||||||
}
|
|
||||||
|
|
||||||
err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, ®ion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
118
vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go
generated
vendored
118
vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go
generated
vendored
|
@ -1,118 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
// effectiveSr gets the current effective scroll region in buffer coordinates
|
|
||||||
func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion {
|
|
||||||
top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom)
|
|
||||||
bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom)
|
|
||||||
if top >= bottom {
|
|
||||||
top = window.Top
|
|
||||||
bottom = window.Bottom
|
|
||||||
}
|
|
||||||
return scrollRegion{top: top, bottom: bottom}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) scrollUp(param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sr := h.effectiveSr(info.Window)
|
|
||||||
return h.scroll(param, sr, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) scrollDown(param int) error {
|
|
||||||
return h.scrollUp(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) deleteLines(param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
start := info.CursorPosition.Y
|
|
||||||
sr := h.effectiveSr(info.Window)
|
|
||||||
// Lines cannot be inserted or deleted outside the scrolling region.
|
|
||||||
if start >= sr.top && start <= sr.bottom {
|
|
||||||
sr.top = start
|
|
||||||
return h.scroll(param, sr, info)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) insertLines(param int) error {
|
|
||||||
return h.deleteLines(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates.
|
|
||||||
func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error {
|
|
||||||
h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
|
|
||||||
h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
|
|
||||||
|
|
||||||
// Copy from and clip to the scroll region (full buffer width)
|
|
||||||
scrollRect := SMALL_RECT{
|
|
||||||
Top: sr.top,
|
|
||||||
Bottom: sr.bottom,
|
|
||||||
Left: 0,
|
|
||||||
Right: info.Size.X - 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Origin to which area should be copied
|
|
||||||
destOrigin := COORD{
|
|
||||||
X: 0,
|
|
||||||
Y: sr.top - int16(param),
|
|
||||||
}
|
|
||||||
|
|
||||||
char := CHAR_INFO{
|
|
||||||
UnicodeChar: ' ',
|
|
||||||
Attributes: h.attributes,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) deleteCharacters(param int) error {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return h.scrollLine(param, info.CursorPosition, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) insertCharacters(param int) error {
|
|
||||||
return h.deleteCharacters(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
// scrollLine scrolls a line horizontally starting at the provided position by a number of columns.
|
|
||||||
func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error {
|
|
||||||
// Copy from and clip to the scroll region (full buffer width)
|
|
||||||
scrollRect := SMALL_RECT{
|
|
||||||
Top: position.Y,
|
|
||||||
Bottom: position.Y,
|
|
||||||
Left: position.X,
|
|
||||||
Right: info.Size.X - 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Origin to which area should be copied
|
|
||||||
destOrigin := COORD{
|
|
||||||
X: position.X - int16(columns),
|
|
||||||
Y: position.Y,
|
|
||||||
}
|
|
||||||
|
|
||||||
char := CHAR_INFO{
|
|
||||||
UnicodeChar: ' ',
|
|
||||||
Attributes: h.attributes,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
9
vendor/github.com/Azure/go-ansiterm/winterm/utilities.go
generated
vendored
9
vendor/github.com/Azure/go-ansiterm/winterm/utilities.go
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
// AddInRange increments a value by the passed quantity while ensuring the values
|
|
||||||
// always remain within the supplied min / max range.
|
|
||||||
func addInRange(n int16, increment int16, min int16, max int16) int16 {
|
|
||||||
return ensureInRange(n+increment, min, max)
|
|
||||||
}
|
|
743
vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go
generated
vendored
743
vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go
generated
vendored
|
@ -1,743 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package winterm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/Azure/go-ansiterm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type windowsAnsiEventHandler struct {
|
|
||||||
fd uintptr
|
|
||||||
file *os.File
|
|
||||||
infoReset *CONSOLE_SCREEN_BUFFER_INFO
|
|
||||||
sr scrollRegion
|
|
||||||
buffer bytes.Buffer
|
|
||||||
attributes uint16
|
|
||||||
inverted bool
|
|
||||||
wrapNext bool
|
|
||||||
drewMarginByte bool
|
|
||||||
originMode bool
|
|
||||||
marginByte byte
|
|
||||||
curInfo *CONSOLE_SCREEN_BUFFER_INFO
|
|
||||||
curPos COORD
|
|
||||||
logf func(string, ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(*windowsAnsiEventHandler)
|
|
||||||
|
|
||||||
func WithLogf(f func(string, ...interface{})) Option {
|
|
||||||
return func(w *windowsAnsiEventHandler) {
|
|
||||||
w.logf = f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler {
|
|
||||||
infoReset, err := GetConsoleScreenBufferInfo(fd)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
h := &windowsAnsiEventHandler{
|
|
||||||
fd: fd,
|
|
||||||
file: file,
|
|
||||||
infoReset: infoReset,
|
|
||||||
attributes: infoReset.Attributes,
|
|
||||||
}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
|
|
||||||
logFile, _ := os.Create("winEventHandler.log")
|
|
||||||
logger := log.New(logFile, "", log.LstdFlags)
|
|
||||||
if h.logf != nil {
|
|
||||||
l := h.logf
|
|
||||||
h.logf = func(s string, v ...interface{}) {
|
|
||||||
l(s, v...)
|
|
||||||
logger.Printf(s, v...)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
h.logf = logger.Printf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.logf == nil {
|
|
||||||
h.logf = func(string, ...interface{}) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
type scrollRegion struct {
|
|
||||||
top int16
|
|
||||||
bottom int16
|
|
||||||
}
|
|
||||||
|
|
||||||
// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the
|
|
||||||
// current cursor position and scroll region settings, in which case it returns
|
|
||||||
// true. If no special handling is necessary, then it does nothing and returns
|
|
||||||
// false.
|
|
||||||
//
|
|
||||||
// In the false case, the caller should ensure that a carriage return
|
|
||||||
// and line feed are inserted or that the text is otherwise wrapped.
|
|
||||||
func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
|
|
||||||
if h.wrapNext {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
h.clearWrap()
|
|
||||||
}
|
|
||||||
pos, info, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
sr := h.effectiveSr(info.Window)
|
|
||||||
if pos.Y == sr.bottom {
|
|
||||||
// Scrolling is necessary. Let Windows automatically scroll if the scrolling region
|
|
||||||
// is the full window.
|
|
||||||
if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom {
|
|
||||||
if includeCR {
|
|
||||||
pos.X = 0
|
|
||||||
h.updatePos(pos)
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// A custom scroll region is active. Scroll the window manually to simulate
|
|
||||||
// the LF.
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
h.logf("Simulating LF inside scroll region")
|
|
||||||
if err := h.scrollUp(1); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if includeCR {
|
|
||||||
pos.X = 0
|
|
||||||
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
|
|
||||||
} else if pos.Y < info.Window.Bottom {
|
|
||||||
// Let Windows handle the LF.
|
|
||||||
pos.Y++
|
|
||||||
if includeCR {
|
|
||||||
pos.X = 0
|
|
||||||
}
|
|
||||||
h.updatePos(pos)
|
|
||||||
return false, nil
|
|
||||||
} else {
|
|
||||||
// The cursor is at the bottom of the screen but outside the scroll
|
|
||||||
// region. Skip the LF.
|
|
||||||
h.logf("Simulating LF outside scroll region")
|
|
||||||
if includeCR {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
pos.X = 0
|
|
||||||
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// executeLF executes a LF without a CR.
|
|
||||||
func (h *windowsAnsiEventHandler) executeLF() error {
|
|
||||||
handled, err := h.simulateLF(false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !handled {
|
|
||||||
// Windows LF will reset the cursor column position. Write the LF
|
|
||||||
// and restore the cursor position.
|
|
||||||
pos, _, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED)
|
|
||||||
if pos.X != 0 {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("Resetting cursor position for LF without CR")
|
|
||||||
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) Print(b byte) error {
|
|
||||||
if h.wrapNext {
|
|
||||||
h.buffer.WriteByte(h.marginByte)
|
|
||||||
h.clearWrap()
|
|
||||||
if _, err := h.simulateLF(true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos, info, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pos.X == info.Size.X-1 {
|
|
||||||
h.wrapNext = true
|
|
||||||
h.marginByte = b
|
|
||||||
} else {
|
|
||||||
pos.X++
|
|
||||||
h.updatePos(pos)
|
|
||||||
h.buffer.WriteByte(b)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) Execute(b byte) error {
|
|
||||||
switch b {
|
|
||||||
case ansiterm.ANSI_TAB:
|
|
||||||
h.logf("Execute(TAB)")
|
|
||||||
// Move to the next tab stop, but preserve auto-wrap if already set.
|
|
||||||
if !h.wrapNext {
|
|
||||||
pos, info, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pos.X = (pos.X + 8) - pos.X%8
|
|
||||||
if pos.X >= info.Size.X {
|
|
||||||
pos.X = info.Size.X - 1
|
|
||||||
}
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case ansiterm.ANSI_BEL:
|
|
||||||
h.buffer.WriteByte(ansiterm.ANSI_BEL)
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case ansiterm.ANSI_BACKSPACE:
|
|
||||||
if h.wrapNext {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.clearWrap()
|
|
||||||
}
|
|
||||||
pos, _, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pos.X > 0 {
|
|
||||||
pos.X--
|
|
||||||
h.updatePos(pos)
|
|
||||||
h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED:
|
|
||||||
// Treat as true LF.
|
|
||||||
return h.executeLF()
|
|
||||||
|
|
||||||
case ansiterm.ANSI_LINE_FEED:
|
|
||||||
// Simulate a CR and LF for now since there is no way in go-ansiterm
|
|
||||||
// to tell if the LF should include CR (and more things break when it's
|
|
||||||
// missing than when it's incorrectly added).
|
|
||||||
handled, err := h.simulateLF(true)
|
|
||||||
if handled || err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED)
|
|
||||||
|
|
||||||
case ansiterm.ANSI_CARRIAGE_RETURN:
|
|
||||||
if h.wrapNext {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.clearWrap()
|
|
||||||
}
|
|
||||||
pos, _, err := h.getCurrentInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pos.X != 0 {
|
|
||||||
pos.X = 0
|
|
||||||
h.updatePos(pos)
|
|
||||||
h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CUU(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CUU: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorVertical(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CUD(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CUD: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorVertical(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CUF(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CUF: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorHorizontal(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CUB(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CUB: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorHorizontal(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CNL(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CNL: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorLine(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CPL(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CPL: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorLine(-param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CHA(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CHA: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.moveCursorColumn(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) VPA(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("VPA: [[%d]]", param)
|
|
||||||
h.clearWrap()
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
window := h.getCursorWindow(info)
|
|
||||||
position := info.CursorPosition
|
|
||||||
position.Y = window.Top + int16(param) - 1
|
|
||||||
return h.setCursorPosition(position, window)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("CUP: [[%d %d]]", row, col)
|
|
||||||
h.clearWrap()
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
window := h.getCursorWindow(info)
|
|
||||||
position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1}
|
|
||||||
return h.setCursorPosition(position, window)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) HVP(row int, col int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("HVP: [[%d %d]]", row, col)
|
|
||||||
h.clearWrap()
|
|
||||||
return h.CUP(row, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)})
|
|
||||||
h.clearWrap()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DECOM(enable bool) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)})
|
|
||||||
h.clearWrap()
|
|
||||||
h.originMode = enable
|
|
||||||
return h.CUP(1, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)})
|
|
||||||
h.clearWrap()
|
|
||||||
if err := h.ED(2); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
targetWidth := int16(80)
|
|
||||||
if use132 {
|
|
||||||
targetWidth = 132
|
|
||||||
}
|
|
||||||
if info.Size.X < targetWidth {
|
|
||||||
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
|
|
||||||
h.logf("set buffer failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window := info.Window
|
|
||||||
window.Left = 0
|
|
||||||
window.Right = targetWidth - 1
|
|
||||||
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
|
|
||||||
h.logf("set window failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if info.Size.X > targetWidth {
|
|
||||||
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
|
|
||||||
h.logf("set buffer failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SetConsoleCursorPosition(h.fd, COORD{0, 0})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) ED(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("ED: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
|
|
||||||
// [J -- Erases from the cursor to the end of the screen, including the cursor position.
|
|
||||||
// [1J -- Erases from the beginning of the screen to the cursor, including the cursor position.
|
|
||||||
// [2J -- Erases the complete display. The cursor does not move.
|
|
||||||
// Notes:
|
|
||||||
// -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles
|
|
||||||
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var start COORD
|
|
||||||
var end COORD
|
|
||||||
|
|
||||||
switch param {
|
|
||||||
case 0:
|
|
||||||
start = info.CursorPosition
|
|
||||||
end = COORD{info.Size.X - 1, info.Size.Y - 1}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
start = COORD{0, 0}
|
|
||||||
end = info.CursorPosition
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
start = COORD{0, 0}
|
|
||||||
end = COORD{info.Size.X - 1, info.Size.Y - 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = h.clearRange(h.attributes, start, end)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the whole buffer was cleared, move the window to the top while preserving
|
|
||||||
// the window-relative cursor position.
|
|
||||||
if param == 2 {
|
|
||||||
pos := info.CursorPosition
|
|
||||||
window := info.Window
|
|
||||||
pos.Y -= window.Top
|
|
||||||
window.Bottom -= window.Top
|
|
||||||
window.Top = 0
|
|
||||||
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) EL(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("EL: [%v]", strconv.Itoa(param))
|
|
||||||
h.clearWrap()
|
|
||||||
|
|
||||||
// [K -- Erases from the cursor to the end of the line, including the cursor position.
|
|
||||||
// [1K -- Erases from the beginning of the line to the cursor, including the cursor position.
|
|
||||||
// [2K -- Erases the complete line.
|
|
||||||
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var start COORD
|
|
||||||
var end COORD
|
|
||||||
|
|
||||||
switch param {
|
|
||||||
case 0:
|
|
||||||
start = info.CursorPosition
|
|
||||||
end = COORD{info.Size.X, info.CursorPosition.Y}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
start = COORD{0, info.CursorPosition.Y}
|
|
||||||
end = info.CursorPosition
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
start = COORD{0, info.CursorPosition.Y}
|
|
||||||
end = COORD{info.Size.X, info.CursorPosition.Y}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = h.clearRange(h.attributes, start, end)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) IL(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("IL: [%v]", strconv.Itoa(param))
|
|
||||||
h.clearWrap()
|
|
||||||
return h.insertLines(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DL(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DL: [%v]", strconv.Itoa(param))
|
|
||||||
h.clearWrap()
|
|
||||||
return h.deleteLines(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) ICH(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("ICH: [%v]", strconv.Itoa(param))
|
|
||||||
h.clearWrap()
|
|
||||||
return h.insertCharacters(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DCH(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DCH: [%v]", strconv.Itoa(param))
|
|
||||||
h.clearWrap()
|
|
||||||
return h.deleteCharacters(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) SGR(params []int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
strings := []string{}
|
|
||||||
for _, v := range params {
|
|
||||||
strings = append(strings, strconv.Itoa(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
h.logf("SGR: [%v]", strings)
|
|
||||||
|
|
||||||
if len(params) <= 0 {
|
|
||||||
h.attributes = h.infoReset.Attributes
|
|
||||||
h.inverted = false
|
|
||||||
} else {
|
|
||||||
for _, attr := range params {
|
|
||||||
|
|
||||||
if attr == ansiterm.ANSI_SGR_RESET {
|
|
||||||
h.attributes = h.infoReset.Attributes
|
|
||||||
h.inverted = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes := h.attributes
|
|
||||||
if h.inverted {
|
|
||||||
attributes = invertAttributes(attributes)
|
|
||||||
}
|
|
||||||
err := SetConsoleTextAttribute(h.fd, attributes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) SU(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("SU: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.scrollUp(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) SD(param int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("SD: [%v]", []string{strconv.Itoa(param)})
|
|
||||||
h.clearWrap()
|
|
||||||
return h.scrollDown(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DA(params []string) error {
|
|
||||||
h.logf("DA: [%v]", params)
|
|
||||||
// DA cannot be implemented because it must send data on the VT100 input stream,
|
|
||||||
// which is not available to go-ansiterm.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("DECSTBM: [%d, %d]", top, bottom)
|
|
||||||
|
|
||||||
// Windows is 0 indexed, Linux is 1 indexed
|
|
||||||
h.sr.top = int16(top - 1)
|
|
||||||
h.sr.bottom = int16(bottom - 1)
|
|
||||||
|
|
||||||
// This command also moves the cursor to the origin.
|
|
||||||
h.clearWrap()
|
|
||||||
return h.CUP(1, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) RI() error {
|
|
||||||
if err := h.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.logf("RI: []")
|
|
||||||
h.clearWrap()
|
|
||||||
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sr := h.effectiveSr(info.Window)
|
|
||||||
if info.CursorPosition.Y == sr.top {
|
|
||||||
return h.scrollDown(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return h.moveCursorVertical(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) IND() error {
|
|
||||||
h.logf("IND: []")
|
|
||||||
return h.executeLF()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) Flush() error {
|
|
||||||
h.curInfo = nil
|
|
||||||
if h.buffer.Len() > 0 {
|
|
||||||
h.logf("Flush: [%s]", h.buffer.Bytes())
|
|
||||||
if _, err := h.buffer.WriteTo(h.file); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.wrapNext && !h.drewMarginByte {
|
|
||||||
h.logf("Flush: drawing margin byte '%c'", h.marginByte)
|
|
||||||
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}}
|
|
||||||
size := COORD{1, 1}
|
|
||||||
position := COORD{0, 0}
|
|
||||||
region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y}
|
|
||||||
if err := WriteConsoleOutput(h.fd, charInfo, size, position, ®ion); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.drewMarginByte = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// cacheConsoleInfo ensures that the current console screen information has been queried
|
|
||||||
// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos.
|
|
||||||
func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) {
|
|
||||||
if h.curInfo == nil {
|
|
||||||
info, err := GetConsoleScreenBufferInfo(h.fd)
|
|
||||||
if err != nil {
|
|
||||||
return COORD{}, nil, err
|
|
||||||
}
|
|
||||||
h.curInfo = info
|
|
||||||
h.curPos = info.CursorPosition
|
|
||||||
}
|
|
||||||
return h.curPos, h.curInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *windowsAnsiEventHandler) updatePos(pos COORD) {
|
|
||||||
if h.curInfo == nil {
|
|
||||||
panic("failed to call getCurrentInfo before calling updatePos")
|
|
||||||
}
|
|
||||||
h.curPos = pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearWrap clears the state where the cursor is in the margin
|
|
||||||
// waiting for the next character before wrapping the line. This must
|
|
||||||
// be done before most operations that act on the cursor.
|
|
||||||
func (h *windowsAnsiEventHandler) clearWrap() {
|
|
||||||
h.wrapNext = false
|
|
||||||
h.drewMarginByte = false
|
|
||||||
}
|
|
191
vendor/github.com/Azure/go-autorest/LICENSE
generated
vendored
191
vendor/github.com/Azure/go-autorest/LICENSE
generated
vendored
|
@ -1,191 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
Copyright 2015 Microsoft Corporation
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
81
vendor/github.com/Azure/go-autorest/autorest/adal/config.go
generated
vendored
81
vendor/github.com/Azure/go-autorest/autorest/adal/config.go
generated
vendored
|
@ -1,81 +0,0 @@
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
activeDirectoryAPIVersion = "1.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OAuthConfig represents the endpoints needed
|
|
||||||
// in OAuth operations
|
|
||||||
type OAuthConfig struct {
|
|
||||||
AuthorityEndpoint url.URL
|
|
||||||
AuthorizeEndpoint url.URL
|
|
||||||
TokenEndpoint url.URL
|
|
||||||
DeviceCodeEndpoint url.URL
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZero returns true if the OAuthConfig object is zero-initialized.
|
|
||||||
func (oac OAuthConfig) IsZero() bool {
|
|
||||||
return oac == OAuthConfig{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateStringParam(param, name string) error {
|
|
||||||
if len(param) == 0 {
|
|
||||||
return fmt.Errorf("parameter '" + name + "' cannot be empty")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOAuthConfig returns an OAuthConfig with tenant specific urls
|
|
||||||
func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) {
|
|
||||||
if err := validateStringParam(activeDirectoryEndpoint, "activeDirectoryEndpoint"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// it's legal for tenantID to be empty so don't validate it
|
|
||||||
const activeDirectoryEndpointTemplate = "%s/oauth2/%s?api-version=%s"
|
|
||||||
u, err := url.Parse(activeDirectoryEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
authorityURL, err := u.Parse(tenantID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", activeDirectoryAPIVersion))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", activeDirectoryAPIVersion))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", activeDirectoryAPIVersion))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &OAuthConfig{
|
|
||||||
AuthorityEndpoint: *authorityURL,
|
|
||||||
AuthorizeEndpoint: *authorizeURL,
|
|
||||||
TokenEndpoint: *tokenURL,
|
|
||||||
DeviceCodeEndpoint: *deviceCodeURL,
|
|
||||||
}, nil
|
|
||||||
}
|
|
242
vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go
generated
vendored
242
vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go
generated
vendored
|
@ -1,242 +0,0 @@
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
/*
|
|
||||||
This file is largely based on rjw57/oauth2device's code, with the follow differences:
|
|
||||||
* scope -> resource, and only allow a single one
|
|
||||||
* receive "Message" in the DeviceCode struct and show it to users as the prompt
|
|
||||||
* azure-xplat-cli has the following behavior that this emulates:
|
|
||||||
- does not send client_secret during the token exchange
|
|
||||||
- sends resource again in the token exchange request
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
logPrefix = "autorest/adal/devicetoken:"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrDeviceGeneric represents an unknown error from the token endpoint when using device flow
|
|
||||||
ErrDeviceGeneric = fmt.Errorf("%s Error while retrieving OAuth token: Unknown Error", logPrefix)
|
|
||||||
|
|
||||||
// ErrDeviceAccessDenied represents an access denied error from the token endpoint when using device flow
|
|
||||||
ErrDeviceAccessDenied = fmt.Errorf("%s Error while retrieving OAuth token: Access Denied", logPrefix)
|
|
||||||
|
|
||||||
// ErrDeviceAuthorizationPending represents the server waiting on the user to complete the device flow
|
|
||||||
ErrDeviceAuthorizationPending = fmt.Errorf("%s Error while retrieving OAuth token: Authorization Pending", logPrefix)
|
|
||||||
|
|
||||||
// ErrDeviceCodeExpired represents the server timing out and expiring the code during device flow
|
|
||||||
ErrDeviceCodeExpired = fmt.Errorf("%s Error while retrieving OAuth token: Code Expired", logPrefix)
|
|
||||||
|
|
||||||
// ErrDeviceSlowDown represents the service telling us we're polling too often during device flow
|
|
||||||
ErrDeviceSlowDown = fmt.Errorf("%s Error while retrieving OAuth token: Slow Down", logPrefix)
|
|
||||||
|
|
||||||
// ErrDeviceCodeEmpty represents an empty device code from the device endpoint while using device flow
|
|
||||||
ErrDeviceCodeEmpty = fmt.Errorf("%s Error while retrieving device code: Device Code Empty", logPrefix)
|
|
||||||
|
|
||||||
// ErrOAuthTokenEmpty represents an empty OAuth token from the token endpoint when using device flow
|
|
||||||
ErrOAuthTokenEmpty = fmt.Errorf("%s Error while retrieving OAuth token: Token Empty", logPrefix)
|
|
||||||
|
|
||||||
errCodeSendingFails = "Error occurred while sending request for Device Authorization Code"
|
|
||||||
errCodeHandlingFails = "Error occurred while handling response from the Device Endpoint"
|
|
||||||
errTokenSendingFails = "Error occurred while sending request with device code for a token"
|
|
||||||
errTokenHandlingFails = "Error occurred while handling response from the Token Endpoint (during device flow)"
|
|
||||||
errStatusNotOK = "Error HTTP status != 200"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeviceCode is the object returned by the device auth endpoint
|
|
||||||
// It contains information to instruct the user to complete the auth flow
|
|
||||||
type DeviceCode struct {
|
|
||||||
DeviceCode *string `json:"device_code,omitempty"`
|
|
||||||
UserCode *string `json:"user_code,omitempty"`
|
|
||||||
VerificationURL *string `json:"verification_url,omitempty"`
|
|
||||||
ExpiresIn *int64 `json:"expires_in,string,omitempty"`
|
|
||||||
Interval *int64 `json:"interval,string,omitempty"`
|
|
||||||
|
|
||||||
Message *string `json:"message"` // Azure specific
|
|
||||||
Resource string // store the following, stored when initiating, used when exchanging
|
|
||||||
OAuthConfig OAuthConfig
|
|
||||||
ClientID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenError is the object returned by the token exchange endpoint
|
|
||||||
// when something is amiss
|
|
||||||
type TokenError struct {
|
|
||||||
Error *string `json:"error,omitempty"`
|
|
||||||
ErrorCodes []int `json:"error_codes,omitempty"`
|
|
||||||
ErrorDescription *string `json:"error_description,omitempty"`
|
|
||||||
Timestamp *string `json:"timestamp,omitempty"`
|
|
||||||
TraceID *string `json:"trace_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceToken is the object return by the token exchange endpoint
|
|
||||||
// It can either look like a Token or an ErrorToken, so put both here
|
|
||||||
// and check for presence of "Error" to know if we are in error state
|
|
||||||
type deviceToken struct {
|
|
||||||
Token
|
|
||||||
TokenError
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitiateDeviceAuth initiates a device auth flow. It returns a DeviceCode
|
|
||||||
// that can be used with CheckForUserCompletion or WaitForUserCompletion.
|
|
||||||
func InitiateDeviceAuth(sender Sender, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) {
|
|
||||||
v := url.Values{
|
|
||||||
"client_id": []string{clientID},
|
|
||||||
"resource": []string{resource},
|
|
||||||
}
|
|
||||||
|
|
||||||
s := v.Encode()
|
|
||||||
body := ioutil.NopCloser(strings.NewReader(s))
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPost, oauthConfig.DeviceCodeEndpoint.String(), body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
req.ContentLength = int64(len(s))
|
|
||||||
req.Header.Set(contentType, mimeTypeFormPost)
|
|
||||||
resp, err := sender.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error())
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
rb, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, errStatusNotOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(strings.Trim(string(rb), " ")) == 0 {
|
|
||||||
return nil, ErrDeviceCodeEmpty
|
|
||||||
}
|
|
||||||
|
|
||||||
var code DeviceCode
|
|
||||||
err = json.Unmarshal(rb, &code)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
code.ClientID = clientID
|
|
||||||
code.Resource = resource
|
|
||||||
code.OAuthConfig = oauthConfig
|
|
||||||
|
|
||||||
return &code, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckForUserCompletion takes a DeviceCode and checks with the Azure AD OAuth endpoint
|
|
||||||
// to see if the device flow has: been completed, timed out, or otherwise failed
|
|
||||||
func CheckForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) {
|
|
||||||
v := url.Values{
|
|
||||||
"client_id": []string{code.ClientID},
|
|
||||||
"code": []string{*code.DeviceCode},
|
|
||||||
"grant_type": []string{OAuthGrantTypeDeviceCode},
|
|
||||||
"resource": []string{code.Resource},
|
|
||||||
}
|
|
||||||
|
|
||||||
s := v.Encode()
|
|
||||||
body := ioutil.NopCloser(strings.NewReader(s))
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPost, code.OAuthConfig.TokenEndpoint.String(), body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
req.ContentLength = int64(len(s))
|
|
||||||
req.Header.Set(contentType, mimeTypeFormPost)
|
|
||||||
resp, err := sender.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error())
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
rb, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK && len(strings.Trim(string(rb), " ")) == 0 {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, errStatusNotOK)
|
|
||||||
}
|
|
||||||
if len(strings.Trim(string(rb), " ")) == 0 {
|
|
||||||
return nil, ErrOAuthTokenEmpty
|
|
||||||
}
|
|
||||||
|
|
||||||
var token deviceToken
|
|
||||||
err = json.Unmarshal(rb, &token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if token.Error == nil {
|
|
||||||
return &token.Token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch *token.Error {
|
|
||||||
case "authorization_pending":
|
|
||||||
return nil, ErrDeviceAuthorizationPending
|
|
||||||
case "slow_down":
|
|
||||||
return nil, ErrDeviceSlowDown
|
|
||||||
case "access_denied":
|
|
||||||
return nil, ErrDeviceAccessDenied
|
|
||||||
case "code_expired":
|
|
||||||
return nil, ErrDeviceCodeExpired
|
|
||||||
default:
|
|
||||||
return nil, ErrDeviceGeneric
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitForUserCompletion calls CheckForUserCompletion repeatedly until a token is granted or an error state occurs.
|
|
||||||
// This prevents the user from looping and checking against 'ErrDeviceAuthorizationPending'.
|
|
||||||
func WaitForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) {
|
|
||||||
intervalDuration := time.Duration(*code.Interval) * time.Second
|
|
||||||
waitDuration := intervalDuration
|
|
||||||
|
|
||||||
for {
|
|
||||||
token, err := CheckForUserCompletion(sender, code)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch err {
|
|
||||||
case ErrDeviceSlowDown:
|
|
||||||
waitDuration += waitDuration
|
|
||||||
case ErrDeviceAuthorizationPending:
|
|
||||||
// noop
|
|
||||||
default: // everything else is "fatal" to us
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if waitDuration > (intervalDuration * 3) {
|
|
||||||
return nil, fmt.Errorf("%s Error waiting for user to complete device flow. Server told us to slow_down too much", logPrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(waitDuration)
|
|
||||||
}
|
|
||||||
}
|
|
73
vendor/github.com/Azure/go-autorest/autorest/adal/persist.go
generated
vendored
73
vendor/github.com/Azure/go-autorest/autorest/adal/persist.go
generated
vendored
|
@ -1,73 +0,0 @@
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoadToken restores a Token object from a file located at 'path'.
|
|
||||||
func LoadToken(path string) (*Token, error) {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to open file (%s) while loading token: %v", path, err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
var token Token
|
|
||||||
|
|
||||||
dec := json.NewDecoder(file)
|
|
||||||
if err = dec.Decode(&token); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode contents of file (%s) into Token representation: %v", path, err)
|
|
||||||
}
|
|
||||||
return &token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SaveToken persists an oauth token at the given location on disk.
|
|
||||||
// It moves the new file into place so it can safely be used to replace an existing file
|
|
||||||
// that maybe accessed by multiple processes.
|
|
||||||
func SaveToken(path string, mode os.FileMode, token Token) error {
|
|
||||||
dir := filepath.Dir(path)
|
|
||||||
err := os.MkdirAll(dir, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create directory (%s) to store token in: %v", dir, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newFile, err := ioutil.TempFile(dir, "token")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create the temp file to write the token: %v", err)
|
|
||||||
}
|
|
||||||
tempPath := newFile.Name()
|
|
||||||
|
|
||||||
if err := json.NewEncoder(newFile).Encode(token); err != nil {
|
|
||||||
return fmt.Errorf("failed to encode token to file (%s) while saving token: %v", tempPath, err)
|
|
||||||
}
|
|
||||||
if err := newFile.Close(); err != nil {
|
|
||||||
return fmt.Errorf("failed to close temp file %s: %v", tempPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atomic replace to avoid multi-writer file corruptions
|
|
||||||
if err := os.Rename(tempPath, path); err != nil {
|
|
||||||
return fmt.Errorf("failed to move temporary token to desired output location. src=%s dst=%s: %v", tempPath, path, err)
|
|
||||||
}
|
|
||||||
if err := os.Chmod(path, mode); err != nil {
|
|
||||||
return fmt.Errorf("failed to chmod the token file %s: %v", path, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
60
vendor/github.com/Azure/go-autorest/autorest/adal/sender.go
generated
vendored
60
vendor/github.com/Azure/go-autorest/autorest/adal/sender.go
generated
vendored
|
@ -1,60 +0,0 @@
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
contentType = "Content-Type"
|
|
||||||
mimeTypeFormPost = "application/x-www-form-urlencoded"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sender is the interface that wraps the Do method to send HTTP requests.
|
|
||||||
//
|
|
||||||
// The standard http.Client conforms to this interface.
|
|
||||||
type Sender interface {
|
|
||||||
Do(*http.Request) (*http.Response, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SenderFunc is a method that implements the Sender interface.
|
|
||||||
type SenderFunc func(*http.Request) (*http.Response, error)
|
|
||||||
|
|
||||||
// Do implements the Sender interface on SenderFunc.
|
|
||||||
func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
|
|
||||||
return sf(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
|
|
||||||
// http.Request and pass it along or, first, pass the http.Request along then react to the
|
|
||||||
// http.Response result.
|
|
||||||
type SendDecorator func(Sender) Sender
|
|
||||||
|
|
||||||
// CreateSender creates, decorates, and returns, as a Sender, the default http.Client.
|
|
||||||
func CreateSender(decorators ...SendDecorator) Sender {
|
|
||||||
return DecorateSender(&http.Client{}, decorators...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to
|
|
||||||
// the Sender. Decorators are applied in the order received, but their affect upon the request
|
|
||||||
// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a
|
|
||||||
// post-decorator (pass the http.Request along and react to the results in http.Response).
|
|
||||||
func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
|
|
||||||
for _, decorate := range decorators {
|
|
||||||
s = decorate(s)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
684
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
684
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
|
@ -1,684 +0,0 @@
|
||||||
package adal
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest/date"
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultRefresh = 5 * time.Minute
|
|
||||||
|
|
||||||
// OAuthGrantTypeDeviceCode is the "grant_type" identifier used in device flow
|
|
||||||
OAuthGrantTypeDeviceCode = "device_code"
|
|
||||||
|
|
||||||
// OAuthGrantTypeClientCredentials is the "grant_type" identifier used in credential flows
|
|
||||||
OAuthGrantTypeClientCredentials = "client_credentials"
|
|
||||||
|
|
||||||
// OAuthGrantTypeUserPass is the "grant_type" identifier used in username and password auth flows
|
|
||||||
OAuthGrantTypeUserPass = "password"
|
|
||||||
|
|
||||||
// OAuthGrantTypeRefreshToken is the "grant_type" identifier used in refresh token flows
|
|
||||||
OAuthGrantTypeRefreshToken = "refresh_token"
|
|
||||||
|
|
||||||
// OAuthGrantTypeAuthorizationCode is the "grant_type" identifier used in authorization code flows
|
|
||||||
OAuthGrantTypeAuthorizationCode = "authorization_code"
|
|
||||||
|
|
||||||
// metadataHeader is the header required by MSI extension
|
|
||||||
metadataHeader = "Metadata"
|
|
||||||
|
|
||||||
// msiEndpoint is the well known endpoint for getting MSI authentications tokens
|
|
||||||
msiEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OAuthTokenProvider is an interface which should be implemented by an access token retriever
|
|
||||||
type OAuthTokenProvider interface {
|
|
||||||
OAuthToken() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenRefreshError is an interface used by errors returned during token refresh.
|
|
||||||
type TokenRefreshError interface {
|
|
||||||
error
|
|
||||||
Response() *http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresher is an interface for token refresh functionality
|
|
||||||
type Refresher interface {
|
|
||||||
Refresh() error
|
|
||||||
RefreshExchange(resource string) error
|
|
||||||
EnsureFresh() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenRefreshCallback is the type representing callbacks that will be called after
|
|
||||||
// a successful token refresh
|
|
||||||
type TokenRefreshCallback func(Token) error
|
|
||||||
|
|
||||||
// Token encapsulates the access token used to authorize Azure requests.
|
|
||||||
type Token struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
|
|
||||||
ExpiresIn string `json:"expires_in"`
|
|
||||||
ExpiresOn string `json:"expires_on"`
|
|
||||||
NotBefore string `json:"not_before"`
|
|
||||||
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
Type string `json:"token_type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsZero returns true if the token object is zero-initialized.
|
|
||||||
func (t Token) IsZero() bool {
|
|
||||||
return t == Token{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expires returns the time.Time when the Token expires.
|
|
||||||
func (t Token) Expires() time.Time {
|
|
||||||
s, err := strconv.Atoi(t.ExpiresOn)
|
|
||||||
if err != nil {
|
|
||||||
s = -3600
|
|
||||||
}
|
|
||||||
|
|
||||||
expiration := date.NewUnixTimeFromSeconds(float64(s))
|
|
||||||
|
|
||||||
return time.Time(expiration).UTC()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExpired returns true if the Token is expired, false otherwise.
|
|
||||||
func (t Token) IsExpired() bool {
|
|
||||||
return t.WillExpireIn(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WillExpireIn returns true if the Token will expire after the passed time.Duration interval
|
|
||||||
// from now, false otherwise.
|
|
||||||
func (t Token) WillExpireIn(d time.Duration) bool {
|
|
||||||
return !t.Expires().After(time.Now().Add(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
//OAuthToken return the current access token
|
|
||||||
func (t *Token) OAuthToken() string {
|
|
||||||
return t.AccessToken
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalNoSecret represents a secret type that contains no secret
|
|
||||||
// meaning it is not valid for fetching a fresh token. This is used by Manual
|
|
||||||
type ServicePrincipalNoSecret struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret
|
|
||||||
// It only returns an error for the ServicePrincipalNoSecret type
|
|
||||||
func (noSecret *ServicePrincipalNoSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form
|
|
||||||
// that is submitted when acquiring an oAuth token.
|
|
||||||
type ServicePrincipalSecret interface {
|
|
||||||
SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization.
|
|
||||||
type ServicePrincipalTokenSecret struct {
|
|
||||||
ClientSecret string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
// It will populate the form submitted during oAuth Token Acquisition using the client_secret.
|
|
||||||
func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
v.Set("client_secret", tokenSecret.ClientSecret)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs.
|
|
||||||
type ServicePrincipalCertificateSecret struct {
|
|
||||||
Certificate *x509.Certificate
|
|
||||||
PrivateKey *rsa.PrivateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalMSISecret implements ServicePrincipalSecret for machines running the MSI Extension.
|
|
||||||
type ServicePrincipalMSISecret struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalUsernamePasswordSecret implements ServicePrincipalSecret for username and password auth.
|
|
||||||
type ServicePrincipalUsernamePasswordSecret struct {
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalAuthorizationCodeSecret implements ServicePrincipalSecret for authorization code auth.
|
|
||||||
type ServicePrincipalAuthorizationCodeSecret struct {
|
|
||||||
ClientSecret string
|
|
||||||
AuthorizationCode string
|
|
||||||
RedirectURI string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (secret *ServicePrincipalAuthorizationCodeSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
v.Set("code", secret.AuthorizationCode)
|
|
||||||
v.Set("client_secret", secret.ClientSecret)
|
|
||||||
v.Set("redirect_uri", secret.RedirectURI)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (secret *ServicePrincipalUsernamePasswordSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
v.Set("username", secret.Username)
|
|
||||||
v.Set("password", secret.Password)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
func (msiSecret *ServicePrincipalMSISecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignJwt returns the JWT signed with the certificate's private key.
|
|
||||||
func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) {
|
|
||||||
hasher := sha1.New()
|
|
||||||
_, err := hasher.Write(secret.Certificate.Raw)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
thumbprint := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
|
|
||||||
|
|
||||||
// The jti (JWT ID) claim provides a unique identifier for the JWT.
|
|
||||||
jti := make([]byte, 20)
|
|
||||||
_, err = rand.Read(jti)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
token := jwt.New(jwt.SigningMethodRS256)
|
|
||||||
token.Header["x5t"] = thumbprint
|
|
||||||
token.Claims = jwt.MapClaims{
|
|
||||||
"aud": spt.oauthConfig.TokenEndpoint.String(),
|
|
||||||
"iss": spt.clientID,
|
|
||||||
"sub": spt.clientID,
|
|
||||||
"jti": base64.URLEncoding.EncodeToString(jti),
|
|
||||||
"nbf": time.Now().Unix(),
|
|
||||||
"exp": time.Now().Add(time.Hour * 24).Unix(),
|
|
||||||
}
|
|
||||||
|
|
||||||
signedString, err := token.SignedString(secret.PrivateKey)
|
|
||||||
return signedString, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
|
||||||
// It will populate the form submitted during oAuth Token Acquisition using a JWT signed with a certificate.
|
|
||||||
func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
|
||||||
jwt, err := secret.SignJwt(spt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Set("client_assertion", jwt)
|
|
||||||
v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicePrincipalToken encapsulates a Token created for a Service Principal.
|
|
||||||
type ServicePrincipalToken struct {
|
|
||||||
token Token
|
|
||||||
secret ServicePrincipalSecret
|
|
||||||
oauthConfig OAuthConfig
|
|
||||||
clientID string
|
|
||||||
resource string
|
|
||||||
autoRefresh bool
|
|
||||||
refreshLock *sync.RWMutex
|
|
||||||
refreshWithin time.Duration
|
|
||||||
sender Sender
|
|
||||||
|
|
||||||
refreshCallbacks []TokenRefreshCallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateOAuthConfig(oac OAuthConfig) error {
|
|
||||||
if oac.IsZero() {
|
|
||||||
return fmt.Errorf("parameter 'oauthConfig' cannot be zero-initialized")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenWithSecret create a ServicePrincipalToken using the supplied ServicePrincipalSecret implementation.
|
|
||||||
func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, resource string, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(id, "id"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if secret == nil {
|
|
||||||
return nil, fmt.Errorf("parameter 'secret' cannot be nil")
|
|
||||||
}
|
|
||||||
spt := &ServicePrincipalToken{
|
|
||||||
oauthConfig: oauthConfig,
|
|
||||||
secret: secret,
|
|
||||||
clientID: id,
|
|
||||||
resource: resource,
|
|
||||||
autoRefresh: true,
|
|
||||||
refreshLock: &sync.RWMutex{},
|
|
||||||
refreshWithin: defaultRefresh,
|
|
||||||
sender: &http.Client{},
|
|
||||||
refreshCallbacks: callbacks,
|
|
||||||
}
|
|
||||||
return spt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromManualToken creates a ServicePrincipalToken using the supplied token
|
|
||||||
func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID string, resource string, token Token, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if token.IsZero() {
|
|
||||||
return nil, fmt.Errorf("parameter 'token' cannot be zero-initialized")
|
|
||||||
}
|
|
||||||
spt, err := NewServicePrincipalTokenWithSecret(
|
|
||||||
oauthConfig,
|
|
||||||
clientID,
|
|
||||||
resource,
|
|
||||||
&ServicePrincipalNoSecret{},
|
|
||||||
callbacks...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
spt.token = token
|
|
||||||
|
|
||||||
return spt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalToken creates a ServicePrincipalToken from the supplied Service Principal
|
|
||||||
// credentials scoped to the named resource.
|
|
||||||
func NewServicePrincipalToken(oauthConfig OAuthConfig, clientID string, secret string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(secret, "secret"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewServicePrincipalTokenWithSecret(
|
|
||||||
oauthConfig,
|
|
||||||
clientID,
|
|
||||||
resource,
|
|
||||||
&ServicePrincipalTokenSecret{
|
|
||||||
ClientSecret: secret,
|
|
||||||
},
|
|
||||||
callbacks...,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromCertificate creates a ServicePrincipalToken from the supplied pkcs12 bytes.
|
|
||||||
func NewServicePrincipalTokenFromCertificate(oauthConfig OAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if certificate == nil {
|
|
||||||
return nil, fmt.Errorf("parameter 'certificate' cannot be nil")
|
|
||||||
}
|
|
||||||
if privateKey == nil {
|
|
||||||
return nil, fmt.Errorf("parameter 'privateKey' cannot be nil")
|
|
||||||
}
|
|
||||||
return NewServicePrincipalTokenWithSecret(
|
|
||||||
oauthConfig,
|
|
||||||
clientID,
|
|
||||||
resource,
|
|
||||||
&ServicePrincipalCertificateSecret{
|
|
||||||
PrivateKey: privateKey,
|
|
||||||
Certificate: certificate,
|
|
||||||
},
|
|
||||||
callbacks...,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromUsernamePassword creates a ServicePrincipalToken from the username and password.
|
|
||||||
func NewServicePrincipalTokenFromUsernamePassword(oauthConfig OAuthConfig, clientID string, username string, password string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(username, "username"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(password, "password"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewServicePrincipalTokenWithSecret(
|
|
||||||
oauthConfig,
|
|
||||||
clientID,
|
|
||||||
resource,
|
|
||||||
&ServicePrincipalUsernamePasswordSecret{
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
},
|
|
||||||
callbacks...,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromAuthorizationCode creates a ServicePrincipalToken from the
|
|
||||||
func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clientID string, clientSecret string, authorizationCode string, redirectURI string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
|
|
||||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(clientSecret, "clientSecret"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(authorizationCode, "authorizationCode"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(redirectURI, "redirectURI"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewServicePrincipalTokenWithSecret(
|
|
||||||
oauthConfig,
|
|
||||||
clientID,
|
|
||||||
resource,
|
|
||||||
&ServicePrincipalAuthorizationCodeSecret{
|
|
||||||
ClientSecret: clientSecret,
|
|
||||||
AuthorizationCode: authorizationCode,
|
|
||||||
RedirectURI: redirectURI,
|
|
||||||
},
|
|
||||||
callbacks...,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines.
|
|
||||||
func GetMSIVMEndpoint() (string, error) {
|
|
||||||
return msiEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension.
|
|
||||||
// It will use the system assigned identity when creating the token.
|
|
||||||
func NewServicePrincipalTokenFromMSI(msiEndpoint, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
return newServicePrincipalTokenFromMSI(msiEndpoint, resource, nil, callbacks...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromMSIWithUserAssignedID creates a ServicePrincipalToken via the MSI VM Extension.
|
|
||||||
// It will use the specified user assigned identity when creating the token.
|
|
||||||
func NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint, resource string, userAssignedID string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
return newServicePrincipalTokenFromMSI(msiEndpoint, resource, &userAssignedID, callbacks...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedID *string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
|
||||||
if err := validateStringParam(msiEndpoint, "msiEndpoint"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateStringParam(resource, "resource"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if userAssignedID != nil {
|
|
||||||
if err := validateStringParam(*userAssignedID, "userAssignedID"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We set the oauth config token endpoint to be MSI's endpoint
|
|
||||||
msiEndpointURL, err := url.Parse(msiEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v := url.Values{}
|
|
||||||
v.Set("resource", resource)
|
|
||||||
v.Set("api-version", "2018-02-01")
|
|
||||||
if userAssignedID != nil {
|
|
||||||
v.Set("client_id", *userAssignedID)
|
|
||||||
}
|
|
||||||
msiEndpointURL.RawQuery = v.Encode()
|
|
||||||
|
|
||||||
spt := &ServicePrincipalToken{
|
|
||||||
oauthConfig: OAuthConfig{
|
|
||||||
TokenEndpoint: *msiEndpointURL,
|
|
||||||
},
|
|
||||||
secret: &ServicePrincipalMSISecret{},
|
|
||||||
resource: resource,
|
|
||||||
autoRefresh: true,
|
|
||||||
refreshLock: &sync.RWMutex{},
|
|
||||||
refreshWithin: defaultRefresh,
|
|
||||||
sender: &http.Client{},
|
|
||||||
refreshCallbacks: callbacks,
|
|
||||||
}
|
|
||||||
|
|
||||||
if userAssignedID != nil {
|
|
||||||
spt.clientID = *userAssignedID
|
|
||||||
}
|
|
||||||
|
|
||||||
return spt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// internal type that implements TokenRefreshError
|
|
||||||
type tokenRefreshError struct {
|
|
||||||
message string
|
|
||||||
resp *http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface which is part of the TokenRefreshError interface.
|
|
||||||
func (tre tokenRefreshError) Error() string {
|
|
||||||
return tre.message
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response implements the TokenRefreshError interface, it returns the raw HTTP response from the refresh operation.
|
|
||||||
func (tre tokenRefreshError) Response() *http.Response {
|
|
||||||
return tre.resp
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTokenRefreshError(message string, resp *http.Response) TokenRefreshError {
|
|
||||||
return tokenRefreshError{message: message, resp: resp}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnsureFresh will refresh the token if it will expire within the refresh window (as set by
|
|
||||||
// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use.
|
|
||||||
func (spt *ServicePrincipalToken) EnsureFresh() error {
|
|
||||||
if spt.autoRefresh && spt.token.WillExpireIn(spt.refreshWithin) {
|
|
||||||
// take the write lock then check to see if the token was already refreshed
|
|
||||||
spt.refreshLock.Lock()
|
|
||||||
defer spt.refreshLock.Unlock()
|
|
||||||
if spt.token.WillExpireIn(spt.refreshWithin) {
|
|
||||||
return spt.refreshInternal(spt.resource)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvokeRefreshCallbacks calls any TokenRefreshCallbacks that were added to the SPT during initialization
|
|
||||||
func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
|
|
||||||
if spt.refreshCallbacks != nil {
|
|
||||||
for _, callback := range spt.refreshCallbacks {
|
|
||||||
err := callback(spt.token)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: TokenRefreshCallback handler failed. Error = '%v'", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh obtains a fresh token for the Service Principal.
|
|
||||||
// This method is not safe for concurrent use and should be syncrhonized.
|
|
||||||
func (spt *ServicePrincipalToken) Refresh() error {
|
|
||||||
spt.refreshLock.Lock()
|
|
||||||
defer spt.refreshLock.Unlock()
|
|
||||||
return spt.refreshInternal(spt.resource)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RefreshExchange refreshes the token, but for a different resource.
|
|
||||||
// This method is not safe for concurrent use and should be syncrhonized.
|
|
||||||
func (spt *ServicePrincipalToken) RefreshExchange(resource string) error {
|
|
||||||
spt.refreshLock.Lock()
|
|
||||||
defer spt.refreshLock.Unlock()
|
|
||||||
return spt.refreshInternal(resource)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (spt *ServicePrincipalToken) getGrantType() string {
|
|
||||||
switch spt.secret.(type) {
|
|
||||||
case *ServicePrincipalUsernamePasswordSecret:
|
|
||||||
return OAuthGrantTypeUserPass
|
|
||||||
case *ServicePrincipalAuthorizationCodeSecret:
|
|
||||||
return OAuthGrantTypeAuthorizationCode
|
|
||||||
default:
|
|
||||||
return OAuthGrantTypeClientCredentials
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isIMDS(u url.URL) bool {
|
|
||||||
imds, err := url.Parse(msiEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return u.Host == imds.Host && u.Path == imds.Path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
|
|
||||||
req, err := http.NewRequest(http.MethodPost, spt.oauthConfig.TokenEndpoint.String(), nil)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isIMDS(spt.oauthConfig.TokenEndpoint) {
|
|
||||||
v := url.Values{}
|
|
||||||
v.Set("client_id", spt.clientID)
|
|
||||||
v.Set("resource", resource)
|
|
||||||
|
|
||||||
if spt.token.RefreshToken != "" {
|
|
||||||
v.Set("grant_type", OAuthGrantTypeRefreshToken)
|
|
||||||
v.Set("refresh_token", spt.token.RefreshToken)
|
|
||||||
} else {
|
|
||||||
v.Set("grant_type", spt.getGrantType())
|
|
||||||
err := spt.secret.SetAuthenticationValues(spt, &v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s := v.Encode()
|
|
||||||
body := ioutil.NopCloser(strings.NewReader(s))
|
|
||||||
req.ContentLength = int64(len(s))
|
|
||||||
req.Header.Set(contentType, mimeTypeFormPost)
|
|
||||||
req.Body = body
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := spt.secret.(*ServicePrincipalMSISecret); ok {
|
|
||||||
req.Method = http.MethodGet
|
|
||||||
req.Header.Set(metadataHeader, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := spt.sender.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: Failed to execute the refresh request. Error = '%v'", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer resp.Body.Close()
|
|
||||||
rb, err := ioutil.ReadAll(resp.Body)
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
if err != nil {
|
|
||||||
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body", resp.StatusCode), resp)
|
|
||||||
}
|
|
||||||
return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s", resp.StatusCode, string(rb)), resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: Failed to read a new service principal token during refresh. Error = '%v'", err)
|
|
||||||
}
|
|
||||||
if len(strings.Trim(string(rb), " ")) == 0 {
|
|
||||||
return fmt.Errorf("adal: Empty service principal token received during refresh")
|
|
||||||
}
|
|
||||||
var token Token
|
|
||||||
err = json.Unmarshal(rb, &token)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb))
|
|
||||||
}
|
|
||||||
|
|
||||||
spt.token = token
|
|
||||||
|
|
||||||
return spt.InvokeRefreshCallbacks(token)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAutoRefresh enables or disables automatic refreshing of stale tokens.
|
|
||||||
func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) {
|
|
||||||
spt.autoRefresh = autoRefresh
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will
|
|
||||||
// refresh the token.
|
|
||||||
func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) {
|
|
||||||
spt.refreshWithin = d
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSender sets the http.Client used when obtaining the Service Principal token. An
|
|
||||||
// undecorated http.Client is used by default.
|
|
||||||
func (spt *ServicePrincipalToken) SetSender(s Sender) { spt.sender = s }
|
|
||||||
|
|
||||||
// OAuthToken implements the OAuthTokenProvider interface. It returns the current access token.
|
|
||||||
func (spt *ServicePrincipalToken) OAuthToken() string {
|
|
||||||
spt.refreshLock.RLock()
|
|
||||||
defer spt.refreshLock.RUnlock()
|
|
||||||
return spt.token.OAuthToken()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token returns a copy of the current token.
|
|
||||||
func (spt *ServicePrincipalToken) Token() Token {
|
|
||||||
spt.refreshLock.RLock()
|
|
||||||
defer spt.refreshLock.RUnlock()
|
|
||||||
return spt.token
|
|
||||||
}
|
|
257
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
257
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
|
@ -1,257 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest/adal"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
bearerChallengeHeader = "Www-Authenticate"
|
|
||||||
bearer = "Bearer"
|
|
||||||
tenantID = "tenantID"
|
|
||||||
apiKeyAuthorizerHeader = "Ocp-Apim-Subscription-Key"
|
|
||||||
bingAPISdkHeader = "X-BingApis-SDK-Client"
|
|
||||||
golangBingAPISdkHeaderValue = "Go-SDK"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Authorizer is the interface that provides a PrepareDecorator used to supply request
|
|
||||||
// authorization. Most often, the Authorizer decorator runs last so it has access to the full
|
|
||||||
// state of the formed HTTP request.
|
|
||||||
type Authorizer interface {
|
|
||||||
WithAuthorization() PrepareDecorator
|
|
||||||
}
|
|
||||||
|
|
||||||
// NullAuthorizer implements a default, "do nothing" Authorizer.
|
|
||||||
type NullAuthorizer struct{}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that does nothing.
|
|
||||||
func (na NullAuthorizer) WithAuthorization() PrepareDecorator {
|
|
||||||
return WithNothing()
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIKeyAuthorizer implements API Key authorization.
|
|
||||||
type APIKeyAuthorizer struct {
|
|
||||||
headers map[string]interface{}
|
|
||||||
queryParameters map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAPIKeyAuthorizerWithHeaders creates an ApiKeyAuthorizer with headers.
|
|
||||||
func NewAPIKeyAuthorizerWithHeaders(headers map[string]interface{}) *APIKeyAuthorizer {
|
|
||||||
return NewAPIKeyAuthorizer(headers, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAPIKeyAuthorizerWithQueryParameters creates an ApiKeyAuthorizer with query parameters.
|
|
||||||
func NewAPIKeyAuthorizerWithQueryParameters(queryParameters map[string]interface{}) *APIKeyAuthorizer {
|
|
||||||
return NewAPIKeyAuthorizer(nil, queryParameters)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAPIKeyAuthorizer creates an ApiKeyAuthorizer with headers.
|
|
||||||
func NewAPIKeyAuthorizer(headers map[string]interface{}, queryParameters map[string]interface{}) *APIKeyAuthorizer {
|
|
||||||
return &APIKeyAuthorizer{headers: headers, queryParameters: queryParameters}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Paramaters
|
|
||||||
func (aka *APIKeyAuthorizer) WithAuthorization() PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return DecoratePreparer(p, WithHeaders(aka.headers), WithQueryParameters(aka.queryParameters))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CognitiveServicesAuthorizer implements authorization for Cognitive Services.
|
|
||||||
type CognitiveServicesAuthorizer struct {
|
|
||||||
subscriptionKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCognitiveServicesAuthorizer is
|
|
||||||
func NewCognitiveServicesAuthorizer(subscriptionKey string) *CognitiveServicesAuthorizer {
|
|
||||||
return &CognitiveServicesAuthorizer{subscriptionKey: subscriptionKey}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization is
|
|
||||||
func (csa *CognitiveServicesAuthorizer) WithAuthorization() PrepareDecorator {
|
|
||||||
headers := make(map[string]interface{})
|
|
||||||
headers[apiKeyAuthorizerHeader] = csa.subscriptionKey
|
|
||||||
headers[bingAPISdkHeader] = golangBingAPISdkHeaderValue
|
|
||||||
|
|
||||||
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
|
|
||||||
}
|
|
||||||
|
|
||||||
// BearerAuthorizer implements the bearer authorization
|
|
||||||
type BearerAuthorizer struct {
|
|
||||||
tokenProvider adal.OAuthTokenProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBearerAuthorizer crates a BearerAuthorizer using the given token provider
|
|
||||||
func NewBearerAuthorizer(tp adal.OAuthTokenProvider) *BearerAuthorizer {
|
|
||||||
return &BearerAuthorizer{tokenProvider: tp}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
|
||||||
// value is "Bearer " followed by the token.
|
|
||||||
//
|
|
||||||
// By default, the token will be automatically refreshed through the Refresher interface.
|
|
||||||
func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
refresher, ok := ba.tokenProvider.(adal.Refresher)
|
|
||||||
if ok {
|
|
||||||
err := refresher.EnsureFresh()
|
|
||||||
if err != nil {
|
|
||||||
var resp *http.Response
|
|
||||||
if tokError, ok := err.(adal.TokenRefreshError); ok {
|
|
||||||
resp = tokError.Response()
|
|
||||||
}
|
|
||||||
return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp,
|
|
||||||
"Failed to refresh the Token for request to %s", r.URL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Prepare(r, WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken())))
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BearerAuthorizerCallbackFunc is the authentication callback signature.
|
|
||||||
type BearerAuthorizerCallbackFunc func(tenantID, resource string) (*BearerAuthorizer, error)
|
|
||||||
|
|
||||||
// BearerAuthorizerCallback implements bearer authorization via a callback.
|
|
||||||
type BearerAuthorizerCallback struct {
|
|
||||||
sender Sender
|
|
||||||
callback BearerAuthorizerCallbackFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBearerAuthorizerCallback creates a bearer authorization callback. The callback
|
|
||||||
// is invoked when the HTTP request is submitted.
|
|
||||||
func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbackFunc) *BearerAuthorizerCallback {
|
|
||||||
if sender == nil {
|
|
||||||
sender = &http.Client{}
|
|
||||||
}
|
|
||||||
return &BearerAuthorizerCallback{sender: sender, callback: callback}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose value
|
|
||||||
// is "Bearer " followed by the token. The BearerAuthorizer is obtained via a user-supplied callback.
|
|
||||||
//
|
|
||||||
// By default, the token will be automatically refreshed through the Refresher interface.
|
|
||||||
func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
// make a copy of the request and remove the body as it's not
|
|
||||||
// required and avoids us having to create a copy of it.
|
|
||||||
rCopy := *r
|
|
||||||
removeRequestBody(&rCopy)
|
|
||||||
|
|
||||||
resp, err := bacb.sender.Do(&rCopy)
|
|
||||||
if err == nil && resp.StatusCode == 401 {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if hasBearerChallenge(resp) {
|
|
||||||
bc, err := newBearerChallenge(resp)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if bacb.callback != nil {
|
|
||||||
ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"])
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
return Prepare(r, ba.WithAuthorization())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true if the HTTP response contains a bearer challenge
|
|
||||||
func hasBearerChallenge(resp *http.Response) bool {
|
|
||||||
authHeader := resp.Header.Get(bearerChallengeHeader)
|
|
||||||
if len(authHeader) == 0 || strings.Index(authHeader, bearer) < 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type bearerChallenge struct {
|
|
||||||
values map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBearerChallenge(resp *http.Response) (bc bearerChallenge, err error) {
|
|
||||||
challenge := strings.TrimSpace(resp.Header.Get(bearerChallengeHeader))
|
|
||||||
trimmedChallenge := challenge[len(bearer)+1:]
|
|
||||||
|
|
||||||
// challenge is a set of key=value pairs that are comma delimited
|
|
||||||
pairs := strings.Split(trimmedChallenge, ",")
|
|
||||||
if len(pairs) < 1 {
|
|
||||||
err = fmt.Errorf("challenge '%s' contains no pairs", challenge)
|
|
||||||
return bc, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bc.values = make(map[string]string)
|
|
||||||
for i := range pairs {
|
|
||||||
trimmedPair := strings.TrimSpace(pairs[i])
|
|
||||||
pair := strings.Split(trimmedPair, "=")
|
|
||||||
if len(pair) == 2 {
|
|
||||||
// remove the enclosing quotes
|
|
||||||
key := strings.Trim(pair[0], "\"")
|
|
||||||
value := strings.Trim(pair[1], "\"")
|
|
||||||
|
|
||||||
switch key {
|
|
||||||
case "authorization", "authorization_uri":
|
|
||||||
// strip the tenant ID from the authorization URL
|
|
||||||
asURL, err := url.Parse(value)
|
|
||||||
if err != nil {
|
|
||||||
return bc, err
|
|
||||||
}
|
|
||||||
bc.values[tenantID] = asURL.Path[1:]
|
|
||||||
default:
|
|
||||||
bc.values[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bc, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EventGridKeyAuthorizer implements authorization for event grid using key authentication.
|
|
||||||
type EventGridKeyAuthorizer struct {
|
|
||||||
topicKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEventGridKeyAuthorizer creates a new EventGridKeyAuthorizer
|
|
||||||
// with the specified topic key.
|
|
||||||
func NewEventGridKeyAuthorizer(topicKey string) EventGridKeyAuthorizer {
|
|
||||||
return EventGridKeyAuthorizer{topicKey: topicKey}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization returns a PrepareDecorator that adds the aeg-sas-key authentication header.
|
|
||||||
func (egta EventGridKeyAuthorizer) WithAuthorization() PrepareDecorator {
|
|
||||||
headers := map[string]interface{}{
|
|
||||||
"aeg-sas-key": egta.topicKey,
|
|
||||||
}
|
|
||||||
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
|
|
||||||
}
|
|
150
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
150
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines
|
|
||||||
and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/)
|
|
||||||
generated Go code.
|
|
||||||
|
|
||||||
The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending,
|
|
||||||
and Responding. A typical pattern is:
|
|
||||||
|
|
||||||
req, err := Prepare(&http.Request{},
|
|
||||||
token.WithAuthorization())
|
|
||||||
|
|
||||||
resp, err := Send(req,
|
|
||||||
WithLogging(logger),
|
|
||||||
DoErrorIfStatusCode(http.StatusInternalServerError),
|
|
||||||
DoCloseIfError(),
|
|
||||||
DoRetryForAttempts(5, time.Second))
|
|
||||||
|
|
||||||
err = Respond(resp,
|
|
||||||
ByDiscardingBody(),
|
|
||||||
ByClosing())
|
|
||||||
|
|
||||||
Each phase relies on decorators to modify and / or manage processing. Decorators may first modify
|
|
||||||
and then pass the data along, pass the data first and then modify the result, or wrap themselves
|
|
||||||
around passing the data (such as a logger might do). Decorators run in the order provided. For
|
|
||||||
example, the following:
|
|
||||||
|
|
||||||
req, err := Prepare(&http.Request{},
|
|
||||||
WithBaseURL("https://microsoft.com/"),
|
|
||||||
WithPath("a"),
|
|
||||||
WithPath("b"),
|
|
||||||
WithPath("c"))
|
|
||||||
|
|
||||||
will set the URL to:
|
|
||||||
|
|
||||||
https://microsoft.com/a/b/c
|
|
||||||
|
|
||||||
Preparers and Responders may be shared and re-used (assuming the underlying decorators support
|
|
||||||
sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders
|
|
||||||
shared among multiple go-routines, and a single Sender shared among multiple sending go-routines,
|
|
||||||
all bound together by means of input / output channels.
|
|
||||||
|
|
||||||
Decorators hold their passed state within a closure (such as the path components in the example
|
|
||||||
above). Be careful to share Preparers and Responders only in a context where such held state
|
|
||||||
applies. For example, it may not make sense to share a Preparer that applies a query string from a
|
|
||||||
fixed set of values. Similarly, sharing a Responder that reads the response body into a passed
|
|
||||||
struct (e.g., ByUnmarshallingJson) is likely incorrect.
|
|
||||||
|
|
||||||
Lastly, the Swagger specification (https://swagger.io) that drives AutoRest
|
|
||||||
(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The
|
|
||||||
github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure
|
|
||||||
correct parsing and formatting.
|
|
||||||
|
|
||||||
Errors raised by autorest objects and methods will conform to the autorest.Error interface.
|
|
||||||
|
|
||||||
See the included examples for more detail. For details on the suggested use of this package by
|
|
||||||
generated clients, see the Client described below.
|
|
||||||
*/
|
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// HeaderLocation specifies the HTTP Location header.
|
|
||||||
HeaderLocation = "Location"
|
|
||||||
|
|
||||||
// HeaderRetryAfter specifies the HTTP Retry-After header.
|
|
||||||
HeaderRetryAfter = "Retry-After"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set
|
|
||||||
// and false otherwise.
|
|
||||||
func ResponseHasStatusCode(resp *http.Response, codes ...int) bool {
|
|
||||||
if resp == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return containsInt(codes, resp.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLocation retrieves the URL from the Location header of the passed response.
|
|
||||||
func GetLocation(resp *http.Response) string {
|
|
||||||
return resp.Header.Get(HeaderLocation)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If
|
|
||||||
// the header is absent or is malformed, it will return the supplied default delay time.Duration.
|
|
||||||
func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration {
|
|
||||||
retry := resp.Header.Get(HeaderRetryAfter)
|
|
||||||
if retry == "" {
|
|
||||||
return defaultDelay
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := time.ParseDuration(retry + "s")
|
|
||||||
if err != nil {
|
|
||||||
return defaultDelay
|
|
||||||
}
|
|
||||||
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPollingRequest allocates and returns a new http.Request to poll for the passed response.
|
|
||||||
func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) {
|
|
||||||
location := GetLocation(resp)
|
|
||||||
if location == "" {
|
|
||||||
return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling")
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := Prepare(&http.Request{Cancel: cancel},
|
|
||||||
AsGet(),
|
|
||||||
WithBaseURL(location))
|
|
||||||
if err != nil {
|
|
||||||
return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location)
|
|
||||||
}
|
|
||||||
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPollingRequestWithContext allocates and returns a new http.Request with the specified context to poll for the passed response.
|
|
||||||
func NewPollingRequestWithContext(ctx context.Context, resp *http.Response) (*http.Request, error) {
|
|
||||||
location := GetLocation(resp)
|
|
||||||
if location == "" {
|
|
||||||
return nil, NewErrorWithResponse("autorest", "NewPollingRequestWithContext", resp, "Location header missing from response that requires polling")
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := Prepare((&http.Request{}).WithContext(ctx),
|
|
||||||
AsGet(),
|
|
||||||
WithBaseURL(location))
|
|
||||||
if err != nil {
|
|
||||||
return nil, NewErrorWithError(err, "autorest", "NewPollingRequestWithContext", nil, "Failure creating poll request to %s", location)
|
|
||||||
}
|
|
||||||
|
|
||||||
return req, nil
|
|
||||||
}
|
|
511
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
511
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
|
@ -1,511 +0,0 @@
|
||||||
package azure
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/Azure/go-autorest/autorest/date"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
headerAsyncOperation = "Azure-AsyncOperation"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
operationInProgress string = "InProgress"
|
|
||||||
operationCanceled string = "Canceled"
|
|
||||||
operationFailed string = "Failed"
|
|
||||||
operationSucceeded string = "Succeeded"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.StatusCreated, http.StatusOK}
|
|
||||||
|
|
||||||
// Future provides a mechanism to access the status and results of an asynchronous request.
|
|
||||||
// Since futures are stateful they should be passed by value to avoid race conditions.
|
|
||||||
type Future struct {
|
|
||||||
req *http.Request
|
|
||||||
resp *http.Response
|
|
||||||
ps pollingState
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFuture returns a new Future object initialized with the specified request.
|
|
||||||
func NewFuture(req *http.Request) Future {
|
|
||||||
return Future{req: req}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response returns the last HTTP response or nil if there isn't one.
|
|
||||||
func (f Future) Response() *http.Response {
|
|
||||||
return f.resp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status returns the last status message of the operation.
|
|
||||||
func (f Future) Status() string {
|
|
||||||
if f.ps.State == "" {
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
return f.ps.State
|
|
||||||
}
|
|
||||||
|
|
||||||
// PollingMethod returns the method used to monitor the status of the asynchronous operation.
|
|
||||||
func (f Future) PollingMethod() PollingMethodType {
|
|
||||||
return f.ps.PollingMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done queries the service to see if the operation has completed.
|
|
||||||
func (f *Future) Done(sender autorest.Sender) (bool, error) {
|
|
||||||
// exit early if this future has terminated
|
|
||||||
if f.ps.hasTerminated() {
|
|
||||||
return true, f.errorInfo()
|
|
||||||
}
|
|
||||||
resp, err := sender.Do(f.req)
|
|
||||||
f.resp = resp
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
|
|
||||||
// check response body for error content
|
|
||||||
if resp.Body != nil {
|
|
||||||
type respErr struct {
|
|
||||||
ServiceError ServiceError `json:"error"`
|
|
||||||
}
|
|
||||||
re := respErr{}
|
|
||||||
|
|
||||||
defer resp.Body.Close()
|
|
||||||
b, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(b, &re)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return false, re.ServiceError
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to return something meaningful
|
|
||||||
return false, ServiceError{
|
|
||||||
Code: fmt.Sprintf("%v", resp.StatusCode),
|
|
||||||
Message: resp.Status,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// PollingURL returns the URL used for retrieving the status of the long-running operation.
|
|
||||||
// For LROs that use the Location header the final URL value is used to retrieve the result.
|
|
||||||
func (f Future) PollingURL() string {
|
|
||||||
return f.ps.URI
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure
|
|
||||||
// long-running operation. It will delay between requests for the duration specified in the
|
|
||||||
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
|
|
||||||
// closing the optional channel on the http.Request.
|
|
||||||
func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
|
|
||||||
return func(s autorest.Sender) autorest.Sender {
|
|
||||||
return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
resp, err = s.Do(r)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ps := pollingState{}
|
|
||||||
for err == nil {
|
|
||||||
err = updatePollingState(resp, &ps)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if ps.hasTerminated() {
|
|
||||||
if !ps.hasSucceeded() {
|
|
||||||
err = ps
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err = newPollingRequest(ps)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
r = r.WithContext(resp.Request.Context())
|
|
||||||
|
|
||||||
delay = autorest.GetRetryAfter(resp, delay)
|
|
||||||
resp, err = autorest.SendWithSender(s, r,
|
|
||||||
autorest.AfterDelay(delay))
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAsyncOperation(resp *http.Response) string {
|
|
||||||
return resp.Header.Get(http.CanonicalHeaderKey(headerAsyncOperation))
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasSucceeded(state string) bool {
|
|
||||||
return strings.EqualFold(state, operationSucceeded)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasTerminated(state string) bool {
|
|
||||||
return strings.EqualFold(state, operationCanceled) || strings.EqualFold(state, operationFailed) || strings.EqualFold(state, operationSucceeded)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasFailed(state string) bool {
|
|
||||||
return strings.EqualFold(state, operationFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
type provisioningTracker interface {
|
|
||||||
state() string
|
|
||||||
hasSucceeded() bool
|
|
||||||
hasTerminated() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type operationResource struct {
|
|
||||||
// Note:
|
|
||||||
// The specification states services should return the "id" field. However some return it as
|
|
||||||
// "operationId".
|
|
||||||
ID string `json:"id"`
|
|
||||||
OperationID string `json:"operationId"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
Properties map[string]interface{} `json:"properties"`
|
|
||||||
OperationError ServiceError `json:"error"`
|
|
||||||
StartTime date.Time `json:"startTime"`
|
|
||||||
EndTime date.Time `json:"endTime"`
|
|
||||||
PercentComplete float64 `json:"percentComplete"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (or operationResource) state() string {
|
|
||||||
return or.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
func (or operationResource) hasSucceeded() bool {
|
|
||||||
return hasSucceeded(or.state())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (or operationResource) hasTerminated() bool {
|
|
||||||
return hasTerminated(or.state())
|
|
||||||
}
|
|
||||||
|
|
||||||
type provisioningProperties struct {
|
|
||||||
ProvisioningState string `json:"provisioningState"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type provisioningStatus struct {
|
|
||||||
Properties provisioningProperties `json:"properties,omitempty"`
|
|
||||||
ProvisioningError ServiceError `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps provisioningStatus) state() string {
|
|
||||||
return ps.Properties.ProvisioningState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps provisioningStatus) hasSucceeded() bool {
|
|
||||||
return hasSucceeded(ps.state())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps provisioningStatus) hasTerminated() bool {
|
|
||||||
return hasTerminated(ps.state())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps provisioningStatus) hasProvisioningError() bool {
|
|
||||||
// code and message are required fields so only check them
|
|
||||||
return len(ps.ProvisioningError.Code) > 0 ||
|
|
||||||
len(ps.ProvisioningError.Message) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// PollingMethodType defines a type used for enumerating polling mechanisms.
|
|
||||||
type PollingMethodType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// PollingAsyncOperation indicates the polling method uses the Azure-AsyncOperation header.
|
|
||||||
PollingAsyncOperation PollingMethodType = "AsyncOperation"
|
|
||||||
|
|
||||||
// PollingLocation indicates the polling method uses the Location header.
|
|
||||||
PollingLocation PollingMethodType = "Location"
|
|
||||||
|
|
||||||
// PollingUnknown indicates an unknown polling method and is the default value.
|
|
||||||
PollingUnknown PollingMethodType = ""
|
|
||||||
)
|
|
||||||
|
|
||||||
type pollingState struct {
|
|
||||||
PollingMethod PollingMethodType `json:"pollingMethod"`
|
|
||||||
URI string `json:"uri"`
|
|
||||||
State string `json:"state"`
|
|
||||||
ServiceError *ServiceError `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps pollingState) hasSucceeded() bool {
|
|
||||||
return hasSucceeded(ps.State)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps pollingState) hasTerminated() bool {
|
|
||||||
return hasTerminated(ps.State)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps pollingState) hasFailed() bool {
|
|
||||||
return hasFailed(ps.State)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps pollingState) Error() string {
|
|
||||||
s := fmt.Sprintf("Long running operation terminated with status '%s'", ps.State)
|
|
||||||
if ps.ServiceError != nil {
|
|
||||||
s = fmt.Sprintf("%s: %+v", s, *ps.ServiceError)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// updatePollingState maps the operation status -- retrieved from either a provisioningState
|
|
||||||
// field, the status field of an OperationResource, or inferred from the HTTP status code --
|
|
||||||
// into a well-known states. Since the process begins from the initial request, the state
|
|
||||||
// always comes from either a the provisioningState returned or is inferred from the HTTP
|
|
||||||
// status code. Subsequent requests will read an Azure OperationResource object if the
|
|
||||||
// service initially returned the Azure-AsyncOperation header. The responseFormat field notes
|
|
||||||
// the expected response format.
|
|
||||||
func updatePollingState(resp *http.Response, ps *pollingState) error {
|
|
||||||
// Determine the response shape
|
|
||||||
// -- The first response will always be a provisioningStatus response; only the polling requests,
|
|
||||||
// depending on the header returned, may be something otherwise.
|
|
||||||
var pt provisioningTracker
|
|
||||||
if ps.PollingMethod == PollingAsyncOperation {
|
|
||||||
pt = &operationResource{}
|
|
||||||
} else {
|
|
||||||
pt = &provisioningStatus{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is the first request (that is, the polling response shape is unknown), determine how
|
|
||||||
// to poll and what to expect
|
|
||||||
if ps.PollingMethod == PollingUnknown {
|
|
||||||
req := resp.Request
|
|
||||||
if req == nil {
|
|
||||||
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Original HTTP request is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer the Azure-AsyncOperation header
|
|
||||||
ps.URI = getAsyncOperation(resp)
|
|
||||||
if ps.URI != "" {
|
|
||||||
ps.PollingMethod = PollingAsyncOperation
|
|
||||||
} else {
|
|
||||||
ps.PollingMethod = PollingLocation
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else, use the Location header
|
|
||||||
if ps.URI == "" {
|
|
||||||
ps.URI = autorest.GetLocation(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lastly, requests against an existing resource, use the last request URI
|
|
||||||
if ps.URI == "" {
|
|
||||||
m := strings.ToUpper(req.Method)
|
|
||||||
if m == http.MethodPatch || m == http.MethodPut || m == http.MethodGet {
|
|
||||||
ps.URI = req.URL.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and interpret the response (saving the Body in case no polling is necessary)
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
err := autorest.Respond(resp,
|
|
||||||
autorest.ByCopying(b),
|
|
||||||
autorest.ByUnmarshallingJSON(pt),
|
|
||||||
autorest.ByClosing())
|
|
||||||
resp.Body = ioutil.NopCloser(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interpret the results
|
|
||||||
// -- Terminal states apply regardless
|
|
||||||
// -- Unknown states are per-service inprogress states
|
|
||||||
// -- Otherwise, infer state from HTTP status code
|
|
||||||
if pt.hasTerminated() {
|
|
||||||
ps.State = pt.state()
|
|
||||||
} else if pt.state() != "" {
|
|
||||||
ps.State = operationInProgress
|
|
||||||
} else {
|
|
||||||
switch resp.StatusCode {
|
|
||||||
case http.StatusAccepted:
|
|
||||||
ps.State = operationInProgress
|
|
||||||
|
|
||||||
case http.StatusNoContent, http.StatusCreated, http.StatusOK:
|
|
||||||
ps.State = operationSucceeded
|
|
||||||
|
|
||||||
default:
|
|
||||||
ps.State = operationFailed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.EqualFold(ps.State, operationInProgress) && ps.URI == "" {
|
|
||||||
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Unable to obtain polling URI for %s %s", resp.Request.Method, resp.Request.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
// For failed operation, check for error code and message in
|
|
||||||
// -- Operation resource
|
|
||||||
// -- Response
|
|
||||||
// -- Otherwise, Unknown
|
|
||||||
if ps.hasFailed() {
|
|
||||||
if or, ok := pt.(*operationResource); ok {
|
|
||||||
ps.ServiceError = &or.OperationError
|
|
||||||
} else if p, ok := pt.(*provisioningStatus); ok && p.hasProvisioningError() {
|
|
||||||
ps.ServiceError = &p.ProvisioningError
|
|
||||||
} else {
|
|
||||||
ps.ServiceError = &ServiceError{
|
|
||||||
Code: "Unknown",
|
|
||||||
Message: "None",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPollingRequest(ps pollingState) (*http.Request, error) {
|
|
||||||
reqPoll, err := autorest.Prepare(&http.Request{},
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(ps.URI))
|
|
||||||
if err != nil {
|
|
||||||
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.URI)
|
|
||||||
}
|
|
||||||
|
|
||||||
return reqPoll, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsyncOpIncompleteError is the type that's returned from a future that has not completed.
|
|
||||||
type AsyncOpIncompleteError struct {
|
|
||||||
// FutureType is the name of the type composed of a azure.Future.
|
|
||||||
FutureType string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns an error message including the originating type name of the error.
|
|
||||||
func (e AsyncOpIncompleteError) Error() string {
|
|
||||||
return fmt.Sprintf("%s: asynchronous operation has not completed", e.FutureType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAsyncOpIncompleteError creates a new AsyncOpIncompleteError with the specified parameters.
|
|
||||||
func NewAsyncOpIncompleteError(futureType string) AsyncOpIncompleteError {
|
|
||||||
return AsyncOpIncompleteError{
|
|
||||||
FutureType: futureType,
|
|
||||||
}
|
|
||||||
}
|
|
408
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
408
vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go
generated
vendored
|
@ -1,408 +0,0 @@
|
||||||
package auth
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf16"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/Azure/go-autorest/autorest/adal"
|
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
|
||||||
"github.com/dimchansky/utfbom"
|
|
||||||
"golang.org/x/crypto/pkcs12"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewAuthorizerFromEnvironment creates an Authorizer configured from environment variables in the order:
|
|
||||||
// 1. Client credentials
|
|
||||||
// 2. Client certificate
|
|
||||||
// 3. Username password
|
|
||||||
// 4. MSI
|
|
||||||
func NewAuthorizerFromEnvironment() (autorest.Authorizer, error) {
|
|
||||||
tenantID := os.Getenv("AZURE_TENANT_ID")
|
|
||||||
clientID := os.Getenv("AZURE_CLIENT_ID")
|
|
||||||
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
|
|
||||||
certificatePath := os.Getenv("AZURE_CERTIFICATE_PATH")
|
|
||||||
certificatePassword := os.Getenv("AZURE_CERTIFICATE_PASSWORD")
|
|
||||||
username := os.Getenv("AZURE_USERNAME")
|
|
||||||
password := os.Getenv("AZURE_PASSWORD")
|
|
||||||
envName := os.Getenv("AZURE_ENVIRONMENT")
|
|
||||||
resource := os.Getenv("AZURE_AD_RESOURCE")
|
|
||||||
|
|
||||||
var env azure.Environment
|
|
||||||
if envName == "" {
|
|
||||||
env = azure.PublicCloud
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
env, err = azure.EnvironmentFromName(envName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if resource == "" {
|
|
||||||
resource = env.ResourceManagerEndpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
//1.Client Credentials
|
|
||||||
if clientSecret != "" {
|
|
||||||
config := NewClientCredentialsConfig(clientID, clientSecret, tenantID)
|
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
|
||||||
config.Resource = resource
|
|
||||||
return config.Authorizer()
|
|
||||||
}
|
|
||||||
|
|
||||||
//2. Client Certificate
|
|
||||||
if certificatePath != "" {
|
|
||||||
config := NewClientCertificateConfig(certificatePath, certificatePassword, clientID, tenantID)
|
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
|
||||||
config.Resource = resource
|
|
||||||
return config.Authorizer()
|
|
||||||
}
|
|
||||||
|
|
||||||
//3. Username Password
|
|
||||||
if username != "" && password != "" {
|
|
||||||
config := NewUsernamePasswordConfig(username, password, clientID, tenantID)
|
|
||||||
config.AADEndpoint = env.ActiveDirectoryEndpoint
|
|
||||||
config.Resource = resource
|
|
||||||
return config.Authorizer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. MSI
|
|
||||||
config := NewMSIConfig()
|
|
||||||
config.Resource = resource
|
|
||||||
config.ClientID = clientID
|
|
||||||
return config.Authorizer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAuthorizerFromFile creates an Authorizer configured from a configuration file.
|
|
||||||
func NewAuthorizerFromFile(baseURI string) (autorest.Authorizer, error) {
|
|
||||||
fileLocation := os.Getenv("AZURE_AUTH_LOCATION")
|
|
||||||
if fileLocation == "" {
|
|
||||||
return nil, errors.New("auth file not found. Environment variable AZURE_AUTH_LOCATION is not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
contents, err := ioutil.ReadFile(fileLocation)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auth file might be encoded
|
|
||||||
decoded, err := decode(contents)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
file := file{}
|
|
||||||
err = json.Unmarshal(decoded, &file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resource, err := getResourceForToken(file, baseURI)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := adal.NewOAuthConfig(file.ActiveDirectoryEndpoint, file.TenantID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalToken(*config, file.ClientID, file.ClientSecret, resource)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// File represents the authentication file
|
|
||||||
type file struct {
|
|
||||||
ClientID string `json:"clientId,omitempty"`
|
|
||||||
ClientSecret string `json:"clientSecret,omitempty"`
|
|
||||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
|
||||||
TenantID string `json:"tenantId,omitempty"`
|
|
||||||
ActiveDirectoryEndpoint string `json:"activeDirectoryEndpointUrl,omitempty"`
|
|
||||||
ResourceManagerEndpoint string `json:"resourceManagerEndpointUrl,omitempty"`
|
|
||||||
GraphResourceID string `json:"activeDirectoryGraphResourceId,omitempty"`
|
|
||||||
SQLManagementEndpoint string `json:"sqlManagementEndpointUrl,omitempty"`
|
|
||||||
GalleryEndpoint string `json:"galleryEndpointUrl,omitempty"`
|
|
||||||
ManagementEndpoint string `json:"managementEndpointUrl,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(b []byte) ([]byte, error) {
|
|
||||||
reader, enc := utfbom.Skip(bytes.NewReader(b))
|
|
||||||
|
|
||||||
switch enc {
|
|
||||||
case utfbom.UTF16LittleEndian:
|
|
||||||
u16 := make([]uint16, (len(b)/2)-1)
|
|
||||||
err := binary.Read(reader, binary.LittleEndian, &u16)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return []byte(string(utf16.Decode(u16))), nil
|
|
||||||
case utfbom.UTF16BigEndian:
|
|
||||||
u16 := make([]uint16, (len(b)/2)-1)
|
|
||||||
err := binary.Read(reader, binary.BigEndian, &u16)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return []byte(string(utf16.Decode(u16))), nil
|
|
||||||
}
|
|
||||||
return ioutil.ReadAll(reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getResourceForToken(f file, baseURI string) (string, error) {
|
|
||||||
// Compare dafault base URI from the SDK to the endpoints from the public cloud
|
|
||||||
// Base URI and token resource are the same string. This func finds the authentication
|
|
||||||
// file field that matches the SDK base URI. The SDK defines the public cloud
|
|
||||||
// endpoint as its default base URI
|
|
||||||
if !strings.HasSuffix(baseURI, "/") {
|
|
||||||
baseURI += "/"
|
|
||||||
}
|
|
||||||
switch baseURI {
|
|
||||||
case azure.PublicCloud.ServiceManagementEndpoint:
|
|
||||||
return f.ManagementEndpoint, nil
|
|
||||||
case azure.PublicCloud.ResourceManagerEndpoint:
|
|
||||||
return f.ResourceManagerEndpoint, nil
|
|
||||||
case azure.PublicCloud.ActiveDirectoryEndpoint:
|
|
||||||
return f.ActiveDirectoryEndpoint, nil
|
|
||||||
case azure.PublicCloud.GalleryEndpoint:
|
|
||||||
return f.GalleryEndpoint, nil
|
|
||||||
case azure.PublicCloud.GraphEndpoint:
|
|
||||||
return f.GraphResourceID, nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("auth: base URI not found in endpoints")
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientCredentialsConfig creates an AuthorizerConfig object configured to obtain an Authorizer through Client Credentials.
|
|
||||||
// Defaults to Public Cloud and Resource Manager Endpoint.
|
|
||||||
func NewClientCredentialsConfig(clientID string, clientSecret string, tenantID string) ClientCredentialsConfig {
|
|
||||||
return ClientCredentialsConfig{
|
|
||||||
ClientID: clientID,
|
|
||||||
ClientSecret: clientSecret,
|
|
||||||
TenantID: tenantID,
|
|
||||||
Resource: azure.PublicCloud.ResourceManagerEndpoint,
|
|
||||||
AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientCertificateConfig creates a ClientCertificateConfig object configured to obtain an Authorizer through client certificate.
|
|
||||||
// Defaults to Public Cloud and Resource Manager Endpoint.
|
|
||||||
func NewClientCertificateConfig(certificatePath string, certificatePassword string, clientID string, tenantID string) ClientCertificateConfig {
|
|
||||||
return ClientCertificateConfig{
|
|
||||||
CertificatePath: certificatePath,
|
|
||||||
CertificatePassword: certificatePassword,
|
|
||||||
ClientID: clientID,
|
|
||||||
TenantID: tenantID,
|
|
||||||
Resource: azure.PublicCloud.ResourceManagerEndpoint,
|
|
||||||
AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUsernamePasswordConfig creates an UsernamePasswordConfig object configured to obtain an Authorizer through username and password.
|
|
||||||
// Defaults to Public Cloud and Resource Manager Endpoint.
|
|
||||||
func NewUsernamePasswordConfig(username string, password string, clientID string, tenantID string) UsernamePasswordConfig {
|
|
||||||
return UsernamePasswordConfig{
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
ClientID: clientID,
|
|
||||||
TenantID: tenantID,
|
|
||||||
Resource: azure.PublicCloud.ResourceManagerEndpoint,
|
|
||||||
AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMSIConfig creates an MSIConfig object configured to obtain an Authorizer through MSI.
|
|
||||||
func NewMSIConfig() MSIConfig {
|
|
||||||
return MSIConfig{
|
|
||||||
Resource: azure.PublicCloud.ResourceManagerEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDeviceFlowConfig creates a DeviceFlowConfig object configured to obtain an Authorizer through device flow.
|
|
||||||
// Defaults to Public Cloud and Resource Manager Endpoint.
|
|
||||||
func NewDeviceFlowConfig(clientID string, tenantID string) DeviceFlowConfig {
|
|
||||||
return DeviceFlowConfig{
|
|
||||||
ClientID: clientID,
|
|
||||||
TenantID: tenantID,
|
|
||||||
Resource: azure.PublicCloud.ResourceManagerEndpoint,
|
|
||||||
AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//AuthorizerConfig provides an authorizer from the configuration provided.
|
|
||||||
type AuthorizerConfig interface {
|
|
||||||
Authorizer() (autorest.Authorizer, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientCredentialsConfig provides the options to get a bearer authorizer from client credentials.
|
|
||||||
type ClientCredentialsConfig struct {
|
|
||||||
ClientID string
|
|
||||||
ClientSecret string
|
|
||||||
TenantID string
|
|
||||||
AADEndpoint string
|
|
||||||
Resource string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorizer gets the authorizer from client credentials.
|
|
||||||
func (ccc ClientCredentialsConfig) Authorizer() (autorest.Authorizer, error) {
|
|
||||||
oauthConfig, err := adal.NewOAuthConfig(ccc.AADEndpoint, ccc.TenantID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalToken(*oauthConfig, ccc.ClientID, ccc.ClientSecret, ccc.Resource)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get oauth token from client credentials: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientCertificateConfig provides the options to get a bearer authorizer from a client certificate.
|
|
||||||
type ClientCertificateConfig struct {
|
|
||||||
ClientID string
|
|
||||||
CertificatePath string
|
|
||||||
CertificatePassword string
|
|
||||||
TenantID string
|
|
||||||
AADEndpoint string
|
|
||||||
Resource string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorizer gets an authorizer object from client certificate.
|
|
||||||
func (ccc ClientCertificateConfig) Authorizer() (autorest.Authorizer, error) {
|
|
||||||
oauthConfig, err := adal.NewOAuthConfig(ccc.AADEndpoint, ccc.TenantID)
|
|
||||||
|
|
||||||
certData, err := ioutil.ReadFile(ccc.CertificatePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read the certificate file (%s): %v", ccc.CertificatePath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certificate, rsaPrivateKey, err := decodePkcs12(certData, ccc.CertificatePassword)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalTokenFromCertificate(*oauthConfig, ccc.ClientID, certificate, rsaPrivateKey, ccc.Resource)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get oauth token from certificate auth: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceFlowConfig provides the options to get a bearer authorizer using device flow authentication.
|
|
||||||
type DeviceFlowConfig struct {
|
|
||||||
ClientID string
|
|
||||||
TenantID string
|
|
||||||
AADEndpoint string
|
|
||||||
Resource string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorizer gets the authorizer from device flow.
|
|
||||||
func (dfc DeviceFlowConfig) Authorizer() (autorest.Authorizer, error) {
|
|
||||||
oauthClient := &autorest.Client{}
|
|
||||||
oauthConfig, err := adal.NewOAuthConfig(dfc.AADEndpoint, dfc.TenantID)
|
|
||||||
deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthConfig, dfc.ClientID, dfc.AADEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to start device auth flow: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println(*deviceCode.Message)
|
|
||||||
|
|
||||||
token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to finish device auth flow: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, dfc.ClientID, dfc.Resource, *token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get oauth token from device flow: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) {
|
|
||||||
privateKey, certificate, err := pkcs12.Decode(pkcs, password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey)
|
|
||||||
if !isRsaKey {
|
|
||||||
return nil, nil, fmt.Errorf("PKCS#12 certificate must contain an RSA private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
return certificate, rsaPrivateKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsernamePasswordConfig provides the options to get a bearer authorizer from a username and a password.
|
|
||||||
type UsernamePasswordConfig struct {
|
|
||||||
ClientID string
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
TenantID string
|
|
||||||
AADEndpoint string
|
|
||||||
Resource string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorizer gets the authorizer from a username and a password.
|
|
||||||
func (ups UsernamePasswordConfig) Authorizer() (autorest.Authorizer, error) {
|
|
||||||
|
|
||||||
oauthConfig, err := adal.NewOAuthConfig(ups.AADEndpoint, ups.TenantID)
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalTokenFromUsernamePassword(*oauthConfig, ups.ClientID, ups.Username, ups.Password, ups.Resource)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get oauth token from username and password auth: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MSIConfig provides the options to get a bearer authorizer through MSI.
|
|
||||||
type MSIConfig struct {
|
|
||||||
Resource string
|
|
||||||
ClientID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorizer gets the authorizer from MSI.
|
|
||||||
func (mc MSIConfig) Authorizer() (autorest.Authorizer, error) {
|
|
||||||
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
spToken, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, mc.Resource)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get oauth token from MSI: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return autorest.NewBearerAuthorizer(spToken), nil
|
|
||||||
}
|
|
301
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
301
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
|
@ -1,301 +0,0 @@
|
||||||
// Package azure provides Azure-specific implementations used with AutoRest.
|
|
||||||
// See the included examples for more detail.
|
|
||||||
package azure
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// HeaderClientID is the Azure extension header to set a user-specified request ID.
|
|
||||||
HeaderClientID = "x-ms-client-request-id"
|
|
||||||
|
|
||||||
// HeaderReturnClientID is the Azure extension header to set if the user-specified request ID
|
|
||||||
// should be included in the response.
|
|
||||||
HeaderReturnClientID = "x-ms-return-client-request-id"
|
|
||||||
|
|
||||||
// HeaderRequestID is the Azure extension header of the service generated request ID returned
|
|
||||||
// in the response.
|
|
||||||
HeaderRequestID = "x-ms-request-id"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServiceError encapsulates the error response from an Azure service.
|
|
||||||
// It adhears to the OData v4 specification for error responses.
|
|
||||||
type ServiceError struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
Target *string `json:"target"`
|
|
||||||
Details []map[string]interface{} `json:"details"`
|
|
||||||
InnerError map[string]interface{} `json:"innererror"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (se ServiceError) Error() string {
|
|
||||||
result := fmt.Sprintf("Code=%q Message=%q", se.Code, se.Message)
|
|
||||||
|
|
||||||
if se.Target != nil {
|
|
||||||
result += fmt.Sprintf(" Target=%q", *se.Target)
|
|
||||||
}
|
|
||||||
|
|
||||||
if se.Details != nil {
|
|
||||||
d, err := json.Marshal(se.Details)
|
|
||||||
if err != nil {
|
|
||||||
result += fmt.Sprintf(" Details=%v", se.Details)
|
|
||||||
}
|
|
||||||
result += fmt.Sprintf(" Details=%v", string(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
if se.InnerError != nil {
|
|
||||||
d, err := json.Marshal(se.InnerError)
|
|
||||||
if err != nil {
|
|
||||||
result += fmt.Sprintf(" InnerError=%v", se.InnerError)
|
|
||||||
}
|
|
||||||
result += fmt.Sprintf(" InnerError=%v", string(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface for the ServiceError type.
|
|
||||||
func (se *ServiceError) UnmarshalJSON(b []byte) error {
|
|
||||||
// per the OData v4 spec the details field must be an array of JSON objects.
|
|
||||||
// unfortunately not all services adhear to the spec and just return a single
|
|
||||||
// object instead of an array with one object. so we have to perform some
|
|
||||||
// shenanigans to accommodate both cases.
|
|
||||||
// http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091
|
|
||||||
|
|
||||||
type serviceError1 struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
Target *string `json:"target"`
|
|
||||||
Details []map[string]interface{} `json:"details"`
|
|
||||||
InnerError map[string]interface{} `json:"innererror"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type serviceError2 struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
Target *string `json:"target"`
|
|
||||||
Details map[string]interface{} `json:"details"`
|
|
||||||
InnerError map[string]interface{} `json:"innererror"`
|
|
||||||
}
|
|
||||||
|
|
||||||
se1 := serviceError1{}
|
|
||||||
err := json.Unmarshal(b, &se1)
|
|
||||||
if err == nil {
|
|
||||||
se.populate(se1.Code, se1.Message, se1.Target, se1.Details, se1.InnerError)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
se2 := serviceError2{}
|
|
||||||
err = json.Unmarshal(b, &se2)
|
|
||||||
if err == nil {
|
|
||||||
se.populate(se2.Code, se2.Message, se2.Target, nil, se2.InnerError)
|
|
||||||
se.Details = append(se.Details, se2.Details)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (se *ServiceError) populate(code, message string, target *string, details []map[string]interface{}, inner map[string]interface{}) {
|
|
||||||
se.Code = code
|
|
||||||
se.Message = message
|
|
||||||
se.Target = target
|
|
||||||
se.Details = details
|
|
||||||
se.InnerError = inner
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestError describes an error response returned by Azure service.
|
|
||||||
type RequestError struct {
|
|
||||||
autorest.DetailedError
|
|
||||||
|
|
||||||
// The error returned by the Azure service.
|
|
||||||
ServiceError *ServiceError `json:"error"`
|
|
||||||
|
|
||||||
// The request id (from the x-ms-request-id-header) of the request.
|
|
||||||
RequestID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns a human-friendly error message from service error.
|
|
||||||
func (e RequestError) Error() string {
|
|
||||||
return fmt.Sprintf("autorest/azure: Service returned an error. Status=%v %v",
|
|
||||||
e.StatusCode, e.ServiceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAzureError returns true if the passed error is an Azure Service error; false otherwise.
|
|
||||||
func IsAzureError(e error) bool {
|
|
||||||
_, ok := e.(*RequestError)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource contains details about an Azure resource.
|
|
||||||
type Resource struct {
|
|
||||||
SubscriptionID string
|
|
||||||
ResourceGroup string
|
|
||||||
Provider string
|
|
||||||
ResourceType string
|
|
||||||
ResourceName string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseResourceID parses a resource ID into a ResourceDetails struct.
|
|
||||||
// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#return-value-4.
|
|
||||||
func ParseResourceID(resourceID string) (Resource, error) {
|
|
||||||
|
|
||||||
const resourceIDPatternText = `(?i)subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)`
|
|
||||||
resourceIDPattern := regexp.MustCompile(resourceIDPatternText)
|
|
||||||
match := resourceIDPattern.FindStringSubmatch(resourceID)
|
|
||||||
|
|
||||||
if len(match) == 0 {
|
|
||||||
return Resource{}, fmt.Errorf("parsing failed for %s. Invalid resource Id format", resourceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := strings.Split(match[5], "/")
|
|
||||||
resourceName := v[len(v)-1]
|
|
||||||
|
|
||||||
result := Resource{
|
|
||||||
SubscriptionID: match[1],
|
|
||||||
ResourceGroup: match[2],
|
|
||||||
Provider: match[3],
|
|
||||||
ResourceType: match[4],
|
|
||||||
ResourceName: resourceName,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrorWithError creates a new Error conforming object from the
|
|
||||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
|
||||||
// if resp is nil), message, and original error. message is treated as a format
|
|
||||||
// string to which the optional args apply.
|
|
||||||
func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) RequestError {
|
|
||||||
if v, ok := original.(*RequestError); ok {
|
|
||||||
return *v
|
|
||||||
}
|
|
||||||
|
|
||||||
statusCode := autorest.UndefinedStatusCode
|
|
||||||
if resp != nil {
|
|
||||||
statusCode = resp.StatusCode
|
|
||||||
}
|
|
||||||
return RequestError{
|
|
||||||
DetailedError: autorest.DetailedError{
|
|
||||||
Original: original,
|
|
||||||
PackageType: packageType,
|
|
||||||
Method: method,
|
|
||||||
StatusCode: statusCode,
|
|
||||||
Message: fmt.Sprintf(message, args...),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithReturningClientID returns a PrepareDecorator that adds an HTTP extension header of
|
|
||||||
// x-ms-client-request-id whose value is the passed, undecorated UUID (e.g.,
|
|
||||||
// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). It also sets the x-ms-return-client-request-id
|
|
||||||
// header to true such that UUID accompanies the http.Response.
|
|
||||||
func WithReturningClientID(uuid string) autorest.PrepareDecorator {
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
WithClientID(uuid),
|
|
||||||
WithReturnClientID(true))
|
|
||||||
|
|
||||||
return func(p autorest.Preparer) autorest.Preparer {
|
|
||||||
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
return preparer.Prepare(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithClientID returns a PrepareDecorator that adds an HTTP extension header of
|
|
||||||
// x-ms-client-request-id whose value is passed, undecorated UUID (e.g.,
|
|
||||||
// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA").
|
|
||||||
func WithClientID(uuid string) autorest.PrepareDecorator {
|
|
||||||
return autorest.WithHeader(HeaderClientID, uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithReturnClientID returns a PrepareDecorator that adds an HTTP extension header of
|
|
||||||
// x-ms-return-client-request-id whose boolean value indicates if the value of the
|
|
||||||
// x-ms-client-request-id header should be included in the http.Response.
|
|
||||||
func WithReturnClientID(b bool) autorest.PrepareDecorator {
|
|
||||||
return autorest.WithHeader(HeaderReturnClientID, strconv.FormatBool(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractClientID extracts the client identifier from the x-ms-client-request-id header set on the
|
|
||||||
// http.Request sent to the service (and returned in the http.Response)
|
|
||||||
func ExtractClientID(resp *http.Response) string {
|
|
||||||
return autorest.ExtractHeaderValue(HeaderClientID, resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractRequestID extracts the Azure server generated request identifier from the
|
|
||||||
// x-ms-request-id header.
|
|
||||||
func ExtractRequestID(resp *http.Response) string {
|
|
||||||
return autorest.ExtractHeaderValue(HeaderRequestID, resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an
|
|
||||||
// azure.RequestError by reading the response body unless the response HTTP status code
|
|
||||||
// is among the set passed.
|
|
||||||
//
|
|
||||||
// If there is a chance service may return responses other than the Azure error
|
|
||||||
// format and the response cannot be parsed into an error, a decoding error will
|
|
||||||
// be returned containing the response body. In any case, the Responder will
|
|
||||||
// return an error if the status code is not satisfied.
|
|
||||||
//
|
|
||||||
// If this Responder returns an error, the response body will be replaced with
|
|
||||||
// an in-memory reader, which needs no further closing.
|
|
||||||
func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
|
|
||||||
return func(r autorest.Responder) autorest.Responder {
|
|
||||||
return autorest.ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) {
|
|
||||||
var e RequestError
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// Copy and replace the Body in case it does not contain an error object.
|
|
||||||
// This will leave the Body available to the caller.
|
|
||||||
b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e)
|
|
||||||
resp.Body = ioutil.NopCloser(&b)
|
|
||||||
if decodeErr != nil {
|
|
||||||
return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
|
|
||||||
} else if e.ServiceError == nil {
|
|
||||||
// Check if error is unwrapped ServiceError
|
|
||||||
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil || e.ServiceError.Message == "" {
|
|
||||||
e.ServiceError = &ServiceError{
|
|
||||||
Code: "Unknown",
|
|
||||||
Message: "Unknown service error",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.RequestID = ExtractRequestID(resp)
|
|
||||||
if e.StatusCode == nil {
|
|
||||||
e.StatusCode = resp.StatusCode
|
|
||||||
}
|
|
||||||
err = &e
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
191
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
191
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
|
@ -1,191 +0,0 @@
|
||||||
package azure
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EnvironmentFilepathName captures the name of the environment variable containing the path to the file
|
|
||||||
// to be used while populating the Azure Environment.
|
|
||||||
const EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH"
|
|
||||||
|
|
||||||
var environments = map[string]Environment{
|
|
||||||
"AZURECHINACLOUD": ChinaCloud,
|
|
||||||
"AZUREGERMANCLOUD": GermanCloud,
|
|
||||||
"AZUREPUBLICCLOUD": PublicCloud,
|
|
||||||
"AZUREUSGOVERNMENTCLOUD": USGovernmentCloud,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Environment represents a set of endpoints for each of Azure's Clouds.
|
|
||||||
type Environment struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
ManagementPortalURL string `json:"managementPortalURL"`
|
|
||||||
PublishSettingsURL string `json:"publishSettingsURL"`
|
|
||||||
ServiceManagementEndpoint string `json:"serviceManagementEndpoint"`
|
|
||||||
ResourceManagerEndpoint string `json:"resourceManagerEndpoint"`
|
|
||||||
ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"`
|
|
||||||
GalleryEndpoint string `json:"galleryEndpoint"`
|
|
||||||
KeyVaultEndpoint string `json:"keyVaultEndpoint"`
|
|
||||||
GraphEndpoint string `json:"graphEndpoint"`
|
|
||||||
ServiceBusEndpoint string `json:"serviceBusEndpoint"`
|
|
||||||
BatchManagementEndpoint string `json:"batchManagementEndpoint"`
|
|
||||||
StorageEndpointSuffix string `json:"storageEndpointSuffix"`
|
|
||||||
SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
|
|
||||||
TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
|
|
||||||
KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"`
|
|
||||||
ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"`
|
|
||||||
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
|
|
||||||
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
|
|
||||||
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
|
|
||||||
TokenAudience string `json:"tokenAudience"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// PublicCloud is the default public Azure cloud environment
|
|
||||||
PublicCloud = Environment{
|
|
||||||
Name: "AzurePublicCloud",
|
|
||||||
ManagementPortalURL: "https://manage.windowsazure.com/",
|
|
||||||
PublishSettingsURL: "https://manage.windowsazure.com/publishsettings/index",
|
|
||||||
ServiceManagementEndpoint: "https://management.core.windows.net/",
|
|
||||||
ResourceManagerEndpoint: "https://management.azure.com/",
|
|
||||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.com/",
|
|
||||||
GalleryEndpoint: "https://gallery.azure.com/",
|
|
||||||
KeyVaultEndpoint: "https://vault.azure.net/",
|
|
||||||
GraphEndpoint: "https://graph.windows.net/",
|
|
||||||
ServiceBusEndpoint: "https://servicebus.windows.net/",
|
|
||||||
BatchManagementEndpoint: "https://batch.core.windows.net/",
|
|
||||||
StorageEndpointSuffix: "core.windows.net",
|
|
||||||
SQLDatabaseDNSSuffix: "database.windows.net",
|
|
||||||
TrafficManagerDNSSuffix: "trafficmanager.net",
|
|
||||||
KeyVaultDNSSuffix: "vault.azure.net",
|
|
||||||
ServiceBusEndpointSuffix: "servicebus.windows.net",
|
|
||||||
ServiceManagementVMDNSSuffix: "cloudapp.net",
|
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
|
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
|
||||||
TokenAudience: "https://management.azure.com/",
|
|
||||||
}
|
|
||||||
|
|
||||||
// USGovernmentCloud is the cloud environment for the US Government
|
|
||||||
USGovernmentCloud = Environment{
|
|
||||||
Name: "AzureUSGovernmentCloud",
|
|
||||||
ManagementPortalURL: "https://manage.windowsazure.us/",
|
|
||||||
PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index",
|
|
||||||
ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/",
|
|
||||||
ResourceManagerEndpoint: "https://management.usgovcloudapi.net/",
|
|
||||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.us/",
|
|
||||||
GalleryEndpoint: "https://gallery.usgovcloudapi.net/",
|
|
||||||
KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
|
|
||||||
GraphEndpoint: "https://graph.windows.net/",
|
|
||||||
ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/",
|
|
||||||
BatchManagementEndpoint: "https://batch.core.usgovcloudapi.net/",
|
|
||||||
StorageEndpointSuffix: "core.usgovcloudapi.net",
|
|
||||||
SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
|
|
||||||
TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
|
|
||||||
KeyVaultDNSSuffix: "vault.usgovcloudapi.net",
|
|
||||||
ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net",
|
|
||||||
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
|
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
|
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
|
||||||
TokenAudience: "https://management.usgovcloudapi.net/",
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChinaCloud is the cloud environment operated in China
|
|
||||||
ChinaCloud = Environment{
|
|
||||||
Name: "AzureChinaCloud",
|
|
||||||
ManagementPortalURL: "https://manage.chinacloudapi.com/",
|
|
||||||
PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index",
|
|
||||||
ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/",
|
|
||||||
ResourceManagerEndpoint: "https://management.chinacloudapi.cn/",
|
|
||||||
ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/",
|
|
||||||
GalleryEndpoint: "https://gallery.chinacloudapi.cn/",
|
|
||||||
KeyVaultEndpoint: "https://vault.azure.cn/",
|
|
||||||
GraphEndpoint: "https://graph.chinacloudapi.cn/",
|
|
||||||
ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/",
|
|
||||||
BatchManagementEndpoint: "https://batch.chinacloudapi.cn/",
|
|
||||||
StorageEndpointSuffix: "core.chinacloudapi.cn",
|
|
||||||
SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
|
|
||||||
TrafficManagerDNSSuffix: "trafficmanager.cn",
|
|
||||||
KeyVaultDNSSuffix: "vault.azure.cn",
|
|
||||||
ServiceBusEndpointSuffix: "servicebus.chinacloudapi.cn",
|
|
||||||
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
|
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
|
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
|
||||||
TokenAudience: "https://management.chinacloudapi.cn/",
|
|
||||||
}
|
|
||||||
|
|
||||||
// GermanCloud is the cloud environment operated in Germany
|
|
||||||
GermanCloud = Environment{
|
|
||||||
Name: "AzureGermanCloud",
|
|
||||||
ManagementPortalURL: "http://portal.microsoftazure.de/",
|
|
||||||
PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index",
|
|
||||||
ServiceManagementEndpoint: "https://management.core.cloudapi.de/",
|
|
||||||
ResourceManagerEndpoint: "https://management.microsoftazure.de/",
|
|
||||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.de/",
|
|
||||||
GalleryEndpoint: "https://gallery.cloudapi.de/",
|
|
||||||
KeyVaultEndpoint: "https://vault.microsoftazure.de/",
|
|
||||||
GraphEndpoint: "https://graph.cloudapi.de/",
|
|
||||||
ServiceBusEndpoint: "https://servicebus.cloudapi.de/",
|
|
||||||
BatchManagementEndpoint: "https://batch.cloudapi.de/",
|
|
||||||
StorageEndpointSuffix: "core.cloudapi.de",
|
|
||||||
SQLDatabaseDNSSuffix: "database.cloudapi.de",
|
|
||||||
TrafficManagerDNSSuffix: "azuretrafficmanager.de",
|
|
||||||
KeyVaultDNSSuffix: "vault.microsoftazure.de",
|
|
||||||
ServiceBusEndpointSuffix: "servicebus.cloudapi.de",
|
|
||||||
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
|
|
||||||
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
|
|
||||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
|
||||||
TokenAudience: "https://management.microsoftazure.de/",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
245
vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go
generated
vendored
245
vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go
generated
vendored
|
@ -1,245 +0,0 @@
|
||||||
package azure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
type audience []string
|
|
||||||
|
|
||||||
type authentication struct {
|
|
||||||
LoginEndpoint string `json:"loginEndpoint"`
|
|
||||||
Audiences audience `json:"audiences"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type environmentMetadataInfo struct {
|
|
||||||
GalleryEndpoint string `json:"galleryEndpoint"`
|
|
||||||
GraphEndpoint string `json:"graphEndpoint"`
|
|
||||||
PortalEndpoint string `json:"portalEndpoint"`
|
|
||||||
Authentication authentication `json:"authentication"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnvironmentProperty represent property names that clients can override
|
|
||||||
type EnvironmentProperty string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// EnvironmentName ...
|
|
||||||
EnvironmentName EnvironmentProperty = "name"
|
|
||||||
// EnvironmentManagementPortalURL ..
|
|
||||||
EnvironmentManagementPortalURL EnvironmentProperty = "managementPortalURL"
|
|
||||||
// EnvironmentPublishSettingsURL ...
|
|
||||||
EnvironmentPublishSettingsURL EnvironmentProperty = "publishSettingsURL"
|
|
||||||
// EnvironmentServiceManagementEndpoint ...
|
|
||||||
EnvironmentServiceManagementEndpoint EnvironmentProperty = "serviceManagementEndpoint"
|
|
||||||
// EnvironmentResourceManagerEndpoint ...
|
|
||||||
EnvironmentResourceManagerEndpoint EnvironmentProperty = "resourceManagerEndpoint"
|
|
||||||
// EnvironmentActiveDirectoryEndpoint ...
|
|
||||||
EnvironmentActiveDirectoryEndpoint EnvironmentProperty = "activeDirectoryEndpoint"
|
|
||||||
// EnvironmentGalleryEndpoint ...
|
|
||||||
EnvironmentGalleryEndpoint EnvironmentProperty = "galleryEndpoint"
|
|
||||||
// EnvironmentKeyVaultEndpoint ...
|
|
||||||
EnvironmentKeyVaultEndpoint EnvironmentProperty = "keyVaultEndpoint"
|
|
||||||
// EnvironmentGraphEndpoint ...
|
|
||||||
EnvironmentGraphEndpoint EnvironmentProperty = "graphEndpoint"
|
|
||||||
// EnvironmentServiceBusEndpoint ...
|
|
||||||
EnvironmentServiceBusEndpoint EnvironmentProperty = "serviceBusEndpoint"
|
|
||||||
// EnvironmentBatchManagementEndpoint ...
|
|
||||||
EnvironmentBatchManagementEndpoint EnvironmentProperty = "batchManagementEndpoint"
|
|
||||||
// EnvironmentStorageEndpointSuffix ...
|
|
||||||
EnvironmentStorageEndpointSuffix EnvironmentProperty = "storageEndpointSuffix"
|
|
||||||
// EnvironmentSQLDatabaseDNSSuffix ...
|
|
||||||
EnvironmentSQLDatabaseDNSSuffix EnvironmentProperty = "sqlDatabaseDNSSuffix"
|
|
||||||
// EnvironmentTrafficManagerDNSSuffix ...
|
|
||||||
EnvironmentTrafficManagerDNSSuffix EnvironmentProperty = "trafficManagerDNSSuffix"
|
|
||||||
// EnvironmentKeyVaultDNSSuffix ...
|
|
||||||
EnvironmentKeyVaultDNSSuffix EnvironmentProperty = "keyVaultDNSSuffix"
|
|
||||||
// EnvironmentServiceBusEndpointSuffix ...
|
|
||||||
EnvironmentServiceBusEndpointSuffix EnvironmentProperty = "serviceBusEndpointSuffix"
|
|
||||||
// EnvironmentServiceManagementVMDNSSuffix ...
|
|
||||||
EnvironmentServiceManagementVMDNSSuffix EnvironmentProperty = "serviceManagementVMDNSSuffix"
|
|
||||||
// EnvironmentResourceManagerVMDNSSuffix ...
|
|
||||||
EnvironmentResourceManagerVMDNSSuffix EnvironmentProperty = "resourceManagerVMDNSSuffix"
|
|
||||||
// EnvironmentContainerRegistryDNSSuffix ...
|
|
||||||
EnvironmentContainerRegistryDNSSuffix EnvironmentProperty = "containerRegistryDNSSuffix"
|
|
||||||
// EnvironmentTokenAudience ...
|
|
||||||
EnvironmentTokenAudience EnvironmentProperty = "tokenAudience"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OverrideProperty represents property name and value that clients can override
|
|
||||||
type OverrideProperty struct {
|
|
||||||
Key EnvironmentProperty
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnvironmentFromURL loads an Environment from a URL
|
|
||||||
// This function is particularly useful in the Hybrid Cloud model, where one may define their own
|
|
||||||
// endpoints.
|
|
||||||
func EnvironmentFromURL(resourceManagerEndpoint string, properties ...OverrideProperty) (environment Environment, err error) {
|
|
||||||
var metadataEnvProperties environmentMetadataInfo
|
|
||||||
|
|
||||||
if resourceManagerEndpoint == "" {
|
|
||||||
return environment, fmt.Errorf("Metadata resource manager endpoint is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadataEnvProperties, err = retrieveMetadataEnvironment(resourceManagerEndpoint); err != nil {
|
|
||||||
return environment, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give priority to user's override values
|
|
||||||
overrideProperties(&environment, properties)
|
|
||||||
|
|
||||||
if environment.Name == "" {
|
|
||||||
environment.Name = "HybridEnvironment"
|
|
||||||
}
|
|
||||||
stampDNSSuffix := environment.StorageEndpointSuffix
|
|
||||||
if stampDNSSuffix == "" {
|
|
||||||
stampDNSSuffix = strings.TrimSuffix(strings.TrimPrefix(strings.Replace(resourceManagerEndpoint, strings.Split(resourceManagerEndpoint, ".")[0], "", 1), "."), "/")
|
|
||||||
environment.StorageEndpointSuffix = stampDNSSuffix
|
|
||||||
}
|
|
||||||
if environment.KeyVaultDNSSuffix == "" {
|
|
||||||
environment.KeyVaultDNSSuffix = fmt.Sprintf("%s.%s", "vault", stampDNSSuffix)
|
|
||||||
}
|
|
||||||
if environment.KeyVaultEndpoint == "" {
|
|
||||||
environment.KeyVaultEndpoint = fmt.Sprintf("%s%s", "https://", environment.KeyVaultDNSSuffix)
|
|
||||||
}
|
|
||||||
if environment.TokenAudience == "" {
|
|
||||||
environment.TokenAudience = metadataEnvProperties.Authentication.Audiences[0]
|
|
||||||
}
|
|
||||||
if environment.ActiveDirectoryEndpoint == "" {
|
|
||||||
environment.ActiveDirectoryEndpoint = metadataEnvProperties.Authentication.LoginEndpoint
|
|
||||||
}
|
|
||||||
if environment.ResourceManagerEndpoint == "" {
|
|
||||||
environment.ResourceManagerEndpoint = resourceManagerEndpoint
|
|
||||||
}
|
|
||||||
if environment.GalleryEndpoint == "" {
|
|
||||||
environment.GalleryEndpoint = metadataEnvProperties.GalleryEndpoint
|
|
||||||
}
|
|
||||||
if environment.GraphEndpoint == "" {
|
|
||||||
environment.GraphEndpoint = metadataEnvProperties.GraphEndpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
return environment, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func overrideProperties(environment *Environment, properties []OverrideProperty) {
|
|
||||||
for _, property := range properties {
|
|
||||||
switch property.Key {
|
|
||||||
case EnvironmentName:
|
|
||||||
{
|
|
||||||
environment.Name = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentManagementPortalURL:
|
|
||||||
{
|
|
||||||
environment.ManagementPortalURL = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentPublishSettingsURL:
|
|
||||||
{
|
|
||||||
environment.PublishSettingsURL = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentServiceManagementEndpoint:
|
|
||||||
{
|
|
||||||
environment.ServiceManagementEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentResourceManagerEndpoint:
|
|
||||||
{
|
|
||||||
environment.ResourceManagerEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentActiveDirectoryEndpoint:
|
|
||||||
{
|
|
||||||
environment.ActiveDirectoryEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentGalleryEndpoint:
|
|
||||||
{
|
|
||||||
environment.GalleryEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentKeyVaultEndpoint:
|
|
||||||
{
|
|
||||||
environment.KeyVaultEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentGraphEndpoint:
|
|
||||||
{
|
|
||||||
environment.GraphEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentServiceBusEndpoint:
|
|
||||||
{
|
|
||||||
environment.ServiceBusEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentBatchManagementEndpoint:
|
|
||||||
{
|
|
||||||
environment.BatchManagementEndpoint = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentStorageEndpointSuffix:
|
|
||||||
{
|
|
||||||
environment.StorageEndpointSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentSQLDatabaseDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.SQLDatabaseDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentTrafficManagerDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.TrafficManagerDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentKeyVaultDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.KeyVaultDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentServiceBusEndpointSuffix:
|
|
||||||
{
|
|
||||||
environment.ServiceBusEndpointSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentServiceManagementVMDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.ServiceManagementVMDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentResourceManagerVMDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.ResourceManagerVMDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentContainerRegistryDNSSuffix:
|
|
||||||
{
|
|
||||||
environment.ContainerRegistryDNSSuffix = property.Value
|
|
||||||
}
|
|
||||||
case EnvironmentTokenAudience:
|
|
||||||
{
|
|
||||||
environment.TokenAudience = property.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func retrieveMetadataEnvironment(endpoint string) (environment environmentMetadataInfo, err error) {
|
|
||||||
client := autorest.NewClientWithUserAgent("")
|
|
||||||
managementEndpoint := fmt.Sprintf("%s%s", strings.TrimSuffix(endpoint, "/"), "/metadata/endpoints?api-version=1.0")
|
|
||||||
req, _ := http.NewRequest("GET", managementEndpoint, nil)
|
|
||||||
response, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return environment, err
|
|
||||||
}
|
|
||||||
defer response.Body.Close()
|
|
||||||
jsonResponse, err := ioutil.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return environment, err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(jsonResponse, &environment)
|
|
||||||
return environment, err
|
|
||||||
}
|
|
200
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
200
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
|
@ -1,200 +0,0 @@
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package azure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DoRetryWithRegistration tries to register the resource provider in case it is unregistered.
|
|
||||||
// It also handles request retries
|
|
||||||
func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator {
|
|
||||||
return func(s autorest.Sender) autorest.Sender {
|
|
||||||
return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
rr := autorest.NewRetriableRequest(r)
|
|
||||||
for currentAttempt := 0; currentAttempt < client.RetryAttempts; currentAttempt++ {
|
|
||||||
err = rr.Prepare()
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err = autorest.SendWithSender(s, rr.Request(),
|
|
||||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusConflict || client.SkipResourceProviderRegistration {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
var re RequestError
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
autorest.ByUnmarshallingJSON(&re),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
err = re
|
|
||||||
|
|
||||||
if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" {
|
|
||||||
regErr := register(client, r, re)
|
|
||||||
if regErr != nil {
|
|
||||||
return resp, fmt.Errorf("failed auto registering Resource Provider: %s. Original error: %s", regErr, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, fmt.Errorf("failed request: %s", err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getProvider(re RequestError) (string, error) {
|
|
||||||
if re.ServiceError != nil && len(re.ServiceError.Details) > 0 {
|
|
||||||
return re.ServiceError.Details[0]["target"].(string), nil
|
|
||||||
}
|
|
||||||
return "", errors.New("provider was not found in the response")
|
|
||||||
}
|
|
||||||
|
|
||||||
func register(client autorest.Client, originalReq *http.Request, re RequestError) error {
|
|
||||||
subID := getSubscription(originalReq.URL.Path)
|
|
||||||
if subID == "" {
|
|
||||||
return errors.New("missing parameter subscriptionID to register resource provider")
|
|
||||||
}
|
|
||||||
providerName, err := getProvider(re)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("missing parameter provider to register resource provider: %s", err)
|
|
||||||
}
|
|
||||||
newURL := url.URL{
|
|
||||||
Scheme: originalReq.URL.Scheme,
|
|
||||||
Host: originalReq.URL.Host,
|
|
||||||
}
|
|
||||||
|
|
||||||
// taken from the resources SDK
|
|
||||||
// with almost identical code, this sections are easier to mantain
|
|
||||||
// It is also not a good idea to import the SDK here
|
|
||||||
// https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L252
|
|
||||||
pathParameters := map[string]interface{}{
|
|
||||||
"resourceProviderNamespace": autorest.Encode("path", providerName),
|
|
||||||
"subscriptionId": autorest.Encode("path", subID),
|
|
||||||
}
|
|
||||||
|
|
||||||
const APIVersion = "2016-09-01"
|
|
||||||
queryParameters := map[string]interface{}{
|
|
||||||
"api-version": APIVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsPost(),
|
|
||||||
autorest.WithBaseURL(newURL.String()),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters),
|
|
||||||
)
|
|
||||||
|
|
||||||
req, err := preparer.Prepare(&http.Request{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req = req.WithContext(originalReq.Context())
|
|
||||||
|
|
||||||
resp, err := autorest.SendWithSender(client, req,
|
|
||||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type Provider struct {
|
|
||||||
RegistrationState *string `json:"registrationState,omitempty"`
|
|
||||||
}
|
|
||||||
var provider Provider
|
|
||||||
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&provider),
|
|
||||||
autorest.ByClosing(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// poll for registered provisioning state
|
|
||||||
now := time.Now()
|
|
||||||
for err == nil && time.Since(now) < client.PollingDuration {
|
|
||||||
// taken from the resources SDK
|
|
||||||
// https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L45
|
|
||||||
preparer := autorest.CreatePreparer(
|
|
||||||
autorest.AsGet(),
|
|
||||||
autorest.WithBaseURL(newURL.String()),
|
|
||||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", pathParameters),
|
|
||||||
autorest.WithQueryParameters(queryParameters),
|
|
||||||
)
|
|
||||||
req, err = preparer.Prepare(&http.Request{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req = req.WithContext(originalReq.Context())
|
|
||||||
|
|
||||||
resp, err := autorest.SendWithSender(client, req,
|
|
||||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = autorest.Respond(
|
|
||||||
resp,
|
|
||||||
WithErrorUnlessStatusCode(http.StatusOK),
|
|
||||||
autorest.ByUnmarshallingJSON(&provider),
|
|
||||||
autorest.ByClosing(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if provider.RegistrationState != nil &&
|
|
||||||
*provider.RegistrationState == "Registered" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
delayed := autorest.DelayWithRetryAfter(resp, originalReq.Context().Done())
|
|
||||||
if !delayed && !autorest.DelayForBackoff(client.PollingDelay, 0, originalReq.Context().Done()) {
|
|
||||||
return originalReq.Context().Err()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !(time.Since(now) < client.PollingDuration) {
|
|
||||||
return errors.New("polling for resource provider registration has exceeded the polling duration")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSubscription(path string) string {
|
|
||||||
parts := strings.Split(path, "/")
|
|
||||||
for i, v := range parts {
|
|
||||||
if v == "subscriptions" && (i+1) < len(parts) {
|
|
||||||
return parts[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
264
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
264
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
|
@ -1,264 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/http/cookiejar"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DefaultPollingDelay is a reasonable delay between polling requests.
|
|
||||||
DefaultPollingDelay = 60 * time.Second
|
|
||||||
|
|
||||||
// DefaultPollingDuration is a reasonable total polling duration.
|
|
||||||
DefaultPollingDuration = 15 * time.Minute
|
|
||||||
|
|
||||||
// DefaultRetryAttempts is number of attempts for retry status codes (5xx).
|
|
||||||
DefaultRetryAttempts = 3
|
|
||||||
|
|
||||||
// DefaultRetryDuration is the duration to wait between retries.
|
|
||||||
DefaultRetryDuration = 30 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// defaultUserAgent builds a string containing the Go version, system archityecture and OS,
|
|
||||||
// and the go-autorest version.
|
|
||||||
defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
|
|
||||||
runtime.Version(),
|
|
||||||
runtime.GOARCH,
|
|
||||||
runtime.GOOS,
|
|
||||||
Version(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// StatusCodesForRetry are a defined group of status code for which the client will retry
|
|
||||||
StatusCodesForRetry = []int{
|
|
||||||
http.StatusRequestTimeout, // 408
|
|
||||||
http.StatusTooManyRequests, // 429
|
|
||||||
http.StatusInternalServerError, // 500
|
|
||||||
http.StatusBadGateway, // 502
|
|
||||||
http.StatusServiceUnavailable, // 503
|
|
||||||
http.StatusGatewayTimeout, // 504
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
requestFormat = `HTTP Request Begin ===================================================
|
|
||||||
%s
|
|
||||||
===================================================== HTTP Request End
|
|
||||||
`
|
|
||||||
responseFormat = `HTTP Response Begin ===================================================
|
|
||||||
%s
|
|
||||||
===================================================== HTTP Response End
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
// Response serves as the base for all responses from generated clients. It provides access to the
|
|
||||||
// last http.Response.
|
|
||||||
type Response struct {
|
|
||||||
*http.Response `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoggingInspector implements request and response inspectors that log the full request and
|
|
||||||
// response to a supplied log.
|
|
||||||
type LoggingInspector struct {
|
|
||||||
Logger *log.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The
|
|
||||||
// body is restored after being emitted.
|
|
||||||
//
|
|
||||||
// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
|
|
||||||
// important. It is best used to trace JSON or similar body values.
|
|
||||||
func (li LoggingInspector) WithInspection() PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
var body, b bytes.Buffer
|
|
||||||
|
|
||||||
defer r.Body.Close()
|
|
||||||
|
|
||||||
r.Body = ioutil.NopCloser(io.TeeReader(r.Body, &body))
|
|
||||||
if err := r.Write(&b); err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to write response: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
li.Logger.Printf(requestFormat, b.String())
|
|
||||||
|
|
||||||
r.Body = ioutil.NopCloser(&body)
|
|
||||||
return p.Prepare(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The
|
|
||||||
// body is restored after being emitted.
|
|
||||||
//
|
|
||||||
// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
|
|
||||||
// important. It is best used to trace JSON or similar body values.
|
|
||||||
func (li LoggingInspector) ByInspecting() RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
var body, b bytes.Buffer
|
|
||||||
defer resp.Body.Close()
|
|
||||||
resp.Body = ioutil.NopCloser(io.TeeReader(resp.Body, &body))
|
|
||||||
if err := resp.Write(&b); err != nil {
|
|
||||||
return fmt.Errorf("Failed to write response: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
li.Logger.Printf(responseFormat, b.String())
|
|
||||||
|
|
||||||
resp.Body = ioutil.NopCloser(&body)
|
|
||||||
return r.Respond(resp)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client is the base for autorest generated clients. It provides default, "do nothing"
|
|
||||||
// implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the
|
|
||||||
// standard, undecorated http.Client as a default Sender.
|
|
||||||
//
|
|
||||||
// Generated clients should also use Error (see NewError and NewErrorWithError) for errors and
|
|
||||||
// return responses that compose with Response.
|
|
||||||
//
|
|
||||||
// Most customization of generated clients is best achieved by supplying a custom Authorizer, custom
|
|
||||||
// RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit
|
|
||||||
// breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence
|
|
||||||
// sending the request by providing a decorated Sender.
|
|
||||||
type Client struct {
|
|
||||||
Authorizer Authorizer
|
|
||||||
Sender Sender
|
|
||||||
RequestInspector PrepareDecorator
|
|
||||||
ResponseInspector RespondDecorator
|
|
||||||
|
|
||||||
// PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header
|
|
||||||
PollingDelay time.Duration
|
|
||||||
|
|
||||||
// PollingDuration sets the maximum polling time after which an error is returned.
|
|
||||||
PollingDuration time.Duration
|
|
||||||
|
|
||||||
// RetryAttempts sets the default number of retry attempts for client.
|
|
||||||
RetryAttempts int
|
|
||||||
|
|
||||||
// RetryDuration sets the delay duration for retries.
|
|
||||||
RetryDuration time.Duration
|
|
||||||
|
|
||||||
// UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent
|
|
||||||
// through the Do method.
|
|
||||||
UserAgent string
|
|
||||||
|
|
||||||
Jar http.CookieJar
|
|
||||||
|
|
||||||
// Set to true to skip attempted registration of resource providers (false by default).
|
|
||||||
SkipResourceProviderRegistration bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed
|
|
||||||
// string.
|
|
||||||
func NewClientWithUserAgent(ua string) Client {
|
|
||||||
c := Client{
|
|
||||||
PollingDelay: DefaultPollingDelay,
|
|
||||||
PollingDuration: DefaultPollingDuration,
|
|
||||||
RetryAttempts: DefaultRetryAttempts,
|
|
||||||
RetryDuration: DefaultRetryDuration,
|
|
||||||
UserAgent: defaultUserAgent,
|
|
||||||
}
|
|
||||||
c.Sender = c.sender()
|
|
||||||
c.AddToUserAgent(ua)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddToUserAgent adds an extension to the current user agent
|
|
||||||
func (c *Client) AddToUserAgent(extension string) error {
|
|
||||||
if extension != "" {
|
|
||||||
c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do implements the Sender interface by invoking the active Sender after applying authorization.
|
|
||||||
// If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent
|
|
||||||
// is set, apply set the User-Agent header.
|
|
||||||
func (c Client) Do(r *http.Request) (*http.Response, error) {
|
|
||||||
if r.UserAgent() == "" {
|
|
||||||
r, _ = Prepare(r,
|
|
||||||
WithUserAgent(c.UserAgent))
|
|
||||||
}
|
|
||||||
// NOTE: c.WithInspection() must be last in the list so that it can inspect all preceding operations
|
|
||||||
r, err := Prepare(r,
|
|
||||||
c.WithAuthorization(),
|
|
||||||
c.WithInspection())
|
|
||||||
if err != nil {
|
|
||||||
var resp *http.Response
|
|
||||||
if detErr, ok := err.(DetailedError); ok {
|
|
||||||
// if the authorization failed (e.g. invalid credentials) there will
|
|
||||||
// be a response associated with the error, be sure to return it.
|
|
||||||
resp = detErr.Response
|
|
||||||
}
|
|
||||||
return resp, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := SendWithSender(c.sender(), r)
|
|
||||||
Respond(resp, c.ByInspecting())
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// sender returns the Sender to which to send requests.
|
|
||||||
func (c Client) sender() Sender {
|
|
||||||
if c.Sender == nil {
|
|
||||||
j, _ := cookiejar.New(nil)
|
|
||||||
return &http.Client{Jar: j}
|
|
||||||
}
|
|
||||||
return c.Sender
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator
|
|
||||||
// from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer.
|
|
||||||
func (c Client) WithAuthorization() PrepareDecorator {
|
|
||||||
return c.authorizer().WithAuthorization()
|
|
||||||
}
|
|
||||||
|
|
||||||
// authorizer returns the Authorizer to use.
|
|
||||||
func (c Client) authorizer() Authorizer {
|
|
||||||
if c.Authorizer == nil {
|
|
||||||
return NullAuthorizer{}
|
|
||||||
}
|
|
||||||
return c.Authorizer
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithInspection is a convenience method that passes the request to the supplied RequestInspector,
|
|
||||||
// if present, or returns the WithNothing PrepareDecorator otherwise.
|
|
||||||
func (c Client) WithInspection() PrepareDecorator {
|
|
||||||
if c.RequestInspector == nil {
|
|
||||||
return WithNothing()
|
|
||||||
}
|
|
||||||
return c.RequestInspector
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByInspecting is a convenience method that passes the response to the supplied ResponseInspector,
|
|
||||||
// if present, or returns the ByIgnoring RespondDecorator otherwise.
|
|
||||||
func (c Client) ByInspecting() RespondDecorator {
|
|
||||||
if c.ResponseInspector == nil {
|
|
||||||
return ByIgnoring()
|
|
||||||
}
|
|
||||||
return c.ResponseInspector
|
|
||||||
}
|
|
96
vendor/github.com/Azure/go-autorest/autorest/date/date.go
generated
vendored
96
vendor/github.com/Azure/go-autorest/autorest/date/date.go
generated
vendored
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/)
|
|
||||||
defined date formats: Date and DateTime. Both types may, in most cases, be used in lieu of
|
|
||||||
time.Time types. And both convert to time.Time through a ToTime method.
|
|
||||||
*/
|
|
||||||
package date
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
fullDate = "2006-01-02"
|
|
||||||
fullDateJSON = `"2006-01-02"`
|
|
||||||
dateFormat = "%04d-%02d-%02d"
|
|
||||||
jsonFormat = `"%04d-%02d-%02d"`
|
|
||||||
)
|
|
||||||
|
|
||||||
// Date defines a type similar to time.Time but assumes a layout of RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
type Date struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDate create a new Date from the passed string.
|
|
||||||
func ParseDate(date string) (d Date, err error) {
|
|
||||||
return parseDate(date, fullDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDate(date string, format string) (Date, error) {
|
|
||||||
d, err := time.Parse(format, date)
|
|
||||||
return Date{Time: d}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary preserves the Date as a byte array conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d Date) MarshalBinary() ([]byte, error) {
|
|
||||||
return d.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d *Date) UnmarshalBinary(data []byte) error {
|
|
||||||
return d.UnmarshalText(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON preserves the Date as a JSON string conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d Date) MarshalJSON() (json []byte, err error) {
|
|
||||||
return []byte(fmt.Sprintf(jsonFormat, d.Year(), d.Month(), d.Day())), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON reconstitutes the Date from a JSON string conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d *Date) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
d.Time, err = time.Parse(fullDateJSON, string(data))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText preserves the Date as a byte array conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d Date) MarshalText() (text []byte, err error) {
|
|
||||||
return []byte(fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e.,
|
|
||||||
// 2006-01-02).
|
|
||||||
func (d *Date) UnmarshalText(data []byte) (err error) {
|
|
||||||
d.Time, err = time.Parse(fullDate, string(data))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the Date formatted as an RFC3339 full-date string (i.e., 2006-01-02).
|
|
||||||
func (d Date) String() string {
|
|
||||||
return fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToTime returns a Date as a time.Time
|
|
||||||
func (d Date) ToTime() time.Time {
|
|
||||||
return d.Time
|
|
||||||
}
|
|
103
vendor/github.com/Azure/go-autorest/autorest/date/time.go
generated
vendored
103
vendor/github.com/Azure/go-autorest/autorest/date/time.go
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
package date
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases.
|
|
||||||
const (
|
|
||||||
azureUtcFormatJSON = `"2006-01-02T15:04:05.999999999"`
|
|
||||||
azureUtcFormat = "2006-01-02T15:04:05.999999999"
|
|
||||||
rfc3339JSON = `"` + time.RFC3339Nano + `"`
|
|
||||||
rfc3339 = time.RFC3339Nano
|
|
||||||
tzOffsetRegex = `(Z|z|\+|-)(\d+:\d+)*"*$`
|
|
||||||
)
|
|
||||||
|
|
||||||
// Time defines a type similar to time.Time but assumes a layout of RFC3339 date-time (i.e.,
|
|
||||||
// 2006-01-02T15:04:05Z).
|
|
||||||
type Time struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary preserves the Time as a byte array conforming to RFC3339 date-time (i.e.,
|
|
||||||
// 2006-01-02T15:04:05Z).
|
|
||||||
func (t Time) MarshalBinary() ([]byte, error) {
|
|
||||||
return t.Time.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC3339 date-time
|
|
||||||
// (i.e., 2006-01-02T15:04:05Z).
|
|
||||||
func (t *Time) UnmarshalBinary(data []byte) error {
|
|
||||||
return t.UnmarshalText(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON preserves the Time as a JSON string conforming to RFC3339 date-time (i.e.,
|
|
||||||
// 2006-01-02T15:04:05Z).
|
|
||||||
func (t Time) MarshalJSON() (json []byte, err error) {
|
|
||||||
return t.Time.MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC3339 date-time
|
|
||||||
// (i.e., 2006-01-02T15:04:05Z).
|
|
||||||
func (t *Time) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
timeFormat := azureUtcFormatJSON
|
|
||||||
match, err := regexp.Match(tzOffsetRegex, data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if match {
|
|
||||||
timeFormat = rfc3339JSON
|
|
||||||
}
|
|
||||||
t.Time, err = ParseTime(timeFormat, string(data))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText preserves the Time as a byte array conforming to RFC3339 date-time (i.e.,
|
|
||||||
// 2006-01-02T15:04:05Z).
|
|
||||||
func (t Time) MarshalText() (text []byte, err error) {
|
|
||||||
return t.Time.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC3339 date-time
|
|
||||||
// (i.e., 2006-01-02T15:04:05Z).
|
|
||||||
func (t *Time) UnmarshalText(data []byte) (err error) {
|
|
||||||
timeFormat := azureUtcFormat
|
|
||||||
match, err := regexp.Match(tzOffsetRegex, data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if match {
|
|
||||||
timeFormat = rfc3339
|
|
||||||
}
|
|
||||||
t.Time, err = ParseTime(timeFormat, string(data))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the Time formatted as an RFC3339 date-time string (i.e.,
|
|
||||||
// 2006-01-02T15:04:05Z).
|
|
||||||
func (t Time) String() string {
|
|
||||||
// Note: time.Time.String does not return an RFC3339 compliant string, time.Time.MarshalText does.
|
|
||||||
b, err := t.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToTime returns a Time as a time.Time
|
|
||||||
func (t Time) ToTime() time.Time {
|
|
||||||
return t.Time
|
|
||||||
}
|
|
100
vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go
generated
vendored
100
vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go
generated
vendored
|
@ -1,100 +0,0 @@
|
||||||
package date
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
rfc1123JSON = `"` + time.RFC1123 + `"`
|
|
||||||
rfc1123 = time.RFC1123
|
|
||||||
)
|
|
||||||
|
|
||||||
// TimeRFC1123 defines a type similar to time.Time but assumes a layout of RFC1123 date-time (i.e.,
|
|
||||||
// Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
type TimeRFC1123 struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC1123 date-time
|
|
||||||
// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t *TimeRFC1123) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
t.Time, err = ParseTime(rfc1123JSON, string(data))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON preserves the Time as a JSON string conforming to RFC1123 date-time (i.e.,
|
|
||||||
// Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t TimeRFC1123) MarshalJSON() ([]byte, error) {
|
|
||||||
if y := t.Year(); y < 0 || y >= 10000 {
|
|
||||||
return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
|
|
||||||
}
|
|
||||||
b := []byte(t.Format(rfc1123JSON))
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText preserves the Time as a byte array conforming to RFC1123 date-time (i.e.,
|
|
||||||
// Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t TimeRFC1123) MarshalText() ([]byte, error) {
|
|
||||||
if y := t.Year(); y < 0 || y >= 10000 {
|
|
||||||
return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
|
|
||||||
}
|
|
||||||
|
|
||||||
b := []byte(t.Format(rfc1123))
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC1123 date-time
|
|
||||||
// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t *TimeRFC1123) UnmarshalText(data []byte) (err error) {
|
|
||||||
t.Time, err = ParseTime(rfc1123, string(data))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary preserves the Time as a byte array conforming to RFC1123 date-time (i.e.,
|
|
||||||
// Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t TimeRFC1123) MarshalBinary() ([]byte, error) {
|
|
||||||
return t.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC1123 date-time
|
|
||||||
// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t *TimeRFC1123) UnmarshalBinary(data []byte) error {
|
|
||||||
return t.UnmarshalText(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToTime returns a Time as a time.Time
|
|
||||||
func (t TimeRFC1123) ToTime() time.Time {
|
|
||||||
return t.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the Time formatted as an RFC1123 date-time string (i.e.,
|
|
||||||
// Mon, 02 Jan 2006 15:04:05 MST).
|
|
||||||
func (t TimeRFC1123) String() string {
|
|
||||||
// Note: time.Time.String does not return an RFC1123 compliant string, time.Time.MarshalText does.
|
|
||||||
b, err := t.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
123
vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go
generated
vendored
123
vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
package date
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// unixEpoch is the moment in time that should be treated as timestamp 0.
|
|
||||||
var unixEpoch = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC)
|
|
||||||
|
|
||||||
// UnixTime marshals and unmarshals a time that is represented as the number
|
|
||||||
// of seconds (ignoring skip-seconds) since the Unix Epoch.
|
|
||||||
type UnixTime time.Time
|
|
||||||
|
|
||||||
// Duration returns the time as a Duration since the UnixEpoch.
|
|
||||||
func (t UnixTime) Duration() time.Duration {
|
|
||||||
return time.Time(t).Sub(unixEpoch)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnixTimeFromSeconds creates a UnixTime as a number of seconds from the UnixEpoch.
|
|
||||||
func NewUnixTimeFromSeconds(seconds float64) UnixTime {
|
|
||||||
return NewUnixTimeFromDuration(time.Duration(seconds * float64(time.Second)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnixTimeFromNanoseconds creates a UnixTime as a number of nanoseconds from the UnixEpoch.
|
|
||||||
func NewUnixTimeFromNanoseconds(nanoseconds int64) UnixTime {
|
|
||||||
return NewUnixTimeFromDuration(time.Duration(nanoseconds))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnixTimeFromDuration creates a UnixTime as a duration of time since the UnixEpoch.
|
|
||||||
func NewUnixTimeFromDuration(dur time.Duration) UnixTime {
|
|
||||||
return UnixTime(unixEpoch.Add(dur))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnixEpoch retreives the moment considered the Unix Epoch. I.e. The time represented by '0'
|
|
||||||
func UnixEpoch() time.Time {
|
|
||||||
return unixEpoch
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON preserves the UnixTime as a JSON number conforming to Unix Timestamp requirements.
|
|
||||||
// (i.e. the number of seconds since midnight January 1st, 1970 not considering leap seconds.)
|
|
||||||
func (t UnixTime) MarshalJSON() ([]byte, error) {
|
|
||||||
buffer := &bytes.Buffer{}
|
|
||||||
enc := json.NewEncoder(buffer)
|
|
||||||
err := enc.Encode(float64(time.Time(t).UnixNano()) / 1e9)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return buffer.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON reconstitures a UnixTime saved as a JSON number of the number of seconds since
|
|
||||||
// midnight January 1st, 1970.
|
|
||||||
func (t *UnixTime) UnmarshalJSON(text []byte) error {
|
|
||||||
dec := json.NewDecoder(bytes.NewReader(text))
|
|
||||||
|
|
||||||
var secondsSinceEpoch float64
|
|
||||||
if err := dec.Decode(&secondsSinceEpoch); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*t = NewUnixTimeFromSeconds(secondsSinceEpoch)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText stores the number of seconds since the Unix Epoch as a textual floating point number.
|
|
||||||
func (t UnixTime) MarshalText() ([]byte, error) {
|
|
||||||
cast := time.Time(t)
|
|
||||||
return cast.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText populates a UnixTime with a value stored textually as a floating point number of seconds since the Unix Epoch.
|
|
||||||
func (t *UnixTime) UnmarshalText(raw []byte) error {
|
|
||||||
var unmarshaled time.Time
|
|
||||||
|
|
||||||
if err := unmarshaled.UnmarshalText(raw); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*t = UnixTime(unmarshaled)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary converts a UnixTime into a binary.LittleEndian float64 of nanoseconds since the epoch.
|
|
||||||
func (t UnixTime) MarshalBinary() ([]byte, error) {
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
payload := int64(t.Duration())
|
|
||||||
|
|
||||||
if err := binary.Write(buf, binary.LittleEndian, &payload); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary converts a from a binary.LittleEndian float64 of nanoseconds since the epoch into a UnixTime.
|
|
||||||
func (t *UnixTime) UnmarshalBinary(raw []byte) error {
|
|
||||||
var nanosecondsSinceEpoch int64
|
|
||||||
|
|
||||||
if err := binary.Read(bytes.NewReader(raw), binary.LittleEndian, &nanosecondsSinceEpoch); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*t = NewUnixTimeFromNanoseconds(nanosecondsSinceEpoch)
|
|
||||||
return nil
|
|
||||||
}
|
|
25
vendor/github.com/Azure/go-autorest/autorest/date/utility.go
generated
vendored
25
vendor/github.com/Azure/go-autorest/autorest/date/utility.go
generated
vendored
|
@ -1,25 +0,0 @@
|
||||||
package date
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ParseTime to parse Time string to specified format.
|
|
||||||
func ParseTime(format string, t string) (d time.Time, err error) {
|
|
||||||
return time.Parse(format, strings.ToUpper(t))
|
|
||||||
}
|
|
98
vendor/github.com/Azure/go-autorest/autorest/error.go
generated
vendored
98
vendor/github.com/Azure/go-autorest/autorest/error.go
generated
vendored
|
@ -1,98 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// UndefinedStatusCode is used when HTTP status code is not available for an error.
|
|
||||||
UndefinedStatusCode = 0
|
|
||||||
)
|
|
||||||
|
|
||||||
// DetailedError encloses a error with details of the package, method, and associated HTTP
|
|
||||||
// status code (if any).
|
|
||||||
type DetailedError struct {
|
|
||||||
Original error
|
|
||||||
|
|
||||||
// PackageType is the package type of the object emitting the error. For types, the value
|
|
||||||
// matches that produced the the '%T' format specifier of the fmt package. For other elements,
|
|
||||||
// such as functions, it is just the package name (e.g., "autorest").
|
|
||||||
PackageType string
|
|
||||||
|
|
||||||
// Method is the name of the method raising the error.
|
|
||||||
Method string
|
|
||||||
|
|
||||||
// StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error.
|
|
||||||
StatusCode interface{}
|
|
||||||
|
|
||||||
// Message is the error message.
|
|
||||||
Message string
|
|
||||||
|
|
||||||
// Service Error is the response body of failed API in bytes
|
|
||||||
ServiceError []byte
|
|
||||||
|
|
||||||
// Response is the response object that was returned during failure if applicable.
|
|
||||||
Response *http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewError creates a new Error conforming object from the passed packageType, method, and
|
|
||||||
// message. message is treated as a format string to which the optional args apply.
|
|
||||||
func NewError(packageType string, method string, message string, args ...interface{}) DetailedError {
|
|
||||||
return NewErrorWithError(nil, packageType, method, nil, message, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrorWithResponse creates a new Error conforming object from the passed
|
|
||||||
// packageType, method, statusCode of the given resp (UndefinedStatusCode if
|
|
||||||
// resp is nil), and message. message is treated as a format string to which the
|
|
||||||
// optional args apply.
|
|
||||||
func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
|
|
||||||
return NewErrorWithError(nil, packageType, method, resp, message, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewErrorWithError creates a new Error conforming object from the
|
|
||||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
|
||||||
// if resp is nil), message, and original error. message is treated as a format
|
|
||||||
// string to which the optional args apply.
|
|
||||||
func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
|
|
||||||
if v, ok := original.(DetailedError); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
statusCode := UndefinedStatusCode
|
|
||||||
if resp != nil {
|
|
||||||
statusCode = resp.StatusCode
|
|
||||||
}
|
|
||||||
|
|
||||||
return DetailedError{
|
|
||||||
Original: original,
|
|
||||||
PackageType: packageType,
|
|
||||||
Method: method,
|
|
||||||
StatusCode: statusCode,
|
|
||||||
Message: fmt.Sprintf(message, args...),
|
|
||||||
Response: resp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns a formatted containing all available details (i.e., PackageType, Method,
|
|
||||||
// StatusCode, Message, and original error (if any)).
|
|
||||||
func (e DetailedError) Error() string {
|
|
||||||
if e.Original == nil {
|
|
||||||
return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original)
|
|
||||||
}
|
|
480
vendor/github.com/Azure/go-autorest/autorest/preparer.go
generated
vendored
480
vendor/github.com/Azure/go-autorest/autorest/preparer.go
generated
vendored
|
@ -1,480 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"mime/multipart"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mimeTypeJSON = "application/json"
|
|
||||||
mimeTypeOctetStream = "application/octet-stream"
|
|
||||||
mimeTypeFormPost = "application/x-www-form-urlencoded"
|
|
||||||
|
|
||||||
headerAuthorization = "Authorization"
|
|
||||||
headerContentType = "Content-Type"
|
|
||||||
headerUserAgent = "User-Agent"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Preparer is the interface that wraps the Prepare method.
|
|
||||||
//
|
|
||||||
// Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations
|
|
||||||
// must ensure to not share or hold per-invocation state since Preparers may be shared and re-used.
|
|
||||||
type Preparer interface {
|
|
||||||
Prepare(*http.Request) (*http.Request, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreparerFunc is a method that implements the Preparer interface.
|
|
||||||
type PreparerFunc func(*http.Request) (*http.Request, error)
|
|
||||||
|
|
||||||
// Prepare implements the Preparer interface on PreparerFunc.
|
|
||||||
func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) {
|
|
||||||
return pf(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the
|
|
||||||
// http.Request and pass it along or, first, pass the http.Request along then affect the result.
|
|
||||||
type PrepareDecorator func(Preparer) Preparer
|
|
||||||
|
|
||||||
// CreatePreparer creates, decorates, and returns a Preparer.
|
|
||||||
// Without decorators, the returned Preparer returns the passed http.Request unmodified.
|
|
||||||
// Preparers are safe to share and re-use.
|
|
||||||
func CreatePreparer(decorators ...PrepareDecorator) Preparer {
|
|
||||||
return DecoratePreparer(
|
|
||||||
Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })),
|
|
||||||
decorators...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it
|
|
||||||
// applies to the Preparer. Decorators are applied in the order received, but their affect upon the
|
|
||||||
// request depends on whether they are a pre-decorator (change the http.Request and then pass it
|
|
||||||
// along) or a post-decorator (pass the http.Request along and alter it on return).
|
|
||||||
func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer {
|
|
||||||
for _, decorate := range decorators {
|
|
||||||
p = decorate(p)
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators.
|
|
||||||
// It creates a Preparer from the decorators which it then applies to the passed http.Request.
|
|
||||||
func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) {
|
|
||||||
if r == nil {
|
|
||||||
return nil, NewError("autorest", "Prepare", "Invoked without an http.Request")
|
|
||||||
}
|
|
||||||
return CreatePreparer(decorators...).Prepare(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed
|
|
||||||
// http.Request.
|
|
||||||
func WithNothing() PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
return p.Prepare(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to
|
|
||||||
// the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before
|
|
||||||
// adding the header.
|
|
||||||
func WithHeader(header string, value string) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.Header == nil {
|
|
||||||
r.Header = make(http.Header)
|
|
||||||
}
|
|
||||||
r.Header.Set(http.CanonicalHeaderKey(header), value)
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHeaders returns a PrepareDecorator that sets the specified HTTP headers of the http.Request to
|
|
||||||
// the passed value. It canonicalizes the passed headers name (via http.CanonicalHeaderKey) before
|
|
||||||
// adding them.
|
|
||||||
func WithHeaders(headers map[string]interface{}) PrepareDecorator {
|
|
||||||
h := ensureValueStrings(headers)
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.Header == nil {
|
|
||||||
r.Header = make(http.Header)
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, value := range h {
|
|
||||||
r.Header.Set(http.CanonicalHeaderKey(name), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
|
||||||
// value is "Bearer " followed by the supplied token.
|
|
||||||
func WithBearerAuthorization(token string) PrepareDecorator {
|
|
||||||
return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value
|
|
||||||
// is the passed contentType.
|
|
||||||
func AsContentType(contentType string) PrepareDecorator {
|
|
||||||
return WithHeader(headerContentType, contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the
|
|
||||||
// passed string.
|
|
||||||
func WithUserAgent(ua string) PrepareDecorator {
|
|
||||||
return WithHeader(headerUserAgent, ua)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
|
|
||||||
// "application/x-www-form-urlencoded".
|
|
||||||
func AsFormURLEncoded() PrepareDecorator {
|
|
||||||
return AsContentType(mimeTypeFormPost)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
|
|
||||||
// "application/json".
|
|
||||||
func AsJSON() PrepareDecorator {
|
|
||||||
return AsContentType(mimeTypeJSON)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsOctetStream returns a PrepareDecorator that adds the "application/octet-stream" Content-Type header.
|
|
||||||
func AsOctetStream() PrepareDecorator {
|
|
||||||
return AsContentType(mimeTypeOctetStream)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The
|
|
||||||
// decorator does not validate that the passed method string is a known HTTP method.
|
|
||||||
func WithMethod(method string) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r.Method = method
|
|
||||||
return p.Prepare(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE.
|
|
||||||
func AsDelete() PrepareDecorator { return WithMethod("DELETE") }
|
|
||||||
|
|
||||||
// AsGet returns a PrepareDecorator that sets the HTTP method to GET.
|
|
||||||
func AsGet() PrepareDecorator { return WithMethod("GET") }
|
|
||||||
|
|
||||||
// AsHead returns a PrepareDecorator that sets the HTTP method to HEAD.
|
|
||||||
func AsHead() PrepareDecorator { return WithMethod("HEAD") }
|
|
||||||
|
|
||||||
// AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS.
|
|
||||||
func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") }
|
|
||||||
|
|
||||||
// AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH.
|
|
||||||
func AsPatch() PrepareDecorator { return WithMethod("PATCH") }
|
|
||||||
|
|
||||||
// AsPost returns a PrepareDecorator that sets the HTTP method to POST.
|
|
||||||
func AsPost() PrepareDecorator { return WithMethod("POST") }
|
|
||||||
|
|
||||||
// AsPut returns a PrepareDecorator that sets the HTTP method to PUT.
|
|
||||||
func AsPut() PrepareDecorator { return WithMethod("PUT") }
|
|
||||||
|
|
||||||
// WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed
|
|
||||||
// from the supplied baseUrl.
|
|
||||||
func WithBaseURL(baseURL string) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
var u *url.URL
|
|
||||||
if u, err = url.Parse(baseURL); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if u.Scheme == "" {
|
|
||||||
err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
r.URL = u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the
|
|
||||||
// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map.
|
|
||||||
func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator {
|
|
||||||
parameters := ensureValueStrings(urlParameters)
|
|
||||||
for key, value := range parameters {
|
|
||||||
baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1)
|
|
||||||
}
|
|
||||||
return WithBaseURL(baseURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the
|
|
||||||
// http.Request body.
|
|
||||||
func WithFormData(v url.Values) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
s := v.Encode()
|
|
||||||
|
|
||||||
if r.Header == nil {
|
|
||||||
r.Header = make(http.Header)
|
|
||||||
}
|
|
||||||
r.Header.Set(http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
|
|
||||||
r.ContentLength = int64(len(s))
|
|
||||||
r.Body = ioutil.NopCloser(strings.NewReader(s))
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters
|
|
||||||
// into the http.Request body.
|
|
||||||
func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
var body bytes.Buffer
|
|
||||||
writer := multipart.NewWriter(&body)
|
|
||||||
for key, value := range formDataParameters {
|
|
||||||
if rc, ok := value.(io.ReadCloser); ok {
|
|
||||||
var fd io.Writer
|
|
||||||
if fd, err = writer.CreateFormFile(key, key); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if _, err = io.Copy(fd, rc); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err = writer.WriteField(key, ensureValueString(value)); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err = writer.Close(); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if r.Header == nil {
|
|
||||||
r.Header = make(http.Header)
|
|
||||||
}
|
|
||||||
r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
|
|
||||||
r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
|
||||||
r.ContentLength = int64(body.Len())
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFile returns a PrepareDecorator that sends file in request body.
|
|
||||||
func WithFile(f io.ReadCloser) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
b, err := ioutil.ReadAll(f)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
r.Body = ioutil.NopCloser(bytes.NewReader(b))
|
|
||||||
r.ContentLength = int64(len(b))
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request
|
|
||||||
// and sets the Content-Length header.
|
|
||||||
func WithBool(v bool) PrepareDecorator {
|
|
||||||
return WithString(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the
|
|
||||||
// request and sets the Content-Length header.
|
|
||||||
func WithFloat32(v float32) PrepareDecorator {
|
|
||||||
return WithString(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the
|
|
||||||
// request and sets the Content-Length header.
|
|
||||||
func WithFloat64(v float64) PrepareDecorator {
|
|
||||||
return WithString(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request
|
|
||||||
// and sets the Content-Length header.
|
|
||||||
func WithInt32(v int32) PrepareDecorator {
|
|
||||||
return WithString(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request
|
|
||||||
// and sets the Content-Length header.
|
|
||||||
func WithInt64(v int64) PrepareDecorator {
|
|
||||||
return WithString(fmt.Sprintf("%v", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithString returns a PrepareDecorator that encodes the passed string into the body of the request
|
|
||||||
// and sets the Content-Length header.
|
|
||||||
func WithString(v string) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
r.ContentLength = int64(len(v))
|
|
||||||
r.Body = ioutil.NopCloser(strings.NewReader(v))
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the
|
|
||||||
// request and sets the Content-Length header.
|
|
||||||
func WithJSON(v interface{}) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
b, err := json.Marshal(v)
|
|
||||||
if err == nil {
|
|
||||||
r.ContentLength = int64(len(b))
|
|
||||||
r.Body = ioutil.NopCloser(bytes.NewReader(b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path
|
|
||||||
// is absolute (that is, it begins with a "/"), it replaces the existing path.
|
|
||||||
func WithPath(path string) PrepareDecorator {
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.URL == nil {
|
|
||||||
return r, NewError("autorest", "WithPath", "Invoked with a nil URL")
|
|
||||||
}
|
|
||||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
|
|
||||||
// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The
|
|
||||||
// values will be escaped (aka URL encoded) before insertion into the path.
|
|
||||||
func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
|
|
||||||
parameters := escapeValueStrings(ensureValueStrings(pathParameters))
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.URL == nil {
|
|
||||||
return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL")
|
|
||||||
}
|
|
||||||
for key, value := range parameters {
|
|
||||||
path = strings.Replace(path, "{"+key+"}", value, -1)
|
|
||||||
}
|
|
||||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
|
|
||||||
// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map.
|
|
||||||
func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
|
|
||||||
parameters := ensureValueStrings(pathParameters)
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.URL == nil {
|
|
||||||
return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL")
|
|
||||||
}
|
|
||||||
for key, value := range parameters {
|
|
||||||
path = strings.Replace(path, "{"+key+"}", value, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseURL(u *url.URL, path string) (*url.URL, error) {
|
|
||||||
p := strings.TrimRight(u.String(), "/")
|
|
||||||
if !strings.HasPrefix(path, "/") {
|
|
||||||
path = "/" + path
|
|
||||||
}
|
|
||||||
return url.Parse(p + path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters
|
|
||||||
// given in the supplied map (i.e., key=value).
|
|
||||||
func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator {
|
|
||||||
parameters := ensureValueStrings(queryParameters)
|
|
||||||
return func(p Preparer) Preparer {
|
|
||||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
r, err := p.Prepare(r)
|
|
||||||
if err == nil {
|
|
||||||
if r.URL == nil {
|
|
||||||
return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL")
|
|
||||||
}
|
|
||||||
|
|
||||||
v := r.URL.Query()
|
|
||||||
for key, value := range parameters {
|
|
||||||
d, err := url.QueryUnescape(value)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
v.Add(key, d)
|
|
||||||
}
|
|
||||||
r.URL.RawQuery = v.Encode()
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
250
vendor/github.com/Azure/go-autorest/autorest/responder.go
generated
vendored
250
vendor/github.com/Azure/go-autorest/autorest/responder.go
generated
vendored
|
@ -1,250 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Responder is the interface that wraps the Respond method.
|
|
||||||
//
|
|
||||||
// Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold
|
|
||||||
// state since Responders may be shared and re-used.
|
|
||||||
type Responder interface {
|
|
||||||
Respond(*http.Response) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResponderFunc is a method that implements the Responder interface.
|
|
||||||
type ResponderFunc func(*http.Response) error
|
|
||||||
|
|
||||||
// Respond implements the Responder interface on ResponderFunc.
|
|
||||||
func (rf ResponderFunc) Respond(r *http.Response) error {
|
|
||||||
return rf(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to
|
|
||||||
// the http.Response and pass it along or, first, pass the http.Response along then react.
|
|
||||||
type RespondDecorator func(Responder) Responder
|
|
||||||
|
|
||||||
// CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned
|
|
||||||
// Responder returns the passed http.Response unmodified. Responders may or may not be safe to share
|
|
||||||
// and re-used: It depends on the applied decorators. For example, a standard decorator that closes
|
|
||||||
// the response body is fine to share whereas a decorator that reads the body into a passed struct
|
|
||||||
// is not.
|
|
||||||
//
|
|
||||||
// To prevent memory leaks, ensure that at least one Responder closes the response body.
|
|
||||||
func CreateResponder(decorators ...RespondDecorator) Responder {
|
|
||||||
return DecorateResponder(
|
|
||||||
Responder(ResponderFunc(func(r *http.Response) error { return nil })),
|
|
||||||
decorators...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it
|
|
||||||
// applies to the Responder. Decorators are applied in the order received, but their affect upon the
|
|
||||||
// request depends on whether they are a pre-decorator (react to the http.Response and then pass it
|
|
||||||
// along) or a post-decorator (pass the http.Response along and then react).
|
|
||||||
func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder {
|
|
||||||
for _, decorate := range decorators {
|
|
||||||
r = decorate(r)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Respond accepts an http.Response and a, possibly empty, set of RespondDecorators.
|
|
||||||
// It creates a Responder from the decorators it then applies to the passed http.Response.
|
|
||||||
func Respond(r *http.Response, decorators ...RespondDecorator) error {
|
|
||||||
if r == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return CreateResponder(decorators...).Respond(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined
|
|
||||||
// to the next RespondDecorator.
|
|
||||||
func ByIgnoring() RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
return r.Respond(resp)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as
|
|
||||||
// the Body is read.
|
|
||||||
func ByCopying(b *bytes.Buffer) RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil && resp != nil && resp.Body != nil {
|
|
||||||
resp.Body = TeeReadCloser(resp.Body, b)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which
|
|
||||||
// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed
|
|
||||||
// Responder is invoked prior to discarding the response body, the decorator may occur anywhere
|
|
||||||
// within the set.
|
|
||||||
func ByDiscardingBody() RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil && resp != nil && resp.Body != nil {
|
|
||||||
if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
|
|
||||||
return fmt.Errorf("Error discarding the response body: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByClosing returns a RespondDecorator that first invokes the passed Responder after which it
|
|
||||||
// closes the response body. Since the passed Responder is invoked prior to closing the response
|
|
||||||
// body, the decorator may occur anywhere within the set.
|
|
||||||
func ByClosing() RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if resp != nil && resp.Body != nil {
|
|
||||||
if err := resp.Body.Close(); err != nil {
|
|
||||||
return fmt.Errorf("Error closing the response body: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which
|
|
||||||
// it closes the response if the passed Responder returns an error and the response body exists.
|
|
||||||
func ByClosingIfError() RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err != nil && resp != nil && resp.Body != nil {
|
|
||||||
if err := resp.Body.Close(); err != nil {
|
|
||||||
return fmt.Errorf("Error closing the response body: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the
|
|
||||||
// response Body into the value pointed to by v.
|
|
||||||
func ByUnmarshallingJSON(v interface{}) RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil {
|
|
||||||
b, errInner := ioutil.ReadAll(resp.Body)
|
|
||||||
// Some responses might include a BOM, remove for successful unmarshalling
|
|
||||||
b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf"))
|
|
||||||
if errInner != nil {
|
|
||||||
err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
|
|
||||||
} else if len(strings.Trim(string(b), " ")) > 0 {
|
|
||||||
errInner = json.Unmarshal(b, v)
|
|
||||||
if errInner != nil {
|
|
||||||
err = fmt.Errorf("Error occurred unmarshalling JSON - Error = '%v' JSON = '%s'", errInner, string(b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the
|
|
||||||
// response Body into the value pointed to by v.
|
|
||||||
func ByUnmarshallingXML(v interface{}) RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil {
|
|
||||||
b, errInner := ioutil.ReadAll(resp.Body)
|
|
||||||
if errInner != nil {
|
|
||||||
err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
|
|
||||||
} else {
|
|
||||||
errInner = xml.Unmarshal(b, v)
|
|
||||||
if errInner != nil {
|
|
||||||
err = fmt.Errorf("Error occurred unmarshalling Xml - Error = '%v' Xml = '%s'", errInner, string(b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response
|
|
||||||
// StatusCode is among the set passed. On error, response body is fully read into a buffer and
|
|
||||||
// presented in the returned error, as well as in the response body.
|
|
||||||
func WithErrorUnlessStatusCode(codes ...int) RespondDecorator {
|
|
||||||
return func(r Responder) Responder {
|
|
||||||
return ResponderFunc(func(resp *http.Response) error {
|
|
||||||
err := r.Respond(resp)
|
|
||||||
if err == nil && !ResponseHasStatusCode(resp, codes...) {
|
|
||||||
derr := NewErrorWithResponse("autorest", "WithErrorUnlessStatusCode", resp, "%v %v failed with %s",
|
|
||||||
resp.Request.Method,
|
|
||||||
resp.Request.URL,
|
|
||||||
resp.Status)
|
|
||||||
if resp.Body != nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
b, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
derr.ServiceError = b
|
|
||||||
resp.Body = ioutil.NopCloser(bytes.NewReader(b))
|
|
||||||
}
|
|
||||||
err = derr
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is
|
|
||||||
// anything other than HTTP 200.
|
|
||||||
func WithErrorUnlessOK() RespondDecorator {
|
|
||||||
return WithErrorUnlessStatusCode(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractHeader extracts all values of the specified header from the http.Response. It returns an
|
|
||||||
// empty string slice if the passed http.Response is nil or the header does not exist.
|
|
||||||
func ExtractHeader(header string, resp *http.Response) []string {
|
|
||||||
if resp != nil && resp.Header != nil {
|
|
||||||
return resp.Header[http.CanonicalHeaderKey(header)]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractHeaderValue extracts the first value of the specified header from the http.Response. It
|
|
||||||
// returns an empty string if the passed http.Response is nil or the header does not exist.
|
|
||||||
func ExtractHeaderValue(header string, resp *http.Response) string {
|
|
||||||
h := ExtractHeader(header, resp)
|
|
||||||
if len(h) > 0 {
|
|
||||||
return h[0]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
52
vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go
generated
vendored
52
vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewRetriableRequest returns a wrapper around an HTTP request that support retry logic.
|
|
||||||
func NewRetriableRequest(req *http.Request) *RetriableRequest {
|
|
||||||
return &RetriableRequest{req: req}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request returns the wrapped HTTP request.
|
|
||||||
func (rr *RetriableRequest) Request() *http.Request {
|
|
||||||
return rr.req
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rr *RetriableRequest) prepareFromByteReader() (err error) {
|
|
||||||
// fall back to making a copy (only do this once)
|
|
||||||
b := []byte{}
|
|
||||||
if rr.req.ContentLength > 0 {
|
|
||||||
b = make([]byte, rr.req.ContentLength)
|
|
||||||
_, err = io.ReadFull(rr.req.Body, b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b, err = ioutil.ReadAll(rr.req.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rr.br = bytes.NewReader(b)
|
|
||||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
|
||||||
return err
|
|
||||||
}
|
|
54
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go
generated
vendored
54
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
// +build !go1.8
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package autorest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RetriableRequest provides facilities for retrying an HTTP request.
|
|
||||||
type RetriableRequest struct {
|
|
||||||
req *http.Request
|
|
||||||
br *bytes.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare signals that the request is about to be sent.
|
|
||||||
func (rr *RetriableRequest) Prepare() (err error) {
|
|
||||||
// preserve the request body; this is to support retry logic as
|
|
||||||
// the underlying transport will always close the reqeust body
|
|
||||||
if rr.req.Body != nil {
|
|
||||||
if rr.br != nil {
|
|
||||||
_, err = rr.br.Seek(0, 0 /*io.SeekStart*/)
|
|
||||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if rr.br == nil {
|
|
||||||
// fall back to making a copy (only do this once)
|
|
||||||
err = rr.prepareFromByteReader()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeRequestBody(req *http.Request) {
|
|
||||||
req.Body = nil
|
|
||||||
req.ContentLength = 0
|
|
||||||
}
|
|
66
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go
generated
vendored
66
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
// +build go1.8
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package autorest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RetriableRequest provides facilities for retrying an HTTP request.
|
|
||||||
type RetriableRequest struct {
|
|
||||||
req *http.Request
|
|
||||||
rc io.ReadCloser
|
|
||||||
br *bytes.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare signals that the request is about to be sent.
|
|
||||||
func (rr *RetriableRequest) Prepare() (err error) {
|
|
||||||
// preserve the request body; this is to support retry logic as
|
|
||||||
// the underlying transport will always close the reqeust body
|
|
||||||
if rr.req.Body != nil {
|
|
||||||
if rr.rc != nil {
|
|
||||||
rr.req.Body = rr.rc
|
|
||||||
} else if rr.br != nil {
|
|
||||||
_, err = rr.br.Seek(0, io.SeekStart)
|
|
||||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if rr.req.GetBody != nil {
|
|
||||||
// this will allow us to preserve the body without having to
|
|
||||||
// make a copy. note we need to do this on each iteration
|
|
||||||
rr.rc, err = rr.req.GetBody()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if rr.br == nil {
|
|
||||||
// fall back to making a copy (only do this once)
|
|
||||||
err = rr.prepareFromByteReader()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeRequestBody(req *http.Request) {
|
|
||||||
req.Body = nil
|
|
||||||
req.GetBody = nil
|
|
||||||
req.ContentLength = 0
|
|
||||||
}
|
|
321
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
321
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
|
@ -1,321 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sender is the interface that wraps the Do method to send HTTP requests.
|
|
||||||
//
|
|
||||||
// The standard http.Client conforms to this interface.
|
|
||||||
type Sender interface {
|
|
||||||
Do(*http.Request) (*http.Response, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SenderFunc is a method that implements the Sender interface.
|
|
||||||
type SenderFunc func(*http.Request) (*http.Response, error)
|
|
||||||
|
|
||||||
// Do implements the Sender interface on SenderFunc.
|
|
||||||
func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
|
|
||||||
return sf(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
|
|
||||||
// http.Request and pass it along or, first, pass the http.Request along then react to the
|
|
||||||
// http.Response result.
|
|
||||||
type SendDecorator func(Sender) Sender
|
|
||||||
|
|
||||||
// CreateSender creates, decorates, and returns, as a Sender, the default http.Client.
|
|
||||||
func CreateSender(decorators ...SendDecorator) Sender {
|
|
||||||
return DecorateSender(&http.Client{}, decorators...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to
|
|
||||||
// the Sender. Decorators are applied in the order received, but their affect upon the request
|
|
||||||
// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a
|
|
||||||
// post-decorator (pass the http.Request along and react to the results in http.Response).
|
|
||||||
func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
|
|
||||||
for _, decorate := range decorators {
|
|
||||||
s = decorate(s)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send sends, by means of the default http.Client, the passed http.Request, returning the
|
|
||||||
// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
|
|
||||||
// it will apply the http.Client before invoking the Do method.
|
|
||||||
//
|
|
||||||
// Send is a convenience method and not recommended for production. Advanced users should use
|
|
||||||
// SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client).
|
|
||||||
//
|
|
||||||
// Send will not poll or retry requests.
|
|
||||||
func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
|
|
||||||
return SendWithSender(&http.Client{}, r, decorators...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendWithSender sends the passed http.Request, through the provided Sender, returning the
|
|
||||||
// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
|
|
||||||
// it will apply the http.Client before invoking the Do method.
|
|
||||||
//
|
|
||||||
// SendWithSender will not poll or retry requests.
|
|
||||||
func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
|
|
||||||
return DecorateSender(s, decorators...).Do(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AfterDelay returns a SendDecorator that delays for the passed time.Duration before
|
|
||||||
// invoking the Sender. The delay may be terminated by closing the optional channel on the
|
|
||||||
// http.Request. If canceled, no further Senders are invoked.
|
|
||||||
func AfterDelay(d time.Duration) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
if !DelayForBackoff(d, 0, r.Context().Done()) {
|
|
||||||
return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay")
|
|
||||||
}
|
|
||||||
return s.Do(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request.
|
|
||||||
func AsIs() SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
return s.Do(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which
|
|
||||||
// it closes the response if the passed Sender returns an error and the response body exists.
|
|
||||||
func DoCloseIfError() SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
resp, err := s.Do(r)
|
|
||||||
if err != nil {
|
|
||||||
Respond(resp, ByDiscardingBody(), ByClosing())
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is
|
|
||||||
// among the set passed. Since these are artificial errors, the response body may still require
|
|
||||||
// closing.
|
|
||||||
func DoErrorIfStatusCode(codes ...int) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
resp, err := s.Do(r)
|
|
||||||
if err == nil && ResponseHasStatusCode(resp, codes...) {
|
|
||||||
err = NewErrorWithResponse("autorest", "DoErrorIfStatusCode", resp, "%v %v failed with %s",
|
|
||||||
resp.Request.Method,
|
|
||||||
resp.Request.URL,
|
|
||||||
resp.Status)
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response
|
|
||||||
// StatusCode is among the set passed. Since these are artificial errors, the response body
|
|
||||||
// may still require closing.
|
|
||||||
func DoErrorUnlessStatusCode(codes ...int) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
resp, err := s.Do(r)
|
|
||||||
if err == nil && !ResponseHasStatusCode(resp, codes...) {
|
|
||||||
err = NewErrorWithResponse("autorest", "DoErrorUnlessStatusCode", resp, "%v %v failed with %s",
|
|
||||||
resp.Request.Method,
|
|
||||||
resp.Request.URL,
|
|
||||||
resp.Status)
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the
|
|
||||||
// passed status codes. It expects the http.Response to contain a Location header providing the
|
|
||||||
// URL at which to poll (using GET) and will poll until the time passed is equal to or greater than
|
|
||||||
// the supplied duration. It will delay between requests for the duration specified in the
|
|
||||||
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
|
|
||||||
// closing the optional channel on the http.Request.
|
|
||||||
func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
resp, err = s.Do(r)
|
|
||||||
|
|
||||||
if err == nil && ResponseHasStatusCode(resp, codes...) {
|
|
||||||
r, err = NewPollingRequestWithContext(r.Context(), resp)
|
|
||||||
|
|
||||||
for err == nil && ResponseHasStatusCode(resp, codes...) {
|
|
||||||
Respond(resp,
|
|
||||||
ByDiscardingBody(),
|
|
||||||
ByClosing())
|
|
||||||
resp, err = SendWithSender(s, r,
|
|
||||||
AfterDelay(GetRetryAfter(resp, delay)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified
|
|
||||||
// number of attempts, exponentially backing off between requests using the supplied backoff
|
|
||||||
// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
|
|
||||||
// the http.Request.
|
|
||||||
func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
rr := NewRetriableRequest(r)
|
|
||||||
for attempt := 0; attempt < attempts; attempt++ {
|
|
||||||
err = rr.Prepare()
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
resp, err = s.Do(rr.Request())
|
|
||||||
if err == nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
if !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
|
||||||
return nil, r.Context().Err()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified
|
|
||||||
// number of attempts, exponentially backing off between requests using the supplied backoff
|
|
||||||
// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
|
|
||||||
// the http.Request.
|
|
||||||
func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
rr := NewRetriableRequest(r)
|
|
||||||
// Increment to add the first call (attempts denotes number of retries)
|
|
||||||
attempts++
|
|
||||||
for attempt := 0; attempt < attempts; {
|
|
||||||
err = rr.Prepare()
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
resp, err = s.Do(rr.Request())
|
|
||||||
// we want to retry if err is not nil (e.g. transient network failure). note that for failed authentication
|
|
||||||
// resp and err will both have a value, so in this case we don't want to retry as it will never succeed.
|
|
||||||
if err == nil && !ResponseHasStatusCode(resp, codes...) || IsTokenRefreshError(err) {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
delayed := DelayWithRetryAfter(resp, r.Context().Done())
|
|
||||||
if !delayed && !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
|
||||||
return nil, r.Context().Err()
|
|
||||||
}
|
|
||||||
// don't count a 429 against the number of attempts
|
|
||||||
// so that we continue to retry until it succeeds
|
|
||||||
if resp == nil || resp.StatusCode != http.StatusTooManyRequests {
|
|
||||||
attempt++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelayWithRetryAfter invokes time.After for the duration specified in the "Retry-After" header in
|
|
||||||
// responses with status code 429
|
|
||||||
func DelayWithRetryAfter(resp *http.Response, cancel <-chan struct{}) bool {
|
|
||||||
if resp == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After"))
|
|
||||||
if resp.StatusCode == http.StatusTooManyRequests && retryAfter > 0 {
|
|
||||||
select {
|
|
||||||
case <-time.After(time.Duration(retryAfter) * time.Second):
|
|
||||||
return true
|
|
||||||
case <-cancel:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal
|
|
||||||
// to or greater than the specified duration, exponentially backing off between requests using the
|
|
||||||
// supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the
|
|
||||||
// optional channel on the http.Request.
|
|
||||||
func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
|
||||||
rr := NewRetriableRequest(r)
|
|
||||||
end := time.Now().Add(d)
|
|
||||||
for attempt := 0; time.Now().Before(end); attempt++ {
|
|
||||||
err = rr.Prepare()
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
resp, err = s.Do(rr.Request())
|
|
||||||
if err == nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
if !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
|
||||||
return nil, r.Context().Err()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithLogging returns a SendDecorator that implements simple before and after logging of the
|
|
||||||
// request.
|
|
||||||
func WithLogging(logger *log.Logger) SendDecorator {
|
|
||||||
return func(s Sender) Sender {
|
|
||||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
|
||||||
logger.Printf("Sending %s %s", r.Method, r.URL)
|
|
||||||
resp, err := s.Do(r)
|
|
||||||
if err != nil {
|
|
||||||
logger.Printf("%s %s received error '%v'", r.Method, r.URL, err)
|
|
||||||
} else {
|
|
||||||
logger.Printf("%s %s received %s", r.Method, r.URL, resp.Status)
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of
|
|
||||||
// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set
|
|
||||||
// to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early,
|
|
||||||
// returns false.
|
|
||||||
// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt
|
|
||||||
// count.
|
|
||||||
func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool {
|
|
||||||
select {
|
|
||||||
case <-time.After(time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second):
|
|
||||||
return true
|
|
||||||
case <-cancel:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
147
vendor/github.com/Azure/go-autorest/autorest/to/convert.go
generated
vendored
147
vendor/github.com/Azure/go-autorest/autorest/to/convert.go
generated
vendored
|
@ -1,147 +0,0 @@
|
||||||
/*
|
|
||||||
Package to provides helpers to ease working with pointer values of marshalled structures.
|
|
||||||
*/
|
|
||||||
package to
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// String returns a string value for the passed string pointer. It returns the empty string if the
|
|
||||||
// pointer is nil.
|
|
||||||
func String(s *string) string {
|
|
||||||
if s != nil {
|
|
||||||
return *s
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringPtr returns a pointer to the passed string.
|
|
||||||
func StringPtr(s string) *string {
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice returns a string slice value for the passed string slice pointer. It returns a nil
|
|
||||||
// slice if the pointer is nil.
|
|
||||||
func StringSlice(s *[]string) []string {
|
|
||||||
if s != nil {
|
|
||||||
return *s
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlicePtr returns a pointer to the passed string slice.
|
|
||||||
func StringSlicePtr(s []string) *[]string {
|
|
||||||
return &s
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringMap returns a map of strings built from the map of string pointers. The empty string is
|
|
||||||
// used for nil pointers.
|
|
||||||
func StringMap(msp map[string]*string) map[string]string {
|
|
||||||
ms := make(map[string]string, len(msp))
|
|
||||||
for k, sp := range msp {
|
|
||||||
if sp != nil {
|
|
||||||
ms[k] = *sp
|
|
||||||
} else {
|
|
||||||
ms[k] = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringMapPtr returns a pointer to a map of string pointers built from the passed map of strings.
|
|
||||||
func StringMapPtr(ms map[string]string) *map[string]*string {
|
|
||||||
msp := make(map[string]*string, len(ms))
|
|
||||||
for k, s := range ms {
|
|
||||||
msp[k] = StringPtr(s)
|
|
||||||
}
|
|
||||||
return &msp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool returns a bool value for the passed bool pointer. It returns false if the pointer is nil.
|
|
||||||
func Bool(b *bool) bool {
|
|
||||||
if b != nil {
|
|
||||||
return *b
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolPtr returns a pointer to the passed bool.
|
|
||||||
func BoolPtr(b bool) *bool {
|
|
||||||
return &b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
|
||||||
func Int(i *int) int {
|
|
||||||
if i != nil {
|
|
||||||
return *i
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntPtr returns a pointer to the passed int.
|
|
||||||
func IntPtr(i int) *int {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32 returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
|
||||||
func Int32(i *int32) int32 {
|
|
||||||
if i != nil {
|
|
||||||
return *i
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32Ptr returns a pointer to the passed int32.
|
|
||||||
func Int32Ptr(i int32) *int32 {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
|
||||||
func Int64(i *int64) int64 {
|
|
||||||
if i != nil {
|
|
||||||
return *i
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Ptr returns a pointer to the passed int64.
|
|
||||||
func Int64Ptr(i int64) *int64 {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil.
|
|
||||||
func Float32(i *float32) float32 {
|
|
||||||
if i != nil {
|
|
||||||
return *i
|
|
||||||
}
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32Ptr returns a pointer to the passed float32.
|
|
||||||
func Float32Ptr(i float32) *float32 {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil.
|
|
||||||
func Float64(i *float64) float64 {
|
|
||||||
if i != nil {
|
|
||||||
return *i
|
|
||||||
}
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64Ptr returns a pointer to the passed float64.
|
|
||||||
func Float64Ptr(i float64) *float64 {
|
|
||||||
return &i
|
|
||||||
}
|
|
218
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
218
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
|
@ -1,218 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Azure/go-autorest/autorest/adal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EncodedAs is a series of constants specifying various data encodings
|
|
||||||
type EncodedAs string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// EncodedAsJSON states that data is encoded as JSON
|
|
||||||
EncodedAsJSON EncodedAs = "JSON"
|
|
||||||
|
|
||||||
// EncodedAsXML states that data is encoded as Xml
|
|
||||||
EncodedAsXML EncodedAs = "XML"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Decoder defines the decoding method json.Decoder and xml.Decoder share
|
|
||||||
type Decoder interface {
|
|
||||||
Decode(v interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDecoder creates a new decoder appropriate to the passed encoding.
|
|
||||||
// encodedAs specifies the type of encoding and r supplies the io.Reader containing the
|
|
||||||
// encoded data.
|
|
||||||
func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder {
|
|
||||||
if encodedAs == EncodedAsJSON {
|
|
||||||
return json.NewDecoder(r)
|
|
||||||
} else if encodedAs == EncodedAsXML {
|
|
||||||
return xml.NewDecoder(r)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy
|
|
||||||
// is especially useful if there is a chance the data will fail to decode.
|
|
||||||
// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v
|
|
||||||
// is the decoding destination.
|
|
||||||
func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) {
|
|
||||||
b := bytes.Buffer{}
|
|
||||||
return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc.
|
|
||||||
// It utilizes io.TeeReader to copy the data read and has the same behavior when reading.
|
|
||||||
// Further, when it is closed, it ensures that rc is closed as well.
|
|
||||||
func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser {
|
|
||||||
return &teeReadCloser{rc, io.TeeReader(rc, w)}
|
|
||||||
}
|
|
||||||
|
|
||||||
type teeReadCloser struct {
|
|
||||||
rc io.ReadCloser
|
|
||||||
r io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *teeReadCloser) Read(p []byte) (int, error) {
|
|
||||||
return t.r.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *teeReadCloser) Close() error {
|
|
||||||
return t.rc.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsInt(ints []int, n int) bool {
|
|
||||||
for _, i := range ints {
|
|
||||||
if i == n {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func escapeValueStrings(m map[string]string) map[string]string {
|
|
||||||
for key, value := range m {
|
|
||||||
m[key] = url.QueryEscape(value)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureValueStrings(mapOfInterface map[string]interface{}) map[string]string {
|
|
||||||
mapOfStrings := make(map[string]string)
|
|
||||||
for key, value := range mapOfInterface {
|
|
||||||
mapOfStrings[key] = ensureValueString(value)
|
|
||||||
}
|
|
||||||
return mapOfStrings
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureValueString(value interface{}) string {
|
|
||||||
if value == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
switch v := value.(type) {
|
|
||||||
case string:
|
|
||||||
return v
|
|
||||||
case []byte:
|
|
||||||
return string(v)
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapToValues method converts map[string]interface{} to url.Values.
|
|
||||||
func MapToValues(m map[string]interface{}) url.Values {
|
|
||||||
v := url.Values{}
|
|
||||||
for key, value := range m {
|
|
||||||
x := reflect.ValueOf(value)
|
|
||||||
if x.Kind() == reflect.Array || x.Kind() == reflect.Slice {
|
|
||||||
for i := 0; i < x.Len(); i++ {
|
|
||||||
v.Add(key, ensureValueString(x.Index(i)))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v.Add(key, ensureValueString(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsStringSlice method converts interface{} to []string. This expects a
|
|
||||||
//that the parameter passed to be a slice or array of a type that has the underlying
|
|
||||||
//type a string.
|
|
||||||
func AsStringSlice(s interface{}) ([]string, error) {
|
|
||||||
v := reflect.ValueOf(s)
|
|
||||||
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
|
|
||||||
return nil, NewError("autorest", "AsStringSlice", "the value's type is not an array.")
|
|
||||||
}
|
|
||||||
stringSlice := make([]string, 0, v.Len())
|
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
stringSlice = append(stringSlice, v.Index(i).String())
|
|
||||||
}
|
|
||||||
return stringSlice, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String method converts interface v to string. If interface is a list, it
|
|
||||||
// joins list elements using the seperator. Note that only sep[0] will be used for
|
|
||||||
// joining if any separator is specified.
|
|
||||||
func String(v interface{}, sep ...string) string {
|
|
||||||
if len(sep) == 0 {
|
|
||||||
return ensureValueString(v)
|
|
||||||
}
|
|
||||||
stringSlice, ok := v.([]string)
|
|
||||||
if ok == false {
|
|
||||||
var err error
|
|
||||||
stringSlice, err = AsStringSlice(v)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("autorest: Couldn't convert value to a string %s.", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ensureValueString(strings.Join(stringSlice, sep[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode method encodes url path and query parameters.
|
|
||||||
func Encode(location string, v interface{}, sep ...string) string {
|
|
||||||
s := String(v, sep...)
|
|
||||||
switch strings.ToLower(location) {
|
|
||||||
case "path":
|
|
||||||
return pathEscape(s)
|
|
||||||
case "query":
|
|
||||||
return queryEscape(s)
|
|
||||||
default:
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathEscape(s string) string {
|
|
||||||
return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func queryEscape(s string) string {
|
|
||||||
return url.QueryEscape(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeToGet turns the specified http.Request into a GET (it assumes it wasn't).
|
|
||||||
// This is mainly useful for long-running operations that use the Azure-AsyncOperation
|
|
||||||
// header, so we change the initial PUT into a GET to retrieve the final result.
|
|
||||||
func ChangeToGet(req *http.Request) *http.Request {
|
|
||||||
req.Method = "GET"
|
|
||||||
req.Body = nil
|
|
||||||
req.ContentLength = 0
|
|
||||||
req.Header.Del("Content-Length")
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError
|
|
||||||
// interface. If err is a DetailedError it will walk the chain of Original errors.
|
|
||||||
func IsTokenRefreshError(err error) bool {
|
|
||||||
if _, ok := err.(adal.TokenRefreshError); ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if de, ok := err.(DetailedError); ok {
|
|
||||||
return IsTokenRefreshError(de.Original)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
20
vendor/github.com/Azure/go-autorest/autorest/version.go
generated
vendored
20
vendor/github.com/Azure/go-autorest/autorest/version.go
generated
vendored
|
@ -1,20 +0,0 @@
|
||||||
package autorest
|
|
||||||
|
|
||||||
// Copyright 2017 Microsoft Corporation
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Version returns the semantic version (see http://semver.org).
|
|
||||||
func Version() string {
|
|
||||||
return "v10.5.0"
|
|
||||||
}
|
|
21
vendor/github.com/BurntSushi/toml/COPYING
generated
vendored
21
vendor/github.com/BurntSushi/toml/COPYING
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 TOML authors
|
|
||||||
|
|
||||||
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.
|
|
14
vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING
generated
vendored
14
vendor/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
Version 2, December 2004
|
|
||||||
|
|
||||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim or modified
|
|
||||||
copies of this license document, and changing it is allowed as long
|
|
||||||
as the name is changed.
|
|
||||||
|
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
||||||
|
|
14
vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING
generated
vendored
14
vendor/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
Version 2, December 2004
|
|
||||||
|
|
||||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim or modified
|
|
||||||
copies of this license document, and changing it is allowed as long
|
|
||||||
as the name is changed.
|
|
||||||
|
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
||||||
|
|
14
vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING
generated
vendored
14
vendor/github.com/BurntSushi/toml/cmd/tomlv/COPYING
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
Version 2, December 2004
|
|
||||||
|
|
||||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim or modified
|
|
||||||
copies of this license document, and changing it is allowed as long
|
|
||||||
as the name is changed.
|
|
||||||
|
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
||||||
|
|
509
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
509
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
|
@ -1,509 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func e(format string, args ...interface{}) error {
|
|
||||||
return fmt.Errorf("toml: "+format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshaler is the interface implemented by objects that can unmarshal a
|
|
||||||
// TOML description of themselves.
|
|
||||||
type Unmarshaler interface {
|
|
||||||
UnmarshalTOML(interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
|
|
||||||
func Unmarshal(p []byte, v interface{}) error {
|
|
||||||
_, err := Decode(string(p), v)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Primitive is a TOML value that hasn't been decoded into a Go value.
|
|
||||||
// When using the various `Decode*` functions, the type `Primitive` may
|
|
||||||
// be given to any value, and its decoding will be delayed.
|
|
||||||
//
|
|
||||||
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
|
|
||||||
//
|
|
||||||
// The underlying representation of a `Primitive` value is subject to change.
|
|
||||||
// Do not rely on it.
|
|
||||||
//
|
|
||||||
// N.B. Primitive values are still parsed, so using them will only avoid
|
|
||||||
// the overhead of reflection. They can be useful when you don't know the
|
|
||||||
// exact type of TOML data until run time.
|
|
||||||
type Primitive struct {
|
|
||||||
undecoded interface{}
|
|
||||||
context Key
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED!
|
|
||||||
//
|
|
||||||
// Use MetaData.PrimitiveDecode instead.
|
|
||||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
|
||||||
md := MetaData{decoded: make(map[string]bool)}
|
|
||||||
return md.unify(primValue.undecoded, rvalue(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrimitiveDecode is just like the other `Decode*` functions, except it
|
|
||||||
// decodes a TOML value that has already been parsed. Valid primitive values
|
|
||||||
// can *only* be obtained from values filled by the decoder functions,
|
|
||||||
// including this method. (i.e., `v` may contain more `Primitive`
|
|
||||||
// values.)
|
|
||||||
//
|
|
||||||
// Meta data for primitive values is included in the meta data returned by
|
|
||||||
// the `Decode*` functions with one exception: keys returned by the Undecoded
|
|
||||||
// method will only reflect keys that were decoded. Namely, any keys hidden
|
|
||||||
// behind a Primitive will be considered undecoded. Executing this method will
|
|
||||||
// update the undecoded keys in the meta data. (See the example.)
|
|
||||||
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
|
|
||||||
md.context = primValue.context
|
|
||||||
defer func() { md.context = nil }()
|
|
||||||
return md.unify(primValue.undecoded, rvalue(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode will decode the contents of `data` in TOML format into a pointer
|
|
||||||
// `v`.
|
|
||||||
//
|
|
||||||
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
|
|
||||||
// used interchangeably.)
|
|
||||||
//
|
|
||||||
// TOML arrays of tables correspond to either a slice of structs or a slice
|
|
||||||
// of maps.
|
|
||||||
//
|
|
||||||
// TOML datetimes correspond to Go `time.Time` values.
|
|
||||||
//
|
|
||||||
// All other TOML types (float, string, int, bool and array) correspond
|
|
||||||
// to the obvious Go types.
|
|
||||||
//
|
|
||||||
// An exception to the above rules is if a type implements the
|
|
||||||
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
|
|
||||||
// (floats, strings, integers, booleans and datetimes) will be converted to
|
|
||||||
// a byte string and given to the value's UnmarshalText method. See the
|
|
||||||
// Unmarshaler example for a demonstration with time duration strings.
|
|
||||||
//
|
|
||||||
// Key mapping
|
|
||||||
//
|
|
||||||
// TOML keys can map to either keys in a Go map or field names in a Go
|
|
||||||
// struct. The special `toml` struct tag may be used to map TOML keys to
|
|
||||||
// struct fields that don't match the key name exactly. (See the example.)
|
|
||||||
// A case insensitive match to struct names will be tried if an exact match
|
|
||||||
// can't be found.
|
|
||||||
//
|
|
||||||
// The mapping between TOML values and Go values is loose. That is, there
|
|
||||||
// may exist TOML values that cannot be placed into your representation, and
|
|
||||||
// there may be parts of your representation that do not correspond to
|
|
||||||
// TOML values. This loose mapping can be made stricter by using the IsDefined
|
|
||||||
// and/or Undecoded methods on the MetaData returned.
|
|
||||||
//
|
|
||||||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
|
||||||
// `Decode` will not terminate.
|
|
||||||
func Decode(data string, v interface{}) (MetaData, error) {
|
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
if rv.Kind() != reflect.Ptr {
|
|
||||||
return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v))
|
|
||||||
}
|
|
||||||
if rv.IsNil() {
|
|
||||||
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
|
|
||||||
}
|
|
||||||
p, err := parse(data)
|
|
||||||
if err != nil {
|
|
||||||
return MetaData{}, err
|
|
||||||
}
|
|
||||||
md := MetaData{
|
|
||||||
p.mapping, p.types, p.ordered,
|
|
||||||
make(map[string]bool, len(p.ordered)), nil,
|
|
||||||
}
|
|
||||||
return md, md.unify(p.mapping, indirect(rv))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeFile is just like Decode, except it will automatically read the
|
|
||||||
// contents of the file at `fpath` and decode it for you.
|
|
||||||
func DecodeFile(fpath string, v interface{}) (MetaData, error) {
|
|
||||||
bs, err := ioutil.ReadFile(fpath)
|
|
||||||
if err != nil {
|
|
||||||
return MetaData{}, err
|
|
||||||
}
|
|
||||||
return Decode(string(bs), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeReader is just like Decode, except it will consume all bytes
|
|
||||||
// from the reader and decode it for you.
|
|
||||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
|
|
||||||
bs, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return MetaData{}, err
|
|
||||||
}
|
|
||||||
return Decode(string(bs), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// unify performs a sort of type unification based on the structure of `rv`,
|
|
||||||
// which is the client representation.
|
|
||||||
//
|
|
||||||
// Any type mismatch produces an error. Finding a type that we don't know
|
|
||||||
// how to handle produces an unsupported type error.
|
|
||||||
func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
|
||||||
|
|
||||||
// Special case. Look for a `Primitive` value.
|
|
||||||
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
|
|
||||||
// Save the undecoded data and the key context into the primitive
|
|
||||||
// value.
|
|
||||||
context := make(Key, len(md.context))
|
|
||||||
copy(context, md.context)
|
|
||||||
rv.Set(reflect.ValueOf(Primitive{
|
|
||||||
undecoded: data,
|
|
||||||
context: context,
|
|
||||||
}))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case. Unmarshaler Interface support.
|
|
||||||
if rv.CanAddr() {
|
|
||||||
if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
|
|
||||||
return v.UnmarshalTOML(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case. Handle time.Time values specifically.
|
|
||||||
// TODO: Remove this code when we decide to drop support for Go 1.1.
|
|
||||||
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
|
|
||||||
// interfaces.
|
|
||||||
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
|
|
||||||
return md.unifyDatetime(data, rv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case. Look for a value satisfying the TextUnmarshaler interface.
|
|
||||||
if v, ok := rv.Interface().(TextUnmarshaler); ok {
|
|
||||||
return md.unifyText(data, v)
|
|
||||||
}
|
|
||||||
// BUG(burntsushi)
|
|
||||||
// The behavior here is incorrect whenever a Go type satisfies the
|
|
||||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML
|
|
||||||
// hash or array. In particular, the unmarshaler should only be applied
|
|
||||||
// to primitive TOML values. But at this point, it will be applied to
|
|
||||||
// all kinds of values and produce an incorrect error whenever those values
|
|
||||||
// are hashes or arrays (including arrays of tables).
|
|
||||||
|
|
||||||
k := rv.Kind()
|
|
||||||
|
|
||||||
// laziness
|
|
||||||
if k >= reflect.Int && k <= reflect.Uint64 {
|
|
||||||
return md.unifyInt(data, rv)
|
|
||||||
}
|
|
||||||
switch k {
|
|
||||||
case reflect.Ptr:
|
|
||||||
elem := reflect.New(rv.Type().Elem())
|
|
||||||
err := md.unify(data, reflect.Indirect(elem))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rv.Set(elem)
|
|
||||||
return nil
|
|
||||||
case reflect.Struct:
|
|
||||||
return md.unifyStruct(data, rv)
|
|
||||||
case reflect.Map:
|
|
||||||
return md.unifyMap(data, rv)
|
|
||||||
case reflect.Array:
|
|
||||||
return md.unifyArray(data, rv)
|
|
||||||
case reflect.Slice:
|
|
||||||
return md.unifySlice(data, rv)
|
|
||||||
case reflect.String:
|
|
||||||
return md.unifyString(data, rv)
|
|
||||||
case reflect.Bool:
|
|
||||||
return md.unifyBool(data, rv)
|
|
||||||
case reflect.Interface:
|
|
||||||
// we only support empty interfaces.
|
|
||||||
if rv.NumMethod() > 0 {
|
|
||||||
return e("unsupported type %s", rv.Type())
|
|
||||||
}
|
|
||||||
return md.unifyAnything(data, rv)
|
|
||||||
case reflect.Float32:
|
|
||||||
fallthrough
|
|
||||||
case reflect.Float64:
|
|
||||||
return md.unifyFloat64(data, rv)
|
|
||||||
}
|
|
||||||
return e("unsupported type %s", rv.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
|
||||||
tmap, ok := mapping.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
if mapping == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return e("type mismatch for %s: expected table but found %T",
|
|
||||||
rv.Type().String(), mapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, datum := range tmap {
|
|
||||||
var f *field
|
|
||||||
fields := cachedTypeFields(rv.Type())
|
|
||||||
for i := range fields {
|
|
||||||
ff := &fields[i]
|
|
||||||
if ff.name == key {
|
|
||||||
f = ff
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if f == nil && strings.EqualFold(ff.name, key) {
|
|
||||||
f = ff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if f != nil {
|
|
||||||
subv := rv
|
|
||||||
for _, i := range f.index {
|
|
||||||
subv = indirect(subv.Field(i))
|
|
||||||
}
|
|
||||||
if isUnifiable(subv) {
|
|
||||||
md.decoded[md.context.add(key).String()] = true
|
|
||||||
md.context = append(md.context, key)
|
|
||||||
if err := md.unify(datum, subv); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
md.context = md.context[0 : len(md.context)-1]
|
|
||||||
} else if f.name != "" {
|
|
||||||
// Bad user! No soup for you!
|
|
||||||
return e("cannot write unexported field %s.%s",
|
|
||||||
rv.Type().String(), f.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
|
|
||||||
tmap, ok := mapping.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
if tmap == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("map", mapping)
|
|
||||||
}
|
|
||||||
if rv.IsNil() {
|
|
||||||
rv.Set(reflect.MakeMap(rv.Type()))
|
|
||||||
}
|
|
||||||
for k, v := range tmap {
|
|
||||||
md.decoded[md.context.add(k).String()] = true
|
|
||||||
md.context = append(md.context, k)
|
|
||||||
|
|
||||||
rvkey := indirect(reflect.New(rv.Type().Key()))
|
|
||||||
rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
|
|
||||||
if err := md.unify(v, rvval); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
md.context = md.context[0 : len(md.context)-1]
|
|
||||||
|
|
||||||
rvkey.SetString(k)
|
|
||||||
rv.SetMapIndex(rvkey, rvval)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
|
|
||||||
datav := reflect.ValueOf(data)
|
|
||||||
if datav.Kind() != reflect.Slice {
|
|
||||||
if !datav.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("slice", data)
|
|
||||||
}
|
|
||||||
sliceLen := datav.Len()
|
|
||||||
if sliceLen != rv.Len() {
|
|
||||||
return e("expected array length %d; got TOML array of length %d",
|
|
||||||
rv.Len(), sliceLen)
|
|
||||||
}
|
|
||||||
return md.unifySliceArray(datav, rv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
|
|
||||||
datav := reflect.ValueOf(data)
|
|
||||||
if datav.Kind() != reflect.Slice {
|
|
||||||
if !datav.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("slice", data)
|
|
||||||
}
|
|
||||||
n := datav.Len()
|
|
||||||
if rv.IsNil() || rv.Cap() < n {
|
|
||||||
rv.Set(reflect.MakeSlice(rv.Type(), n, n))
|
|
||||||
}
|
|
||||||
rv.SetLen(n)
|
|
||||||
return md.unifySliceArray(datav, rv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
|
|
||||||
sliceLen := data.Len()
|
|
||||||
for i := 0; i < sliceLen; i++ {
|
|
||||||
v := data.Index(i).Interface()
|
|
||||||
sliceval := indirect(rv.Index(i))
|
|
||||||
if err := md.unify(v, sliceval); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
|
|
||||||
if _, ok := data.(time.Time); ok {
|
|
||||||
rv.Set(reflect.ValueOf(data))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("time.Time", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
|
|
||||||
if s, ok := data.(string); ok {
|
|
||||||
rv.SetString(s)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("string", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
|
|
||||||
if num, ok := data.(float64); ok {
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Float32:
|
|
||||||
fallthrough
|
|
||||||
case reflect.Float64:
|
|
||||||
rv.SetFloat(num)
|
|
||||||
default:
|
|
||||||
panic("bug")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("float", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
|
|
||||||
if num, ok := data.(int64); ok {
|
|
||||||
if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Int, reflect.Int64:
|
|
||||||
// No bounds checking necessary.
|
|
||||||
case reflect.Int8:
|
|
||||||
if num < math.MinInt8 || num > math.MaxInt8 {
|
|
||||||
return e("value %d is out of range for int8", num)
|
|
||||||
}
|
|
||||||
case reflect.Int16:
|
|
||||||
if num < math.MinInt16 || num > math.MaxInt16 {
|
|
||||||
return e("value %d is out of range for int16", num)
|
|
||||||
}
|
|
||||||
case reflect.Int32:
|
|
||||||
if num < math.MinInt32 || num > math.MaxInt32 {
|
|
||||||
return e("value %d is out of range for int32", num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rv.SetInt(num)
|
|
||||||
} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
|
|
||||||
unum := uint64(num)
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Uint, reflect.Uint64:
|
|
||||||
// No bounds checking necessary.
|
|
||||||
case reflect.Uint8:
|
|
||||||
if num < 0 || unum > math.MaxUint8 {
|
|
||||||
return e("value %d is out of range for uint8", num)
|
|
||||||
}
|
|
||||||
case reflect.Uint16:
|
|
||||||
if num < 0 || unum > math.MaxUint16 {
|
|
||||||
return e("value %d is out of range for uint16", num)
|
|
||||||
}
|
|
||||||
case reflect.Uint32:
|
|
||||||
if num < 0 || unum > math.MaxUint32 {
|
|
||||||
return e("value %d is out of range for uint32", num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rv.SetUint(unum)
|
|
||||||
} else {
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("integer", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
|
|
||||||
if b, ok := data.(bool); ok {
|
|
||||||
rv.SetBool(b)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return badtype("boolean", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
|
|
||||||
rv.Set(reflect.ValueOf(data))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
|
||||||
var s string
|
|
||||||
switch sdata := data.(type) {
|
|
||||||
case TextMarshaler:
|
|
||||||
text, err := sdata.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s = string(text)
|
|
||||||
case fmt.Stringer:
|
|
||||||
s = sdata.String()
|
|
||||||
case string:
|
|
||||||
s = sdata
|
|
||||||
case bool:
|
|
||||||
s = fmt.Sprintf("%v", sdata)
|
|
||||||
case int64:
|
|
||||||
s = fmt.Sprintf("%d", sdata)
|
|
||||||
case float64:
|
|
||||||
s = fmt.Sprintf("%f", sdata)
|
|
||||||
default:
|
|
||||||
return badtype("primitive (string-like)", data)
|
|
||||||
}
|
|
||||||
if err := v.UnmarshalText([]byte(s)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// rvalue returns a reflect.Value of `v`. All pointers are resolved.
|
|
||||||
func rvalue(v interface{}) reflect.Value {
|
|
||||||
return indirect(reflect.ValueOf(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// indirect returns the value pointed to by a pointer.
|
|
||||||
// Pointers are followed until the value is not a pointer.
|
|
||||||
// New values are allocated for each nil pointer.
|
|
||||||
//
|
|
||||||
// An exception to this rule is if the value satisfies an interface of
|
|
||||||
// interest to us (like encoding.TextUnmarshaler).
|
|
||||||
func indirect(v reflect.Value) reflect.Value {
|
|
||||||
if v.Kind() != reflect.Ptr {
|
|
||||||
if v.CanSet() {
|
|
||||||
pv := v.Addr()
|
|
||||||
if _, ok := pv.Interface().(TextUnmarshaler); ok {
|
|
||||||
return pv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
if v.IsNil() {
|
|
||||||
v.Set(reflect.New(v.Type().Elem()))
|
|
||||||
}
|
|
||||||
return indirect(reflect.Indirect(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
func isUnifiable(rv reflect.Value) bool {
|
|
||||||
if rv.CanSet() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if _, ok := rv.Interface().(TextUnmarshaler); ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func badtype(expected string, data interface{}) error {
|
|
||||||
return e("cannot load TOML value of type %T into a Go %s", data, expected)
|
|
||||||
}
|
|
121
vendor/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
121
vendor/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
|
@ -1,121 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// MetaData allows access to meta information about TOML data that may not
|
|
||||||
// be inferrable via reflection. In particular, whether a key has been defined
|
|
||||||
// and the TOML type of a key.
|
|
||||||
type MetaData struct {
|
|
||||||
mapping map[string]interface{}
|
|
||||||
types map[string]tomlType
|
|
||||||
keys []Key
|
|
||||||
decoded map[string]bool
|
|
||||||
context Key // Used only during decoding.
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDefined returns true if the key given exists in the TOML data. The key
|
|
||||||
// should be specified hierarchially. e.g.,
|
|
||||||
//
|
|
||||||
// // access the TOML key 'a.b.c'
|
|
||||||
// IsDefined("a", "b", "c")
|
|
||||||
//
|
|
||||||
// IsDefined will return false if an empty key given. Keys are case sensitive.
|
|
||||||
func (md *MetaData) IsDefined(key ...string) bool {
|
|
||||||
if len(key) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash map[string]interface{}
|
|
||||||
var ok bool
|
|
||||||
var hashOrVal interface{} = md.mapping
|
|
||||||
for _, k := range key {
|
|
||||||
if hash, ok = hashOrVal.(map[string]interface{}); !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if hashOrVal, ok = hash[k]; !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type returns a string representation of the type of the key specified.
|
|
||||||
//
|
|
||||||
// Type will return the empty string if given an empty key or a key that
|
|
||||||
// does not exist. Keys are case sensitive.
|
|
||||||
func (md *MetaData) Type(key ...string) string {
|
|
||||||
fullkey := strings.Join(key, ".")
|
|
||||||
if typ, ok := md.types[fullkey]; ok {
|
|
||||||
return typ.typeString()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
|
|
||||||
// to get values of this type.
|
|
||||||
type Key []string
|
|
||||||
|
|
||||||
func (k Key) String() string {
|
|
||||||
return strings.Join(k, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k Key) maybeQuotedAll() string {
|
|
||||||
var ss []string
|
|
||||||
for i := range k {
|
|
||||||
ss = append(ss, k.maybeQuoted(i))
|
|
||||||
}
|
|
||||||
return strings.Join(ss, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k Key) maybeQuoted(i int) string {
|
|
||||||
quote := false
|
|
||||||
for _, c := range k[i] {
|
|
||||||
if !isBareKeyChar(c) {
|
|
||||||
quote = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if quote {
|
|
||||||
return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
|
|
||||||
}
|
|
||||||
return k[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k Key) add(piece string) Key {
|
|
||||||
newKey := make(Key, len(k)+1)
|
|
||||||
copy(newKey, k)
|
|
||||||
newKey[len(k)] = piece
|
|
||||||
return newKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys returns a slice of every key in the TOML data, including key groups.
|
|
||||||
// Each key is itself a slice, where the first element is the top of the
|
|
||||||
// hierarchy and the last is the most specific.
|
|
||||||
//
|
|
||||||
// The list will have the same order as the keys appeared in the TOML data.
|
|
||||||
//
|
|
||||||
// All keys returned are non-empty.
|
|
||||||
func (md *MetaData) Keys() []Key {
|
|
||||||
return md.keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undecoded returns all keys that have not been decoded in the order in which
|
|
||||||
// they appear in the original TOML document.
|
|
||||||
//
|
|
||||||
// This includes keys that haven't been decoded because of a Primitive value.
|
|
||||||
// Once the Primitive value is decoded, the keys will be considered decoded.
|
|
||||||
//
|
|
||||||
// Also note that decoding into an empty interface will result in no decoding,
|
|
||||||
// and so no keys will be considered decoded.
|
|
||||||
//
|
|
||||||
// In this sense, the Undecoded keys correspond to keys in the TOML document
|
|
||||||
// that do not have a concrete type in your representation.
|
|
||||||
func (md *MetaData) Undecoded() []Key {
|
|
||||||
undecoded := make([]Key, 0, len(md.keys))
|
|
||||||
for _, key := range md.keys {
|
|
||||||
if !md.decoded[key.String()] {
|
|
||||||
undecoded = append(undecoded, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undecoded
|
|
||||||
}
|
|
27
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
27
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
Package toml provides facilities for decoding and encoding TOML configuration
|
|
||||||
files via reflection. There is also support for delaying decoding with
|
|
||||||
the Primitive type, and querying the set of keys in a TOML document with the
|
|
||||||
MetaData type.
|
|
||||||
|
|
||||||
The specification implemented: https://github.com/toml-lang/toml
|
|
||||||
|
|
||||||
The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
|
|
||||||
whether a file is a valid TOML document. It can also be used to print the
|
|
||||||
type of each key in a TOML document.
|
|
||||||
|
|
||||||
Testing
|
|
||||||
|
|
||||||
There are two important types of tests used for this package. The first is
|
|
||||||
contained inside '*_test.go' files and uses the standard Go unit testing
|
|
||||||
framework. These tests are primarily devoted to holistically testing the
|
|
||||||
decoder and encoder.
|
|
||||||
|
|
||||||
The second type of testing is used to verify the implementation's adherence
|
|
||||||
to the TOML specification. These tests have been factored into their own
|
|
||||||
project: https://github.com/BurntSushi/toml-test
|
|
||||||
|
|
||||||
The reason the tests are in a separate project is so that they can be used by
|
|
||||||
any implementation of TOML. Namely, it is language agnostic.
|
|
||||||
*/
|
|
||||||
package toml
|
|
568
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
568
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
|
@ -1,568 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type tomlEncodeError struct{ error }
|
|
||||||
|
|
||||||
var (
|
|
||||||
errArrayMixedElementTypes = errors.New(
|
|
||||||
"toml: cannot encode array with mixed element types")
|
|
||||||
errArrayNilElement = errors.New(
|
|
||||||
"toml: cannot encode array with nil element")
|
|
||||||
errNonString = errors.New(
|
|
||||||
"toml: cannot encode a map with non-string key type")
|
|
||||||
errAnonNonStruct = errors.New(
|
|
||||||
"toml: cannot encode an anonymous field that is not a struct")
|
|
||||||
errArrayNoTable = errors.New(
|
|
||||||
"toml: TOML array element cannot contain a table")
|
|
||||||
errNoKey = errors.New(
|
|
||||||
"toml: top-level values must be Go maps or structs")
|
|
||||||
errAnything = errors.New("") // used in testing
|
|
||||||
)
|
|
||||||
|
|
||||||
var quotedReplacer = strings.NewReplacer(
|
|
||||||
"\t", "\\t",
|
|
||||||
"\n", "\\n",
|
|
||||||
"\r", "\\r",
|
|
||||||
"\"", "\\\"",
|
|
||||||
"\\", "\\\\",
|
|
||||||
)
|
|
||||||
|
|
||||||
// Encoder controls the encoding of Go values to a TOML document to some
|
|
||||||
// io.Writer.
|
|
||||||
//
|
|
||||||
// The indentation level can be controlled with the Indent field.
|
|
||||||
type Encoder struct {
|
|
||||||
// A single indentation level. By default it is two spaces.
|
|
||||||
Indent string
|
|
||||||
|
|
||||||
// hasWritten is whether we have written any output to w yet.
|
|
||||||
hasWritten bool
|
|
||||||
w *bufio.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
|
|
||||||
// given. By default, a single indentation level is 2 spaces.
|
|
||||||
func NewEncoder(w io.Writer) *Encoder {
|
|
||||||
return &Encoder{
|
|
||||||
w: bufio.NewWriter(w),
|
|
||||||
Indent: " ",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode writes a TOML representation of the Go value to the underlying
|
|
||||||
// io.Writer. If the value given cannot be encoded to a valid TOML document,
|
|
||||||
// then an error is returned.
|
|
||||||
//
|
|
||||||
// The mapping between Go values and TOML values should be precisely the same
|
|
||||||
// as for the Decode* functions. Similarly, the TextMarshaler interface is
|
|
||||||
// supported by encoding the resulting bytes as strings. (If you want to write
|
|
||||||
// arbitrary binary data then you will need to use something like base64 since
|
|
||||||
// TOML does not have any binary types.)
|
|
||||||
//
|
|
||||||
// When encoding TOML hashes (i.e., Go maps or structs), keys without any
|
|
||||||
// sub-hashes are encoded first.
|
|
||||||
//
|
|
||||||
// If a Go map is encoded, then its keys are sorted alphabetically for
|
|
||||||
// deterministic output. More control over this behavior may be provided if
|
|
||||||
// there is demand for it.
|
|
||||||
//
|
|
||||||
// Encoding Go values without a corresponding TOML representation---like map
|
|
||||||
// types with non-string keys---will cause an error to be returned. Similarly
|
|
||||||
// for mixed arrays/slices, arrays/slices with nil elements, embedded
|
|
||||||
// non-struct types and nested slices containing maps or structs.
|
|
||||||
// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
|
|
||||||
// and so is []map[string][]string.)
|
|
||||||
func (enc *Encoder) Encode(v interface{}) error {
|
|
||||||
rv := eindirect(reflect.ValueOf(v))
|
|
||||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return enc.w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
if terr, ok := r.(tomlEncodeError); ok {
|
|
||||||
err = terr.error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
enc.encode(key, rv)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
|
||||||
// Special case. Time needs to be in ISO8601 format.
|
|
||||||
// Special case. If we can marshal the type to text, then we used that.
|
|
||||||
// Basically, this prevents the encoder for handling these types as
|
|
||||||
// generic structs (or whatever the underlying type of a TextMarshaler is).
|
|
||||||
switch rv.Interface().(type) {
|
|
||||||
case time.Time, TextMarshaler:
|
|
||||||
enc.keyEqElement(key, rv)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
k := rv.Kind()
|
|
||||||
switch k {
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
||||||
reflect.Int64,
|
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
|
||||||
reflect.Uint64,
|
|
||||||
reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
|
|
||||||
enc.keyEqElement(key, rv)
|
|
||||||
case reflect.Array, reflect.Slice:
|
|
||||||
if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
|
|
||||||
enc.eArrayOfTables(key, rv)
|
|
||||||
} else {
|
|
||||||
enc.keyEqElement(key, rv)
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
if rv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
enc.encode(key, rv.Elem())
|
|
||||||
case reflect.Map:
|
|
||||||
if rv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
enc.eTable(key, rv)
|
|
||||||
case reflect.Ptr:
|
|
||||||
if rv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
enc.encode(key, rv.Elem())
|
|
||||||
case reflect.Struct:
|
|
||||||
enc.eTable(key, rv)
|
|
||||||
default:
|
|
||||||
panic(e("unsupported type for key '%s': %s", key, k))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eElement encodes any value that can be an array element (primitives and
|
|
||||||
// arrays).
|
|
||||||
func (enc *Encoder) eElement(rv reflect.Value) {
|
|
||||||
switch v := rv.Interface().(type) {
|
|
||||||
case time.Time:
|
|
||||||
// Special case time.Time as a primitive. Has to come before
|
|
||||||
// TextMarshaler below because time.Time implements
|
|
||||||
// encoding.TextMarshaler, but we need to always use UTC.
|
|
||||||
enc.wf(v.UTC().Format("2006-01-02T15:04:05Z"))
|
|
||||||
return
|
|
||||||
case TextMarshaler:
|
|
||||||
// Special case. Use text marshaler if it's available for this value.
|
|
||||||
if s, err := v.MarshalText(); err != nil {
|
|
||||||
encPanic(err)
|
|
||||||
} else {
|
|
||||||
enc.writeQuoted(string(s))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
||||||
reflect.Int64:
|
|
||||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16,
|
|
||||||
reflect.Uint32, reflect.Uint64:
|
|
||||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
|
||||||
case reflect.Float32:
|
|
||||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
|
|
||||||
case reflect.Float64:
|
|
||||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
|
|
||||||
case reflect.Array, reflect.Slice:
|
|
||||||
enc.eArrayOrSliceElement(rv)
|
|
||||||
case reflect.Interface:
|
|
||||||
enc.eElement(rv.Elem())
|
|
||||||
case reflect.String:
|
|
||||||
enc.writeQuoted(rv.String())
|
|
||||||
default:
|
|
||||||
panic(e("unexpected primitive type: %s", rv.Kind()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// By the TOML spec, all floats must have a decimal with at least one
|
|
||||||
// number on either side.
|
|
||||||
func floatAddDecimal(fstr string) string {
|
|
||||||
if !strings.Contains(fstr, ".") {
|
|
||||||
return fstr + ".0"
|
|
||||||
}
|
|
||||||
return fstr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) writeQuoted(s string) {
|
|
||||||
enc.wf("\"%s\"", quotedReplacer.Replace(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
|
|
||||||
length := rv.Len()
|
|
||||||
enc.wf("[")
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
elem := rv.Index(i)
|
|
||||||
enc.eElement(elem)
|
|
||||||
if i != length-1 {
|
|
||||||
enc.wf(", ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enc.wf("]")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
|
||||||
if len(key) == 0 {
|
|
||||||
encPanic(errNoKey)
|
|
||||||
}
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
|
||||||
trv := rv.Index(i)
|
|
||||||
if isNil(trv) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
panicIfInvalidKey(key)
|
|
||||||
enc.newline()
|
|
||||||
enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
|
|
||||||
enc.newline()
|
|
||||||
enc.eMapOrStruct(key, trv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eTable(key Key, rv reflect.Value) {
|
|
||||||
panicIfInvalidKey(key)
|
|
||||||
if len(key) == 1 {
|
|
||||||
// Output an extra newline between top-level tables.
|
|
||||||
// (The newline isn't written if nothing else has been written though.)
|
|
||||||
enc.newline()
|
|
||||||
}
|
|
||||||
if len(key) > 0 {
|
|
||||||
enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
|
|
||||||
enc.newline()
|
|
||||||
}
|
|
||||||
enc.eMapOrStruct(key, rv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
|
|
||||||
switch rv := eindirect(rv); rv.Kind() {
|
|
||||||
case reflect.Map:
|
|
||||||
enc.eMap(key, rv)
|
|
||||||
case reflect.Struct:
|
|
||||||
enc.eStruct(key, rv)
|
|
||||||
default:
|
|
||||||
panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eMap(key Key, rv reflect.Value) {
|
|
||||||
rt := rv.Type()
|
|
||||||
if rt.Key().Kind() != reflect.String {
|
|
||||||
encPanic(errNonString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort keys so that we have deterministic output. And write keys directly
|
|
||||||
// underneath this key first, before writing sub-structs or sub-maps.
|
|
||||||
var mapKeysDirect, mapKeysSub []string
|
|
||||||
for _, mapKey := range rv.MapKeys() {
|
|
||||||
k := mapKey.String()
|
|
||||||
if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
|
|
||||||
mapKeysSub = append(mapKeysSub, k)
|
|
||||||
} else {
|
|
||||||
mapKeysDirect = append(mapKeysDirect, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var writeMapKeys = func(mapKeys []string) {
|
|
||||||
sort.Strings(mapKeys)
|
|
||||||
for _, mapKey := range mapKeys {
|
|
||||||
mrv := rv.MapIndex(reflect.ValueOf(mapKey))
|
|
||||||
if isNil(mrv) {
|
|
||||||
// Don't write anything for nil fields.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
enc.encode(key.add(mapKey), mrv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeMapKeys(mapKeysDirect)
|
|
||||||
writeMapKeys(mapKeysSub)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
|
||||||
// Write keys for fields directly under this key first, because if we write
|
|
||||||
// a field that creates a new table, then all keys under it will be in that
|
|
||||||
// table (not the one we're writing here).
|
|
||||||
rt := rv.Type()
|
|
||||||
var fieldsDirect, fieldsSub [][]int
|
|
||||||
var addFields func(rt reflect.Type, rv reflect.Value, start []int)
|
|
||||||
addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
|
|
||||||
for i := 0; i < rt.NumField(); i++ {
|
|
||||||
f := rt.Field(i)
|
|
||||||
// skip unexported fields
|
|
||||||
if f.PkgPath != "" && !f.Anonymous {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
frv := rv.Field(i)
|
|
||||||
if f.Anonymous {
|
|
||||||
t := f.Type
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
// Treat anonymous struct fields with
|
|
||||||
// tag names as though they are not
|
|
||||||
// anonymous, like encoding/json does.
|
|
||||||
if getOptions(f.Tag).name == "" {
|
|
||||||
addFields(t, frv, f.Index)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case reflect.Ptr:
|
|
||||||
if t.Elem().Kind() == reflect.Struct &&
|
|
||||||
getOptions(f.Tag).name == "" {
|
|
||||||
if !frv.IsNil() {
|
|
||||||
addFields(t.Elem(), frv.Elem(), f.Index)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Fall through to the normal field encoding logic below
|
|
||||||
// for non-struct anonymous fields.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if typeIsHash(tomlTypeOfGo(frv)) {
|
|
||||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
|
||||||
} else {
|
|
||||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addFields(rt, rv, nil)
|
|
||||||
|
|
||||||
var writeFields = func(fields [][]int) {
|
|
||||||
for _, fieldIndex := range fields {
|
|
||||||
sft := rt.FieldByIndex(fieldIndex)
|
|
||||||
sf := rv.FieldByIndex(fieldIndex)
|
|
||||||
if isNil(sf) {
|
|
||||||
// Don't write anything for nil fields.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := getOptions(sft.Tag)
|
|
||||||
if opts.skip {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
keyName := sft.Name
|
|
||||||
if opts.name != "" {
|
|
||||||
keyName = opts.name
|
|
||||||
}
|
|
||||||
if opts.omitempty && isEmpty(sf) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if opts.omitzero && isZero(sf) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
enc.encode(key.add(keyName), sf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeFields(fieldsDirect)
|
|
||||||
writeFields(fieldsSub)
|
|
||||||
}
|
|
||||||
|
|
||||||
// tomlTypeName returns the TOML type name of the Go value's type. It is
|
|
||||||
// used to determine whether the types of array elements are mixed (which is
|
|
||||||
// forbidden). If the Go value is nil, then it is illegal for it to be an array
|
|
||||||
// element, and valueIsNil is returned as true.
|
|
||||||
|
|
||||||
// Returns the TOML type of a Go value. The type may be `nil`, which means
|
|
||||||
// no concrete TOML type could be found.
|
|
||||||
func tomlTypeOfGo(rv reflect.Value) tomlType {
|
|
||||||
if isNil(rv) || !rv.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return tomlBool
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
||||||
reflect.Int64,
|
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
|
||||||
reflect.Uint64:
|
|
||||||
return tomlInteger
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return tomlFloat
|
|
||||||
case reflect.Array, reflect.Slice:
|
|
||||||
if typeEqual(tomlHash, tomlArrayType(rv)) {
|
|
||||||
return tomlArrayHash
|
|
||||||
}
|
|
||||||
return tomlArray
|
|
||||||
case reflect.Ptr, reflect.Interface:
|
|
||||||
return tomlTypeOfGo(rv.Elem())
|
|
||||||
case reflect.String:
|
|
||||||
return tomlString
|
|
||||||
case reflect.Map:
|
|
||||||
return tomlHash
|
|
||||||
case reflect.Struct:
|
|
||||||
switch rv.Interface().(type) {
|
|
||||||
case time.Time:
|
|
||||||
return tomlDatetime
|
|
||||||
case TextMarshaler:
|
|
||||||
return tomlString
|
|
||||||
default:
|
|
||||||
return tomlHash
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unexpected reflect.Kind: " + rv.Kind().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tomlArrayType returns the element type of a TOML array. The type returned
|
|
||||||
// may be nil if it cannot be determined (e.g., a nil slice or a zero length
|
|
||||||
// slize). This function may also panic if it finds a type that cannot be
|
|
||||||
// expressed in TOML (such as nil elements, heterogeneous arrays or directly
|
|
||||||
// nested arrays of tables).
|
|
||||||
func tomlArrayType(rv reflect.Value) tomlType {
|
|
||||||
if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
firstType := tomlTypeOfGo(rv.Index(0))
|
|
||||||
if firstType == nil {
|
|
||||||
encPanic(errArrayNilElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
rvlen := rv.Len()
|
|
||||||
for i := 1; i < rvlen; i++ {
|
|
||||||
elem := rv.Index(i)
|
|
||||||
switch elemType := tomlTypeOfGo(elem); {
|
|
||||||
case elemType == nil:
|
|
||||||
encPanic(errArrayNilElement)
|
|
||||||
case !typeEqual(firstType, elemType):
|
|
||||||
encPanic(errArrayMixedElementTypes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we have a nested array, then we must make sure that the nested
|
|
||||||
// array contains ONLY primitives.
|
|
||||||
// This checks arbitrarily nested arrays.
|
|
||||||
if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
|
|
||||||
nest := tomlArrayType(eindirect(rv.Index(0)))
|
|
||||||
if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
|
|
||||||
encPanic(errArrayNoTable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstType
|
|
||||||
}
|
|
||||||
|
|
||||||
type tagOptions struct {
|
|
||||||
skip bool // "-"
|
|
||||||
name string
|
|
||||||
omitempty bool
|
|
||||||
omitzero bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOptions(tag reflect.StructTag) tagOptions {
|
|
||||||
t := tag.Get("toml")
|
|
||||||
if t == "-" {
|
|
||||||
return tagOptions{skip: true}
|
|
||||||
}
|
|
||||||
var opts tagOptions
|
|
||||||
parts := strings.Split(t, ",")
|
|
||||||
opts.name = parts[0]
|
|
||||||
for _, s := range parts[1:] {
|
|
||||||
switch s {
|
|
||||||
case "omitempty":
|
|
||||||
opts.omitempty = true
|
|
||||||
case "omitzero":
|
|
||||||
opts.omitzero = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return opts
|
|
||||||
}
|
|
||||||
|
|
||||||
func isZero(rv reflect.Value) bool {
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return rv.Int() == 0
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
return rv.Uint() == 0
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return rv.Float() == 0.0
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isEmpty(rv reflect.Value) bool {
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
|
||||||
return rv.Len() == 0
|
|
||||||
case reflect.Bool:
|
|
||||||
return !rv.Bool()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) newline() {
|
|
||||||
if enc.hasWritten {
|
|
||||||
enc.wf("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
|
|
||||||
if len(key) == 0 {
|
|
||||||
encPanic(errNoKey)
|
|
||||||
}
|
|
||||||
panicIfInvalidKey(key)
|
|
||||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
|
||||||
enc.eElement(val)
|
|
||||||
enc.newline()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) wf(format string, v ...interface{}) {
|
|
||||||
if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
|
|
||||||
encPanic(err)
|
|
||||||
}
|
|
||||||
enc.hasWritten = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) indentStr(key Key) string {
|
|
||||||
return strings.Repeat(enc.Indent, len(key)-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func encPanic(err error) {
|
|
||||||
panic(tomlEncodeError{err})
|
|
||||||
}
|
|
||||||
|
|
||||||
func eindirect(v reflect.Value) reflect.Value {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Ptr, reflect.Interface:
|
|
||||||
return eindirect(v.Elem())
|
|
||||||
default:
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNil(rv reflect.Value) bool {
|
|
||||||
switch rv.Kind() {
|
|
||||||
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
||||||
return rv.IsNil()
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func panicIfInvalidKey(key Key) {
|
|
||||||
for _, k := range key {
|
|
||||||
if len(k) == 0 {
|
|
||||||
encPanic(e("Key '%s' is not a valid table name. Key names "+
|
|
||||||
"cannot be empty.", key.maybeQuotedAll()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidKeyName(s string) bool {
|
|
||||||
return len(s) != 0
|
|
||||||
}
|
|
19
vendor/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
19
vendor/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
// +build go1.2
|
|
||||||
|
|
||||||
package toml
|
|
||||||
|
|
||||||
// In order to support Go 1.1, we define our own TextMarshaler and
|
|
||||||
// TextUnmarshaler types. For Go 1.2+, we just alias them with the
|
|
||||||
// standard library interfaces.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
|
||||||
// so that Go 1.1 can be supported.
|
|
||||||
type TextMarshaler encoding.TextMarshaler
|
|
||||||
|
|
||||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
|
||||||
// here so that Go 1.1 can be supported.
|
|
||||||
type TextUnmarshaler encoding.TextUnmarshaler
|
|
18
vendor/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
18
vendor/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
|
@ -1,18 +0,0 @@
|
||||||
// +build !go1.2
|
|
||||||
|
|
||||||
package toml
|
|
||||||
|
|
||||||
// These interfaces were introduced in Go 1.2, so we add them manually when
|
|
||||||
// compiling for Go 1.1.
|
|
||||||
|
|
||||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
|
||||||
// so that Go 1.1 can be supported.
|
|
||||||
type TextMarshaler interface {
|
|
||||||
MarshalText() (text []byte, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
|
||||||
// here so that Go 1.1 can be supported.
|
|
||||||
type TextUnmarshaler interface {
|
|
||||||
UnmarshalText(text []byte) error
|
|
||||||
}
|
|
953
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
953
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
|
@ -1,953 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type itemType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
itemError itemType = iota
|
|
||||||
itemNIL // used in the parser to indicate no type
|
|
||||||
itemEOF
|
|
||||||
itemText
|
|
||||||
itemString
|
|
||||||
itemRawString
|
|
||||||
itemMultilineString
|
|
||||||
itemRawMultilineString
|
|
||||||
itemBool
|
|
||||||
itemInteger
|
|
||||||
itemFloat
|
|
||||||
itemDatetime
|
|
||||||
itemArray // the start of an array
|
|
||||||
itemArrayEnd
|
|
||||||
itemTableStart
|
|
||||||
itemTableEnd
|
|
||||||
itemArrayTableStart
|
|
||||||
itemArrayTableEnd
|
|
||||||
itemKeyStart
|
|
||||||
itemCommentStart
|
|
||||||
itemInlineTableStart
|
|
||||||
itemInlineTableEnd
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
eof = 0
|
|
||||||
comma = ','
|
|
||||||
tableStart = '['
|
|
||||||
tableEnd = ']'
|
|
||||||
arrayTableStart = '['
|
|
||||||
arrayTableEnd = ']'
|
|
||||||
tableSep = '.'
|
|
||||||
keySep = '='
|
|
||||||
arrayStart = '['
|
|
||||||
arrayEnd = ']'
|
|
||||||
commentStart = '#'
|
|
||||||
stringStart = '"'
|
|
||||||
stringEnd = '"'
|
|
||||||
rawStringStart = '\''
|
|
||||||
rawStringEnd = '\''
|
|
||||||
inlineTableStart = '{'
|
|
||||||
inlineTableEnd = '}'
|
|
||||||
)
|
|
||||||
|
|
||||||
type stateFn func(lx *lexer) stateFn
|
|
||||||
|
|
||||||
type lexer struct {
|
|
||||||
input string
|
|
||||||
start int
|
|
||||||
pos int
|
|
||||||
line int
|
|
||||||
state stateFn
|
|
||||||
items chan item
|
|
||||||
|
|
||||||
// Allow for backing up up to three runes.
|
|
||||||
// This is necessary because TOML contains 3-rune tokens (""" and ''').
|
|
||||||
prevWidths [3]int
|
|
||||||
nprev int // how many of prevWidths are in use
|
|
||||||
// If we emit an eof, we can still back up, but it is not OK to call
|
|
||||||
// next again.
|
|
||||||
atEOF bool
|
|
||||||
|
|
||||||
// A stack of state functions used to maintain context.
|
|
||||||
// The idea is to reuse parts of the state machine in various places.
|
|
||||||
// For example, values can appear at the top level or within arbitrarily
|
|
||||||
// nested arrays. The last state on the stack is used after a value has
|
|
||||||
// been lexed. Similarly for comments.
|
|
||||||
stack []stateFn
|
|
||||||
}
|
|
||||||
|
|
||||||
type item struct {
|
|
||||||
typ itemType
|
|
||||||
val string
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) nextItem() item {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case item := <-lx.items:
|
|
||||||
return item
|
|
||||||
default:
|
|
||||||
lx.state = lx.state(lx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lex(input string) *lexer {
|
|
||||||
lx := &lexer{
|
|
||||||
input: input,
|
|
||||||
state: lexTop,
|
|
||||||
line: 1,
|
|
||||||
items: make(chan item, 10),
|
|
||||||
stack: make([]stateFn, 0, 10),
|
|
||||||
}
|
|
||||||
return lx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) push(state stateFn) {
|
|
||||||
lx.stack = append(lx.stack, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) pop() stateFn {
|
|
||||||
if len(lx.stack) == 0 {
|
|
||||||
return lx.errorf("BUG in lexer: no states to pop")
|
|
||||||
}
|
|
||||||
last := lx.stack[len(lx.stack)-1]
|
|
||||||
lx.stack = lx.stack[0 : len(lx.stack)-1]
|
|
||||||
return last
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) current() string {
|
|
||||||
return lx.input[lx.start:lx.pos]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) emit(typ itemType) {
|
|
||||||
lx.items <- item{typ, lx.current(), lx.line}
|
|
||||||
lx.start = lx.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) emitTrim(typ itemType) {
|
|
||||||
lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line}
|
|
||||||
lx.start = lx.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lx *lexer) next() (r rune) {
|
|
||||||
if lx.atEOF {
|
|
||||||
panic("next called after EOF")
|
|
||||||
}
|
|
||||||
if lx.pos >= len(lx.input) {
|
|
||||||
lx.atEOF = true
|
|
||||||
return eof
|
|
||||||
}
|
|
||||||
|
|
||||||
if lx.input[lx.pos] == '\n' {
|
|
||||||
lx.line++
|
|
||||||
}
|
|
||||||
lx.prevWidths[2] = lx.prevWidths[1]
|
|
||||||
lx.prevWidths[1] = lx.prevWidths[0]
|
|
||||||
if lx.nprev < 3 {
|
|
||||||
lx.nprev++
|
|
||||||
}
|
|
||||||
r, w := utf8.DecodeRuneInString(lx.input[lx.pos:])
|
|
||||||
lx.prevWidths[0] = w
|
|
||||||
lx.pos += w
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore skips over the pending input before this point.
|
|
||||||
func (lx *lexer) ignore() {
|
|
||||||
lx.start = lx.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// backup steps back one rune. Can be called only twice between calls to next.
|
|
||||||
func (lx *lexer) backup() {
|
|
||||||
if lx.atEOF {
|
|
||||||
lx.atEOF = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if lx.nprev < 1 {
|
|
||||||
panic("backed up too far")
|
|
||||||
}
|
|
||||||
w := lx.prevWidths[0]
|
|
||||||
lx.prevWidths[0] = lx.prevWidths[1]
|
|
||||||
lx.prevWidths[1] = lx.prevWidths[2]
|
|
||||||
lx.nprev--
|
|
||||||
lx.pos -= w
|
|
||||||
if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' {
|
|
||||||
lx.line--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// accept consumes the next rune if it's equal to `valid`.
|
|
||||||
func (lx *lexer) accept(valid rune) bool {
|
|
||||||
if lx.next() == valid {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// peek returns but does not consume the next rune in the input.
|
|
||||||
func (lx *lexer) peek() rune {
|
|
||||||
r := lx.next()
|
|
||||||
lx.backup()
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip ignores all input that matches the given predicate.
|
|
||||||
func (lx *lexer) skip(pred func(rune) bool) {
|
|
||||||
for {
|
|
||||||
r := lx.next()
|
|
||||||
if pred(r) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
lx.ignore()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorf stops all lexing by emitting an error and returning `nil`.
|
|
||||||
// Note that any value that is a character is escaped if it's a special
|
|
||||||
// character (newlines, tabs, etc.).
|
|
||||||
func (lx *lexer) errorf(format string, values ...interface{}) stateFn {
|
|
||||||
lx.items <- item{
|
|
||||||
itemError,
|
|
||||||
fmt.Sprintf(format, values...),
|
|
||||||
lx.line,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexTop consumes elements at the top level of TOML data.
|
|
||||||
func lexTop(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isWhitespace(r) || isNL(r) {
|
|
||||||
return lexSkip(lx, lexTop)
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case commentStart:
|
|
||||||
lx.push(lexTop)
|
|
||||||
return lexCommentStart
|
|
||||||
case tableStart:
|
|
||||||
return lexTableStart
|
|
||||||
case eof:
|
|
||||||
if lx.pos > lx.start {
|
|
||||||
return lx.errorf("unexpected EOF")
|
|
||||||
}
|
|
||||||
lx.emit(itemEOF)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, the only valid item can be a key, so we back up
|
|
||||||
// and let the key lexer do the rest.
|
|
||||||
lx.backup()
|
|
||||||
lx.push(lexTopEnd)
|
|
||||||
return lexKeyStart
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexTopEnd is entered whenever a top-level item has been consumed. (A value
|
|
||||||
// or a table.) It must see only whitespace, and will turn back to lexTop
|
|
||||||
// upon a newline. If it sees EOF, it will quit the lexer successfully.
|
|
||||||
func lexTopEnd(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case r == commentStart:
|
|
||||||
// a comment will read to a newline for us.
|
|
||||||
lx.push(lexTop)
|
|
||||||
return lexCommentStart
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexTopEnd
|
|
||||||
case isNL(r):
|
|
||||||
lx.ignore()
|
|
||||||
return lexTop
|
|
||||||
case r == eof:
|
|
||||||
lx.emit(itemEOF)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return lx.errorf("expected a top-level item to end with a newline, "+
|
|
||||||
"comment, or EOF, but got %q instead", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexTable lexes the beginning of a table. Namely, it makes sure that
|
|
||||||
// it starts with a character other than '.' and ']'.
|
|
||||||
// It assumes that '[' has already been consumed.
|
|
||||||
// It also handles the case that this is an item in an array of tables.
|
|
||||||
// e.g., '[[name]]'.
|
|
||||||
func lexTableStart(lx *lexer) stateFn {
|
|
||||||
if lx.peek() == arrayTableStart {
|
|
||||||
lx.next()
|
|
||||||
lx.emit(itemArrayTableStart)
|
|
||||||
lx.push(lexArrayTableEnd)
|
|
||||||
} else {
|
|
||||||
lx.emit(itemTableStart)
|
|
||||||
lx.push(lexTableEnd)
|
|
||||||
}
|
|
||||||
return lexTableNameStart
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexTableEnd(lx *lexer) stateFn {
|
|
||||||
lx.emit(itemTableEnd)
|
|
||||||
return lexTopEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexArrayTableEnd(lx *lexer) stateFn {
|
|
||||||
if r := lx.next(); r != arrayTableEnd {
|
|
||||||
return lx.errorf("expected end of table array name delimiter %q, "+
|
|
||||||
"but got %q instead", arrayTableEnd, r)
|
|
||||||
}
|
|
||||||
lx.emit(itemArrayTableEnd)
|
|
||||||
return lexTopEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexTableNameStart(lx *lexer) stateFn {
|
|
||||||
lx.skip(isWhitespace)
|
|
||||||
switch r := lx.peek(); {
|
|
||||||
case r == tableEnd || r == eof:
|
|
||||||
return lx.errorf("unexpected end of table name " +
|
|
||||||
"(table names cannot be empty)")
|
|
||||||
case r == tableSep:
|
|
||||||
return lx.errorf("unexpected table separator " +
|
|
||||||
"(table names cannot be empty)")
|
|
||||||
case r == stringStart || r == rawStringStart:
|
|
||||||
lx.ignore()
|
|
||||||
lx.push(lexTableNameEnd)
|
|
||||||
return lexValue // reuse string lexing
|
|
||||||
default:
|
|
||||||
return lexBareTableName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexBareTableName lexes the name of a table. It assumes that at least one
|
|
||||||
// valid character for the table has already been read.
|
|
||||||
func lexBareTableName(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isBareKeyChar(r) {
|
|
||||||
return lexBareTableName
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemText)
|
|
||||||
return lexTableNameEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexTableNameEnd reads the end of a piece of a table name, optionally
|
|
||||||
// consuming whitespace.
|
|
||||||
func lexTableNameEnd(lx *lexer) stateFn {
|
|
||||||
lx.skip(isWhitespace)
|
|
||||||
switch r := lx.next(); {
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexTableNameEnd
|
|
||||||
case r == tableSep:
|
|
||||||
lx.ignore()
|
|
||||||
return lexTableNameStart
|
|
||||||
case r == tableEnd:
|
|
||||||
return lx.pop()
|
|
||||||
default:
|
|
||||||
return lx.errorf("expected '.' or ']' to end table name, "+
|
|
||||||
"but got %q instead", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexKeyStart consumes a key name up until the first non-whitespace character.
|
|
||||||
// lexKeyStart will ignore whitespace.
|
|
||||||
func lexKeyStart(lx *lexer) stateFn {
|
|
||||||
r := lx.peek()
|
|
||||||
switch {
|
|
||||||
case r == keySep:
|
|
||||||
return lx.errorf("unexpected key separator %q", keySep)
|
|
||||||
case isWhitespace(r) || isNL(r):
|
|
||||||
lx.next()
|
|
||||||
return lexSkip(lx, lexKeyStart)
|
|
||||||
case r == stringStart || r == rawStringStart:
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemKeyStart)
|
|
||||||
lx.push(lexKeyEnd)
|
|
||||||
return lexValue // reuse string lexing
|
|
||||||
default:
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemKeyStart)
|
|
||||||
return lexBareKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexBareKey consumes the text of a bare key. Assumes that the first character
|
|
||||||
// (which is not whitespace) has not yet been consumed.
|
|
||||||
func lexBareKey(lx *lexer) stateFn {
|
|
||||||
switch r := lx.next(); {
|
|
||||||
case isBareKeyChar(r):
|
|
||||||
return lexBareKey
|
|
||||||
case isWhitespace(r):
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemText)
|
|
||||||
return lexKeyEnd
|
|
||||||
case r == keySep:
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemText)
|
|
||||||
return lexKeyEnd
|
|
||||||
default:
|
|
||||||
return lx.errorf("bare keys cannot contain %q", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexKeyEnd consumes the end of a key and trims whitespace (up to the key
|
|
||||||
// separator).
|
|
||||||
func lexKeyEnd(lx *lexer) stateFn {
|
|
||||||
switch r := lx.next(); {
|
|
||||||
case r == keySep:
|
|
||||||
return lexSkip(lx, lexValue)
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexSkip(lx, lexKeyEnd)
|
|
||||||
default:
|
|
||||||
return lx.errorf("expected key separator %q, but got %q instead",
|
|
||||||
keySep, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexValue starts the consumption of a value anywhere a value is expected.
|
|
||||||
// lexValue will ignore whitespace.
|
|
||||||
// After a value is lexed, the last state on the next is popped and returned.
|
|
||||||
func lexValue(lx *lexer) stateFn {
|
|
||||||
// We allow whitespace to precede a value, but NOT newlines.
|
|
||||||
// In array syntax, the array states are responsible for ignoring newlines.
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexSkip(lx, lexValue)
|
|
||||||
case isDigit(r):
|
|
||||||
lx.backup() // avoid an extra state and use the same as above
|
|
||||||
return lexNumberOrDateStart
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case arrayStart:
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemArray)
|
|
||||||
return lexArrayValue
|
|
||||||
case inlineTableStart:
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemInlineTableStart)
|
|
||||||
return lexInlineTableValue
|
|
||||||
case stringStart:
|
|
||||||
if lx.accept(stringStart) {
|
|
||||||
if lx.accept(stringStart) {
|
|
||||||
lx.ignore() // Ignore """
|
|
||||||
return lexMultilineString
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
}
|
|
||||||
lx.ignore() // ignore the '"'
|
|
||||||
return lexString
|
|
||||||
case rawStringStart:
|
|
||||||
if lx.accept(rawStringStart) {
|
|
||||||
if lx.accept(rawStringStart) {
|
|
||||||
lx.ignore() // Ignore """
|
|
||||||
return lexMultilineRawString
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
}
|
|
||||||
lx.ignore() // ignore the "'"
|
|
||||||
return lexRawString
|
|
||||||
case '+', '-':
|
|
||||||
return lexNumberStart
|
|
||||||
case '.': // special error case, be kind to users
|
|
||||||
return lx.errorf("floats must start with a digit, not '.'")
|
|
||||||
}
|
|
||||||
if unicode.IsLetter(r) {
|
|
||||||
// Be permissive here; lexBool will give a nice error if the
|
|
||||||
// user wrote something like
|
|
||||||
// x = foo
|
|
||||||
// (i.e. not 'true' or 'false' but is something else word-like.)
|
|
||||||
lx.backup()
|
|
||||||
return lexBool
|
|
||||||
}
|
|
||||||
return lx.errorf("expected value but found %q instead", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexArrayValue consumes one value in an array. It assumes that '[' or ','
|
|
||||||
// have already been consumed. All whitespace and newlines are ignored.
|
|
||||||
func lexArrayValue(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case isWhitespace(r) || isNL(r):
|
|
||||||
return lexSkip(lx, lexArrayValue)
|
|
||||||
case r == commentStart:
|
|
||||||
lx.push(lexArrayValue)
|
|
||||||
return lexCommentStart
|
|
||||||
case r == comma:
|
|
||||||
return lx.errorf("unexpected comma")
|
|
||||||
case r == arrayEnd:
|
|
||||||
// NOTE(caleb): The spec isn't clear about whether you can have
|
|
||||||
// a trailing comma or not, so we'll allow it.
|
|
||||||
return lexArrayEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
lx.backup()
|
|
||||||
lx.push(lexArrayValueEnd)
|
|
||||||
return lexValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexArrayValueEnd consumes everything between the end of an array value and
|
|
||||||
// the next value (or the end of the array): it ignores whitespace and newlines
|
|
||||||
// and expects either a ',' or a ']'.
|
|
||||||
func lexArrayValueEnd(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case isWhitespace(r) || isNL(r):
|
|
||||||
return lexSkip(lx, lexArrayValueEnd)
|
|
||||||
case r == commentStart:
|
|
||||||
lx.push(lexArrayValueEnd)
|
|
||||||
return lexCommentStart
|
|
||||||
case r == comma:
|
|
||||||
lx.ignore()
|
|
||||||
return lexArrayValue // move on to the next value
|
|
||||||
case r == arrayEnd:
|
|
||||||
return lexArrayEnd
|
|
||||||
}
|
|
||||||
return lx.errorf(
|
|
||||||
"expected a comma or array terminator %q, but got %q instead",
|
|
||||||
arrayEnd, r,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexArrayEnd finishes the lexing of an array.
|
|
||||||
// It assumes that a ']' has just been consumed.
|
|
||||||
func lexArrayEnd(lx *lexer) stateFn {
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemArrayEnd)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexInlineTableValue consumes one key/value pair in an inline table.
|
|
||||||
// It assumes that '{' or ',' have already been consumed. Whitespace is ignored.
|
|
||||||
func lexInlineTableValue(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexSkip(lx, lexInlineTableValue)
|
|
||||||
case isNL(r):
|
|
||||||
return lx.errorf("newlines not allowed within inline tables")
|
|
||||||
case r == commentStart:
|
|
||||||
lx.push(lexInlineTableValue)
|
|
||||||
return lexCommentStart
|
|
||||||
case r == comma:
|
|
||||||
return lx.errorf("unexpected comma")
|
|
||||||
case r == inlineTableEnd:
|
|
||||||
return lexInlineTableEnd
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
lx.push(lexInlineTableValueEnd)
|
|
||||||
return lexKeyStart
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexInlineTableValueEnd consumes everything between the end of an inline table
|
|
||||||
// key/value pair and the next pair (or the end of the table):
|
|
||||||
// it ignores whitespace and expects either a ',' or a '}'.
|
|
||||||
func lexInlineTableValueEnd(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case isWhitespace(r):
|
|
||||||
return lexSkip(lx, lexInlineTableValueEnd)
|
|
||||||
case isNL(r):
|
|
||||||
return lx.errorf("newlines not allowed within inline tables")
|
|
||||||
case r == commentStart:
|
|
||||||
lx.push(lexInlineTableValueEnd)
|
|
||||||
return lexCommentStart
|
|
||||||
case r == comma:
|
|
||||||
lx.ignore()
|
|
||||||
return lexInlineTableValue
|
|
||||||
case r == inlineTableEnd:
|
|
||||||
return lexInlineTableEnd
|
|
||||||
}
|
|
||||||
return lx.errorf("expected a comma or an inline table terminator %q, "+
|
|
||||||
"but got %q instead", inlineTableEnd, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexInlineTableEnd finishes the lexing of an inline table.
|
|
||||||
// It assumes that a '}' has just been consumed.
|
|
||||||
func lexInlineTableEnd(lx *lexer) stateFn {
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemInlineTableEnd)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexString consumes the inner contents of a string. It assumes that the
|
|
||||||
// beginning '"' has already been consumed and ignored.
|
|
||||||
func lexString(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case r == eof:
|
|
||||||
return lx.errorf("unexpected EOF")
|
|
||||||
case isNL(r):
|
|
||||||
return lx.errorf("strings cannot contain newlines")
|
|
||||||
case r == '\\':
|
|
||||||
lx.push(lexString)
|
|
||||||
return lexStringEscape
|
|
||||||
case r == stringEnd:
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemString)
|
|
||||||
lx.next()
|
|
||||||
lx.ignore()
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
return lexString
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexMultilineString consumes the inner contents of a string. It assumes that
|
|
||||||
// the beginning '"""' has already been consumed and ignored.
|
|
||||||
func lexMultilineString(lx *lexer) stateFn {
|
|
||||||
switch lx.next() {
|
|
||||||
case eof:
|
|
||||||
return lx.errorf("unexpected EOF")
|
|
||||||
case '\\':
|
|
||||||
return lexMultilineStringEscape
|
|
||||||
case stringEnd:
|
|
||||||
if lx.accept(stringEnd) {
|
|
||||||
if lx.accept(stringEnd) {
|
|
||||||
lx.backup()
|
|
||||||
lx.backup()
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemMultilineString)
|
|
||||||
lx.next()
|
|
||||||
lx.next()
|
|
||||||
lx.next()
|
|
||||||
lx.ignore()
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lexMultilineString
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexRawString consumes a raw string. Nothing can be escaped in such a string.
|
|
||||||
// It assumes that the beginning "'" has already been consumed and ignored.
|
|
||||||
func lexRawString(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch {
|
|
||||||
case r == eof:
|
|
||||||
return lx.errorf("unexpected EOF")
|
|
||||||
case isNL(r):
|
|
||||||
return lx.errorf("strings cannot contain newlines")
|
|
||||||
case r == rawStringEnd:
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemRawString)
|
|
||||||
lx.next()
|
|
||||||
lx.ignore()
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
return lexRawString
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such
|
|
||||||
// a string. It assumes that the beginning "'''" has already been consumed and
|
|
||||||
// ignored.
|
|
||||||
func lexMultilineRawString(lx *lexer) stateFn {
|
|
||||||
switch lx.next() {
|
|
||||||
case eof:
|
|
||||||
return lx.errorf("unexpected EOF")
|
|
||||||
case rawStringEnd:
|
|
||||||
if lx.accept(rawStringEnd) {
|
|
||||||
if lx.accept(rawStringEnd) {
|
|
||||||
lx.backup()
|
|
||||||
lx.backup()
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemRawMultilineString)
|
|
||||||
lx.next()
|
|
||||||
lx.next()
|
|
||||||
lx.next()
|
|
||||||
lx.ignore()
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lexMultilineRawString
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexMultilineStringEscape consumes an escaped character. It assumes that the
|
|
||||||
// preceding '\\' has already been consumed.
|
|
||||||
func lexMultilineStringEscape(lx *lexer) stateFn {
|
|
||||||
// Handle the special case first:
|
|
||||||
if isNL(lx.next()) {
|
|
||||||
return lexMultilineString
|
|
||||||
}
|
|
||||||
lx.backup()
|
|
||||||
lx.push(lexMultilineString)
|
|
||||||
return lexStringEscape(lx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexStringEscape(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
switch r {
|
|
||||||
case 'b':
|
|
||||||
fallthrough
|
|
||||||
case 't':
|
|
||||||
fallthrough
|
|
||||||
case 'n':
|
|
||||||
fallthrough
|
|
||||||
case 'f':
|
|
||||||
fallthrough
|
|
||||||
case 'r':
|
|
||||||
fallthrough
|
|
||||||
case '"':
|
|
||||||
fallthrough
|
|
||||||
case '\\':
|
|
||||||
return lx.pop()
|
|
||||||
case 'u':
|
|
||||||
return lexShortUnicodeEscape
|
|
||||||
case 'U':
|
|
||||||
return lexLongUnicodeEscape
|
|
||||||
}
|
|
||||||
return lx.errorf("invalid escape character %q; only the following "+
|
|
||||||
"escape characters are allowed: "+
|
|
||||||
`\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX`, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexShortUnicodeEscape(lx *lexer) stateFn {
|
|
||||||
var r rune
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
r = lx.next()
|
|
||||||
if !isHexadecimal(r) {
|
|
||||||
return lx.errorf(`expected four hexadecimal digits after '\u', `+
|
|
||||||
"but got %q instead", lx.current())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
func lexLongUnicodeEscape(lx *lexer) stateFn {
|
|
||||||
var r rune
|
|
||||||
for i := 0; i < 8; i++ {
|
|
||||||
r = lx.next()
|
|
||||||
if !isHexadecimal(r) {
|
|
||||||
return lx.errorf(`expected eight hexadecimal digits after '\U', `+
|
|
||||||
"but got %q instead", lx.current())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexNumberOrDateStart consumes either an integer, a float, or datetime.
|
|
||||||
func lexNumberOrDateStart(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isDigit(r) {
|
|
||||||
return lexNumberOrDate
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '_':
|
|
||||||
return lexNumber
|
|
||||||
case 'e', 'E':
|
|
||||||
return lexFloat
|
|
||||||
case '.':
|
|
||||||
return lx.errorf("floats must start with a digit, not '.'")
|
|
||||||
}
|
|
||||||
return lx.errorf("expected a digit but got %q", r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexNumberOrDate consumes either an integer, float or datetime.
|
|
||||||
func lexNumberOrDate(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isDigit(r) {
|
|
||||||
return lexNumberOrDate
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '-':
|
|
||||||
return lexDatetime
|
|
||||||
case '_':
|
|
||||||
return lexNumber
|
|
||||||
case '.', 'e', 'E':
|
|
||||||
return lexFloat
|
|
||||||
}
|
|
||||||
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemInteger)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexDatetime consumes a Datetime, to a first approximation.
|
|
||||||
// The parser validates that it matches one of the accepted formats.
|
|
||||||
func lexDatetime(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isDigit(r) {
|
|
||||||
return lexDatetime
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '-', 'T', ':', '.', 'Z', '+':
|
|
||||||
return lexDatetime
|
|
||||||
}
|
|
||||||
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemDatetime)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexNumberStart consumes either an integer or a float. It assumes that a sign
|
|
||||||
// has already been read, but that *no* digits have been consumed.
|
|
||||||
// lexNumberStart will move to the appropriate integer or float states.
|
|
||||||
func lexNumberStart(lx *lexer) stateFn {
|
|
||||||
// We MUST see a digit. Even floats have to start with a digit.
|
|
||||||
r := lx.next()
|
|
||||||
if !isDigit(r) {
|
|
||||||
if r == '.' {
|
|
||||||
return lx.errorf("floats must start with a digit, not '.'")
|
|
||||||
}
|
|
||||||
return lx.errorf("expected a digit but got %q", r)
|
|
||||||
}
|
|
||||||
return lexNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexNumber consumes an integer or a float after seeing the first digit.
|
|
||||||
func lexNumber(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isDigit(r) {
|
|
||||||
return lexNumber
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '_':
|
|
||||||
return lexNumber
|
|
||||||
case '.', 'e', 'E':
|
|
||||||
return lexFloat
|
|
||||||
}
|
|
||||||
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemInteger)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexFloat consumes the elements of a float. It allows any sequence of
|
|
||||||
// float-like characters, so floats emitted by the lexer are only a first
|
|
||||||
// approximation and must be validated by the parser.
|
|
||||||
func lexFloat(lx *lexer) stateFn {
|
|
||||||
r := lx.next()
|
|
||||||
if isDigit(r) {
|
|
||||||
return lexFloat
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '_', '.', '-', '+', 'e', 'E':
|
|
||||||
return lexFloat
|
|
||||||
}
|
|
||||||
|
|
||||||
lx.backup()
|
|
||||||
lx.emit(itemFloat)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexBool consumes a bool string: 'true' or 'false.
|
|
||||||
func lexBool(lx *lexer) stateFn {
|
|
||||||
var rs []rune
|
|
||||||
for {
|
|
||||||
r := lx.next()
|
|
||||||
if !unicode.IsLetter(r) {
|
|
||||||
lx.backup()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
rs = append(rs, r)
|
|
||||||
}
|
|
||||||
s := string(rs)
|
|
||||||
switch s {
|
|
||||||
case "true", "false":
|
|
||||||
lx.emit(itemBool)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
return lx.errorf("expected value but found %q instead", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexCommentStart begins the lexing of a comment. It will emit
|
|
||||||
// itemCommentStart and consume no characters, passing control to lexComment.
|
|
||||||
func lexCommentStart(lx *lexer) stateFn {
|
|
||||||
lx.ignore()
|
|
||||||
lx.emit(itemCommentStart)
|
|
||||||
return lexComment
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexComment lexes an entire comment. It assumes that '#' has been consumed.
|
|
||||||
// It will consume *up to* the first newline character, and pass control
|
|
||||||
// back to the last state on the stack.
|
|
||||||
func lexComment(lx *lexer) stateFn {
|
|
||||||
r := lx.peek()
|
|
||||||
if isNL(r) || r == eof {
|
|
||||||
lx.emit(itemText)
|
|
||||||
return lx.pop()
|
|
||||||
}
|
|
||||||
lx.next()
|
|
||||||
return lexComment
|
|
||||||
}
|
|
||||||
|
|
||||||
// lexSkip ignores all slurped input and moves on to the next state.
|
|
||||||
func lexSkip(lx *lexer, nextState stateFn) stateFn {
|
|
||||||
return func(lx *lexer) stateFn {
|
|
||||||
lx.ignore()
|
|
||||||
return nextState
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWhitespace returns true if `r` is a whitespace character according
|
|
||||||
// to the spec.
|
|
||||||
func isWhitespace(r rune) bool {
|
|
||||||
return r == '\t' || r == ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNL(r rune) bool {
|
|
||||||
return r == '\n' || r == '\r'
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDigit(r rune) bool {
|
|
||||||
return r >= '0' && r <= '9'
|
|
||||||
}
|
|
||||||
|
|
||||||
func isHexadecimal(r rune) bool {
|
|
||||||
return (r >= '0' && r <= '9') ||
|
|
||||||
(r >= 'a' && r <= 'f') ||
|
|
||||||
(r >= 'A' && r <= 'F')
|
|
||||||
}
|
|
||||||
|
|
||||||
func isBareKeyChar(r rune) bool {
|
|
||||||
return (r >= 'A' && r <= 'Z') ||
|
|
||||||
(r >= 'a' && r <= 'z') ||
|
|
||||||
(r >= '0' && r <= '9') ||
|
|
||||||
r == '_' ||
|
|
||||||
r == '-'
|
|
||||||
}
|
|
||||||
|
|
||||||
func (itype itemType) String() string {
|
|
||||||
switch itype {
|
|
||||||
case itemError:
|
|
||||||
return "Error"
|
|
||||||
case itemNIL:
|
|
||||||
return "NIL"
|
|
||||||
case itemEOF:
|
|
||||||
return "EOF"
|
|
||||||
case itemText:
|
|
||||||
return "Text"
|
|
||||||
case itemString, itemRawString, itemMultilineString, itemRawMultilineString:
|
|
||||||
return "String"
|
|
||||||
case itemBool:
|
|
||||||
return "Bool"
|
|
||||||
case itemInteger:
|
|
||||||
return "Integer"
|
|
||||||
case itemFloat:
|
|
||||||
return "Float"
|
|
||||||
case itemDatetime:
|
|
||||||
return "DateTime"
|
|
||||||
case itemTableStart:
|
|
||||||
return "TableStart"
|
|
||||||
case itemTableEnd:
|
|
||||||
return "TableEnd"
|
|
||||||
case itemKeyStart:
|
|
||||||
return "KeyStart"
|
|
||||||
case itemArray:
|
|
||||||
return "Array"
|
|
||||||
case itemArrayEnd:
|
|
||||||
return "ArrayEnd"
|
|
||||||
case itemCommentStart:
|
|
||||||
return "CommentStart"
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item item) String() string {
|
|
||||||
return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val)
|
|
||||||
}
|
|
592
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
592
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
|
@ -1,592 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type parser struct {
|
|
||||||
mapping map[string]interface{}
|
|
||||||
types map[string]tomlType
|
|
||||||
lx *lexer
|
|
||||||
|
|
||||||
// A list of keys in the order that they appear in the TOML data.
|
|
||||||
ordered []Key
|
|
||||||
|
|
||||||
// the full key for the current hash in scope
|
|
||||||
context Key
|
|
||||||
|
|
||||||
// the base key name for everything except hashes
|
|
||||||
currentKey string
|
|
||||||
|
|
||||||
// rough approximation of line number
|
|
||||||
approxLine int
|
|
||||||
|
|
||||||
// A map of 'key.group.names' to whether they were created implicitly.
|
|
||||||
implicits map[string]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type parseError string
|
|
||||||
|
|
||||||
func (pe parseError) Error() string {
|
|
||||||
return string(pe)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(data string) (p *parser, err error) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
var ok bool
|
|
||||||
if err, ok = r.(parseError); ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
p = &parser{
|
|
||||||
mapping: make(map[string]interface{}),
|
|
||||||
types: make(map[string]tomlType),
|
|
||||||
lx: lex(data),
|
|
||||||
ordered: make([]Key, 0),
|
|
||||||
implicits: make(map[string]bool),
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
item := p.next()
|
|
||||||
if item.typ == itemEOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.topLevel(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) panicf(format string, v ...interface{}) {
|
|
||||||
msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s",
|
|
||||||
p.approxLine, p.current(), fmt.Sprintf(format, v...))
|
|
||||||
panic(parseError(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) next() item {
|
|
||||||
it := p.lx.nextItem()
|
|
||||||
if it.typ == itemError {
|
|
||||||
p.panicf("%s", it.val)
|
|
||||||
}
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) bug(format string, v ...interface{}) {
|
|
||||||
panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) expect(typ itemType) item {
|
|
||||||
it := p.next()
|
|
||||||
p.assertEqual(typ, it.typ)
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) assertEqual(expected, got itemType) {
|
|
||||||
if expected != got {
|
|
||||||
p.bug("Expected '%s' but got '%s'.", expected, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) topLevel(item item) {
|
|
||||||
switch item.typ {
|
|
||||||
case itemCommentStart:
|
|
||||||
p.approxLine = item.line
|
|
||||||
p.expect(itemText)
|
|
||||||
case itemTableStart:
|
|
||||||
kg := p.next()
|
|
||||||
p.approxLine = kg.line
|
|
||||||
|
|
||||||
var key Key
|
|
||||||
for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() {
|
|
||||||
key = append(key, p.keyString(kg))
|
|
||||||
}
|
|
||||||
p.assertEqual(itemTableEnd, kg.typ)
|
|
||||||
|
|
||||||
p.establishContext(key, false)
|
|
||||||
p.setType("", tomlHash)
|
|
||||||
p.ordered = append(p.ordered, key)
|
|
||||||
case itemArrayTableStart:
|
|
||||||
kg := p.next()
|
|
||||||
p.approxLine = kg.line
|
|
||||||
|
|
||||||
var key Key
|
|
||||||
for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() {
|
|
||||||
key = append(key, p.keyString(kg))
|
|
||||||
}
|
|
||||||
p.assertEqual(itemArrayTableEnd, kg.typ)
|
|
||||||
|
|
||||||
p.establishContext(key, true)
|
|
||||||
p.setType("", tomlArrayHash)
|
|
||||||
p.ordered = append(p.ordered, key)
|
|
||||||
case itemKeyStart:
|
|
||||||
kname := p.next()
|
|
||||||
p.approxLine = kname.line
|
|
||||||
p.currentKey = p.keyString(kname)
|
|
||||||
|
|
||||||
val, typ := p.value(p.next())
|
|
||||||
p.setValue(p.currentKey, val)
|
|
||||||
p.setType(p.currentKey, typ)
|
|
||||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
|
||||||
p.currentKey = ""
|
|
||||||
default:
|
|
||||||
p.bug("Unexpected type at top level: %s", item.typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets a string for a key (or part of a key in a table name).
|
|
||||||
func (p *parser) keyString(it item) string {
|
|
||||||
switch it.typ {
|
|
||||||
case itemText:
|
|
||||||
return it.val
|
|
||||||
case itemString, itemMultilineString,
|
|
||||||
itemRawString, itemRawMultilineString:
|
|
||||||
s, _ := p.value(it)
|
|
||||||
return s.(string)
|
|
||||||
default:
|
|
||||||
p.bug("Unexpected key type: %s", it.typ)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// value translates an expected value from the lexer into a Go value wrapped
|
|
||||||
// as an empty interface.
|
|
||||||
func (p *parser) value(it item) (interface{}, tomlType) {
|
|
||||||
switch it.typ {
|
|
||||||
case itemString:
|
|
||||||
return p.replaceEscapes(it.val), p.typeOfPrimitive(it)
|
|
||||||
case itemMultilineString:
|
|
||||||
trimmed := stripFirstNewline(stripEscapedWhitespace(it.val))
|
|
||||||
return p.replaceEscapes(trimmed), p.typeOfPrimitive(it)
|
|
||||||
case itemRawString:
|
|
||||||
return it.val, p.typeOfPrimitive(it)
|
|
||||||
case itemRawMultilineString:
|
|
||||||
return stripFirstNewline(it.val), p.typeOfPrimitive(it)
|
|
||||||
case itemBool:
|
|
||||||
switch it.val {
|
|
||||||
case "true":
|
|
||||||
return true, p.typeOfPrimitive(it)
|
|
||||||
case "false":
|
|
||||||
return false, p.typeOfPrimitive(it)
|
|
||||||
}
|
|
||||||
p.bug("Expected boolean value, but got '%s'.", it.val)
|
|
||||||
case itemInteger:
|
|
||||||
if !numUnderscoresOK(it.val) {
|
|
||||||
p.panicf("Invalid integer %q: underscores must be surrounded by digits",
|
|
||||||
it.val)
|
|
||||||
}
|
|
||||||
val := strings.Replace(it.val, "_", "", -1)
|
|
||||||
num, err := strconv.ParseInt(val, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
// Distinguish integer values. Normally, it'd be a bug if the lexer
|
|
||||||
// provides an invalid integer, but it's possible that the number is
|
|
||||||
// out of range of valid values (which the lexer cannot determine).
|
|
||||||
// So mark the former as a bug but the latter as a legitimate user
|
|
||||||
// error.
|
|
||||||
if e, ok := err.(*strconv.NumError); ok &&
|
|
||||||
e.Err == strconv.ErrRange {
|
|
||||||
|
|
||||||
p.panicf("Integer '%s' is out of the range of 64-bit "+
|
|
||||||
"signed integers.", it.val)
|
|
||||||
} else {
|
|
||||||
p.bug("Expected integer value, but got '%s'.", it.val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return num, p.typeOfPrimitive(it)
|
|
||||||
case itemFloat:
|
|
||||||
parts := strings.FieldsFunc(it.val, func(r rune) bool {
|
|
||||||
switch r {
|
|
||||||
case '.', 'e', 'E':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
for _, part := range parts {
|
|
||||||
if !numUnderscoresOK(part) {
|
|
||||||
p.panicf("Invalid float %q: underscores must be "+
|
|
||||||
"surrounded by digits", it.val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !numPeriodsOK(it.val) {
|
|
||||||
// As a special case, numbers like '123.' or '1.e2',
|
|
||||||
// which are valid as far as Go/strconv are concerned,
|
|
||||||
// must be rejected because TOML says that a fractional
|
|
||||||
// part consists of '.' followed by 1+ digits.
|
|
||||||
p.panicf("Invalid float %q: '.' must be followed "+
|
|
||||||
"by one or more digits", it.val)
|
|
||||||
}
|
|
||||||
val := strings.Replace(it.val, "_", "", -1)
|
|
||||||
num, err := strconv.ParseFloat(val, 64)
|
|
||||||
if err != nil {
|
|
||||||
if e, ok := err.(*strconv.NumError); ok &&
|
|
||||||
e.Err == strconv.ErrRange {
|
|
||||||
|
|
||||||
p.panicf("Float '%s' is out of the range of 64-bit "+
|
|
||||||
"IEEE-754 floating-point numbers.", it.val)
|
|
||||||
} else {
|
|
||||||
p.panicf("Invalid float value: %q", it.val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return num, p.typeOfPrimitive(it)
|
|
||||||
case itemDatetime:
|
|
||||||
var t time.Time
|
|
||||||
var ok bool
|
|
||||||
var err error
|
|
||||||
for _, format := range []string{
|
|
||||||
"2006-01-02T15:04:05Z07:00",
|
|
||||||
"2006-01-02T15:04:05",
|
|
||||||
"2006-01-02",
|
|
||||||
} {
|
|
||||||
t, err = time.ParseInLocation(format, it.val, time.Local)
|
|
||||||
if err == nil {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
p.panicf("Invalid TOML Datetime: %q.", it.val)
|
|
||||||
}
|
|
||||||
return t, p.typeOfPrimitive(it)
|
|
||||||
case itemArray:
|
|
||||||
array := make([]interface{}, 0)
|
|
||||||
types := make([]tomlType, 0)
|
|
||||||
|
|
||||||
for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
|
|
||||||
if it.typ == itemCommentStart {
|
|
||||||
p.expect(itemText)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val, typ := p.value(it)
|
|
||||||
array = append(array, val)
|
|
||||||
types = append(types, typ)
|
|
||||||
}
|
|
||||||
return array, p.typeOfArray(types)
|
|
||||||
case itemInlineTableStart:
|
|
||||||
var (
|
|
||||||
hash = make(map[string]interface{})
|
|
||||||
outerContext = p.context
|
|
||||||
outerKey = p.currentKey
|
|
||||||
)
|
|
||||||
|
|
||||||
p.context = append(p.context, p.currentKey)
|
|
||||||
p.currentKey = ""
|
|
||||||
for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
|
|
||||||
if it.typ != itemKeyStart {
|
|
||||||
p.bug("Expected key start but instead found %q, around line %d",
|
|
||||||
it.val, p.approxLine)
|
|
||||||
}
|
|
||||||
if it.typ == itemCommentStart {
|
|
||||||
p.expect(itemText)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve key
|
|
||||||
k := p.next()
|
|
||||||
p.approxLine = k.line
|
|
||||||
kname := p.keyString(k)
|
|
||||||
|
|
||||||
// retrieve value
|
|
||||||
p.currentKey = kname
|
|
||||||
val, typ := p.value(p.next())
|
|
||||||
// make sure we keep metadata up to date
|
|
||||||
p.setType(kname, typ)
|
|
||||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
|
||||||
hash[kname] = val
|
|
||||||
}
|
|
||||||
p.context = outerContext
|
|
||||||
p.currentKey = outerKey
|
|
||||||
return hash, tomlHash
|
|
||||||
}
|
|
||||||
p.bug("Unexpected value type: %s", it.typ)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// numUnderscoresOK checks whether each underscore in s is surrounded by
|
|
||||||
// characters that are not underscores.
|
|
||||||
func numUnderscoresOK(s string) bool {
|
|
||||||
accept := false
|
|
||||||
for _, r := range s {
|
|
||||||
if r == '_' {
|
|
||||||
if !accept {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
accept = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
accept = true
|
|
||||||
}
|
|
||||||
return accept
|
|
||||||
}
|
|
||||||
|
|
||||||
// numPeriodsOK checks whether every period in s is followed by a digit.
|
|
||||||
func numPeriodsOK(s string) bool {
|
|
||||||
period := false
|
|
||||||
for _, r := range s {
|
|
||||||
if period && !isDigit(r) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
period = r == '.'
|
|
||||||
}
|
|
||||||
return !period
|
|
||||||
}
|
|
||||||
|
|
||||||
// establishContext sets the current context of the parser,
|
|
||||||
// where the context is either a hash or an array of hashes. Which one is
|
|
||||||
// set depends on the value of the `array` parameter.
|
|
||||||
//
|
|
||||||
// Establishing the context also makes sure that the key isn't a duplicate, and
|
|
||||||
// will create implicit hashes automatically.
|
|
||||||
func (p *parser) establishContext(key Key, array bool) {
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
// Always start at the top level and drill down for our context.
|
|
||||||
hashContext := p.mapping
|
|
||||||
keyContext := make(Key, 0)
|
|
||||||
|
|
||||||
// We only need implicit hashes for key[0:-1]
|
|
||||||
for _, k := range key[0 : len(key)-1] {
|
|
||||||
_, ok = hashContext[k]
|
|
||||||
keyContext = append(keyContext, k)
|
|
||||||
|
|
||||||
// No key? Make an implicit hash and move on.
|
|
||||||
if !ok {
|
|
||||||
p.addImplicit(keyContext)
|
|
||||||
hashContext[k] = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the hash context is actually an array of tables, then set
|
|
||||||
// the hash context to the last element in that array.
|
|
||||||
//
|
|
||||||
// Otherwise, it better be a table, since this MUST be a key group (by
|
|
||||||
// virtue of it not being the last element in a key).
|
|
||||||
switch t := hashContext[k].(type) {
|
|
||||||
case []map[string]interface{}:
|
|
||||||
hashContext = t[len(t)-1]
|
|
||||||
case map[string]interface{}:
|
|
||||||
hashContext = t
|
|
||||||
default:
|
|
||||||
p.panicf("Key '%s' was already created as a hash.", keyContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.context = keyContext
|
|
||||||
if array {
|
|
||||||
// If this is the first element for this array, then allocate a new
|
|
||||||
// list of tables for it.
|
|
||||||
k := key[len(key)-1]
|
|
||||||
if _, ok := hashContext[k]; !ok {
|
|
||||||
hashContext[k] = make([]map[string]interface{}, 0, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new table. But make sure the key hasn't already been used
|
|
||||||
// for something else.
|
|
||||||
if hash, ok := hashContext[k].([]map[string]interface{}); ok {
|
|
||||||
hashContext[k] = append(hash, make(map[string]interface{}))
|
|
||||||
} else {
|
|
||||||
p.panicf("Key '%s' was already created and cannot be used as "+
|
|
||||||
"an array.", keyContext)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p.setValue(key[len(key)-1], make(map[string]interface{}))
|
|
||||||
}
|
|
||||||
p.context = append(p.context, key[len(key)-1])
|
|
||||||
}
|
|
||||||
|
|
||||||
// setValue sets the given key to the given value in the current context.
|
|
||||||
// It will make sure that the key hasn't already been defined, account for
|
|
||||||
// implicit key groups.
|
|
||||||
func (p *parser) setValue(key string, value interface{}) {
|
|
||||||
var tmpHash interface{}
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
hash := p.mapping
|
|
||||||
keyContext := make(Key, 0)
|
|
||||||
for _, k := range p.context {
|
|
||||||
keyContext = append(keyContext, k)
|
|
||||||
if tmpHash, ok = hash[k]; !ok {
|
|
||||||
p.bug("Context for key '%s' has not been established.", keyContext)
|
|
||||||
}
|
|
||||||
switch t := tmpHash.(type) {
|
|
||||||
case []map[string]interface{}:
|
|
||||||
// The context is a table of hashes. Pick the most recent table
|
|
||||||
// defined as the current hash.
|
|
||||||
hash = t[len(t)-1]
|
|
||||||
case map[string]interface{}:
|
|
||||||
hash = t
|
|
||||||
default:
|
|
||||||
p.bug("Expected hash to have type 'map[string]interface{}', but "+
|
|
||||||
"it has '%T' instead.", tmpHash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keyContext = append(keyContext, key)
|
|
||||||
|
|
||||||
if _, ok := hash[key]; ok {
|
|
||||||
// Typically, if the given key has already been set, then we have
|
|
||||||
// to raise an error since duplicate keys are disallowed. However,
|
|
||||||
// it's possible that a key was previously defined implicitly. In this
|
|
||||||
// case, it is allowed to be redefined concretely. (See the
|
|
||||||
// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
|
|
||||||
//
|
|
||||||
// But we have to make sure to stop marking it as an implicit. (So that
|
|
||||||
// another redefinition provokes an error.)
|
|
||||||
//
|
|
||||||
// Note that since it has already been defined (as a hash), we don't
|
|
||||||
// want to overwrite it. So our business is done.
|
|
||||||
if p.isImplicit(keyContext) {
|
|
||||||
p.removeImplicit(keyContext)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we have a concrete key trying to override a previous
|
|
||||||
// key, which is *always* wrong.
|
|
||||||
p.panicf("Key '%s' has already been defined.", keyContext)
|
|
||||||
}
|
|
||||||
hash[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// setType sets the type of a particular value at a given key.
|
|
||||||
// It should be called immediately AFTER setValue.
|
|
||||||
//
|
|
||||||
// Note that if `key` is empty, then the type given will be applied to the
|
|
||||||
// current context (which is either a table or an array of tables).
|
|
||||||
func (p *parser) setType(key string, typ tomlType) {
|
|
||||||
keyContext := make(Key, 0, len(p.context)+1)
|
|
||||||
for _, k := range p.context {
|
|
||||||
keyContext = append(keyContext, k)
|
|
||||||
}
|
|
||||||
if len(key) > 0 { // allow type setting for hashes
|
|
||||||
keyContext = append(keyContext, key)
|
|
||||||
}
|
|
||||||
p.types[keyContext.String()] = typ
|
|
||||||
}
|
|
||||||
|
|
||||||
// addImplicit sets the given Key as having been created implicitly.
|
|
||||||
func (p *parser) addImplicit(key Key) {
|
|
||||||
p.implicits[key.String()] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeImplicit stops tagging the given key as having been implicitly
|
|
||||||
// created.
|
|
||||||
func (p *parser) removeImplicit(key Key) {
|
|
||||||
p.implicits[key.String()] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isImplicit returns true if the key group pointed to by the key was created
|
|
||||||
// implicitly.
|
|
||||||
func (p *parser) isImplicit(key Key) bool {
|
|
||||||
return p.implicits[key.String()]
|
|
||||||
}
|
|
||||||
|
|
||||||
// current returns the full key name of the current context.
|
|
||||||
func (p *parser) current() string {
|
|
||||||
if len(p.currentKey) == 0 {
|
|
||||||
return p.context.String()
|
|
||||||
}
|
|
||||||
if len(p.context) == 0 {
|
|
||||||
return p.currentKey
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s.%s", p.context, p.currentKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stripFirstNewline(s string) string {
|
|
||||||
if len(s) == 0 || s[0] != '\n' {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return s[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func stripEscapedWhitespace(s string) string {
|
|
||||||
esc := strings.Split(s, "\\\n")
|
|
||||||
if len(esc) > 1 {
|
|
||||||
for i := 1; i < len(esc); i++ {
|
|
||||||
esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(esc, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) replaceEscapes(str string) string {
|
|
||||||
var replaced []rune
|
|
||||||
s := []byte(str)
|
|
||||||
r := 0
|
|
||||||
for r < len(s) {
|
|
||||||
if s[r] != '\\' {
|
|
||||||
c, size := utf8.DecodeRune(s[r:])
|
|
||||||
r += size
|
|
||||||
replaced = append(replaced, c)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
r += 1
|
|
||||||
if r >= len(s) {
|
|
||||||
p.bug("Escape sequence at end of string.")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
switch s[r] {
|
|
||||||
default:
|
|
||||||
p.bug("Expected valid escape code after \\, but got %q.", s[r])
|
|
||||||
return ""
|
|
||||||
case 'b':
|
|
||||||
replaced = append(replaced, rune(0x0008))
|
|
||||||
r += 1
|
|
||||||
case 't':
|
|
||||||
replaced = append(replaced, rune(0x0009))
|
|
||||||
r += 1
|
|
||||||
case 'n':
|
|
||||||
replaced = append(replaced, rune(0x000A))
|
|
||||||
r += 1
|
|
||||||
case 'f':
|
|
||||||
replaced = append(replaced, rune(0x000C))
|
|
||||||
r += 1
|
|
||||||
case 'r':
|
|
||||||
replaced = append(replaced, rune(0x000D))
|
|
||||||
r += 1
|
|
||||||
case '"':
|
|
||||||
replaced = append(replaced, rune(0x0022))
|
|
||||||
r += 1
|
|
||||||
case '\\':
|
|
||||||
replaced = append(replaced, rune(0x005C))
|
|
||||||
r += 1
|
|
||||||
case 'u':
|
|
||||||
// At this point, we know we have a Unicode escape of the form
|
|
||||||
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
|
|
||||||
// for us.)
|
|
||||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+5])
|
|
||||||
replaced = append(replaced, escaped)
|
|
||||||
r += 5
|
|
||||||
case 'U':
|
|
||||||
// At this point, we know we have a Unicode escape of the form
|
|
||||||
// `uXXXX` at [r, r+9). (Because the lexer guarantees this
|
|
||||||
// for us.)
|
|
||||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+9])
|
|
||||||
replaced = append(replaced, escaped)
|
|
||||||
r += 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(replaced)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) asciiEscapeToUnicode(bs []byte) rune {
|
|
||||||
s := string(bs)
|
|
||||||
hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
p.bug("Could not parse '%s' as a hexadecimal number, but the "+
|
|
||||||
"lexer claims it's OK: %s", s, err)
|
|
||||||
}
|
|
||||||
if !utf8.ValidRune(rune(hex)) {
|
|
||||||
p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s)
|
|
||||||
}
|
|
||||||
return rune(hex)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isStringType(ty itemType) bool {
|
|
||||||
return ty == itemString || ty == itemMultilineString ||
|
|
||||||
ty == itemRawString || ty == itemRawMultilineString
|
|
||||||
}
|
|
91
vendor/github.com/BurntSushi/toml/type_check.go
generated
vendored
91
vendor/github.com/BurntSushi/toml/type_check.go
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
// tomlType represents any Go type that corresponds to a TOML type.
|
|
||||||
// While the first draft of the TOML spec has a simplistic type system that
|
|
||||||
// probably doesn't need this level of sophistication, we seem to be militating
|
|
||||||
// toward adding real composite types.
|
|
||||||
type tomlType interface {
|
|
||||||
typeString() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeEqual accepts any two types and returns true if they are equal.
|
|
||||||
func typeEqual(t1, t2 tomlType) bool {
|
|
||||||
if t1 == nil || t2 == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return t1.typeString() == t2.typeString()
|
|
||||||
}
|
|
||||||
|
|
||||||
func typeIsHash(t tomlType) bool {
|
|
||||||
return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tomlBaseType string
|
|
||||||
|
|
||||||
func (btype tomlBaseType) typeString() string {
|
|
||||||
return string(btype)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (btype tomlBaseType) String() string {
|
|
||||||
return btype.typeString()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
tomlInteger tomlBaseType = "Integer"
|
|
||||||
tomlFloat tomlBaseType = "Float"
|
|
||||||
tomlDatetime tomlBaseType = "Datetime"
|
|
||||||
tomlString tomlBaseType = "String"
|
|
||||||
tomlBool tomlBaseType = "Bool"
|
|
||||||
tomlArray tomlBaseType = "Array"
|
|
||||||
tomlHash tomlBaseType = "Hash"
|
|
||||||
tomlArrayHash tomlBaseType = "ArrayHash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// typeOfPrimitive returns a tomlType of any primitive value in TOML.
|
|
||||||
// Primitive values are: Integer, Float, Datetime, String and Bool.
|
|
||||||
//
|
|
||||||
// Passing a lexer item other than the following will cause a BUG message
|
|
||||||
// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
|
|
||||||
func (p *parser) typeOfPrimitive(lexItem item) tomlType {
|
|
||||||
switch lexItem.typ {
|
|
||||||
case itemInteger:
|
|
||||||
return tomlInteger
|
|
||||||
case itemFloat:
|
|
||||||
return tomlFloat
|
|
||||||
case itemDatetime:
|
|
||||||
return tomlDatetime
|
|
||||||
case itemString:
|
|
||||||
return tomlString
|
|
||||||
case itemMultilineString:
|
|
||||||
return tomlString
|
|
||||||
case itemRawString:
|
|
||||||
return tomlString
|
|
||||||
case itemRawMultilineString:
|
|
||||||
return tomlString
|
|
||||||
case itemBool:
|
|
||||||
return tomlBool
|
|
||||||
}
|
|
||||||
p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeOfArray returns a tomlType for an array given a list of types of its
|
|
||||||
// values.
|
|
||||||
//
|
|
||||||
// In the current spec, if an array is homogeneous, then its type is always
|
|
||||||
// "Array". If the array is not homogeneous, an error is generated.
|
|
||||||
func (p *parser) typeOfArray(types []tomlType) tomlType {
|
|
||||||
// Empty arrays are cool.
|
|
||||||
if len(types) == 0 {
|
|
||||||
return tomlArray
|
|
||||||
}
|
|
||||||
|
|
||||||
theType := types[0]
|
|
||||||
for _, t := range types[1:] {
|
|
||||||
if !typeEqual(theType, t) {
|
|
||||||
p.panicf("Array contains values of type '%s' and '%s', but "+
|
|
||||||
"arrays must be homogeneous.", theType, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tomlArray
|
|
||||||
}
|
|
242
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
242
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
|
@ -1,242 +0,0 @@
|
||||||
package toml
|
|
||||||
|
|
||||||
// Struct field handling is adapted from code in encoding/json:
|
|
||||||
//
|
|
||||||
// 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 Go distribution.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A field represents a single field found in a struct.
|
|
||||||
type field struct {
|
|
||||||
name string // the name of the field (`toml` tag included)
|
|
||||||
tag bool // whether field has a `toml` tag
|
|
||||||
index []int // represents the depth of an anonymous field
|
|
||||||
typ reflect.Type // the type of the field
|
|
||||||
}
|
|
||||||
|
|
||||||
// byName sorts field by name, breaking ties with depth,
|
|
||||||
// then breaking ties with "name came from toml tag", then
|
|
||||||
// breaking ties with index sequence.
|
|
||||||
type byName []field
|
|
||||||
|
|
||||||
func (x byName) Len() int { return len(x) }
|
|
||||||
|
|
||||||
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
|
||||||
|
|
||||||
func (x byName) Less(i, j int) bool {
|
|
||||||
if x[i].name != x[j].name {
|
|
||||||
return x[i].name < x[j].name
|
|
||||||
}
|
|
||||||
if len(x[i].index) != len(x[j].index) {
|
|
||||||
return len(x[i].index) < len(x[j].index)
|
|
||||||
}
|
|
||||||
if x[i].tag != x[j].tag {
|
|
||||||
return x[i].tag
|
|
||||||
}
|
|
||||||
return byIndex(x).Less(i, j)
|
|
||||||
}
|
|
||||||
|
|
||||||
// byIndex sorts field by index sequence.
|
|
||||||
type byIndex []field
|
|
||||||
|
|
||||||
func (x byIndex) Len() int { return len(x) }
|
|
||||||
|
|
||||||
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
|
||||||
|
|
||||||
func (x byIndex) Less(i, j int) bool {
|
|
||||||
for k, xik := range x[i].index {
|
|
||||||
if k >= len(x[j].index) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if xik != x[j].index[k] {
|
|
||||||
return xik < x[j].index[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(x[i].index) < len(x[j].index)
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeFields returns a list of fields that TOML should recognize for the given
|
|
||||||
// type. The algorithm is breadth-first search over the set of structs to
|
|
||||||
// include - the top struct and then any reachable anonymous structs.
|
|
||||||
func typeFields(t reflect.Type) []field {
|
|
||||||
// Anonymous fields to explore at the current level and the next.
|
|
||||||
current := []field{}
|
|
||||||
next := []field{{typ: t}}
|
|
||||||
|
|
||||||
// Count of queued names for current level and the next.
|
|
||||||
count := map[reflect.Type]int{}
|
|
||||||
nextCount := map[reflect.Type]int{}
|
|
||||||
|
|
||||||
// Types already visited at an earlier level.
|
|
||||||
visited := map[reflect.Type]bool{}
|
|
||||||
|
|
||||||
// Fields found.
|
|
||||||
var fields []field
|
|
||||||
|
|
||||||
for len(next) > 0 {
|
|
||||||
current, next = next, current[:0]
|
|
||||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
|
||||||
|
|
||||||
for _, f := range current {
|
|
||||||
if visited[f.typ] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
visited[f.typ] = true
|
|
||||||
|
|
||||||
// Scan f.typ for fields to include.
|
|
||||||
for i := 0; i < f.typ.NumField(); i++ {
|
|
||||||
sf := f.typ.Field(i)
|
|
||||||
if sf.PkgPath != "" && !sf.Anonymous { // unexported
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
opts := getOptions(sf.Tag)
|
|
||||||
if opts.skip {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
index := make([]int, len(f.index)+1)
|
|
||||||
copy(index, f.index)
|
|
||||||
index[len(f.index)] = i
|
|
||||||
|
|
||||||
ft := sf.Type
|
|
||||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
|
||||||
// Follow pointer.
|
|
||||||
ft = ft.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record found field and index sequence.
|
|
||||||
if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
|
||||||
tagged := opts.name != ""
|
|
||||||
name := opts.name
|
|
||||||
if name == "" {
|
|
||||||
name = sf.Name
|
|
||||||
}
|
|
||||||
fields = append(fields, field{name, tagged, index, ft})
|
|
||||||
if count[f.typ] > 1 {
|
|
||||||
// If there were multiple instances, add a second,
|
|
||||||
// so that the annihilation code will see a duplicate.
|
|
||||||
// It only cares about the distinction between 1 or 2,
|
|
||||||
// so don't bother generating any more copies.
|
|
||||||
fields = append(fields, fields[len(fields)-1])
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record new anonymous struct to explore in next round.
|
|
||||||
nextCount[ft]++
|
|
||||||
if nextCount[ft] == 1 {
|
|
||||||
f := field{name: ft.Name(), index: index, typ: ft}
|
|
||||||
next = append(next, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(byName(fields))
|
|
||||||
|
|
||||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
|
||||||
// except that fields with TOML tags are promoted.
|
|
||||||
|
|
||||||
// The fields are sorted in primary order of name, secondary order
|
|
||||||
// of field index length. Loop over names; for each name, delete
|
|
||||||
// hidden fields by choosing the one dominant field that survives.
|
|
||||||
out := fields[:0]
|
|
||||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
|
||||||
// One iteration per name.
|
|
||||||
// Find the sequence of fields with the name of this first field.
|
|
||||||
fi := fields[i]
|
|
||||||
name := fi.name
|
|
||||||
for advance = 1; i+advance < len(fields); advance++ {
|
|
||||||
fj := fields[i+advance]
|
|
||||||
if fj.name != name {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if advance == 1 { // Only one field with this name
|
|
||||||
out = append(out, fi)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dominant, ok := dominantField(fields[i : i+advance])
|
|
||||||
if ok {
|
|
||||||
out = append(out, dominant)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fields = out
|
|
||||||
sort.Sort(byIndex(fields))
|
|
||||||
|
|
||||||
return fields
|
|
||||||
}
|
|
||||||
|
|
||||||
// dominantField looks through the fields, all of which are known to
|
|
||||||
// have the same name, to find the single field that dominates the
|
|
||||||
// others using Go's embedding rules, modified by the presence of
|
|
||||||
// TOML tags. If there are multiple top-level fields, the boolean
|
|
||||||
// will be false: This condition is an error in Go and we skip all
|
|
||||||
// the fields.
|
|
||||||
func dominantField(fields []field) (field, bool) {
|
|
||||||
// The fields are sorted in increasing index-length order. The winner
|
|
||||||
// must therefore be one with the shortest index length. Drop all
|
|
||||||
// longer entries, which is easy: just truncate the slice.
|
|
||||||
length := len(fields[0].index)
|
|
||||||
tagged := -1 // Index of first tagged field.
|
|
||||||
for i, f := range fields {
|
|
||||||
if len(f.index) > length {
|
|
||||||
fields = fields[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if f.tag {
|
|
||||||
if tagged >= 0 {
|
|
||||||
// Multiple tagged fields at the same level: conflict.
|
|
||||||
// Return no field.
|
|
||||||
return field{}, false
|
|
||||||
}
|
|
||||||
tagged = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tagged >= 0 {
|
|
||||||
return fields[tagged], true
|
|
||||||
}
|
|
||||||
// All remaining fields have the same length. If there's more than one,
|
|
||||||
// we have a conflict (two fields named "X" at the same level) and we
|
|
||||||
// return no field.
|
|
||||||
if len(fields) > 1 {
|
|
||||||
return field{}, false
|
|
||||||
}
|
|
||||||
return fields[0], true
|
|
||||||
}
|
|
||||||
|
|
||||||
var fieldCache struct {
|
|
||||||
sync.RWMutex
|
|
||||||
m map[reflect.Type][]field
|
|
||||||
}
|
|
||||||
|
|
||||||
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
|
||||||
func cachedTypeFields(t reflect.Type) []field {
|
|
||||||
fieldCache.RLock()
|
|
||||||
f := fieldCache.m[t]
|
|
||||||
fieldCache.RUnlock()
|
|
||||||
if f != nil {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute fields without lock.
|
|
||||||
// Might duplicate effort but won't hold other computations back.
|
|
||||||
f = typeFields(t)
|
|
||||||
if f == nil {
|
|
||||||
f = []field{}
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldCache.Lock()
|
|
||||||
if fieldCache.m == nil {
|
|
||||||
fieldCache.m = map[reflect.Type][]field{}
|
|
||||||
}
|
|
||||||
fieldCache.m[t] = f
|
|
||||||
fieldCache.Unlock()
|
|
||||||
return f
|
|
||||||
}
|
|
201
vendor/github.com/ExpediaDotCom/haystack-client-go/LICENSE
generated
vendored
201
vendor/github.com/ExpediaDotCom/haystack-client-go/LICENSE
generated
vendored
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [2018] Expedia Group.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
356
vendor/github.com/ExpediaDotCom/haystack-client-go/dispatcher.go
generated
vendored
356
vendor/github.com/ExpediaDotCom/haystack-client-go/dispatcher.go
generated
vendored
|
@ -1,356 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
|
||||||
"github.com/opentracing/opentracing-go/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*Dispatcher dispatches the span object*/
|
|
||||||
type Dispatcher interface {
|
|
||||||
Name() string
|
|
||||||
Dispatch(span *_Span)
|
|
||||||
DispatchProtoSpan(span *Span)
|
|
||||||
Close()
|
|
||||||
SetLogger(logger Logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*InMemoryDispatcher implements the Dispatcher interface*/
|
|
||||||
type InMemoryDispatcher struct {
|
|
||||||
spans []*_Span
|
|
||||||
logger Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewInMemoryDispatcher creates a new in memory dispatcher*/
|
|
||||||
func NewInMemoryDispatcher() Dispatcher {
|
|
||||||
return &InMemoryDispatcher{}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Name gives the Dispatcher name*/
|
|
||||||
func (d *InMemoryDispatcher) Name() string {
|
|
||||||
return "InMemoryDispatcher"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SetLogger sets the logger to use*/
|
|
||||||
func (d *InMemoryDispatcher) SetLogger(logger Logger) {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Dispatch dispatches the span object*/
|
|
||||||
func (d *InMemoryDispatcher) Dispatch(span *_Span) {
|
|
||||||
d.spans = append(d.spans, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*DispatchProtoSpan dispatches proto span object*/
|
|
||||||
func (d *InMemoryDispatcher) DispatchProtoSpan(span *Span) {
|
|
||||||
/* not implemented */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close down the inMemory dispatcher*/
|
|
||||||
func (d *InMemoryDispatcher) Close() {
|
|
||||||
d.spans = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*FileDispatcher file dispatcher*/
|
|
||||||
type FileDispatcher struct {
|
|
||||||
fileHandle *os.File
|
|
||||||
logger Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewFileDispatcher creates a new file dispatcher*/
|
|
||||||
func NewFileDispatcher(filename string) Dispatcher {
|
|
||||||
fd, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return &FileDispatcher{
|
|
||||||
fileHandle: fd,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Name gives the Dispatcher name*/
|
|
||||||
func (d *FileDispatcher) Name() string {
|
|
||||||
return "FileDispatcher"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SetLogger sets the logger to use*/
|
|
||||||
func (d *FileDispatcher) SetLogger(logger Logger) {
|
|
||||||
d.logger = logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Dispatch dispatches the span object*/
|
|
||||||
func (d *FileDispatcher) Dispatch(span *_Span) {
|
|
||||||
_, err := d.fileHandle.WriteString(span.String() + "\n")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*DispatchProtoSpan dispatches proto span object*/
|
|
||||||
func (d *FileDispatcher) DispatchProtoSpan(span *Span) {
|
|
||||||
/* not implemented */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close down the file dispatcher*/
|
|
||||||
func (d *FileDispatcher) Close() {
|
|
||||||
err := d.fileHandle.Close()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*RemoteDispatcher dispatcher, client can be grpc or http*/
|
|
||||||
type RemoteDispatcher struct {
|
|
||||||
client RemoteClient
|
|
||||||
timeout time.Duration
|
|
||||||
logger Logger
|
|
||||||
spanChannel chan *Span
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewHTTPDispatcher creates a new haystack-agent dispatcher*/
|
|
||||||
func NewHTTPDispatcher(url string, timeout time.Duration, headers map[string]string, maxQueueLength int) Dispatcher {
|
|
||||||
dispatcher := &RemoteDispatcher{
|
|
||||||
client: NewHTTPClient(url, headers, timeout),
|
|
||||||
timeout: timeout,
|
|
||||||
spanChannel: make(chan *Span, maxQueueLength),
|
|
||||||
}
|
|
||||||
|
|
||||||
go startListener(dispatcher)
|
|
||||||
return dispatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewDefaultHTTPDispatcher creates a new http dispatcher*/
|
|
||||||
func NewDefaultHTTPDispatcher() Dispatcher {
|
|
||||||
return NewHTTPDispatcher("http://haystack-collector/span", 3*time.Second, make(map[string](string)), 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewAgentDispatcher creates a new haystack-agent dispatcher*/
|
|
||||||
func NewAgentDispatcher(host string, port int, timeout time.Duration, maxQueueLength int) Dispatcher {
|
|
||||||
dispatcher := &RemoteDispatcher{
|
|
||||||
client: NewGrpcClient(host, port, timeout),
|
|
||||||
timeout: timeout,
|
|
||||||
spanChannel: make(chan *Span, maxQueueLength),
|
|
||||||
}
|
|
||||||
|
|
||||||
go startListener(dispatcher)
|
|
||||||
return dispatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewDefaultAgentDispatcher creates a new haystack-agent dispatcher*/
|
|
||||||
func NewDefaultAgentDispatcher() Dispatcher {
|
|
||||||
return NewAgentDispatcher("haystack-agent", 35000, 3*time.Second, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
func startListener(dispatcher *RemoteDispatcher) {
|
|
||||||
signals := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(signals, os.Interrupt, os.Kill)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case sp := <-dispatcher.spanChannel:
|
|
||||||
dispatcher.client.Send(sp)
|
|
||||||
case <-signals:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Name gives the Dispatcher name*/
|
|
||||||
func (d *RemoteDispatcher) Name() string {
|
|
||||||
return "RemoteDispatcher"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SetLogger sets the logger to use*/
|
|
||||||
func (d *RemoteDispatcher) SetLogger(logger Logger) {
|
|
||||||
d.logger = logger
|
|
||||||
d.client.SetLogger(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Dispatch dispatches the span object*/
|
|
||||||
func (d *RemoteDispatcher) Dispatch(span *_Span) {
|
|
||||||
s := &Span{
|
|
||||||
TraceId: span.context.TraceID,
|
|
||||||
SpanId: span.context.SpanID,
|
|
||||||
ParentSpanId: span.context.ParentID,
|
|
||||||
ServiceName: span.ServiceName(),
|
|
||||||
OperationName: span.OperationName(),
|
|
||||||
StartTime: span.startTime.UnixNano() / int64(time.Microsecond),
|
|
||||||
Duration: span.duration.Nanoseconds() / int64(time.Microsecond),
|
|
||||||
Tags: d.tags(span),
|
|
||||||
Logs: d.logs(span),
|
|
||||||
}
|
|
||||||
d.spanChannel <- s
|
|
||||||
}
|
|
||||||
|
|
||||||
/*DispatchProtoSpan dispatches the proto span object*/
|
|
||||||
func (d *RemoteDispatcher) DispatchProtoSpan(s *Span) {
|
|
||||||
d.spanChannel <- s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *RemoteDispatcher) logs(span *_Span) []*Log {
|
|
||||||
var spanLogs []*Log
|
|
||||||
for _, lg := range span.logs {
|
|
||||||
spanLogs = append(spanLogs, &Log{
|
|
||||||
Timestamp: lg.Timestamp.UnixNano() / int64(time.Microsecond),
|
|
||||||
Fields: d.logFieldsToTags(lg.Fields),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return spanLogs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *RemoteDispatcher) logFieldsToTags(fields []log.Field) []*Tag {
|
|
||||||
var spanTags []*Tag
|
|
||||||
for _, field := range fields {
|
|
||||||
spanTags = append(spanTags, ConvertToProtoTag(field.Key(), field.Value()))
|
|
||||||
}
|
|
||||||
return spanTags
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *RemoteDispatcher) tags(span *_Span) []*Tag {
|
|
||||||
var spanTags []*Tag
|
|
||||||
for _, tag := range span.tags {
|
|
||||||
spanTags = append(spanTags, ConvertToProtoTag(tag.Key, tag.Value))
|
|
||||||
}
|
|
||||||
return spanTags
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close down the file dispatcher*/
|
|
||||||
func (d *RemoteDispatcher) Close() {
|
|
||||||
err := d.client.Close()
|
|
||||||
if err != nil {
|
|
||||||
d.logger.Error("Fail to close the haystack-agent dispatcher %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ConvertToProtoTag converts to proto tag*/
|
|
||||||
func ConvertToProtoTag(key string, value interface{}) *Tag {
|
|
||||||
switch v := value.(type) {
|
|
||||||
case string:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VStr{
|
|
||||||
VStr: value.(string),
|
|
||||||
},
|
|
||||||
Type: Tag_STRING,
|
|
||||||
}
|
|
||||||
case int:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(int)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case int32:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(int32)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case int16:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(int16)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case int64:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: value.(int64),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case uint16:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(uint16)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case uint32:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(uint32)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case uint64:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VLong{
|
|
||||||
VLong: int64(value.(uint64)),
|
|
||||||
},
|
|
||||||
Type: Tag_LONG,
|
|
||||||
}
|
|
||||||
case float32:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VDouble{
|
|
||||||
VDouble: float64(value.(float32)),
|
|
||||||
},
|
|
||||||
Type: Tag_DOUBLE,
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VDouble{
|
|
||||||
VDouble: value.(float64),
|
|
||||||
},
|
|
||||||
Type: Tag_DOUBLE,
|
|
||||||
}
|
|
||||||
case bool:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VBool{
|
|
||||||
VBool: value.(bool),
|
|
||||||
},
|
|
||||||
Type: Tag_BOOL,
|
|
||||||
}
|
|
||||||
case []byte:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VBytes{
|
|
||||||
VBytes: value.([]byte),
|
|
||||||
},
|
|
||||||
Type: Tag_BINARY,
|
|
||||||
}
|
|
||||||
case ext.SpanKindEnum:
|
|
||||||
return &Tag{
|
|
||||||
Key: key,
|
|
||||||
Myvalue: &Tag_VStr{
|
|
||||||
VStr: string(value.(ext.SpanKindEnum)),
|
|
||||||
},
|
|
||||||
Type: Tag_STRING,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unknown format %v", v))
|
|
||||||
}
|
|
||||||
}
|
|
37
vendor/github.com/ExpediaDotCom/haystack-client-go/logger.go
generated
vendored
37
vendor/github.com/ExpediaDotCom/haystack-client-go/logger.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
/*Logger defines a new logger interface*/
|
|
||||||
type Logger interface {
|
|
||||||
Info(format string, v ...interface{})
|
|
||||||
Error(format string, v ...interface{})
|
|
||||||
Debug(format string, v ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NullLogger does nothing*/
|
|
||||||
type NullLogger struct{}
|
|
||||||
|
|
||||||
/*Error prints the error message*/
|
|
||||||
func (logger NullLogger) Error(format string, v ...interface{}) {}
|
|
||||||
|
|
||||||
/*Info prints the info message*/
|
|
||||||
func (logger NullLogger) Info(format string, v ...interface{}) {}
|
|
||||||
|
|
||||||
/*Debug prints the info message*/
|
|
||||||
func (logger NullLogger) Debug(format string, v ...interface{}) {}
|
|
193
vendor/github.com/ExpediaDotCom/haystack-client-go/propagator.go
generated
vendored
193
vendor/github.com/ExpediaDotCom/haystack-client-go/propagator.go
generated
vendored
|
@ -1,193 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*Propagator defines the interface for injecting and extracing the SpanContext from the carrier*/
|
|
||||||
type Propagator interface {
|
|
||||||
// Inject takes `SpanContext` and injects it into `carrier`
|
|
||||||
Inject(ctx *SpanContext, carrier interface{}) error
|
|
||||||
|
|
||||||
// Extract `SpanContext` from the `carrier`
|
|
||||||
Extract(carrier interface{}) (*SpanContext, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Codex defines the interface for encoding and decoding the propagated data*/
|
|
||||||
type Codex interface {
|
|
||||||
Encode(value string) string
|
|
||||||
Decode(value string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
/*DefaultCodex is a no op*/
|
|
||||||
type DefaultCodex struct{}
|
|
||||||
|
|
||||||
/*Encode a no-op for encoding the value*/
|
|
||||||
func (c DefaultCodex) Encode(value string) string { return value }
|
|
||||||
|
|
||||||
/*Decode a no-op for decoding the value*/
|
|
||||||
func (c DefaultCodex) Decode(value string) string { return value }
|
|
||||||
|
|
||||||
/*URLCodex encodes decodes a url*/
|
|
||||||
type URLCodex struct{}
|
|
||||||
|
|
||||||
/*Encode a no-op for encoding the value*/
|
|
||||||
func (c URLCodex) Encode(value string) string { return url.QueryEscape(value) }
|
|
||||||
|
|
||||||
/*Decode a no-op for decoding the value*/
|
|
||||||
func (c URLCodex) Decode(value string) string {
|
|
||||||
decoded, err := url.QueryUnescape(value)
|
|
||||||
if err == nil {
|
|
||||||
return decoded
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
/*PropagatorOpts defines the options need by a propagator*/
|
|
||||||
type PropagatorOpts struct {
|
|
||||||
TraceIDKEYName string
|
|
||||||
SpanIDKEYName string
|
|
||||||
ParentSpanIDKEYName string
|
|
||||||
BaggagePrefixKEYName string
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultPropagatorOpts = PropagatorOpts{}
|
|
||||||
var defaultCodex = DefaultCodex{}
|
|
||||||
|
|
||||||
/*TraceIDKEY returns the trace id key in the propagator*/
|
|
||||||
func (p *PropagatorOpts) TraceIDKEY() string {
|
|
||||||
if p.TraceIDKEYName != "" {
|
|
||||||
return p.TraceIDKEYName
|
|
||||||
}
|
|
||||||
return "Trace-ID"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SpanIDKEY returns the span id key in the propagator*/
|
|
||||||
func (p *PropagatorOpts) SpanIDKEY() string {
|
|
||||||
if p.SpanIDKEYName != "" {
|
|
||||||
return p.SpanIDKEYName
|
|
||||||
}
|
|
||||||
return "Span-ID"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ParentSpanIDKEY returns the parent span id key in the propagator*/
|
|
||||||
func (p *PropagatorOpts) ParentSpanIDKEY() string {
|
|
||||||
if p.ParentSpanIDKEYName != "" {
|
|
||||||
return p.ParentSpanIDKEYName
|
|
||||||
}
|
|
||||||
return "Parent-ID"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*BaggageKeyPrefix returns the baggage key prefix*/
|
|
||||||
func (p *PropagatorOpts) BaggageKeyPrefix() string {
|
|
||||||
if p.BaggagePrefixKEYName != "" {
|
|
||||||
return p.BaggagePrefixKEYName
|
|
||||||
}
|
|
||||||
return "Baggage-"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*TextMapPropagator implements Propagator interface*/
|
|
||||||
type TextMapPropagator struct {
|
|
||||||
opts PropagatorOpts
|
|
||||||
codex Codex
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Inject injects the span context in the carrier*/
|
|
||||||
func (p *TextMapPropagator) Inject(ctx *SpanContext, carrier interface{}) error {
|
|
||||||
textMapWriter, ok := carrier.(opentracing.TextMapWriter)
|
|
||||||
if !ok {
|
|
||||||
return opentracing.ErrInvalidCarrier
|
|
||||||
}
|
|
||||||
|
|
||||||
textMapWriter.Set(p.opts.TraceIDKEY(), ctx.TraceID)
|
|
||||||
textMapWriter.Set(p.opts.SpanIDKEY(), ctx.SpanID)
|
|
||||||
textMapWriter.Set(p.opts.ParentSpanIDKEY(), ctx.ParentID)
|
|
||||||
|
|
||||||
ctx.ForeachBaggageItem(func(key, value string) bool {
|
|
||||||
textMapWriter.Set(fmt.Sprintf("%s%s", p.opts.BaggageKeyPrefix(), key), p.codex.Encode(ctx.Baggage[key]))
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Extract the span context from the carrier*/
|
|
||||||
func (p *TextMapPropagator) Extract(carrier interface{}) (*SpanContext, error) {
|
|
||||||
textMapReader, ok := carrier.(opentracing.TextMapReader)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
return nil, opentracing.ErrInvalidCarrier
|
|
||||||
}
|
|
||||||
|
|
||||||
baggageKeyLowerCasePrefix := strings.ToLower(p.opts.BaggageKeyPrefix())
|
|
||||||
traceIDKeyLowerCase := strings.ToLower(p.opts.TraceIDKEY())
|
|
||||||
spanIDKeyLowerCase := strings.ToLower(p.opts.SpanIDKEY())
|
|
||||||
parentSpanIDKeyLowerCase := strings.ToLower(p.opts.ParentSpanIDKEY())
|
|
||||||
|
|
||||||
traceID := ""
|
|
||||||
spanID := ""
|
|
||||||
parentSpanID := ""
|
|
||||||
|
|
||||||
baggage := make(map[string]string)
|
|
||||||
err := textMapReader.ForeachKey(func(k, v string) error {
|
|
||||||
lcKey := strings.ToLower(k)
|
|
||||||
|
|
||||||
if strings.HasPrefix(lcKey, baggageKeyLowerCasePrefix) {
|
|
||||||
keySansPrefix := lcKey[len(p.opts.BaggageKeyPrefix()):]
|
|
||||||
baggage[keySansPrefix] = p.codex.Decode(v)
|
|
||||||
} else if lcKey == traceIDKeyLowerCase {
|
|
||||||
traceID = v
|
|
||||||
} else if lcKey == spanIDKeyLowerCase {
|
|
||||||
spanID = v
|
|
||||||
} else if lcKey == parentSpanIDKeyLowerCase {
|
|
||||||
parentSpanID = v
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SpanContext{
|
|
||||||
TraceID: traceID,
|
|
||||||
SpanID: spanID,
|
|
||||||
ParentID: parentSpanID,
|
|
||||||
Baggage: baggage,
|
|
||||||
IsExtractedContext: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewDefaultTextMapPropagator returns a default text map propagator*/
|
|
||||||
func NewDefaultTextMapPropagator() *TextMapPropagator {
|
|
||||||
return NewTextMapPropagator(defaultPropagatorOpts, defaultCodex)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewTextMapPropagator returns a text map propagator*/
|
|
||||||
func NewTextMapPropagator(opts PropagatorOpts, codex Codex) *TextMapPropagator {
|
|
||||||
return &TextMapPropagator{
|
|
||||||
opts: opts,
|
|
||||||
codex: codex,
|
|
||||||
}
|
|
||||||
}
|
|
165
vendor/github.com/ExpediaDotCom/haystack-client-go/remote_client.go
generated
vendored
165
vendor/github.com/ExpediaDotCom/haystack-client-go/remote_client.go
generated
vendored
|
@ -1,165 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
context "golang.org/x/net/context"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*RemoteClient remote client*/
|
|
||||||
type RemoteClient interface {
|
|
||||||
Send(span *Span)
|
|
||||||
Close() error
|
|
||||||
SetLogger(logger Logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*GrpcClient grpc client*/
|
|
||||||
type GrpcClient struct {
|
|
||||||
conn *grpc.ClientConn
|
|
||||||
client SpanAgentClient
|
|
||||||
timeout time.Duration
|
|
||||||
logger Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewGrpcClient returns a new grpc client*/
|
|
||||||
func NewGrpcClient(host string, port int, timeout time.Duration) *GrpcClient {
|
|
||||||
targetHost := fmt.Sprintf("%s:%d", host, port)
|
|
||||||
conn, err := grpc.Dial(targetHost, grpc.WithInsecure())
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("fail to connect to agent with error: %v", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &GrpcClient{
|
|
||||||
conn: conn,
|
|
||||||
client: NewSpanAgentClient(conn),
|
|
||||||
timeout: timeout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Send a proto span to grpc server*/
|
|
||||||
func (c *GrpcClient) Send(span *Span) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
result, err := c.client.Dispatch(ctx, span)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.logger.Error("Fail to dispatch to haystack-agent with error %v", err)
|
|
||||||
} else if result.GetCode() != DispatchResult_SUCCESS {
|
|
||||||
c.logger.Error(fmt.Sprintf("Fail to dispatch to haystack-agent with error code: %d, message :%s", result.GetCode(), result.GetErrorMessage()))
|
|
||||||
} else {
|
|
||||||
c.logger.Debug(fmt.Sprintf("span [%v] has been successfully dispatched to haystack", span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close the grpc client*/
|
|
||||||
func (c *GrpcClient) Close() error {
|
|
||||||
return c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SetLogger sets the logger*/
|
|
||||||
func (c *GrpcClient) SetLogger(logger Logger) {
|
|
||||||
c.logger = logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*HTTPClient a http client*/
|
|
||||||
type HTTPClient struct {
|
|
||||||
url string
|
|
||||||
headers map[string]string
|
|
||||||
client *http.Client
|
|
||||||
logger Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewHTTPClient returns a new http client*/
|
|
||||||
func NewHTTPClient(url string, headers map[string]string, timeout time.Duration) *HTTPClient {
|
|
||||||
httpClient := &http.Client{
|
|
||||||
Timeout: timeout,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &HTTPClient{
|
|
||||||
url: url,
|
|
||||||
headers: headers,
|
|
||||||
client: httpClient,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Send a proto span to http server*/
|
|
||||||
func (c *HTTPClient) Send(span *Span) {
|
|
||||||
serializedBytes, marshalErr := proto.Marshal(span)
|
|
||||||
|
|
||||||
if marshalErr != nil {
|
|
||||||
c.logger.Error("Fail to serialize the span to proto bytes, error=%v", marshalErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
postRequest, requestErr := http.NewRequest(http.MethodPost, c.url, bytes.NewReader(serializedBytes))
|
|
||||||
if requestErr != nil {
|
|
||||||
c.logger.Error("Fail to create request for posting span to haystack server, error=%v", requestErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.headers != nil {
|
|
||||||
for k, v := range c.headers {
|
|
||||||
postRequest.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.client.Do(postRequest)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.logger.Error("Fail to dispatch to haystack http server, error=%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
closeErr := resp.Body.Close()
|
|
||||||
if closeErr != nil {
|
|
||||||
/* do nothing */
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
respBytes, respErr := ioutil.ReadAll(resp.Body)
|
|
||||||
if respErr != nil {
|
|
||||||
c.logger.Error("Fail to read the http response from haystack server, error=%v", respErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
||||||
c.logger.Error("Fail to dispatch the span to haystack http server with statusCode=%d , payload=%s", resp.StatusCode, string(respBytes))
|
|
||||||
} else {
|
|
||||||
c.logger.Debug(fmt.Sprintf("span [%v] has been successfully dispatched to haystack, response=%s", span, string(respBytes)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close the http client*/
|
|
||||||
func (c *HTTPClient) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*SetLogger sets the logger*/
|
|
||||||
func (c *HTTPClient) SetLogger(logger Logger) {
|
|
||||||
c.logger = logger
|
|
||||||
}
|
|
164
vendor/github.com/ExpediaDotCom/haystack-client-go/span.go
generated
vendored
164
vendor/github.com/ExpediaDotCom/haystack-client-go/span.go
generated
vendored
|
@ -1,164 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
"github.com/opentracing/opentracing-go/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*_Span implements opentracing.Span*/
|
|
||||||
type _Span struct {
|
|
||||||
tracer *Tracer
|
|
||||||
context *SpanContext
|
|
||||||
|
|
||||||
operationName string
|
|
||||||
|
|
||||||
// startTime is the timestamp indicating when the span began, with microseconds precision.
|
|
||||||
startTime time.Time
|
|
||||||
// duration returns duration of the span with microseconds precision.
|
|
||||||
duration time.Duration
|
|
||||||
|
|
||||||
tags []opentracing.Tag
|
|
||||||
logs []opentracing.LogRecord
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOperationName sets or changes the operation name.
|
|
||||||
func (span *_Span) SetOperationName(operationName string) opentracing.Span {
|
|
||||||
span.operationName = operationName
|
|
||||||
return span
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTag implements SetTag() of opentracing.Span
|
|
||||||
func (span *_Span) SetTag(key string, value interface{}) opentracing.Span {
|
|
||||||
span.tags = append(span.tags,
|
|
||||||
opentracing.Tag{
|
|
||||||
Key: key,
|
|
||||||
Value: value,
|
|
||||||
})
|
|
||||||
return span
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogFields implements opentracing.Span API
|
|
||||||
func (span *_Span) LogFields(fields ...log.Field) {
|
|
||||||
log := opentracing.LogRecord{
|
|
||||||
Fields: fields,
|
|
||||||
Timestamp: time.Now(),
|
|
||||||
}
|
|
||||||
span.logs = append(span.logs, log)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogKV implements opentracing.Span API
|
|
||||||
func (span *_Span) LogKV(alternatingKeyValues ...interface{}) {
|
|
||||||
fields, err := log.InterleavedKVToFields(alternatingKeyValues...)
|
|
||||||
if err != nil {
|
|
||||||
span.LogFields(log.Error(err), log.String("function", "LogKV"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
span.LogFields(fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogEvent implements opentracing.Span API
|
|
||||||
func (span *_Span) LogEvent(event string) {
|
|
||||||
span.Log(opentracing.LogData{Event: event})
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogEventWithPayload implements opentracing.Span API
|
|
||||||
func (span *_Span) LogEventWithPayload(event string, payload interface{}) {
|
|
||||||
span.Log(opentracing.LogData{Event: event, Payload: payload})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log implements opentracing.Span API
|
|
||||||
func (span *_Span) Log(ld opentracing.LogData) {
|
|
||||||
span.logs = append(span.logs, ld.ToLogRecord())
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext
|
|
||||||
func (span *_Span) SetBaggageItem(key, value string) opentracing.Span {
|
|
||||||
span.context = span.context.WithBaggageItem(key, value)
|
|
||||||
span.LogFields(log.String("event", "baggage"), log.String("payload", key), log.String("payload", value))
|
|
||||||
return span
|
|
||||||
}
|
|
||||||
|
|
||||||
// BaggageItem implements BaggageItem() of opentracing.SpanContext
|
|
||||||
func (span *_Span) BaggageItem(key string) string {
|
|
||||||
return span.context.Baggage[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish implements opentracing.Span API
|
|
||||||
func (span *_Span) Finish() {
|
|
||||||
span.FinishWithOptions(opentracing.FinishOptions{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FinishWithOptions implements opentracing.Span API
|
|
||||||
func (span *_Span) FinishWithOptions(options opentracing.FinishOptions) {
|
|
||||||
if options.FinishTime.IsZero() {
|
|
||||||
options.FinishTime = span.tracer.timeNow()
|
|
||||||
}
|
|
||||||
span.duration = options.FinishTime.Sub(span.startTime)
|
|
||||||
if options.LogRecords != nil {
|
|
||||||
span.logs = append(span.logs, options.LogRecords...)
|
|
||||||
}
|
|
||||||
for _, ld := range options.BulkLogData {
|
|
||||||
span.logs = append(span.logs, ld.ToLogRecord())
|
|
||||||
}
|
|
||||||
span.tracer.DispatchSpan(span)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context implements opentracing.Span API
|
|
||||||
func (span *_Span) Context() opentracing.SpanContext {
|
|
||||||
return span.context
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Tracer returns the tracer*/
|
|
||||||
func (span *_Span) Tracer() opentracing.Tracer {
|
|
||||||
return span.tracer
|
|
||||||
}
|
|
||||||
|
|
||||||
/*OperationName allows retrieving current operation name*/
|
|
||||||
func (span *_Span) OperationName() string {
|
|
||||||
return span.operationName
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ServiceName returns the name of the service*/
|
|
||||||
func (span *_Span) ServiceName() string {
|
|
||||||
return span.tracer.serviceName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (span *_Span) String() string {
|
|
||||||
data, err := json.Marshal(map[string]interface{}{
|
|
||||||
"traceId": span.context.TraceID,
|
|
||||||
"spanId": span.context.SpanID,
|
|
||||||
"parentSpanId": span.context.ParentID,
|
|
||||||
"operationName": span.OperationName(),
|
|
||||||
"serviceName": span.ServiceName(),
|
|
||||||
"tags": span.Tags(),
|
|
||||||
"logs": span.logs,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return string(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (span *_Span) Tags() []opentracing.Tag {
|
|
||||||
return span.tags
|
|
||||||
}
|
|
433
vendor/github.com/ExpediaDotCom/haystack-client-go/span.pb.go
generated
vendored
433
vendor/github.com/ExpediaDotCom/haystack-client-go/span.pb.go
generated
vendored
|
@ -1,433 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// source: span.proto
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
fmt "fmt"
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
math "math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package it is being compiled against.
|
|
||||||
// A compilation error at this line likely means your copy of the
|
|
||||||
// proto package needs to be updated.
|
|
||||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
|
||||||
|
|
||||||
// TagType denotes the type of a Tag's value.
|
|
||||||
type Tag_TagType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Tag_STRING Tag_TagType = 0
|
|
||||||
Tag_DOUBLE Tag_TagType = 1
|
|
||||||
Tag_BOOL Tag_TagType = 2
|
|
||||||
Tag_LONG Tag_TagType = 3
|
|
||||||
Tag_BINARY Tag_TagType = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
var Tag_TagType_name = map[int32]string{
|
|
||||||
0: "STRING",
|
|
||||||
1: "DOUBLE",
|
|
||||||
2: "BOOL",
|
|
||||||
3: "LONG",
|
|
||||||
4: "BINARY",
|
|
||||||
}
|
|
||||||
|
|
||||||
var Tag_TagType_value = map[string]int32{
|
|
||||||
"STRING": 0,
|
|
||||||
"DOUBLE": 1,
|
|
||||||
"BOOL": 2,
|
|
||||||
"LONG": 3,
|
|
||||||
"BINARY": 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Tag_TagType) String() string {
|
|
||||||
return proto.EnumName(Tag_TagType_name, int32(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Tag_TagType) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_fc5f2b88b579999f, []int{2, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Span represents a unit of work performed by a service.
|
|
||||||
type Span struct {
|
|
||||||
TraceId string `protobuf:"bytes,1,opt,name=traceId,proto3" json:"traceId,omitempty"`
|
|
||||||
SpanId string `protobuf:"bytes,2,opt,name=spanId,proto3" json:"spanId,omitempty"`
|
|
||||||
ParentSpanId string `protobuf:"bytes,3,opt,name=parentSpanId,proto3" json:"parentSpanId,omitempty"`
|
|
||||||
ServiceName string `protobuf:"bytes,4,opt,name=serviceName,proto3" json:"serviceName,omitempty"`
|
|
||||||
OperationName string `protobuf:"bytes,5,opt,name=operationName,proto3" json:"operationName,omitempty"`
|
|
||||||
StartTime int64 `protobuf:"varint,6,opt,name=startTime,proto3" json:"startTime,omitempty"`
|
|
||||||
Duration int64 `protobuf:"varint,7,opt,name=duration,proto3" json:"duration,omitempty"`
|
|
||||||
Logs []*Log `protobuf:"bytes,8,rep,name=logs,proto3" json:"logs,omitempty"`
|
|
||||||
Tags []*Tag `protobuf:"bytes,9,rep,name=tags,proto3" json:"tags,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) Reset() { *m = Span{} }
|
|
||||||
func (m *Span) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Span) ProtoMessage() {}
|
|
||||||
func (*Span) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_fc5f2b88b579999f, []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) XXX_Unmarshal(b []byte) error {
|
|
||||||
return xxx_messageInfo_Span.Unmarshal(m, b)
|
|
||||||
}
|
|
||||||
func (m *Span) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
return xxx_messageInfo_Span.Marshal(b, m, deterministic)
|
|
||||||
}
|
|
||||||
func (m *Span) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_Span.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *Span) XXX_Size() int {
|
|
||||||
return xxx_messageInfo_Span.Size(m)
|
|
||||||
}
|
|
||||||
func (m *Span) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_Span.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_Span proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *Span) GetTraceId() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.TraceId
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetSpanId() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.SpanId
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetParentSpanId() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.ParentSpanId
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetServiceName() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.ServiceName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetOperationName() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.OperationName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetStartTime() int64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.StartTime
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetDuration() int64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.Duration
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetLogs() []*Log {
|
|
||||||
if m != nil {
|
|
||||||
return m.Logs
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Span) GetTags() []*Tag {
|
|
||||||
if m != nil {
|
|
||||||
return m.Tags
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log is a timestamped event with a set of tags.
|
|
||||||
type Log struct {
|
|
||||||
Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
|
||||||
Fields []*Tag `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Log) Reset() { *m = Log{} }
|
|
||||||
func (m *Log) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Log) ProtoMessage() {}
|
|
||||||
func (*Log) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_fc5f2b88b579999f, []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Log) XXX_Unmarshal(b []byte) error {
|
|
||||||
return xxx_messageInfo_Log.Unmarshal(m, b)
|
|
||||||
}
|
|
||||||
func (m *Log) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
return xxx_messageInfo_Log.Marshal(b, m, deterministic)
|
|
||||||
}
|
|
||||||
func (m *Log) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_Log.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *Log) XXX_Size() int {
|
|
||||||
return xxx_messageInfo_Log.Size(m)
|
|
||||||
}
|
|
||||||
func (m *Log) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_Log.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_Log proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *Log) GetTimestamp() int64 {
|
|
||||||
if m != nil {
|
|
||||||
return m.Timestamp
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Log) GetFields() []*Tag {
|
|
||||||
if m != nil {
|
|
||||||
return m.Fields
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag is a strongly typed key/value pair. We use 'oneof' protobuf attribute to represent the possible tagTypes
|
|
||||||
type Tag struct {
|
|
||||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
|
||||||
Type Tag_TagType `protobuf:"varint,2,opt,name=type,proto3,enum=Tag_TagType" json:"type,omitempty"`
|
|
||||||
// Types that are valid to be assigned to Myvalue:
|
|
||||||
// *Tag_VStr
|
|
||||||
// *Tag_VLong
|
|
||||||
// *Tag_VDouble
|
|
||||||
// *Tag_VBool
|
|
||||||
// *Tag_VBytes
|
|
||||||
Myvalue isTag_Myvalue `protobuf_oneof:"myvalue"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) Reset() { *m = Tag{} }
|
|
||||||
func (m *Tag) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Tag) ProtoMessage() {}
|
|
||||||
func (*Tag) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_fc5f2b88b579999f, []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) XXX_Unmarshal(b []byte) error {
|
|
||||||
return xxx_messageInfo_Tag.Unmarshal(m, b)
|
|
||||||
}
|
|
||||||
func (m *Tag) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
return xxx_messageInfo_Tag.Marshal(b, m, deterministic)
|
|
||||||
}
|
|
||||||
func (m *Tag) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_Tag.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *Tag) XXX_Size() int {
|
|
||||||
return xxx_messageInfo_Tag.Size(m)
|
|
||||||
}
|
|
||||||
func (m *Tag) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_Tag.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_Tag proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *Tag) GetKey() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.Key
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetType() Tag_TagType {
|
|
||||||
if m != nil {
|
|
||||||
return m.Type
|
|
||||||
}
|
|
||||||
return Tag_STRING
|
|
||||||
}
|
|
||||||
|
|
||||||
type isTag_Myvalue interface {
|
|
||||||
isTag_Myvalue()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag_VStr struct {
|
|
||||||
VStr string `protobuf:"bytes,3,opt,name=vStr,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag_VLong struct {
|
|
||||||
VLong int64 `protobuf:"varint,4,opt,name=vLong,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag_VDouble struct {
|
|
||||||
VDouble float64 `protobuf:"fixed64,5,opt,name=vDouble,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag_VBool struct {
|
|
||||||
VBool bool `protobuf:"varint,6,opt,name=vBool,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tag_VBytes struct {
|
|
||||||
VBytes []byte `protobuf:"bytes,7,opt,name=vBytes,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Tag_VStr) isTag_Myvalue() {}
|
|
||||||
|
|
||||||
func (*Tag_VLong) isTag_Myvalue() {}
|
|
||||||
|
|
||||||
func (*Tag_VDouble) isTag_Myvalue() {}
|
|
||||||
|
|
||||||
func (*Tag_VBool) isTag_Myvalue() {}
|
|
||||||
|
|
||||||
func (*Tag_VBytes) isTag_Myvalue() {}
|
|
||||||
|
|
||||||
func (m *Tag) GetMyvalue() isTag_Myvalue {
|
|
||||||
if m != nil {
|
|
||||||
return m.Myvalue
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetVStr() string {
|
|
||||||
if x, ok := m.GetMyvalue().(*Tag_VStr); ok {
|
|
||||||
return x.VStr
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetVLong() int64 {
|
|
||||||
if x, ok := m.GetMyvalue().(*Tag_VLong); ok {
|
|
||||||
return x.VLong
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetVDouble() float64 {
|
|
||||||
if x, ok := m.GetMyvalue().(*Tag_VDouble); ok {
|
|
||||||
return x.VDouble
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetVBool() bool {
|
|
||||||
if x, ok := m.GetMyvalue().(*Tag_VBool); ok {
|
|
||||||
return x.VBool
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Tag) GetVBytes() []byte {
|
|
||||||
if x, ok := m.GetMyvalue().(*Tag_VBytes); ok {
|
|
||||||
return x.VBytes
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX_OneofWrappers is for the internal use of the proto package.
|
|
||||||
func (*Tag) XXX_OneofWrappers() []interface{} {
|
|
||||||
return []interface{}{
|
|
||||||
(*Tag_VStr)(nil),
|
|
||||||
(*Tag_VLong)(nil),
|
|
||||||
(*Tag_VDouble)(nil),
|
|
||||||
(*Tag_VBool)(nil),
|
|
||||||
(*Tag_VBytes)(nil),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can optionally use Batch to send a collection of spans. Spans may not necessarily belong to one traceId.
|
|
||||||
type Batch struct {
|
|
||||||
Spans []*Span `protobuf:"bytes,1,rep,name=spans,proto3" json:"spans,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Batch) Reset() { *m = Batch{} }
|
|
||||||
func (m *Batch) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Batch) ProtoMessage() {}
|
|
||||||
func (*Batch) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_fc5f2b88b579999f, []int{3}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Batch) XXX_Unmarshal(b []byte) error {
|
|
||||||
return xxx_messageInfo_Batch.Unmarshal(m, b)
|
|
||||||
}
|
|
||||||
func (m *Batch) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
return xxx_messageInfo_Batch.Marshal(b, m, deterministic)
|
|
||||||
}
|
|
||||||
func (m *Batch) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_Batch.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *Batch) XXX_Size() int {
|
|
||||||
return xxx_messageInfo_Batch.Size(m)
|
|
||||||
}
|
|
||||||
func (m *Batch) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_Batch.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_Batch proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *Batch) GetSpans() []*Span {
|
|
||||||
if m != nil {
|
|
||||||
return m.Spans
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("Tag_TagType", Tag_TagType_name, Tag_TagType_value)
|
|
||||||
proto.RegisterType((*Span)(nil), "Span")
|
|
||||||
proto.RegisterType((*Log)(nil), "Log")
|
|
||||||
proto.RegisterType((*Tag)(nil), "Tag")
|
|
||||||
proto.RegisterType((*Batch)(nil), "Batch")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { proto.RegisterFile("span.proto", fileDescriptor_fc5f2b88b579999f) }
|
|
||||||
|
|
||||||
var fileDescriptor_fc5f2b88b579999f = []byte{
|
|
||||||
// 456 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0xcd, 0x8a, 0x9c, 0x40,
|
|
||||||
0x14, 0x85, 0xdb, 0xf6, 0xb7, 0xef, 0x74, 0x82, 0x14, 0x61, 0x28, 0x26, 0xb3, 0x10, 0x19, 0x42,
|
|
||||||
0xaf, 0x5c, 0x4c, 0x9e, 0xa0, 0x65, 0xc2, 0x74, 0x83, 0x74, 0x87, 0x6a, 0xb3, 0x48, 0x76, 0x35,
|
|
||||||
0x5a, 0x71, 0x64, 0xd4, 0x2a, 0xac, 0x6a, 0x89, 0xeb, 0xbc, 0x41, 0x9e, 0x38, 0x54, 0xe9, 0xfc,
|
|
||||||
0x2d, 0x84, 0x7b, 0xbe, 0x73, 0xaf, 0xca, 0xe1, 0x00, 0x48, 0x41, 0xbb, 0x44, 0xf4, 0x5c, 0xf1,
|
|
||||||
0xf8, 0xdf, 0x12, 0x9c, 0x93, 0xa0, 0x1d, 0xc2, 0xe0, 0xab, 0x9e, 0x16, 0x6c, 0x5f, 0x62, 0x2b,
|
|
||||||
0xb2, 0x36, 0x2b, 0xf2, 0x2c, 0xd1, 0x25, 0x78, 0xfa, 0x60, 0x5f, 0xe2, 0xa5, 0x31, 0x66, 0x85,
|
|
||||||
0x62, 0x58, 0x0b, 0xda, 0xb3, 0x4e, 0x9d, 0x26, 0xd7, 0x36, 0xee, 0x3b, 0x86, 0x22, 0xb8, 0x90,
|
|
||||||
0xac, 0x1f, 0xea, 0x82, 0x1d, 0x68, 0xcb, 0xb0, 0x63, 0x56, 0xde, 0x22, 0x74, 0x03, 0x1f, 0xb8,
|
|
||||||
0x60, 0x3d, 0x55, 0x35, 0xef, 0xcc, 0x8e, 0x6b, 0x76, 0xde, 0x43, 0x74, 0x0d, 0x2b, 0xa9, 0x68,
|
|
||||||
0xaf, 0xf2, 0xba, 0x65, 0xd8, 0x8b, 0xac, 0x8d, 0x4d, 0x5e, 0x01, 0xba, 0x82, 0xa0, 0x3c, 0x4f,
|
|
||||||
0xdb, 0xd8, 0x37, 0xe6, 0x8b, 0x46, 0x18, 0x9c, 0x86, 0x57, 0x12, 0x07, 0x91, 0xbd, 0xb9, 0xb8,
|
|
||||||
0x75, 0x92, 0x8c, 0x57, 0xc4, 0x10, 0xed, 0x28, 0x5a, 0x49, 0xbc, 0x9a, 0x9d, 0x9c, 0x56, 0xc4,
|
|
||||||
0x90, 0x78, 0x0b, 0x76, 0xc6, 0x2b, 0xfd, 0x51, 0x55, 0xb7, 0x4c, 0x2a, 0xda, 0x0a, 0x13, 0x8a,
|
|
||||||
0x4d, 0x5e, 0x01, 0xba, 0x06, 0xef, 0x77, 0xcd, 0x9a, 0x52, 0xe2, 0xe5, 0x9b, 0x17, 0xcc, 0x2c,
|
|
||||||
0xfe, 0xbb, 0x04, 0x3b, 0xa7, 0x15, 0x0a, 0xc1, 0x7e, 0x62, 0xe3, 0x1c, 0xa9, 0x1e, 0x51, 0x04,
|
|
||||||
0x8e, 0x1a, 0x05, 0x33, 0x61, 0x7e, 0xbc, 0x5d, 0xeb, 0x2b, 0xfd, 0xe4, 0xa3, 0x60, 0xc4, 0x38,
|
|
||||||
0xe8, 0x13, 0x38, 0xc3, 0x49, 0xf5, 0x53, 0xa0, 0xbb, 0x05, 0x31, 0x0a, 0x5d, 0x82, 0x3b, 0x64,
|
|
||||||
0xbc, 0xab, 0x4c, 0x88, 0xf6, 0x6e, 0x41, 0x26, 0x89, 0xae, 0xc0, 0x1f, 0xee, 0xf8, 0xf9, 0xa1,
|
|
||||||
0x99, 0xa2, 0xb3, 0x76, 0x0b, 0xf2, 0x0c, 0xcc, 0x4d, 0xca, 0x79, 0x63, 0x22, 0x0b, 0xcc, 0x8d,
|
|
||||||
0x96, 0x08, 0x83, 0x37, 0xa4, 0xa3, 0x62, 0xd2, 0xc4, 0xb5, 0xde, 0x2d, 0xc8, 0xac, 0xe3, 0x2d,
|
|
||||||
0xf8, 0xf3, 0xcf, 0x20, 0x00, 0xef, 0x94, 0x93, 0xfd, 0xe1, 0x3e, 0x5c, 0xe8, 0xf9, 0xee, 0xf8,
|
|
||||||
0x23, 0xcd, 0xbe, 0x85, 0x16, 0x0a, 0xc0, 0x49, 0x8f, 0xc7, 0x2c, 0x5c, 0xea, 0x29, 0x3b, 0x1e,
|
|
||||||
0xee, 0x43, 0x5b, 0xfb, 0xe9, 0xfe, 0xb0, 0x25, 0x3f, 0x43, 0x27, 0x5d, 0x81, 0xdf, 0x8e, 0x03,
|
|
||||||
0x6d, 0xce, 0x2c, 0xbe, 0x01, 0x37, 0xa5, 0xaa, 0x78, 0x44, 0x9f, 0xc1, 0xd5, 0xad, 0x91, 0xd8,
|
|
||||||
0x32, 0x59, 0xb9, 0x89, 0xee, 0x07, 0x99, 0x58, 0xfa, 0x05, 0x70, 0xc1, 0xdb, 0x84, 0xfd, 0x11,
|
|
||||||
0xac, 0xac, 0x69, 0xc2, 0x05, 0xeb, 0x12, 0x5d, 0xbe, 0xba, 0xab, 0xbe, 0x5b, 0xbf, 0x82, 0x47,
|
|
||||||
0x3a, 0x4a, 0x45, 0x8b, 0xa7, 0x07, 0xcf, 0x54, 0xf6, 0xeb, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
||||||
0xdd, 0x60, 0xee, 0x6b, 0xc0, 0x02, 0x00, 0x00,
|
|
||||||
}
|
|
197
vendor/github.com/ExpediaDotCom/haystack-client-go/spanAgent.pb.go
generated
vendored
197
vendor/github.com/ExpediaDotCom/haystack-client-go/spanAgent.pb.go
generated
vendored
|
@ -1,197 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// source: spanAgent.proto
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "context"
|
|
||||||
fmt "fmt"
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
math "math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package it is being compiled against.
|
|
||||||
// A compilation error at this line likely means your copy of the
|
|
||||||
// proto package needs to be updated.
|
|
||||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
|
||||||
|
|
||||||
type DispatchResult_ResultCode int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
DispatchResult_SUCCESS DispatchResult_ResultCode = 0
|
|
||||||
DispatchResult_UNKNOWN_ERROR DispatchResult_ResultCode = 1
|
|
||||||
DispatchResult_RATE_LIMIT_ERROR DispatchResult_ResultCode = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var DispatchResult_ResultCode_name = map[int32]string{
|
|
||||||
0: "SUCCESS",
|
|
||||||
1: "UNKNOWN_ERROR",
|
|
||||||
2: "RATE_LIMIT_ERROR",
|
|
||||||
}
|
|
||||||
|
|
||||||
var DispatchResult_ResultCode_value = map[string]int32{
|
|
||||||
"SUCCESS": 0,
|
|
||||||
"UNKNOWN_ERROR": 1,
|
|
||||||
"RATE_LIMIT_ERROR": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x DispatchResult_ResultCode) String() string {
|
|
||||||
return proto.EnumName(DispatchResult_ResultCode_name, int32(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (DispatchResult_ResultCode) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_5a4cb81dd7dcc459, []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type DispatchResult struct {
|
|
||||||
Code DispatchResult_ResultCode `protobuf:"varint,1,opt,name=code,proto3,enum=DispatchResult_ResultCode" json:"code,omitempty"`
|
|
||||||
ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DispatchResult) Reset() { *m = DispatchResult{} }
|
|
||||||
func (m *DispatchResult) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*DispatchResult) ProtoMessage() {}
|
|
||||||
func (*DispatchResult) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_5a4cb81dd7dcc459, []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DispatchResult) XXX_Unmarshal(b []byte) error {
|
|
||||||
return xxx_messageInfo_DispatchResult.Unmarshal(m, b)
|
|
||||||
}
|
|
||||||
func (m *DispatchResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
return xxx_messageInfo_DispatchResult.Marshal(b, m, deterministic)
|
|
||||||
}
|
|
||||||
func (m *DispatchResult) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_DispatchResult.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *DispatchResult) XXX_Size() int {
|
|
||||||
return xxx_messageInfo_DispatchResult.Size(m)
|
|
||||||
}
|
|
||||||
func (m *DispatchResult) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_DispatchResult.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_DispatchResult proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func (m *DispatchResult) GetCode() DispatchResult_ResultCode {
|
|
||||||
if m != nil {
|
|
||||||
return m.Code
|
|
||||||
}
|
|
||||||
return DispatchResult_SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DispatchResult) GetErrorMessage() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.ErrorMessage
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("DispatchResult_ResultCode", DispatchResult_ResultCode_name, DispatchResult_ResultCode_value)
|
|
||||||
proto.RegisterType((*DispatchResult)(nil), "DispatchResult")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { proto.RegisterFile("spanAgent.proto", fileDescriptor_5a4cb81dd7dcc459) }
|
|
||||||
|
|
||||||
var fileDescriptor_5a4cb81dd7dcc459 = []byte{
|
|
||||||
// 254 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xc1, 0x4a, 0xf3, 0x40,
|
|
||||||
0x10, 0xc7, 0xbf, 0x2d, 0x9f, 0xda, 0x8e, 0xb6, 0x8d, 0x8b, 0x87, 0x92, 0x53, 0x89, 0x97, 0x9e,
|
|
||||||
0x56, 0xa9, 0x4f, 0xd0, 0xc6, 0x1c, 0x8a, 0x36, 0x95, 0x4d, 0x8b, 0xe0, 0x25, 0x8c, 0x9b, 0x21,
|
|
||||||
0x0d, 0xda, 0xec, 0xb2, 0xbb, 0x82, 0x3e, 0x92, 0x6f, 0x29, 0x4d, 0x2a, 0xa2, 0xa7, 0x19, 0x7e,
|
|
||||||
0x33, 0x03, 0xff, 0xf9, 0xc1, 0xd0, 0x19, 0xac, 0x67, 0x25, 0xd5, 0x5e, 0x18, 0xab, 0xbd, 0x0e,
|
|
||||||
0x61, 0x0f, 0xda, 0x3e, 0xfa, 0x64, 0x30, 0xb8, 0xad, 0x9c, 0x41, 0xaf, 0xb6, 0x92, 0xdc, 0xdb,
|
|
||||||
0xab, 0xe7, 0x02, 0xfe, 0x2b, 0x5d, 0xd0, 0x88, 0x8d, 0xd9, 0x64, 0x30, 0x0d, 0xc5, 0xef, 0xb1,
|
|
||||||
0x68, 0x4b, 0xac, 0x0b, 0x92, 0xcd, 0x1e, 0xbf, 0x84, 0x3e, 0x59, 0xab, 0x6d, 0xbe, 0x23, 0xe7,
|
|
||||||
0xb0, 0xa4, 0x51, 0x67, 0xcc, 0x26, 0x3d, 0x79, 0xd6, 0xc0, 0x65, 0xcb, 0xa2, 0x39, 0xc0, 0xcf,
|
|
||||||
0x21, 0x3f, 0x85, 0x93, 0x6c, 0x13, 0xc7, 0x49, 0x96, 0x05, 0xff, 0xf8, 0x39, 0xf4, 0x37, 0xe9,
|
|
||||||
0x5d, 0xba, 0x7a, 0x4c, 0xf3, 0x44, 0xca, 0x95, 0x0c, 0x18, 0xbf, 0x80, 0x40, 0xce, 0xd6, 0x49,
|
|
||||||
0x7e, 0xbf, 0x58, 0x2e, 0xd6, 0x07, 0xda, 0x99, 0x5e, 0x41, 0x2f, 0xfb, 0x7e, 0x85, 0x47, 0xd0,
|
|
||||||
0x2d, 0x0e, 0xc1, 0xf8, 0x91, 0xd8, 0xf3, 0x70, 0xf8, 0x27, 0xea, 0xfc, 0x1a, 0x22, 0xa5, 0x77,
|
|
||||||
0x82, 0xde, 0x0d, 0x15, 0x15, 0x0a, 0x6d, 0xa8, 0x16, 0xde, 0xa2, 0xaa, 0xea, 0x52, 0x60, 0x23,
|
|
||||||
0x04, 0x4d, 0xf5, 0xc0, 0x9e, 0xba, 0x5b, 0xfc, 0x70, 0x1e, 0xd5, 0xcb, 0xf3, 0x71, 0x63, 0xe5,
|
|
||||||
0xe6, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x30, 0xb9, 0x7d, 0x07, 0x34, 0x01, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ context.Context
|
|
||||||
var _ grpc.ClientConn
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
const _ = grpc.SupportPackageIsVersion4
|
|
||||||
|
|
||||||
// SpanAgentClient is the client API for SpanAgent service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
|
||||||
type SpanAgentClient interface {
|
|
||||||
Dispatch(ctx context.Context, in *Span, opts ...grpc.CallOption) (*DispatchResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type spanAgentClient struct {
|
|
||||||
cc *grpc.ClientConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSpanAgentClient(cc *grpc.ClientConn) SpanAgentClient {
|
|
||||||
return &spanAgentClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *spanAgentClient) Dispatch(ctx context.Context, in *Span, opts ...grpc.CallOption) (*DispatchResult, error) {
|
|
||||||
out := new(DispatchResult)
|
|
||||||
err := c.cc.Invoke(ctx, "/SpanAgent/dispatch", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SpanAgentServer is the server API for SpanAgent service.
|
|
||||||
type SpanAgentServer interface {
|
|
||||||
Dispatch(context.Context, *Span) (*DispatchResult, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterSpanAgentServer(s *grpc.Server, srv SpanAgentServer) {
|
|
||||||
s.RegisterService(&_SpanAgent_serviceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _SpanAgent_Dispatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(Span)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(SpanAgentServer).Dispatch(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/SpanAgent/Dispatch",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(SpanAgentServer).Dispatch(ctx, req.(*Span))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _SpanAgent_serviceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "SpanAgent",
|
|
||||||
HandlerType: (*SpanAgentServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "dispatch",
|
|
||||||
Handler: _SpanAgent_Dispatch_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "spanAgent.proto",
|
|
||||||
}
|
|
80
vendor/github.com/ExpediaDotCom/haystack-client-go/span_context.go
generated
vendored
80
vendor/github.com/ExpediaDotCom/haystack-client-go/span_context.go
generated
vendored
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*SpanContext implements opentracing.spanContext*/
|
|
||||||
type SpanContext struct {
|
|
||||||
// traceID represents globally unique ID of the trace.
|
|
||||||
TraceID string
|
|
||||||
|
|
||||||
// spanID represents span ID that must be unique within its trace
|
|
||||||
SpanID string
|
|
||||||
|
|
||||||
// parentID refers to the ID of the parent span.
|
|
||||||
// Should be empty if the current span is a root span.
|
|
||||||
ParentID string
|
|
||||||
|
|
||||||
//Context baggage. The is a snapshot in time.
|
|
||||||
Baggage map[string]string
|
|
||||||
|
|
||||||
// set to true if extracted using a extractor in tracer
|
|
||||||
IsExtractedContext bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid indicates whether this context actually represents a valid trace.
|
|
||||||
func (context SpanContext) IsValid() bool {
|
|
||||||
return context.TraceID != "" && context.SpanID != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ForeachBaggageItem implements opentracing.spancontext*/
|
|
||||||
func (context SpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
|
|
||||||
for k, v := range context.Baggage {
|
|
||||||
if !handler(k, v) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithBaggageItem creates a new context with an extra baggage item.
|
|
||||||
func (context SpanContext) WithBaggageItem(key, value string) *SpanContext {
|
|
||||||
var newBaggage map[string]string
|
|
||||||
if context.Baggage == nil {
|
|
||||||
newBaggage = map[string]string{key: value}
|
|
||||||
} else {
|
|
||||||
newBaggage = make(map[string]string, len(context.Baggage)+1)
|
|
||||||
for k, v := range context.Baggage {
|
|
||||||
newBaggage[k] = v
|
|
||||||
}
|
|
||||||
newBaggage[key] = value
|
|
||||||
}
|
|
||||||
return &SpanContext{
|
|
||||||
TraceID: context.TraceID,
|
|
||||||
SpanID: context.SpanID,
|
|
||||||
ParentID: context.ParentID,
|
|
||||||
Baggage: newBaggage,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ToString represents the string*/
|
|
||||||
func (context SpanContext) ToString() string {
|
|
||||||
return fmt.Sprintf("%+v", context)
|
|
||||||
}
|
|
214
vendor/github.com/ExpediaDotCom/haystack-client-go/tracer.go
generated
vendored
214
vendor/github.com/ExpediaDotCom/haystack-client-go/tracer.go
generated
vendored
|
@ -1,214 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*Tracer implements the opentracing.tracer*/
|
|
||||||
type Tracer struct {
|
|
||||||
serviceName string
|
|
||||||
logger Logger
|
|
||||||
dispatcher Dispatcher
|
|
||||||
commonTags []opentracing.Tag
|
|
||||||
timeNow func() time.Time
|
|
||||||
idGenerator func() string
|
|
||||||
propagators map[interface{}]Propagator
|
|
||||||
useDualSpanMode bool
|
|
||||||
}
|
|
||||||
|
|
||||||
/*NewTracer creates a new tracer*/
|
|
||||||
func NewTracer(
|
|
||||||
serviceName string,
|
|
||||||
dispatcher Dispatcher,
|
|
||||||
options ...TracerOption,
|
|
||||||
) (opentracing.Tracer, io.Closer) {
|
|
||||||
tracer := &Tracer{
|
|
||||||
serviceName: serviceName,
|
|
||||||
dispatcher: dispatcher,
|
|
||||||
useDualSpanMode: false,
|
|
||||||
}
|
|
||||||
tracer.propagators = make(map[interface{}]Propagator)
|
|
||||||
tracer.propagators[opentracing.TextMap] = NewDefaultTextMapPropagator()
|
|
||||||
tracer.propagators[opentracing.HTTPHeaders] = NewTextMapPropagator(PropagatorOpts{}, URLCodex{})
|
|
||||||
for _, option := range options {
|
|
||||||
option(tracer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tracer.timeNow == nil {
|
|
||||||
tracer.timeNow = time.Now
|
|
||||||
}
|
|
||||||
|
|
||||||
if tracer.logger == nil {
|
|
||||||
tracer.logger = NullLogger{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tracer.idGenerator == nil {
|
|
||||||
tracer.idGenerator = func() string {
|
|
||||||
_uuid, err := uuid.NewUUID()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return _uuid.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatcher.SetLogger(tracer.logger)
|
|
||||||
return tracer, tracer
|
|
||||||
}
|
|
||||||
|
|
||||||
/*StartSpan starts a new span*/
|
|
||||||
func (tracer *Tracer) StartSpan(
|
|
||||||
operationName string,
|
|
||||||
options ...opentracing.StartSpanOption,
|
|
||||||
) opentracing.Span {
|
|
||||||
sso := opentracing.StartSpanOptions{}
|
|
||||||
|
|
||||||
for _, o := range options {
|
|
||||||
o.Apply(&sso)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sso.StartTime.IsZero() {
|
|
||||||
sso.StartTime = tracer.timeNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
var followsFromIsParent = false
|
|
||||||
var parent *SpanContext
|
|
||||||
|
|
||||||
for _, ref := range sso.References {
|
|
||||||
if ref.Type == opentracing.ChildOfRef {
|
|
||||||
if parent == nil || followsFromIsParent {
|
|
||||||
parent = ref.ReferencedContext.(*SpanContext)
|
|
||||||
}
|
|
||||||
} else if ref.Type == opentracing.FollowsFromRef {
|
|
||||||
if parent == nil {
|
|
||||||
parent = ref.ReferencedContext.(*SpanContext)
|
|
||||||
followsFromIsParent = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spanContext := tracer.createSpanContext(parent, tracer.isServerSpan(sso.Tags))
|
|
||||||
|
|
||||||
span := &_Span{
|
|
||||||
tracer: tracer,
|
|
||||||
context: spanContext,
|
|
||||||
operationName: operationName,
|
|
||||||
startTime: sso.StartTime,
|
|
||||||
duration: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range tracer.Tags() {
|
|
||||||
span.SetTag(tag.Key, tag.Value)
|
|
||||||
}
|
|
||||||
for k, v := range sso.Tags {
|
|
||||||
span.SetTag(k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return span
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tracer *Tracer) isServerSpan(spanTags map[string]interface{}) bool {
|
|
||||||
if spanKind, ok := spanTags[string(ext.SpanKind)]; ok && spanKind == "server" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tracer *Tracer) createSpanContext(parent *SpanContext, isServerSpan bool) *SpanContext {
|
|
||||||
if parent == nil || !parent.IsValid() {
|
|
||||||
return &SpanContext{
|
|
||||||
TraceID: tracer.idGenerator(),
|
|
||||||
SpanID: tracer.idGenerator(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a check to see if the tracer is configured to support single
|
|
||||||
// single span type (Zipkin style shared span id) or
|
|
||||||
// dual span type (client and server having their own span ids ).
|
|
||||||
// a. If tracer is not of dualSpanType and if it is a server span then we
|
|
||||||
// just return the parent context with the same shared span ids
|
|
||||||
// b. If tracer is not of dualSpanType and if the parent context is an extracted one from the wire
|
|
||||||
// then we assume this is the first span in the server and so just return the parent context
|
|
||||||
// with the same shared span ids
|
|
||||||
if !tracer.useDualSpanMode && (isServerSpan || parent.IsExtractedContext) {
|
|
||||||
return &SpanContext{
|
|
||||||
TraceID: parent.TraceID,
|
|
||||||
SpanID: parent.SpanID,
|
|
||||||
ParentID: parent.ParentID,
|
|
||||||
Baggage: parent.Baggage,
|
|
||||||
IsExtractedContext: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &SpanContext{
|
|
||||||
TraceID: parent.TraceID,
|
|
||||||
SpanID: tracer.idGenerator(),
|
|
||||||
ParentID: parent.SpanID,
|
|
||||||
Baggage: parent.Baggage,
|
|
||||||
IsExtractedContext: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Inject implements Inject() method of opentracing.Tracer*/
|
|
||||||
func (tracer *Tracer) Inject(ctx opentracing.SpanContext, format interface{}, carrier interface{}) error {
|
|
||||||
c, ok := ctx.(*SpanContext)
|
|
||||||
if !ok {
|
|
||||||
return opentracing.ErrInvalidSpanContext
|
|
||||||
}
|
|
||||||
if injector, ok := tracer.propagators[format]; ok {
|
|
||||||
return injector.Inject(c, carrier)
|
|
||||||
}
|
|
||||||
return opentracing.ErrUnsupportedFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Extract implements Extract() method of opentracing.Tracer*/
|
|
||||||
func (tracer *Tracer) Extract(
|
|
||||||
format interface{},
|
|
||||||
carrier interface{},
|
|
||||||
) (opentracing.SpanContext, error) {
|
|
||||||
if extractor, ok := tracer.propagators[format]; ok {
|
|
||||||
return extractor.Extract(carrier)
|
|
||||||
}
|
|
||||||
return nil, opentracing.ErrUnsupportedFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Tags return all common tags */
|
|
||||||
func (tracer *Tracer) Tags() []opentracing.Tag {
|
|
||||||
return tracer.commonTags
|
|
||||||
}
|
|
||||||
|
|
||||||
/*DispatchSpan dispatches the span to a dispatcher*/
|
|
||||||
func (tracer *Tracer) DispatchSpan(span *_Span) {
|
|
||||||
if tracer.dispatcher != nil {
|
|
||||||
tracer.dispatcher.Dispatch(span)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Close closes the tracer*/
|
|
||||||
func (tracer *Tracer) Close() error {
|
|
||||||
if tracer.dispatcher != nil {
|
|
||||||
tracer.dispatcher.Close()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
59
vendor/github.com/ExpediaDotCom/haystack-client-go/tracer_options.go
generated
vendored
59
vendor/github.com/ExpediaDotCom/haystack-client-go/tracer_options.go
generated
vendored
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 Expedia Group.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package haystack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/opentracing/opentracing-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TracerOption is a function that sets some option on the tracer
|
|
||||||
type TracerOption func(tracer *Tracer)
|
|
||||||
|
|
||||||
/*TracerOptions a list of tracer options*/
|
|
||||||
type TracerOptions struct{}
|
|
||||||
|
|
||||||
/*TracerOptionsFactory factory to create multiple tracer options*/
|
|
||||||
var TracerOptionsFactory TracerOptions
|
|
||||||
|
|
||||||
/*Propagator registers a new Propagator*/
|
|
||||||
func (t TracerOptions) Propagator(format interface{}, propagator Propagator) TracerOption {
|
|
||||||
return func(tracer *Tracer) {
|
|
||||||
tracer.propagators[format] = propagator
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Tag adds a common tag in every span*/
|
|
||||||
func (t TracerOptions) Tag(key string, value interface{}) TracerOption {
|
|
||||||
return func(tracer *Tracer) {
|
|
||||||
tracer.commonTags = append(tracer.commonTags, opentracing.Tag{Key: key, Value: value})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Logger set the logger type*/
|
|
||||||
func (t TracerOptions) Logger(logger Logger) TracerOption {
|
|
||||||
return func(tracer *Tracer) {
|
|
||||||
tracer.logger = logger
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*UseDualSpanMode sets the tracer in dual span mode*/
|
|
||||||
func (t TracerOptions) UseDualSpanMode() TracerOption {
|
|
||||||
return func(tracer *Tracer) {
|
|
||||||
tracer.useDualSpanMode = true
|
|
||||||
}
|
|
||||||
}
|
|
22
vendor/github.com/JamesClonk/vultr/LICENSE
generated
vendored
22
vendor/github.com/JamesClonk/vultr/LICENSE
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 Fabio Berchtold
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
71
vendor/github.com/JamesClonk/vultr/lib/account_info.go
generated
vendored
71
vendor/github.com/JamesClonk/vultr/lib/account_info.go
generated
vendored
|
@ -1,71 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AccountInfo of Vultr account
|
|
||||||
type AccountInfo struct {
|
|
||||||
Balance float64 `json:"balance"`
|
|
||||||
PendingCharges float64 `json:"pending_charges"`
|
|
||||||
LastPaymentDate string `json:"last_payment_date"`
|
|
||||||
LastPaymentAmount float64 `json:"last_payment_amount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAccountInfo retrieves the Vultr account information about current balance, pending charges, etc..
|
|
||||||
func (c *Client) GetAccountInfo() (info AccountInfo, err error) {
|
|
||||||
if err := c.get(`account/info`, &info); err != nil {
|
|
||||||
return AccountInfo{}, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaller on AccountInfo.
|
|
||||||
// This is needed because the Vultr API is inconsistent in it's JSON responses for account info.
|
|
||||||
// Some fields can change type, from JSON number to JSON string and vice-versa.
|
|
||||||
func (a *AccountInfo) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
if a == nil {
|
|
||||||
*a = AccountInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fields map[string]interface{}
|
|
||||||
if err := json.Unmarshal(data, &fields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
value := fmt.Sprintf("%v", fields["balance"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
b, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.Balance = b
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["pending_charges"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
pc, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.PendingCharges = pc
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["last_payment_amount"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
lpa, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.LastPaymentAmount = lpa
|
|
||||||
|
|
||||||
a.LastPaymentDate = fmt.Sprintf("%v", fields["last_payment_date"])
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
38
vendor/github.com/JamesClonk/vultr/lib/applications.go
generated
vendored
38
vendor/github.com/JamesClonk/vultr/lib/applications.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Application on Vultr
|
|
||||||
type Application struct {
|
|
||||||
ID string `json:"APPID"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
ShortName string `json:"short_name"`
|
|
||||||
DeployName string `json:"deploy_name"`
|
|
||||||
Surcharge float64 `json:"surcharge"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type applications []Application
|
|
||||||
|
|
||||||
func (s applications) Len() int { return len(s) }
|
|
||||||
func (s applications) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s applications) Less(i, j int) bool {
|
|
||||||
return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetApplications returns a list of all available applications on Vultr
|
|
||||||
func (c *Client) GetApplications() ([]Application, error) {
|
|
||||||
var appMap map[string]Application
|
|
||||||
if err := c.get(`app/list`, &appMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var appList []Application
|
|
||||||
for _, app := range appMap {
|
|
||||||
appList = append(appList, app)
|
|
||||||
}
|
|
||||||
sort.Sort(applications(appList))
|
|
||||||
return appList, nil
|
|
||||||
}
|
|
210
vendor/github.com/JamesClonk/vultr/lib/block_storage.go
generated
vendored
210
vendor/github.com/JamesClonk/vultr/lib/block_storage.go
generated
vendored
|
@ -1,210 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BlockStorage on Vultr account
|
|
||||||
type BlockStorage struct {
|
|
||||||
ID string `json:"SUBID,string"`
|
|
||||||
Name string `json:"label"`
|
|
||||||
RegionID int `json:"DCID,string"`
|
|
||||||
SizeGB int `json:"size_gb,string"`
|
|
||||||
Created string `json:"date_created"`
|
|
||||||
Cost string `json:"cost_per_month"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
AttachedTo string `json:"attached_to_SUBID"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type blockstorages []BlockStorage
|
|
||||||
|
|
||||||
func (b blockstorages) Len() int { return len(b) }
|
|
||||||
func (b blockstorages) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
|
||||||
func (b blockstorages) Less(i, j int) bool {
|
|
||||||
// sort order: name, size, status
|
|
||||||
if strings.ToLower(b[i].Name) < strings.ToLower(b[j].Name) {
|
|
||||||
return true
|
|
||||||
} else if strings.ToLower(b[i].Name) > strings.ToLower(b[j].Name) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if b[i].SizeGB < b[j].SizeGB {
|
|
||||||
return true
|
|
||||||
} else if b[i].SizeGB > b[j].SizeGB {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return b[i].Status < b[j].Status
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaller on BlockStorage.
|
|
||||||
// This is needed because the Vultr API is inconsistent in it's JSON responses.
|
|
||||||
// Some fields can change type, from JSON number to JSON string and vice-versa.
|
|
||||||
func (b *BlockStorage) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
if b == nil {
|
|
||||||
*b = BlockStorage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fields map[string]interface{}
|
|
||||||
if err := json.Unmarshal(data, &fields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
value := fmt.Sprintf("%v", fields["SUBID"])
|
|
||||||
if len(value) == 0 || value == "<nil>" || value == "0" {
|
|
||||||
b.ID = ""
|
|
||||||
} else {
|
|
||||||
id, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.ID = strconv.FormatFloat(id, 'f', -1, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["DCID"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
region, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.RegionID = int(region)
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["size_gb"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
size, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.SizeGB = int(size)
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["attached_to_SUBID"])
|
|
||||||
if len(value) == 0 || value == "<nil>" || value == "0" {
|
|
||||||
b.AttachedTo = ""
|
|
||||||
} else {
|
|
||||||
attached, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.AttachedTo = strconv.FormatFloat(attached, 'f', -1, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.Name = fmt.Sprintf("%v", fields["label"])
|
|
||||||
b.Created = fmt.Sprintf("%v", fields["date_created"])
|
|
||||||
b.Status = fmt.Sprintf("%v", fields["status"])
|
|
||||||
b.Cost = fmt.Sprintf("%v", fields["cost_per_month"])
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockStorages returns a list of all active block storages on Vultr account
|
|
||||||
func (c *Client) GetBlockStorages() (storages []BlockStorage, err error) {
|
|
||||||
if err := c.get(`block/list`, &storages); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sort.Sort(blockstorages(storages))
|
|
||||||
return storages, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockStorage returns block storage with given ID
|
|
||||||
func (c *Client) GetBlockStorage(id string) (BlockStorage, error) {
|
|
||||||
storages, err := c.GetBlockStorages()
|
|
||||||
if err != nil {
|
|
||||||
return BlockStorage{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range storages {
|
|
||||||
if s.ID == id {
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return BlockStorage{}, fmt.Errorf("BlockStorage with ID %v not found", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBlockStorage creates a new block storage on Vultr account
|
|
||||||
func (c *Client) CreateBlockStorage(name string, regionID, size int) (BlockStorage, error) {
|
|
||||||
values := url.Values{
|
|
||||||
"label": {name},
|
|
||||||
"DCID": {fmt.Sprintf("%v", regionID)},
|
|
||||||
"size_gb": {fmt.Sprintf("%v", size)},
|
|
||||||
}
|
|
||||||
|
|
||||||
var storage BlockStorage
|
|
||||||
if err := c.post(`block/create`, values, &storage); err != nil {
|
|
||||||
return BlockStorage{}, err
|
|
||||||
}
|
|
||||||
storage.RegionID = regionID
|
|
||||||
storage.Name = name
|
|
||||||
storage.SizeGB = size
|
|
||||||
|
|
||||||
return storage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResizeBlockStorage resizes an existing block storage
|
|
||||||
func (c *Client) ResizeBlockStorage(id string, size int) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"size_gb": {fmt.Sprintf("%v", size)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`block/resize`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LabelBlockStorage changes the label on an existing block storage
|
|
||||||
func (c *Client) LabelBlockStorage(id, name string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"label": {name},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`block/label_set`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AttachBlockStorage attaches block storage to an existing virtual machine
|
|
||||||
func (c *Client) AttachBlockStorage(id, serverID string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"attach_to_SUBID": {serverID},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`block/attach`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DetachBlockStorage detaches block storage from virtual machine
|
|
||||||
func (c *Client) DetachBlockStorage(id string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`block/detach`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteBlockStorage deletes an existing block storage
|
|
||||||
func (c *Client) DeleteBlockStorage(id string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`block/delete`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
249
vendor/github.com/JamesClonk/vultr/lib/client.go
generated
vendored
249
vendor/github.com/JamesClonk/vultr/lib/client.go
generated
vendored
|
@ -1,249 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/juju/ratelimit"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Version of this libary
|
|
||||||
Version = "1.13.0"
|
|
||||||
|
|
||||||
// APIVersion of Vultr
|
|
||||||
APIVersion = "v1"
|
|
||||||
|
|
||||||
// DefaultEndpoint to be used
|
|
||||||
DefaultEndpoint = "https://api.vultr.com/"
|
|
||||||
|
|
||||||
mediaType = "application/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// retryableStatusCodes are API response status codes that indicate that
|
|
||||||
// the failed request can be retried without further actions.
|
|
||||||
var retryableStatusCodes = map[int]struct{}{
|
|
||||||
503: {}, // Rate limit hit
|
|
||||||
500: {}, // Internal server error. Try again at a later time.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client represents the Vultr API client
|
|
||||||
type Client struct {
|
|
||||||
// HTTP client for communication with the Vultr API
|
|
||||||
client *http.Client
|
|
||||||
|
|
||||||
// User agent for HTTP client
|
|
||||||
UserAgent string
|
|
||||||
|
|
||||||
// Endpoint URL for API requests
|
|
||||||
Endpoint *url.URL
|
|
||||||
|
|
||||||
// API key for accessing the Vultr API
|
|
||||||
APIKey string
|
|
||||||
|
|
||||||
// Max. number of request attempts
|
|
||||||
MaxAttempts int
|
|
||||||
|
|
||||||
// Throttling struct
|
|
||||||
bucket *ratelimit.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options represents optional settings and flags that can be passed to NewClient
|
|
||||||
type Options struct {
|
|
||||||
// HTTP client for communication with the Vultr API
|
|
||||||
HTTPClient *http.Client
|
|
||||||
|
|
||||||
// User agent for HTTP client
|
|
||||||
UserAgent string
|
|
||||||
|
|
||||||
// Endpoint URL for API requests
|
|
||||||
Endpoint string
|
|
||||||
|
|
||||||
// API rate limitation, calls per duration
|
|
||||||
RateLimitation time.Duration
|
|
||||||
|
|
||||||
// Max. number of times to retry API calls
|
|
||||||
MaxRetries int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient creates new Vultr API client. Options are optional and can be nil.
|
|
||||||
func NewClient(apiKey string, options *Options) *Client {
|
|
||||||
userAgent := "vultr-go/" + Version
|
|
||||||
transport := &http.Transport{
|
|
||||||
TLSNextProto: make(map[string]func(string, *tls.Conn) http.RoundTripper),
|
|
||||||
}
|
|
||||||
client := http.DefaultClient
|
|
||||||
client.Transport = transport
|
|
||||||
endpoint, _ := url.Parse(DefaultEndpoint)
|
|
||||||
rate := 505 * time.Millisecond
|
|
||||||
attempts := 1
|
|
||||||
|
|
||||||
if options != nil {
|
|
||||||
if options.HTTPClient != nil {
|
|
||||||
client = options.HTTPClient
|
|
||||||
}
|
|
||||||
if options.UserAgent != "" {
|
|
||||||
userAgent = options.UserAgent
|
|
||||||
}
|
|
||||||
if options.Endpoint != "" {
|
|
||||||
endpoint, _ = url.Parse(options.Endpoint)
|
|
||||||
}
|
|
||||||
if options.RateLimitation != 0 {
|
|
||||||
rate = options.RateLimitation
|
|
||||||
}
|
|
||||||
if options.MaxRetries != 0 {
|
|
||||||
attempts = options.MaxRetries + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Client{
|
|
||||||
UserAgent: userAgent,
|
|
||||||
client: client,
|
|
||||||
Endpoint: endpoint,
|
|
||||||
APIKey: apiKey,
|
|
||||||
MaxAttempts: attempts,
|
|
||||||
bucket: ratelimit.NewBucket(rate, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func apiPath(path string) string {
|
|
||||||
return fmt.Sprintf("/%s/%s", APIVersion, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func apiKeyPath(path, apiKey string) string {
|
|
||||||
if strings.Contains(path, "?") {
|
|
||||||
return path + "&api_key=" + apiKey
|
|
||||||
}
|
|
||||||
return path + "?api_key=" + apiKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) get(path string, data interface{}) error {
|
|
||||||
req, err := c.newRequest("GET", apiPath(path), nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.do(req, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) post(path string, values url.Values, data interface{}) error {
|
|
||||||
req, err := c.newRequest("POST", apiPath(path), strings.NewReader(values.Encode()))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.do(req, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) newRequest(method string, path string, body io.Reader) (*http.Request, error) {
|
|
||||||
relPath, err := url.Parse(apiKeyPath(path, c.APIKey))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
url := c.Endpoint.ResolveReference(relPath)
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, url.String(), body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Add("User-Agent", c.UserAgent)
|
|
||||||
req.Header.Add("Accept", mediaType)
|
|
||||||
|
|
||||||
if req.Method == "POST" {
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
}
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) do(req *http.Request, data interface{}) error {
|
|
||||||
// Throttle http requests to avoid hitting Vultr's API rate-limit
|
|
||||||
c.bucket.Wait(1)
|
|
||||||
|
|
||||||
// Request body gets drained on each read so we
|
|
||||||
// need to save it's content for retrying requests
|
|
||||||
var err error
|
|
||||||
var requestBody []byte
|
|
||||||
if req.Body != nil {
|
|
||||||
requestBody, err = ioutil.ReadAll(req.Body)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error reading request body: %v", err)
|
|
||||||
}
|
|
||||||
req.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiError error
|
|
||||||
for tryCount := 1; tryCount <= c.MaxAttempts; tryCount++ {
|
|
||||||
// Restore request body to the original state
|
|
||||||
if requestBody != nil {
|
|
||||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
resp.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode == http.StatusOK {
|
|
||||||
if data != nil {
|
|
||||||
// avoid unmarshalling problem because Vultr API returns
|
|
||||||
// empty array instead of empty map when it shouldn't!
|
|
||||||
if string(body) == `[]` {
|
|
||||||
data = nil
|
|
||||||
} else {
|
|
||||||
if err := json.Unmarshal(body, data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
apiError = errors.New(string(body))
|
|
||||||
if !isCodeRetryable(resp.StatusCode) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
delay := backoffDuration(tryCount)
|
|
||||||
time.Sleep(delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiError
|
|
||||||
}
|
|
||||||
|
|
||||||
// backoffDuration returns the duration to wait before retrying the request.
|
|
||||||
// Duration is an exponential function of the retry count with a jitter of ~0-30%.
|
|
||||||
func backoffDuration(retryCount int) time.Duration {
|
|
||||||
// Upper limit of delay at ~1 minute
|
|
||||||
if retryCount > 7 {
|
|
||||||
retryCount = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
delay := (1 << uint(retryCount)) * (rand.Intn(150) + 500)
|
|
||||||
return time.Duration(delay) * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
// isCodeRetryable returns true if the given status code means that we should retry.
|
|
||||||
func isCodeRetryable(statusCode int) bool {
|
|
||||||
if _, ok := retryableStatusCodes[statusCode]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
150
vendor/github.com/JamesClonk/vultr/lib/dns.go
generated
vendored
150
vendor/github.com/JamesClonk/vultr/lib/dns.go
generated
vendored
|
@ -1,150 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNSDomain represents a DNS domain on Vultr
|
|
||||||
type DNSDomain struct {
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
Created string `json:"date_created"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type dnsdomains []DNSDomain
|
|
||||||
|
|
||||||
func (d dnsdomains) Len() int { return len(d) }
|
|
||||||
func (d dnsdomains) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
|
||||||
func (d dnsdomains) Less(i, j int) bool {
|
|
||||||
return strings.ToLower(d[i].Domain) < strings.ToLower(d[j].Domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DNSRecord represents a DNS record on Vultr
|
|
||||||
type DNSRecord struct {
|
|
||||||
RecordID int `json:"RECORDID"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Data string `json:"data"`
|
|
||||||
Priority int `json:"priority"`
|
|
||||||
TTL int `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type dnsrecords []DNSRecord
|
|
||||||
|
|
||||||
func (d dnsrecords) Len() int { return len(d) }
|
|
||||||
func (d dnsrecords) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
|
||||||
func (d dnsrecords) Less(i, j int) bool {
|
|
||||||
// sort order: type, data, name
|
|
||||||
if d[i].Type < d[j].Type {
|
|
||||||
return true
|
|
||||||
} else if d[i].Type > d[j].Type {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if d[i].Data < d[j].Data {
|
|
||||||
return true
|
|
||||||
} else if d[i].Data > d[j].Data {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return strings.ToLower(d[i].Name) < strings.ToLower(d[j].Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDNSDomains returns a list of available domains on Vultr account
|
|
||||||
func (c *Client) GetDNSDomains() (domains []DNSDomain, err error) {
|
|
||||||
if err := c.get(`dns/list`, &domains); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sort.Sort(dnsdomains(domains))
|
|
||||||
return domains, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDNSRecords returns a list of all DNS records of a particular domain
|
|
||||||
func (c *Client) GetDNSRecords(domain string) (records []DNSRecord, err error) {
|
|
||||||
if err := c.get(`dns/records?domain=`+domain, &records); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sort.Sort(dnsrecords(records))
|
|
||||||
return records, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateDNSDomain creates a new DNS domain name on Vultr
|
|
||||||
func (c *Client) CreateDNSDomain(domain, serverIP string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"domain": {domain},
|
|
||||||
"serverip": {serverIP},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`dns/create_domain`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDNSDomain deletes an existing DNS domain name
|
|
||||||
func (c *Client) DeleteDNSDomain(domain string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"domain": {domain},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`dns/delete_domain`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateDNSRecord creates a new DNS record
|
|
||||||
func (c *Client) CreateDNSRecord(domain, name, rtype, data string, priority, ttl int) error {
|
|
||||||
values := url.Values{
|
|
||||||
"domain": {domain},
|
|
||||||
"name": {name},
|
|
||||||
"type": {rtype},
|
|
||||||
"data": {data},
|
|
||||||
"priority": {fmt.Sprintf("%v", priority)},
|
|
||||||
"ttl": {fmt.Sprintf("%v", ttl)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`dns/create_record`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDNSRecord updates an existing DNS record
|
|
||||||
func (c *Client) UpdateDNSRecord(domain string, dnsrecord DNSRecord) error {
|
|
||||||
values := url.Values{
|
|
||||||
"domain": {domain},
|
|
||||||
"RECORDID": {fmt.Sprintf("%v", dnsrecord.RecordID)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if dnsrecord.Name != "" {
|
|
||||||
values.Add("name", dnsrecord.Name)
|
|
||||||
}
|
|
||||||
if dnsrecord.Data != "" {
|
|
||||||
values.Add("data", dnsrecord.Data)
|
|
||||||
}
|
|
||||||
if dnsrecord.Priority != 0 {
|
|
||||||
values.Add("priority", fmt.Sprintf("%v", dnsrecord.Priority))
|
|
||||||
}
|
|
||||||
if dnsrecord.TTL != 0 {
|
|
||||||
values.Add("ttl", fmt.Sprintf("%v", dnsrecord.TTL))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`dns/update_record`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDNSRecord deletes an existing DNS record
|
|
||||||
func (c *Client) DeleteDNSRecord(domain string, recordID int) error {
|
|
||||||
values := url.Values{
|
|
||||||
"domain": {domain},
|
|
||||||
"RECORDID": {fmt.Sprintf("%v", recordID)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`dns/delete_record`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
248
vendor/github.com/JamesClonk/vultr/lib/firewall.go
generated
vendored
248
vendor/github.com/JamesClonk/vultr/lib/firewall.go
generated
vendored
|
@ -1,248 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FirewallGroup represents a firewall group on Vultr
|
|
||||||
type FirewallGroup struct {
|
|
||||||
ID string `json:"FIREWALLGROUPID"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Created string `json:"date_created"`
|
|
||||||
Modified string `json:"date_modified"`
|
|
||||||
InstanceCount int `json:"instance_count"`
|
|
||||||
RuleCount int `json:"rule_count"`
|
|
||||||
MaxRuleCount int `json:"max_rule_count"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FirewallRule represents a firewall rule on Vultr
|
|
||||||
type FirewallRule struct {
|
|
||||||
RuleNumber int `json:"rulenumber"`
|
|
||||||
Action string `json:"action"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
Port string `json:"port"`
|
|
||||||
Network *net.IPNet
|
|
||||||
}
|
|
||||||
|
|
||||||
type firewallGroups []FirewallGroup
|
|
||||||
|
|
||||||
func (f firewallGroups) Len() int { return len(f) }
|
|
||||||
func (f firewallGroups) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
|
||||||
func (f firewallGroups) Less(i, j int) bool {
|
|
||||||
// sort order: description
|
|
||||||
return strings.ToLower(f[i].Description) < strings.ToLower(f[j].Description)
|
|
||||||
}
|
|
||||||
|
|
||||||
type firewallRules []FirewallRule
|
|
||||||
|
|
||||||
func (r firewallRules) Len() int { return len(r) }
|
|
||||||
func (r firewallRules) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
|
||||||
func (r firewallRules) Less(i, j int) bool {
|
|
||||||
// sort order: rule number
|
|
||||||
return r[i].RuleNumber < r[j].RuleNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaller on FirewallRule.
|
|
||||||
// This is needed because the Vultr API is inconsistent in it's JSON responses.
|
|
||||||
// Some fields can change type, from JSON number to JSON string and vice-versa.
|
|
||||||
func (r *FirewallRule) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
if r == nil {
|
|
||||||
*r = FirewallRule{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fields map[string]interface{}
|
|
||||||
if err := json.Unmarshal(data, &fields); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
value := fmt.Sprintf("%v", fields["rulenumber"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
number, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.RuleNumber = int(number)
|
|
||||||
|
|
||||||
value = fmt.Sprintf("%v", fields["subnet_size"])
|
|
||||||
if len(value) == 0 || value == "<nil>" {
|
|
||||||
value = "0"
|
|
||||||
}
|
|
||||||
subnetSize, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Action = fmt.Sprintf("%v", fields["action"])
|
|
||||||
r.Protocol = fmt.Sprintf("%v", fields["protocol"])
|
|
||||||
r.Port = fmt.Sprintf("%v", fields["port"])
|
|
||||||
subnet := fmt.Sprintf("%v", fields["subnet"])
|
|
||||||
|
|
||||||
if subnetSize > 0 && len(subnet) > 0 {
|
|
||||||
_, r.Network, err = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet, subnetSize))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to parse subnet from Vultr API")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, r.Network, _ = net.ParseCIDR("0.0.0.0/0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFirewallGroups returns a list of all available firewall groups on Vultr
|
|
||||||
func (c *Client) GetFirewallGroups() ([]FirewallGroup, error) {
|
|
||||||
var groupMap map[string]FirewallGroup
|
|
||||||
if err := c.get(`firewall/group_list`, &groupMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var groupList []FirewallGroup
|
|
||||||
for _, g := range groupMap {
|
|
||||||
groupList = append(groupList, g)
|
|
||||||
}
|
|
||||||
sort.Sort(firewallGroups(groupList))
|
|
||||||
return groupList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFirewallGroup returns the firewall group with given ID
|
|
||||||
func (c *Client) GetFirewallGroup(id string) (FirewallGroup, error) {
|
|
||||||
groups, err := c.GetFirewallGroups()
|
|
||||||
if err != nil {
|
|
||||||
return FirewallGroup{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, g := range groups {
|
|
||||||
if g.ID == id {
|
|
||||||
return g, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FirewallGroup{}, fmt.Errorf("Firewall group with ID %v not found", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFirewallGroup creates a new firewall group in Vultr account
|
|
||||||
func (c *Client) CreateFirewallGroup(description string) (string, error) {
|
|
||||||
values := url.Values{}
|
|
||||||
|
|
||||||
// Optional description
|
|
||||||
if len(description) > 0 {
|
|
||||||
values.Add("description", description)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result FirewallGroup
|
|
||||||
err := c.post(`firewall/group_create`, values, &result)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return result.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteFirewallGroup deletes an existing firewall group
|
|
||||||
func (c *Client) DeleteFirewallGroup(groupID string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"FIREWALLGROUPID": {groupID},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`firewall/group_delete`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFirewallGroupDescription sets the description of an existing firewall group
|
|
||||||
func (c *Client) SetFirewallGroupDescription(groupID, description string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"FIREWALLGROUPID": {groupID},
|
|
||||||
"description": {description},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`firewall/group_set_description`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFirewallRules returns a list of rules for the given firewall group
|
|
||||||
func (c *Client) GetFirewallRules(groupID string) ([]FirewallRule, error) {
|
|
||||||
var ruleMap map[string]FirewallRule
|
|
||||||
ipTypes := []string{"v4", "v6"}
|
|
||||||
for _, ipType := range ipTypes {
|
|
||||||
args := fmt.Sprintf("direction=in&FIREWALLGROUPID=%s&ip_type=%s",
|
|
||||||
groupID, ipType)
|
|
||||||
if err := c.get(`firewall/rule_list?`+args, &ruleMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ruleList []FirewallRule
|
|
||||||
for _, r := range ruleMap {
|
|
||||||
ruleList = append(ruleList, r)
|
|
||||||
}
|
|
||||||
sort.Sort(firewallRules(ruleList))
|
|
||||||
return ruleList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFirewallRule creates a new firewall rule in Vultr account.
|
|
||||||
// groupID is the ID of the firewall group to create the rule in
|
|
||||||
// protocol must be one of: "icmp", "tcp", "udp", "gre"
|
|
||||||
// port can be a port number or colon separated port range (TCP/UDP only)
|
|
||||||
func (c *Client) CreateFirewallRule(groupID, protocol, port string,
|
|
||||||
network *net.IPNet) (int, error) {
|
|
||||||
ip := network.IP.String()
|
|
||||||
maskBits, _ := network.Mask.Size()
|
|
||||||
if ip == "<nil>" {
|
|
||||||
return 0, fmt.Errorf("Invalid network")
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipType string
|
|
||||||
if network.IP.To4() != nil {
|
|
||||||
ipType = "v4"
|
|
||||||
} else {
|
|
||||||
ipType = "v6"
|
|
||||||
}
|
|
||||||
|
|
||||||
values := url.Values{
|
|
||||||
"FIREWALLGROUPID": {groupID},
|
|
||||||
// possible values: "in"
|
|
||||||
"direction": {"in"},
|
|
||||||
// possible values: "icmp", "tcp", "udp", "gre"
|
|
||||||
"protocol": {protocol},
|
|
||||||
// possible values: "v4", "v6"
|
|
||||||
"ip_type": {ipType},
|
|
||||||
// IP address representing a subnet
|
|
||||||
"subnet": {ip},
|
|
||||||
// IP prefix size in bits
|
|
||||||
"subnet_size": {fmt.Sprintf("%v", maskBits)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(port) > 0 {
|
|
||||||
values.Add("port", port)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result FirewallRule
|
|
||||||
err := c.post(`firewall/rule_create`, values, &result)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return result.RuleNumber, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteFirewallRule deletes an existing firewall rule
|
|
||||||
func (c *Client) DeleteFirewallRule(ruleNumber int, groupID string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"FIREWALLGROUPID": {groupID},
|
|
||||||
"rulenumber": {fmt.Sprintf("%v", ruleNumber)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`firewall/rule_delete`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
192
vendor/github.com/JamesClonk/vultr/lib/ip.go
generated
vendored
192
vendor/github.com/JamesClonk/vultr/lib/ip.go
generated
vendored
|
@ -1,192 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IPv4 information of a virtual machine
|
|
||||||
type IPv4 struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Netmask string `json:"netmask"`
|
|
||||||
Gateway string `json:"gateway"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
ReverseDNS string `json:"reverse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ipv4s []IPv4
|
|
||||||
|
|
||||||
func (s ipv4s) Len() int { return len(s) }
|
|
||||||
func (s ipv4s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s ipv4s) Less(i, j int) bool {
|
|
||||||
// sort order: type, ip
|
|
||||||
if s[i].Type < s[j].Type {
|
|
||||||
return true
|
|
||||||
} else if s[i].Type > s[j].Type {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return s[i].IP < s[j].IP
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPv6 information of a virtual machine
|
|
||||||
type IPv6 struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Network string `json:"network"`
|
|
||||||
NetworkSize string `json:"network_size"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ipv6s []IPv6
|
|
||||||
|
|
||||||
func (s ipv6s) Len() int { return len(s) }
|
|
||||||
func (s ipv6s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s ipv6s) Less(i, j int) bool {
|
|
||||||
// sort order: type, ip
|
|
||||||
if s[i].Type < s[j].Type {
|
|
||||||
return true
|
|
||||||
} else if s[i].Type > s[j].Type {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return s[i].IP < s[j].IP
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReverseDNSIPv6 information of a virtual machine
|
|
||||||
type ReverseDNSIPv6 struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
ReverseDNS string `json:"reverse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type reverseDNSIPv6s []ReverseDNSIPv6
|
|
||||||
|
|
||||||
func (s reverseDNSIPv6s) Len() int { return len(s) }
|
|
||||||
func (s reverseDNSIPv6s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s reverseDNSIPv6s) Less(i, j int) bool { return s[i].IP < s[j].IP }
|
|
||||||
|
|
||||||
// ListIPv4 lists the IPv4 information of a virtual machine
|
|
||||||
func (c *Client) ListIPv4(id string) (list []IPv4, err error) {
|
|
||||||
var ipMap map[string][]IPv4
|
|
||||||
if err := c.get(`server/list_ipv4?SUBID=`+id, &ipMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iplist := range ipMap {
|
|
||||||
for _, ip := range iplist {
|
|
||||||
list = append(list, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Sort(ipv4s(list))
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateIPv4 creates an IPv4 address and attaches it to a virtual machine
|
|
||||||
func (c *Client) CreateIPv4(id string, reboot bool) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"reboot": {fmt.Sprintf("%t", reboot)},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/create_ipv4`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteIPv4 deletes an IPv4 address and detaches it from a virtual machine
|
|
||||||
func (c *Client) DeleteIPv4(id, ip string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"ip": {ip},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/destroy_ipv4`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListIPv6 lists the IPv4 information of a virtual machine
|
|
||||||
func (c *Client) ListIPv6(id string) (list []IPv6, err error) {
|
|
||||||
var ipMap map[string][]IPv6
|
|
||||||
if err := c.get(`server/list_ipv6?SUBID=`+id, &ipMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iplist := range ipMap {
|
|
||||||
for _, ip := range iplist {
|
|
||||||
list = append(list, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Sort(ipv6s(list))
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListIPv6ReverseDNS lists the IPv6 reverse DNS entries of a virtual machine
|
|
||||||
func (c *Client) ListIPv6ReverseDNS(id string) (list []ReverseDNSIPv6, err error) {
|
|
||||||
var ipMap map[string][]ReverseDNSIPv6
|
|
||||||
if err := c.get(`server/reverse_list_ipv6?SUBID=`+id, &ipMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iplist := range ipMap {
|
|
||||||
for _, ip := range iplist {
|
|
||||||
list = append(list, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Sort(reverseDNSIPv6s(list))
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteIPv6ReverseDNS removes a reverse DNS entry for an IPv6 address of a virtual machine
|
|
||||||
func (c *Client) DeleteIPv6ReverseDNS(id string, ip string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"ip": {ip},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/reverse_delete_ipv6`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetIPv6ReverseDNS sets a reverse DNS entry for an IPv6 address of a virtual machine
|
|
||||||
func (c *Client) SetIPv6ReverseDNS(id, ip, entry string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"ip": {ip},
|
|
||||||
"entry": {entry},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/reverse_set_ipv6`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultIPv4ReverseDNS sets a reverse DNS entry for an IPv4 address of a virtual machine to the original setting
|
|
||||||
func (c *Client) DefaultIPv4ReverseDNS(id, ip string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"ip": {ip},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/reverse_default_ipv4`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetIPv4ReverseDNS sets a reverse DNS entry for an IPv4 address of a virtual machine
|
|
||||||
func (c *Client) SetIPv4ReverseDNS(id, ip, entry string) error {
|
|
||||||
values := url.Values{
|
|
||||||
"SUBID": {id},
|
|
||||||
"ip": {ip},
|
|
||||||
"entry": {entry},
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.post(`server/reverse_set_ipv4`, values, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
44
vendor/github.com/JamesClonk/vultr/lib/iso.go
generated
vendored
44
vendor/github.com/JamesClonk/vultr/lib/iso.go
generated
vendored
|
@ -1,44 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ISO image on Vultr
|
|
||||||
type ISO struct {
|
|
||||||
ID int `json:"ISOID"`
|
|
||||||
Created string `json:"date_created"`
|
|
||||||
Filename string `json:"filename"`
|
|
||||||
Size int `json:"size"`
|
|
||||||
MD5sum string `json:"md5sum"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type isos []ISO
|
|
||||||
|
|
||||||
func (s isos) Len() int { return len(s) }
|
|
||||||
func (s isos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s isos) Less(i, j int) bool {
|
|
||||||
// sort order: filename, created
|
|
||||||
if strings.ToLower(s[i].Filename) < strings.ToLower(s[j].Filename) {
|
|
||||||
return true
|
|
||||||
} else if strings.ToLower(s[i].Filename) > strings.ToLower(s[j].Filename) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return s[i].Created < s[j].Created
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetISO returns a list of all ISO images on Vultr account
|
|
||||||
func (c *Client) GetISO() ([]ISO, error) {
|
|
||||||
var isoMap map[string]ISO
|
|
||||||
if err := c.get(`iso/list`, &isoMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var isoList []ISO
|
|
||||||
for _, iso := range isoMap {
|
|
||||||
isoList = append(isoList, iso)
|
|
||||||
}
|
|
||||||
sort.Sort(isos(isoList))
|
|
||||||
return isoList, nil
|
|
||||||
}
|
|
37
vendor/github.com/JamesClonk/vultr/lib/os.go
generated
vendored
37
vendor/github.com/JamesClonk/vultr/lib/os.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OS image on Vultr
|
|
||||||
type OS struct {
|
|
||||||
ID int `json:"OSID"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Arch string `json:"arch"`
|
|
||||||
Family string `json:"family"`
|
|
||||||
Windows bool `json:"windows"`
|
|
||||||
Surcharge string `json:"surcharge"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type oses []OS
|
|
||||||
|
|
||||||
func (s oses) Len() int { return len(s) }
|
|
||||||
func (s oses) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
func (s oses) Less(i, j int) bool { return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name) }
|
|
||||||
|
|
||||||
// GetOS returns a list of all available operating systems on Vultr
|
|
||||||
func (c *Client) GetOS() ([]OS, error) {
|
|
||||||
var osMap map[string]OS
|
|
||||||
if err := c.get(`os/list`, &osMap); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var osList []OS
|
|
||||||
for _, os := range osMap {
|
|
||||||
osList = append(osList, os)
|
|
||||||
}
|
|
||||||
sort.Sort(oses(osList))
|
|
||||||
return osList, nil
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue