go mod vendor && go mod tidy
This commit is contained in:
parent
dcd21d37da
commit
2f97dc2933
114
go.mod
114
go.mod
|
@ -3,113 +3,71 @@ module github.com/hashicorp/packer
|
|||
require (
|
||||
github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1
|
||||
github.com/Azure/azure-sdk-for-go v17.3.1+incompatible
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||
github.com/Azure/go-autorest v10.12.0+incompatible
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4 // indirect
|
||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290
|
||||
github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect
|
||||
github.com/Jeffail/gabs v1.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.11 // indirect
|
||||
github.com/NYTimes/gziphandler v1.0.1 // indirect
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go v0.0.0-20180110055012-c2e73f942591
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
github.com/SAP/go-hdb v0.13.1 // indirect
|
||||
github.com/SermoDigital/jose v0.9.1 // indirect
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af // indirect
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f
|
||||
github.com/antchfx/xpath v0.0.0-20170728053731-b5c552e1acbd // indirect
|
||||
github.com/antchfx/xquery v0.0.0-20170730121040-eb8c3c172607 // indirect
|
||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6 // indirect
|
||||
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43
|
||||
github.com/armon/go-metrics v0.0.0-20180713145231-3c58d8115a78 // indirect
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.16.24
|
||||
github.com/bgentry/speakeasy v0.0.0-20150902231413-36e9cfdd6909 // indirect
|
||||
github.com/biogo/hts v0.0.0-20160420073057-50da7d4131a3
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/cenkalti/backoff v2.1.0+incompatible // indirect
|
||||
github.com/cheggaaa/pb v1.0.27
|
||||
github.com/circonus-labs/circonus-gometrics v2.2.5+incompatible // indirect
|
||||
github.com/circonus-labs/circonusllhist v0.1.3 // indirect
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect
|
||||
github.com/creack/goselect v0.0.0-20180210034346-528c74964609 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f // indirect
|
||||
github.com/denverdino/aliyungo v0.0.0-20190220033614-36e2ae938978
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/digitalocean/godo v1.7.3
|
||||
github.com/digitalocean/godo v1.11.1
|
||||
github.com/dnaeon/go-vcr v1.0.0 // indirect
|
||||
github.com/docker/docker v0.0.0-20170406124027-fa3e2d5ab9b5 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.3.3 // indirect
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20181210160733-61e0defebf22 // indirect
|
||||
github.com/docker/docker v0.0.0-20180422163414-57142e89befe // indirect
|
||||
github.com/dylanmei/iso8601 v0.1.0 // indirect
|
||||
github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/go-ini/ini v1.25.4
|
||||
github.com/go-ldap/ldap v2.5.1+incompatible // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||
github.com/go-test/deep v1.0.1 // indirect
|
||||
github.com/gocql/gocql v0.0.0-20181124151448-70385f88b28b // indirect
|
||||
github.com/gofrs/flock v0.7.0
|
||||
github.com/gogo/protobuf v1.2.0 // indirect
|
||||
github.com/gofrs/flock v0.7.1
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
||||
github.com/google/go-cmp v0.2.0
|
||||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
|
||||
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d
|
||||
github.com/google/uuid v1.0.0
|
||||
github.com/gophercloud/gophercloud v0.0.0-20180903124057-ea7289ebdf06
|
||||
github.com/gophercloud/utils v0.0.0-20190124192022-a5c25e7a53a6
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
|
||||
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777 // indirect
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
||||
github.com/hashicorp/consul v0.0.0-20180807174550-3e6313bebbf0
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce
|
||||
github.com/hashicorp/consul v1.4.0
|
||||
github.com/hashicorp/errwrap v1.0.0
|
||||
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0
|
||||
github.com/hashicorp/go-getter v1.2.0
|
||||
github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f // indirect
|
||||
github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa // indirect
|
||||
github.com/hashicorp/go-memdb v0.0.0-20181108192425-032f93b25bec // indirect
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c // indirect
|
||||
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79
|
||||
github.com/hashicorp/go-plugin v0.0.0-20181030172320-54b6ff97d818 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 // indirect
|
||||
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect
|
||||
github.com/hashicorp/go-uuid v0.0.0-20160329185618-73d19cdc2bf0
|
||||
github.com/hashicorp/go-uuid v1.0.1
|
||||
github.com/hashicorp/go-version v1.1.0
|
||||
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47 // indirect
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect
|
||||
github.com/hashicorp/memberlist v0.1.0 // indirect
|
||||
github.com/hashicorp/serf v0.0.0-20180530155958-984a73625de3 // indirect
|
||||
github.com/hashicorp/vault v0.0.0-20180724215049-b9adaf9c6959
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/serf v0.8.2 // indirect
|
||||
github.com/hashicorp/vault v1.1.0
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
|
||||
github.com/hetznercloud/hcloud-go v1.12.0
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775
|
||||
github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee // indirect
|
||||
github.com/joyent/triton-go v0.0.0-20180116165742-545edbe0d564
|
||||
github.com/jtolds/gls v4.2.1+incompatible // indirect
|
||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1
|
||||
github.com/keybase/go-crypto v0.0.0-20181127160227-255a5089e85a // indirect
|
||||
github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77 // indirect
|
||||
github.com/klauspost/cpuid v0.0.0-20160106104451-349c67577817 // indirect
|
||||
github.com/klauspost/crc32 v0.0.0-20160114101742-999f3125931f // indirect
|
||||
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
|
||||
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 // indirect
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 // indirect
|
||||
github.com/lib/pq v1.0.0 // indirect
|
||||
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c // indirect
|
||||
github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c // indirect
|
||||
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1 // indirect
|
||||
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
|
||||
github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939
|
||||
github.com/mattn/go-tty v0.0.0-20190402035014-76a2065f1a95
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007
|
||||
github.com/miekg/dns v1.1.1 // indirect
|
||||
github.com/mitchellh/cli v0.0.0-20170908181043-65fcae5817c8
|
||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||
github.com/mitchellh/cli v1.0.0
|
||||
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7
|
||||
github.com/mitchellh/go-homedir v1.0.0
|
||||
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
|
||||
|
@ -125,52 +83,36 @@ require (
|
|||
github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b
|
||||
github.com/onsi/ginkgo v1.7.0 // indirect
|
||||
github.com/onsi/gomega v1.4.3 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/runc v0.1.1 // indirect
|
||||
github.com/oracle/oci-go-sdk v1.8.0
|
||||
github.com/ory/dockertest v3.3.2+incompatible // indirect
|
||||
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pierrec/lz4 v0.0.0-20160112163551-383c0d87b5dd
|
||||
github.com/pierrec/xxHash v0.0.0-20160112165351-5a004441f897 // indirect
|
||||
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca
|
||||
github.com/posener/complete v0.0.0-20170908125245-88e59760adad
|
||||
github.com/posener/complete v1.1.1
|
||||
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible
|
||||
github.com/prometheus/client_golang v0.9.2 // indirect
|
||||
github.com/renstrom/fuzzysearch v0.0.0-20160331204855-2d205ac6ec17 // indirect
|
||||
github.com/rwtodd/Go.Sed v0.0.0-20170507045331-d6d5d585814e
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 // indirect
|
||||
github.com/satori/go.uuid v0.0.0-20170321230731-5bf94b69c6b6 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/scaleway/scaleway-cli v0.0.0-20180921094345-7b12c9699d70
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/sirupsen/logrus v0.0.0-20180315010703-90150a8ed11b // indirect
|
||||
github.com/sirupsen/logrus v1.2.0 // indirect
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181220135002-f1744d40d346
|
||||
github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9 // indirect
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect
|
||||
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1
|
||||
github.com/ulikunitz/xz v0.5.5
|
||||
github.com/vmware/govmomi v0.0.0-20170707011325-c2105a174311
|
||||
github.com/xanzy/go-cloudstack v2.4.1+incompatible
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f
|
||||
golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4
|
||||
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6
|
||||
google.golang.org/api v0.1.0
|
||||
google.golang.org/appengine v1.4.0 // indirect
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/h2non/gock.v1 v1.0.12 // indirect
|
||||
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516 // indirect
|
||||
gopkg.in/ldap.v2 v2.5.1 // indirect
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.1 // indirect
|
||||
gotest.tools v2.2.0+incompatible // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
)
|
||||
|
|
284
go.sum
284
go.sum
|
@ -1,4 +1,3 @@
|
|||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8=
|
||||
|
@ -12,8 +11,6 @@ github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1 h1:RMTyvS5bjvSWiUcfqfr/E2px
|
|||
github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1/go.mod h1:61apmbkVJH4kg+38ftT+/l0XxdUCVnHggqcOTqZRSEE=
|
||||
github.com/Azure/azure-sdk-for-go v17.3.1+incompatible h1:9Nzge8xxnYm5lVRkvTpG1odiDN0fYDorQwVEaVfg1+g=
|
||||
github.com/Azure/azure-sdk-for-go v17.3.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v10.12.0+incompatible h1:6YphwUK+oXbzvCc1fd5VrnxCekwzDkpA7gUEbci2MvI=
|
||||
github.com/Azure/go-autorest v10.12.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4 h1:pSm8mp0T2OH2CPmPDPtwHPr3VAQaOwVF/JbllOPP4xA=
|
||||
|
@ -21,22 +18,10 @@ github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzS
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290 h1:K9I21XUHNbYD3GNMmJBN0UKJCpdP+glftwNZ7Bo8kqY=
|
||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
|
||||
github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 h1:dmc/C8bpE5VkQn65PNbbyACDC8xw8Hpp/NEurdPmQDQ=
|
||||
github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E=
|
||||
github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/NYTimes/gziphandler v1.0.1 h1:iLrQrdwjDd52kHDA5op2UBJFjmOb9g+7scBan4RN8F0=
|
||||
github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go v0.0.0-20180110055012-c2e73f942591 h1:/P9HCl71+Eh6vDbKNyRu+rpIIR70UCZWNOGexVV3e6k=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go v0.0.0-20180110055012-c2e73f942591/go.mod h1:EHGzQGbwozJBj/4qj3WGrTJ0FqjgOTOxLQ0VNWvPn08=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/SAP/go-hdb v0.13.1 h1:BuZlUZtqbF/oVSQ8Vp+/+wOtcBLh55zwMV7XnvYcz8g=
|
||||
github.com/SAP/go-hdb v0.13.1/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0=
|
||||
github.com/SermoDigital/jose v0.9.1 h1:atYaHPD3lPICcbK1owly3aPm0iaJGSGPi0WD4vLznv8=
|
||||
github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
|
||||
github.com/Telmate/proxmox-api-go v0.0.0-20190410200643-f08824d5082d h1:igrCnHheXb+lZ1bW9Ths8JZZIjh9D4Vi/49JqiHE+cI=
|
||||
github.com/Telmate/proxmox-api-go v0.0.0-20190410200643-f08824d5082d/go.mod h1:OGWyIMJ87/k/GCz8CGiWB2HOXsOVDM6Lpe/nFPkC4IQ=
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
|
||||
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f h1:jI4DIE5Vf4oRaHfthB0oRhU+yuYuoOTurDzwAlskP00=
|
||||
|
@ -50,74 +35,47 @@ github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6 h1:uZuxRZCz65cG1o
|
|||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43 h1:ePCAQPf5tUc5IMcUvu6euhSGna7jzs7eiXtJXHig6Zc=
|
||||
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43/go.mod h1:S6puKjZ9ZeqUPBv2hEBnMZGcM2J6mOsDRQcmxkMAND0=
|
||||
github.com/armon/go-metrics v0.0.0-20180713145231-3c58d8115a78 h1:mdRSArcFLfW0VoL34LZAKSz6LkkK4jFxVx2xYavACMg=
|
||||
github.com/armon/go-metrics v0.0.0-20180713145231-3c58d8115a78/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7 h1:MBXhrxjNkjdqJysfNbKMMPFNXlz6EzpOnPcsoYBeD3E=
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
|
||||
github.com/aws/aws-sdk-go v1.16.24 h1:I/A3Hwbgs3IEAP6v1bFpHKXiT7wZDoToX9cb00nxZnM=
|
||||
github.com/aws/aws-sdk-go v1.16.24/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bgentry/speakeasy v0.0.0-20150902231413-36e9cfdd6909 h1:mUVWHQ4tjVv86uJhxSbYqwdz4o+Imcl6HoZtoaqC3zM=
|
||||
github.com/bgentry/speakeasy v0.0.0-20150902231413-36e9cfdd6909/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/biogo/hts v0.0.0-20160420073057-50da7d4131a3 h1:3b+p838vN4sc37brz9W2HDphtSwZFcXZwFLyzm5Vk28=
|
||||
github.com/biogo/hts v0.0.0-20160420073057-50da7d4131a3/go.mod h1:YOY5xnRf7Jz2SZCLSKgVfyqNzbRgyTznM3HyDqQMxcU=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/cenkalti/backoff v2.1.0+incompatible h1:FIRvWBZrzS4YC7NT5cOuZjexzFvIr+Dbi6aD1cZaNBk=
|
||||
github.com/cenkalti/backoff v2.1.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc=
|
||||
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/circonus-labs/circonus-gometrics v2.2.5+incompatible h1:KsuY3ogbxgVv3FNhbLUoT+SE9znoWEUIuChSIT4HukI=
|
||||
github.com/circonus-labs/circonus-gometrics v2.2.5+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/creack/goselect v0.0.0-20180210034346-528c74964609 h1:FSxXMd2wCHj6GqgBdo4UtVA9R2aieIDvSniepqyOppU=
|
||||
github.com/creack/goselect v0.0.0-20180210034346-528c74964609/go.mod h1:gHrIcH/9UZDn2qgeTUeW5K9eZsVYCH6/60J/FHysWyE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f h1:WH0w/R4Yoey+04HhFxqZ6VX6I0d7RMyw5aXQ9UTvQPs=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||
github.com/denverdino/aliyungo v0.0.0-20190220033614-36e2ae938978 h1:oyfbRmu7YnytN4bXhvJPY1HPgUL52j5AxtgGDU0bMVs=
|
||||
github.com/denverdino/aliyungo v0.0.0-20190220033614-36e2ae938978/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/digitalocean/godo v1.7.3 h1:0tFPilFBDsVSiAKF8hyzj/MAmRYxNc5MGhAiYZYVrpo=
|
||||
github.com/digitalocean/godo v1.7.3/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU=
|
||||
github.com/digitalocean/godo v1.11.1 h1:OsTh37YFKk+g6DnAOrkXJ9oDArTkRx5UTkBJ2EWAO38=
|
||||
github.com/digitalocean/godo v1.11.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU=
|
||||
github.com/dnaeon/go-vcr v1.0.0 h1:1QZ+ahihvRvppcJnFvuoHAdnZTf1PqKjO4Ftr1cfQTo=
|
||||
github.com/dnaeon/go-vcr v1.0.0/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/docker v0.0.0-20170406124027-fa3e2d5ab9b5 h1:DwY2bFs8p+xf2WaQewx2hnGdjYR5K4UAaxcNPyKkTek=
|
||||
github.com/docker/docker v0.0.0-20170406124027-fa3e2d5ab9b5/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20181210160733-61e0defebf22 h1:RqZJa9Ohzpyr5OADCKz/8t0vtdD2vczMdjqCbvTYz7o=
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20181210160733-61e0defebf22/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
|
||||
github.com/docker/docker v0.0.0-20180422163414-57142e89befe h1:VW8TnWi0CZgg7oCv0wH6evNwkzcJg/emnw4HrVIWws4=
|
||||
github.com/docker/docker v0.0.0-20180422163414-57142e89befe/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
|
||||
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
|
||||
github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08 h1:0bp6/GrNOrTDtSXe9YYGCwf8jp5Fb/b+4a6MTRm4qzY=
|
||||
github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
@ -125,19 +83,9 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
|||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo=
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-ldap/ldap v2.5.1+incompatible h1:Opaoft5zMW8IU/VRULB0eGMBQ9P5buRvCW6sFTRmMn8=
|
||||
github.com/go-ldap/ldap v2.5.1+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg=
|
||||
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/gocql/gocql v0.0.0-20181124151448-70385f88b28b h1:dnUw9Ih14dCKzbtZxm+pwQRYIb+9ypiwtZgsCQN4zmg=
|
||||
github.com/gocql/gocql v0.0.0-20181124151448-70385f88b28b/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gofrs/flock v0.7.0 h1:pGFUjl501gafK9HBt1VGL1KCOd/YhIooID+xgyJCf3g=
|
||||
github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
|
@ -145,12 +93,11 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||
|
@ -158,8 +105,7 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
|||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9 h1:JM174NTeGNJ2m/oLH3UOWOvWQQKd+BoL3hcSCUWFLt0=
|
||||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d h1:rXQlD9GXkjA/PQZhmEaF/8Pj/sJfdZJK7GJG0gkS8I0=
|
||||
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3 h1:siORttZ36U2R/WjiJuDz8znElWBiAlO9rVt+mqJt0Cc=
|
||||
|
@ -173,71 +119,55 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1
|
|||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777 h1:JIM+OacoOJRU30xpjMf8sulYqjr0ViA3WDrTX6j/yDI=
|
||||
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/consul v0.0.0-20180807174550-3e6313bebbf0 h1:vh/G7ew4mi/FcKNrRk4x1N1fWYzYB5/AaSHr9W+wrF4=
|
||||
github.com/hashicorp/consul v0.0.0-20180807174550-3e6313bebbf0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/consul v1.4.0 h1:PQTW4xCuAExEiSbhrsFsikzbW5gVBoi74BjUvYFyKHw=
|
||||
github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de h1:XDCSythtg8aWSRSO29uwhgh7b127fWr+m5SemqjSUL8=
|
||||
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-getter v1.2.0 h1:E05bVPilzyh2yXgT6srn7WEkfMZaH+LuX9tDJw/4kaE=
|
||||
github.com/hashicorp/go-getter v1.2.0/go.mod h1:/O1k/AizTN0QmfEKknCYGvICeyKUDqCYA8vvWtGWDeQ=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f h1:Yv9YzBlAETjy6AOX9eLBZ3nshNVRREgerT/3nvxlGho=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa h1:0nA8i+6Rwqaq9xlpmVxxTwk6rxiEhX+E6Wh4vPNHiS8=
|
||||
github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa/go.mod h1:6ij3Z20p+OhOkCSrA0gImAWoHYQRGbnlcuk6XYTiaRw=
|
||||
github.com/hashicorp/go-memdb v0.0.0-20181108192425-032f93b25bec h1:A1nDk9UOKWPTQh5YcCnbwNbqj23e5pggf4HxGBulhr8=
|
||||
github.com/hashicorp/go-memdb v0.0.0-20181108192425-032f93b25bec/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c h1:BTAbnbegUIMB6xmQCwWE8yRzbA4XSpnZY5hvRJC188I=
|
||||
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19 h1:gb61U/o4ZJ6TRYvZqJUKYidIhJOEAvNyVMesryROxAY=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79 h1:RKu7yAXZTaQsxj1K9GDsh+QVw0+Wu1SWHxtbFN0n+hE=
|
||||
github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79/go.mod h1:09jT3Y/OIsjTjQ2+3bkVNPDKqWcGIYYvjB2BEKVUdvc=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20181030172320-54b6ff97d818 h1:wA1XRGBHMdpio0gcKUtnmkwSIlCAG1qzpsr+iPyi3Y8=
|
||||
github.com/hashicorp/go-plugin v0.0.0-20181030172320-54b6ff97d818/go.mod h1:Ft7ju2vWzhO0ETMKUVo12XmXmII6eSUS4rsPTkY/siA=
|
||||
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 h1:qCv4319q2q7XKn0MQbi8p37hsJ+9Xo8e6yojA73JVxk=
|
||||
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.2 h1:AoISa4P4IsW0/m4T6St8Yw38gTl5GtBAgfkhYh1xAz4=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E=
|
||||
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg=
|
||||
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
|
||||
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
|
||||
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 h1:7YOlAIO2YWnJZkQp7B5eFykaIY7C9JndqAFQyVV5BhM=
|
||||
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-uuid v0.0.0-20160329185618-73d19cdc2bf0 h1:YnYV/qHLtjZmhFnWaSsNqVAUhxCuPKRe5wDGpOKYL/U=
|
||||
github.com/hashicorp/go-uuid v0.0.0-20160329185618-73d19cdc2bf0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47 h1:UnszMmmmm5vLwWzDjTFVIkfhvWF1NdrmChl8L2NUDCw=
|
||||
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno=
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/memberlist v0.1.0 h1:qSsCiC0WYD39lbSitKNt40e30uorm2Ss/d4JGU1hzH8=
|
||||
github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE=
|
||||
github.com/hashicorp/serf v0.0.0-20180530155958-984a73625de3 h1:NUr1hG6WO9sI1x8ofSimmpqfJ+rEHiHP/PLEA33rcfQ=
|
||||
github.com/hashicorp/serf v0.0.0-20180530155958-984a73625de3/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE=
|
||||
github.com/hashicorp/vault v0.0.0-20180724215049-b9adaf9c6959 h1:PyVs2CB7Hxgl1kU0tWAVpagLK3N+MC0eeyKmG+L5VPI=
|
||||
github.com/hashicorp/vault v0.0.0-20180724215049-b9adaf9c6959/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e h1:2Hwd2Yi0/qjAC6ujOu6WBVXAak9Snuw0LTYdZkqIdKM=
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20181106190520-2236f141171e/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE=
|
||||
github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hetznercloud/hcloud-go v1.12.0 h1:ugZO8a8ADekqSWi7xWlcs6pxr4QE0tw5VnyjXcL5n28=
|
||||
github.com/hetznercloud/hcloud-go v1.12.0/go.mod h1:g5pff0YNAZywQaivY/CmhUYFVp7oP0nu3MiODC2W4Hw=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775 h1:MIteIoIQ5nFoOmwEHPDsqng8d0dtKj3lCnQCwGvtxXc=
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20190122232013-cf38e8387775/go.mod h1:R9rU87RxxmcD3DkspW9JqGBXiJyg5MA+WNCtJrBtnXs=
|
||||
github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee h1:AQ/QmCk6x8ECPpf2pkPtA4lyncEEBbs8VFnVXPYKhIs=
|
||||
github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
|
@ -248,8 +178,6 @@ github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpR
|
|||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
|
||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/keybase/go-crypto v0.0.0-20181127160227-255a5089e85a h1:X/UFlwD2/UV0RCy+8ITi4DmxJwk83YUH7bXwkJIHHMo=
|
||||
github.com/keybase/go-crypto v0.0.0-20181127160227-255a5089e85a/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77 h1:rJnR80lkojFgjdg/oQPhbZoY8t8uM51XMz8DrJrjabk=
|
||||
github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
|
@ -259,6 +187,8 @@ github.com/klauspost/crc32 v0.0.0-20160114101742-999f3125931f h1:UD9YLTi2aBhdOOT
|
|||
github.com/klauspost/crc32 v0.0.0-20160114101742-999f3125931f/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec h1:PYqF3Tiz2W2Ag0ezyDhAobWDWlrFv7U+qct4spLeDBM=
|
||||
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q=
|
||||
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
|
@ -269,46 +199,39 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c h1:N7uWGS2fTwH/4BwxbHiJZNAFTSJ5yPU0emHsQWvkxEY=
|
||||
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c h1:FMUOnVGy8nWk1cvlMCAoftRItQGMxI0vzJ3dQjeZTCE=
|
||||
github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c/go.mod h1:mf8fjOu33zCqxUjuiU3I8S1lJMyEAlH+0F2+M5xl3hE=
|
||||
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1 h1:cLEbk5d4t8CDqmQtCMc2lk91cflxOrj31k9LTIabPoA=
|
||||
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
|
||||
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=
|
||||
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
|
||||
github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939 h1:cRFHA33ER97Xy5jmjS519OXCS/yE3AT3zdbQAg0Z53g=
|
||||
github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939/go.mod h1:CfZSN7zwz5gJiFhZJz49Uzk7mEBHIceWmbFmYx7Hf7E=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-tty v0.0.0-20190402035014-76a2065f1a95 h1:zyW7ieMaS0tXk1KgXxFgQ+HAMmxYpwe7MiAzE4C/rkE=
|
||||
github.com/mattn/go-tty v0.0.0-20190402035014-76a2065f1a95/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007 h1:xjZxmVDmDZoEsl2gV0qD0pyBH+wXmJIZd27wsNFphJk=
|
||||
github.com/mattn/go-tty v0.0.0-20190407112021-83fae09cc007/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.1 h1:DVkblRdiScEnEr0LR9nTnEQqHYycjkXW9bOjd+2EL2o=
|
||||
github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v0.0.0-20170908181043-65fcae5817c8 h1:ZPmOsqSxGDUqFp0ErYpJDIfaBRBGvQv0qDPr37kZBrk=
|
||||
github.com/mitchellh/cli v0.0.0-20170908181043-65fcae5817c8/go.mod h1:oGumspjLm2kTyiT1QMGpFqRlmxnKHfCvhZEVnx+5UeE=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7 h1:PXPMDtfqV+rZJshQHOiwUFqlqErXaAcuWy+/ZmyRfNc=
|
||||
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU=
|
||||
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=
|
||||
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
|
||||
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95 h1:aHWVygBsLb+Kls/35B3tevL1hvDxZ0UklPA0BmhqTEk=
|
||||
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/iochan v1.0.1-0.20190408094311-e9f5309a3061 h1:BSEloc+wp5WA/fu0jw5HBWOfoKLdvpqi38ZP22eNemg=
|
||||
github.com/mitchellh/iochan v1.0.1-0.20190408094311-e9f5309a3061/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc h1:5T6hzGUO5OrL6MdYXYoLQtRWJDDgjdlOVBn9mIqGY1g=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/panicwrap v0.0.0-20170106182340-fce601fe5557 h1:w1QuuAA2km2Hax+EPamrq5ZRBeaNv2vsjvgB4an0zoU=
|
||||
|
@ -327,8 +250,6 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE
|
|||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b h1:LGItPaClbzopugAomw5VFKnG3h1dUr9QW5KOU+m8gu0=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -336,57 +257,36 @@ github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
|||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/oracle/oci-go-sdk v1.8.0 h1:4SO45bKV0I3/Mn1os3ANDZmV0eSE5z5CLdSUIkxtyzs=
|
||||
github.com/oracle/oci-go-sdk v1.8.0/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
||||
github.com/ory/dockertest v3.3.2+incompatible h1:uO+NcwH6GuFof/Uz8yzjNi1g0sGT5SLAJbdBvD8bUYc=
|
||||
github.com/ory/dockertest v3.3.2+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a h1:A3QMuteviunoaY/8ex+RKFqwhcZJ/Cf3fCW3IwL2wx4=
|
||||
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pierrec/lz4 v0.0.0-20160112163551-383c0d87b5dd h1:0EXhZlgCFcAZjhD6f6yqIINBBBym9seHr6AkvAWUgN8=
|
||||
github.com/pierrec/lz4 v0.0.0-20160112163551-383c0d87b5dd/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/xxHash v0.0.0-20160112165351-5a004441f897 h1:jp3jc/PyyTrTKjJJ6rWnhTbmo7tGgBFyG9AL5FIrO1I=
|
||||
github.com/pierrec/xxHash v0.0.0-20160112165351-5a004441f897/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I=
|
||||
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e h1:+RHxT/gm0O3UF7nLJbdNzAmULvCFt4XfXHWzh3XI/zs=
|
||||
github.com/pkg/errors v0.0.0-20171216070316-e881fd58d78e/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca h1:k8gsErq3rkcbAyCnpOycQsbw88NjCHk7L3KfBZKhQDQ=
|
||||
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v0.0.0-20170908125245-88e59760adad h1:jTlrcNQXxCpT8NU0MG1aiUkfAiTlm+W6KPScysqjvdA=
|
||||
github.com/posener/complete v0.0.0-20170908125245-88e59760adad/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible h1:ZoVHH6voxW9Onzo6z2yLtocVoN6mBocyDoqoyAMHokE=
|
||||
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible/go.mod h1:T3/WrziK7fYH3C8ilAFAHe99R452/IzIG3YYkqaOFeQ=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/renstrom/fuzzysearch v0.0.0-20160331204855-2d205ac6ec17 h1:4qPms2txLWMLXKzqlnYSulKRS4cS9aYgPtAEpUelQok=
|
||||
github.com/renstrom/fuzzysearch v0.0.0-20160331204855-2d205ac6ec17/go.mod h1:SAEjPB4voP88qmWJXI7mA5m15uNlEnuHLx4Eu2mPGpQ=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/rwtodd/Go.Sed v0.0.0-20170507045331-d6d5d585814e h1:lN+IKs+Jb9uwDOMO4VJZzH9vOjjist0THR5s9akp+Ss=
|
||||
github.com/rwtodd/Go.Sed v0.0.0-20170507045331-d6d5d585814e/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/satori/go.uuid v0.0.0-20170321230731-5bf94b69c6b6 h1:7PFDlUz5/yGp8w21PuZGgEfN7ZF7OXvgAIDjwih82Gs=
|
||||
github.com/satori/go.uuid v0.0.0-20170321230731-5bf94b69c6b6/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/scaleway/scaleway-cli v0.0.0-20180921094345-7b12c9699d70 h1:DaqC32ZwOuO4ctgg9qAdKnlQxwFPkKmCOEqwSNwYy7c=
|
||||
github.com/scaleway/scaleway-cli v0.0.0-20180921094345-7b12c9699d70/go.mod h1:XjlXWPd6VONhsRSEuzGkV8mzRpH7ou1cdLV7IKJk96s=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
|
@ -414,23 +314,24 @@ github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1l
|
|||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v0.0.0-20180315010703-90150a8ed11b h1:m1cItYkpJSJ3ZKPEV/XKbZTcCaJHY1qF+R9GisLZ4kw=
|
||||
github.com/sirupsen/logrus v0.0.0-20180315010703-90150a8ed11b/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w=
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181220135002-f1744d40d346 h1:a014AaXz7AISMePv8xKRffUZZkr5z2XmSDf41gRV3+A=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181220135002-f1744d40d346/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
|
||||
github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9 h1:/Bsw4C+DEdqPjt8vAqaC9LAqpAQnaCQQqmolqq3S1T4=
|
||||
github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1 h1:U6ufy3mLDgg9RYupntOvAF7xCmNNquyKaYaaVHo1Nnk=
|
||||
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
|
||||
|
@ -443,14 +344,19 @@ go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938=
|
|||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -458,21 +364,26 @@ golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsq
|
|||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 h1:uESlIz09WIHT2I+pasSXcpLYqYK8wHcdCetU3VuMBJE=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06 h1:0oC8rFnE+74kEmuHZ46F6KHsMr5Gx2gUQPuNz28iQZM=
|
||||
golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6 h1:MXtOG7w2ND9qNCUZSDBGll/SpVIq7ftozR9I8/JGBHY=
|
||||
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
|
||||
|
@ -487,13 +398,11 @@ google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+
|
|||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
|
@ -504,36 +413,25 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE
|
|||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/h2non/gock.v1 v1.0.12 h1:o3JJqe+h7R9Ay6LtMeFrKz1WnokrJDrNpDQs9KGqVn8=
|
||||
gopkg.in/h2non/gock.v1 v1.0.12/go.mod h1:KHI4Z1sxDW6P4N3DfTWSEza07YpkQP7KJBfglRMEjKY=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516 h1:H6trpavCIuipdInWrab8l34Mf+GGVfphniHostMdMaQ=
|
||||
gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516/go.mod h1:d3R+NllX3X5e0zlG1Rful3uLvsGC/Q3OHut5464DEQw=
|
||||
gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
|
||||
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.1 h1:kb0VV7NuIojvRfzwslQeP3yArBqJHW9tOl4t38VS1jM=
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
|
@ -1,12 +0,0 @@
|
|||
# go-ansiterm
|
||||
|
||||
This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent.
|
||||
|
||||
For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position.
|
||||
|
||||
The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go).
|
||||
|
||||
See parser_test.go for examples exercising the state machine and generating appropriate function calls.
|
||||
|
||||
-----
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
@ -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
|
|
@ -1,7 +0,0 @@
|
|||
package ansiterm
|
||||
|
||||
type ansiContext struct {
|
||||
currentChar byte
|
||||
paramBuffer []byte
|
||||
interBuffer []byte
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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{}) {}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
before_script:
|
||||
- go get -u github.com/golang/lint/golint
|
||||
|
||||
go:
|
||||
- 1.10.x
|
||||
- master
|
||||
|
||||
script:
|
||||
- test -z "$(gofmt -s -l . | tee /dev/stderr)"
|
||||
- test -z "$(golint ./... | tee /dev/stderr)"
|
||||
- go vet ./...
|
||||
- go build -v ./...
|
||||
- go test -v ./...
|
|
@ -0,0 +1,16 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
|
||||
before_install:
|
||||
- go get -u github.com/ChrisTrenkamp/goxpath
|
||||
- go get -u github.com/ChrisTrenkamp/goxpath/cmd/goxpath
|
||||
- go get -u github.com/wadey/gocovmerge
|
||||
|
||||
script:
|
||||
- go list -f '{{if gt (len .TestGoFiles) 0}}"go test -covermode count -coverprofile {{.Name}}.coverprofile -coverpkg ./... {{.ImportPath}}"{{end}}' ./... | xargs -I {} bash -c {}
|
||||
- gocovmerge `ls *.coverprofile` > coverage.txt
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
0
vendor/github.com/ChrisTrenkamp/goxpath/coverage.sh
generated
vendored
Executable file → Normal file
0
vendor/github.com/ChrisTrenkamp/goxpath/coverage.sh
generated
vendored
Executable file → Normal file
|
@ -1,597 +0,0 @@
|
|||
package proxmox
|
||||
|
||||
// inspired by https://github.com/Telmate/vagrant-proxmox/blob/master/lib/vagrant-proxmox/proxmox/connection.rb
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TaskTimeout - default async task call timeout in seconds
|
||||
const TaskTimeout = 300
|
||||
|
||||
// TaskStatusCheckInterval - time between async checks in seconds
|
||||
const TaskStatusCheckInterval = 2
|
||||
|
||||
const exitStatusSuccess = "OK"
|
||||
|
||||
// Client - URL, user and password to specifc Proxmox node
|
||||
type Client struct {
|
||||
session *Session
|
||||
ApiUrl string
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
// VmRef - virtual machine ref parts
|
||||
// map[type:qemu node:proxmox1-xx id:qemu/132 diskread:5.57424738e+08 disk:0 netin:5.9297450593e+10 mem:3.3235968e+09 uptime:1.4567097e+07 vmid:132 template:0 maxcpu:2 netout:6.053310416e+09 maxdisk:3.4359738368e+10 maxmem:8.592031744e+09 diskwrite:1.49663619584e+12 status:running cpu:0.00386980694947209 name:appt-app1-dev.xxx.xx]
|
||||
type VmRef struct {
|
||||
vmId int
|
||||
node string
|
||||
vmType string
|
||||
}
|
||||
|
||||
func (vmr *VmRef) SetNode(node string) {
|
||||
vmr.node = node
|
||||
return
|
||||
}
|
||||
|
||||
func (vmr *VmRef) SetVmType(vmType string) {
|
||||
vmr.vmType = vmType
|
||||
return
|
||||
}
|
||||
|
||||
func (vmr *VmRef) VmId() int {
|
||||
return vmr.vmId
|
||||
}
|
||||
|
||||
func (vmr *VmRef) Node() string {
|
||||
return vmr.node
|
||||
}
|
||||
|
||||
func NewVmRef(vmId int) (vmr *VmRef) {
|
||||
vmr = &VmRef{vmId: vmId, node: "", vmType: ""}
|
||||
return
|
||||
}
|
||||
|
||||
func NewClient(apiUrl string, hclient *http.Client, tls *tls.Config) (client *Client, err error) {
|
||||
var sess *Session
|
||||
sess, err = NewSession(apiUrl, hclient, tls)
|
||||
if err == nil {
|
||||
client = &Client{session: sess, ApiUrl: apiUrl}
|
||||
}
|
||||
return client, err
|
||||
}
|
||||
|
||||
func (c *Client) Login(username string, password string) (err error) {
|
||||
c.Username = username
|
||||
c.Password = password
|
||||
return c.session.Login(username, password)
|
||||
}
|
||||
|
||||
func (c *Client) GetJsonRetryable(url string, data *map[string]interface{}, tries int) error {
|
||||
var statErr error
|
||||
for ii := 0; ii < tries; ii++ {
|
||||
_, statErr = c.session.GetJSON(url, nil, nil, data)
|
||||
if statErr == nil {
|
||||
return nil
|
||||
}
|
||||
// if statErr != io.ErrUnexpectedEOF { // don't give up on ErrUnexpectedEOF
|
||||
// return statErr
|
||||
// }
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
return statErr
|
||||
}
|
||||
|
||||
func (c *Client) GetNodeList() (list map[string]interface{}, err error) {
|
||||
err = c.GetJsonRetryable("/nodes", &list, 3)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) GetVmList() (list map[string]interface{}, err error) {
|
||||
err = c.GetJsonRetryable("/cluster/resources?type=vm", &list, 3)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) CheckVmRef(vmr *VmRef) (err error) {
|
||||
if vmr.node == "" || vmr.vmType == "" {
|
||||
_, err = c.GetVmInfo(vmr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) GetVmInfo(vmr *VmRef) (vmInfo map[string]interface{}, err error) {
|
||||
resp, err := c.GetVmList()
|
||||
vms := resp["data"].([]interface{})
|
||||
for vmii := range vms {
|
||||
vm := vms[vmii].(map[string]interface{})
|
||||
if int(vm["vmid"].(float64)) == vmr.vmId {
|
||||
vmInfo = vm
|
||||
vmr.node = vmInfo["node"].(string)
|
||||
vmr.vmType = vmInfo["type"].(string)
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil, errors.New(fmt.Sprintf("Vm '%d' not found", vmr.vmId))
|
||||
}
|
||||
|
||||
func (c *Client) GetVmRefByName(vmName string) (vmr *VmRef, err error) {
|
||||
resp, err := c.GetVmList()
|
||||
vms := resp["data"].([]interface{})
|
||||
for vmii := range vms {
|
||||
vm := vms[vmii].(map[string]interface{})
|
||||
if vm["name"] != nil && vm["name"].(string) == vmName {
|
||||
vmr = NewVmRef(int(vm["vmid"].(float64)))
|
||||
vmr.node = vm["node"].(string)
|
||||
vmr.vmType = vm["type"].(string)
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil, errors.New(fmt.Sprintf("Vm '%s' not found", vmName))
|
||||
}
|
||||
|
||||
func (c *Client) GetVmState(vmr *VmRef) (vmState map[string]interface{}, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data map[string]interface{}
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/status/current", vmr.node, vmr.vmType, vmr.vmId)
|
||||
err = c.GetJsonRetryable(url, &data, 3)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data["data"] == nil {
|
||||
return nil, errors.New("Vm STATE not readable")
|
||||
}
|
||||
vmState = data["data"].(map[string]interface{})
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) GetVmConfig(vmr *VmRef) (vmConfig map[string]interface{}, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data map[string]interface{}
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
|
||||
err = c.GetJsonRetryable(url, &data, 3)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data["data"] == nil {
|
||||
return nil, errors.New("Vm CONFIG not readable")
|
||||
}
|
||||
vmConfig = data["data"].(map[string]interface{})
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) GetVmSpiceProxy(vmr *VmRef) (vmSpiceProxy map[string]interface{}, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data map[string]interface{}
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/spiceproxy", vmr.node, vmr.vmType, vmr.vmId)
|
||||
_, err = c.session.PostJSON(url, nil, nil, nil, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data["data"] == nil {
|
||||
return nil, errors.New("Vm SpiceProxy not readable")
|
||||
}
|
||||
vmSpiceProxy = data["data"].(map[string]interface{})
|
||||
return
|
||||
}
|
||||
|
||||
type AgentNetworkInterface struct {
|
||||
MACAddress string
|
||||
IPAddresses []net.IP
|
||||
Name string
|
||||
Statistics map[string]int64
|
||||
}
|
||||
|
||||
func (a *AgentNetworkInterface) UnmarshalJSON(b []byte) error {
|
||||
var intermediate struct {
|
||||
HardwareAddress string `json:"hardware-address"`
|
||||
IPAddresses []struct {
|
||||
IPAddress string `json:"ip-address"`
|
||||
IPAddressType string `json:"ip-address-type"`
|
||||
Prefix int `json:"prefix"`
|
||||
} `json:"ip-addresses"`
|
||||
Name string `json:"name"`
|
||||
Statistics map[string]int64 `json:"statistics"`
|
||||
}
|
||||
err := json.Unmarshal(b, &intermediate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.IPAddresses = make([]net.IP, len(intermediate.IPAddresses))
|
||||
for idx, ip := range intermediate.IPAddresses {
|
||||
a.IPAddresses[idx] = net.ParseIP(ip.IPAddress)
|
||||
if a.IPAddresses[idx] == nil {
|
||||
return fmt.Errorf("Could not parse %s as IP", ip.IPAddress)
|
||||
}
|
||||
}
|
||||
a.MACAddress = intermediate.HardwareAddress
|
||||
a.Name = intermediate.Name
|
||||
a.Statistics = intermediate.Statistics
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) GetVmAgentNetworkInterfaces(vmr *VmRef) ([]AgentNetworkInterface, error) {
|
||||
var ifs []AgentNetworkInterface
|
||||
err := c.doAgentGet(vmr, "network-get-interfaces", &ifs)
|
||||
return ifs, err
|
||||
}
|
||||
|
||||
func (c *Client) doAgentGet(vmr *VmRef, command string, output interface{}) error {
|
||||
err := c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/agent/%s", vmr.node, vmr.vmType, vmr.vmId, command)
|
||||
resp, err := c.session.Get(url, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return TypedResponse(resp, output)
|
||||
}
|
||||
|
||||
func (c *Client) CreateTemplate(vmr *VmRef) error {
|
||||
err := c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/template", vmr.node, vmr.vmType, vmr.vmId)
|
||||
_, err = c.session.Post(url, nil, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) MonitorCmd(vmr *VmRef, command string) (monitorRes map[string]interface{}, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqbody := ParamsToBody(map[string]interface{}{"command": command})
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/monitor", vmr.node, vmr.vmType, vmr.vmId)
|
||||
resp, err := c.session.Post(url, nil, nil, &reqbody)
|
||||
monitorRes, err = ResponseJSON(resp)
|
||||
return
|
||||
}
|
||||
|
||||
// WaitForCompletion - poll the API for task completion
|
||||
func (c *Client) WaitForCompletion(taskResponse map[string]interface{}) (waitExitStatus string, err error) {
|
||||
if taskResponse["errors"] != nil {
|
||||
errJSON, _ := json.MarshalIndent(taskResponse["errors"], "", " ")
|
||||
return string(errJSON), errors.New("Error reponse")
|
||||
}
|
||||
if taskResponse["data"] == nil {
|
||||
return "", nil
|
||||
}
|
||||
waited := 0
|
||||
taskUpid := taskResponse["data"].(string)
|
||||
for waited < TaskTimeout {
|
||||
exitStatus, statErr := c.GetTaskExitstatus(taskUpid)
|
||||
if statErr != nil {
|
||||
if statErr != io.ErrUnexpectedEOF { // don't give up on ErrUnexpectedEOF
|
||||
return "", statErr
|
||||
}
|
||||
}
|
||||
if exitStatus != nil {
|
||||
waitExitStatus = exitStatus.(string)
|
||||
return
|
||||
}
|
||||
time.Sleep(TaskStatusCheckInterval * time.Second)
|
||||
waited = waited + TaskStatusCheckInterval
|
||||
}
|
||||
return "", errors.New("Wait timeout for:" + taskUpid)
|
||||
}
|
||||
|
||||
var rxTaskNode = regexp.MustCompile("UPID:(.*?):")
|
||||
|
||||
func (c *Client) GetTaskExitstatus(taskUpid string) (exitStatus interface{}, err error) {
|
||||
node := rxTaskNode.FindStringSubmatch(taskUpid)[1]
|
||||
url := fmt.Sprintf("/nodes/%s/tasks/%s/status", node, taskUpid)
|
||||
var data map[string]interface{}
|
||||
_, err = c.session.GetJSON(url, nil, nil, &data)
|
||||
if err == nil {
|
||||
exitStatus = data["data"].(map[string]interface{})["exitstatus"]
|
||||
}
|
||||
if exitStatus != nil && exitStatus != exitStatusSuccess {
|
||||
err = errors.New(exitStatus.(string))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) StatusChangeVm(vmr *VmRef, setStatus string) (exitStatus string, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/status/%s", vmr.node, vmr.vmType, vmr.vmId, setStatus)
|
||||
var taskResponse map[string]interface{}
|
||||
for i := 0; i < 3; i++ {
|
||||
_, err = c.session.PostJSON(url, nil, nil, nil, &taskResponse)
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
if exitStatus == "" {
|
||||
time.Sleep(TaskStatusCheckInterval * time.Second)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) StartVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "start")
|
||||
}
|
||||
|
||||
func (c *Client) StopVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "stop")
|
||||
}
|
||||
|
||||
func (c *Client) ShutdownVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "shutdown")
|
||||
}
|
||||
|
||||
func (c *Client) ResetVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "reset")
|
||||
}
|
||||
|
||||
func (c *Client) SuspendVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "suspend")
|
||||
}
|
||||
|
||||
func (c *Client) ResumeVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
return c.StatusChangeVm(vmr, "resume")
|
||||
}
|
||||
|
||||
func (c *Client) DeleteVm(vmr *VmRef) (exitStatus string, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d", vmr.node, vmr.vmType, vmr.vmId)
|
||||
var taskResponse map[string]interface{}
|
||||
_, err = c.session.RequestJSON("DELETE", url, nil, nil, nil, &taskResponse)
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) CreateQemuVm(node string, vmParams map[string]interface{}) (exitStatus string, err error) {
|
||||
// Create VM disks first to ensure disks names.
|
||||
createdDisks, createdDisksErr := c.createVMDisks(node, vmParams)
|
||||
if createdDisksErr != nil {
|
||||
return "", createdDisksErr
|
||||
}
|
||||
|
||||
// Then create the VM itself.
|
||||
reqbody := ParamsToBody(vmParams)
|
||||
url := fmt.Sprintf("/nodes/%s/qemu", node)
|
||||
var resp *http.Response
|
||||
resp, err = c.session.Post(url, nil, nil, &reqbody)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
exitStatus = string(b)
|
||||
return
|
||||
}
|
||||
|
||||
taskResponse, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
// Delete VM disks if the VM didn't create.
|
||||
if exitStatus != "OK" {
|
||||
deleteDisksErr := c.DeleteVMDisks(node, createdDisks)
|
||||
if deleteDisksErr != nil {
|
||||
return "", deleteDisksErr
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) CloneQemuVm(vmr *VmRef, vmParams map[string]interface{}) (exitStatus string, err error) {
|
||||
reqbody := ParamsToBody(vmParams)
|
||||
url := fmt.Sprintf("/nodes/%s/qemu/%d/clone", vmr.node, vmr.vmId)
|
||||
resp, err := c.session.Post(url, nil, nil, &reqbody)
|
||||
if err == nil {
|
||||
taskResponse, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) RollbackQemuVm(vmr *VmRef, snapshot string) (exitStatus string, err error) {
|
||||
err = c.CheckVmRef(vmr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/snapshot/%s/rollback", vmr.node, vmr.vmType, vmr.vmId, snapshot)
|
||||
var taskResponse map[string]interface{}
|
||||
_, err = c.session.PostJSON(url, nil, nil, nil, &taskResponse)
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
return
|
||||
}
|
||||
|
||||
// SetVmConfig - send config options
|
||||
func (c *Client) SetVmConfig(vmr *VmRef, vmParams map[string]interface{}) (exitStatus interface{}, err error) {
|
||||
reqbody := ParamsToBody(vmParams)
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/config", vmr.node, vmr.vmType, vmr.vmId)
|
||||
resp, err := c.session.Post(url, nil, nil, &reqbody)
|
||||
if err == nil {
|
||||
taskResponse, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) ResizeQemuDisk(vmr *VmRef, disk string, moreSizeGB int) (exitStatus interface{}, err error) {
|
||||
// PUT
|
||||
//disk:virtio0
|
||||
//size:+2G
|
||||
if disk == "" {
|
||||
disk = "virtio0"
|
||||
}
|
||||
size := fmt.Sprintf("+%dG", moreSizeGB)
|
||||
reqbody := ParamsToBody(map[string]interface{}{"disk": disk, "size": size})
|
||||
url := fmt.Sprintf("/nodes/%s/%s/%d/resize", vmr.node, vmr.vmType, vmr.vmId)
|
||||
resp, err := c.session.Put(url, nil, nil, &reqbody)
|
||||
if err == nil {
|
||||
taskResponse, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exitStatus, err = c.WaitForCompletion(taskResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetNextID - Get next free VMID
|
||||
func (c *Client) GetNextID(currentID int) (nextID int, err error) {
|
||||
var data map[string]interface{}
|
||||
var url string
|
||||
if currentID >= 100 {
|
||||
url = fmt.Sprintf("/cluster/nextid?vmid=%d", currentID)
|
||||
} else {
|
||||
url = "/cluster/nextid"
|
||||
}
|
||||
_, err = c.session.GetJSON(url, nil, nil, &data)
|
||||
if err == nil {
|
||||
if data["errors"] != nil {
|
||||
if currentID >= 100 {
|
||||
return c.GetNextID(currentID + 1)
|
||||
} else {
|
||||
return -1, errors.New("error using /cluster/nextid")
|
||||
}
|
||||
}
|
||||
nextID, err = strconv.Atoi(data["data"].(string))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CreateVMDisk - Create single disk for VM on host node.
|
||||
func (c *Client) CreateVMDisk(
|
||||
nodeName string,
|
||||
storageName string,
|
||||
fullDiskName string,
|
||||
diskParams map[string]interface{},
|
||||
) error {
|
||||
|
||||
reqbody := ParamsToBody(diskParams)
|
||||
url := fmt.Sprintf("/nodes/%s/storage/%s/content", nodeName, storageName)
|
||||
resp, err := c.session.Post(url, nil, nil, &reqbody)
|
||||
if err == nil {
|
||||
taskResponse, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if diskName, containsData := taskResponse["data"]; !containsData || diskName != fullDiskName {
|
||||
return errors.New(fmt.Sprintf("Cannot create VM disk %s", fullDiskName))
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createVMDisks - Make disks parameters and create all VM disks on host node.
|
||||
func (c *Client) createVMDisks(
|
||||
node string,
|
||||
vmParams map[string]interface{},
|
||||
) (disks []string, err error) {
|
||||
var createdDisks []string
|
||||
vmID := vmParams["vmid"].(int)
|
||||
for deviceName, deviceConf := range vmParams {
|
||||
rxStorageModels := `(ide|sata|scsi|virtio)\d+`
|
||||
if matched, _ := regexp.MatchString(rxStorageModels, deviceName); matched {
|
||||
deviceConfMap := ParseConf(deviceConf.(string), ",", "=")
|
||||
// This if condition to differentiate between `disk` and `cdrom`.
|
||||
if media, containsFile := deviceConfMap["media"]; containsFile && media == "disk" {
|
||||
fullDiskName := deviceConfMap["file"].(string)
|
||||
storageName, volumeName := getStorageAndVolumeName(fullDiskName, ":")
|
||||
diskParams := map[string]interface{}{
|
||||
"vmid": vmID,
|
||||
"filename": volumeName,
|
||||
"size": deviceConfMap["size"],
|
||||
}
|
||||
err := c.CreateVMDisk(node, storageName, fullDiskName, diskParams)
|
||||
if err != nil {
|
||||
return createdDisks, err
|
||||
} else {
|
||||
createdDisks = append(createdDisks, fullDiskName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return createdDisks, nil
|
||||
}
|
||||
|
||||
// DeleteVMDisks - Delete VM disks from host node.
|
||||
// By default the VM disks are deteled when the VM is deleted,
|
||||
// so mainly this is used to delete the disks in case VM creation didn't complete.
|
||||
func (c *Client) DeleteVMDisks(
|
||||
node string,
|
||||
disks []string,
|
||||
) error {
|
||||
for _, fullDiskName := range disks {
|
||||
storageName, volumeName := getStorageAndVolumeName(fullDiskName, ":")
|
||||
url := fmt.Sprintf("/nodes/%s/storage/%s/content/%s", node, storageName, volumeName)
|
||||
_, err := c.session.Post(url, nil, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getStorageAndVolumeName - Extract disk storage and disk volume, since disk name is saved
|
||||
// in Proxmox with its storage.
|
||||
func getStorageAndVolumeName(
|
||||
fullDiskName string,
|
||||
separator string,
|
||||
) (storageName string, diskName string) {
|
||||
storageAndVolumeName := strings.Split(fullDiskName, separator)
|
||||
storageName, volumeName := storageAndVolumeName[0], storageAndVolumeName[1]
|
||||
|
||||
// when disk type is dir, volumeName is `file=local:100/vm-100-disk-0.raw`
|
||||
re := regexp.MustCompile(`\d+/(?P<filename>\S+.\S+)`)
|
||||
match := re.FindStringSubmatch(volumeName)
|
||||
if len(match) == 2 {
|
||||
volumeName = match[1]
|
||||
}
|
||||
|
||||
return storageName, volumeName
|
||||
}
|
|
@ -1,706 +0,0 @@
|
|||
package proxmox
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
QemuDevices map[int]map[string]interface{}
|
||||
QemuDevice map[string]interface{}
|
||||
QemuDeviceParam []string
|
||||
)
|
||||
|
||||
// ConfigQemu - Proxmox API QEMU options
|
||||
type ConfigQemu struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"desc"`
|
||||
Onboot bool `json:"onboot"`
|
||||
Agent string `json:"agent"`
|
||||
Memory int `json:"memory"`
|
||||
QemuOs string `json:"os"`
|
||||
QemuCores int `json:"cores"`
|
||||
QemuSockets int `json:"sockets"`
|
||||
QemuIso string `json:"iso"`
|
||||
FullClone *int `json:"fullclone"`
|
||||
QemuDisks QemuDevices `json:"disk"`
|
||||
QemuNetworks QemuDevices `json:"network"`
|
||||
|
||||
// Deprecated single disk.
|
||||
DiskSize float64 `json:"diskGB"`
|
||||
Storage string `json:"storage"`
|
||||
StorageType string `json:"storageType"` // virtio|scsi (cloud-init defaults to scsi)
|
||||
|
||||
// Deprecated single nic.
|
||||
QemuNicModel string `json:"nic"`
|
||||
QemuBrige string `json:"bridge"`
|
||||
QemuVlanTag int `json:"vlan"`
|
||||
QemuMacAddr string `json:"mac"`
|
||||
|
||||
// cloud-init options
|
||||
CIuser string `json:"ciuser"`
|
||||
CIpassword string `json:"cipassword"`
|
||||
|
||||
Searchdomain string `json:"searchdomain"`
|
||||
Nameserver string `json:"nameserver"`
|
||||
Sshkeys string `json:"sshkeys"`
|
||||
|
||||
// arrays are hard, support 2 interfaces for now
|
||||
Ipconfig0 string `json:"ipconfig0"`
|
||||
Ipconfig1 string `json:"ipconfig1"`
|
||||
}
|
||||
|
||||
// CreateVm - Tell Proxmox API to make the VM
|
||||
func (config ConfigQemu) CreateVm(vmr *VmRef, client *Client) (err error) {
|
||||
if config.HasCloudInit() {
|
||||
return errors.New("Cloud-init parameters only supported on clones or updates")
|
||||
}
|
||||
vmr.SetVmType("qemu")
|
||||
|
||||
params := map[string]interface{}{
|
||||
"vmid": vmr.vmId,
|
||||
"name": config.Name,
|
||||
"onboot": config.Onboot,
|
||||
"agent": config.Agent,
|
||||
"ide2": config.QemuIso + ",media=cdrom",
|
||||
"ostype": config.QemuOs,
|
||||
"sockets": config.QemuSockets,
|
||||
"cores": config.QemuCores,
|
||||
"cpu": "host",
|
||||
"memory": config.Memory,
|
||||
"description": config.Description,
|
||||
}
|
||||
|
||||
// Create disks config.
|
||||
config.CreateQemuDisksParams(vmr.vmId, params, false)
|
||||
|
||||
// Create networks config.
|
||||
config.CreateQemuNetworksParams(vmr.vmId, params)
|
||||
|
||||
exitStatus, err := client.CreateQemuVm(vmr.node, params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating VM: %v, error status: %s (params: %v)", err, exitStatus, params)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HasCloudInit - are there cloud-init options?
|
||||
func (config ConfigQemu) HasCloudInit() bool {
|
||||
return config.CIuser != "" ||
|
||||
config.CIpassword != "" ||
|
||||
config.Searchdomain != "" ||
|
||||
config.Nameserver != "" ||
|
||||
config.Sshkeys != "" ||
|
||||
config.Ipconfig0 != "" ||
|
||||
config.Ipconfig1 != ""
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CloneVm
|
||||
Example: Request
|
||||
|
||||
nodes/proxmox1-xx/qemu/1012/clone
|
||||
|
||||
newid:145
|
||||
name:tf-clone1
|
||||
target:proxmox1-xx
|
||||
full:1
|
||||
storage:xxx
|
||||
|
||||
*/
|
||||
func (config ConfigQemu) CloneVm(sourceVmr *VmRef, vmr *VmRef, client *Client) (err error) {
|
||||
vmr.SetVmType("qemu")
|
||||
fullclone := "1"
|
||||
if config.FullClone != nil {
|
||||
fullclone = strconv.Itoa(*config.FullClone)
|
||||
}
|
||||
storage := config.Storage
|
||||
if disk0Storage, ok := config.QemuDisks[0]["storage"].(string); ok && len(disk0Storage) > 0 {
|
||||
storage = disk0Storage
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"newid": vmr.vmId,
|
||||
"target": vmr.node,
|
||||
"name": config.Name,
|
||||
"storage": storage,
|
||||
"full": fullclone,
|
||||
}
|
||||
_, err = client.CloneQemuVm(sourceVmr, params)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return config.UpdateConfig(vmr, client)
|
||||
}
|
||||
|
||||
func (config ConfigQemu) UpdateConfig(vmr *VmRef, client *Client) (err error) {
|
||||
configParams := map[string]interface{}{
|
||||
"name": config.Name,
|
||||
"description": config.Description,
|
||||
"onboot": config.Onboot,
|
||||
"agent": config.Agent,
|
||||
"sockets": config.QemuSockets,
|
||||
"cores": config.QemuCores,
|
||||
"memory": config.Memory,
|
||||
}
|
||||
|
||||
// Create disks config.
|
||||
config.CreateQemuDisksParams(vmr.vmId, configParams, true)
|
||||
|
||||
// Create networks config.
|
||||
config.CreateQemuNetworksParams(vmr.vmId, configParams)
|
||||
|
||||
// cloud-init options
|
||||
if config.CIuser != "" {
|
||||
configParams["ciuser"] = config.CIuser
|
||||
}
|
||||
if config.CIpassword != "" {
|
||||
configParams["cipassword"] = config.CIpassword
|
||||
}
|
||||
if config.Searchdomain != "" {
|
||||
configParams["searchdomain"] = config.Searchdomain
|
||||
}
|
||||
if config.Nameserver != "" {
|
||||
configParams["nameserver"] = config.Nameserver
|
||||
}
|
||||
if config.Sshkeys != "" {
|
||||
sshkeyEnc := url.PathEscape(config.Sshkeys + "\n")
|
||||
sshkeyEnc = strings.Replace(sshkeyEnc, "+", "%2B", -1)
|
||||
sshkeyEnc = strings.Replace(sshkeyEnc, "@", "%40", -1)
|
||||
sshkeyEnc = strings.Replace(sshkeyEnc, "=", "%3D", -1)
|
||||
configParams["sshkeys"] = sshkeyEnc
|
||||
}
|
||||
if config.Ipconfig0 != "" {
|
||||
configParams["ipconfig0"] = config.Ipconfig0
|
||||
}
|
||||
if config.Ipconfig1 != "" {
|
||||
configParams["ipconfig1"] = config.Ipconfig1
|
||||
}
|
||||
_, err = client.SetVmConfig(vmr, configParams)
|
||||
return err
|
||||
}
|
||||
|
||||
func NewConfigQemuFromJson(io io.Reader) (config *ConfigQemu, err error) {
|
||||
config = &ConfigQemu{QemuVlanTag: -1}
|
||||
err = json.NewDecoder(io).Decode(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
log.Println(config)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
rxIso = regexp.MustCompile(`(.*?),media`)
|
||||
rxDeviceID = regexp.MustCompile(`\d+`)
|
||||
rxDiskName = regexp.MustCompile(`(virtio|scsi)\d+`)
|
||||
rxDiskType = regexp.MustCompile(`\D+`)
|
||||
rxNicName = regexp.MustCompile(`net\d+`)
|
||||
)
|
||||
|
||||
func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err error) {
|
||||
var vmConfig map[string]interface{}
|
||||
for ii := 0; ii < 3; ii++ {
|
||||
vmConfig, err = client.GetVmConfig(vmr)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
// this can happen:
|
||||
// {"data":{"lock":"clone","digest":"eb54fb9d9f120ba0c3bdf694f73b10002c375c38","description":" qmclone temporary file\n"}})
|
||||
if vmConfig["lock"] == nil {
|
||||
break
|
||||
} else {
|
||||
time.Sleep(8 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
if vmConfig["lock"] != nil {
|
||||
return nil, errors.New("vm locked, could not obtain config")
|
||||
}
|
||||
|
||||
// vmConfig Sample: map[ cpu:host
|
||||
// net0:virtio=62:DF:XX:XX:XX:XX,bridge=vmbr0
|
||||
// ide2:local:iso/xxx-xx.iso,media=cdrom memory:2048
|
||||
// smbios1:uuid=8b3bf833-aad8-4545-xxx-xxxxxxx digest:aa6ce5xxxxx1b9ce33e4aaeff564d4 sockets:1
|
||||
// name:terraform-ubuntu1404-template bootdisk:virtio0
|
||||
// virtio0:ProxmoxxxxISCSI:vm-1014-disk-2,size=4G
|
||||
// description:Base image
|
||||
// cores:2 ostype:l26
|
||||
|
||||
name := ""
|
||||
if _, isSet := vmConfig["name"]; isSet {
|
||||
name = vmConfig["name"].(string)
|
||||
}
|
||||
description := ""
|
||||
if _, isSet := vmConfig["description"]; isSet {
|
||||
description = vmConfig["description"].(string)
|
||||
}
|
||||
onboot := true
|
||||
if _, isSet := vmConfig["onboot"]; isSet {
|
||||
onboot = Itob(int(vmConfig["onboot"].(float64)))
|
||||
}
|
||||
agent := "1"
|
||||
if _, isSet := vmConfig["agent"]; isSet {
|
||||
agent = vmConfig["agent"].(string)
|
||||
}
|
||||
ostype := "other"
|
||||
if _, isSet := vmConfig["ostype"]; isSet {
|
||||
ostype = vmConfig["ostype"].(string)
|
||||
}
|
||||
memory := 0.0
|
||||
if _, isSet := vmConfig["memory"]; isSet {
|
||||
memory = vmConfig["memory"].(float64)
|
||||
}
|
||||
cores := 1.0
|
||||
if _, isSet := vmConfig["cores"]; isSet {
|
||||
cores = vmConfig["cores"].(float64)
|
||||
}
|
||||
sockets := 1.0
|
||||
if _, isSet := vmConfig["sockets"]; isSet {
|
||||
sockets = vmConfig["sockets"].(float64)
|
||||
}
|
||||
config = &ConfigQemu{
|
||||
Name: name,
|
||||
Description: strings.TrimSpace(description),
|
||||
Onboot: onboot,
|
||||
Agent: agent,
|
||||
QemuOs: ostype,
|
||||
Memory: int(memory),
|
||||
QemuCores: int(cores),
|
||||
QemuSockets: int(sockets),
|
||||
QemuVlanTag: -1,
|
||||
QemuDisks: QemuDevices{},
|
||||
QemuNetworks: QemuDevices{},
|
||||
}
|
||||
|
||||
if vmConfig["ide2"] != nil {
|
||||
isoMatch := rxIso.FindStringSubmatch(vmConfig["ide2"].(string))
|
||||
config.QemuIso = isoMatch[1]
|
||||
}
|
||||
|
||||
if _, isSet := vmConfig["ciuser"]; isSet {
|
||||
config.CIuser = vmConfig["ciuser"].(string)
|
||||
}
|
||||
if _, isSet := vmConfig["cipassword"]; isSet {
|
||||
config.CIpassword = vmConfig["cipassword"].(string)
|
||||
}
|
||||
if _, isSet := vmConfig["searchdomain"]; isSet {
|
||||
config.Searchdomain = vmConfig["searchdomain"].(string)
|
||||
}
|
||||
if _, isSet := vmConfig["sshkeys"]; isSet {
|
||||
config.Sshkeys, _ = url.PathUnescape(vmConfig["sshkeys"].(string))
|
||||
}
|
||||
if _, isSet := vmConfig["ipconfig0"]; isSet {
|
||||
config.Ipconfig0 = vmConfig["ipconfig0"].(string)
|
||||
}
|
||||
if _, isSet := vmConfig["ipconfig1"]; isSet {
|
||||
config.Ipconfig1 = vmConfig["ipconfig1"].(string)
|
||||
}
|
||||
|
||||
// Add disks.
|
||||
diskNames := []string{}
|
||||
|
||||
for k, _ := range vmConfig {
|
||||
if diskName := rxDiskName.FindStringSubmatch(k); len(diskName) > 0 {
|
||||
diskNames = append(diskNames, diskName[0])
|
||||
}
|
||||
}
|
||||
|
||||
for _, diskName := range diskNames {
|
||||
diskConfStr := vmConfig[diskName]
|
||||
diskConfList := strings.Split(diskConfStr.(string), ",")
|
||||
|
||||
//
|
||||
id := rxDeviceID.FindStringSubmatch(diskName)
|
||||
diskID, _ := strconv.Atoi(id[0])
|
||||
diskType := rxDiskType.FindStringSubmatch(diskName)[0]
|
||||
storageName, fileName := ParseSubConf(diskConfList[0], ":")
|
||||
|
||||
//
|
||||
diskConfMap := QemuDevice{
|
||||
"type": diskType,
|
||||
"storage": storageName,
|
||||
"file": fileName,
|
||||
}
|
||||
|
||||
// Add rest of device config.
|
||||
diskConfMap.readDeviceConfig(diskConfList[1:])
|
||||
|
||||
// And device config to disks map.
|
||||
if len(diskConfMap) > 0 {
|
||||
config.QemuDisks[diskID] = diskConfMap
|
||||
}
|
||||
}
|
||||
|
||||
// Add networks.
|
||||
nicNameRe := regexp.MustCompile(`net\d+`)
|
||||
nicNames := []string{}
|
||||
|
||||
for k, _ := range vmConfig {
|
||||
if nicName := nicNameRe.FindStringSubmatch(k); len(nicName) > 0 {
|
||||
nicNames = append(nicNames, nicName[0])
|
||||
}
|
||||
}
|
||||
|
||||
for _, nicName := range nicNames {
|
||||
nicConfStr := vmConfig[nicName]
|
||||
nicConfList := strings.Split(nicConfStr.(string), ",")
|
||||
|
||||
//
|
||||
id := rxDeviceID.FindStringSubmatch(nicName)
|
||||
nicID, _ := strconv.Atoi(id[0])
|
||||
model, macaddr := ParseSubConf(nicConfList[0], "=")
|
||||
|
||||
// Add model and MAC address.
|
||||
nicConfMap := QemuDevice{
|
||||
"model": model,
|
||||
"macaddr": macaddr,
|
||||
}
|
||||
|
||||
// Add rest of device config.
|
||||
nicConfMap.readDeviceConfig(nicConfList[1:])
|
||||
|
||||
// And device config to networks.
|
||||
if len(nicConfMap) > 0 {
|
||||
config.QemuNetworks[nicID] = nicConfMap
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Useful waiting for ISO install to complete
|
||||
func WaitForShutdown(vmr *VmRef, client *Client) (err error) {
|
||||
for ii := 0; ii < 100; ii++ {
|
||||
vmState, err := client.GetVmState(vmr)
|
||||
if err != nil {
|
||||
log.Print("Wait error:")
|
||||
log.Println(err)
|
||||
} else if vmState["status"] == "stopped" {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
return errors.New("Not shutdown within wait time")
|
||||
}
|
||||
|
||||
// This is because proxmox create/config API won't let us make usernet devices
|
||||
func SshForwardUsernet(vmr *VmRef, client *Client) (sshPort string, err error) {
|
||||
vmState, err := client.GetVmState(vmr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if vmState["status"] == "stopped" {
|
||||
return "", errors.New("VM must be running first")
|
||||
}
|
||||
sshPort = strconv.Itoa(vmr.VmId() + 22000)
|
||||
_, err = client.MonitorCmd(vmr, "netdev_add user,id=net1,hostfwd=tcp::"+sshPort+"-:22")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = client.MonitorCmd(vmr, "device_add virtio-net-pci,id=net1,netdev=net1,addr=0x13")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// device_del net1
|
||||
// netdev_del net1
|
||||
func RemoveSshForwardUsernet(vmr *VmRef, client *Client) (err error) {
|
||||
vmState, err := client.GetVmState(vmr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if vmState["status"] == "stopped" {
|
||||
return errors.New("VM must be running first")
|
||||
}
|
||||
_, err = client.MonitorCmd(vmr, "device_del net1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = client.MonitorCmd(vmr, "netdev_del net1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MaxVmId(client *Client) (max int, err error) {
|
||||
resp, err := client.GetVmList()
|
||||
vms := resp["data"].([]interface{})
|
||||
max = 0
|
||||
for vmii := range vms {
|
||||
vm := vms[vmii].(map[string]interface{})
|
||||
vmid := int(vm["vmid"].(float64))
|
||||
if vmid > max {
|
||||
max = vmid
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SendKeysString(vmr *VmRef, client *Client, keys string) (err error) {
|
||||
vmState, err := client.GetVmState(vmr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if vmState["status"] == "stopped" {
|
||||
return errors.New("VM must be running first")
|
||||
}
|
||||
for _, r := range keys {
|
||||
c := string(r)
|
||||
lower := strings.ToLower(c)
|
||||
if c != lower {
|
||||
c = "shift-" + lower
|
||||
} else {
|
||||
switch c {
|
||||
case "!":
|
||||
c = "shift-1"
|
||||
case "@":
|
||||
c = "shift-2"
|
||||
case "#":
|
||||
c = "shift-3"
|
||||
case "$":
|
||||
c = "shift-4"
|
||||
case "%%":
|
||||
c = "shift-5"
|
||||
case "^":
|
||||
c = "shift-6"
|
||||
case "&":
|
||||
c = "shift-7"
|
||||
case "*":
|
||||
c = "shift-8"
|
||||
case "(":
|
||||
c = "shift-9"
|
||||
case ")":
|
||||
c = "shift-0"
|
||||
case "_":
|
||||
c = "shift-minus"
|
||||
case "+":
|
||||
c = "shift-equal"
|
||||
case " ":
|
||||
c = "spc"
|
||||
case "/":
|
||||
c = "slash"
|
||||
case "\\":
|
||||
c = "backslash"
|
||||
case ",":
|
||||
c = "comma"
|
||||
case "-":
|
||||
c = "minus"
|
||||
case "=":
|
||||
c = "equal"
|
||||
case ".":
|
||||
c = "dot"
|
||||
case "?":
|
||||
c = "shift-slash"
|
||||
}
|
||||
}
|
||||
_, err = client.MonitorCmd(vmr, "sendkey "+c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(100)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create parameters for each Nic device.
|
||||
func (c ConfigQemu) CreateQemuNetworksParams(vmID int, params map[string]interface{}) error {
|
||||
|
||||
// For backward compatibility.
|
||||
if len(c.QemuNetworks) == 0 && len(c.QemuNicModel) > 0 {
|
||||
deprecatedStyleMap := QemuDevice{
|
||||
"model": c.QemuNicModel,
|
||||
"bridge": c.QemuBrige,
|
||||
"macaddr": c.QemuMacAddr,
|
||||
}
|
||||
|
||||
if c.QemuVlanTag > 0 {
|
||||
deprecatedStyleMap["tag"] = strconv.Itoa(c.QemuVlanTag)
|
||||
}
|
||||
|
||||
c.QemuNetworks[0] = deprecatedStyleMap
|
||||
}
|
||||
|
||||
// For new style with multi net device.
|
||||
for nicID, nicConfMap := range c.QemuNetworks {
|
||||
|
||||
nicConfParam := QemuDeviceParam{}
|
||||
|
||||
// Set Nic name.
|
||||
qemuNicName := "net" + strconv.Itoa(nicID)
|
||||
|
||||
// Set Mac address.
|
||||
if nicConfMap["macaddr"] == nil || nicConfMap["macaddr"].(string) == "" {
|
||||
// Generate Mac based on VmID and NicID so it will be the same always.
|
||||
macaddr := make(net.HardwareAddr, 6)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
rand.Read(macaddr)
|
||||
macaddr[0] = (macaddr[0] | 2) & 0xfe // fix from github issue #18
|
||||
macAddrUppr := strings.ToUpper(fmt.Sprintf("%v", macaddr))
|
||||
// use model=mac format for older proxmox compatability
|
||||
macAddr := fmt.Sprintf("%v=%v", nicConfMap["model"], macAddrUppr)
|
||||
|
||||
// Add Mac to source map so it will be returned. (useful for some use case like Terraform)
|
||||
nicConfMap["macaddr"] = macAddrUppr
|
||||
// and also add it to the parameters which will be sent to Proxmox API.
|
||||
nicConfParam = append(nicConfParam, macAddr)
|
||||
} else {
|
||||
macAddr := fmt.Sprintf("%v=%v", nicConfMap["model"], nicConfMap["macaddr"].(string))
|
||||
nicConfParam = append(nicConfParam, macAddr)
|
||||
}
|
||||
|
||||
// Set bridge if not nat.
|
||||
if nicConfMap["bridge"].(string) != "nat" {
|
||||
bridge := fmt.Sprintf("bridge=%v", nicConfMap["bridge"])
|
||||
nicConfParam = append(nicConfParam, bridge)
|
||||
}
|
||||
|
||||
// Keys that are not used as real/direct conf.
|
||||
ignoredKeys := []string{"id", "bridge", "macaddr", "model"}
|
||||
|
||||
// Rest of config.
|
||||
nicConfParam = nicConfParam.createDeviceParam(nicConfMap, ignoredKeys)
|
||||
|
||||
// Add nic to Qemu prams.
|
||||
params[qemuNicName] = strings.Join(nicConfParam, ",")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create parameters for each disk.
|
||||
func (c ConfigQemu) CreateQemuDisksParams(
|
||||
vmID int,
|
||||
params map[string]interface{},
|
||||
cloned bool,
|
||||
) error {
|
||||
|
||||
// For backward compatibility.
|
||||
if len(c.QemuDisks) == 0 && len(c.Storage) > 0 {
|
||||
|
||||
dType := c.StorageType
|
||||
if dType == "" {
|
||||
if c.HasCloudInit() {
|
||||
dType = "scsi"
|
||||
} else {
|
||||
dType = "virtio"
|
||||
}
|
||||
}
|
||||
deprecatedStyleMap := QemuDevice{
|
||||
"type": dType,
|
||||
"storage": c.Storage,
|
||||
"size": c.DiskSize,
|
||||
"storage_type": "lvm", // default old style
|
||||
"cache": "none", // default old value
|
||||
}
|
||||
|
||||
c.QemuDisks[0] = deprecatedStyleMap
|
||||
}
|
||||
|
||||
// For new style with multi disk device.
|
||||
for diskID, diskConfMap := range c.QemuDisks {
|
||||
|
||||
// skip the first disk for clones (may not always be right, but a template probably has at least 1 disk)
|
||||
if diskID == 0 && cloned {
|
||||
continue
|
||||
}
|
||||
diskConfParam := QemuDeviceParam{
|
||||
"media=disk",
|
||||
}
|
||||
|
||||
// Device name.
|
||||
deviceType := diskConfMap["type"].(string)
|
||||
qemuDiskName := deviceType + strconv.Itoa(diskID)
|
||||
|
||||
// Set disk storage.
|
||||
// Disk size.
|
||||
diskSizeGB := fmt.Sprintf("size=%v", diskConfMap["size"])
|
||||
diskConfParam = append(diskConfParam, diskSizeGB)
|
||||
|
||||
// Disk name.
|
||||
var diskFile string
|
||||
// Currently ZFS local, LVM, and Directory are considered.
|
||||
// Other formats are not verified, but could be added if they're needed.
|
||||
rxStorageTypes := `(zfspool|lvm)`
|
||||
storageType := diskConfMap["storage_type"].(string)
|
||||
if matched, _ := regexp.MatchString(rxStorageTypes, storageType); matched {
|
||||
diskFile = fmt.Sprintf("file=%v:vm-%v-disk-%v", diskConfMap["storage"], vmID, diskID)
|
||||
} else {
|
||||
diskFile = fmt.Sprintf("file=%v:%v/vm-%v-disk-%v.%v", diskConfMap["storage"], vmID, vmID, diskID, diskConfMap["format"])
|
||||
}
|
||||
diskConfParam = append(diskConfParam, diskFile)
|
||||
|
||||
// Set cache if not none (default).
|
||||
if diskConfMap["cache"].(string) != "none" {
|
||||
diskCache := fmt.Sprintf("cache=%v", diskConfMap["cache"])
|
||||
diskConfParam = append(diskConfParam, diskCache)
|
||||
}
|
||||
|
||||
// Keys that are not used as real/direct conf.
|
||||
ignoredKeys := []string{"id", "type", "storage", "storage_type", "size", "cache"}
|
||||
|
||||
// Rest of config.
|
||||
diskConfParam = diskConfParam.createDeviceParam(diskConfMap, ignoredKeys)
|
||||
|
||||
// Add back to Qemu prams.
|
||||
params[qemuDiskName] = strings.Join(diskConfParam, ",")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create the parameters for each device that will be sent to Proxmox API.
|
||||
func (p QemuDeviceParam) createDeviceParam(
|
||||
deviceConfMap QemuDevice,
|
||||
ignoredKeys []string,
|
||||
) QemuDeviceParam {
|
||||
|
||||
for key, value := range deviceConfMap {
|
||||
if ignored := inArray(ignoredKeys, key); !ignored {
|
||||
var confValue interface{}
|
||||
if bValue, ok := value.(bool); ok && bValue {
|
||||
confValue = "1"
|
||||
} else if sValue, ok := value.(string); ok && len(sValue) > 0 {
|
||||
confValue = sValue
|
||||
} else if iValue, ok := value.(int); ok && iValue > 0 {
|
||||
confValue = iValue
|
||||
}
|
||||
if confValue != nil {
|
||||
deviceConf := fmt.Sprintf("%v=%v", key, confValue)
|
||||
p = append(p, deviceConf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// readDeviceConfig - get standard sub-conf strings where `key=value` and update conf map.
|
||||
func (confMap QemuDevice) readDeviceConfig(confList []string) error {
|
||||
// Add device config.
|
||||
for _, conf := range confList {
|
||||
key, value := ParseSubConf(conf, "=")
|
||||
confMap[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c ConfigQemu) String() string {
|
||||
jsConf, _ := json.Marshal(c)
|
||||
return string(jsConf)
|
||||
}
|
|
@ -1,319 +0,0 @@
|
|||
package proxmox
|
||||
|
||||
// inspired by https://github.com/openstack/golang-client/blob/master/openstack/session.go
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var Debug = new(bool)
|
||||
|
||||
type Response struct {
|
||||
Resp *http.Response
|
||||
Body []byte
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
httpClient *http.Client
|
||||
ApiUrl string
|
||||
AuthTicket string
|
||||
CsrfToken string
|
||||
Headers http.Header
|
||||
}
|
||||
|
||||
func NewSession(apiUrl string, hclient *http.Client, tls *tls.Config) (session *Session, err error) {
|
||||
if hclient == nil {
|
||||
// Only build a transport if we're also building the client
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: tls,
|
||||
DisableCompression: true,
|
||||
}
|
||||
hclient = &http.Client{Transport: tr}
|
||||
}
|
||||
session = &Session{
|
||||
httpClient: hclient,
|
||||
ApiUrl: apiUrl,
|
||||
AuthTicket: "",
|
||||
CsrfToken: "",
|
||||
Headers: http.Header{},
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func ParamsToBody(params map[string]interface{}) (body []byte) {
|
||||
vals := url.Values{}
|
||||
for k, intrV := range params {
|
||||
var v string
|
||||
switch intrV.(type) {
|
||||
// Convert true/false bool to 1/0 string where Proxmox API can understand it.
|
||||
case bool:
|
||||
if intrV.(bool) {
|
||||
v = "1"
|
||||
} else {
|
||||
v = "0"
|
||||
}
|
||||
default:
|
||||
v = fmt.Sprintf("%v", intrV)
|
||||
}
|
||||
vals.Set(k, v)
|
||||
}
|
||||
body = bytes.NewBufferString(vals.Encode()).Bytes()
|
||||
return
|
||||
}
|
||||
|
||||
func decodeResponse(resp *http.Response, v interface{}) error {
|
||||
if resp.Body == nil {
|
||||
return nil
|
||||
}
|
||||
rbody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading response body: %s", err)
|
||||
}
|
||||
if err = json.Unmarshal(rbody, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResponseJSON(resp *http.Response) (jbody map[string]interface{}, err error) {
|
||||
err = decodeResponse(resp, &jbody)
|
||||
return jbody, err
|
||||
}
|
||||
|
||||
func TypedResponse(resp *http.Response, v interface{}) error {
|
||||
var intermediate struct {
|
||||
Data struct {
|
||||
Result json.RawMessage `json:"result"`
|
||||
} `json:"data"`
|
||||
}
|
||||
err := decodeResponse(resp, &intermediate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading response envelope: %v", err)
|
||||
}
|
||||
if err = json.Unmarshal(intermediate.Data.Result, v); err != nil {
|
||||
return fmt.Errorf("error unmarshalling result %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) Login(username string, password string) (err error) {
|
||||
reqbody := ParamsToBody(map[string]interface{}{"username": username, "password": password})
|
||||
olddebug := *Debug
|
||||
*Debug = false // don't share passwords in debug log
|
||||
resp, err := s.Post("/access/ticket", nil, nil, &reqbody)
|
||||
*Debug = olddebug
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp == nil {
|
||||
return errors.New("Login error reading response")
|
||||
}
|
||||
dr, _ := httputil.DumpResponse(resp, true)
|
||||
jbody, err := ResponseJSON(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if jbody == nil || jbody["data"] == nil {
|
||||
return fmt.Errorf("Invalid login response:\n-----\n%s\n-----", dr)
|
||||
}
|
||||
dat := jbody["data"].(map[string]interface{})
|
||||
s.AuthTicket = dat["ticket"].(string)
|
||||
s.CsrfToken = dat["CSRFPreventionToken"].(string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) NewRequest(method, url string, headers *http.Header, body io.Reader) (req *http.Request, err error) {
|
||||
req, err = http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if headers != nil {
|
||||
req.Header = *headers
|
||||
}
|
||||
if s.AuthTicket != "" {
|
||||
req.Header.Add("Cookie", "PVEAuthCookie="+s.AuthTicket)
|
||||
req.Header.Add("CSRFPreventionToken", s.CsrfToken)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Session) Do(req *http.Request) (*http.Response, error) {
|
||||
// Add session headers
|
||||
for k := range s.Headers {
|
||||
req.Header.Set(k, s.Headers.Get(k))
|
||||
}
|
||||
|
||||
if *Debug {
|
||||
d, _ := httputil.DumpRequestOut(req, true)
|
||||
log.Printf(">>>>>>>>>> REQUEST:\n", string(d))
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if *Debug {
|
||||
dr, _ := httputil.DumpResponse(resp, true)
|
||||
log.Printf("<<<<<<<<<< RESULT:\n", string(dr))
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||
return resp, errors.New(resp.Status)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Perform a simple get to an endpoint
|
||||
func (s *Session) Request(
|
||||
method string,
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
body *[]byte,
|
||||
) (resp *http.Response, err error) {
|
||||
// add params to url here
|
||||
url = s.ApiUrl + url
|
||||
if params != nil {
|
||||
url = url + "?" + params.Encode()
|
||||
}
|
||||
|
||||
// Get the body if one is present
|
||||
var buf io.Reader
|
||||
if body != nil {
|
||||
buf = bytes.NewReader(*body)
|
||||
}
|
||||
|
||||
req, err := s.NewRequest(method, url, headers, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
return s.Do(req)
|
||||
}
|
||||
|
||||
// Perform a simple get to an endpoint and unmarshall returned JSON
|
||||
func (s *Session) RequestJSON(
|
||||
method string,
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
body interface{},
|
||||
responseContainer interface{},
|
||||
) (resp *http.Response, err error) {
|
||||
var bodyjson []byte
|
||||
if body != nil {
|
||||
bodyjson, err = json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// if headers == nil {
|
||||
// headers = &http.Header{}
|
||||
// headers.Add("Content-Type", "application/json")
|
||||
// }
|
||||
|
||||
resp, err = s.Request(method, url, params, headers, &bodyjson)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// err = util.CheckHTTPResponseStatusCode(resp)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
rbody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return resp, errors.New("error reading response body")
|
||||
}
|
||||
if err = json.Unmarshal(rbody, &responseContainer); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Session) Delete(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
) (resp *http.Response, err error) {
|
||||
return s.Request("DELETE", url, params, headers, nil)
|
||||
}
|
||||
|
||||
func (s *Session) Get(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
) (resp *http.Response, err error) {
|
||||
return s.Request("GET", url, params, headers, nil)
|
||||
}
|
||||
|
||||
func (s *Session) GetJSON(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
responseContainer interface{},
|
||||
) (resp *http.Response, err error) {
|
||||
return s.RequestJSON("GET", url, params, headers, nil, responseContainer)
|
||||
}
|
||||
|
||||
func (s *Session) Head(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
) (resp *http.Response, err error) {
|
||||
return s.Request("HEAD", url, params, headers, nil)
|
||||
}
|
||||
|
||||
func (s *Session) Post(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
body *[]byte,
|
||||
) (resp *http.Response, err error) {
|
||||
if headers == nil {
|
||||
headers = &http.Header{}
|
||||
headers.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
return s.Request("POST", url, params, headers, body)
|
||||
}
|
||||
|
||||
func (s *Session) PostJSON(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
body interface{},
|
||||
responseContainer interface{},
|
||||
) (resp *http.Response, err error) {
|
||||
return s.RequestJSON("POST", url, params, headers, body, responseContainer)
|
||||
}
|
||||
|
||||
func (s *Session) Put(
|
||||
url string,
|
||||
params *url.Values,
|
||||
headers *http.Header,
|
||||
body *[]byte,
|
||||
) (resp *http.Response, err error) {
|
||||
if headers == nil {
|
||||
headers = &http.Header{}
|
||||
headers.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
return s.Request("PUT", url, params, headers, body)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
# vscode
|
||||
.vscode
|
||||
debug
|
||||
*.test
|
||||
|
||||
./build
|
||||
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
|
@ -0,0 +1,12 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
|
||||
install:
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
@ -0,0 +1,25 @@
|
|||
*.received.*
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
|
@ -0,0 +1,16 @@
|
|||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
|
||||
install:
|
||||
- go get -u github.com/golang/lint/golint
|
||||
|
||||
script:
|
||||
- test -z "$(go fmt -s -l -w ./... | tee /dev/stderr)"
|
||||
- golint -set_exit_status ./...
|
||||
- go vet ./...
|
||||
- go build -v ./...
|
||||
- go test -v ./...
|
|
@ -0,0 +1,24 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
/metrics.out
|
|
@ -0,0 +1,22 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
|
@ -0,0 +1,3 @@
|
|||
language: go
|
||||
go:
|
||||
- tip
|
|
@ -0,0 +1 @@
|
|||
module github.com/armon/go-radix
|
|
@ -44,13 +44,13 @@ func (n *node) addEdge(e edge) {
|
|||
n.edges.Sort()
|
||||
}
|
||||
|
||||
func (n *node) replaceEdge(e edge) {
|
||||
func (n *node) updateEdge(label byte, node *node) {
|
||||
num := len(n.edges)
|
||||
idx := sort.Search(num, func(i int) bool {
|
||||
return n.edges[i].label >= e.label
|
||||
return n.edges[i].label >= label
|
||||
})
|
||||
if idx < num && n.edges[idx].label == e.label {
|
||||
n.edges[idx].node = e.node
|
||||
if idx < num && n.edges[idx].label == label {
|
||||
n.edges[idx].node = node
|
||||
return
|
||||
}
|
||||
panic("replacing missing edge")
|
||||
|
@ -198,10 +198,7 @@ func (t *Tree) Insert(s string, v interface{}) (interface{}, bool) {
|
|||
child := &node{
|
||||
prefix: search[:commonPrefix],
|
||||
}
|
||||
parent.replaceEdge(edge{
|
||||
label: search[0],
|
||||
node: child,
|
||||
})
|
||||
parent.updateEdge(search[0], child)
|
||||
|
||||
// Restore the existing node
|
||||
child.addEdge(edge{
|
||||
|
@ -292,6 +289,53 @@ DELETE:
|
|||
return leaf.val, true
|
||||
}
|
||||
|
||||
// DeletePrefix is used to delete the subtree under a prefix
|
||||
// Returns how many nodes were deleted
|
||||
// Use this to delete large subtrees efficiently
|
||||
func (t *Tree) DeletePrefix(s string) int {
|
||||
return t.deletePrefix(nil, t.root, s)
|
||||
}
|
||||
|
||||
// delete does a recursive deletion
|
||||
func (t *Tree) deletePrefix(parent, n *node, prefix string) int {
|
||||
// Check for key exhaustion
|
||||
if len(prefix) == 0 {
|
||||
// Remove the leaf node
|
||||
subTreeSize := 0
|
||||
//recursively walk from all edges of the node to be deleted
|
||||
recursiveWalk(n, func(s string, v interface{}) bool {
|
||||
subTreeSize++
|
||||
return false
|
||||
})
|
||||
if n.isLeaf() {
|
||||
n.leaf = nil
|
||||
}
|
||||
n.edges = nil // deletes the entire subtree
|
||||
|
||||
// Check if we should merge the parent's other child
|
||||
if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() {
|
||||
parent.mergeChild()
|
||||
}
|
||||
t.size -= subTreeSize
|
||||
return subTreeSize
|
||||
}
|
||||
|
||||
// Look for an edge
|
||||
label := prefix[0]
|
||||
child := n.getEdge(label)
|
||||
if child == nil || (!strings.HasPrefix(child.prefix, prefix) && !strings.HasPrefix(prefix, child.prefix)) {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Consume the search prefix
|
||||
if len(child.prefix) > len(prefix) {
|
||||
prefix = prefix[len(prefix):]
|
||||
} else {
|
||||
prefix = prefix[len(child.prefix):]
|
||||
}
|
||||
return t.deletePrefix(n, child, prefix)
|
||||
}
|
||||
|
||||
func (n *node) mergeChild() {
|
||||
e := n.edges[0]
|
||||
child := e.node
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
Original version Copyright © 2010 Fazlul Shahriar <fshahriar@gmail.com>. Newer
|
||||
portions Copyright © 2014 Blake Gentry <blakesgentry@gmail.com>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
|
@ -0,0 +1,2 @@
|
|||
example/example
|
||||
example/example.exe
|
|
@ -0,0 +1,24 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Blake Gentry
|
||||
|
||||
This license applies to the non-Windows portions of this library. The Windows
|
||||
portion maintains its own Apache 2.0 license.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,18 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/bgentry/speakeasy"
|
||||
)
|
||||
|
||||
func main() {
|
||||
password, err := speakeasy.Ask("Please enter a password: ")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Password result: %q\n", password)
|
||||
fmt.Printf("Password len: %d\n", len(password))
|
||||
}
|
|
@ -14,16 +14,18 @@ func Ask(prompt string) (password string, err error) {
|
|||
return FAsk(os.Stdout, prompt)
|
||||
}
|
||||
|
||||
// Same as the Ask function, except it is possible to specify the file to write
|
||||
// the prompt to.
|
||||
func FAsk(file *os.File, prompt string) (password string, err error) {
|
||||
if prompt != "" {
|
||||
fmt.Fprint(file, prompt) // Display the prompt.
|
||||
// FAsk is the same as Ask, except it is possible to specify the file to write
|
||||
// the prompt to. If 'nil' is passed as the writer, no prompt will be written.
|
||||
func FAsk(wr io.Writer, prompt string) (password string, err error) {
|
||||
if wr != nil && prompt != "" {
|
||||
fmt.Fprint(wr, prompt) // Display the prompt.
|
||||
}
|
||||
password, err = getPassword()
|
||||
|
||||
// Carriage return after the user input.
|
||||
fmt.Fprintln(file, "")
|
||||
if wr != nil {
|
||||
fmt.Fprintln(wr, "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Original code is based on code by RogerV in the golang-nuts thread:
|
||||
// https://groups.google.com/group/golang-nuts/browse_thread/thread/40cc41e9d9fc9247
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd solaris
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package speakeasy
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package speakeasy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
@ -12,18 +11,17 @@ import (
|
|||
const ENABLE_ECHO_INPUT = 0x0004
|
||||
|
||||
func getPassword() (password string, err error) {
|
||||
hStdin := syscall.Handle(os.Stdin.Fd())
|
||||
var oldMode uint32
|
||||
|
||||
err = syscall.GetConsoleMode(hStdin, &oldMode)
|
||||
err = syscall.GetConsoleMode(syscall.Stdin, &oldMode)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var newMode uint32 = (oldMode &^ ENABLE_ECHO_INPUT)
|
||||
|
||||
err = setConsoleMode(hStdin, newMode)
|
||||
defer setConsoleMode(hStdin, oldMode)
|
||||
err = setConsoleMode(syscall.Stdin, newMode)
|
||||
defer setConsoleMode(syscall.Stdin, oldMode)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
go-select*
|
||||
goselect*
|
||||
example-*
|
||||
example/example
|
0
vendor/github.com/creack/goselect/test_crosscompile.sh
generated
vendored
Executable file → Normal file
0
vendor/github.com/creack/goselect/test_crosscompile.sh
generated
vendored
Executable file → Normal file
|
@ -2,7 +2,7 @@ ISC License
|
|||
|
||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build !js,!appengine,!safe,!disableunsafe
|
||||
// Go versions prior to 1.4 are disabled because they use a different layout
|
||||
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
||||
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
||||
|
||||
package spew
|
||||
|
||||
|
@ -34,80 +36,49 @@ const (
|
|||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||
)
|
||||
|
||||
var (
|
||||
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
|
||||
// internal reflect.Value fields. These values are valid before golang
|
||||
// commit ecccf07e7f9d which changed the format. The are also valid
|
||||
// after commit 82f48826c6c7 which changed the format again to mirror
|
||||
// the original format. Code in the init function updates these offsets
|
||||
// as necessary.
|
||||
offsetPtr = uintptr(ptrSize)
|
||||
offsetScalar = uintptr(0)
|
||||
offsetFlag = uintptr(ptrSize * 2)
|
||||
type flag uintptr
|
||||
|
||||
// flagKindWidth and flagKindShift indicate various bits that the
|
||||
// reflect package uses internally to track kind information.
|
||||
//
|
||||
// flagRO indicates whether or not the value field of a reflect.Value is
|
||||
// read-only.
|
||||
//
|
||||
// flagIndir indicates whether the value field of a reflect.Value is
|
||||
// the actual data or a pointer to the data.
|
||||
//
|
||||
// These values are valid before golang commit 90a7c3c86944 which
|
||||
// changed their positions. Code in the init function updates these
|
||||
// flags as necessary.
|
||||
flagKindWidth = uintptr(5)
|
||||
flagKindShift = uintptr(flagKindWidth - 1)
|
||||
flagRO = uintptr(1 << 0)
|
||||
flagIndir = uintptr(1 << 1)
|
||||
var (
|
||||
// flagRO indicates whether the value field of a reflect.Value
|
||||
// is read-only.
|
||||
flagRO flag
|
||||
|
||||
// flagAddr indicates whether the address of the reflect.Value's
|
||||
// value may be taken.
|
||||
flagAddr flag
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Older versions of reflect.Value stored small integers directly in the
|
||||
// ptr field (which is named val in the older versions). Versions
|
||||
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
|
||||
// scalar for this purpose which unfortunately came before the flag
|
||||
// field, so the offset of the flag field is different for those
|
||||
// versions.
|
||||
//
|
||||
// This code constructs a new reflect.Value from a known small integer
|
||||
// and checks if the size of the reflect.Value struct indicates it has
|
||||
// the scalar field. When it does, the offsets are updated accordingly.
|
||||
vv := reflect.ValueOf(0xf00)
|
||||
if unsafe.Sizeof(vv) == (ptrSize * 4) {
|
||||
offsetScalar = ptrSize * 2
|
||||
offsetFlag = ptrSize * 3
|
||||
}
|
||||
// flagKindMask holds the bits that make up the kind
|
||||
// part of the flags field. In all the supported versions,
|
||||
// it is in the lower 5 bits.
|
||||
const flagKindMask = flag(0x1f)
|
||||
|
||||
// Commit 90a7c3c86944 changed the flag positions such that the low
|
||||
// order bits are the kind. This code extracts the kind from the flags
|
||||
// field and ensures it's the correct type. When it's not, the flag
|
||||
// order has been changed to the newer format, so the flags are updated
|
||||
// accordingly.
|
||||
upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
|
||||
upfv := *(*uintptr)(upf)
|
||||
flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
|
||||
if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
|
||||
flagKindShift = 0
|
||||
flagRO = 1 << 5
|
||||
flagIndir = 1 << 6
|
||||
// Different versions of Go have used different
|
||||
// bit layouts for the flags type. This table
|
||||
// records the known combinations.
|
||||
var okFlags = []struct {
|
||||
ro, addr flag
|
||||
}{{
|
||||
// From Go 1.4 to 1.5
|
||||
ro: 1 << 5,
|
||||
addr: 1 << 7,
|
||||
}, {
|
||||
// Up to Go tip.
|
||||
ro: 1<<5 | 1<<6,
|
||||
addr: 1 << 8,
|
||||
}}
|
||||
|
||||
// Commit adf9b30e5594 modified the flags to separate the
|
||||
// flagRO flag into two bits which specifies whether or not the
|
||||
// field is embedded. This causes flagIndir to move over a bit
|
||||
// and means that flagRO is the combination of either of the
|
||||
// original flagRO bit and the new bit.
|
||||
//
|
||||
// This code detects the change by extracting what used to be
|
||||
// the indirect bit to ensure it's set. When it's not, the flag
|
||||
// order has been changed to the newer format, so the flags are
|
||||
// updated accordingly.
|
||||
if upfv&flagIndir == 0 {
|
||||
flagRO = 3 << 5
|
||||
flagIndir = 1 << 7
|
||||
}
|
||||
var flagValOffset = func() uintptr {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
return field.Offset
|
||||
}()
|
||||
|
||||
// flagField returns a pointer to the flag field of a reflect.Value.
|
||||
func flagField(v *reflect.Value) *flag {
|
||||
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
||||
}
|
||||
|
||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||
|
@ -119,34 +90,56 @@ func init() {
|
|||
// This allows us to check for implementations of the Stringer and error
|
||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||
// inaccessible values such as unexported struct fields.
|
||||
func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
|
||||
indirects := 1
|
||||
vt := v.Type()
|
||||
upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
|
||||
rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
|
||||
if rvf&flagIndir != 0 {
|
||||
vt = reflect.PtrTo(v.Type())
|
||||
indirects++
|
||||
} else if offsetScalar != 0 {
|
||||
// The value is in the scalar field when it's not one of the
|
||||
// reference types.
|
||||
switch vt.Kind() {
|
||||
case reflect.Uintptr:
|
||||
case reflect.Chan:
|
||||
case reflect.Func:
|
||||
case reflect.Map:
|
||||
case reflect.Ptr:
|
||||
case reflect.UnsafePointer:
|
||||
default:
|
||||
upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
|
||||
offsetScalar)
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
||||
return v
|
||||
}
|
||||
flagFieldPtr := flagField(&v)
|
||||
*flagFieldPtr &^= flagRO
|
||||
*flagFieldPtr |= flagAddr
|
||||
return v
|
||||
}
|
||||
|
||||
// Sanity checks against future reflect package changes
|
||||
// to the type or semantics of the Value.flag field.
|
||||
func init() {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
||||
panic("reflect.Value flag field has changed kind")
|
||||
}
|
||||
type t0 int
|
||||
var t struct {
|
||||
A t0
|
||||
// t0 will have flagEmbedRO set.
|
||||
t0
|
||||
// a will have flagStickyRO set
|
||||
a t0
|
||||
}
|
||||
vA := reflect.ValueOf(t).FieldByName("A")
|
||||
va := reflect.ValueOf(t).FieldByName("a")
|
||||
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
||||
|
||||
// Infer flagRO from the difference between the flags
|
||||
// for the (otherwise identical) fields in t.
|
||||
flagPublic := *flagField(&vA)
|
||||
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
||||
flagRO = flagPublic ^ flagWithRO
|
||||
|
||||
// Infer flagAddr from the difference between a value
|
||||
// taken from a pointer and not.
|
||||
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
||||
flagNoPtr := *flagField(&vA)
|
||||
flagPtr := *flagField(&vPtrA)
|
||||
flagAddr = flagNoPtr ^ flagPtr
|
||||
|
||||
// Check that the inferred flags tally with one of the known versions.
|
||||
for _, f := range okFlags {
|
||||
if flagRO == f.ro && flagAddr == f.addr {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
pv := reflect.NewAt(vt, upv)
|
||||
rv = pv
|
||||
for i := 0; i < indirects; i++ {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
return rv
|
||||
panic("reflect.Value read-only flag has changed semantics")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build js appengine safe disableunsafe !go1.4
|
||||
|
||||
package spew
|
||||
|
||||
import "reflect"
|
||||
|
||||
const (
|
||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||
// not access to the unsafe package is available.
|
||||
UnsafeDisabled = true
|
||||
)
|
||||
|
||||
// unsafeReflectValue typically converts the passed reflect.Value into a one
|
||||
// that bypasses the typical safety restrictions preventing access to
|
||||
// unaddressable and unexported data. However, doing this relies on access to
|
||||
// the unsafe package. This is a stub version which simply returns the passed
|
||||
// reflect.Value when the unsafe package is not available.
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
return v
|
||||
}
|
|
@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
|||
w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
|
||||
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||
// prefix to Writer w.
|
||||
func printHexPtr(w io.Writer, p uintptr) {
|
||||
// Null pointer.
|
||||
|
|
|
@ -35,16 +35,16 @@ var (
|
|||
|
||||
// cCharRE is a regular expression that matches a cgo char.
|
||||
// It is used to detect character arrays to hexdump them.
|
||||
cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
|
||||
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
||||
|
||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||
// char. It is used to detect unsigned character arrays to hexdump
|
||||
// them.
|
||||
cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
|
||||
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
||||
|
||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||
// It is used to detect uint8_t arrays to hexdump them.
|
||||
cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
|
||||
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
||||
)
|
||||
|
||||
// dumpState contains information about the state of a dump operation.
|
||||
|
@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
|||
// Display dereferenced value.
|
||||
d.w.Write(openParenBytes)
|
||||
switch {
|
||||
case nilFound == true:
|
||||
case nilFound:
|
||||
d.w.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound == true:
|
||||
case cycleFound:
|
||||
d.w.Write(circularBytes)
|
||||
|
||||
default:
|
||||
|
|
|
@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) {
|
|||
|
||||
// Display dereferenced value.
|
||||
switch {
|
||||
case nilFound == true:
|
||||
case nilFound:
|
||||
f.fs.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound == true:
|
||||
case cycleFound:
|
||||
f.fs.Write(circularShortBytes)
|
||||
|
||||
default:
|
||||
|
|
|
@ -69,7 +69,6 @@ func (client *Client) NewInit(endpoint, version, accessKeyId, accessKeySecret, s
|
|||
client.Init(endpoint, version, accessKeyId, accessKeySecret)
|
||||
client.serviceCode = serviceCode
|
||||
client.regionID = regionID
|
||||
client.setEndpointByLocation(regionID, serviceCode, accessKeyId, accessKeySecret, client.securityToken)
|
||||
}
|
||||
|
||||
// Intialize client object when all properties are ready
|
||||
|
@ -86,7 +85,6 @@ func (client *Client) InitClient() *Client {
|
|||
TLSHandshakeTimeout: time.Duration(handshakeTimeout) * time.Second}
|
||||
client.httpClient = &http.Client{Transport: t}
|
||||
}
|
||||
client.setEndpointByLocation(client.regionID, client.serviceCode, client.AccessKeyId, client.AccessKeySecret, client.securityToken)
|
||||
return client
|
||||
}
|
||||
|
||||
|
@ -95,9 +93,17 @@ func (client *Client) NewInitForAssumeRole(endpoint, version, accessKeyId, acces
|
|||
client.securityToken = securityToken
|
||||
}
|
||||
|
||||
//getLocationEndpoint
|
||||
func (client *Client) getEndpointByLocation() string {
|
||||
locationClient := NewLocationClient(client.AccessKeyId, client.AccessKeySecret, client.securityToken)
|
||||
locationClient.SetDebug(true)
|
||||
return locationClient.DescribeOpenAPIEndpoint(client.regionID, client.serviceCode)
|
||||
}
|
||||
|
||||
//NewClient using location service
|
||||
func (client *Client) setEndpointByLocation(region Region, serviceCode, accessKeyId, accessKeySecret, securityToken string) {
|
||||
locationClient := NewLocationClient(accessKeyId, accessKeySecret, securityToken)
|
||||
locationClient.SetDebug(true)
|
||||
ep := locationClient.DescribeOpenAPIEndpoint(region, serviceCode)
|
||||
if ep == "" {
|
||||
ep = loadEndpointFromFile(region, serviceCode)
|
||||
|
@ -251,12 +257,34 @@ func (client *Client) SetSecurityToken(securityToken string) {
|
|||
client.securityToken = securityToken
|
||||
}
|
||||
|
||||
func (client *Client) initEndpoint() error {
|
||||
// if set any value to "CUSTOMIZED_ENDPOINT" could skip location service.
|
||||
// example: export CUSTOMIZED_ENDPOINT=true
|
||||
if os.Getenv("CUSTOMIZED_ENDPOINT") != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if client.serviceCode != "" && client.regionID != "" {
|
||||
endpoint := client.getEndpointByLocation()
|
||||
if endpoint == "" {
|
||||
return GetCustomError("InvalidEndpoint", "endpoint is empty,pls check")
|
||||
}
|
||||
client.endpoint = endpoint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
|
||||
if err := client.ensureProperties(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//init endpoint
|
||||
if err := client.initEndpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID)
|
||||
|
||||
|
@ -330,6 +358,11 @@ func (client *Client) InvokeByFlattenMethod(action string, args interface{}, res
|
|||
return err
|
||||
}
|
||||
|
||||
//init endpoint
|
||||
if err := client.initEndpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID)
|
||||
|
||||
|
@ -406,6 +439,11 @@ func (client *Client) InvokeByAnyMethod(method, action, path string, args interf
|
|||
return err
|
||||
}
|
||||
|
||||
//init endpoint
|
||||
if err := client.initEndpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID)
|
||||
data := util.ConvertToQueryValues(request)
|
||||
|
@ -500,3 +538,13 @@ func GetClientErrorFromString(str string) error {
|
|||
func GetClientError(err error) error {
|
||||
return GetClientErrorFromString(err.Error())
|
||||
}
|
||||
|
||||
func GetCustomError(code, message string) error {
|
||||
return &Error{
|
||||
ErrorResponse: ErrorResponse{
|
||||
Code: code,
|
||||
Message: message,
|
||||
},
|
||||
StatusCode: 400,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -50,6 +52,12 @@ var (
|
|||
"rds": "https://rds.eu-central-1.aliyuncs.com",
|
||||
"vpc": "https://vpc.eu-central-1.aliyuncs.com",
|
||||
},
|
||||
EUWest1: {
|
||||
"ecs": "https://ecs.eu-west-1.aliyuncs.com",
|
||||
"slb": "https://slb.eu-west-1.aliyuncs.com",
|
||||
"rds": "https://rds.eu-west-1.aliyuncs.com",
|
||||
"vpc": "https://vpc.eu-west-1.aliyuncs.com",
|
||||
},
|
||||
Zhangjiakou: {
|
||||
"ecs": "https://ecs.cn-zhangjiakou.aliyuncs.com",
|
||||
"slb": "https://slb.cn-zhangjiakou.aliyuncs.com",
|
||||
|
@ -140,7 +148,6 @@ func (client *LocationClient) DescribeOpenAPIEndpoint(region Region, serviceCode
|
|||
if endpoint := getProductRegionEndpoint(region, serviceCode); endpoint != "" {
|
||||
return endpoint
|
||||
}
|
||||
|
||||
defaultProtocols := HTTP_PROTOCOL
|
||||
|
||||
args := &DescribeEndpointsArgs{
|
||||
|
@ -149,8 +156,18 @@ func (client *LocationClient) DescribeOpenAPIEndpoint(region Region, serviceCode
|
|||
Type: "openAPI",
|
||||
}
|
||||
|
||||
endpoint, err := client.DescribeEndpoints(args)
|
||||
if err != nil || len(endpoint.Endpoints.Endpoint) <= 0 {
|
||||
var endpoint *DescribeEndpointsResponse
|
||||
var err error
|
||||
for index := 0; index < 5; index++ {
|
||||
endpoint, err = client.DescribeEndpoints(args)
|
||||
if err == nil && endpoint != nil && len(endpoint.Endpoints.Endpoint) > 0 {
|
||||
break
|
||||
}
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
if err != nil || endpoint == nil || len(endpoint.Endpoints.Endpoint) <= 0 {
|
||||
log.Printf("aliyungo: can not get endpoint from service, use default. endpoint=[%v], error=[%v]\n", endpoint, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -163,7 +180,7 @@ func (client *LocationClient) DescribeOpenAPIEndpoint(region Region, serviceCode
|
|||
|
||||
ep := fmt.Sprintf("%s://%s", defaultProtocols, endpoint.Endpoints.Endpoint[0].Endpoint)
|
||||
|
||||
//setProductRegionEndpoint(region, serviceCode, ep)
|
||||
setProductRegionEndpoint(region, serviceCode, ep)
|
||||
return ep
|
||||
}
|
||||
|
||||
|
|
|
@ -1336,6 +1336,17 @@
|
|||
<Product><ProductName>Slb</ProductName><DomainName>slb.eu-central-1.aliyuncs.com</DomainName></Product>
|
||||
</Products>
|
||||
</Endpoint>
|
||||
<Endpoint name="eu-west-1">
|
||||
<RegionIds><RegionId>eu-west-1</RegionId></RegionIds>
|
||||
<Products>
|
||||
<Product><ProductName>Rds</ProductName><DomainName>rds.eu-west-1.aliyuncs.com</DomainName></Product>
|
||||
<Product><ProductName>Ecs</ProductName><DomainName>ecs.eu-west-1.aliyuncs.com</DomainName></Product>
|
||||
<Product><ProductName>Vpc</ProductName><DomainName>vpc.eu-west-1.aliyuncs.com</DomainName></Product>
|
||||
<Product><ProductName>Kms</ProductName><DomainName>kms.eu-west-1.aliyuncs.com</DomainName></Product>
|
||||
<Product><ProductName>Cms</ProductName><DomainName>metrics.cn-hangzhou.aliyuncs.com</DomainName></Product>
|
||||
<Product><ProductName>Slb</ProductName><DomainName>slb.eu-west-1.aliyuncs.com</DomainName></Product>
|
||||
</Products>
|
||||
</Endpoint>
|
||||
<Endpoint name="cn-zhangjiakou">
|
||||
<RegionIds><RegionId>cn-zhangjiakou</RegionId></RegionIds>
|
||||
<Products>
|
||||
|
|
|
@ -28,6 +28,7 @@ const (
|
|||
MEEast1 = Region("me-east-1")
|
||||
|
||||
EUCentral1 = Region("eu-central-1")
|
||||
EUWest1 = Region("eu-west-1")
|
||||
|
||||
ShenZhenFinance = Region("cn-shenzhen-finance-1")
|
||||
ShanghaiFinance = Region("cn-shanghai-finance-1")
|
||||
|
@ -39,6 +40,16 @@ var ValidRegions = []Region{
|
|||
APNorthEast1, APSouthEast1, APSouthEast2, APSouthEast3, APSouthEast5,
|
||||
APSouth1,
|
||||
MEEast1,
|
||||
EUCentral1,
|
||||
EUCentral1, EUWest1,
|
||||
ShenZhenFinance, ShanghaiFinance,
|
||||
}
|
||||
|
||||
// IsValidRegion checks if r is an Ali supported region.
|
||||
func IsValidRegion(r string) bool {
|
||||
for _, v := range ValidRegions {
|
||||
if r == string(v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -113,3 +113,12 @@ func NewVPCClientWithEndpointAndSecurityToken(endpoint string, accessKeyId strin
|
|||
InitClient()
|
||||
return client
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
// NewVPCClientWithRegion creates a new instance of VPC client automatically get endpoint
|
||||
// ---------------------------------------
|
||||
func NewVPCClientWithRegion(endpoint string, accessKeyId string, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, VPCAPIVersion, accessKeyId, accessKeySecret, VPCServiceCode, regionID)
|
||||
return client
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ type DescribeDisksArgs struct {
|
|||
Category DiskCategory //enum for all(default) | cloud | ephemeral
|
||||
Status DiskStatus //enum for In_use | Available | Attaching | Detaching | Creating | ReIniting | All(default)
|
||||
SnapshotId string
|
||||
Name string
|
||||
DiskName string
|
||||
Portable *bool //optional
|
||||
DeleteWithInstance *bool //optional
|
||||
DeleteAutoSnapshot *bool //optional
|
||||
|
@ -78,6 +78,7 @@ type DiskItemType struct {
|
|||
DiskName string
|
||||
Description string
|
||||
Type DiskType
|
||||
Encrypted bool
|
||||
Category DiskCategory
|
||||
Size int
|
||||
ImageId string
|
||||
|
@ -242,7 +243,7 @@ func (client *Client) DetachDisk(instanceId string, diskId string) error {
|
|||
}
|
||||
|
||||
type ResizeDiskArgs struct {
|
||||
DiskId string
|
||||
DiskId string
|
||||
NewSize int
|
||||
}
|
||||
|
||||
|
@ -255,15 +256,14 @@ type ResizeDiskResponse struct {
|
|||
// You can read doc at https://help.aliyun.com/document_detail/25522.html
|
||||
func (client *Client) ResizeDisk(diskId string, sizeGB int) error {
|
||||
args := ResizeDiskArgs{
|
||||
DiskId:diskId,
|
||||
NewSize:sizeGB,
|
||||
DiskId: diskId,
|
||||
NewSize: sizeGB,
|
||||
}
|
||||
response := ResizeDiskResponse{}
|
||||
err := client.Invoke("ResizeDisk", &args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
type ResetDiskArgs struct {
|
||||
DiskId string
|
||||
SnapshotId string
|
||||
|
@ -273,7 +273,6 @@ type ResetDiskResponse struct {
|
|||
common.Response
|
||||
}
|
||||
|
||||
|
||||
// ResetDisk resets disk to original status
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&resetdisk
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
package ecs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type CreateNetworkInterfaceArgs struct {
|
||||
RegionId common.Region
|
||||
VSwitchId string
|
||||
PrimaryIpAddress string // optional
|
||||
SecurityGroupId string
|
||||
NetworkInterfaceName string // optional
|
||||
Description string // optional
|
||||
ClientToken string // optional
|
||||
}
|
||||
|
||||
type CreateNetworkInterfaceResponse struct {
|
||||
common.Response
|
||||
NetworkInterfaceId string
|
||||
}
|
||||
type DeleteNetworkInterfaceArgs struct {
|
||||
RegionId common.Region
|
||||
NetworkInterfaceId string
|
||||
}
|
||||
|
||||
type DeleteNetworkInterfaceResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type DescribeNetworkInterfacesArgs struct {
|
||||
RegionId common.Region
|
||||
VSwitchId string
|
||||
PrimaryIpAddress string
|
||||
SecurityGroupId string
|
||||
NetworkInterfaceName string
|
||||
Type string
|
||||
InstanceId string
|
||||
NetworkInterfaceId []string `query:"list"`
|
||||
PageNumber int
|
||||
PageSize int
|
||||
}
|
||||
type NetworkInterfaceType struct {
|
||||
NetworkInterfaceId string
|
||||
NetworkInterfaceName string
|
||||
PrimaryIpAddress string
|
||||
MacAddress string
|
||||
Status string
|
||||
PrivateIpAddress string
|
||||
}
|
||||
|
||||
type DescribeNetworkInterfacesResponse struct {
|
||||
common.Response
|
||||
NetworkInterfaceSets struct {
|
||||
NetworkInterfaceSet []NetworkInterfaceType
|
||||
}
|
||||
TotalCount int
|
||||
PageNumber int
|
||||
PageSize int
|
||||
}
|
||||
type AttachNetworkInterfaceArgs struct {
|
||||
RegionId common.Region
|
||||
NetworkInterfaceId string
|
||||
InstanceId string
|
||||
}
|
||||
|
||||
type AttachNetworkInterfaceResponse common.Response
|
||||
|
||||
type DetachNetworkInterfaceArgs AttachNetworkInterfaceArgs
|
||||
|
||||
type DetachNetworkInterfaceResponse common.Response
|
||||
|
||||
type ModifyNetworkInterfaceAttributeArgs struct {
|
||||
RegionId common.Region
|
||||
NetworkInterfaceId string
|
||||
SecurityGroupId []string
|
||||
NetworkInterfaceName string
|
||||
Description string
|
||||
}
|
||||
type ModifyNetworkInterfaceAttributeResponse common.Response
|
||||
|
||||
type UnassignPrivateIpAddressesArgs struct {
|
||||
RegionId common.Region
|
||||
NetworkInterfaceId string
|
||||
PrivateIpAddress []string `query:"list"`
|
||||
}
|
||||
|
||||
type UnassignPrivateIpAddressesResponse common.Response
|
||||
|
||||
type AssignPrivateIpAddressesArgs struct {
|
||||
RegionId common.Region
|
||||
NetworkInterfaceId string
|
||||
PrivateIpAddress []string `query:"list"` // optional
|
||||
SecondaryPrivateIpAddressCount int // optional
|
||||
}
|
||||
|
||||
type AssignPrivateIpAddressesResponse common.Response
|
||||
|
||||
func (client *Client) CreateNetworkInterface(args *CreateNetworkInterfaceArgs) (resp *CreateNetworkInterfaceResponse, err error) {
|
||||
resp = &CreateNetworkInterfaceResponse{}
|
||||
err = client.Invoke("CreateNetworkInterface", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) DeleteNetworkInterface(args *DeleteNetworkInterfaceArgs) (resp *DeleteNetworkInterfaceResponse, err error) {
|
||||
resp = &DeleteNetworkInterfaceResponse{}
|
||||
err = client.Invoke("DeleteNetworkInterface", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) DescribeNetworkInterfaces(args *DescribeNetworkInterfacesArgs) (resp *DescribeNetworkInterfacesResponse, err error) {
|
||||
resp = &DescribeNetworkInterfacesResponse{}
|
||||
err = client.Invoke("DescribeNetworkInterfaces", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) AttachNetworkInterface(args *AttachNetworkInterfaceArgs) error {
|
||||
resp := &AttachNetworkInterfaceResponse{}
|
||||
err := client.Invoke("AttachNetworkInterface", args, resp)
|
||||
return err
|
||||
}
|
||||
|
||||
func (client *Client) DetachNetworkInterface(args *DetachNetworkInterfaceArgs) (resp *DetachNetworkInterfaceResponse, err error) {
|
||||
resp = &DetachNetworkInterfaceResponse{}
|
||||
err = client.Invoke("DetachNetworkInterface", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) ModifyNetworkInterfaceAttribute(args *ModifyNetworkInterfaceAttributeArgs) (resp *ModifyNetworkInterfaceAttributeResponse, err error) {
|
||||
resp = &ModifyNetworkInterfaceAttributeResponse{}
|
||||
err = client.Invoke("ModifyNetworkInterfaceAttribute", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) UnassignPrivateIpAddresses(args *UnassignPrivateIpAddressesArgs) (resp *UnassignPrivateIpAddressesResponse, err error) {
|
||||
resp = &UnassignPrivateIpAddressesResponse{}
|
||||
err = client.Invoke("UnassignPrivateIpAddresses", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (client *Client) AssignPrivateIpAddresses(args *AssignPrivateIpAddressesArgs) (resp *AssignPrivateIpAddressesResponse, err error) {
|
||||
resp = &AssignPrivateIpAddressesResponse{}
|
||||
err = client.Invoke("AssignPrivateIpAddresses", args, resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Default timeout value for WaitForInstance method
|
||||
const NetworkInterfacesDefaultTimeout = 120
|
||||
|
||||
// WaitForInstance waits for instance to given status
|
||||
func (client *Client) WaitForNetworkInterface(regionId common.Region, eniID string, status string, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = NetworkInterfacesDefaultTimeout
|
||||
}
|
||||
for {
|
||||
|
||||
eniIds := []string{eniID}
|
||||
|
||||
describeNetworkInterfacesArgs := DescribeNetworkInterfacesArgs{
|
||||
RegionId: regionId,
|
||||
NetworkInterfaceId: eniIds,
|
||||
}
|
||||
|
||||
nisResponse, err := client.DescribeNetworkInterfaces(&describeNetworkInterfacesArgs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to describe network interface %v: %v", eniID, err)
|
||||
}
|
||||
|
||||
if len(nisResponse.NetworkInterfaceSets.NetworkInterfaceSet) > 0 && nisResponse.NetworkInterfaceSets.NetworkInterfaceSet[0].Status == status {
|
||||
break
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
if timeout <= 0 {
|
||||
return fmt.Errorf("Timeout for waiting available status for network interfaces")
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -37,6 +37,13 @@ const (
|
|||
ImageUsageNone = ImageUsage("none")
|
||||
)
|
||||
|
||||
type ImageFormatType string
|
||||
|
||||
const (
|
||||
RAW = ImageFormatType("RAW")
|
||||
VHD = ImageFormatType("VHD")
|
||||
)
|
||||
|
||||
// DescribeImagesArgs repsents arguments to describe images
|
||||
type DescribeImagesArgs struct {
|
||||
RegionId common.Region
|
||||
|
@ -63,8 +70,10 @@ type DescribeImagesResponse struct {
|
|||
type DiskDeviceMapping struct {
|
||||
SnapshotId string
|
||||
//Why Size Field is string-type.
|
||||
Size string
|
||||
Device string
|
||||
Size string
|
||||
// Now the key Size change to DiskImageSize
|
||||
DiskImageSize string
|
||||
Device string
|
||||
//For import images
|
||||
Format string
|
||||
OSSBucket string
|
||||
|
@ -151,6 +160,7 @@ func (client *Client) CreateImage(args *CreateImageArgs) (imageId string, err er
|
|||
type DeleteImageArgs struct {
|
||||
RegionId common.Region
|
||||
ImageId string
|
||||
Force bool
|
||||
}
|
||||
|
||||
type DeleteImageResponse struct {
|
||||
|
@ -170,6 +180,20 @@ func (client *Client) DeleteImage(regionId common.Region, imageId string) error
|
|||
return client.Invoke("DeleteImage", &args, &response)
|
||||
}
|
||||
|
||||
// DeleteImage deletes Image
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/image&deleteimage
|
||||
func (client *Client) DeleteImageWithForce(regionId common.Region, imageId string, force bool) error {
|
||||
args := DeleteImageArgs{
|
||||
RegionId: regionId,
|
||||
ImageId: imageId,
|
||||
Force: force,
|
||||
}
|
||||
|
||||
response := &DeleteImageResponse{}
|
||||
return client.Invoke("DeleteImage", &args, &response)
|
||||
}
|
||||
|
||||
// ModifyImageSharePermission repsents arguments to share image
|
||||
type ModifyImageSharePermissionArgs struct {
|
||||
RegionId common.Region
|
||||
|
|
|
@ -9,10 +9,19 @@ type DescribeInstanceTypesArgs struct {
|
|||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancetypeitemtype
|
||||
type InstanceTypeItemType struct {
|
||||
InstanceTypeId string
|
||||
CpuCoreCount int
|
||||
MemorySize float64
|
||||
InstanceTypeFamily string
|
||||
InstanceTypeId string
|
||||
CpuCoreCount int
|
||||
MemorySize float64
|
||||
InstanceTypeFamily string
|
||||
GPUAmount int
|
||||
GPUSpec string
|
||||
InitialCredit int
|
||||
BaselineCredit int
|
||||
EniQuantity int
|
||||
EniPrivateIpAddressQuantity int
|
||||
LocalStorageCapacity int
|
||||
LocalStorageAmount int
|
||||
LocalStorageCategory string
|
||||
}
|
||||
|
||||
type DescribeInstanceTypesResponse struct {
|
||||
|
|
|
@ -245,7 +245,7 @@ type InstanceAttributesType struct {
|
|||
SerialNumber string
|
||||
Status InstanceStatus
|
||||
OperationLocks OperationLocksType
|
||||
SecurityGroupIds struct {
|
||||
SecurityGroupIds struct {
|
||||
SecurityGroupId []string
|
||||
}
|
||||
PublicIpAddress IpAddressSetType
|
||||
|
@ -260,7 +260,7 @@ type InstanceAttributesType struct {
|
|||
IoOptimized StringOrBool
|
||||
InstanceChargeType common.InstanceChargeType
|
||||
ExpiredTime util.ISO6801Time
|
||||
Tags struct {
|
||||
Tags struct {
|
||||
Tag []TagItemType
|
||||
}
|
||||
SpotStrategy SpotStrategyType
|
||||
|
@ -440,6 +440,28 @@ func (client *Client) DescribeInstancesWithRaw(args *DescribeInstancesArgs) (res
|
|||
return response, nil
|
||||
}
|
||||
|
||||
type ModifyInstanceAutoReleaseTimeArgs struct {
|
||||
InstanceId string
|
||||
AutoReleaseTime string
|
||||
}
|
||||
|
||||
type ModifyInstanceAutoReleaseTimeResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// 对给定的实例设定自动释放时间。
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/47576.html
|
||||
func (client *Client) ModifyInstanceAutoReleaseTime(instanceId, time string) error {
|
||||
args := ModifyInstanceAutoReleaseTimeArgs{
|
||||
InstanceId: instanceId,
|
||||
AutoReleaseTime: time,
|
||||
}
|
||||
response := ModifyInstanceAutoReleaseTimeResponse{}
|
||||
err := client.Invoke("ModifyInstanceAutoReleaseTime", &args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DeleteInstanceArgs struct {
|
||||
InstanceId string
|
||||
}
|
||||
|
@ -512,34 +534,43 @@ var (
|
|||
IoOptimizedOptimized = IoOptimized("optimized")
|
||||
)
|
||||
|
||||
type SecurityEnhancementStrategy string
|
||||
|
||||
var (
|
||||
InactiveSecurityEnhancementStrategy = SecurityEnhancementStrategy("Active")
|
||||
DeactiveSecurityEnhancementStrategy = SecurityEnhancementStrategy("Deactive")
|
||||
)
|
||||
|
||||
type CreateInstanceArgs struct {
|
||||
RegionId common.Region
|
||||
ZoneId string
|
||||
ImageId string
|
||||
InstanceType string
|
||||
SecurityGroupId string
|
||||
InstanceName string
|
||||
Description string
|
||||
InternetChargeType common.InternetChargeType
|
||||
InternetMaxBandwidthIn int
|
||||
InternetMaxBandwidthOut int
|
||||
HostName string
|
||||
Password string
|
||||
IoOptimized IoOptimized
|
||||
SystemDisk SystemDiskType
|
||||
DataDisk []DataDiskType
|
||||
VSwitchId string
|
||||
PrivateIpAddress string
|
||||
ClientToken string
|
||||
InstanceChargeType common.InstanceChargeType
|
||||
Period int
|
||||
UserData string
|
||||
AutoRenew bool
|
||||
AutoRenewPeriod int
|
||||
SpotStrategy SpotStrategyType
|
||||
SpotPriceLimit float64
|
||||
KeyPairName string
|
||||
RamRoleName string
|
||||
RegionId common.Region
|
||||
ZoneId string
|
||||
ImageId string
|
||||
InstanceType string
|
||||
SecurityGroupId string
|
||||
InstanceName string
|
||||
Description string
|
||||
InternetChargeType common.InternetChargeType
|
||||
InternetMaxBandwidthIn int
|
||||
InternetMaxBandwidthOut int
|
||||
HostName string
|
||||
Password string
|
||||
IoOptimized IoOptimized
|
||||
SystemDisk SystemDiskType
|
||||
DataDisk []DataDiskType
|
||||
VSwitchId string
|
||||
PrivateIpAddress string
|
||||
ClientToken string
|
||||
InstanceChargeType common.InstanceChargeType
|
||||
Period int
|
||||
PeriodUnit common.TimeType
|
||||
UserData string
|
||||
AutoRenew bool
|
||||
AutoRenewPeriod int
|
||||
SpotStrategy SpotStrategyType
|
||||
SpotPriceLimit float64
|
||||
KeyPairName string
|
||||
RamRoleName string
|
||||
SecurityEnhancementStrategy SecurityEnhancementStrategy
|
||||
}
|
||||
|
||||
type CreateInstanceResponse struct {
|
||||
|
@ -682,3 +713,120 @@ func (client *Client) DescribeInstanceRamRole(args *AttachInstancesArgs) (resp *
|
|||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type ModifyInstanceSpecArgs struct {
|
||||
InstanceId string
|
||||
InstanceType string
|
||||
InternetMaxBandwidthOut *int
|
||||
InternetMaxBandwidthIn *int
|
||||
ClientToken string
|
||||
}
|
||||
|
||||
type ModifyInstanceSpecResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
//ModifyInstanceSpec modify instance specification
|
||||
//
|
||||
// Notice: 1. An instance that was successfully modified once cannot be modified again within 5 minutes.
|
||||
// 2. The API only can be used Pay-As-You-Go (PostPaid) instance
|
||||
//
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/57633.htm
|
||||
func (client *Client) ModifyInstanceSpec(args *ModifyInstanceSpecArgs) error {
|
||||
response := ModifyInstanceSpecResponse{}
|
||||
return client.Invoke("ModifyInstanceSpec", args, &response)
|
||||
}
|
||||
|
||||
type ModifyInstanceVpcAttributeArgs struct {
|
||||
InstanceId string
|
||||
VSwitchId string
|
||||
PrivateIpAddress string
|
||||
}
|
||||
|
||||
type ModifyInstanceVpcAttributeResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
//ModifyInstanceVpcAttribute modify instance vswitchID and private ip address
|
||||
//
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/25504.htm
|
||||
func (client *Client) ModifyInstanceVpcAttribute(args *ModifyInstanceVpcAttributeArgs) error {
|
||||
response := ModifyInstanceVpcAttributeResponse{}
|
||||
return client.Invoke("ModifyInstanceVpcAttribute", args, &response)
|
||||
}
|
||||
|
||||
type ModifyInstanceChargeTypeArgs struct {
|
||||
InstanceIds string
|
||||
RegionId common.Region
|
||||
Period int
|
||||
PeriodUnit common.TimeType
|
||||
IncludeDataDisks bool
|
||||
DryRun bool
|
||||
AutoPay bool
|
||||
ClientToken string
|
||||
}
|
||||
|
||||
type ModifyInstanceChargeTypeResponse struct {
|
||||
common.Response
|
||||
Order string
|
||||
}
|
||||
|
||||
//ModifyInstanceChargeType modify instance charge type
|
||||
//
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/25504.htm
|
||||
func (client *Client) ModifyInstanceChargeType(args *ModifyInstanceChargeTypeArgs) (*ModifyInstanceChargeTypeResponse, error) {
|
||||
response := &ModifyInstanceChargeTypeResponse{}
|
||||
if err := client.Invoke("ModifyInstanceChargeType", args, response); err != nil {
|
||||
return response, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type RenewalStatus string
|
||||
|
||||
const (
|
||||
RenewAutoRenewal = RenewalStatus("AutoRenewal")
|
||||
RenewNormal = RenewalStatus("Normal")
|
||||
RenewNotRenewal = RenewalStatus("NotRenewal")
|
||||
)
|
||||
|
||||
type ModifyInstanceAutoRenewAttributeArgs struct {
|
||||
InstanceId string
|
||||
RegionId common.Region
|
||||
Duration int
|
||||
AutoRenew bool
|
||||
RenewalStatus RenewalStatus
|
||||
}
|
||||
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/52843.htm
|
||||
func (client *Client) ModifyInstanceAutoRenewAttribute(args *ModifyInstanceAutoRenewAttributeArgs) error {
|
||||
response := &common.Response{}
|
||||
return client.Invoke("ModifyInstanceAutoRenewAttribute", args, response)
|
||||
}
|
||||
|
||||
type DescribeInstanceAutoRenewAttributeArgs struct {
|
||||
InstanceId string
|
||||
RegionId common.Region
|
||||
}
|
||||
|
||||
type InstanceRenewAttribute struct {
|
||||
InstanceId string
|
||||
Duration int
|
||||
AutoRenewEnabled bool
|
||||
PeriodUnit string
|
||||
RenewalStatus RenewalStatus
|
||||
}
|
||||
|
||||
type DescribeInstanceAutoRenewAttributeResponse struct {
|
||||
common.Response
|
||||
InstanceRenewAttributes struct {
|
||||
InstanceRenewAttribute []InstanceRenewAttribute
|
||||
}
|
||||
}
|
||||
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/52844.htm
|
||||
func (client *Client) DescribeInstanceAutoRenewAttribute(args *DescribeInstanceAutoRenewAttributeArgs) (*DescribeInstanceAutoRenewAttributeResponse, error) {
|
||||
response := &DescribeInstanceAutoRenewAttributeResponse{}
|
||||
err := client.Invoke("DescribeInstanceAutoRenewAttribute", args, response)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -28,6 +28,16 @@ type SnatTableIdType struct {
|
|||
SnatTableId []string
|
||||
}
|
||||
|
||||
type IpListsType struct {
|
||||
IpList []IpListItem
|
||||
}
|
||||
|
||||
type IpListItem struct {
|
||||
IpAddress string
|
||||
AllocationId string
|
||||
UsingStatus string
|
||||
}
|
||||
|
||||
type BandwidthPackageIdType struct {
|
||||
BandwidthPackageId []string
|
||||
}
|
||||
|
@ -57,6 +67,7 @@ type NatGatewaySetType struct {
|
|||
BandwidthPackageIds BandwidthPackageIdType
|
||||
ForwardTableIds ForwardTableIdType
|
||||
SnatTableIds SnatTableIdType
|
||||
IpLists IpListsType
|
||||
InstanceChargeType string
|
||||
Name string
|
||||
NatGatewayId string
|
||||
|
@ -147,7 +158,8 @@ func (client *Client) DeleteNatGateway(args *DeleteNatGatewayArgs) error {
|
|||
}
|
||||
|
||||
type DescribeBandwidthPackagesArgs struct {
|
||||
RegionId common.Region
|
||||
RegionId common.Region
|
||||
common.Pagination
|
||||
BandwidthPackageId string
|
||||
NatGatewayId string
|
||||
}
|
||||
|
@ -170,12 +182,13 @@ type DescribeBandwidthPackageType struct {
|
|||
|
||||
type DescribeBandwidthPackagesResponse struct {
|
||||
common.Response
|
||||
common.PaginationResult
|
||||
BandwidthPackages struct {
|
||||
BandwidthPackage []DescribeBandwidthPackageType
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) DescribeBandwidthPackages(args *DescribeBandwidthPackagesArgs) ([]DescribeBandwidthPackageType, error) {
|
||||
func (client *Client) DescribeBandwidthPackages(args *DescribeBandwidthPackagesArgs) (*DescribeBandwidthPackagesResponse, error) {
|
||||
response := &DescribeBandwidthPackagesResponse{}
|
||||
|
||||
err := client.Invoke("DescribeBandwidthPackages", args, response)
|
||||
|
@ -183,7 +196,7 @@ func (client *Client) DescribeBandwidthPackages(args *DescribeBandwidthPackagesA
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return response.BandwidthPackages.BandwidthPackage, err
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DeleteBandwidthPackageArgs struct {
|
||||
|
|
|
@ -36,8 +36,9 @@ func (client *Client) AllocatePublicIpAddress(instanceId string) (ipAddress stri
|
|||
|
||||
type ModifyInstanceNetworkSpec struct {
|
||||
InstanceId string
|
||||
InternetMaxBandwidthOut int
|
||||
InternetMaxBandwidthIn int
|
||||
InternetMaxBandwidthOut *int
|
||||
InternetMaxBandwidthIn *int
|
||||
NetworkChargeType common.InternetChargeType
|
||||
}
|
||||
|
||||
type ModifyInstanceNetworkSpecResponse struct {
|
||||
|
@ -57,6 +58,7 @@ type AllocateEipAddressArgs struct {
|
|||
RegionId common.Region
|
||||
Bandwidth int
|
||||
InternetChargeType common.InternetChargeType
|
||||
ISP string
|
||||
ClientToken string
|
||||
}
|
||||
|
||||
|
@ -81,9 +83,19 @@ func (client *Client) AllocateEipAddress(args *AllocateEipAddressArgs) (EipAddre
|
|||
return response.EipAddress, response.AllocationId, nil
|
||||
}
|
||||
|
||||
type EipInstanceType string
|
||||
|
||||
const (
|
||||
EcsInstance = "EcsInstance"
|
||||
SlbInstance = "SlbInstance"
|
||||
Nat = "Nat"
|
||||
HaVip = "HaVip"
|
||||
)
|
||||
|
||||
type AssociateEipAddressArgs struct {
|
||||
AllocationId string
|
||||
InstanceId string
|
||||
InstanceType EipInstanceType
|
||||
}
|
||||
|
||||
type AssociateEipAddressResponse struct {
|
||||
|
@ -102,6 +114,11 @@ func (client *Client) AssociateEipAddress(allocationId string, instanceId string
|
|||
return client.Invoke("AssociateEipAddress", &args, &response)
|
||||
}
|
||||
|
||||
func (client *Client) NewAssociateEipAddress(args *AssociateEipAddressArgs) error {
|
||||
response := ModifyInstanceNetworkSpecResponse{}
|
||||
return client.Invoke("AssociateEipAddress", args, &response)
|
||||
}
|
||||
|
||||
// Status of disks
|
||||
type EipStatus string
|
||||
|
||||
|
@ -112,11 +129,22 @@ const (
|
|||
EipStatusAvailable = EipStatus("Available")
|
||||
)
|
||||
|
||||
type AssociatedInstanceType string
|
||||
|
||||
const (
|
||||
AssociatedInstanceTypeEcsInstance = AssociatedInstanceType("EcsInstance")
|
||||
AssociatedInstanceTypeSlbInstance = AssociatedInstanceType("SlbInstance")
|
||||
AssociatedInstanceTypeNat = AssociatedInstanceType("Nat")
|
||||
AssociatedInstanceTypeHaVip = AssociatedInstanceType("HaVip")
|
||||
)
|
||||
|
||||
type DescribeEipAddressesArgs struct {
|
||||
RegionId common.Region
|
||||
Status EipStatus //enum Associating | Unassociating | InUse | Available
|
||||
EipAddress string
|
||||
AllocationId string
|
||||
RegionId common.Region
|
||||
Status EipStatus //enum Associating | Unassociating | InUse | Available
|
||||
EipAddress string
|
||||
AllocationId string
|
||||
AssociatedInstanceType AssociatedInstanceType //enum EcsInstance | SlbInstance | Nat | HaVip
|
||||
AssociatedInstanceId string //绑定的资源的Id。 这是一个过滤器性质的参数,若不指定,则表示不适用该条件对结果进行过滤。 如果要使用该过滤器,必须同时使用AssociatedInstanceType。若InstanceType为EcsInstance,则此处填写ECS实例Id。若InstanceType为SlbInstance,则此处填写VPC类型的私网SLB 的实例ID。若InstanceType为Nat,则此处填写NAT 的实例ID。。若InstanceType为HaVip,则此处填写HaVipId。
|
||||
common.Pagination
|
||||
}
|
||||
|
||||
|
@ -128,6 +156,7 @@ type EipAddressSetType struct {
|
|||
AllocationId string
|
||||
Status EipStatus
|
||||
InstanceId string
|
||||
InstanceType string
|
||||
Bandwidth string // Why string
|
||||
InternetChargeType common.InternetChargeType
|
||||
OperationLocks OperationLocksType
|
||||
|
|
|
@ -100,8 +100,8 @@ func (client *Client) DescribeRouteTablesWithRaw(args *DescribeRouteTablesArgs)
|
|||
type NextHopType string
|
||||
|
||||
const (
|
||||
NextHopIntance = NextHopType("Instance") //Default
|
||||
NextHopTunnel = NextHopType("Tunnel")
|
||||
NextHopIntance = NextHopType("Instance") //Default
|
||||
NextHopTunnel = NextHopType("Tunnel")
|
||||
NextHopTunnelRouterInterface = NextHopType("RouterInterface")
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ecs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
|
@ -19,6 +21,8 @@ const (
|
|||
Idl = InterfaceStatus("Idl")
|
||||
Active = InterfaceStatus("Active")
|
||||
Inactive = InterfaceStatus("Inactive")
|
||||
// 'Idle' means the router interface is not connected. 'Idl' may be a incorrect status.
|
||||
Idle = InterfaceStatus("Idle")
|
||||
|
||||
InitiatingSide = Role("InitiatingSide")
|
||||
AcceptingSide = Role("AcceptingSide")
|
||||
|
@ -77,7 +81,7 @@ type Filter struct {
|
|||
type DescribeRouterInterfacesArgs struct {
|
||||
RegionId common.Region
|
||||
common.Pagination
|
||||
Filter []Filter
|
||||
Filter []Filter
|
||||
}
|
||||
|
||||
type RouterInterfaceItemType struct {
|
||||
|
@ -225,3 +229,29 @@ func (client *Client) DeleteRouterInterface(args *OperateRouterInterfaceArgs) (r
|
|||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// WaitForRouterInterface waits for router interface to given status
|
||||
func (client *Client) WaitForRouterInterfaceAsyn(regionId common.Region, interfaceId string, status InterfaceStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
interfaces, err := client.DescribeRouterInterfaces(&DescribeRouterInterfacesArgs{
|
||||
RegionId: regionId,
|
||||
Filter: []Filter{Filter{Key: "RouterInterfaceId", Value: []string{interfaceId}}},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if interfaces != nil && InterfaceStatus(interfaces.RouterInterfaceSet.RouterInterfaceType[0].Status) == status {
|
||||
//TODO
|
||||
break
|
||||
}
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,10 +6,15 @@ import (
|
|||
)
|
||||
|
||||
type NicType string
|
||||
type Direction string
|
||||
|
||||
const (
|
||||
NicTypeInternet = NicType("internet")
|
||||
NicTypeIntranet = NicType("intranet")
|
||||
|
||||
DirectionIngress = Direction("ingress")
|
||||
DirectionEgress = Direction("egress")
|
||||
DirectionAll = Direction("all")
|
||||
)
|
||||
|
||||
type IpProtocol string
|
||||
|
@ -29,11 +34,18 @@ const (
|
|||
PermissionPolicyDrop = PermissionPolicy("drop")
|
||||
)
|
||||
|
||||
type GroupInnerAccessPolicy string
|
||||
|
||||
const (
|
||||
GroupInnerAccept = GroupInnerAccessPolicy("Accept")
|
||||
GroupInnerDrop = GroupInnerAccessPolicy("Drop")
|
||||
)
|
||||
|
||||
type DescribeSecurityGroupAttributeArgs struct {
|
||||
SecurityGroupId string
|
||||
RegionId common.Region
|
||||
NicType NicType //enum for internet (default) |intranet
|
||||
Direction string // enum ingress egress
|
||||
NicType NicType //enum for internet (default) |intranet
|
||||
Direction Direction // enum ingress egress
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -64,7 +76,8 @@ type DescribeSecurityGroupAttributeResponse struct {
|
|||
Permissions struct {
|
||||
Permission []PermissionType
|
||||
}
|
||||
VpcId string
|
||||
VpcId string
|
||||
InnerAccessPolicy GroupInnerAccessPolicy
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -197,6 +210,21 @@ func (client *Client) ModifySecurityGroupAttribute(args *ModifySecurityGroupAttr
|
|||
return err
|
||||
}
|
||||
|
||||
type ModifySecurityGroupPolicyArgs struct {
|
||||
RegionId common.Region
|
||||
SecurityGroupId string
|
||||
InnerAccessPolicy GroupInnerAccessPolicy
|
||||
}
|
||||
|
||||
// ModifySecurityGroupPolicy modifies inner access policy of security group
|
||||
//
|
||||
// You can read doc at https://www.alibabacloud.com/help/doc-detail/57315.htm
|
||||
func (client *Client) ModifySecurityGroupPolicy(args *ModifySecurityGroupPolicyArgs) error {
|
||||
response := common.Response{}
|
||||
err := client.Invoke("ModifySecurityGroupPolicy", args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
type AuthorizeSecurityGroupArgs struct {
|
||||
SecurityGroupId string
|
||||
RegionId common.Region
|
||||
|
|
|
@ -26,6 +26,8 @@ type SnapshotType struct {
|
|||
SourceDiskSize int
|
||||
SourceDiskType string //enum for System | Data
|
||||
ProductCode string
|
||||
Status string
|
||||
Usage string
|
||||
CreationTime util.ISO6801Time
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ func (client *Client) DescribeSnatTableEntries(args *DescribeSnatTableEntriesArg
|
|||
return response.SnatTableEntries.SnatTableEntry, &response.PaginationResult, nil
|
||||
}
|
||||
|
||||
func (client *Client) DescribeSnatTableEntriesWithRaw(args *DescribeSnatTableEntriesArgs) ( response *DescribeSnatTableEntriesResponse, err error) {
|
||||
func (client *Client) DescribeSnatTableEntriesWithRaw(args *DescribeSnatTableEntriesArgs) (response *DescribeSnatTableEntriesResponse, err error) {
|
||||
args.Validate()
|
||||
response = &DescribeSnatTableEntriesResponse{}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ type CreateKeyPairResponse struct {
|
|||
// CreateKeyPair creates keypair
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/51771.html?spm=5176.doc51775.6.910.cedjfr
|
||||
func (client *Client) CreateKeyPair(args *CreateKeyPairArgs) (resp *CreateKeyPairResponse,err error) {
|
||||
func (client *Client) CreateKeyPair(args *CreateKeyPairArgs) (resp *CreateKeyPairResponse, err error) {
|
||||
response := CreateKeyPairResponse{}
|
||||
err = client.Invoke("CreateKeyPair", args, &response)
|
||||
if err != nil {
|
||||
|
@ -43,7 +43,7 @@ type ImportKeyPairResponse struct {
|
|||
// ImportKeyPair import keypair
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/51774.html?spm=5176.doc51771.6.911.BicQq2
|
||||
func (client *Client) ImportKeyPair(args *ImportKeyPairArgs) (resp *ImportKeyPairResponse,err error) {
|
||||
func (client *Client) ImportKeyPair(args *ImportKeyPairArgs) (resp *ImportKeyPairResponse, err error) {
|
||||
response := ImportKeyPairResponse{}
|
||||
err = client.Invoke("ImportKeyPair", args, &response)
|
||||
if err != nil {
|
||||
|
@ -69,14 +69,14 @@ type DescribeKeyPairsResponse struct {
|
|||
common.PaginationResult
|
||||
RegionId common.Region
|
||||
KeyPairs struct {
|
||||
KeyPair []KeyPairItemType
|
||||
KeyPair []KeyPairItemType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeKeyPairs describe keypairs
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/51773.html?spm=5176.doc51774.6.912.lyE0iX
|
||||
func (client *Client) DescribeKeyPairs(args *DescribeKeyPairsArgs) (KeyPairs []KeyPairItemType, pagination *common.PaginationResult, err error) {
|
||||
func (client *Client) DescribeKeyPairs(args *DescribeKeyPairsArgs) (KeyPairs []KeyPairItemType, pagination *common.PaginationResult, err error) {
|
||||
response, err := client.DescribeKeyPairsWithRaw(args)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -149,5 +149,3 @@ func (client *Client) DeleteKeyPairs(args *DeleteKeyPairsArgs) (err error) {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ type VpcSetType struct {
|
|||
Description string
|
||||
IsDefault bool
|
||||
CreationTime util.ISO6801Time
|
||||
RouterTableIds struct{
|
||||
RouterTableIds []string
|
||||
}
|
||||
}
|
||||
|
||||
type DescribeVpcsResponse struct {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ecs
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type ResourceType string
|
||||
|
||||
|
@ -15,19 +17,20 @@ const (
|
|||
type SupportedResourceType string
|
||||
|
||||
const (
|
||||
SupportedInstanceType = SupportedResourceType("supportedInstanceType")
|
||||
SupportedInstanceTypeFamily = SupportedResourceType("supportedInstanceTypeFamily")
|
||||
SupportedInstanceGeneration = SupportedResourceType("supportedInstanceGeneration")
|
||||
SupportedSystemDiskCategory = SupportedResourceType("supportedSystemDiskCategory")
|
||||
SupportedDataDiskCategory = SupportedResourceType("supportedDataDiskCategory")
|
||||
SupportedNetworkCategory = SupportedResourceType("supportedNetworkCategory")
|
||||
|
||||
SupportedInstanceType = SupportedResourceType("supportedInstanceType")
|
||||
SupportedInstanceTypeFamily = SupportedResourceType("supportedInstanceTypeFamily")
|
||||
SupportedInstanceGeneration = SupportedResourceType("supportedInstanceGeneration")
|
||||
SupportedSystemDiskCategory = SupportedResourceType("supportedSystemDiskCategory")
|
||||
SupportedDataDiskCategory = SupportedResourceType("supportedDataDiskCategory")
|
||||
SupportedNetworkCategory = SupportedResourceType("supportedNetworkCategory")
|
||||
)
|
||||
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/25670.html?spm=5176.doc25640.2.1.J24zQt
|
||||
type ResourcesInfoType struct {
|
||||
ResourcesInfo []AvailableResourcesType
|
||||
}
|
||||
|
||||
// Because the sub-item of AvailableResourcesType starts with supported and golang struct cann't refer them, this uses map to parse ResourcesInfo
|
||||
type AvailableResourcesType struct {
|
||||
IoOptimized bool
|
||||
|
@ -64,7 +67,7 @@ type AvailableInstanceTypesType struct {
|
|||
type ZoneType struct {
|
||||
ZoneId string
|
||||
LocalName string
|
||||
AvailableResources ResourcesInfoType
|
||||
AvailableResources ResourcesInfoType
|
||||
AvailableInstanceTypes AvailableInstanceTypesType
|
||||
AvailableResourceCreation AvailableResourceCreationType
|
||||
AvailableDiskCategories AvailableDiskCategoriesType
|
||||
|
@ -101,3 +104,55 @@ func (client *Client) DescribeZonesWithRaw(regionId common.Region) (response *De
|
|||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DescribeAvailableResourceArgs struct {
|
||||
RegionId string
|
||||
DestinationResource string
|
||||
ZoneId string
|
||||
InstanceChargeType string
|
||||
SpotStrategy string
|
||||
IoOptimized string
|
||||
InstanceType string
|
||||
SystemDiskCategory string
|
||||
DataDiskCategory string
|
||||
NetworkCategory string
|
||||
}
|
||||
|
||||
type DescribeAvailableResourceResponse struct {
|
||||
common.Response
|
||||
AvailableZones struct {
|
||||
AvailableZone []AvailableZoneType
|
||||
}
|
||||
}
|
||||
|
||||
type AvailableZoneType struct {
|
||||
RegionId string
|
||||
ZoneId string
|
||||
Status string
|
||||
AvailableResources struct {
|
||||
AvailableResource []NewAvailableResourcesType
|
||||
}
|
||||
}
|
||||
|
||||
type NewAvailableResourcesType struct {
|
||||
Type string
|
||||
SupportedResources struct {
|
||||
SupportedResource []SupportedResourcesType
|
||||
}
|
||||
}
|
||||
|
||||
type SupportedResourcesType struct {
|
||||
Value string
|
||||
Status string
|
||||
Min string
|
||||
Max string
|
||||
Unit string
|
||||
}
|
||||
|
||||
// https://www.alibabacloud.com/help/doc-detail/66186.htm
|
||||
func (client *Client) DescribeAvailableResource(args *DescribeAvailableResourceArgs) (response *DescribeAvailableResourceResponse, err error) {
|
||||
|
||||
response = &DescribeAvailableResourceResponse{}
|
||||
err = client.Invoke("DescribeAvailableResource", args, response)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -81,4 +81,7 @@ type RamClientInterface interface {
|
|||
ClearAccountAlias() (RamCommonResponse, error)
|
||||
SetPasswordPolicy(passwordPolicy PasswordPolicyRequest) (PasswordPolicyResponse, error)
|
||||
GetPasswordPolicy() (PasswordPolicyResponse, error)
|
||||
|
||||
// Common Client Methods
|
||||
SetUserAgent(userAgent string)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ type GroupListResponse struct {
|
|||
RamCommonResponse
|
||||
IsTruncated bool
|
||||
Marker string
|
||||
Groups struct {
|
||||
Groups struct {
|
||||
Group []Group
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ type PolicyQueryResponse struct {
|
|||
RamCommonResponse
|
||||
IsTruncated bool
|
||||
Marker string
|
||||
Policies struct {
|
||||
Policies struct {
|
||||
Policy []Policy
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
package slb
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type UploadServerCertificateArgs struct {
|
||||
RegionId common.Region
|
||||
ServerCertificate string
|
||||
ServerCertificateName string
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
type UploadServerCertificateResponse struct {
|
||||
common.Response
|
||||
ServerCertificateId string
|
||||
ServerCertificateName string
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
// UploadServerCertificate Upload server certificate
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#pub/slb/api-reference/api-servercertificate&UploadServerCertificate
|
||||
func (client *Client) UploadServerCertificate(args *UploadServerCertificateArgs) (response *UploadServerCertificateResponse, err error) {
|
||||
response = &UploadServerCertificateResponse{}
|
||||
err = client.Invoke("UploadServerCertificate", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DeleteServerCertificateArgs struct {
|
||||
RegionId common.Region
|
||||
ServerCertificateId string
|
||||
}
|
||||
|
||||
type DeleteServerCertificateResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// DeleteServerCertificate Delete server certificate
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#pub/slb/api-reference/api-servercertificate&DeleteServerCertificate
|
||||
func (client *Client) DeleteServerCertificate(regionId common.Region, serverCertificateId string) (err error) {
|
||||
args := &DeleteServerCertificateArgs{
|
||||
RegionId: regionId,
|
||||
ServerCertificateId: serverCertificateId,
|
||||
}
|
||||
response := &DeleteServerCertificateResponse{}
|
||||
return client.Invoke("DeleteServerCertificate", args, response)
|
||||
}
|
||||
|
||||
type SetServerCertificateNameArgs struct {
|
||||
RegionId common.Region
|
||||
ServerCertificateId string
|
||||
ServerCertificateName string
|
||||
}
|
||||
|
||||
type SetServerCertificateNameResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// SetServerCertificateName Set name of server certificate
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#pub/slb/api-reference/api-servercertificate&SetServerCertificateName
|
||||
func (client *Client) SetServerCertificateName(regionId common.Region, serverCertificateId string, name string) (err error) {
|
||||
args := &SetServerCertificateNameArgs{
|
||||
RegionId: regionId,
|
||||
ServerCertificateId: serverCertificateId,
|
||||
ServerCertificateName: name,
|
||||
}
|
||||
response := &SetServerCertificateNameResponse{}
|
||||
return client.Invoke("SetServerCertificateName", args, response)
|
||||
}
|
||||
|
||||
type DescribeServerCertificatesArgs struct {
|
||||
RegionId common.Region
|
||||
ServerCertificateId string
|
||||
}
|
||||
|
||||
type ServerCertificateType struct {
|
||||
RegionId common.Region
|
||||
ServerCertificateId string
|
||||
ServerCertificateName string
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
type DescribeServerCertificatesResponse struct {
|
||||
common.Response
|
||||
ServerCertificates struct {
|
||||
ServerCertificate []ServerCertificateType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeServerCertificates Describe server certificates
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#pub/slb/api-reference/api-servercertificate&DescribeServerCertificates
|
||||
func (client *Client) DescribeServerCertificatesArgs(regionId common.Region, serverCertificateId string) (serverCertificates []ServerCertificateType, err error) {
|
||||
args := &DescribeServerCertificatesArgs{
|
||||
RegionId: regionId,
|
||||
ServerCertificateId: serverCertificateId,
|
||||
}
|
||||
response := &DescribeServerCertificatesResponse{}
|
||||
err = client.Invoke("DescribeServerCertificates", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.ServerCertificates.ServerCertificate, err
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
common.Client
|
||||
}
|
||||
|
||||
const (
|
||||
// SLBDefaultEndpoint is the default API endpoint of SLB services
|
||||
SLBDefaultEndpoint = "https://slb.aliyuncs.com"
|
||||
SLBAPIVersion = "2014-05-15"
|
||||
|
||||
SLBServiceCode = "slb"
|
||||
)
|
||||
|
||||
// NewClient creates a new instance of ECS client
|
||||
func NewClient(accessKeyId, accessKeySecret string) *Client {
|
||||
endpoint := os.Getenv("SLB_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = SLBDefaultEndpoint
|
||||
}
|
||||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
|
||||
client := &Client{}
|
||||
client.Init(endpoint, SLBAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewSLBClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
endpoint := os.Getenv("SLB_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = SLBDefaultEndpoint
|
||||
}
|
||||
|
||||
return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, SLBAPIVersion, accessKeyId, accessKeySecret, SLBServiceCode, regionID)
|
||||
return client
|
||||
}
|
|
@ -1,536 +0,0 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type ListenerStatus string
|
||||
|
||||
const (
|
||||
Starting = ListenerStatus("starting")
|
||||
Running = ListenerStatus("running")
|
||||
Configuring = ListenerStatus("configuring")
|
||||
Stopping = ListenerStatus("stopping")
|
||||
Stopped = ListenerStatus("stopped")
|
||||
)
|
||||
|
||||
type SchedulerType string
|
||||
|
||||
const (
|
||||
WRRScheduler = SchedulerType("wrr")
|
||||
WLCScheduler = SchedulerType("wlc")
|
||||
)
|
||||
|
||||
type FlagType string
|
||||
|
||||
const (
|
||||
OnFlag = FlagType("on")
|
||||
OffFlag = FlagType("off")
|
||||
)
|
||||
|
||||
type StickySessionType string
|
||||
|
||||
const (
|
||||
InsertStickySessionType = StickySessionType("insert")
|
||||
ServerStickySessionType = StickySessionType("server")
|
||||
)
|
||||
|
||||
const BackendServerPort = -520
|
||||
|
||||
type HealthCheckHttpCodeType string
|
||||
|
||||
const (
|
||||
HTTP_2XX = HealthCheckHttpCodeType("http_2xx")
|
||||
HTTP_3XX = HealthCheckHttpCodeType("http_3xx")
|
||||
HTTP_4XX = HealthCheckHttpCodeType("http_4xx")
|
||||
HTTP_5XX = HealthCheckHttpCodeType("http_5xx")
|
||||
)
|
||||
|
||||
func EncodeHealthCheckHttpCodeType(healthCheckHttpCodes []HealthCheckHttpCodeType) (HealthCheckHttpCodeType, error) {
|
||||
code := ""
|
||||
|
||||
if nil == healthCheckHttpCodes || len(healthCheckHttpCodes) < 1 {
|
||||
return "", fmt.Errorf("Invalid size of healthCheckHttpCodes")
|
||||
}
|
||||
|
||||
for _, healthCheckHttpCode := range healthCheckHttpCodes {
|
||||
if strings.EqualFold(string(HTTP_2XX), string(healthCheckHttpCode)) ||
|
||||
strings.EqualFold(string(HTTP_3XX), string(healthCheckHttpCode)) ||
|
||||
strings.EqualFold(string(HTTP_4XX), string(healthCheckHttpCode)) ||
|
||||
strings.EqualFold(string(HTTP_5XX), string(healthCheckHttpCode)) {
|
||||
if "" == code {
|
||||
code = string(healthCheckHttpCode)
|
||||
} else {
|
||||
if strings.Contains(code, string(healthCheckHttpCode)) {
|
||||
return "", fmt.Errorf("Duplicates healthCheckHttpCode(%v in %v)", healthCheckHttpCode, healthCheckHttpCodes)
|
||||
}
|
||||
code += code + "," + string(healthCheckHttpCode)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("Invalid healthCheckHttpCode(%v in %v)", healthCheckHttpCode, healthCheckHttpCodes)
|
||||
}
|
||||
}
|
||||
return HealthCheckHttpCodeType(code), nil
|
||||
}
|
||||
|
||||
type CommonLoadBalancerListenerResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type HTTPListenerType struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
BackendServerPort int
|
||||
Bandwidth int
|
||||
Scheduler SchedulerType
|
||||
StickySession FlagType
|
||||
StickySessionType StickySessionType
|
||||
CookieTimeout int
|
||||
Cookie string
|
||||
HealthCheck FlagType
|
||||
HealthCheckDomain string
|
||||
HealthCheckURI string
|
||||
HealthCheckConnectPort int
|
||||
HealthyThreshold int
|
||||
UnhealthyThreshold int
|
||||
HealthCheckTimeout int
|
||||
HealthCheckInterval int
|
||||
HealthCheckHttpCode HealthCheckHttpCodeType
|
||||
VServerGroup FlagType
|
||||
VServerGroupId string
|
||||
Gzip FlagType
|
||||
}
|
||||
type CreateLoadBalancerHTTPListenerArgs HTTPListenerType
|
||||
|
||||
// CreateLoadBalancerHTTPListener create HTTP listener on loadbalancer
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&CreateLoadBalancerHTTPListener
|
||||
func (client *Client) CreateLoadBalancerHTTPListener(args *CreateLoadBalancerHTTPListenerArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("CreateLoadBalancerHTTPListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type HTTPSListenerType struct {
|
||||
HTTPListenerType
|
||||
ServerCertificateId string
|
||||
}
|
||||
|
||||
type CreateLoadBalancerHTTPSListenerArgs HTTPSListenerType
|
||||
|
||||
// CreateLoadBalancerHTTPSListener create HTTPS listener on loadbalancer
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&CreateLoadBalancerHTTPSListener
|
||||
func (client *Client) CreateLoadBalancerHTTPSListener(args *CreateLoadBalancerHTTPSListenerArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("CreateLoadBalancerHTTPSListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type HealthCheckType string
|
||||
|
||||
const (
|
||||
TCPHealthCheckType = HealthCheckType("tcp")
|
||||
HTTPHealthCheckType = HealthCheckType("http")
|
||||
)
|
||||
|
||||
type TCPListenerType struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
BackendServerPort int
|
||||
Bandwidth int
|
||||
Scheduler SchedulerType
|
||||
PersistenceTimeout int
|
||||
HealthCheck FlagType
|
||||
HealthCheckType HealthCheckType
|
||||
HealthCheckDomain string
|
||||
HealthCheckURI string
|
||||
HealthCheckConnectPort int
|
||||
HealthyThreshold int
|
||||
UnhealthyThreshold int
|
||||
HealthCheckConnectTimeout int
|
||||
HealthCheckInterval int
|
||||
HealthCheckHttpCode HealthCheckHttpCodeType
|
||||
VServerGroup FlagType
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
type CreateLoadBalancerTCPListenerArgs TCPListenerType
|
||||
|
||||
// CreateLoadBalancerTCPListener create TCP listener on loadbalancer
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&CreateLoadBalancerTCPListener
|
||||
func (client *Client) CreateLoadBalancerTCPListener(args *CreateLoadBalancerTCPListenerArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("CreateLoadBalancerTCPListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type UDPListenerType struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
BackendServerPort int
|
||||
Bandwidth int
|
||||
Scheduler SchedulerType
|
||||
PersistenceTimeout int
|
||||
HealthCheck FlagType
|
||||
HealthCheckConnectPort int
|
||||
HealthyThreshold int
|
||||
UnhealthyThreshold int
|
||||
HealthCheckConnectTimeout int
|
||||
HealthCheckInterval int
|
||||
VServerGroup FlagType
|
||||
VServerGroupId string
|
||||
}
|
||||
type CreateLoadBalancerUDPListenerArgs UDPListenerType
|
||||
|
||||
// CreateLoadBalancerUDPListener create UDP listener on loadbalancer
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&CreateLoadBalancerUDPListener
|
||||
func (client *Client) CreateLoadBalancerUDPListener(args *CreateLoadBalancerUDPListenerArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("CreateLoadBalancerUDPListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type CommonLoadBalancerListenerArgs struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
}
|
||||
|
||||
// DeleteLoadBalancerListener Delete listener
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DeleteLoadBalancerListener
|
||||
func (client *Client) DeleteLoadBalancerListener(loadBalancerId string, port int) (err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("DeleteLoadBalancerListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
// StartLoadBalancerListener Start listener
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&StartLoadBalancerListener
|
||||
func (client *Client) StartLoadBalancerListener(loadBalancerId string, port int) (err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("StartLoadBalancerListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
// StopLoadBalancerListener Stop listener
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&StopLoadBalancerListener
|
||||
func (client *Client) StopLoadBalancerListener(loadBalancerId string, port int) (err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("StopLoadBalancerListener", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type AccessControlStatus string
|
||||
|
||||
const (
|
||||
OpenWhileList = AccessControlStatus("open_white_list")
|
||||
Close = AccessControlStatus("close")
|
||||
)
|
||||
|
||||
type SetListenerAccessControlStatusArgs struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
AccessControlStatus AccessControlStatus
|
||||
}
|
||||
|
||||
// SetListenerAccessControlStatus Set listener access control status
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&SetListenerAccessControlStatus
|
||||
func (client *Client) SetListenerAccessControlStatus(loadBalancerId string, port int, status AccessControlStatus) (err error) {
|
||||
args := &SetListenerAccessControlStatusArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
AccessControlStatus: status,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("SetListenerAccessControlStatus", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type CommonListenerWhiteListItemArgs struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
SourceItems string
|
||||
}
|
||||
|
||||
// AddListenerWhiteListItem Add listener white-list item
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&AddListenerWhiteListItem
|
||||
func (client *Client) AddListenerWhiteListItem(loadBalancerId string, port int, sourceItems string) (err error) {
|
||||
args := &CommonListenerWhiteListItemArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
SourceItems: sourceItems,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("AddListenerWhiteListItem", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveListenerWhiteListItem Remove listener white-list item
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&RemoveListenerWhiteListItem
|
||||
func (client *Client) RemoveListenerWhiteListItem(loadBalancerId string, port int, sourceItems string) (err error) {
|
||||
args := &CommonListenerWhiteListItemArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
SourceItems: sourceItems,
|
||||
}
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("RemoveListenerWhiteListItem", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type SetLoadBalancerHTTPListenerAttributeArgs CreateLoadBalancerHTTPListenerArgs
|
||||
|
||||
// SetLoadBalancerHTTPListenerAttribute Set HTTP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&SetLoadBalancerHTTPListenerAttribute
|
||||
func (client *Client) SetLoadBalancerHTTPListenerAttribute(args *SetLoadBalancerHTTPListenerAttributeArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("SetLoadBalancerHTTPListenerAttribute", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type SetLoadBalancerHTTPSListenerAttributeArgs CreateLoadBalancerHTTPSListenerArgs
|
||||
|
||||
// SetLoadBalancerHTTPSListenerAttribute Set HTTPS listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&SetLoadBalancerHTTPSListenerAttribute
|
||||
func (client *Client) SetLoadBalancerHTTPSListenerAttribute(args *SetLoadBalancerHTTPSListenerAttributeArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("SetLoadBalancerHTTPSListenerAttribute", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type SetLoadBalancerTCPListenerAttributeArgs CreateLoadBalancerTCPListenerArgs
|
||||
|
||||
// SetLoadBalancerTCPListenerAttribute Set TCP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&SetLoadBalancerTCPListenerAttribute
|
||||
func (client *Client) SetLoadBalancerTCPListenerAttribute(args *SetLoadBalancerTCPListenerAttributeArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("SetLoadBalancerTCPListenerAttribute", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type SetLoadBalancerUDPListenerAttributeArgs CreateLoadBalancerUDPListenerArgs
|
||||
|
||||
// SetLoadBalancerUDPListenerAttribute Set UDP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&SetLoadBalancerUDPListenerAttribute
|
||||
func (client *Client) SetLoadBalancerUDPListenerAttribute(args *SetLoadBalancerUDPListenerAttributeArgs) (err error) {
|
||||
response := &CommonLoadBalancerListenerResponse{}
|
||||
err = client.Invoke("SetLoadBalancerUDPListenerAttribute", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerListenerAttributeResponse struct {
|
||||
common.Response
|
||||
Status ListenerStatus
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerHTTPListenerAttributeResponse struct {
|
||||
DescribeLoadBalancerListenerAttributeResponse
|
||||
HTTPListenerType
|
||||
}
|
||||
|
||||
// DescribeLoadBalancerHTTPListenerAttribute Describe HTTP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DescribeLoadBalancerHTTPListenerAttribute
|
||||
func (client *Client) DescribeLoadBalancerHTTPListenerAttribute(loadBalancerId string, port int) (response *DescribeLoadBalancerHTTPListenerAttributeResponse, err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response = &DescribeLoadBalancerHTTPListenerAttributeResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancerHTTPListenerAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerHTTPSListenerAttributeResponse struct {
|
||||
DescribeLoadBalancerListenerAttributeResponse
|
||||
HTTPSListenerType
|
||||
}
|
||||
|
||||
// DescribeLoadBalancerHTTPSListenerAttribute Describe HTTPS listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DescribeLoadBalancerHTTPSListenerAttribute
|
||||
func (client *Client) DescribeLoadBalancerHTTPSListenerAttribute(loadBalancerId string, port int) (response *DescribeLoadBalancerHTTPSListenerAttributeResponse, err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response = &DescribeLoadBalancerHTTPSListenerAttributeResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancerHTTPSListenerAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerTCPListenerAttributeResponse struct {
|
||||
DescribeLoadBalancerListenerAttributeResponse
|
||||
TCPListenerType
|
||||
}
|
||||
|
||||
// DescribeLoadBalancerTCPListenerAttribute Describe TCP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DescribeLoadBalancerTCPListenerAttribute
|
||||
func (client *Client) DescribeLoadBalancerTCPListenerAttribute(loadBalancerId string, port int) (response *DescribeLoadBalancerTCPListenerAttributeResponse, err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response = &DescribeLoadBalancerTCPListenerAttributeResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancerTCPListenerAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerUDPListenerAttributeResponse struct {
|
||||
DescribeLoadBalancerListenerAttributeResponse
|
||||
UDPListenerType
|
||||
}
|
||||
|
||||
// DescribeLoadBalancerUDPListenerAttribute Describe UDP listener attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DescribeLoadBalancerUDPListenerAttribute
|
||||
func (client *Client) DescribeLoadBalancerUDPListenerAttribute(loadBalancerId string, port int) (response *DescribeLoadBalancerUDPListenerAttributeResponse, err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response = &DescribeLoadBalancerUDPListenerAttributeResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancerUDPListenerAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type ListenerType string
|
||||
|
||||
const (
|
||||
UDP = ListenerType("UDP")
|
||||
TCP = ListenerType("TCP")
|
||||
HTTP = ListenerType("HTTP")
|
||||
HTTPS = ListenerType("HTTPS")
|
||||
)
|
||||
|
||||
const DefaultWaitForInterval = 5 //5 seconds
|
||||
const DefaultTimeout = 60 //60 seconds
|
||||
|
||||
// WaitForListener waits for listener to given status
|
||||
func (client *Client) WaitForListener(loadBalancerId string, port int, listenerType ListenerType) (status ListenerStatus, err error) {
|
||||
timeout := DefaultTimeout
|
||||
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
|
||||
method := fmt.Sprintf("DescribeLoadBalancer%sListenerAttribute", listenerType)
|
||||
response := &DescribeLoadBalancerListenerAttributeResponse{}
|
||||
|
||||
for {
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
if timeout <= 0 {
|
||||
return response.Status, common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
//Sleep first to ensure the previous request is sent
|
||||
err = client.Invoke(method, args, response)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if response.Status == Running || response.Status == Stopped {
|
||||
break
|
||||
}
|
||||
}
|
||||
return response.Status, nil
|
||||
}
|
||||
|
||||
// WaitForListener waits for listener to given status
|
||||
func (client *Client) WaitForListenerAsyn(loadBalancerId string, port int, listenerType ListenerType, status ListenerStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = DefaultTimeout
|
||||
}
|
||||
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
|
||||
method := fmt.Sprintf("DescribeLoadBalancer%sListenerAttribute", listenerType)
|
||||
response := &DescribeLoadBalancerListenerAttributeResponse{}
|
||||
|
||||
for {
|
||||
err := client.Invoke(method, args, response)
|
||||
e, _ := err.(*common.Error)
|
||||
if e != nil {
|
||||
if e.StatusCode == 404 || e.Code == "InvalidLoadBalancerId.NotFound" {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
} else if response != nil && response.Status == status {
|
||||
//TODO
|
||||
break
|
||||
}
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DescribeListenerAccessControlAttributeResponse struct {
|
||||
common.Response
|
||||
AccessControlStatus AccessControlStatus
|
||||
SourceItems string
|
||||
}
|
||||
|
||||
// DescribeListenerAccessControlAttribute Describe listener access control attribute
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/slb/api-reference/api-related-listener&DescribeListenerAccessControlAttribute
|
||||
func (client *Client) DescribeListenerAccessControlAttribute(loadBalancerId string, port int) (response *DescribeListenerAccessControlAttributeResponse, err error) {
|
||||
args := &CommonLoadBalancerListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: port,
|
||||
}
|
||||
response = &DescribeListenerAccessControlAttributeResponse{}
|
||||
err = client.Invoke("DescribeListenerAccessControlAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/util"
|
||||
)
|
||||
|
||||
type AddressType string
|
||||
|
||||
const (
|
||||
InternetAddressType = AddressType("internet")
|
||||
IntranetAddressType = AddressType("intranet")
|
||||
)
|
||||
|
||||
type InternetChargeType string
|
||||
|
||||
const (
|
||||
PayByBandwidth = InternetChargeType("paybybandwidth")
|
||||
PayByTraffic = InternetChargeType("paybytraffic")
|
||||
)
|
||||
|
||||
type CreateLoadBalancerArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerName string
|
||||
AddressType AddressType
|
||||
VSwitchId string
|
||||
InternetChargeType InternetChargeType
|
||||
Bandwidth int
|
||||
ClientToken string
|
||||
}
|
||||
|
||||
type CreateLoadBalancerResponse struct {
|
||||
common.Response
|
||||
LoadBalancerId string
|
||||
Address string
|
||||
NetworkType string
|
||||
VpcId string
|
||||
VSwitchId string
|
||||
LoadBalancerName string
|
||||
}
|
||||
|
||||
// CreateLoadBalancer create loadbalancer
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&CreateLoadBalancer
|
||||
func (client *Client) CreateLoadBalancer(args *CreateLoadBalancerArgs) (response *CreateLoadBalancerResponse, err error) {
|
||||
response = &CreateLoadBalancerResponse{}
|
||||
err = client.Invoke("CreateLoadBalancer", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DeleteLoadBalancerArgs struct {
|
||||
LoadBalancerId string
|
||||
}
|
||||
|
||||
type DeleteLoadBalancerResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// DeleteLoadBalancer delete loadbalancer
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&DeleteLoadBalancer
|
||||
func (client *Client) DeleteLoadBalancer(loadBalancerId string) (err error) {
|
||||
args := &DeleteLoadBalancerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
}
|
||||
response := &DeleteLoadBalancerResponse{}
|
||||
err = client.Invoke("DeleteLoadBalancer", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type ModifyLoadBalancerInternetSpecArgs struct {
|
||||
LoadBalancerId string
|
||||
InternetChargeType InternetChargeType
|
||||
Bandwidth int
|
||||
}
|
||||
|
||||
type ModifyLoadBalancerInternetSpecResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// ModifyLoadBalancerInternetSpec Modify loadbalancer internet spec
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&ModifyLoadBalancerInternetSpec
|
||||
|
||||
func (client *Client) ModifyLoadBalancerInternetSpec(args *ModifyLoadBalancerInternetSpecArgs) (err error) {
|
||||
response := &ModifyLoadBalancerInternetSpecResponse{}
|
||||
err = client.Invoke("ModifyLoadBalancerInternetSpec", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type Status string
|
||||
|
||||
const InactiveStatus = Status("inactive")
|
||||
const ActiveStatus = Status("active")
|
||||
const LockedStatus = Status("locked")
|
||||
|
||||
type SetLoadBalancerStatusArgs struct {
|
||||
LoadBalancerId string
|
||||
LoadBalancerStatus Status
|
||||
}
|
||||
|
||||
type SetLoadBalancerStatusResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// SetLoadBalancerStatus Set loadbalancer status
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&SetLoadBalancerStatus
|
||||
|
||||
func (client *Client) SetLoadBalancerStatus(loadBalancerId string, status Status) (err error) {
|
||||
args := &SetLoadBalancerStatusArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
LoadBalancerStatus: status,
|
||||
}
|
||||
response := &SetLoadBalancerStatusResponse{}
|
||||
err = client.Invoke("SetLoadBalancerStatus", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type SetLoadBalancerNameArgs struct {
|
||||
LoadBalancerId string
|
||||
LoadBalancerName string
|
||||
}
|
||||
|
||||
type SetLoadBalancerNameResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// SetLoadBalancerName Set loadbalancer name
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&SetLoadBalancerName
|
||||
|
||||
func (client *Client) SetLoadBalancerName(loadBalancerId string, name string) (err error) {
|
||||
args := &SetLoadBalancerNameArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
LoadBalancerName: name,
|
||||
}
|
||||
response := &SetLoadBalancerNameResponse{}
|
||||
err = client.Invoke("SetLoadBalancerName", args, response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancersArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerId string
|
||||
LoadBalancerName string
|
||||
AddressType AddressType
|
||||
NetworkType string
|
||||
VpcId string
|
||||
VSwitchId string
|
||||
Address string
|
||||
InternetChargeType InternetChargeType
|
||||
ServerId string
|
||||
}
|
||||
|
||||
type ListenerPortAndProtocolType struct {
|
||||
ListenerPort int
|
||||
ListenerProtocol string
|
||||
}
|
||||
|
||||
type BackendServerType struct {
|
||||
ServerId string
|
||||
Weight int
|
||||
}
|
||||
|
||||
type LoadBalancerType struct {
|
||||
LoadBalancerId string
|
||||
LoadBalancerName string
|
||||
LoadBalancerStatus string
|
||||
Address string
|
||||
RegionId common.Region
|
||||
RegionIdAlias string
|
||||
AddressType AddressType
|
||||
VSwitchId string
|
||||
VpcId string
|
||||
NetworkType string
|
||||
Bandwidth int
|
||||
InternetChargeType InternetChargeType
|
||||
CreateTime string //Why not ISO 6801
|
||||
CreateTimeStamp util.ISO6801Time
|
||||
ListenerPorts struct {
|
||||
ListenerPort []int
|
||||
}
|
||||
ListenerPortsAndProtocol struct {
|
||||
ListenerPortAndProtocol []ListenerPortAndProtocolType
|
||||
}
|
||||
BackendServers struct {
|
||||
BackendServer []BackendServerType
|
||||
}
|
||||
}
|
||||
|
||||
type DescribeLoadBalancersResponse struct {
|
||||
common.Response
|
||||
LoadBalancers struct {
|
||||
LoadBalancer []LoadBalancerType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeLoadBalancers Describe loadbalancers
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&DescribeLoadBalancers
|
||||
|
||||
func (client *Client) DescribeLoadBalancers(args *DescribeLoadBalancersArgs) (loadBalancers []LoadBalancerType, err error) {
|
||||
response := &DescribeLoadBalancersResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.LoadBalancers.LoadBalancer, err
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerAttributeArgs struct {
|
||||
LoadBalancerId string
|
||||
}
|
||||
|
||||
type DescribeLoadBalancerAttributeResponse struct {
|
||||
common.Response
|
||||
LoadBalancerType
|
||||
}
|
||||
|
||||
// DescribeLoadBalancerAttribute Describe loadbalancer attribute
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&DescribeLoadBalancerAttribute
|
||||
|
||||
func (client *Client) DescribeLoadBalancerAttribute(loadBalancerId string) (loadBalancer *LoadBalancerType, err error) {
|
||||
args := &DescribeLoadBalancersArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
}
|
||||
response := &DescribeLoadBalancerAttributeResponse{}
|
||||
err = client.Invoke("DescribeLoadBalancerAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response.LoadBalancerType, err
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package slb
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DescribeRegionsArgs struct {
|
||||
}
|
||||
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype®iontype
|
||||
type RegionType struct {
|
||||
RegionId common.Region
|
||||
LocalName string
|
||||
}
|
||||
|
||||
type DescribeRegionsResponse struct {
|
||||
common.Response
|
||||
Regions struct {
|
||||
Region []RegionType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeRegions describes regions
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-loadbalancer&DescribeRegions
|
||||
func (client *Client) DescribeRegions() (regions []RegionType, err error) {
|
||||
response := DescribeRegionsResponse{}
|
||||
|
||||
err = client.Invoke("DescribeRegions", &DescribeRegionsArgs{}, &response)
|
||||
|
||||
if err != nil {
|
||||
return []RegionType{}, err
|
||||
}
|
||||
return response.Regions.Region, nil
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
package slb
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type CreateRulesResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type CreateRulesArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
RuleList string
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
RuleId string
|
||||
RuleName string
|
||||
Domain string
|
||||
Url string `json:",omitempty"`
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
// Create forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35226.html?spm=5176.doc35226.6.671.625Omh
|
||||
func (client *Client) CreateRules(args *CreateRulesArgs) error {
|
||||
response := CreateRulesResponse{}
|
||||
err := client.Invoke("CreateRules", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type DeleteRulesArgs struct {
|
||||
RegionId common.Region
|
||||
RuleIds string
|
||||
}
|
||||
|
||||
type DeleteRulesResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// Delete forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35227.html?spm=5176.doc35226.6.672.6iNBtR
|
||||
func (client *Client) DeleteRules(args *DeleteRulesArgs) error {
|
||||
response := DeleteRulesResponse{}
|
||||
err := client.Invoke("DeleteRules", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type SetRuleArgs struct {
|
||||
RegionId common.Region
|
||||
RuleId string
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
type SetRuleResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// Modify forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35228.html?spm=5176.doc35227.6.673.rq40a9
|
||||
func (client *Client) SetRule(args *SetRuleArgs) error {
|
||||
response := SetRuleResponse{}
|
||||
err := client.Invoke("SetRule", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeRuleAttributeArgs struct {
|
||||
RegionId common.Region
|
||||
RuleId string
|
||||
}
|
||||
|
||||
type DescribeRuleAttributeResponse struct {
|
||||
common.Response
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
Rule
|
||||
}
|
||||
|
||||
// Describe rule
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35229.html?spm=5176.doc35226.6.674.DRJeKJ
|
||||
func (client *Client) DescribeRuleAttribute(args *DescribeRuleAttributeArgs) (*DescribeRuleAttributeResponse, error) {
|
||||
response := &DescribeRuleAttributeResponse{}
|
||||
err := client.Invoke("DescribeRuleAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type DescribeRulesArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
}
|
||||
|
||||
type DescribeRulesResponse struct {
|
||||
common.Response
|
||||
Rules struct {
|
||||
Rule []Rule
|
||||
}
|
||||
}
|
||||
|
||||
// Describe rule
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35229.html?spm=5176.doc35226.6.674.DRJeKJ
|
||||
func (client *Client) DescribeRules(args *DescribeRulesArgs) (*DescribeRulesResponse, error) {
|
||||
response := &DescribeRulesResponse{}
|
||||
err := client.Invoke("DescribeRules", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type AddBackendServersArgs struct {
|
||||
LoadBalancerId string
|
||||
BackendServers string
|
||||
}
|
||||
|
||||
type SetBackendServersArgs AddBackendServersArgs
|
||||
|
||||
type AddBackendServersResponse struct {
|
||||
common.Response
|
||||
LoadBalancerId string
|
||||
BackendServers struct {
|
||||
BackendServer []BackendServerType
|
||||
}
|
||||
}
|
||||
|
||||
type SetBackendServersResponse AddBackendServersResponse
|
||||
|
||||
// SetBackendServers set weight of backend servers
|
||||
|
||||
func (client *Client) SetBackendServers(loadBalancerId string, backendServers []BackendServerType) (result []BackendServerType, err error) {
|
||||
bytes, _ := json.Marshal(backendServers)
|
||||
|
||||
args := &SetBackendServersArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
BackendServers: string(bytes),
|
||||
}
|
||||
response := &SetBackendServersResponse{}
|
||||
|
||||
err = client.Invoke("SetBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.BackendServers.BackendServer, err
|
||||
}
|
||||
|
||||
// AddBackendServers Add backend servers
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&AddBackendServers
|
||||
func (client *Client) AddBackendServers(loadBalancerId string, backendServers []BackendServerType) (result []BackendServerType, err error) {
|
||||
|
||||
bytes, _ := json.Marshal(backendServers)
|
||||
|
||||
args := &AddBackendServersArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
BackendServers: string(bytes),
|
||||
}
|
||||
response := &AddBackendServersResponse{}
|
||||
|
||||
err = client.Invoke("AddBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.BackendServers.BackendServer, err
|
||||
}
|
||||
|
||||
type RemoveBackendServersArgs struct {
|
||||
LoadBalancerId string
|
||||
BackendServers []string
|
||||
}
|
||||
|
||||
type RemoveBackendServersResponse struct {
|
||||
common.Response
|
||||
LoadBalancerId string
|
||||
BackendServers struct {
|
||||
BackendServer []BackendServerType
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveBackendServers Remove backend servers
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&RemoveBackendServers
|
||||
func (client *Client) RemoveBackendServers(loadBalancerId string, backendServers []string) (result []BackendServerType, err error) {
|
||||
args := &RemoveBackendServersArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
BackendServers: backendServers,
|
||||
}
|
||||
response := &RemoveBackendServersResponse{}
|
||||
err = client.Invoke("RemoveBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.BackendServers.BackendServer, err
|
||||
}
|
||||
|
||||
type HealthStatusType struct {
|
||||
ServerId string
|
||||
ServerHealthStatus string
|
||||
}
|
||||
|
||||
type DescribeHealthStatusArgs struct {
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
}
|
||||
|
||||
type DescribeHealthStatusResponse struct {
|
||||
common.Response
|
||||
BackendServers struct {
|
||||
BackendServer []HealthStatusType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeHealthStatus Describe health status
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&DescribeHealthStatus
|
||||
func (client *Client) DescribeHealthStatus(args *DescribeHealthStatusArgs) (response *DescribeHealthStatusResponse, err error) {
|
||||
response = &DescribeHealthStatusResponse{}
|
||||
err = client.Invoke("DescribeHealthStatus", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package slb
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type TagItem struct {
|
||||
TagKey string
|
||||
TagValue string
|
||||
}
|
||||
|
||||
type AddTagsArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerID string
|
||||
Tags string
|
||||
}
|
||||
|
||||
type AddTagsResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// AddTags Add tags to resource
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/42871.html
|
||||
func (client *Client) AddTags(args *AddTagsArgs) error {
|
||||
response := AddTagsResponse{}
|
||||
err := client.Invoke("AddTags", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type RemoveTagsArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerID string
|
||||
Tags string
|
||||
}
|
||||
|
||||
type RemoveTagsResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// RemoveTags remove tags to resource
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/42872.html
|
||||
func (client *Client) RemoveTags(args *RemoveTagsArgs) error {
|
||||
response := RemoveTagsResponse{}
|
||||
err := client.Invoke("RemoveTags", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type TagItemType struct {
|
||||
TagItem
|
||||
InstanceCount int
|
||||
}
|
||||
|
||||
type DescribeTagsArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerID string
|
||||
Tags string
|
||||
common.Pagination
|
||||
}
|
||||
|
||||
type DescribeTagsResponse struct {
|
||||
common.Response
|
||||
common.PaginationResult
|
||||
TagSets struct {
|
||||
TagSet []TagItemType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeResourceByTags describe resource by tags
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/42873.html?spm=5176.doc42872.6.267.CP1iWu
|
||||
func (client *Client) DescribeTags(args *DescribeTagsArgs) (tags []TagItemType, pagination *common.PaginationResult, err error) {
|
||||
args.Validate()
|
||||
response := DescribeTagsResponse{}
|
||||
err = client.Invoke("DescribeTags", args, &response)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return response.TagSets.TagSet, &response.PaginationResult, nil
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type VBackendServerType struct {
|
||||
ServerId string
|
||||
Weight int
|
||||
Port int
|
||||
}
|
||||
|
||||
type VServerGroup struct {
|
||||
VServerGroupName string
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
type VBackendServers struct {
|
||||
BackendServer []VBackendServerType
|
||||
}
|
||||
|
||||
type CreateVServerGroupArgs struct {
|
||||
LoadBalancerId string
|
||||
RegionId common.Region
|
||||
VServerGroupName string
|
||||
VServerGroupId string
|
||||
BackendServers string
|
||||
}
|
||||
|
||||
type SetVServerGroupAttributeArgs struct {
|
||||
LoadBalancerId string
|
||||
RegionId common.Region
|
||||
VServerGroupName string
|
||||
VServerGroupId string
|
||||
BackendServers string
|
||||
}
|
||||
|
||||
type AddVServerGroupBackendServersArgs CreateVServerGroupArgs
|
||||
type RemoveVServerGroupBackendServersArgs CreateVServerGroupArgs
|
||||
type ModifyVServerGroupBackendServersArgs struct {
|
||||
VServerGroupId string
|
||||
RegionId common.Region
|
||||
OldBackendServers string
|
||||
NewBackendServers string
|
||||
}
|
||||
|
||||
type DeleteVServerGroupArgs struct {
|
||||
VServerGroupId string
|
||||
RegionId common.Region
|
||||
}
|
||||
|
||||
type DescribeVServerGroupsArgs struct {
|
||||
LoadBalancerId string
|
||||
RegionId common.Region
|
||||
}
|
||||
|
||||
type DescribeVServerGroupAttributeArgs struct {
|
||||
VServerGroupId string
|
||||
RegionId common.Region
|
||||
}
|
||||
|
||||
type CreateVServerGroupResponse struct {
|
||||
common.Response
|
||||
VServerGroupId string
|
||||
VServerGroupName string
|
||||
BackendServers VBackendServers
|
||||
}
|
||||
|
||||
type SetVServerGroupAttributeResponse struct {
|
||||
common.Response
|
||||
VServerGroupId string
|
||||
VServerGroupName string
|
||||
BackendServers VBackendServers
|
||||
}
|
||||
|
||||
type AddVServerGroupBackendServersResponse CreateVServerGroupResponse
|
||||
type RemoveVServerGroupBackendServersResponse CreateVServerGroupResponse
|
||||
type ModifyVServerGroupBackendServersResponse CreateVServerGroupResponse
|
||||
type DeleteVServerGroupResponse struct{ common.Response }
|
||||
type DescribeVServerGroupsResponse struct {
|
||||
common.Response
|
||||
VServerGroups struct {
|
||||
VServerGroup []VServerGroup
|
||||
}
|
||||
}
|
||||
type DescribeVServerGroupAttributeResponse CreateVServerGroupResponse
|
||||
|
||||
|
||||
func (client *Client) CreateVServerGroup(args *CreateVServerGroupArgs) (response *CreateVServerGroupResponse, err error) {
|
||||
response = &CreateVServerGroupResponse{}
|
||||
err = client.Invoke("CreateVServerGroup", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) SetVServerGroupAttribute(args *SetVServerGroupAttributeArgs) (response *SetVServerGroupAttributeResponse, err error) {
|
||||
response = &SetVServerGroupAttributeResponse{}
|
||||
err = client.Invoke("SetVServerGroupAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) AddVServerGroupBackendServers(args *AddVServerGroupBackendServersArgs) (response *AddVServerGroupBackendServersResponse, err error) {
|
||||
response = &AddVServerGroupBackendServersResponse{}
|
||||
err = client.Invoke("AddVServerGroupBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) RemoveVServerGroupBackendServers(args *RemoveVServerGroupBackendServersArgs) (response *RemoveVServerGroupBackendServersResponse, err error) {
|
||||
response = &RemoveVServerGroupBackendServersResponse{}
|
||||
err = client.Invoke("RemoveVServerGroupBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) ModifyVServerGroupBackendServers(args *ModifyVServerGroupBackendServersArgs) (response *ModifyVServerGroupBackendServersResponse, err error) {
|
||||
response = &ModifyVServerGroupBackendServersResponse{}
|
||||
err = client.Invoke("ModifyVServerGroupBackendServers", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) DeleteVServerGroup(args *DeleteVServerGroupArgs) (response *DeleteVServerGroupResponse, err error) {
|
||||
response = &DeleteVServerGroupResponse{}
|
||||
err = client.Invoke("DeleteVServerGroup", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) DescribeVServerGroups(args *DescribeVServerGroupsArgs) (response *DescribeVServerGroupsResponse, err error) {
|
||||
response = &DescribeVServerGroupsResponse{}
|
||||
err = client.Invoke("DescribeVServerGroups", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func (client *Client) DescribeVServerGroupAttribute(args *DescribeVServerGroupAttributeArgs) (response *DescribeVServerGroupAttributeResponse, err error) {
|
||||
response = &DescribeVServerGroupAttributeResponse{}
|
||||
err = client.Invoke("DescribeVServerGroupAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
|
@ -62,6 +62,8 @@ func setQueryValues(i interface{}, values *url.Values, prefix string) {
|
|||
|
||||
fieldName := elemType.Field(i).Name
|
||||
anonymous := elemType.Field(i).Anonymous
|
||||
tag := elemType.Field(i).Tag.Get("query")
|
||||
argName := elemType.Field(i).Tag.Get("ArgName")
|
||||
field := elem.Field(i)
|
||||
// TODO Use Tag for validation
|
||||
// tag := typ.Field(i).Tag.Get("tagname")
|
||||
|
@ -116,15 +118,26 @@ func setQueryValues(i interface{}, values *url.Values, prefix string) {
|
|||
case reflect.String:
|
||||
l := field.Len()
|
||||
if l > 0 {
|
||||
strArray := make([]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
strArray[i] = field.Index(i).String()
|
||||
}
|
||||
bytes, err := json.Marshal(strArray)
|
||||
if err == nil {
|
||||
value = string(bytes)
|
||||
if tag == "list" {
|
||||
name := argName
|
||||
if argName == "" {
|
||||
name = fieldName
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
valueName := fmt.Sprintf("%s.%d", name, (i + 1))
|
||||
values.Set(valueName, field.Index(i).String())
|
||||
}
|
||||
} else {
|
||||
log.Printf("Failed to convert JSON: %v", err)
|
||||
strArray := make([]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
strArray[i] = field.Index(i).String()
|
||||
}
|
||||
bytes, err := json.Marshal(strArray)
|
||||
if err == nil {
|
||||
value = string(bytes)
|
||||
} else {
|
||||
log.Printf("Failed to convert JSON: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -162,8 +175,8 @@ func setQueryValues(i interface{}, values *url.Values, prefix string) {
|
|||
}
|
||||
}
|
||||
if value != "" {
|
||||
name := elemType.Field(i).Tag.Get("ArgName")
|
||||
if name == "" {
|
||||
name := argName
|
||||
if argName == "" {
|
||||
name = fieldName
|
||||
}
|
||||
if prefix != "" {
|
||||
|
|
|
@ -35,6 +35,5 @@ func CreateSignatureForRequest(method string, values *url.Values, accessKeySecre
|
|||
canonicalizedQueryString := percentReplace(values.Encode())
|
||||
|
||||
stringToSign := method + "&%2F&" + url.QueryEscape(canonicalizedQueryString)
|
||||
|
||||
return CreateSignature(stringToSign, accessKeySecret)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"bytes"
|
||||
srand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -64,6 +66,34 @@ func Encode(v url.Values) string {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
// Like Encode, but key and value are not escaped
|
||||
func EncodeWithoutEscape(v url.Values) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, 0, len(v))
|
||||
for k := range v {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
vs := v[k]
|
||||
prefix := k
|
||||
for _, v := range vs {
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteByte('&')
|
||||
}
|
||||
buf.WriteString(prefix)
|
||||
if v != "" {
|
||||
buf.WriteString("=")
|
||||
buf.WriteString(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func GetGMTime() string {
|
||||
return time.Now().UTC().Format(http.TimeFormat)
|
||||
}
|
||||
|
@ -145,3 +175,11 @@ func GenerateRandomECSPassword() string {
|
|||
return string(s)
|
||||
|
||||
}
|
||||
|
||||
func PrettyJson(object interface{}) string {
|
||||
b, err := json.MarshalIndent(object, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: PrettyJson, %v\n %s\n", err, b)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.DS_Store
|
||||
bin
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
language: go
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- tip
|
|
@ -0,0 +1 @@
|
|||
vendor/
|
|
@ -0,0 +1,8 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- "1.10"
|
||||
- tip
|
|
@ -1,5 +1,53 @@
|
|||
# Change Log
|
||||
|
||||
## [v1.11.1] - 2019-04-04
|
||||
|
||||
- #222 Fix Create Database Pools json fields - @sunny-b
|
||||
|
||||
## [v1.11.0] - 2019-04-03
|
||||
|
||||
- #220 roll out vpc functionality - @jheimann
|
||||
|
||||
## [v1.10.1] - 2019-03-27
|
||||
|
||||
- #219 Fix Database Pools json field - @sunny-b
|
||||
|
||||
## [v1.10.0] - 2019-03-20
|
||||
|
||||
- #215 Add support for Databases - @mikejholly
|
||||
|
||||
## [v1.9.0] - 2019-03-18
|
||||
|
||||
- #214 add support for enable_proxy_protocol. - @mregmi
|
||||
|
||||
## [v1.8.0] - 2019-03-13
|
||||
|
||||
- #210 Expose tags on storage volume create/list/get. - @jcodybaker
|
||||
|
||||
## [v1.7.5] - 2019-03-04
|
||||
|
||||
- #207 Add support for custom subdomains for Spaces CDN [beta] - @xornivore
|
||||
|
||||
## [v1.7.4] - 2019-02-08
|
||||
|
||||
- #202 Allow tagging volumes - @mchitten
|
||||
|
||||
## [v1.7.3] - 2018-12-18
|
||||
|
||||
- #196 Expose tag support for creating Load Balancers.
|
||||
|
||||
## [v1.7.2] - 2018-12-04
|
||||
|
||||
- #192 Exposes more options for Kubernetes clusters.
|
||||
|
||||
## [v1.7.1] - 2018-11-27
|
||||
|
||||
- #190 Expose constants for the state of Kubernetes clusters.
|
||||
|
||||
## [v1.7.0] - 2018-11-13
|
||||
|
||||
- #188 Kubernetes support [beta] - @aybabtme
|
||||
|
||||
## [v1.6.0] - 2018-10-16
|
||||
|
||||
- #185 Projects support [beta] - @mchitten
|
||||
|
|
|
@ -22,3 +22,27 @@ When working on code in this repository, tests can be run via:
|
|||
```sh
|
||||
go test .
|
||||
```
|
||||
|
||||
## Versioning
|
||||
|
||||
Godo follows [semver](https://www.semver.org) versioning semantics. New functionality should be accompanied by increment to the minor version number. The current strategy is to release often. Any code which is complete, tested, reviewed, and merged to master is worthy of release.
|
||||
|
||||
## Releasing
|
||||
|
||||
Releasing a new version of godo is currently a manual process.
|
||||
|
||||
1. Update the `CHANGELOG.md` with your changes. If a version header for the next (unreleased) version does not exist, create one. Include one bullet point for each piece of new functionality in the release, including the pull request ID, description, and author(s).
|
||||
|
||||
```
|
||||
## [v1.8.0] - 2019-03-13
|
||||
|
||||
- #210 Expose tags on storage volume create/list/get. - @jcodybaker
|
||||
- #123 Update test dependencies - @digitalocean
|
||||
```
|
||||
|
||||
2. Update the `libraryVersion` number in `godo.go`.
|
||||
3. Make a pull request with these changes. This PR should be separate from the PR containing the godo changes.
|
||||
4. Once the pull request has been merged, visit [https://github.com/digitalocean/godo/releases](https://github.com/digitalocean/godo/release) and click `Draft a new release`.
|
||||
5. Update the `Tag version` and `Release title` field with the new godo version. Be sure the version has a `v` prefixed in both places. Ex `v1.8.0`.
|
||||
6. Copy the changelog bullet points to the description field.
|
||||
7. Publish the release.
|
|
@ -14,7 +14,8 @@ type CDNService interface {
|
|||
List(context.Context, *ListOptions) ([]CDN, *Response, error)
|
||||
Get(context.Context, string) (*CDN, *Response, error)
|
||||
Create(context.Context, *CDNCreateRequest) (*CDN, *Response, error)
|
||||
UpdateTTL(context.Context, string, *CDNUpdateRequest) (*CDN, *Response, error)
|
||||
UpdateTTL(context.Context, string, *CDNUpdateTTLRequest) (*CDN, *Response, error)
|
||||
UpdateCustomDomain(context.Context, string, *CDNUpdateCustomDomainRequest) (*CDN, *Response, error)
|
||||
FlushCache(context.Context, string, *CDNFlushCacheRequest) (*Response, error)
|
||||
Delete(context.Context, string) (*Response, error)
|
||||
}
|
||||
|
@ -29,11 +30,13 @@ var _ CDNService = &CDNServiceOp{}
|
|||
|
||||
// CDN represents a DigitalOcean CDN
|
||||
type CDN struct {
|
||||
ID string `json:"id"`
|
||||
Origin string `json:"origin"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
TTL uint32 `json:"ttl"`
|
||||
ID string `json:"id"`
|
||||
Origin string `json:"origin"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
TTL uint32 `json:"ttl"`
|
||||
CertificateID string `json:"certificate_id,omitempty"`
|
||||
CustomDomain string `json:"custom_domain,omitempty"`
|
||||
}
|
||||
|
||||
// CDNRoot represents a response from the DigitalOcean API
|
||||
|
@ -48,15 +51,23 @@ type cdnsRoot struct {
|
|||
|
||||
// CDNCreateRequest represents a request to create a CDN.
|
||||
type CDNCreateRequest struct {
|
||||
Origin string `json:"origin"`
|
||||
TTL uint32 `json:"ttl"`
|
||||
Origin string `json:"origin"`
|
||||
TTL uint32 `json:"ttl"`
|
||||
CustomDomain string `json:"custom_domain,omitempty"`
|
||||
CertificateID string `json:"certificate_id,omitempty"`
|
||||
}
|
||||
|
||||
// CDNUpdateRequest represents a request to update the ttl of a CDN.
|
||||
type CDNUpdateRequest struct {
|
||||
// CDNUpdateTTLRequest represents a request to update the ttl of a CDN.
|
||||
type CDNUpdateTTLRequest struct {
|
||||
TTL uint32 `json:"ttl"`
|
||||
}
|
||||
|
||||
// CDNUpdateCustomDomainRequest represents a request to update the custom domain of a CDN.
|
||||
type CDNUpdateCustomDomainRequest struct {
|
||||
CustomDomain string `json:"custom_domain"`
|
||||
CertificateID string `json:"certificate_id"`
|
||||
}
|
||||
|
||||
// CDNFlushCacheRequest represents a request to flush cache of a CDN.
|
||||
type CDNFlushCacheRequest struct {
|
||||
Files []string `json:"files"`
|
||||
|
@ -128,8 +139,17 @@ func (c CDNServiceOp) Create(ctx context.Context, createRequest *CDNCreateReques
|
|||
return root.Endpoint, resp, err
|
||||
}
|
||||
|
||||
// UpdateTTL updates the ttl of individual CDN
|
||||
func (c CDNServiceOp) UpdateTTL(ctx context.Context, id string, updateRequest *CDNUpdateRequest) (*CDN, *Response, error) {
|
||||
// UpdateTTL updates the ttl of an individual CDN
|
||||
func (c CDNServiceOp) UpdateTTL(ctx context.Context, id string, updateRequest *CDNUpdateTTLRequest) (*CDN, *Response, error) {
|
||||
return c.update(ctx, id, updateRequest)
|
||||
}
|
||||
|
||||
// UpdateCustomDomain sets or removes the custom domain of an individual CDN
|
||||
func (c CDNServiceOp) UpdateCustomDomain(ctx context.Context, id string, updateRequest *CDNUpdateCustomDomainRequest) (*CDN, *Response, error) {
|
||||
return c.update(ctx, id, updateRequest)
|
||||
}
|
||||
|
||||
func (c CDNServiceOp) update(ctx context.Context, id string, updateRequest interface{}) (*CDN, *Response, error) {
|
||||
if updateRequest == nil {
|
||||
return nil, nil, NewArgError("updateRequest", "cannot be nil")
|
||||
}
|
||||
|
@ -137,7 +157,6 @@ func (c CDNServiceOp) UpdateTTL(ctx context.Context, id string, updateRequest *C
|
|||
if len(id) == 0 {
|
||||
return nil, nil, NewArgError("id", "cannot be an empty string")
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/%s", cdnBasePath, id)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, http.MethodPut, path, updateRequest)
|
||||
|
|
|
@ -0,0 +1,618 @@
|
|||
package godo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
databaseBasePath = "/v2/databases"
|
||||
databaseSinglePath = databaseBasePath + "/%s"
|
||||
databaseResizePath = databaseBasePath + "/%s/resize"
|
||||
databaseMigratePath = databaseBasePath + "/%s/migrate"
|
||||
databaseMaintenancePath = databaseBasePath + "/%s/maintenance"
|
||||
databaseBackupsPath = databaseBasePath + "/%s/backups"
|
||||
databaseUsersPath = databaseBasePath + "/%s/users"
|
||||
databaseUserPath = databaseBasePath + "/%s/users/%s"
|
||||
databaseDBPath = databaseBasePath + "/%s/dbs/%s"
|
||||
databaseDBsPath = databaseBasePath + "/%s/dbs"
|
||||
databasePoolPath = databaseBasePath + "/%s/pools/%s"
|
||||
databasePoolsPath = databaseBasePath + "/%s/pools"
|
||||
databaseReplicaPath = databaseBasePath + "/%s/replicas/%s"
|
||||
databaseReplicasPath = databaseBasePath + "/%s/replicas"
|
||||
)
|
||||
|
||||
// DatabasesService is an interface for interfacing with the databases endpoints
|
||||
// of the DigitalOcean API.
|
||||
// See: https://developers.digitalocean.com/documentation/v2#databases
|
||||
type DatabasesService interface {
|
||||
List(context.Context, *ListOptions) ([]Database, *Response, error)
|
||||
Get(context.Context, string) (*Database, *Response, error)
|
||||
Create(context.Context, *DatabaseCreateRequest) (*Database, *Response, error)
|
||||
Delete(context.Context, string) (*Response, error)
|
||||
Resize(context.Context, string, *DatabaseResizeRequest) (*Response, error)
|
||||
Migrate(context.Context, string, *DatabaseMigrateRequest) (*Response, error)
|
||||
UpdateMaintenance(context.Context, string, *DatabaseUpdateMaintenanceRequest) (*Response, error)
|
||||
ListBackups(context.Context, string, *ListOptions) ([]DatabaseBackup, *Response, error)
|
||||
GetUser(context.Context, string, string) (*DatabaseUser, *Response, error)
|
||||
ListUsers(context.Context, string, *ListOptions) ([]DatabaseUser, *Response, error)
|
||||
CreateUser(context.Context, string, *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error)
|
||||
DeleteUser(context.Context, string, string) (*Response, error)
|
||||
ListDBs(context.Context, string, *ListOptions) ([]DatabaseDB, *Response, error)
|
||||
CreateDB(context.Context, string, *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error)
|
||||
GetDB(context.Context, string, string) (*DatabaseDB, *Response, error)
|
||||
DeleteDB(context.Context, string, string) (*Response, error)
|
||||
ListPools(context.Context, string, *ListOptions) ([]DatabasePool, *Response, error)
|
||||
CreatePool(context.Context, string, *DatabaseCreatePoolRequest) (*DatabasePool, *Response, error)
|
||||
GetPool(context.Context, string, string) (*DatabasePool, *Response, error)
|
||||
DeletePool(context.Context, string, string) (*Response, error)
|
||||
GetReplica(context.Context, string, string) (*DatabaseReplica, *Response, error)
|
||||
ListReplicas(context.Context, string, *ListOptions) ([]DatabaseReplica, *Response, error)
|
||||
CreateReplica(context.Context, string, *DatabaseCreateReplicaRequest) (*DatabaseReplica, *Response, error)
|
||||
DeleteReplica(context.Context, string, string) (*Response, error)
|
||||
}
|
||||
|
||||
// DatabasesServiceOp handles communication with the Databases related methods
|
||||
// of the DigitalOcean API.
|
||||
type DatabasesServiceOp struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
var _ DatabasesService = &DatabasesServiceOp{}
|
||||
|
||||
// Database represents a DigitalOcean managed database product. These managed databases
|
||||
// are usually comprised of a cluster of database nodes, a primary and 0 or more replicas.
|
||||
// The EngineSlug is a string which indicates the type of database service. Some examples are
|
||||
// "pg", "mysql" or "redis". A Database also includes connection information and other
|
||||
// properties of the service like region, size and current status.
|
||||
type Database struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
EngineSlug string `json:"engine,omitempty"`
|
||||
VersionSlug string `json:"version,omitempty"`
|
||||
Connection *DatabaseConnection `json:"connection,omitempty"`
|
||||
Users []DatabaseUser `json:"users,omitempty"`
|
||||
NumNodes int `json:"num_nodes,omitempty"`
|
||||
SizeSlug string `json:"size,omitempty"`
|
||||
DBNames []string `json:"db_names,omitempty"`
|
||||
RegionSlug string `json:"region,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
MaintenanceWindow *DatabaseMaintenanceWindow `json:"maintenance_window,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseConnection represents a database connection
|
||||
type DatabaseConnection struct {
|
||||
URI string `json:"uri,omitempty"`
|
||||
Database string `json:"database,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
SSL bool `json:"ssl,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseUser represents a user in the database
|
||||
type DatabaseUser struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseMaintenanceWindow represents the maintenance_window of a database
|
||||
// cluster
|
||||
type DatabaseMaintenanceWindow struct {
|
||||
Day string `json:"day,omitempty"`
|
||||
Hour string `json:"hour,omitempty"`
|
||||
Pending bool `json:"pending,omitempty"`
|
||||
Description []string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseBackup represents a database backup.
|
||||
type DatabaseBackup struct {
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
SizeGigabytes float64 `json:"size_gigabytes,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseCreateRequest represents a request to create a database cluster
|
||||
type DatabaseCreateRequest struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
EngineSlug string `json:"engine,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
SizeSlug string `json:"size,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
NumNodes int `json:"num_nodes,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseResizeRequest can be used to initiate a database resize operation.
|
||||
type DatabaseResizeRequest struct {
|
||||
SizeSlug string `json:"size,omitempty"`
|
||||
NumNodes int `json:"num_nodes,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseMigrateRequest can be used to initiate a database migrate operation.
|
||||
type DatabaseMigrateRequest struct {
|
||||
Region string `json:"region,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseUpdateMaintenanceRequest can be used to update the database's maintenance window.
|
||||
type DatabaseUpdateMaintenanceRequest struct {
|
||||
Day string `json:"day,omitempty"`
|
||||
Hour string `json:"hour,omitempty"`
|
||||
}
|
||||
|
||||
// DatabaseDB represents an engine-specific database created within a database cluster. For SQL
|
||||
// databases like PostgreSQL or MySQL, a "DB" refers to a database created on the RDBMS. For instance,
|
||||
// a PostgreSQL database server can contain many database schemas, each with it's own settings, access
|
||||
// permissions and data. ListDBs will return all databases present on the server.
|
||||
type DatabaseDB struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DatabaseReplica represents a read-only replica of a particular database
|
||||
type DatabaseReplica struct {
|
||||
Name string `json:"name"`
|
||||
Connection *DatabaseConnection `json:"connection"`
|
||||
Region string `json:"region"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// DatabasePool represents a database connection pool
|
||||
type DatabasePool struct {
|
||||
User string `json:"user"`
|
||||
Name string `json:"name"`
|
||||
Size int `json:"size"`
|
||||
Database string `json:"db"`
|
||||
Mode string `json:"mode"`
|
||||
Connection *DatabaseConnection `json:"connection"`
|
||||
}
|
||||
|
||||
// DatabaseCreatePoolRequest is used to create a new database connection pool
|
||||
type DatabaseCreatePoolRequest struct {
|
||||
User string `json:"user"`
|
||||
Name string `json:"name"`
|
||||
Size int `json:"size"`
|
||||
Database string `json:"db"`
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
|
||||
// DatabaseCreateUserRequest is used to create a new database user
|
||||
type DatabaseCreateUserRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DatabaseCreateDBRequest is used to create a new engine-specific database within the cluster
|
||||
type DatabaseCreateDBRequest struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DatabaseCreateReplicaRequest is used to create a new read-only replica
|
||||
type DatabaseCreateReplicaRequest struct {
|
||||
Name string `json:"name"`
|
||||
Region string `json:"region"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
type databaseUserRoot struct {
|
||||
User *DatabaseUser `json:"user"`
|
||||
}
|
||||
|
||||
type databaseUsersRoot struct {
|
||||
Users []DatabaseUser `json:"users"`
|
||||
}
|
||||
|
||||
type databaseDBRoot struct {
|
||||
DB *DatabaseDB `json:"db"`
|
||||
}
|
||||
|
||||
type databaseDBsRoot struct {
|
||||
DBs []DatabaseDB `json:"dbs"`
|
||||
}
|
||||
|
||||
type databasesRoot struct {
|
||||
Databases []Database `json:"databases"`
|
||||
}
|
||||
|
||||
type databaseRoot struct {
|
||||
Database *Database `json:"database"`
|
||||
}
|
||||
|
||||
type databaseBackupsRoot struct {
|
||||
Backups []DatabaseBackup `json:"backups"`
|
||||
}
|
||||
|
||||
type databasePoolRoot struct {
|
||||
Pool *DatabasePool `json:"pool"`
|
||||
}
|
||||
|
||||
type databasePoolsRoot struct {
|
||||
Pools []DatabasePool `json:"pools"`
|
||||
}
|
||||
|
||||
type databaseReplicaRoot struct {
|
||||
Replica *DatabaseReplica `json:"replica"`
|
||||
}
|
||||
|
||||
type databaseReplicasRoot struct {
|
||||
Replicas []DatabaseReplica `json:"replicas"`
|
||||
}
|
||||
|
||||
// List returns a list of the Databases visible with the caller's API token
|
||||
func (svc *DatabasesServiceOp) List(ctx context.Context, opts *ListOptions) ([]Database, *Response, error) {
|
||||
path := databaseBasePath
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databasesRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Databases, resp, nil
|
||||
}
|
||||
|
||||
// Get retrieves the details of a database cluster
|
||||
func (svc *DatabasesServiceOp) Get(ctx context.Context, databaseID string) (*Database, *Response, error) {
|
||||
path := fmt.Sprintf(databaseSinglePath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Database, resp, nil
|
||||
}
|
||||
|
||||
// Create creates a database cluster
|
||||
func (svc *DatabasesServiceOp) Create(ctx context.Context, create *DatabaseCreateRequest) (*Database, *Response, error) {
|
||||
path := databaseBasePath
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, create)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Database, resp, nil
|
||||
}
|
||||
|
||||
// Delete deletes a database cluster. There is no way to recover a cluster once
|
||||
// it has been destroyed.
|
||||
func (svc *DatabasesServiceOp) Delete(ctx context.Context, databaseID string) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/%s", databaseBasePath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Resize resizes a database cluster by number of nodes or size
|
||||
func (svc *DatabasesServiceOp) Resize(ctx context.Context, databaseID string, resize *DatabaseResizeRequest) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseResizePath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, resize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Migrate migrates a database cluster to a new region
|
||||
func (svc *DatabasesServiceOp) Migrate(ctx context.Context, databaseID string, migrate *DatabaseMigrateRequest) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseMigratePath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, migrate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// UpdateMaintenance updates the maintenance window on a cluster
|
||||
func (svc *DatabasesServiceOp) UpdateMaintenance(ctx context.Context, databaseID string, maintenance *DatabaseUpdateMaintenanceRequest) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseMaintenancePath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPut, path, maintenance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ListBackups returns a list of the current backups of a database
|
||||
func (svc *DatabasesServiceOp) ListBackups(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseBackup, *Response, error) {
|
||||
path := fmt.Sprintf(databaseBackupsPath, databaseID)
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseBackupsRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Backups, resp, nil
|
||||
}
|
||||
|
||||
// GetUser returns the database user identified by userID
|
||||
func (svc *DatabasesServiceOp) GetUser(ctx context.Context, databaseID, userID string) (*DatabaseUser, *Response, error) {
|
||||
path := fmt.Sprintf(databaseUserPath, databaseID, userID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseUserRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.User, resp, nil
|
||||
}
|
||||
|
||||
// ListUsers returns all database users for the database
|
||||
func (svc *DatabasesServiceOp) ListUsers(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseUser, *Response, error) {
|
||||
path := fmt.Sprintf(databaseUsersPath, databaseID)
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseUsersRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Users, resp, nil
|
||||
}
|
||||
|
||||
// CreateUser will create a new database user
|
||||
func (svc *DatabasesServiceOp) CreateUser(ctx context.Context, databaseID string, createUser *DatabaseCreateUserRequest) (*DatabaseUser, *Response, error) {
|
||||
path := fmt.Sprintf(databaseUsersPath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createUser)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseUserRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.User, resp, nil
|
||||
}
|
||||
|
||||
// DeleteUser will delete an existing database user
|
||||
func (svc *DatabasesServiceOp) DeleteUser(ctx context.Context, databaseID, userID string) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseUserPath, databaseID, userID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ListDBs returns all databases for a given database cluster
|
||||
func (svc *DatabasesServiceOp) ListDBs(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseDB, *Response, error) {
|
||||
path := fmt.Sprintf(databaseDBsPath, databaseID)
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseDBsRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.DBs, resp, nil
|
||||
}
|
||||
|
||||
// GetDB returns a single database by name
|
||||
func (svc *DatabasesServiceOp) GetDB(ctx context.Context, databaseID, name string) (*DatabaseDB, *Response, error) {
|
||||
path := fmt.Sprintf(databaseDBPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseDBRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.DB, resp, nil
|
||||
}
|
||||
|
||||
// CreateDB will create a new database
|
||||
func (svc *DatabasesServiceOp) CreateDB(ctx context.Context, databaseID string, createDB *DatabaseCreateDBRequest) (*DatabaseDB, *Response, error) {
|
||||
path := fmt.Sprintf(databaseDBsPath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createDB)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseDBRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.DB, resp, nil
|
||||
}
|
||||
|
||||
// DeleteDB will delete an existing database
|
||||
func (svc *DatabasesServiceOp) DeleteDB(ctx context.Context, databaseID, name string) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseDBPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ListPools returns all connection pools for a given database cluster
|
||||
func (svc *DatabasesServiceOp) ListPools(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabasePool, *Response, error) {
|
||||
path := fmt.Sprintf(databasePoolsPath, databaseID)
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databasePoolsRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Pools, resp, nil
|
||||
}
|
||||
|
||||
// GetPool returns a single database connection pool by name
|
||||
func (svc *DatabasesServiceOp) GetPool(ctx context.Context, databaseID, name string) (*DatabasePool, *Response, error) {
|
||||
path := fmt.Sprintf(databasePoolPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databasePoolRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Pool, resp, nil
|
||||
}
|
||||
|
||||
// CreatePool will create a new database connection pool
|
||||
func (svc *DatabasesServiceOp) CreatePool(ctx context.Context, databaseID string, createPool *DatabaseCreatePoolRequest) (*DatabasePool, *Response, error) {
|
||||
path := fmt.Sprintf(databasePoolsPath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createPool)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databasePoolRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Pool, resp, nil
|
||||
}
|
||||
|
||||
// DeletePool will delete an existing database connection pool
|
||||
func (svc *DatabasesServiceOp) DeletePool(ctx context.Context, databaseID, name string) (*Response, error) {
|
||||
path := fmt.Sprintf(databasePoolPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetReplica returns a single database replica
|
||||
func (svc *DatabasesServiceOp) GetReplica(ctx context.Context, databaseID, name string) (*DatabaseReplica, *Response, error) {
|
||||
path := fmt.Sprintf(databaseReplicaPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseReplicaRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Replica, resp, nil
|
||||
}
|
||||
|
||||
// ListReplicas returns all read-only replicas for a given database cluster
|
||||
func (svc *DatabasesServiceOp) ListReplicas(ctx context.Context, databaseID string, opts *ListOptions) ([]DatabaseReplica, *Response, error) {
|
||||
path := fmt.Sprintf(databaseReplicasPath, databaseID)
|
||||
path, err := addOptions(path, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseReplicasRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Replicas, resp, nil
|
||||
}
|
||||
|
||||
// CreateReplica will create a new database connection pool
|
||||
func (svc *DatabasesServiceOp) CreateReplica(ctx context.Context, databaseID string, createReplica *DatabaseCreateReplicaRequest) (*DatabaseReplica, *Response, error) {
|
||||
path := fmt.Sprintf(databaseReplicasPath, databaseID)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodPost, path, createReplica)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
root := new(databaseReplicaRoot)
|
||||
resp, err := svc.client.Do(ctx, req, root)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
return root.Replica, resp, nil
|
||||
}
|
||||
|
||||
// DeleteReplica will delete an existing database replica
|
||||
func (svc *DatabasesServiceOp) DeleteReplica(ctx context.Context, databaseID, name string) (*Response, error) {
|
||||
path := fmt.Sprintf(databaseReplicaPath, databaseID, name)
|
||||
req, err := svc.client.NewRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := svc.client.Do(ctx, req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
|
@ -1,2 +1,11 @@
|
|||
// Package godo is the DigtalOcean API v2 client for Go
|
||||
//
|
||||
// Databases
|
||||
//
|
||||
// The Databases service provides access to the DigitalOcean managed database
|
||||
// suite of products. Customers can create new database clusters, migrate them
|
||||
// between regions, create replicas and interact with their configurations.
|
||||
// Each database service is refered to as a Database. A SQL database service
|
||||
// can have multiple databases residing in the system. To help make these
|
||||
// entities distinct from Databases in godo, we refer to them here as DatabaseDBs.
|
||||
package godo
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue