Revert the 0.12 SDK (#3158)

We aren't ready to release a `0.12` SDK based build because of these issues:

• https://github.com/hashicorp/terraform/issues/20505https://github.com/hashicorp/terraform/issues/20507https://github.com/hashicorp/terraform/issues/20506https://github.com/hashicorp/terraform/issues/20504
This commit is contained in:
Riley Karson 2019-02-28 16:33:44 -08:00 committed by GitHub
parent 190601fe38
commit 9ff66c4283
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
679 changed files with 21445 additions and 68391 deletions

32
go.mod
View File

@ -1,24 +1,48 @@
module github.com/terraform-providers/terraform-provider-google
require (
cloud.google.com/go v0.36.0
cloud.google.com/go v0.34.0
github.com/apparentlymart/go-cidr v1.0.0
github.com/aws/aws-sdk-go v1.16.24 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/davecgh/go-spew v1.1.1
github.com/dustinkirkland/golang-petname v0.0.0-20170921220637-d3c2ba80e75e // indirect
github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect
github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect
github.com/googleapis/gax-go v2.0.2+incompatible // indirect
github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-cleanhttp v0.5.0
github.com/hashicorp/go-getter v1.0.1 // indirect
github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f // indirect
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-plugin v0.0.0-20181212150838-f444068e8f5a // indirect
github.com/hashicorp/go-uuid v1.0.0 // indirect
github.com/hashicorp/go-version v1.1.0
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/terraform v0.12.0-alpha4.0.20190226230829-c2f653cf1a35
github.com/hashicorp/hcl2 v0.0.0-20181215005721-253da47fd604 // indirect
github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform v0.11.9-0.20180926212128-35d82b055591
github.com/hashicorp/vault v1.0.1 // indirect
github.com/keybase/go-crypto v0.0.0-20181127160227-255a5089e85a // indirect
github.com/mitchellh/cli v1.0.0 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/hashstructure v1.0.0
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/pierrec/lz4 v2.0.5+incompatible // indirect
github.com/stoewer/go-strcase v1.0.2
github.com/stretchr/testify v1.3.0 // indirect
github.com/terraform-providers/terraform-provider-random v2.0.0+incompatible
golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9
google.golang.org/api v0.1.0
github.com/zclconf/go-cty v0.0.0-20181218225846-4fe1e489ee06 // indirect
go.opencensus.io v0.18.0 // indirect
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 // indirect
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e // indirect
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890
golang.org/x/sys v0.0.0-20190123074212-c6b37f3e9285 // indirect
google.golang.org/api v0.0.0-20181217000635-41dc4b66e69d
google.golang.org/appengine v1.3.0 // indirect
google.golang.org/genproto v0.0.0-20181218023534-67d6565462c5 // indirect
google.golang.org/grpc v1.17.0 // indirect
)

269
go.sum
View File

@ -1,46 +1,19 @@
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.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.36.0 h1:+aCSj7tOo2LODWVEuZDZeGCckdt6MlSF+X/rB3wUiS8=
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/Azure/azure-sdk-for-go v21.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v10.15.4+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292/go.mod h1:KYCjqMOeHpNuTOiFQU6WEcTG7poCJrUs0YgyHNtn1no=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agl/ed25519 v0.0.0-20150830182803-278e1ec8e8a6/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antchfx/xpath v0.0.0-20190129040759-c8489ed3251e/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xquery v0.0.0-20180515051857-ad5b8c7a47b0/go.mod h1:LzD22aAzDP8/dyiCKFp31He4m2GPjl0AFyzDtZzUu9M=
github.com/apparentlymart/go-cidr v1.0.0 h1:lGDvXx8Lv9QHjrAVP7jyzleG4F9+FkRhJcEsDFxeb8w=
github.com/apparentlymart/go-cidr v1.0.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=
github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
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.36 h1:POeH34ZME++pr7GBGh+ZO6Y5kOwSMQpqp5BGUgooJ6k=
github.com/aws/aws-sdk-go v1.16.36/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
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/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=
@ -48,377 +21,189 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20161106042343-c914be64f07d/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.0.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustinkirkland/golang-petname v0.0.0-20170921220637-d3c2ba80e75e h1:bRcq7ruHMqCVB/ugLbBylx+LrccNACFDEaqAD/aZ80Q=
github.com/dustinkirkland/golang-petname v0.0.0-20170921220637-d3c2ba80e75e/go.mod h1:V+Qd57rJe8gd4eiGzZyg4h54VLHmYVVw54iMnlAMrF8=
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
github.com/dylanmei/winrmtest v0.0.0-20190225150635-99b7fe2fddf1/go.mod h1:lcy9/2gH1jn/VCLouHA6tOEwLoNVd4GW6zhuKLmHC2Y=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo=
github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI=
github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io=
github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
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/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
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/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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-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 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
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=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gophercloud/gophercloud v0.0.0-20190208042652-bc37892e1968/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gophercloud/utils v0.0.0-20190128072930-fbb6ab446f01/go.mod h1:wjDF8z83zTeg5eMLml5EBSlAhbF7G8DobyI1YsMuyzw=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/aws-sdk-go-base v0.2.0/go.mod h1:ZIWACGGi0N7a4DZbf15yuE1JQORmWLtBcVM6F5SXNFU=
github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-azure-helpers v0.0.0-20190129193224-166dfd221bb2/go.mod h1:lu62V//auUow6k0IykxLK2DCNW8qTmpm8KqhYVWattA=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
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.1.0 h1:iGVeg7L4V5FTFV3D6w+1NAyvth7BIWWSzD60pWloe2Q=
github.com/hashicorp/go-getter v1.1.0/go.mod h1:q+PoBhh16brIKwJS9kt18jEtXHTg2EGkmrA9P7HVS+U=
github.com/hashicorp/go-getter v1.0.1 h1:WlFPjyPrd34KmTQMzSPA0pn9JpRsuHjHaRTx0VPzxYw=
github.com/hashicorp/go-getter v1.0.1/go.mod h1:tkKN/c6I/LRSXLOWZ8wa/VB0LfVrryHzk/B0aZLKZI0=
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/go.mod h1:6ij3Z20p+OhOkCSrA0gImAWoHYQRGbnlcuk6XYTiaRw=
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-plugin v0.0.0-20190220160451-3f118e8ee104 h1:9iQ/zrTOJqzP+kH37s6xNb6T1RysiT7fnDD3DJbspVw=
github.com/hashicorp/go-plugin v0.0.0-20190220160451-3f118e8ee104/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-retryablehttp v0.5.1/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-plugin v0.0.0-20181212150838-f444068e8f5a h1:z9eTtDWoxYrJvtAD+xAepmTEfEmYgouWUytJ84UWAr8=
github.com/hashicorp/go-plugin v0.0.0-20181212150838-f444068e8f5a/go.mod h1:Ft7ju2vWzhO0ETMKUVo12XmXmII6eSUS4rsPTkY/siA=
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-slug v0.2.0/go.mod h1:+zDycQOzGqOqMW7Kn2fp9vz/NtqpMLQlgb9JUF+0km4=
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-tfe v0.3.10/go.mod h1:LHLchj07PCYgQqcyE5Sz+g4zrMNW+nALKbiSNTZedEs=
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl2 v0.0.0-20181208003705-670926858200/go.mod h1:ShfpTh661oAaxo7VcNxg0zcZW6jvMa7Moy2oFx7e5dE=
github.com/hashicorp/hcl2 v0.0.0-20190214011454-504b92060753 h1:8wCARxVLkMdcvxSaI2F/zL31FLQuAJkzIkayl5br8TY=
github.com/hashicorp/hcl2 v0.0.0-20190214011454-504b92060753/go.mod h1:HtEzazM5AZ9fviNEof8QZB4T1Vz9UhHrGhnMPzl//Ek=
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 h1:2yzhWGdgQUWZUCNK+AoO35V+HTsgEmcM4J9IkArh7PI=
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE=
github.com/hashicorp/hcl2 v0.0.0-20181215005721-253da47fd604 h1:k660QMbAqhL4vxSNPmvOAjzZJ7BQiwTrT8pa8RH3OEA=
github.com/hashicorp/hcl2 v0.0.0-20181215005721-253da47fd604/go.mod h1:ShfpTh661oAaxo7VcNxg0zcZW6jvMa7Moy2oFx7e5dE=
github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 h1:fooK5IvDL/KIsi4LxF/JH68nVdrBSiGNPhS2JAQjtjo=
github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250/go.mod h1:KHvg/R2/dPtaePb16oW4qIyzkMxXOL38xjRN64adsts=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE=
github.com/hashicorp/serf v0.0.0-20160124182025-e4ec8cc423bb/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE=
github.com/hashicorp/terraform v0.12.0-alpha4.0.20190226230829-c2f653cf1a35 h1:fXWLwWzGY4u82Srhx+Sm2ecM9ySQOFbzwZ/GPTPT0do=
github.com/hashicorp/terraform v0.12.0-alpha4.0.20190226230829-c2f653cf1a35/go.mod h1:IBJbeQNPU1HTVzDLsy6NBI/W70I4SW1+AE0D2cMzLao=
github.com/hashicorp/terraform-config-inspect v0.0.0-20190208230122-b0707673339c h1:nCnsfi66NloVlmquh5dLox5yBwQk5CV5s2roWvbstnE=
github.com/hashicorp/terraform-config-inspect v0.0.0-20190208230122-b0707673339c/go.mod h1:ItvqtvbC3K23FFET62ZwnkwtpbKZm8t8eMcWjmVVjD8=
github.com/hashicorp/vault v0.10.4/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
github.com/hashicorp/terraform v0.11.9-0.20180926212128-35d82b055591 h1:A2Bm1/dX0N2FRBqg10MgN0OYmdL/S8ZbgdmDvWmmQ7o=
github.com/hashicorp/terraform v0.11.9-0.20180926212128-35d82b055591/go.mod h1:uN1KUiT7Wdg61fPwsGXQwK3c8PmpIVZrt5Vcb1VrSoM=
github.com/hashicorp/vault v1.0.1 h1:x3hcjkJLd5L4ehPhZcraokFO7dq8MJ3oKvQtrkIiIU8=
github.com/hashicorp/vault v1.0.1/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
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=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/joyent/triton-go v0.0.0-20180313100802-d8f9c0314926/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA=
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/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
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/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
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/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82/go.mod h1:y54tfGmO3NKssKveTEFFzH8C/akrSOy/iW9qEAUDV84=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b/go.mod h1:wr1VqkwW0AB5JS0QLy5GpVMS9E3VtRoSYXUYyVk46KY=
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-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-shellwords v1.0.4/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
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.8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
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/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb/go.mod h1:OaY7UOoTkkrX3wRwjpYRKafIkkyeD0UtweSHAWWiqQM=
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-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/panicwrap v0.0.0-20190213213626-17011010aaa4/go.mod h1:YYMf4xtQnR8LRC0vKi3afvQ5QwRPQ17zjcpkBCufb+I=
github.com/mitchellh/prefixedio v0.0.0-20190213213902-5733675afd51/go.mod h1:kB1naBgV9ORnkiTVeyJOI1DavaJkG4oNIq0Af6ZVKUo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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 v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6DI=
github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
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/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
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 v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
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/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M=
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stoewer/go-strcase v1.0.2 h1:l3iQ2FPu8+36ars/7syO1dQAkjwMCb1IE3J+Th0ohfE=
github.com/stoewer/go-strcase v1.0.2/go.mod h1:eLfe5bL3qbL7ep/KafHzthxejrOF5J3xmt03uL5tzek=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d/go.mod h1:BSTlc8jOjh0niykqEGVXOLXdi9o0r0kR8tCYiMvjFgw=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/terraform-providers/terraform-provider-openstack v1.15.0/go.mod h1:2aQ6n/BtChAl1y2S60vebhyJyZXBsuAI5G4+lHrT1Ew=
github.com/terraform-providers/terraform-provider-random v2.0.0+incompatible h1:4wuExSWk/NHYS95P2H4KGv22bsabuDjGk5cFikIYzuU=
github.com/terraform-providers/terraform-provider-random v2.0.0+incompatible/go.mod h1:1U2balY0mfjMnO5iotT60EuFqDJxqP433wJcybviCTw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU=
github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/zclconf/go-cty v0.0.0-20181129180422-88fbe721e0f8/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v0.0.0-20190124225737-a385d646c1e9/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v0.0.0-20190201220620-4ca19710f056 h1:C6LhH3JHz2k6tnw5sYXBc8rD8SD/qFp6EhiZAcVyalk=
github.com/zclconf/go-cty v0.0.0-20190201220620-4ca19710f056/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v0.0.0-20181218225846-4fe1e489ee06 h1:J3bfEicd/d85VHC6bPhrKb+2jO+Uquiy2bnkhia6XBA=
github.com/zclconf/go-cty v0.0.0-20181218225846-4fe1e489ee06/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
go.opencensus.io v0.18.0 h1:Mk5rgZcggtbvtAun5aJzAtjKKN/t0R3jJPlWILlv938=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
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-20180816225734-aabede6cba87/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY=
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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/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-20180811021610-c39426892332/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-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=
golang.org/x/net v0.0.0-20181129055619-fae4c4e3ad76/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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/net v0.0.0-20190119204137-ed066c81e75e h1:MDa3fSUp6MdYHouVmCCNz/zaH2a6CRcxY3VhT/K3C5Q=
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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/oauth2 v0.0.0-20190220154721-9b3c75971fc9 h1:pfyU+l9dEu0vZzDDMsdAKa1gZbJYEn6urYXj/+Xkz7s=
golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
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/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/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/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190123074212-c6b37f3e9285 h1:b5t9HsJXzMmseFB6KtTJWSEtPP8SlVI5nFdf4hnoRFY=
golang.org/x/sys v0.0.0-20190123074212-c6b37f3e9285/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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
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/api v0.0.0-20181217000635-41dc4b66e69d h1:VhRqKr7/NDe5MpNpIj6Cy1xiwcVL4ZPs2GjTYziBRRg=
google.golang.org/api v0.0.0-20181217000635-41dc4b66e69d/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
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 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
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/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=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922 h1:mBVYJnbrXLA/ZCBTCe7PtEgAUP+1bg92qTaFoPHdz+8=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
google.golang.org/genproto v0.0.0-20181218023534-67d6565462c5 h1:ZcmLUbATcwP+ZlsJ5pn5qeF9O3pC7U7mYpSnHH7RFFs=
google.golang.org/genproto v0.0.0-20181218023534-67d6565462c5/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
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=
google.golang.org/grpc v1.18.0 h1:IZl7mfBGfbhYx2p2rKRtYgDFw6SBz+kclmxYrCksPPA=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
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/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
labix.org/v2/mgo v0.0.0-20140701140051-000000000287/go.mod h1:Lg7AYkt1uXJoR9oeSZ3W/8IXLdvOfIITgZnommstyz4=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@ -385,7 +385,7 @@ func (ac *AdminClient) Snapshots(ctx context.Context, cluster string) *SnapshotI
for _, s := range resp.Snapshots {
snapshotInfo, err := newSnapshotInfo(s)
if err != nil {
return "", fmt.Errorf("failed to parse snapshot proto %v", err)
return "", fmt.Errorf("Failed to parse snapshot proto %v", err)
}
it.items = append(it.items, snapshotInfo)
}
@ -407,12 +407,12 @@ func newSnapshotInfo(snapshot *btapb.Snapshot) (*SnapshotInfo, error) {
createTime, err := ptypes.Timestamp(snapshot.CreateTime)
if err != nil {
return nil, fmt.Errorf("invalid createTime: %v", err)
return nil, fmt.Errorf("Invalid createTime: %v", err)
}
deleteTime, err := ptypes.Timestamp(snapshot.DeleteTime)
if err != nil {
return nil, fmt.Errorf("invalid deleteTime: %v", err)
return nil, fmt.Errorf("Invalid deleteTime: %v", err)
}
return &SnapshotInfo{
@ -1064,7 +1064,9 @@ func (iac *InstanceAdminClient) ListAppProfiles(ctx context.Context, instanceID
return "", err
}
pit.items = append(pit.items, profileRes.AppProfiles...)
for _, a := range profileRes.AppProfiles {
pit.items = append(pit.items, a)
}
return profileRes.NextPageToken, nil
}

View File

@ -71,7 +71,7 @@ func NewClientWithConfig(ctx context.Context, project, instance string, config C
o = append(o,
option.WithGRPCConnectionPool(4),
// Set the max size to correspond to server-side limits.
option.WithGRPCDialOption(grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(1<<28), grpc.MaxCallRecvMsgSize(1<<28))),
option.WithGRPCDialOption(grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(100<<20), grpc.MaxCallRecvMsgSize(100<<20))),
// TODO(grpc/grpc-go#1388) using connection pool without WithBlock
// can cause RPCs to fail randomly. We can delete this after the issue is fixed.
option.WithGRPCDialOption(grpc.WithBlock()))

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package gax is a snapshot from github.com/googleapis/gax-go/v2 with minor modifications.
// Package gax is a snapshot from github.com/googleapis/gax-go with minor modifications.
package gax
import (

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package gax is a snapshot from github.com/googleapis/gax-go/v2 with minor modifications.
// Package gax is a snapshot from github.com/googleapis/gax-go with minor modifications.
package gax
import (

View File

@ -137,7 +137,7 @@ func testOnGCE() bool {
resc := make(chan bool, 2)
// Try two strategies in parallel.
// See https://github.com/googleapis/google-cloud-go/issues/194
// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
go func() {
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
req.Header.Set("User-Agent", userAgent)
@ -300,8 +300,8 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
// being stable anyway.
host = metadataIP
}
u := "http://" + host + "/computeMetadata/v1/" + suffix
req, _ := http.NewRequest("GET", u, nil)
url := "http://" + host + "/computeMetadata/v1/" + suffix
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Metadata-Flavor", "Google")
req.Header.Set("User-Agent", userAgent)
res, err := c.hc.Do(req)
@ -312,13 +312,13 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
if res.StatusCode == http.StatusNotFound {
return "", "", NotDefinedError(suffix)
}
if res.StatusCode != 200 {
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
}
all, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", "", err
}
if res.StatusCode != 200 {
return "", "", &Error{Code: res.StatusCode, Message: string(all)}
}
return string(all), res.Header.Get("Etag"), nil
}
@ -499,15 +499,3 @@ func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) erro
}
}
}
// Error contains an error response from the server.
type Error struct {
// Code is the HTTP response status code.
Code int
// Message is the server response message.
Message string
}
func (e *Error) Error() string {
return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
}

View File

@ -23,14 +23,12 @@ package iam
import (
"context"
"fmt"
"time"
gax "github.com/googleapis/gax-go/v2"
gax "github.com/googleapis/gax-go"
pb "google.golang.org/genproto/googleapis/iam/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
)
// client abstracts the IAMPolicy API to allow multiple implementations.
@ -58,9 +56,6 @@ var withRetry = gax.WithRetry(func() gax.Retryer {
func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
var proto *pb.Policy
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
ctx = insertMetadata(ctx, md)
err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
var err error
proto, err = g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
@ -73,9 +68,6 @@ func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, erro
}
func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
ctx = insertMetadata(ctx, md)
return gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
_, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
Resource: resource,
@ -87,9 +79,6 @@ func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) err
func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
var res *pb.TestIamPermissionsResponse
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
ctx = insertMetadata(ctx, md)
err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
var err error
res, err = g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
@ -301,15 +290,3 @@ func memberIndex(m string, b *pb.Binding) int {
}
return -1
}
// insertMetadata inserts metadata into the given context
func insertMetadata(ctx context.Context, mds ...metadata.MD) context.Context {
out, _ := metadata.FromOutgoingContext(ctx)
out = out.Copy()
for _, md := range mds {
for k, v := range md {
out[k] = append(out[k], v...)
}
}
return metadata.NewOutgoingContext(ctx, out)
}

View File

@ -1,4 +1,4 @@
// Copyright 2019 Google LLC
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
// AUTO-GENERATED CODE. DO NOT EDIT.
// Package longrunning is an auto-generated package for the
// Google Long Running Operations API.
@ -85,4 +85,4 @@ func versionGo() string {
return "UNKNOWN"
}
const versionClient = "20190121"
const versionClient = "20181129"

View File

@ -1,4 +1,4 @@
// Copyright 2019 Google LLC
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
// AUTO-GENERATED CODE. DO NOT EDIT.
package longrunning
@ -22,7 +22,7 @@ import (
"time"
"github.com/golang/protobuf/proto"
gax "github.com/googleapis/gax-go/v2"
gax "github.com/googleapis/gax-go"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/api/transport"

View File

@ -30,7 +30,7 @@ import (
autogen "cloud.google.com/go/longrunning/autogen"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
gax "github.com/googleapis/gax-go/v2"
gax "github.com/googleapis/gax-go"
pb "google.golang.org/genproto/googleapis/longrunning"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

View File

@ -1,53 +1,2 @@
# Ignore docs files
_gh_pages
_site
# Ignore temporary files
README.html
coverage.out
.tmp
# Numerous always-ignore extensions
*.diff
*.err
*.log
*.orig
*.rej
*.swo
*.swp
*.vi
*.zip
*~
# OS or Editor folders
._*
.cache
.DS_Store
.idea
.project
.settings
.tmproj
*.esproj
*.sublime-project
*.sublime-workspace
nbproject
Thumbs.db
# Komodo
.komodotools
*.komodoproject
# SCSS-Lint
scss-lint-report.xml
# grunt-contrib-sass cache
.sass-cache
# Jekyll metadata
docs/.jekyll-metadata
# Folders to ignore
.build
.test
bower_components
node_modules

View File

@ -1,25 +1,70 @@
language: go
sudo: false
matrix:
fast_finish: true
include:
- go: 1.11.x
env: TEST_METHOD=goveralls
- go: 1.10.x
- go: tip
- go: 1.9.x
- go: 1.8.x
- go: 1.7.x
- go: 1.6.x
- go: 1.5.x
allow_failures:
- go: tip
- go: 1.9.x
- go: 1.8.x
- go: 1.7.x
- go: 1.6.x
- go: 1.5.x
script: ./test.sh $TEST_METHOD
go:
- 1.8
- 1.7.5
- 1.7.4
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7
- tip
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5
- 1.4.3
- 1.4.2
- 1.4.1
- 1.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3
- 1.2.2
- 1.2.1
- 1.2
- 1.1.2
- 1.1.1
- 1.1
before_install:
- go get github.com/mattn/goveralls
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
notifications:
email:
on_success: never
matrix:
fast_finish: true
allow_failures:
- go: tip
- go: 1.6.4
- go: 1.6.3
- go: 1.6.2
- go: 1.6.1
- go: 1.6
- go: 1.5.4
- go: 1.5.3
- go: 1.5.2
- go: 1.5.1
- go: 1.5
- go: 1.4.3
- go: 1.4.2
- go: 1.4.1
- go: 1.4
- go: 1.3.3
- go: 1.3.2
- go: 1.3.1
- go: 1.3
- go: 1.2.2
- go: 1.2.1
- go: 1.2
- go: 1.1.2
- go: 1.1.1
- go: 1.1

View File

@ -11,7 +11,7 @@ This package implements distance and similarity metrics for strings, based on th
## Project Status
v1.2.2 Stable: Guaranteed no breaking changes to the API in future v1.x releases. Probably safe to use in production, though provided on "AS IS" basis.
v1.2.1 Stable: Guaranteed no breaking changes to the API in future v1.x releases. Probably safe to use in production, though provided on "AS IS" basis.
This package is being actively maintained. If you encounter any problems or have any suggestions for improvement, please [open an issue](https://github.com/agext/levenshtein/issues). Pull requests are welcome.

View File

@ -1 +0,0 @@
module github.com/agext/levenshtein

View File

@ -1,10 +0,0 @@
set -ev
if [[ "$1" == "goveralls" ]]; then
echo "Testing with goveralls..."
go get github.com/mattn/goveralls
$HOME/gopath/bin/goveralls -service=travis-ci
else
echo "Testing with go test..."
go test -v ./...
fi

View File

@ -1 +0,0 @@
module github.com/armon/go-radix

View File

@ -185,107 +185,6 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"api.ecr": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{
Hostname: "api.ecr.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
"ap-northeast-2": endpoint{
Hostname: "api.ecr.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
"ap-south-1": endpoint{
Hostname: "api.ecr.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
"ap-southeast-1": endpoint{
Hostname: "api.ecr.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
"ap-southeast-2": endpoint{
Hostname: "api.ecr.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
"ca-central-1": endpoint{
Hostname: "api.ecr.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"eu-central-1": endpoint{
Hostname: "api.ecr.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
"eu-north-1": endpoint{
Hostname: "api.ecr.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
"eu-west-1": endpoint{
Hostname: "api.ecr.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
"eu-west-2": endpoint{
Hostname: "api.ecr.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
"eu-west-3": endpoint{
Hostname: "api.ecr.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
"sa-east-1": endpoint{
Hostname: "api.ecr.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
"us-east-1": endpoint{
Hostname: "api.ecr.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"us-east-2": endpoint{
Hostname: "api.ecr.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"us-west-1": endpoint{
Hostname: "api.ecr.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"us-west-2": endpoint{
Hostname: "api.ecr.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"api.mediatailor": service{
Endpoints: endpoints{
@ -321,33 +220,9 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-east-1-fips": endpoint{
Hostname: "api-fips.sagemaker.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"us-east-2": endpoint{},
"us-east-2-fips": endpoint{
Hostname: "api-fips.sagemaker.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"us-west-1": endpoint{},
"us-west-1-fips": endpoint{
Hostname: "api-fips.sagemaker.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"us-west-2": endpoint{},
"us-west-2-fips": endpoint{
Hostname: "api-fips.sagemaker.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"apigateway": service{
@ -407,7 +282,6 @@ var awsPartition = partition{
},
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
@ -504,7 +378,6 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
@ -899,9 +772,7 @@ var awsPartition = partition{
Protocols: []string{"https"},
},
Endpoints: endpoints{
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"us-east-1": endpoint{},
@ -1019,7 +890,6 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
@ -1142,6 +1012,27 @@ var awsPartition = partition{
},
},
},
"ecr": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"ecs": service{
Endpoints: endpoints{
@ -1220,7 +1111,6 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
@ -1323,17 +1213,11 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"fips": endpoint{
Hostname: "es-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"events": service{
@ -1622,12 +1506,6 @@ var awsPartition = partition{
"kms": service{
Endpoints: endpoints{
"ProdFips": endpoint{
Hostname: "kms-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
@ -1667,22 +1545,6 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"license-manager": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
},
},
"lightsail": service{
Endpoints: endpoints{
@ -1898,12 +1760,6 @@ var awsPartition = partition{
"neptune": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{
Hostname: "rds.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
"ap-southeast-1": endpoint{
Hostname: "rds.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
@ -2082,8 +1938,6 @@ var awsPartition = partition{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-west-1": endpoint{},
"us-east-1": endpoint{},
@ -2535,7 +2389,6 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
@ -2918,7 +2771,6 @@ var awsPartition = partition{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
@ -3077,23 +2929,6 @@ var awscnPartition = partition{
},
},
Services: services{
"api.ecr": service{
Endpoints: endpoints{
"cn-north-1": endpoint{
Hostname: "api.ecr.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
"cn-northwest-1": endpoint{
Hostname: "api.ecr.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"apigateway": service{
Endpoints: endpoints{
@ -3214,6 +3049,13 @@ var awscnPartition = partition{
},
},
},
"ecr": service{
Endpoints: endpoints{
"cn-north-1": endpoint{},
"cn-northwest-1": endpoint{},
},
},
"ecs": service{
Endpoints: endpoints{
@ -3274,12 +3116,6 @@ var awscnPartition = partition{
"cn-northwest-1": endpoint{},
},
},
"gamelift": service{
Endpoints: endpoints{
"cn-north-1": endpoint{},
},
},
"glacier": service{
Defaults: endpoint{
Protocols: []string{"http", "https"},
@ -3518,23 +3354,6 @@ var awsusgovPartition = partition{
"us-gov-west-1": endpoint{},
},
},
"api.ecr": service{
Endpoints: endpoints{
"us-gov-east-1": endpoint{
Hostname: "api.ecr.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"us-gov-west-1": endpoint{
Hostname: "api.ecr.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"api.sagemaker": service{
Endpoints: endpoints{
@ -3560,12 +3379,6 @@ var awsusgovPartition = partition{
"us-gov-west-1": endpoint{},
},
},
"athena": service{
Endpoints: endpoints{
"us-gov-west-1": endpoint{},
},
},
"autoscaling": service{
Endpoints: endpoints{
@ -3689,6 +3502,13 @@ var awsusgovPartition = partition{
},
},
},
"ecr": service{
Endpoints: endpoints{
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
},
"ecs": service{
Endpoints: endpoints{
@ -3743,12 +3563,6 @@ var awsusgovPartition = partition{
"es": service{
Endpoints: endpoints{
"fips": endpoint{
Hostname: "es-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -3775,12 +3589,6 @@ var awsusgovPartition = partition{
},
},
},
"glue": service{
Endpoints: endpoints{
"us-gov-west-1": endpoint{},
},
},
"guardduty": service{
IsRegionalized: boxedTrue,
Defaults: endpoint{
@ -3830,12 +3638,6 @@ var awsusgovPartition = partition{
"kms": service{
Endpoints: endpoints{
"ProdFips": endpoint{
Hostname: "kms-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
@ -4071,11 +3873,5 @@ var awsusgovPartition = partition{
},
},
},
"workspaces": service{
Endpoints: endpoints{
"us-gov-west-1": endpoint{},
},
},
},
}

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.16.36"
const SDKVersion = "1.16.24"

1
vendor/github.com/googleapis/gax-go/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
*.cover

12
vendor/github.com/googleapis/gax-go/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,12 @@
sudo: false
language: go
go:
- 1.9.x
- 1.10.x
- 1.11.x
script:
- gofmt -l .
- go tool vet .
- go test -coverprofile=coverage.txt -covermode=atomic
after_success:
- bash <(curl -s https://codecov.io/bash)

43
vendor/github.com/googleapis/gax-go/CODE_OF_CONDUCT.md generated vendored Normal file
View File

@ -0,0 +1,43 @@
# Contributor Code of Conduct
As contributors and maintainers of this project,
and in the interest of fostering an open and welcoming community,
we pledge to respect all people who contribute through reporting issues,
posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in this project
a harassment-free experience for everyone,
regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information,
such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct.
By adopting this Code of Conduct,
project maintainers commit themselves to fairly and consistently
applying these principles to every aspect of managing this project.
Project maintainers who do not follow or enforce the Code of Conduct
may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported by opening an issue
or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)

27
vendor/github.com/googleapis/gax-go/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,27 @@
Want to contribute? Great! First, read this page (including the small print at the end).
### Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement]
(https://cla.developers.google.com/about/google-individual)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things—for instance that you'll tell us if you
know that your code infringes on other people's patents. You don't have to sign
the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first through the issue tracker with your idea so that we can help out and
possibly guide you. Coordinating up front makes it much easier to avoid
frustration later on.
### Code reviews
All submissions, including submissions by project members, require review. We
use Github pull requests for this purpose.
### The small print
Contributions made by corporations are covered by a different agreement than
the one above, the
[Software Grant and Corporate Contributor License Agreement]
(https://cla.developers.google.com/about/google-corporate).

29
vendor/github.com/googleapis/gax-go/README.md generated vendored Normal file
View File

@ -0,0 +1,29 @@
Google API Extensions for Go
============================
[![Build Status](https://travis-ci.org/googleapis/gax-go.svg?branch=master)](https://travis-ci.org/googleapis/gax-go)
[![Code Coverage](https://img.shields.io/codecov/c/github/googleapis/gax-go.svg)](https://codecov.io/github/googleapis/gax-go)
[![GoDoc](https://godoc.org/github.com/googleapis/gax-go?status.svg)](https://godoc.org/github.com/googleapis/gax-go)
Google API Extensions for Go (gax-go) is a set of modules which aids the
development of APIs for clients and servers based on `gRPC` and Google API
conventions.
To install the API extensions, use:
```
go get -u github.com/googleapis/gax-go
```
**Note:** Application code will rarely need to use this library directly,
but the code generated automatically from API definition files can use it
to simplify code generation and to provide more convenient and idiomatic API surface.
Go Versions
===========
This library requires Go 1.6 or above.
License
=======
BSD - please see [LICENSE](https://github.com/googleapis/gax-go/blob/master/LICENSE)
for more information.

View File

@ -113,7 +113,6 @@ type Backoff struct {
cur time.Duration
}
// Pause returns the next time.Duration that the caller should use to backoff.
func (bo *Backoff) Pause() time.Duration {
if bo.Initial == 0 {
bo.Initial = time.Second
@ -127,11 +126,10 @@ func (bo *Backoff) Pause() time.Duration {
if bo.Multiplier < 1 {
bo.Multiplier = 2
}
// Select a duration between 1ns and the current max. It might seem
// counterintuitive to have so much jitter, but
// https://www.awsarchitectureblog.com/2015/03/backoff.html argues that
// that is the best strategy.
d := time.Duration(1 + rand.Int63n(int64(bo.cur)))
// Select a duration between zero and the current max. It might seem counterintuitive to
// have so much jitter, but https://www.awsarchitectureblog.com/2015/03/backoff.html
// argues that that is the best strategy.
d := time.Duration(rand.Int63n(int64(bo.cur)))
bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier)
if bo.cur > bo.Max {
bo.cur = bo.Max
@ -145,12 +143,10 @@ func (o grpcOpt) Resolve(s *CallSettings) {
s.GRPC = o
}
// WithGRPCOptions allows passing gRPC call options during client creation.
func WithGRPCOptions(opt ...grpc.CallOption) CallOption {
return grpcOpt(append([]grpc.CallOption(nil), opt...))
}
// CallSettings allow fine-grained control over how calls are made.
type CallSettings struct {
// Retry returns a Retryer to be used to control retry logic of a method call.
// If Retry is nil or the returned Retryer is nil, the call will not be retried.

View File

@ -35,5 +35,4 @@
// to simplify code generation and to provide more convenient and idiomatic API surfaces.
package gax
// Version specifies the gax-go version being used.
const Version = "2.0.3"
const Version = "2.0.0"

24
vendor/github.com/googleapis/gax-go/header.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
package gax
import "bytes"
// XGoogHeader is for use by the Google Cloud Libraries only.
//
// XGoogHeader formats key-value pairs.
// The resulting string is suitable for x-goog-api-client header.
func XGoogHeader(keyval ...string) string {
if len(keyval) == 0 {
return ""
}
if len(keyval)%2 != 0 {
panic("gax.Header: odd argument count")
}
var buf bytes.Buffer
for i := 0; i < len(keyval); i += 2 {
buf.WriteByte(' ')
buf.WriteString(keyval[i])
buf.WriteByte('/')
buf.WriteString(keyval[i+1])
}
return buf.String()[1:]
}

View File

@ -31,11 +31,10 @@ package gax
import (
"context"
"strings"
"time"
)
// APICall is a user defined call stub.
// A user defined call stub.
type APICall func(context.Context, CallSettings) error
// Invoke calls the given APICall,
@ -74,15 +73,6 @@ func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper
if settings.Retry == nil {
return err
}
// Never retry permanent certificate errors. (e.x. if ca-certificates
// are not installed). We should only make very few, targeted
// exceptions: many (other) status=Unavailable should be retried, such
// as if there's a network hiccup, or the internet goes out for a
// minute. This is also why here we are doing string parsing instead of
// simply making Unavailable a non-retried code elsewhere.
if strings.Contains(err.Error(), "x509: certificate signed by unknown authority") {
return err
}
if retryer == nil {
if r := settings.Retry(); r != nil {
retryer = r

View File

@ -1,3 +0,0 @@
module github.com/googleapis/gax-go/v2
require google.golang.org/grpc v1.16.0

View File

@ -1,26 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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=
github.com/golang/mock v1.1.1/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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
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/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -1,53 +0,0 @@
// Copyright 2018, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package gax
import "bytes"
// XGoogHeader is for use by the Google Cloud Libraries only.
//
// XGoogHeader formats key-value pairs.
// The resulting string is suitable for x-goog-api-client header.
func XGoogHeader(keyval ...string) string {
if len(keyval) == 0 {
return ""
}
if len(keyval)%2 != 0 {
panic("gax.Header: odd argument count")
}
var buf bytes.Buffer
for i := 0; i < len(keyval); i += 2 {
buf.WriteByte(' ')
buf.WriteString(keyval[i])
buf.WriteByte('/')
buf.WriteString(keyval[i+1])
}
return buf.String()[1:]
}

View File

@ -9,10 +9,6 @@ addons:
language: go
os:
- linux
- osx
go:
- "1.11.x"

View File

@ -275,9 +275,6 @@ None
from a private key file on disk, you would run `base64 -w0 <file>`.
**Note**: Git 2.3+ is required to use this feature.
* `depth` - The Git clone depth. The provided number specifies the last `n`
revisions to clone from the repository.
### Mercurial (`hg`)

View File

@ -13,4 +13,4 @@ install:
go get -d -v -t ./...
build_script:
- cmd: go test ./...
- cmd: go test -v ./...

View File

@ -36,7 +36,6 @@ func (c *fileChecksum) checksum(source string) error {
}
defer f.Close()
c.Hash.Reset()
if _, err := io.Copy(c.Hash, f); err != nil {
return fmt.Errorf("Failed to hash: %s", err)
}
@ -180,15 +179,13 @@ func (c *Client) checksumFromFile(checksumFile string, src *url.URL) (*fileCheck
defer os.Remove(tempfile)
c2 := &Client{
Ctx: c.Ctx,
Getters: c.Getters,
Decompressors: c.Decompressors,
Detectors: c.Detectors,
Pwd: c.Pwd,
Dir: false,
Src: checksumFile,
Dst: tempfile,
ProgressListener: c.ProgressListener,
Getters: c.Getters,
Decompressors: c.Decompressors,
Detectors: c.Detectors,
Pwd: c.Pwd,
Dir: false,
Src: checksumFile,
Dst: tempfile,
}
if err = c2.Get(); err != nil {
return nil, fmt.Errorf(
@ -200,15 +197,8 @@ func (c *Client) checksumFromFile(checksumFile string, src *url.URL) (*fileCheck
if err != nil {
return nil, err
}
checksumFileDir := filepath.Dir(checksumFileURL.Path)
relpath, err := filepath.Rel(checksumFileDir, absPath)
switch {
case err == nil ||
err.Error() == "Rel: can't make "+absPath+" relative to "+checksumFileDir:
// ex: on windows C:\gopath\...\content.txt cannot be relative to \
// which is okay, may be another expected path will work.
break
default:
relpath, err := filepath.Rel(filepath.Dir(checksumFileURL.Path), absPath)
if err != nil {
return nil, err
}
@ -248,7 +238,7 @@ func (c *Client) checksumFromFile(checksumFile string, src *url.URL) (*fileCheck
}
// make sure the checksum is for the right file
for _, option := range options {
if option != "" && checksum.Filename == option {
if checksum.Filename == option {
// any checksum will work so we return the first one
return checksum, nil
}

View File

@ -9,6 +9,5 @@ func tmpFile(dir, pattern string) (string, error) {
if err != nil {
return "", err
}
f.Close()
return f.Name(), nil
}

View File

@ -10,9 +10,7 @@ import (
type FileGetter struct {
getter
// Copy, if set to true, will copy data instead of using a symlink. If
// false, attempts to symlink to speed up the operation and to lower the
// disk space usage. If the symlink fails, may attempt to copy on windows.
// Copy, if set to true, will copy data instead of using a symlink
Copy bool
}

View File

@ -9,7 +9,6 @@ import (
"os/exec"
"path/filepath"
"strings"
"syscall"
)
func (g *FileGetter) Get(dst string, u *url.URL) error {
@ -94,21 +93,7 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error {
// If we're not copying, just symlink and we're done
if !g.Copy {
if err = os.Symlink(path, dst); err == nil {
return err
}
lerr, ok := err.(*os.LinkError)
if !ok {
return err
}
switch lerr.Err {
case syscall.ERROR_PRIVILEGE_NOT_HELD:
// no symlink privilege, let's
// fallback to a copy to avoid an error.
break
default:
return err
}
return os.Symlink(path, dst)
}
// Copy

View File

@ -9,8 +9,6 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
urlhelper "github.com/hashicorp/go-getter/helper/url"
@ -36,7 +34,6 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
// Extract some query parameters we use
var ref, sshKey string
var depth int
q := u.Query()
if len(q) > 0 {
ref = q.Get("ref")
@ -45,11 +42,6 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
sshKey = q.Get("sshkey")
q.Del("sshkey")
if n, err := strconv.Atoi(q.Get("depth")); err == nil {
depth = n
}
q.Del("depth")
// Copy the URL
var newU url.URL = *u
u = &newU
@ -116,9 +108,9 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
return err
}
if err == nil {
err = g.update(ctx, dst, sshKeyFile, ref, depth)
err = g.update(ctx, dst, sshKeyFile, ref)
} else {
err = g.clone(ctx, dst, sshKeyFile, u, depth)
err = g.clone(ctx, dst, sshKeyFile, u)
}
if err != nil {
return err
@ -132,7 +124,7 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
}
// Lastly, download any/all submodules.
return g.fetchSubmodules(ctx, dst, sshKeyFile, depth)
return g.fetchSubmodules(ctx, dst, sshKeyFile)
}
// GetFile for Git doesn't support updating at this time. It will download
@ -170,20 +162,13 @@ func (g *GitGetter) checkout(dst string, ref string) error {
return getRunCommand(cmd)
}
func (g *GitGetter) clone(ctx context.Context, dst, sshKeyFile string, u *url.URL, depth int) error {
args := []string{"clone"}
if depth > 0 {
args = append(args, "--depth", strconv.Itoa(depth))
}
args = append(args, u.String(), dst)
cmd := exec.CommandContext(ctx, "git", args...)
func (g *GitGetter) clone(ctx context.Context, dst, sshKeyFile string, u *url.URL) error {
cmd := exec.CommandContext(ctx, "git", "clone", u.String(), dst)
setupGitEnv(cmd, sshKeyFile)
return getRunCommand(cmd)
}
func (g *GitGetter) update(ctx context.Context, dst, sshKeyFile, ref string, depth int) error {
func (g *GitGetter) update(ctx context.Context, dst, sshKeyFile, ref string) error {
// Determine if we're a branch. If we're NOT a branch, then we just
// switch to master prior to checking out
cmd := exec.CommandContext(ctx, "git", "show-ref", "-q", "--verify", "refs/heads/"+ref)
@ -201,24 +186,15 @@ func (g *GitGetter) update(ctx context.Context, dst, sshKeyFile, ref string, dep
return err
}
if depth > 0 {
cmd = exec.Command("git", "pull", "--depth", strconv.Itoa(depth), "--ff-only")
} else {
cmd = exec.Command("git", "pull", "--ff-only")
}
cmd = exec.Command("git", "pull", "--ff-only")
cmd.Dir = dst
setupGitEnv(cmd, sshKeyFile)
return getRunCommand(cmd)
}
// fetchSubmodules downloads any configured submodules recursively.
func (g *GitGetter) fetchSubmodules(ctx context.Context, dst, sshKeyFile string, depth int) error {
args := []string{"submodule", "update", "--init", "--recursive"}
if depth > 0 {
args = append(args, "--depth", strconv.Itoa(depth))
}
cmd := exec.CommandContext(ctx, "git", args...)
func (g *GitGetter) fetchSubmodules(ctx context.Context, dst, sshKeyFile string) error {
cmd := exec.CommandContext(ctx, "git", "submodule", "update", "--init", "--recursive")
cmd.Dir = dst
setupGitEnv(cmd, sshKeyFile)
return getRunCommand(cmd)
@ -235,7 +211,7 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
// with versions of Go < 1.9.
env := os.Environ()
for i, v := range env {
if strings.HasPrefix(v, gitSSHCommand) && len(v) > len(gitSSHCommand) {
if strings.HasPrefix(v, gitSSHCommand) {
sshCmd = []string{v}
env[i], env[len(env)-1] = env[len(env)-1], env[i]
@ -250,9 +226,6 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
if sshKeyFile != "" {
// We have an SSH key temp file configured, tell ssh about this.
if runtime.GOOS == "windows" {
sshKeyFile = strings.Replace(sshKeyFile, `\`, `/`, -1)
}
sshCmd = append(sshCmd, "-i", sshKeyFile)
}
@ -278,17 +251,8 @@ func checkGitVersion(min string) error {
if len(fields) < 3 {
return fmt.Errorf("Unexpected 'git version' output: %q", string(out))
}
v := fields[2]
if runtime.GOOS == "windows" && strings.Contains(v, ".windows.") {
// on windows, git version will return for example:
// git version 2.20.1.windows.1
// Which does not follow the semantic versionning specs
// https://semver.org. We remove that part in order for
// go-version to not error.
v = v[:strings.Index(v, ".windows.")]
}
have, err := version.NewVersion(v)
have, err := version.NewVersion(fields[2])
if err != nil {
return err
}

View File

@ -146,7 +146,6 @@ func (g *HttpGetter) GetFile(dst string, src *url.URL) error {
if err != nil {
return err
}
defer f.Close()
if g.Client == nil {
g.Client = httpClient
@ -212,6 +211,9 @@ func (g *HttpGetter) GetFile(dst string, src *url.URL) error {
if err == nil && n < resp.ContentLength {
err = io.ErrShortWrite
}
if err1 := f.Close(); err == nil {
err = err1
}
return err
}

View File

@ -8,7 +8,7 @@ require (
github.com/fatih/color v1.7.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.0
github.com/hashicorp/go-safetemp v1.0.0
github.com/hashicorp/go-version v1.1.0
github.com/hashicorp/go-version v1.0.0
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect

View File

@ -14,8 +14,6 @@ github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhE
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=

View File

@ -11,18 +11,19 @@ func parse(rawURL string) (*url.URL, error) {
// Make sure we're using "/" since URLs are "/"-based.
rawURL = filepath.ToSlash(rawURL)
if len(rawURL) > 1 && rawURL[1] == ':' {
// Assume we're dealing with a drive letter. In which case we
// force the 'file' scheme to avoid "net/url" URL.String() prepending
// our url with "./".
rawURL = "file://" + rawURL
}
u, err := url.Parse(rawURL)
if err != nil {
return nil, err
}
if len(rawURL) > 1 && rawURL[1] == ':' {
// Assume we're dealing with a drive letter file path where the drive
// letter has been parsed into the URL Scheme, and the rest of the path
// has been parsed into the URL Path without the leading ':' character.
u.Path = fmt.Sprintf("%s:%s", string(rawURL[0]), u.Path)
u.Scheme = ""
}
if len(u.Host) > 1 && u.Host[1] == ':' && strings.HasPrefix(rawURL, "file://") {
// Assume we're dealing with a drive letter file path where the drive
// letter has been parsed into the URL Host.

View File

@ -21,6 +21,7 @@ import (
"sync"
"sync/atomic"
"time"
"unicode"
hclog "github.com/hashicorp/go-hclog"
)
@ -932,48 +933,21 @@ func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) {
return conn, nil
}
var stdErrBufferSize = 64 * 1024
func (c *Client) logStderr(r io.Reader) {
defer c.clientWaitGroup.Done()
scanner := bufio.NewScanner(r)
l := c.logger.Named(filepath.Base(c.config.Cmd.Path))
reader := bufio.NewReaderSize(r, stdErrBufferSize)
// continuation indicates the previous line was a prefix
continuation := false
for {
line, isPrefix, err := reader.ReadLine()
switch {
case err == io.EOF:
return
case err != nil:
l.Error("reading plugin stderr", "error", err)
return
}
c.config.Stderr.Write(line)
// The line was longer than our max token size, so it's likely
// incomplete and won't unmarshal.
if isPrefix || continuation {
l.Debug(string(line))
// if we're finishing a continued line, add the newline back in
if !isPrefix {
c.config.Stderr.Write([]byte{'\n'})
}
continuation = isPrefix
continue
}
c.config.Stderr.Write([]byte{'\n'})
for scanner.Scan() {
line := scanner.Text()
c.config.Stderr.Write([]byte(line + "\n"))
line = strings.TrimRightFunc(line, unicode.IsSpace)
entry, err := parseJSON(line)
// If output is not JSON format, print directly to Debug
if err != nil {
l.Debug(string(line))
l.Debug(line)
} else {
out := flattenKVPairs(entry.KVPairs)
@ -992,4 +966,8 @@ func (c *Client) logStderr(r io.Reader) {
}
}
}
if err := scanner.Err(); err != nil {
l.Error("reading plugin stderr", "error", err)
}
}

View File

@ -1,16 +1,12 @@
module github.com/hashicorp/go-plugin
require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang/protobuf v1.2.0
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77
github.com/oklog/run v1.0.0
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect
google.golang.org/grpc v1.14.0

View File

@ -1,7 +1,3 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
@ -12,17 +8,8 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/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=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=

View File

@ -11,7 +11,7 @@ import (
"sync/atomic"
"time"
"github.com/hashicorp/go-plugin/internal/plugin"
"github.com/hashicorp/go-plugin/internal/proto"
"github.com/oklog/run"
"google.golang.org/grpc"
@ -21,14 +21,14 @@ import (
// streamer interface is used in the broker to send/receive connection
// information.
type streamer interface {
Send(*plugin.ConnInfo) error
Recv() (*plugin.ConnInfo, error)
Send(*proto.ConnInfo) error
Recv() (*proto.ConnInfo, error)
Close()
}
// sendErr is used to pass errors back during a send.
type sendErr struct {
i *plugin.ConnInfo
i *proto.ConnInfo
ch chan error
}
@ -40,7 +40,7 @@ type gRPCBrokerServer struct {
send chan *sendErr
// recv is used to receive connection info from the gRPC stream.
recv chan *plugin.ConnInfo
recv chan *proto.ConnInfo
// quit closes down the stream.
quit chan struct{}
@ -52,7 +52,7 @@ type gRPCBrokerServer struct {
func newGRPCBrokerServer() *gRPCBrokerServer {
return &gRPCBrokerServer{
send: make(chan *sendErr),
recv: make(chan *plugin.ConnInfo),
recv: make(chan *proto.ConnInfo),
quit: make(chan struct{}),
}
}
@ -60,7 +60,7 @@ func newGRPCBrokerServer() *gRPCBrokerServer {
// StartStream implements the GRPCBrokerServer interface and will block until
// the quit channel is closed or the context reports Done. The stream will pass
// connection information to/from the client.
func (s *gRPCBrokerServer) StartStream(stream plugin.GRPCBroker_StartStreamServer) error {
func (s *gRPCBrokerServer) StartStream(stream proto.GRPCBroker_StartStreamServer) error {
doneCh := stream.Context().Done()
defer s.Close()
@ -99,7 +99,7 @@ func (s *gRPCBrokerServer) StartStream(stream plugin.GRPCBroker_StartStreamServe
// Send is used by the GRPCBroker to pass connection information into the stream
// to the client.
func (s *gRPCBrokerServer) Send(i *plugin.ConnInfo) error {
func (s *gRPCBrokerServer) Send(i *proto.ConnInfo) error {
ch := make(chan error)
defer close(ch)
@ -117,7 +117,7 @@ func (s *gRPCBrokerServer) Send(i *plugin.ConnInfo) error {
// Recv is used by the GRPCBroker to pass connection information that has been
// sent from the client from the stream to the broker.
func (s *gRPCBrokerServer) Recv() (*plugin.ConnInfo, error) {
func (s *gRPCBrokerServer) Recv() (*proto.ConnInfo, error) {
select {
case <-s.quit:
return nil, errors.New("broker closed")
@ -138,13 +138,13 @@ func (s *gRPCBrokerServer) Close() {
// streamer interfaces.
type gRPCBrokerClientImpl struct {
// client is the underlying GRPC client used to make calls to the server.
client plugin.GRPCBrokerClient
client proto.GRPCBrokerClient
// send is used to send connection info to the gRPC stream.
send chan *sendErr
// recv is used to receive connection info from the gRPC stream.
recv chan *plugin.ConnInfo
recv chan *proto.ConnInfo
// quit closes down the stream.
quit chan struct{}
@ -155,9 +155,9 @@ type gRPCBrokerClientImpl struct {
func newGRPCBrokerClient(conn *grpc.ClientConn) *gRPCBrokerClientImpl {
return &gRPCBrokerClientImpl{
client: plugin.NewGRPCBrokerClient(conn),
client: proto.NewGRPCBrokerClient(conn),
send: make(chan *sendErr),
recv: make(chan *plugin.ConnInfo),
recv: make(chan *proto.ConnInfo),
quit: make(chan struct{}),
}
}
@ -209,7 +209,7 @@ func (s *gRPCBrokerClientImpl) StartStream() error {
// Send is used by the GRPCBroker to pass connection information into the stream
// to the plugin.
func (s *gRPCBrokerClientImpl) Send(i *plugin.ConnInfo) error {
func (s *gRPCBrokerClientImpl) Send(i *proto.ConnInfo) error {
ch := make(chan error)
defer close(ch)
@ -227,7 +227,7 @@ func (s *gRPCBrokerClientImpl) Send(i *plugin.ConnInfo) error {
// Recv is used by the GRPCBroker to pass connection information that has been
// sent from the plugin to the broker.
func (s *gRPCBrokerClientImpl) Recv() (*plugin.ConnInfo, error) {
func (s *gRPCBrokerClientImpl) Recv() (*proto.ConnInfo, error) {
select {
case <-s.quit:
return nil, errors.New("broker closed")
@ -268,7 +268,7 @@ type GRPCBroker struct {
}
type gRPCBrokerPending struct {
ch chan *plugin.ConnInfo
ch chan *proto.ConnInfo
doneCh chan struct{}
}
@ -290,7 +290,7 @@ func (b *GRPCBroker) Accept(id uint32) (net.Listener, error) {
return nil, err
}
err = b.streamer.Send(&plugin.ConnInfo{
err = b.streamer.Send(&proto.ConnInfo{
ServiceId: id,
Network: listener.Addr().Network(),
Address: listener.Addr().String(),
@ -365,7 +365,7 @@ func (b *GRPCBroker) Close() error {
// Dial opens a connection by ID.
func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) {
var c *plugin.ConnInfo
var c *proto.ConnInfo
// Open the stream
p := b.getStream(id)
@ -435,7 +435,7 @@ func (m *GRPCBroker) getStream(id uint32) *gRPCBrokerPending {
}
m.streams[id] = &gRPCBrokerPending{
ch: make(chan *plugin.ConnInfo, 1),
ch: make(chan *proto.ConnInfo, 1),
doneCh: make(chan struct{}),
}
return m.streams[id]

View File

@ -6,7 +6,7 @@ import (
"net"
"time"
"github.com/hashicorp/go-plugin/internal/plugin"
"github.com/hashicorp/go-plugin/internal/proto"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@ -61,7 +61,7 @@ func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
Plugins: c.config.Plugins,
doneCtx: doneCtx,
broker: broker,
controller: plugin.NewGRPCControllerClient(conn),
controller: proto.NewGRPCControllerClient(conn),
}
return cl, nil
@ -75,13 +75,13 @@ type GRPCClient struct {
doneCtx context.Context
broker *GRPCBroker
controller plugin.GRPCControllerClient
controller proto.GRPCControllerClient
}
// ClientProtocol impl.
func (c *GRPCClient) Close() error {
c.broker.Close()
c.controller.Shutdown(c.doneCtx, &plugin.Empty{})
c.controller.Shutdown(c.doneCtx, &proto.Empty{})
return c.Conn.Close()
}

View File

@ -3,7 +3,7 @@ package plugin
import (
"context"
"github.com/hashicorp/go-plugin/internal/plugin"
"github.com/hashicorp/go-plugin/internal/proto"
)
// GRPCControllerServer handles shutdown calls to terminate the server when the
@ -14,8 +14,8 @@ type grpcControllerServer struct {
// Shutdown stops the grpc server. It first will attempt a graceful stop, then a
// full stop on the server.
func (s *grpcControllerServer) Shutdown(ctx context.Context, _ *plugin.Empty) (*plugin.Empty, error) {
resp := &plugin.Empty{}
func (s *grpcControllerServer) Shutdown(ctx context.Context, _ *proto.Empty) (*proto.Empty, error) {
resp := &proto.Empty{}
// TODO: figure out why GracefullStop doesn't work.
s.server.Stop()

View File

@ -9,7 +9,7 @@ import (
"net"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin/internal/plugin"
"github.com/hashicorp/go-plugin/internal/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/health"
@ -75,7 +75,7 @@ func (s *GRPCServer) Init() error {
// Register the broker service
brokerServer := newGRPCBrokerServer()
plugin.RegisterGRPCBrokerServer(s.server, brokerServer)
proto.RegisterGRPCBrokerServer(s.server, brokerServer)
s.broker = newGRPCBroker(brokerServer, s.TLS)
go s.broker.Run()
@ -83,7 +83,7 @@ func (s *GRPCServer) Init() error {
controllerServer := &grpcControllerServer{
server: s,
}
plugin.RegisterGRPCControllerServer(s.server, controllerServer)
proto.RegisterGRPCControllerServer(s.server, controllerServer)
// Register all our plugins onto the gRPC server.
for k, raw := range s.Plugins {

View File

@ -1,3 +1,3 @@
//go:generate protoc -I ./ ./grpc_broker.proto ./grpc_controller.proto --go_out=plugins=grpc:.
package plugin
package proto

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpc_broker.proto
package plugin
package proto
import (
fmt "fmt"
@ -78,24 +78,24 @@ func (m *ConnInfo) GetAddress() string {
}
func init() {
proto.RegisterType((*ConnInfo)(nil), "plugin.ConnInfo")
proto.RegisterType((*ConnInfo)(nil), "proto.ConnInfo")
}
func init() { proto.RegisterFile("grpc_broker.proto", fileDescriptor_802e9beed3ec3b28) }
var fileDescriptor_802e9beed3ec3b28 = []byte{
// 175 bytes of a gzipped FileDescriptorProto
// 164 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x2f, 0x2a, 0x48,
0x8e, 0x4f, 0x2a, 0xca, 0xcf, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b,
0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0x53, 0x8a, 0xe5, 0xe2, 0x70, 0xce, 0xcf, 0xcb, 0xf3, 0xcc, 0x4b,
0xcb, 0x17, 0x92, 0xe5, 0xe2, 0x2a, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x8d, 0xcf, 0x4c, 0x91,
0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0xe2, 0x84, 0x8a, 0x78, 0xa6, 0x08, 0x49, 0x70, 0xb1, 0xe7,
0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x4b, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x20,
0x99, 0xc4, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0x62, 0x09, 0x66, 0x88, 0x0c, 0x94, 0x6b, 0xe4, 0xcc,
0xc5, 0xe5, 0x1e, 0x14, 0xe0, 0xec, 0x04, 0xb6, 0x5a, 0xc8, 0x94, 0x8b, 0x3b, 0xb8, 0x24, 0xb1,
0xa8, 0x24, 0xb8, 0xa4, 0x28, 0x35, 0x31, 0x57, 0x48, 0x40, 0x0f, 0xe2, 0x08, 0x3d, 0x98, 0x0b,
0xa4, 0x30, 0x44, 0x34, 0x18, 0x0d, 0x18, 0x9d, 0x38, 0xa2, 0xa0, 0xae, 0x4d, 0x62, 0x03, 0x3b,
0xde, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x10, 0x15, 0x39, 0x47, 0xd1, 0x00, 0x00, 0x00,
0x8e, 0x4f, 0x2a, 0xca, 0xcf, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05,
0x53, 0x4a, 0xb1, 0x5c, 0x1c, 0xce, 0xf9, 0x79, 0x79, 0x9e, 0x79, 0x69, 0xf9, 0x42, 0xb2, 0x5c,
0x5c, 0xc5, 0xa9, 0x45, 0x65, 0x99, 0xc9, 0xa9, 0xf1, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a,
0xbc, 0x41, 0x9c, 0x50, 0x11, 0xcf, 0x14, 0x21, 0x09, 0x2e, 0xf6, 0xbc, 0xd4, 0x92, 0xf2, 0xfc,
0xa2, 0x6c, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x18, 0x17, 0x24, 0x93, 0x98, 0x92, 0x52,
0x94, 0x5a, 0x5c, 0x2c, 0xc1, 0x0c, 0x91, 0x81, 0x72, 0x8d, 0x1c, 0xb9, 0xb8, 0xdc, 0x83, 0x02,
0x9c, 0x9d, 0xc0, 0x36, 0x0b, 0x19, 0x73, 0x71, 0x07, 0x97, 0x24, 0x16, 0x95, 0x04, 0x97, 0x14,
0xa5, 0x26, 0xe6, 0x0a, 0xf1, 0x43, 0x9c, 0xa2, 0x07, 0x73, 0x80, 0x14, 0xba, 0x80, 0x06, 0xa3,
0x01, 0x63, 0x12, 0x1b, 0x58, 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x7a, 0xda, 0xd5, 0x84,
0xc4, 0x00, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -122,7 +122,7 @@ func NewGRPCBrokerClient(cc *grpc.ClientConn) GRPCBrokerClient {
}
func (c *gRPCBrokerClient) StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GRPCBroker_serviceDesc.Streams[0], "/plugin.GRPCBroker/StartStream", opts...)
stream, err := c.cc.NewStream(ctx, &_GRPCBroker_serviceDesc.Streams[0], "/proto.GRPCBroker/StartStream", opts...)
if err != nil {
return nil, err
}
@ -188,7 +188,7 @@ func (x *gRPCBrokerStartStreamServer) Recv() (*ConnInfo, error) {
}
var _GRPCBroker_serviceDesc = grpc.ServiceDesc{
ServiceName: "plugin.GRPCBroker",
ServiceName: "proto.GRPCBroker",
HandlerType: (*GRPCBrokerServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{

View File

@ -1,6 +1,5 @@
syntax = "proto3";
package plugin;
option go_package = "plugin";
package proto;
message ConnInfo {
uint32 service_id = 1;

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpc_controller.proto
package plugin
package proto
import (
fmt "fmt"
@ -54,20 +54,20 @@ func (m *Empty) XXX_DiscardUnknown() {
var xxx_messageInfo_Empty proto.InternalMessageInfo
func init() {
proto.RegisterType((*Empty)(nil), "plugin.Empty")
proto.RegisterType((*Empty)(nil), "proto.Empty")
}
func init() { proto.RegisterFile("grpc_controller.proto", fileDescriptor_23c2c7e42feab570) }
var fileDescriptor_23c2c7e42feab570 = []byte{
// 108 bytes of a gzipped FileDescriptorProto
// 97 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0x2f, 0x2a, 0x48,
0x8e, 0x4f, 0xce, 0xcf, 0x2b, 0x29, 0xca, 0xcf, 0xc9, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f,
0xc9, 0x17, 0x62, 0x2b, 0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0x53, 0x62, 0xe7, 0x62, 0x75, 0xcd, 0x2d,
0x28, 0xa9, 0x34, 0xb2, 0xe2, 0xe2, 0x73, 0x0f, 0x0a, 0x70, 0x76, 0x86, 0x2b, 0x14, 0xd2, 0xe0,
0xe2, 0x08, 0xce, 0x28, 0x2d, 0x49, 0xc9, 0x2f, 0xcf, 0x13, 0xe2, 0xd5, 0x83, 0xa8, 0xd7, 0x03,
0x2b, 0x96, 0x42, 0xe5, 0x3a, 0x71, 0x44, 0x41, 0x8d, 0x4b, 0x62, 0x03, 0x9b, 0x6e, 0x0c, 0x08,
0x00, 0x00, 0xff, 0xff, 0xab, 0x7c, 0x27, 0xe5, 0x76, 0x00, 0x00, 0x00,
0xc9, 0x17, 0x62, 0x05, 0x53, 0x4a, 0xec, 0x5c, 0xac, 0xae, 0xb9, 0x05, 0x25, 0x95, 0x46, 0x16,
0x5c, 0x7c, 0xee, 0x41, 0x01, 0xce, 0xce, 0x70, 0x75, 0x42, 0x6a, 0x5c, 0x1c, 0xc1, 0x19, 0xa5,
0x25, 0x29, 0xf9, 0xe5, 0x79, 0x42, 0x3c, 0x10, 0x5d, 0x7a, 0x60, 0xb5, 0x52, 0x28, 0xbc, 0x24,
0x36, 0x30, 0xc7, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x69, 0xa1, 0xad, 0x79, 0x69, 0x00, 0x00,
0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -95,7 +95,7 @@ func NewGRPCControllerClient(cc *grpc.ClientConn) GRPCControllerClient {
func (c *gRPCControllerClient) Shutdown(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/plugin.GRPCController/Shutdown", in, out, opts...)
err := c.cc.Invoke(ctx, "/proto.GRPCController/Shutdown", in, out, opts...)
if err != nil {
return nil, err
}
@ -121,7 +121,7 @@ func _GRPCController_Shutdown_Handler(srv interface{}, ctx context.Context, dec
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/plugin.GRPCController/Shutdown",
FullMethod: "/proto.GRPCController/Shutdown",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GRPCControllerServer).Shutdown(ctx, req.(*Empty))
@ -130,7 +130,7 @@ func _GRPCController_Shutdown_Handler(srv interface{}, ctx context.Context, dec
}
var _GRPCController_serviceDesc = grpc.ServiceDesc{
ServiceName: "plugin.GRPCController",
ServiceName: "proto.GRPCController",
HandlerType: (*GRPCControllerServer)(nil),
Methods: []grpc.MethodDesc{
{

View File

@ -1,6 +1,5 @@
syntax = "proto3";
package plugin;
option go_package = "plugin";
package proto;
message Empty {
}

View File

@ -32,11 +32,11 @@ func flattenKVPairs(kvs []*logEntryKV) []interface{} {
}
// parseJSON handles parsing JSON output
func parseJSON(input []byte) (*logEntry, error) {
func parseJSON(input string) (*logEntry, error) {
var raw map[string]interface{}
entry := &logEntry{}
err := json.Unmarshal(input, &raw)
err := json.Unmarshal([]byte(input), &raw)
if err != nil {
return nil, err
}

View File

@ -7,9 +7,9 @@ import (
"net"
"net/rpc"
"github.com/mitchellh/go-testing-interface"
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin/internal/plugin"
"github.com/hashicorp/go-plugin/internal/proto"
"github.com/mitchellh/go-testing-interface"
"google.golang.org/grpc"
)
@ -173,7 +173,7 @@ func TestPluginGRPCConn(t testing.T, ps map[string]Plugin) (*GRPCClient, *GRPCSe
Plugins: ps,
broker: broker,
doneCtx: context.Background(),
controller: plugin.NewGRPCControllerClient(conn),
controller: proto.NewGRPCControllerClient(conn),
}
return client, server

View File

@ -1,184 +0,0 @@
# HCL Dynamic Blocks Extension
This HCL extension implements a special block type named "dynamic" that can
be used to dynamically generate blocks of other types by iterating over
collection values.
Normally the block structure in an HCL configuration file is rigid, even
though dynamic expressions can be used within attribute values. This is
convenient for most applications since it allows the overall structure of
the document to be decoded easily, but in some applications it is desirable
to allow dynamic block generation within certain portions of the configuration.
Dynamic block generation is performed using the `dynamic` block type:
```hcl
toplevel {
nested {
foo = "static block 1"
}
dynamic "nested" {
for_each = ["a", "b", "c"]
iterator = nested
content {
foo = "dynamic block ${nested.value}"
}
}
nested {
foo = "static block 2"
}
}
```
The above is interpreted as if it were written as follows:
```hcl
toplevel {
nested {
foo = "static block 1"
}
nested {
foo = "dynamic block a"
}
nested {
foo = "dynamic block b"
}
nested {
foo = "dynamic block c"
}
nested {
foo = "static block 2"
}
}
```
Since HCL block syntax is not normally exposed to the possibility of unknown
values, this extension must make some compromises when asked to iterate over
an unknown collection. If the length of the collection cannot be statically
recognized (because it is an unknown value of list, map, or set type) then
the `dynamic` construct will generate a _single_ dynamic block whose iterator
key and value are both unknown values of the dynamic pseudo-type, thus causing
any attribute values derived from iteration to appear as unknown values. There
is no explicit representation of the fact that the length of the collection may
eventually be different than one.
## Usage
Pass a body to function `Expand` to obtain a new body that will, on access
to its content, evaluate and expand any nested `dynamic` blocks.
Dynamic block processing is also automatically propagated into any nested
blocks that are returned, allowing users to nest dynamic blocks inside
one another and to nest dynamic blocks inside other static blocks.
HCL structural decoding does not normally have access to an `EvalContext`, so
any variables and functions that should be available to the `for_each`
and `labels` expressions must be passed in when calling `Expand`. Expressions
within the `content` block are evaluated separately and so can be passed a
separate `EvalContext` if desired, during normal attribute expression
evaluation.
## Detecting Variables
Some applications dynamically generate an `EvalContext` by analyzing which
variables are referenced by an expression before evaluating it.
This unfortunately requires some extra effort when this analysis is required
for the context passed to `Expand`: the HCL API requires a schema to be
provided in order to do any analysis of the blocks in a body, but the low-level
schema model provides a description of only one level of nested blocks at
a time, and thus a new schema must be provided for each additional level of
nesting.
To make this arduous process as convenient as possbile, this package provides
a helper function `WalkForEachVariables`, which returns a `WalkVariablesNode`
instance that can be used to find variables directly in a given body and also
determine which nested blocks require recursive calls. Using this mechanism
requires that the caller be able to look up a schema given a nested block type.
For _simple_ formats where a specific block type name always has the same schema
regardless of context, a walk can be implemented as follows:
```go
func walkVariables(node dynblock.WalkVariablesNode, schema *hcl.BodySchema) []hcl.Traversal {
vars, children := node.Visit(schema)
for _, child := range children {
var childSchema *hcl.BodySchema
switch child.BlockTypeName {
case "a":
childSchema = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "b",
LabelNames: []string{"key"},
},
},
}
case "b":
childSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "val",
Required: true,
},
},
}
default:
// Should never happen, because the above cases should be exhaustive
// for the application's configuration format.
panic(fmt.Errorf("can't find schema for unknown block type %q", child.BlockTypeName))
}
vars = append(vars, testWalkAndAccumVars(child.Node, childSchema)...)
}
}
```
### Detecting Variables with `hcldec` Specifications
For applications that use the higher-level `hcldec` package to decode nested
configuration structures into `cty` values, the same specification can be used
to automatically drive the recursive variable-detection walk described above.
The helper function `ForEachVariablesHCLDec` allows an entire recursive
configuration structure to be analyzed in a single call given a `hcldec.Spec`
that describes the nested block structure. This means a `hcldec`-based
application can support dynamic blocks with only a little additional effort:
```go
func decodeBody(body hcl.Body, spec hcldec.Spec) (cty.Value, hcl.Diagnostics) {
// Determine which variables are needed to expand dynamic blocks
neededForDynamic := dynblock.ForEachVariablesHCLDec(body, spec)
// Build a suitable EvalContext and expand dynamic blocks
dynCtx := buildEvalContext(neededForDynamic)
dynBody := dynblock.Expand(body, dynCtx)
// Determine which variables are needed to fully decode the expanded body
// This will analyze expressions that came both from static blocks in the
// original body and from blocks that were dynamically added by Expand.
neededForDecode := hcldec.Variables(dynBody, spec)
// Build a suitable EvalContext and then fully decode the body as per the
// hcldec specification.
decCtx := buildEvalContext(neededForDecode)
return hcldec.Decode(dynBody, spec, decCtx)
}
func buildEvalContext(needed []hcl.Traversal) *hcl.EvalContext {
// (to be implemented by your application)
}
```
# Performance
This extension is going quite harshly against the grain of the HCL API, and
so it uses lots of wrapping objects and temporary data structures to get its
work done. HCL in general is not suitable for use in high-performance situations
or situations sensitive to memory pressure, but that is _especially_ true for
this extension.

View File

@ -1,252 +0,0 @@
package dynblock
import (
"fmt"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
// expandBody wraps another hcl.Body and expands any "dynamic" blocks found
// inside whenever Content or PartialContent is called.
type expandBody struct {
original hcl.Body
forEachCtx *hcl.EvalContext
iteration *iteration // non-nil if we're nested inside another "dynamic" block
// These are used with PartialContent to produce a "remaining items"
// body to return. They are nil on all bodies fresh out of the transformer.
//
// Note that this is re-implemented here rather than delegating to the
// existing support required by the underlying body because we need to
// retain access to the entire original body on subsequent decode operations
// so we can retain any "dynamic" blocks for types we didn't take consume
// on the first pass.
hiddenAttrs map[string]struct{}
hiddenBlocks map[string]hcl.BlockHeaderSchema
}
func (b *expandBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
extSchema := b.extendSchema(schema)
rawContent, diags := b.original.Content(extSchema)
blocks, blockDiags := b.expandBlocks(schema, rawContent.Blocks, false)
diags = append(diags, blockDiags...)
attrs := b.prepareAttributes(rawContent.Attributes)
content := &hcl.BodyContent{
Attributes: attrs,
Blocks: blocks,
MissingItemRange: b.original.MissingItemRange(),
}
return content, diags
}
func (b *expandBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
extSchema := b.extendSchema(schema)
rawContent, _, diags := b.original.PartialContent(extSchema)
// We discard the "remain" argument above because we're going to construct
// our own remain that also takes into account remaining "dynamic" blocks.
blocks, blockDiags := b.expandBlocks(schema, rawContent.Blocks, true)
diags = append(diags, blockDiags...)
attrs := b.prepareAttributes(rawContent.Attributes)
content := &hcl.BodyContent{
Attributes: attrs,
Blocks: blocks,
MissingItemRange: b.original.MissingItemRange(),
}
remain := &expandBody{
original: b.original,
forEachCtx: b.forEachCtx,
iteration: b.iteration,
hiddenAttrs: make(map[string]struct{}),
hiddenBlocks: make(map[string]hcl.BlockHeaderSchema),
}
for name := range b.hiddenAttrs {
remain.hiddenAttrs[name] = struct{}{}
}
for typeName, blockS := range b.hiddenBlocks {
remain.hiddenBlocks[typeName] = blockS
}
for _, attrS := range schema.Attributes {
remain.hiddenAttrs[attrS.Name] = struct{}{}
}
for _, blockS := range schema.Blocks {
remain.hiddenBlocks[blockS.Type] = blockS
}
return content, remain, diags
}
func (b *expandBody) extendSchema(schema *hcl.BodySchema) *hcl.BodySchema {
// We augment the requested schema to also include our special "dynamic"
// block type, since then we'll get instances of it interleaved with
// all of the literal child blocks we must also include.
extSchema := &hcl.BodySchema{
Attributes: schema.Attributes,
Blocks: make([]hcl.BlockHeaderSchema, len(schema.Blocks), len(schema.Blocks)+len(b.hiddenBlocks)+1),
}
copy(extSchema.Blocks, schema.Blocks)
extSchema.Blocks = append(extSchema.Blocks, dynamicBlockHeaderSchema)
// If we have any hiddenBlocks then we also need to register those here
// so that a call to "Content" on the underlying body won't fail.
// (We'll filter these out again once we process the result of either
// Content or PartialContent.)
for _, blockS := range b.hiddenBlocks {
extSchema.Blocks = append(extSchema.Blocks, blockS)
}
// If we have any hiddenAttrs then we also need to register these, for
// the same reason as we deal with hiddenBlocks above.
if len(b.hiddenAttrs) != 0 {
newAttrs := make([]hcl.AttributeSchema, len(schema.Attributes), len(schema.Attributes)+len(b.hiddenAttrs))
copy(newAttrs, extSchema.Attributes)
for name := range b.hiddenAttrs {
newAttrs = append(newAttrs, hcl.AttributeSchema{
Name: name,
Required: false,
})
}
extSchema.Attributes = newAttrs
}
return extSchema
}
func (b *expandBody) prepareAttributes(rawAttrs hcl.Attributes) hcl.Attributes {
if len(b.hiddenAttrs) == 0 && b.iteration == nil {
// Easy path: just pass through the attrs from the original body verbatim
return rawAttrs
}
// Otherwise we have some work to do: we must filter out any attributes
// that are hidden (since a previous PartialContent call already saw these)
// and wrap the expressions of the inner attributes so that they will
// have access to our iteration variables.
attrs := make(hcl.Attributes, len(rawAttrs))
for name, rawAttr := range rawAttrs {
if _, hidden := b.hiddenAttrs[name]; hidden {
continue
}
if b.iteration != nil {
attr := *rawAttr // shallow copy so we can mutate it
attr.Expr = exprWrap{
Expression: attr.Expr,
i: b.iteration,
}
attrs[name] = &attr
} else {
// If we have no active iteration then no wrapping is required.
attrs[name] = rawAttr
}
}
return attrs
}
func (b *expandBody) expandBlocks(schema *hcl.BodySchema, rawBlocks hcl.Blocks, partial bool) (hcl.Blocks, hcl.Diagnostics) {
var blocks hcl.Blocks
var diags hcl.Diagnostics
for _, rawBlock := range rawBlocks {
switch rawBlock.Type {
case "dynamic":
realBlockType := rawBlock.Labels[0]
if _, hidden := b.hiddenBlocks[realBlockType]; hidden {
continue
}
var blockS *hcl.BlockHeaderSchema
for _, candidate := range schema.Blocks {
if candidate.Type == realBlockType {
blockS = &candidate
break
}
}
if blockS == nil {
// Not a block type that the caller requested.
if !partial {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Unsupported block type",
Detail: fmt.Sprintf("Blocks of type %q are not expected here.", realBlockType),
Subject: &rawBlock.LabelRanges[0],
})
}
continue
}
spec, specDiags := b.decodeSpec(blockS, rawBlock)
diags = append(diags, specDiags...)
if specDiags.HasErrors() {
continue
}
if spec.forEachVal.IsKnown() {
for it := spec.forEachVal.ElementIterator(); it.Next(); {
key, value := it.Element()
i := b.iteration.MakeChild(spec.iteratorName, key, value)
block, blockDiags := spec.newBlock(i, b.forEachCtx)
diags = append(diags, blockDiags...)
if block != nil {
// Attach our new iteration context so that attributes
// and other nested blocks can refer to our iterator.
block.Body = b.expandChild(block.Body, i)
blocks = append(blocks, block)
}
}
} else {
// If our top-level iteration value isn't known then we're forced
// to compromise since HCL doesn't have any concept of an
// "unknown block". In this case then, we'll produce a single
// dynamic block with the iterator values set to DynamicVal,
// which at least makes the potential for a block visible
// in our result, even though it's not represented in a fully-accurate
// way.
i := b.iteration.MakeChild(spec.iteratorName, cty.DynamicVal, cty.DynamicVal)
block, blockDiags := spec.newBlock(i, b.forEachCtx)
diags = append(diags, blockDiags...)
if block != nil {
block.Body = b.expandChild(block.Body, i)
blocks = append(blocks, block)
}
}
default:
if _, hidden := b.hiddenBlocks[rawBlock.Type]; !hidden {
// A static block doesn't create a new iteration context, but
// it does need to inherit _our own_ iteration context in
// case it contains expressions that refer to our inherited
// iterators, or nested "dynamic" blocks.
expandedBlock := *rawBlock // shallow copy
expandedBlock.Body = b.expandChild(rawBlock.Body, b.iteration)
blocks = append(blocks, &expandedBlock)
}
}
}
return blocks, diags
}
func (b *expandBody) expandChild(child hcl.Body, i *iteration) hcl.Body {
chiCtx := i.EvalContext(b.forEachCtx)
ret := Expand(child, chiCtx)
ret.(*expandBody).iteration = i
return ret
}
func (b *expandBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
// blocks aren't allowed in JustAttributes mode and this body can
// only produce blocks, so we'll just pass straight through to our
// underlying body here.
return b.original.JustAttributes()
}
func (b *expandBody) MissingItemRange() hcl.Range {
return b.original.MissingItemRange()
}

View File

@ -1,215 +0,0 @@
package dynblock
import (
"fmt"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
)
type expandSpec struct {
blockType string
blockTypeRange hcl.Range
defRange hcl.Range
forEachVal cty.Value
iteratorName string
labelExprs []hcl.Expression
contentBody hcl.Body
inherited map[string]*iteration
}
func (b *expandBody) decodeSpec(blockS *hcl.BlockHeaderSchema, rawSpec *hcl.Block) (*expandSpec, hcl.Diagnostics) {
var diags hcl.Diagnostics
var schema *hcl.BodySchema
if len(blockS.LabelNames) != 0 {
schema = dynamicBlockBodySchemaLabels
} else {
schema = dynamicBlockBodySchemaNoLabels
}
specContent, specDiags := rawSpec.Body.Content(schema)
diags = append(diags, specDiags...)
if specDiags.HasErrors() {
return nil, diags
}
//// for_each attribute
eachAttr := specContent.Attributes["for_each"]
eachVal, eachDiags := eachAttr.Expr.Value(b.forEachCtx)
diags = append(diags, eachDiags...)
if !eachVal.CanIterateElements() && eachVal.Type() != cty.DynamicPseudoType {
// We skip this error for DynamicPseudoType because that means we either
// have a null (which is checked immediately below) or an unknown
// (which is handled in the expandBody Content methods).
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic for_each value",
Detail: fmt.Sprintf("Cannot use a %s value in for_each. An iterable collection is required.", eachVal.Type().FriendlyName()),
Subject: eachAttr.Expr.Range().Ptr(),
Expression: eachAttr.Expr,
EvalContext: b.forEachCtx,
})
return nil, diags
}
if eachVal.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic for_each value",
Detail: "Cannot use a null value in for_each.",
Subject: eachAttr.Expr.Range().Ptr(),
Expression: eachAttr.Expr,
EvalContext: b.forEachCtx,
})
return nil, diags
}
//// iterator attribute
iteratorName := blockS.Type
if iteratorAttr := specContent.Attributes["iterator"]; iteratorAttr != nil {
itTraversal, itDiags := hcl.AbsTraversalForExpr(iteratorAttr.Expr)
diags = append(diags, itDiags...)
if itDiags.HasErrors() {
return nil, diags
}
if len(itTraversal) != 1 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic iterator name",
Detail: "Dynamic iterator must be a single variable name.",
Subject: itTraversal.SourceRange().Ptr(),
})
return nil, diags
}
iteratorName = itTraversal.RootName()
}
var labelExprs []hcl.Expression
if labelsAttr := specContent.Attributes["labels"]; labelsAttr != nil {
var labelDiags hcl.Diagnostics
labelExprs, labelDiags = hcl.ExprList(labelsAttr.Expr)
diags = append(diags, labelDiags...)
if labelDiags.HasErrors() {
return nil, diags
}
if len(labelExprs) > len(blockS.LabelNames) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Extraneous dynamic block label",
Detail: fmt.Sprintf("Blocks of type %q require %d label(s).", blockS.Type, len(blockS.LabelNames)),
Subject: labelExprs[len(blockS.LabelNames)].Range().Ptr(),
})
return nil, diags
} else if len(labelExprs) < len(blockS.LabelNames) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Insufficient dynamic block labels",
Detail: fmt.Sprintf("Blocks of type %q require %d label(s).", blockS.Type, len(blockS.LabelNames)),
Subject: labelsAttr.Expr.Range().Ptr(),
})
return nil, diags
}
}
// Since our schema requests only blocks of type "content", we can assume
// that all entries in specContent.Blocks are content blocks.
if len(specContent.Blocks) == 0 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing dynamic content block",
Detail: "A dynamic block must have a nested block of type \"content\" to describe the body of each generated block.",
Subject: &specContent.MissingItemRange,
})
return nil, diags
}
if len(specContent.Blocks) > 1 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Extraneous dynamic content block",
Detail: "Only one nested content block is allowed for each dynamic block.",
Subject: &specContent.Blocks[1].DefRange,
})
return nil, diags
}
return &expandSpec{
blockType: blockS.Type,
blockTypeRange: rawSpec.LabelRanges[0],
defRange: rawSpec.DefRange,
forEachVal: eachVal,
iteratorName: iteratorName,
labelExprs: labelExprs,
contentBody: specContent.Blocks[0].Body,
}, diags
}
func (s *expandSpec) newBlock(i *iteration, ctx *hcl.EvalContext) (*hcl.Block, hcl.Diagnostics) {
var diags hcl.Diagnostics
var labels []string
var labelRanges []hcl.Range
lCtx := i.EvalContext(ctx)
for _, labelExpr := range s.labelExprs {
labelVal, labelDiags := labelExpr.Value(lCtx)
diags = append(diags, labelDiags...)
if labelDiags.HasErrors() {
return nil, diags
}
var convErr error
labelVal, convErr = convert.Convert(labelVal, cty.String)
if convErr != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic block label",
Detail: fmt.Sprintf("Cannot use this value as a dynamic block label: %s.", convErr),
Subject: labelExpr.Range().Ptr(),
Expression: labelExpr,
EvalContext: lCtx,
})
return nil, diags
}
if labelVal.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic block label",
Detail: "Cannot use a null value as a dynamic block label.",
Subject: labelExpr.Range().Ptr(),
Expression: labelExpr,
EvalContext: lCtx,
})
return nil, diags
}
if !labelVal.IsKnown() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic block label",
Detail: "This value is not yet known. Dynamic block labels must be immediately-known values.",
Subject: labelExpr.Range().Ptr(),
Expression: labelExpr,
EvalContext: lCtx,
})
return nil, diags
}
labels = append(labels, labelVal.AsString())
labelRanges = append(labelRanges, labelExpr.Range())
}
block := &hcl.Block{
Type: s.blockType,
TypeRange: s.blockTypeRange,
Labels: labels,
LabelRanges: labelRanges,
DefRange: s.defRange,
Body: s.contentBody,
}
return block, diags
}

View File

@ -1,42 +0,0 @@
package dynblock
import (
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
type exprWrap struct {
hcl.Expression
i *iteration
}
func (e exprWrap) Variables() []hcl.Traversal {
raw := e.Expression.Variables()
ret := make([]hcl.Traversal, 0, len(raw))
// Filter out traversals that refer to our iterator name or any
// iterator we've inherited; we're going to provide those in
// our Value wrapper, so the caller doesn't need to know about them.
for _, traversal := range raw {
rootName := traversal.RootName()
if rootName == e.i.IteratorName {
continue
}
if _, inherited := e.i.Inherited[rootName]; inherited {
continue
}
ret = append(ret, traversal)
}
return ret
}
func (e exprWrap) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
extCtx := e.i.EvalContext(ctx)
return e.Expression.Value(extCtx)
}
// UnwrapExpression returns the expression being wrapped by this instance.
// This allows the original expression to be recovered by hcl.UnwrapExpression.
func (e exprWrap) UnwrapExpression() hcl.Expression {
return e.Expression
}

View File

@ -1,66 +0,0 @@
package dynblock
import (
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
type iteration struct {
IteratorName string
Key cty.Value
Value cty.Value
Inherited map[string]*iteration
}
func (s *expandSpec) MakeIteration(key, value cty.Value) *iteration {
return &iteration{
IteratorName: s.iteratorName,
Key: key,
Value: value,
Inherited: s.inherited,
}
}
func (i *iteration) Object() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"key": i.Key,
"value": i.Value,
})
}
func (i *iteration) EvalContext(base *hcl.EvalContext) *hcl.EvalContext {
new := base.NewChild()
if i != nil {
new.Variables = map[string]cty.Value{}
for name, otherIt := range i.Inherited {
new.Variables[name] = otherIt.Object()
}
new.Variables[i.IteratorName] = i.Object()
}
return new
}
func (i *iteration) MakeChild(iteratorName string, key, value cty.Value) *iteration {
if i == nil {
// Create entirely new root iteration, then
return &iteration{
IteratorName: iteratorName,
Key: key,
Value: value,
}
}
inherited := map[string]*iteration{}
for name, otherIt := range i.Inherited {
inherited[name] = otherIt
}
inherited[i.IteratorName] = i
return &iteration{
IteratorName: iteratorName,
Key: key,
Value: value,
Inherited: inherited,
}
}

View File

@ -1,44 +0,0 @@
package dynblock
import (
"github.com/hashicorp/hcl2/hcl"
)
// Expand "dynamic" blocks in the given body, returning a new body that
// has those blocks expanded.
//
// The given EvalContext is used when evaluating "for_each" and "labels"
// attributes within dynamic blocks, allowing those expressions access to
// variables and functions beyond the iterator variable created by the
// iteration.
//
// Expand returns no diagnostics because no blocks are actually expanded
// until a call to Content or PartialContent on the returned body, which
// will then expand only the blocks selected by the schema.
//
// "dynamic" blocks are also expanded automatically within nested blocks
// in the given body, including within other dynamic blocks, thus allowing
// multi-dimensional iteration. However, it is not possible to
// dynamically-generate the "dynamic" blocks themselves except through nesting.
//
// parent {
// dynamic "child" {
// for_each = child_objs
// content {
// dynamic "grandchild" {
// for_each = child.value.children
// labels = [grandchild.key]
// content {
// parent_key = child.key
// value = grandchild.value
// }
// }
// }
// }
// }
func Expand(body hcl.Body, ctx *hcl.EvalContext) hcl.Body {
return &expandBody{
original: body,
forEachCtx: ctx,
}
}

View File

@ -1,50 +0,0 @@
package dynblock
import "github.com/hashicorp/hcl2/hcl"
var dynamicBlockHeaderSchema = hcl.BlockHeaderSchema{
Type: "dynamic",
LabelNames: []string{"type"},
}
var dynamicBlockBodySchemaLabels = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "for_each",
Required: true,
},
{
Name: "iterator",
Required: false,
},
{
Name: "labels",
Required: true,
},
},
Blocks: []hcl.BlockHeaderSchema{
{
Type: "content",
LabelNames: nil,
},
},
}
var dynamicBlockBodySchemaNoLabels = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "for_each",
Required: true,
},
{
Name: "iterator",
Required: false,
},
},
Blocks: []hcl.BlockHeaderSchema{
{
Type: "content",
LabelNames: nil,
},
},
}

View File

@ -1,165 +0,0 @@
package dynblock
import (
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
// WalkVariables begins the recursive process of walking the variables in the
// given body that are needed by any "for_each" or "labels" attributes in
// "dynamic" blocks. The result is a WalkVariablesNode, which can extract
// root-level variable traversals and produce a list of child nodes that
// also need to be processed by calling Visit.
//
// This function requires that the caller walk through the nested block
// structure in the given body level-by-level so that an appropriate schema
// can be provided at each level to inform further processing. This workflow
// is thus easiest to use for calling applications that have some higher-level
// schema representation available with which to drive this multi-step
// process.
func WalkForEachVariables(body hcl.Body) WalkVariablesNode {
return WalkVariablesNode{
body: body,
}
}
type WalkVariablesNode struct {
body hcl.Body
it *iteration
}
type WalkVariablesChild struct {
BlockTypeName string
Node WalkVariablesNode
}
// Visit returns the variable traversals required for any "dynamic" blocks
// directly in the body associated with this node, and also returns any child
// nodes that must be visited in order to continue the walk.
//
// Each child node has its associated block type name given in its BlockTypeName
// field, which the calling application should use to determine the appropriate
// schema for the content of each child node and pass it to the child node's
// own Visit method to continue the walk recursively.
func (n WalkVariablesNode) Visit(schema *hcl.BodySchema) (vars []hcl.Traversal, children []WalkVariablesChild) {
extSchema := n.extendSchema(schema)
container, _, _ := n.body.PartialContent(extSchema)
if container == nil {
return vars, children
}
children = make([]WalkVariablesChild, 0, len(container.Blocks))
for _, block := range container.Blocks {
switch block.Type {
case "dynamic":
blockTypeName := block.Labels[0]
inner, _, _ := block.Body.PartialContent(variableDetectionInnerSchema)
if inner == nil {
continue
}
iteratorName := blockTypeName
if attr, exists := inner.Attributes["iterator"]; exists {
iterTraversal, _ := hcl.AbsTraversalForExpr(attr.Expr)
if len(iterTraversal) == 0 {
// Ignore this invalid dynamic block, since it'll produce
// an error if someone tries to extract content from it
// later anyway.
continue
}
iteratorName = iterTraversal.RootName()
}
blockIt := n.it.MakeChild(iteratorName, cty.DynamicVal, cty.DynamicVal)
if attr, exists := inner.Attributes["for_each"]; exists {
// Filter out iterator names inherited from parent blocks
for _, traversal := range attr.Expr.Variables() {
if _, inherited := blockIt.Inherited[traversal.RootName()]; !inherited {
vars = append(vars, traversal)
}
}
}
if attr, exists := inner.Attributes["labels"]; exists {
// Filter out both our own iterator name _and_ those inherited
// from parent blocks, since we provide _both_ of these to the
// label expressions.
for _, traversal := range attr.Expr.Variables() {
ours := traversal.RootName() == iteratorName
_, inherited := blockIt.Inherited[traversal.RootName()]
if !(ours || inherited) {
vars = append(vars, traversal)
}
}
}
for _, contentBlock := range inner.Blocks {
// We only request "content" blocks in our schema, so we know
// any blocks we find here will be content blocks. We require
// exactly one content block for actual expansion, but we'll
// be more liberal here so that callers can still collect
// variables from erroneous "dynamic" blocks.
children = append(children, WalkVariablesChild{
BlockTypeName: blockTypeName,
Node: WalkVariablesNode{
body: contentBlock.Body,
it: blockIt,
},
})
}
default:
children = append(children, WalkVariablesChild{
BlockTypeName: block.Type,
Node: WalkVariablesNode{
body: block.Body,
it: n.it,
},
})
}
}
return vars, children
}
func (n WalkVariablesNode) extendSchema(schema *hcl.BodySchema) *hcl.BodySchema {
// We augment the requested schema to also include our special "dynamic"
// block type, since then we'll get instances of it interleaved with
// all of the literal child blocks we must also include.
extSchema := &hcl.BodySchema{
Attributes: schema.Attributes,
Blocks: make([]hcl.BlockHeaderSchema, len(schema.Blocks), len(schema.Blocks)+1),
}
copy(extSchema.Blocks, schema.Blocks)
extSchema.Blocks = append(extSchema.Blocks, dynamicBlockHeaderSchema)
return extSchema
}
// This is a more relaxed schema than what's in schema.go, since we
// want to maximize the amount of variables we can find even if there
// are erroneous blocks.
var variableDetectionInnerSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "for_each",
Required: false,
},
{
Name: "labels",
Required: false,
},
{
Name: "iterator",
Required: false,
},
},
Blocks: []hcl.BlockHeaderSchema{
{
Type: "content",
},
},
}

View File

@ -1,33 +0,0 @@
package dynblock
import (
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcldec"
)
// ForEachVariablesHCLDec is a wrapper around WalkForEachVariables that
// uses the given hcldec specification to automatically drive the recursive
// walk through nested blocks in the given body.
//
// This provides more convenient access to all of the "for_each" and "labels"
// dependencies in a body for applications that are already using hcldec
// as a more convenient way to recursively decode body contents.
func ForEachVariablesHCLDec(body hcl.Body, spec hcldec.Spec) []hcl.Traversal {
rootNode := WalkForEachVariables(body)
return walkVariablesWithHCLDec(rootNode, spec)
}
func walkVariablesWithHCLDec(node WalkVariablesNode, spec hcldec.Spec) []hcl.Traversal {
vars, children := node.Visit(hcldec.ImpliedSchema(spec))
if len(children) > 0 {
childSpecs := hcldec.ChildBlockTypes(spec)
for _, child := range children {
if childSpec, exists := childSpecs[child.BlockTypeName]; exists {
vars = append(vars, walkVariablesWithHCLDec(child.Node, childSpec)...)
}
}
}
return vars
}

View File

@ -1,67 +0,0 @@
# HCL Type Expressions Extension
This HCL extension defines a convention for describing HCL types using function
call and variable reference syntax, allowing configuration formats to include
type information provided by users.
The type syntax is processed statically from a hcl.Expression, so it cannot
use any of the usual language operators. This is similar to type expressions
in statically-typed programming languages.
```hcl
variable "example" {
type = list(string)
}
```
The extension is built using the `hcl.ExprAsKeyword` and `hcl.ExprCall`
functions, and so it relies on the underlying syntax to define how "keyword"
and "call" are interpreted. The above shows how they are interpreted in
the HCL native syntax, while the following shows the same information
expressed in JSON:
```json
{
"variable": {
"example": {
"type": "list(string)"
}
}
}
```
Notice that since we have additional contextual information that we intend
to allow only calls and keywords the JSON syntax is able to parse the given
string directly as an expression, rather than as a template as would be
the case for normal expression evaluation.
For more information, see [the godoc reference](http://godoc.org/github.com/hashicorp/hcl2/ext/typeexpr).
## Type Expression Syntax
When expressed in the native syntax, the following expressions are permitted
in a type expression:
* `string` - string
* `bool` - boolean
* `number` - number
* `any` - `cty.DynamicPseudoType` (in function `TypeConstraint` only)
* `list(<type_expr>)` - list of the type given as an argument
* `set(<type_expr>)` - set of the type given as an argument
* `map(<type_expr>)` - map of the type given as an argument
* `tuple([<type_exprs...>])` - tuple with the element types given in the single list argument
* `object({<attr_name>=<type_expr>, ...}` - object with the attributes and corresponding types given in the single map argument
For example:
* `list(string)`
* `object({name=string,age=number})`
* `map(object({name=string,age=number}))`
Note that the object constructor syntax is not fully-general for all possible
object types because it requires the attribute names to be valid identifiers.
In practice it is expected that any time an object type is being fixed for
type checking it will be one that has identifiers as its attributes; object
types with weird attributes generally show up only from arbitrary object
constructors in configuration files, which are usually treated either as maps
or as the dynamic pseudo-type.

View File

@ -1,11 +0,0 @@
// Package typeexpr extends HCL with a convention for describing HCL types
// within configuration files.
//
// The type syntax is processed statically from a hcl.Expression, so it cannot
// use any of the usual language operators. This is similar to type expressions
// in statically-typed programming languages.
//
// variable "example" {
// type = list(string)
// }
package typeexpr

View File

@ -1,196 +0,0 @@
package typeexpr
import (
"fmt"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
const invalidTypeSummary = "Invalid type specification"
// getType is the internal implementation of both Type and TypeConstraint,
// using the passed flag to distinguish. When constraint is false, the "any"
// keyword will produce an error.
func getType(expr hcl.Expression, constraint bool) (cty.Type, hcl.Diagnostics) {
// First we'll try for one of our keywords
kw := hcl.ExprAsKeyword(expr)
switch kw {
case "bool":
return cty.Bool, nil
case "string":
return cty.String, nil
case "number":
return cty.Number, nil
case "any":
if constraint {
return cty.DynamicPseudoType, nil
}
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("The keyword %q cannot be used in this type specification: an exact type is required.", kw),
Subject: expr.Range().Ptr(),
}}
case "list", "map", "set":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("The %s type constructor requires one argument specifying the element type.", kw),
Subject: expr.Range().Ptr(),
}}
case "object":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "The object type constructor requires one argument specifying the attribute types and values as a map.",
Subject: expr.Range().Ptr(),
}}
case "tuple":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "The tuple type constructor requires one argument specifying the element types as a list.",
Subject: expr.Range().Ptr(),
}}
case "":
// okay! we'll fall through and try processing as a call, then.
default:
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("The keyword %q is not a valid type specification.", kw),
Subject: expr.Range().Ptr(),
}}
}
// If we get down here then our expression isn't just a keyword, so we'll
// try to process it as a call instead.
call, diags := hcl.ExprCall(expr)
if diags.HasErrors() {
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "A type specification is either a primitive type keyword (bool, number, string) or a complex type constructor call, like list(string).",
Subject: expr.Range().Ptr(),
}}
}
switch call.Name {
case "bool", "string", "number", "any":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("Primitive type keyword %q does not expect arguments.", call.Name),
Subject: &call.ArgsRange,
}}
}
if len(call.Arguments) != 1 {
contextRange := call.ArgsRange
subjectRange := call.ArgsRange
if len(call.Arguments) > 1 {
// If we have too many arguments (as opposed to too _few_) then
// we'll highlight the extraneous arguments as the diagnostic
// subject.
subjectRange = hcl.RangeBetween(call.Arguments[1].Range(), call.Arguments[len(call.Arguments)-1].Range())
}
switch call.Name {
case "list", "set", "map":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("The %s type constructor requires one argument specifying the element type.", call.Name),
Subject: &subjectRange,
Context: &contextRange,
}}
case "object":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "The object type constructor requires one argument specifying the attribute types and values as a map.",
Subject: &subjectRange,
Context: &contextRange,
}}
case "tuple":
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "The tuple type constructor requires one argument specifying the element types as a list.",
Subject: &subjectRange,
Context: &contextRange,
}}
}
}
switch call.Name {
case "list":
ety, diags := getType(call.Arguments[0], constraint)
return cty.List(ety), diags
case "set":
ety, diags := getType(call.Arguments[0], constraint)
return cty.Set(ety), diags
case "map":
ety, diags := getType(call.Arguments[0], constraint)
return cty.Map(ety), diags
case "object":
attrDefs, diags := hcl.ExprMap(call.Arguments[0])
if diags.HasErrors() {
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "Object type constructor requires a map whose keys are attribute names and whose values are the corresponding attribute types.",
Subject: call.Arguments[0].Range().Ptr(),
Context: expr.Range().Ptr(),
}}
}
atys := make(map[string]cty.Type)
for _, attrDef := range attrDefs {
attrName := hcl.ExprAsKeyword(attrDef.Key)
if attrName == "" {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "Object constructor map keys must be attribute names.",
Subject: attrDef.Key.Range().Ptr(),
Context: expr.Range().Ptr(),
})
continue
}
aty, attrDiags := getType(attrDef.Value, constraint)
diags = append(diags, attrDiags...)
atys[attrName] = aty
}
return cty.Object(atys), diags
case "tuple":
elemDefs, diags := hcl.ExprList(call.Arguments[0])
if diags.HasErrors() {
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: "Tuple type constructor requires a list of element types.",
Subject: call.Arguments[0].Range().Ptr(),
Context: expr.Range().Ptr(),
}}
}
etys := make([]cty.Type, len(elemDefs))
for i, defExpr := range elemDefs {
ety, elemDiags := getType(defExpr, constraint)
diags = append(diags, elemDiags...)
etys[i] = ety
}
return cty.Tuple(etys), diags
default:
// Can't access call.Arguments in this path because we've not validated
// that it contains exactly one expression here.
return cty.DynamicPseudoType, hcl.Diagnostics{{
Severity: hcl.DiagError,
Summary: invalidTypeSummary,
Detail: fmt.Sprintf("Keyword %q is not a valid type constructor.", call.Name),
Subject: expr.Range().Ptr(),
}}
}
}

View File

@ -1,129 +0,0 @@
package typeexpr
import (
"bytes"
"fmt"
"sort"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
// Type attempts to process the given expression as a type expression and, if
// successful, returns the resulting type. If unsuccessful, error diagnostics
// are returned.
func Type(expr hcl.Expression) (cty.Type, hcl.Diagnostics) {
return getType(expr, false)
}
// TypeConstraint attempts to parse the given expression as a type constraint
// and, if successful, returns the resulting type. If unsuccessful, error
// diagnostics are returned.
//
// A type constraint has the same structure as a type, but it additionally
// allows the keyword "any" to represent cty.DynamicPseudoType, which is often
// used as a wildcard in type checking and type conversion operations.
func TypeConstraint(expr hcl.Expression) (cty.Type, hcl.Diagnostics) {
return getType(expr, true)
}
// TypeString returns a string rendering of the given type as it would be
// expected to appear in the HCL native syntax.
//
// This is primarily intended for showing types to the user in an application
// that uses typexpr, where the user can be assumed to be familiar with the
// type expression syntax. In applications that do not use typeexpr these
// results may be confusing to the user and so type.FriendlyName may be
// preferable, even though it's less precise.
//
// TypeString produces reasonable results only for types like what would be
// produced by the Type and TypeConstraint functions. In particular, it cannot
// support capsule types.
func TypeString(ty cty.Type) string {
// Easy cases first
switch ty {
case cty.String:
return "string"
case cty.Bool:
return "bool"
case cty.Number:
return "number"
case cty.DynamicPseudoType:
return "any"
}
if ty.IsCapsuleType() {
panic("TypeString does not support capsule types")
}
if ty.IsCollectionType() {
ety := ty.ElementType()
etyString := TypeString(ety)
switch {
case ty.IsListType():
return fmt.Sprintf("list(%s)", etyString)
case ty.IsSetType():
return fmt.Sprintf("set(%s)", etyString)
case ty.IsMapType():
return fmt.Sprintf("map(%s)", etyString)
default:
// Should never happen because the above is exhaustive
panic("unsupported collection type")
}
}
if ty.IsObjectType() {
var buf bytes.Buffer
buf.WriteString("object({")
atys := ty.AttributeTypes()
names := make([]string, 0, len(atys))
for name := range atys {
names = append(names, name)
}
sort.Strings(names)
first := true
for _, name := range names {
aty := atys[name]
if !first {
buf.WriteByte(',')
}
if !hclsyntax.ValidIdentifier(name) {
// Should never happen for any type produced by this package,
// but we'll do something reasonable here just so we don't
// produce garbage if someone gives us a hand-assembled object
// type that has weird attribute names.
// Using Go-style quoting here isn't perfect, since it doesn't
// exactly match HCL syntax, but it's fine for an edge-case.
buf.WriteString(fmt.Sprintf("%q", name))
} else {
buf.WriteString(name)
}
buf.WriteByte('=')
buf.WriteString(TypeString(aty))
first = false
}
buf.WriteString("})")
return buf.String()
}
if ty.IsTupleType() {
var buf bytes.Buffer
buf.WriteString("tuple([")
etys := ty.TupleElementTypes()
first := true
for _, ety := range etys {
if !first {
buf.WriteByte(',')
}
buf.WriteString(TypeString(ety))
first = false
}
buf.WriteString("])")
return buf.String()
}
// Should never happen because we covered all cases above.
panic(fmt.Errorf("unsupported type %#v", ty))
}

View File

@ -1235,6 +1235,19 @@ func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
return cty.DynamicVal, diags
}
if sourceVal.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Splat of null value",
Detail: "Splat expressions (with the * symbol) cannot be applied to null values.",
Subject: e.Source.Range().Ptr(),
Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
Expression: e.Source,
EvalContext: ctx,
})
return cty.DynamicVal, diags
}
sourceTy := sourceVal.Type()
if sourceTy == cty.DynamicPseudoType {
// If we don't even know the _type_ of our source value yet then
@ -1245,27 +1258,9 @@ func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
// A "special power" of splat expressions is that they can be applied
// both to tuples/lists and to other values, and in the latter case
// the value will be treated as an implicit single-item tuple, or as
// an empty tuple if the value is null.
autoUpgrade := !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType())
if sourceVal.IsNull() {
if autoUpgrade {
return cty.EmptyTupleVal, diags
}
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Splat of null value",
Detail: "Splat expressions (with the * symbol) cannot be applied to null sequences.",
Subject: e.Source.Range().Ptr(),
Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
Expression: e.Source,
EvalContext: ctx,
})
return cty.DynamicVal, diags
}
if autoUpgrade {
// the value will be treated as an implicit single-value tuple. We'll
// deal with that here first.
if !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType()) {
sourceVal = cty.TupleVal([]cty.Value{sourceVal})
sourceTy = sourceVal.Type()
}

View File

@ -9,6 +9,7 @@ import (
"github.com/apparentlymart/go-textseg/textseg"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
)
type parser struct {
@ -235,18 +236,10 @@ func (p *parser) finishParsingBodyAttribute(ident Token, singleLine bool) (Node,
end := p.Peek()
if end.Type != TokenNewline && end.Type != TokenEOF {
if !p.recovery {
summary := "Missing newline after argument"
detail := "An argument definition must end with a newline."
if end.Type == TokenComma {
summary = "Unexpected comma after argument"
detail = "Argument definitions must be separated by newlines, not commas. " + detail
}
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: summary,
Detail: detail,
Summary: "Missing newline after argument",
Detail: "An argument definition must end with a newline.",
Subject: &end.Range,
Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(),
})
@ -293,9 +286,19 @@ Token:
diags = append(diags, labelDiags...)
labels = append(labels, label)
labelRanges = append(labelRanges, labelRange)
// parseQuoteStringLiteral recovers up to the closing quote
// if it encounters problems, so we can continue looking for
// more labels and eventually the block body even.
if labelDiags.HasErrors() {
p.recoverAfterBodyItem()
return &Block{
Type: blockType,
Labels: labels,
Body: nil,
TypeRange: ident.Range,
LabelRanges: labelRanges,
OpenBraceRange: ident.Range, // placeholder
CloseBraceRange: ident.Range, // placeholder
}, diags
}
case TokenIdent:
tok = p.Read() // eat token
@ -1047,10 +1050,11 @@ func (p *parser) parseExpressionTerm() (Expression, hcl.Diagnostics) {
}
func (p *parser) numberLitValue(tok Token) (cty.Value, hcl.Diagnostics) {
// The cty.ParseNumberVal is always the same behavior as converting a
// string to a number, ensuring we always interpret decimal numbers in
// the same way.
numVal, err := cty.ParseNumberVal(string(tok.Bytes))
// We'll lean on the cty converter to do the conversion, to ensure that
// the behavior is the same as what would happen if converting a
// non-literal string to a number.
numStrVal := cty.StringVal(string(tok.Bytes))
numVal, err := convert.Convert(numStrVal, cty.Number)
if err != nil {
ret := cty.UnknownVal(cty.Number)
return ret, hcl.Diagnostics{
@ -1644,16 +1648,7 @@ Token:
Subject: &tok.Range,
Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),
})
// Now that we're returning an error callers won't attempt to use
// the result for any real operations, but they might try to use
// the partial AST for other analyses, so we'll leave a marker
// to indicate that there was something invalid in the string to
// help avoid misinterpretation of the partial result
ret.WriteString(which)
ret.WriteString("{ ... }")
p.recover(TokenTemplateSeqEnd) // we'll try to keep parsing after the sequence ends
p.recover(TokenTemplateSeqEnd)
case TokenEOF:
diags = append(diags, &hcl.Diagnostic{
@ -1674,7 +1669,7 @@ Token:
Subject: &tok.Range,
Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),
})
p.recover(TokenCQuote)
p.recover(TokenOQuote)
break Token
}

View File

@ -1,10 +1,10 @@
//line scan_string_lit.rl:1
// line 1 "scan_string_lit.rl"
package hclsyntax
// This file is generated from scan_string_lit.rl. DO NOT EDIT.
//line scan_string_lit.go:9
// line 9 "scan_string_lit.go"
var _hclstrtok_actions []byte = []byte{
0, 1, 0, 1, 1, 2, 1, 0,
}
@ -114,12 +114,12 @@ const hclstrtok_error int = 0
const hclstrtok_en_quoted int = 10
const hclstrtok_en_unquoted int = 4
//line scan_string_lit.rl:10
// line 10 "scan_string_lit.rl"
func scanStringLit(data []byte, quoted bool) [][]byte {
var ret [][]byte
//line scan_string_lit.rl:61
// line 61 "scan_string_lit.rl"
// Ragel state
p := 0 // "Pointer" into data
@ -144,11 +144,11 @@ func scanStringLit(data []byte, quoted bool) [][]byte {
ret = append(ret, data[ts:te])
}*/
//line scan_string_lit.go:154
// line 154 "scan_string_lit.go"
{
}
//line scan_string_lit.go:158
// line 158 "scan_string_lit.go"
{
var _klen int
var _trans int
@ -229,7 +229,7 @@ func scanStringLit(data []byte, quoted bool) [][]byte {
_acts++
switch _hclstrtok_actions[_acts-1] {
case 0:
//line scan_string_lit.rl:40
// line 40 "scan_string_lit.rl"
// If te is behind p then we've skipped over some literal
// characters which we must now return.
@ -239,12 +239,12 @@ func scanStringLit(data []byte, quoted bool) [][]byte {
ts = p
case 1:
//line scan_string_lit.rl:48
// line 48 "scan_string_lit.rl"
te = p
ret = append(ret, data[ts:te])
//line scan_string_lit.go:253
// line 255 "scan_string_lit.go"
}
}
@ -267,12 +267,12 @@ func scanStringLit(data []byte, quoted bool) [][]byte {
__acts++
switch _hclstrtok_actions[__acts-1] {
case 1:
//line scan_string_lit.rl:48
// line 48 "scan_string_lit.rl"
te = p
ret = append(ret, data[ts:te])
//line scan_string_lit.go:278
// line 281 "scan_string_lit.go"
}
}
}
@ -282,7 +282,7 @@ func scanStringLit(data []byte, quoted bool) [][]byte {
}
}
//line scan_string_lit.rl:89
// line 89 "scan_string_lit.rl"
if te < p {
// Collect any leftover literal characters at the end of the input

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,13 @@ import (
// This file is generated from scan_tokens.rl. DO NOT EDIT.
%%{
# (except when you are actually in scan_tokens.rl here, so edit away!)
# (except you are actually in scan_tokens.rl here, so edit away!)
machine hcltok;
write data;
}%%
func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {
stripData := stripUTF8BOM(data)
start.Byte += len(data) - len(stripData)
data = stripData
f := &tokenAccum{
Filename: filename,
Bytes: data,
@ -44,7 +40,7 @@ func scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []To
Ident = (ID_Start | '_') (ID_Continue | '-')*;
# Symbols that just represent themselves are handled as a single rule.
SelfToken = "[" | "]" | "(" | ")" | "." | "," | "*" | "/" | "%" | "+" | "-" | "=" | "<" | ">" | "!" | "?" | ":" | "\n" | "&" | "|" | "~" | "^" | ";" | "`" | "'";
SelfToken = "[" | "]" | "(" | ")" | "." | "," | "*" | "/" | "%" | "+" | "-" | "=" | "<" | ">" | "!" | "?" | ":" | "\n" | "&" | "|" | "~" | "^" | ";" | "`";
EqualOp = "==";
NotEqual = "!=";

View File

@ -9,13 +9,13 @@ generation of configuration.
The language consists of three integrated sub-languages:
- The _structural_ language defines the overall hierarchical configuration
* The _structural_ language defines the overall hierarchical configuration
structure, and is a serialization of HCL bodies, blocks and attributes.
- The _expression_ language is used to express attribute values, either as
* The _expression_ language is used to express attribute values, either as
literals or as derivations of other values.
- The _template_ language is used to compose values together into strings,
* The _template_ language is used to compose values together into strings,
as one of several types of expression in the expression language.
In normal use these three sub-languages are used together within configuration
@ -30,19 +30,19 @@ Within this specification a semi-formal notation is used to illustrate the
details of syntax. This notation is intended for human consumption rather
than machine consumption, with the following conventions:
- A naked name starting with an uppercase letter is a global production,
* A naked name starting with an uppercase letter is a global production,
common to all of the syntax specifications in this document.
- A naked name starting with a lowercase letter is a local production,
* A naked name starting with a lowercase letter is a local production,
meaningful only within the specification where it is defined.
- Double and single quotes (`"` and `'`) are used to mark literal character
* Double and single quotes (`"` and `'`) are used to mark literal character
sequences, which may be either punctuation markers or keywords.
- The default operator for combining items, which has no punctuation,
* The default operator for combining items, which has no punctuation,
is concatenation.
- The symbol `|` indicates that any one of its left and right operands may
* The symbol `|` indicates that any one of its left and right operands may
be present.
- The `*` symbol indicates zero or more repetitions of the item to its left.
- The `?` symbol indicates zero or one of the item to its left.
- Parentheses (`(` and `)`) are used to group items together to apply
* The `*` symbol indicates zero or more repetitions of the item to its left.
* The `?` symbol indicates zero or one of the item to its left.
* Parentheses (`(` and `)`) are used to group items together to apply
the `|`, `*` and `?` operators to them collectively.
The grammar notation does not fully describe the language. The prose may
@ -77,11 +77,11 @@ are not valid within HCL native syntax.
Comments serve as program documentation and come in two forms:
- _Line comments_ start with either the `//` or `#` sequences and end with
* _Line comments_ start with either the `//` or `#` sequences and end with
the next newline sequence. A line comments is considered equivalent to a
newline sequence.
- _Inline comments_ start with the `/*` sequence and end with the `*/`
* _Inline comments_ start with the `/*` sequence and end with the `*/`
sequence, and may have any characters within except the ending sequence.
An inline comments is considered equivalent to a whitespace sequence.
@ -91,7 +91,7 @@ template literals except inside an interpolation sequence or template directive.
### Identifiers
Identifiers name entities such as blocks, attributes and expression variables.
Identifiers are interpreted as per [UAX #31][uax31] Section 2. Specifically,
Identifiers are interpreted as per [UAX #31][UAX31] Section 2. Specifically,
their syntax is defined in terms of the `ID_Start` and `ID_Continue`
character properties as follows:
@ -109,7 +109,7 @@ that is not part of the unicode `ID_Continue` definition. This is to allow
attribute names and block type names to contain dashes, although underscores
as word separators are considered the idiomatic usage.
[uax31]: http://unicode.org/reports/tr31/ "Unicode Identifier and Pattern Syntax"
[UAX31]: http://unicode.org/reports/tr31/ "Unicode Identifier and Pattern Syntax"
### Keywords
@ -150,9 +150,9 @@ expmark = ('e' | 'E') ("+" | "-")?;
The structural language consists of syntax representing the following
constructs:
- _Attributes_, which assign a value to a specified name.
- _Blocks_, which create a child body annotated by a type and optional labels.
- _Body Content_, which consists of a collection of attributes and blocks.
* _Attributes_, which assign a value to a specified name.
* _Blocks_, which create a child body annotated by a type and optional labels.
* _Body Content_, which consists of a collection of attributes and blocks.
These constructs correspond to the similarly-named concepts in the
language-agnostic HCL information model.
@ -253,9 +253,9 @@ LiteralValue = (
);
```
- Numeric literals represent values of type _number_.
- The `true` and `false` keywords represent values of type _bool_.
- The `null` keyword represents a null value of the dynamic pseudo-type.
* Numeric literals represent values of type _number_.
* The `true` and `false` keywords represent values of type _bool_.
* The `null` keyword represents a null value of the dynamic pseudo-type.
String literals are not directly available in the expression sub-language, but
are available via the template sub-language, which can in turn be incorporated
@ -286,8 +286,8 @@ When specifying an object element, an identifier is interpreted as a literal
attribute name as opposed to a variable reference. To populate an item key
from a variable, use parentheses to disambiguate:
- `{foo = "baz"}` is interpreted as an attribute literally named `foo`.
- `{(foo) = "baz"}` is interpreted as an attribute whose name is taken
* `{foo = "baz"}` is interpreted as an attribute literally named `foo`.
* `{(foo) = "baz"}` is interpreted as an attribute whose name is taken
from the variable named `foo`.
Between the open and closing delimiters of these sequences, newline sequences
@ -299,12 +299,12 @@ _for expression_ interpretation has priority, so to produce a tuple whose
first element is the value of a variable named `for`, or an object with a
key named `for`, use parentheses to disambiguate:
- `[for, foo, baz]` is a syntax error.
- `[(for), foo, baz]` is a tuple whose first element is the value of variable
* `[for, foo, baz]` is a syntax error.
* `[(for), foo, baz]` is a tuple whose first element is the value of variable
`for`.
- `{for: 1, baz: 2}` is a syntax error.
- `{(for): 1, baz: 2}` is an object with an attribute literally named `for`.
- `{baz: 2, for: 1}` is equivalent to the previous example, and resolves the
* `{for: 1, baz: 2}` is a syntax error.
* `{(for): 1, baz: 2}` is an object with an attribute literally named `for`.
* `{baz: 2, for: 1}` is equivalent to the previous example, and resolves the
ambiguity by reordering.
### Template Expressions
@ -312,9 +312,9 @@ key named `for`, use parentheses to disambiguate:
A _template expression_ embeds a program written in the template sub-language
as an expression. Template expressions come in two forms:
- A _quoted_ template expression is delimited by quote characters (`"`) and
* A _quoted_ template expression is delimited by quote characters (`"`) and
defines a template as a single-line expression with escape characters.
- A _heredoc_ template expression is introduced by a `<<` sequence and
* A _heredoc_ template expression is introduced by a `<<` sequence and
defines a template via a multi-line sequence terminated by a user-chosen
delimiter.
@ -322,7 +322,7 @@ In both cases the template interpolation and directive syntax is available for
use within the delimiters, and any text outside of these special sequences is
interpreted as a literal string.
In _quoted_ template expressions any literal string sequences within the
In _quoted_ template expressions any literal string sequences within the
template behave in a special way: literal newline sequences are not permitted
and instead _escape sequences_ can be included, starting with the
backslash `\`:
@ -458,14 +458,14 @@ are provided, the first is the key and the second is the value.
Tuple, object, list, map, and set types are iterable. The type of collection
used defines how the key and value variables are populated:
- For tuple and list types, the _key_ is the zero-based index into the
* For tuple and list types, the _key_ is the zero-based index into the
sequence for each element, and the _value_ is the element value. The
elements are visited in index order.
- For object and map types, the _key_ is the string attribute name or element
* For object and map types, the _key_ is the string attribute name or element
key, and the _value_ is the attribute or element value. The elements are
visited in the order defined by a lexicographic sort of the attribute names
or keys.
- For set types, the _key_ and _value_ are both the element value. The elements
* For set types, the _key_ and _value_ are both the element value. The elements
are visited in an undefined but consistent order.
The expression after the colon and (in the case of object `for`) the expression
@ -487,12 +487,12 @@ immediately after the value expression, this activates the grouping mode in
which each value in the resulting object is a _tuple_ of all of the values
that were produced against each distinct key.
- `[for v in ["a", "b"]: v]` returns `["a", "b"]`.
- `[for i, v in ["a", "b"]: i]` returns `[0, 1]`.
- `{for i, v in ["a", "b"]: v => i}` returns `{a = 0, b = 1}`.
- `{for i, v in ["a", "a", "b"]: k => v}` produces an error, because attribute
* `[for v in ["a", "b"]: v]` returns `["a", "b"]`.
* `[for i, v in ["a", "b"]: i]` returns `[0, 1]`.
* `{for i, v in ["a", "b"]: v => i}` returns `{a = 0, b = 1}`.
* `{for i, v in ["a", "a", "b"]: k => v}` produces an error, because attribute
`a` is defined twice.
- `{for i, v in ["a", "a", "b"]: v => i...}` returns `{a = [0, 1], b = [2]}`.
* `{for i, v in ["a", "a", "b"]: v => i...}` returns `{a = [0, 1], b = [2]}`.
If the `if` keyword is used after the element expression(s), it applies an
additional predicate that can be used to conditionally filter elements from
@ -502,7 +502,7 @@ element expression(s). It must evaluate to a boolean value; if `true`, the
element will be evaluated as normal, while if `false` the element will be
skipped.
- `[for i, v in ["a", "b", "c"]: v if i < 2]` returns `["a", "b"]`.
* `[for i, v in ["a", "b", "c"]: v if i < 2]` returns `["a", "b"]`.
If the collection value, element expression(s) or condition expression return
unknown values that are otherwise type-valid, the result is a value of the
@ -567,10 +567,10 @@ elements in a tuple, list, or set value.
There are two kinds of "splat" operator:
- The _attribute-only_ splat operator supports only attribute lookups into
* The _attribute-only_ splat operator supports only attribute lookups into
the elements from a list, but supports an arbitrary number of them.
- The _full_ splat operator additionally supports indexing into the elements
* The _full_ splat operator additionally supports indexing into the elements
from a list, and allows any combination of attribute access and index
operations.
@ -583,9 +583,9 @@ fullSplat = "[" "*" "]" (GetAttr | Index)*;
The splat operators can be thought of as shorthands for common operations that
could otherwise be performed using _for expressions_:
- `tuple.*.foo.bar[0]` is approximately equivalent to
* `tuple.*.foo.bar[0]` is approximately equivalent to
`[for v in tuple: v.foo.bar][0]`.
- `tuple[*].foo.bar[0]` is approximately equivalent to
* `tuple[*].foo.bar[0]` is approximately equivalent to
`[for v in tuple: v.foo.bar[0]]`
Note the difference in how the trailing index operator is interpreted in
@ -597,15 +597,13 @@ _for expressions_ shown above: if a splat operator is applied to a value that
is _not_ of tuple, list, or set type, the value is coerced automatically into
a single-value list of the value type:
- `any_object.*.id` is equivalent to `[any_object.id]`, assuming that `any_object`
* `any_object.*.id` is equivalent to `[any_object.id]`, assuming that `any_object`
is a single object.
- `any_number.*` is equivalent to `[any_number]`, assuming that `any_number`
* `any_number.*` is equivalent to `[any_number]`, assuming that `any_number`
is a single number.
If applied to a null value that is not tuple, list, or set, the result is always
an empty tuple, which allows conveniently converting a possibly-null scalar
value into a tuple of zero or one elements. It is illegal to apply a splat
operator to a null value of tuple, list, or set type.
If the left operand of a splat operator is an unknown value of any type, the
result is a value of the dynamic pseudo-type.
### Operations
@ -686,7 +684,7 @@ Arithmetic operations are considered to be performed in an arbitrary-precision
number space.
If either operand of an arithmetic operator is an unknown number or a value
of the dynamic pseudo-type, the result is an unknown number.
of the dynamic pseudo-type, the result is an unknown number.
### Logic Operators
@ -711,7 +709,7 @@ the outcome of a boolean expression.
Conditional = Expression "?" Expression ":" Expression;
```
The first expression is the _predicate_, which is evaluated and must produce
The first expression is the _predicate_, which is evaluated and must produce
a boolean result. If the predicate value is `true`, the result of the second
expression is the result of the conditional. If the predicate value is
`false`, the result of the third expression is the result of the conditional.
@ -779,8 +777,8 @@ interpolations or directives that are adjacent to it. A strip marker is
a tilde (`~`) placed immediately after the opening `{` or before the closing
`}` of a template sequence:
- `hello ${~ "world" }` produces `"helloworld"`.
- `%{ if true ~} hello %{~ endif }` produces `"hello"`.
* `hello ${~ "world" }` produces `"helloworld"`.
* `%{ if true ~} hello %{~ endif }` produces `"hello"`.
When a strip marker is present, any spaces adjacent to it in the corresponding
string literal (if any) are removed before producing the final value. Space
@ -789,7 +787,7 @@ characters are interpreted as per Unicode's definition.
Stripping is done at syntax level rather than value level. Values returned
by interpolations or directives are not subject to stripping:
- `${"hello" ~}${" world"}` produces `"hello world"`, and not `"helloworld"`,
* `${"hello" ~}${" world"}` produces `"hello world"`, and not `"helloworld"`,
because the space is not in a template literal directly adjacent to the
strip marker.
@ -827,9 +825,9 @@ TemplateIf = (
The evaluation of the `if` directive is equivalent to the conditional
expression, with the following exceptions:
- The two sub-templates always produce strings, and thus the result value is
* The two sub-templates always produce strings, and thus the result value is
also always a string.
- The `else` clause may be omitted, in which case the conditional's third
* The `else` clause may be omitted, in which case the conditional's third
expression result is implied to be the empty string.
### Template For Directive
@ -849,9 +847,9 @@ TemplateFor = (
The evaluation of the `for` directive is equivalent to the _for expression_
when producing a tuple, with the following exceptions:
- The sub-template always produces a string.
- There is no equivalent of the "if" clause on the for expression.
- The elements of the resulting tuple are all converted to strings and
* The sub-template always produces a string.
* There is no equivalent of the "if" clause on the for expression.
* The elements of the resulting tuple are all converted to strings and
concatenated to produce a flat string result.
### Template Interpolation Unwrapping
@ -867,13 +865,13 @@ template or expression syntax. Unwrapping allows arbitrary expressions to be
used to populate attributes when strings in such languages are interpreted
as templates.
- `${true}` produces the boolean value `true`
- `${"${true}"}` produces the boolean value `true`, because both the inner
* `${true}` produces the boolean value `true`
* `${"${true}"}` produces the boolean value `true`, because both the inner
and outer interpolations are subject to unwrapping.
- `hello ${true}` produces the string `"hello true"`
- `${""}${true}` produces the string `"true"` because there are two
* `hello ${true}` produces the string `"hello true"`
* `${""}${true}` produces the string `"true"` because there are two
interpolation sequences, even though one produces an empty result.
- `%{ for v in [true] }${v}%{ endif }` produces the string `true` because
* `%{ for v in [true] }${v}%{ endif }` produces the string `true` because
the presence of the `for` directive circumvents the unwrapping even though
the final result is a single value.

View File

@ -255,9 +255,9 @@ func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
example := b.Blocks[0]
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unexpected %q block", example.Type),
Summary: fmt.Sprintf("Unexpected %s block", example.Type),
Detail: "Blocks are not allowed here.",
Subject: &example.TypeRange,
Context: &example.TypeRange,
})
// we will continue processing anyway, and return the attributes
// we are able to find so that certain analyses can still be done

View File

@ -90,7 +90,6 @@ const (
TokenBitwiseNot TokenType = '~'
TokenBitwiseXor TokenType = '^'
TokenStarStar TokenType = '➚'
TokenApostrophe TokenType = '\''
TokenBacktick TokenType = '`'
TokenSemicolon TokenType = ';'
TokenTabs TokenType = '␉'
@ -184,15 +183,11 @@ func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
toldBitwise := 0
toldExponent := 0
toldBacktick := 0
toldApostrophe := 0
toldSemicolon := 0
toldTabs := 0
toldBadUTF8 := 0
for _, tok := range tokens {
// copy token so it's safe to point to it
tok := tok
switch tok.Type {
case TokenBitwiseAnd, TokenBitwiseOr, TokenBitwiseXor, TokenBitwiseNot:
if toldBitwise < 4 {
@ -228,30 +223,16 @@ func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
case TokenBacktick:
// Only report for alternating (even) backticks, so we won't report both start and ends of the same
// backtick-quoted string.
if (toldBacktick % 2) == 0 {
if toldExponent < 4 && (toldExponent%2) == 0 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid character",
Detail: "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<<EOT\".",
Subject: &tok.Range,
})
}
if toldBacktick <= 2 {
toldBacktick++
}
case TokenApostrophe:
if (toldApostrophe % 2) == 0 {
newDiag := &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid character",
Detail: "Single quotes are not valid. Use double quotes (\") to enclose strings.",
Subject: &tok.Range,
}
diags = append(diags, newDiag)
}
if toldApostrophe <= 2 {
toldApostrophe++
}
case TokenSemicolon:
if toldSemicolon < 1 {
diags = append(diags, &hcl.Diagnostic{
@ -292,21 +273,9 @@ func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
Detail: "This character is not used within the language.",
Subject: &tok.Range,
})
toldTabs++
}
}
return diags
}
var utf8BOM = []byte{0xef, 0xbb, 0xbf}
// stripUTF8BOM checks whether the given buffer begins with a UTF-8 byte order
// mark (0xEF 0xBB 0xBF) and, if so, returns a truncated slice with the same
// backing array but with the BOM skipped.
//
// If there is no BOM present, the given slice is returned verbatim.
func stripUTF8BOM(src []byte) []byte {
if bytes.HasPrefix(src, utf8BOM) {
return src[3:]
}
return src
}

View File

@ -4,7 +4,7 @@ package hclsyntax
import "strconv"
const _TokenType_name = "TokenNilTokenNewlineTokenBangTokenPercentTokenBitwiseAndTokenApostropheTokenOParenTokenCParenTokenStarTokenPlusTokenCommaTokenMinusTokenDotTokenSlashTokenColonTokenSemicolonTokenLessThanTokenEqualTokenGreaterThanTokenQuestionTokenCommentTokenOHeredocTokenIdentTokenNumberLitTokenQuotedLitTokenStringLitTokenOBrackTokenCBrackTokenBitwiseXorTokenBacktickTokenCHeredocTokenOBraceTokenBitwiseOrTokenCBraceTokenBitwiseNotTokenOQuoteTokenCQuoteTokenTemplateControlTokenEllipsisTokenFatArrowTokenTemplateSeqEndTokenAndTokenOrTokenTemplateInterpTokenEqualOpTokenNotEqualTokenLessThanEqTokenGreaterThanEqTokenEOFTokenTabsTokenStarStarTokenInvalidTokenBadUTF8"
const _TokenType_name = "TokenNilTokenNewlineTokenBangTokenPercentTokenBitwiseAndTokenOParenTokenCParenTokenStarTokenPlusTokenCommaTokenMinusTokenDotTokenSlashTokenColonTokenSemicolonTokenLessThanTokenEqualTokenGreaterThanTokenQuestionTokenCommentTokenOHeredocTokenIdentTokenNumberLitTokenQuotedLitTokenStringLitTokenOBrackTokenCBrackTokenBitwiseXorTokenBacktickTokenCHeredocTokenOBraceTokenBitwiseOrTokenCBraceTokenBitwiseNotTokenOQuoteTokenCQuoteTokenTemplateControlTokenEllipsisTokenFatArrowTokenTemplateSeqEndTokenAndTokenOrTokenTemplateInterpTokenEqualOpTokenNotEqualTokenLessThanEqTokenGreaterThanEqTokenEOFTokenTabsTokenStarStarTokenInvalidTokenBadUTF8"
var _TokenType_map = map[TokenType]string{
0: _TokenType_name[0:8],
@ -12,54 +12,53 @@ var _TokenType_map = map[TokenType]string{
33: _TokenType_name[20:29],
37: _TokenType_name[29:41],
38: _TokenType_name[41:56],
39: _TokenType_name[56:71],
40: _TokenType_name[71:82],
41: _TokenType_name[82:93],
42: _TokenType_name[93:102],
43: _TokenType_name[102:111],
44: _TokenType_name[111:121],
45: _TokenType_name[121:131],
46: _TokenType_name[131:139],
47: _TokenType_name[139:149],
58: _TokenType_name[149:159],
59: _TokenType_name[159:173],
60: _TokenType_name[173:186],
61: _TokenType_name[186:196],
62: _TokenType_name[196:212],
63: _TokenType_name[212:225],
67: _TokenType_name[225:237],
72: _TokenType_name[237:250],
73: _TokenType_name[250:260],
78: _TokenType_name[260:274],
81: _TokenType_name[274:288],
83: _TokenType_name[288:302],
91: _TokenType_name[302:313],
93: _TokenType_name[313:324],
94: _TokenType_name[324:339],
96: _TokenType_name[339:352],
104: _TokenType_name[352:365],
123: _TokenType_name[365:376],
124: _TokenType_name[376:390],
125: _TokenType_name[390:401],
126: _TokenType_name[401:416],
171: _TokenType_name[416:427],
187: _TokenType_name[427:438],
955: _TokenType_name[438:458],
8230: _TokenType_name[458:471],
8658: _TokenType_name[471:484],
8718: _TokenType_name[484:503],
8743: _TokenType_name[503:511],
8744: _TokenType_name[511:518],
8747: _TokenType_name[518:537],
8788: _TokenType_name[537:549],
8800: _TokenType_name[549:562],
8804: _TokenType_name[562:577],
8805: _TokenType_name[577:595],
9220: _TokenType_name[595:603],
9225: _TokenType_name[603:612],
10138: _TokenType_name[612:625],
65533: _TokenType_name[625:637],
128169: _TokenType_name[637:649],
40: _TokenType_name[56:67],
41: _TokenType_name[67:78],
42: _TokenType_name[78:87],
43: _TokenType_name[87:96],
44: _TokenType_name[96:106],
45: _TokenType_name[106:116],
46: _TokenType_name[116:124],
47: _TokenType_name[124:134],
58: _TokenType_name[134:144],
59: _TokenType_name[144:158],
60: _TokenType_name[158:171],
61: _TokenType_name[171:181],
62: _TokenType_name[181:197],
63: _TokenType_name[197:210],
67: _TokenType_name[210:222],
72: _TokenType_name[222:235],
73: _TokenType_name[235:245],
78: _TokenType_name[245:259],
81: _TokenType_name[259:273],
83: _TokenType_name[273:287],
91: _TokenType_name[287:298],
93: _TokenType_name[298:309],
94: _TokenType_name[309:324],
96: _TokenType_name[324:337],
104: _TokenType_name[337:350],
123: _TokenType_name[350:361],
124: _TokenType_name[361:375],
125: _TokenType_name[375:386],
126: _TokenType_name[386:401],
171: _TokenType_name[401:412],
187: _TokenType_name[412:423],
955: _TokenType_name[423:443],
8230: _TokenType_name[443:456],
8658: _TokenType_name[456:469],
8718: _TokenType_name[469:488],
8743: _TokenType_name[488:496],
8744: _TokenType_name[496:503],
8747: _TokenType_name[503:522],
8788: _TokenType_name[522:534],
8800: _TokenType_name[534:547],
8804: _TokenType_name[547:562],
8805: _TokenType_name[562:580],
9220: _TokenType_name[580:588],
9225: _TokenType_name[588:597],
10138: _TokenType_name[597:610],
65533: _TokenType_name[610:622],
128169: _TokenType_name[622:634],
}
func (i TokenType) String() string {

View File

@ -3,9 +3,9 @@ package json
import (
"encoding/json"
"fmt"
"math/big"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty"
)
func parseFileContent(buf []byte, filename string) (node, hcl.Diagnostics) {
@ -370,15 +370,10 @@ func parseNumber(p *peeker) (node, hcl.Diagnostics) {
}
}
// We want to guarantee that we parse numbers the same way as cty (and thus
// native syntax HCL) would here, so we'll use the cty parser even though
// in most other cases we don't actually introduce cty concepts until
// decoding time. We'll unwrap the parsed float immediately afterwards, so
// the cty value is just a temporary helper.
nv, err := cty.ParseNumberVal(string(num))
f, _, err := big.ParseFloat(string(num), 10, 512, big.ToNearestEven)
if err != nil {
// Should never happen if above passed, since JSON numbers are a subset
// of what cty can parse...
// of what big.Float can parse...
return nil, hcl.Diagnostics{
{
Severity: hcl.DiagError,
@ -390,7 +385,7 @@ func parseNumber(p *peeker) (node, hcl.Diagnostics) {
}
return &numberVal{
Value: nv.AsBigFloat(),
Value: f,
SrcRange: tok.Range,
}, nil
}

View File

@ -18,11 +18,11 @@ _Parsing_ such JSON has some additional constraints not beyond what is normally
supported by JSON parsers, so a specialized parser may be required that
is able to:
- Preserve the relative ordering of properties defined in an object.
- Preserve multiple definitions of the same property name.
- Preserve numeric values to the precision required by the number type
* Preserve the relative ordering of properties defined in an object.
* Preserve multiple definitions of the same property name.
* Preserve numeric values to the precision required by the number type
in [the HCL syntax-agnostic information model](../spec.md).
- Retain source location information for parsed tokens/constructs in order
* Retain source location information for parsed tokens/constructs in order
to produce good error messages.
## Structural Elements
@ -118,7 +118,6 @@ type:
]
}
```
```json
{
"foo": []
@ -148,7 +147,7 @@ the following examples:
"boz": {
"baz": {
"child_attr": "baz"
}
},
}
}
}
@ -190,7 +189,7 @@ the following examples:
"boz": {
"child_attr": "baz"
}
}
},
},
{
"bar": {
@ -403,3 +402,4 @@ to that expression.
If the original expression is not a string or its contents cannot be parsed
as a native syntax expression then static call analysis is not supported.

View File

@ -145,122 +145,3 @@ func Index(collection, key cty.Value, srcRange *Range) (cty.Value, Diagnostics)
}
}
// GetAttr is a helper function that performs the same operation as the
// attribute access in the HCL expression language. That is, the result is the
// same as it would be for obj.attr in a configuration expression.
//
// This is exported so that applications can access attributes in a manner
// consistent with how the language does it, including handling of null and
// unknown values, etc.
//
// Diagnostics are produced if the given combination of values is not valid.
// Therefore a pointer to a source range must be provided to use in diagnostics,
// though nil can be provided if the calling application is going to
// ignore the subject of the returned diagnostics anyway.
func GetAttr(obj cty.Value, attrName string, srcRange *Range) (cty.Value, Diagnostics) {
if obj.IsNull() {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Attempt to get attribute from null value",
Detail: "This value is null, so it does not have any attributes.",
Subject: srcRange,
},
}
}
ty := obj.Type()
switch {
case ty.IsObjectType():
if !ty.HasAttribute(attrName) {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: fmt.Sprintf("This object does not have an attribute named %q.", attrName),
Subject: srcRange,
},
}
}
if !obj.IsKnown() {
return cty.UnknownVal(ty.AttributeType(attrName)), nil
}
return obj.GetAttr(attrName), nil
case ty.IsMapType():
if !obj.IsKnown() {
return cty.UnknownVal(ty.ElementType()), nil
}
idx := cty.StringVal(attrName)
if obj.HasIndex(idx).False() {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Missing map element",
Detail: fmt.Sprintf("This map does not have an element with the key %q.", attrName),
Subject: srcRange,
},
}
}
return obj.Index(idx), nil
case ty == cty.DynamicPseudoType:
return cty.DynamicVal, nil
default:
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: "This value does not have any attributes.",
Subject: srcRange,
},
}
}
}
// ApplyPath is a helper function that applies a cty.Path to a value using the
// indexing and attribute access operations from HCL.
//
// This is similar to calling the path's own Apply method, but ApplyPath uses
// the more relaxed typing rules that apply to these operations in HCL, rather
// than cty's relatively-strict rules. ApplyPath is implemented in terms of
// Index and GetAttr, and so it has the same behavior for individual steps
// but will stop and return any errors returned by intermediate steps.
//
// Diagnostics are produced if the given path cannot be applied to the given
// value. Therefore a pointer to a source range must be provided to use in
// diagnostics, though nil can be provided if the calling application is going
// to ignore the subject of the returned diagnostics anyway.
func ApplyPath(val cty.Value, path cty.Path, srcRange *Range) (cty.Value, Diagnostics) {
var diags Diagnostics
for _, step := range path {
var stepDiags Diagnostics
switch ts := step.(type) {
case cty.IndexStep:
val, stepDiags = Index(val, ts.Key, srcRange)
case cty.GetAttrStep:
val, stepDiags = GetAttr(val, ts.Name, srcRange)
default:
// Should never happen because the above are all of the step types.
diags = diags.Append(&Diagnostic{
Severity: DiagError,
Summary: "Invalid path step",
Detail: fmt.Sprintf("Go type %T is not a valid path step. This is a bug in this program.", step),
Subject: srcRange,
})
return cty.DynamicVal, diags
}
diags = append(diags, stepDiags...)
if stepDiags.HasErrors() {
return cty.DynamicVal, diags
}
}
return val, diags
}

View File

@ -57,10 +57,10 @@ access to the specific attributes and blocks requested.
A _body schema_ consists of a list of _attribute schemata_ and
_block header schemata_:
- An _attribute schema_ provides the name of an attribute and whether its
* An _attribute schema_ provides the name of an attribute and whether its
presence is required.
- A _block header schema_ provides a block type name and the semantic names
* A _block header schema_ provides a block type name and the semantic names
assigned to each of the labels of that block type, if any.
Within a schema, it is an error to request the same attribute name twice or
@ -72,11 +72,11 @@ a block whose type name is identical to the attribute name.
The result of applying a body schema to a body is _body content_, which
consists of an _attribute map_ and a _block sequence_:
- The _attribute map_ is a map data structure whose keys are attribute names
* The _attribute map_ is a map data structure whose keys are attribute names
and whose values are _expressions_ that represent the corresponding attribute
values.
- The _block sequence_ is an ordered sequence of blocks, with each specifying
* The _block sequence_ is an ordered sequence of blocks, with each specifying
a block _type name_, the sequence of _labels_ specified for the block,
and the body object (not body _content_) representing the block's own body.
@ -132,13 +132,13 @@ the schema has been processed.
Specifically:
- Any attribute whose name is specified in the schema is returned in body
* Any attribute whose name is specified in the schema is returned in body
content and elided from the new body.
- Any block whose type is specified in the schema is returned in body content
* Any block whose type is specified in the schema is returned in body content
and elided from the new body.
- Any attribute or block _not_ meeting the above conditions is placed into
* Any attribute or block _not_ meeting the above conditions is placed into
the new body, unmodified.
The new body can then be recursively processed using any of the body
@ -168,20 +168,20 @@ In order to obtain a concrete value, each expression must be _evaluated_.
Evaluation is performed in terms of an evaluation context, which
consists of the following:
- An _evaluation mode_, which is defined below.
- A _variable scope_, which provides a set of named variables for use in
* An _evaluation mode_, which is defined below.
* A _variable scope_, which provides a set of named variables for use in
expressions.
- A _function table_, which provides a set of named functions for use in
* A _function table_, which provides a set of named functions for use in
expressions.
The _evaluation mode_ allows for two different interpretations of an
expression:
- In _literal-only mode_, variables and functions are not available and it
* In _literal-only mode_, variables and functions are not available and it
is assumed that the calling application's intent is to treat the attribute
value as a literal.
- In _full expression mode_, variables and functions are defined and it is
* In _full expression mode_, variables and functions are defined and it is
assumed that the calling application wishes to provide a full expression
language for definition of the attribute value.
@ -235,15 +235,15 @@ for interpretation into any suitable number representation. An implementation
may in practice implement numbers with limited precision so long as the
following constraints are met:
- Integers are represented with at least 256 bits.
- Non-integer numbers are represented as floating point values with a
* Integers are represented with at least 256 bits.
* Non-integer numbers are represented as floating point values with a
mantissa of at least 256 bits and a signed binary exponent of at least
16 bits.
- An error is produced if an integer value given in source cannot be
* An error is produced if an integer value given in source cannot be
represented precisely.
- An error is produced if a non-integer value cannot be represented due to
* An error is produced if a non-integer value cannot be represented due to
overflow.
- A non-integer number is rounded to the nearest possible value when a
* A non-integer number is rounded to the nearest possible value when a
value is of too high a precision to be represented.
The _number_ type also requires representation of both positive and negative
@ -265,11 +265,11 @@ _Structural types_ are types that are constructed by combining other types.
Each distinct combination of other types is itself a distinct type. There
are two structural type _kinds_:
- _Object types_ are constructed of a set of named attributes, each of which
* _Object types_ are constructed of a set of named attributes, each of which
has a type. Attribute names are always strings. (_Object_ attributes are a
distinct idea from _body_ attributes, though calling applications
may choose to blur the distinction by use of common naming schemes.)
- _Tuple types_ are constructed of a sequence of elements, each of which
* _Tuple types_ are constructed of a sequence of elements, each of which
has a type.
Values of structural types are compared for equality in terms of their
@ -284,9 +284,9 @@ have attributes or elements with identical types.
_Collection types_ are types that combine together an arbitrary number of
values of some other single type. There are three collection type _kinds_:
- _List types_ represent ordered sequences of values of their element type.
- _Map types_ represent values of their element type accessed via string keys.
- _Set types_ represent unordered sets of distinct values of their element type.
* _List types_ represent ordered sequences of values of their element type.
* _Map types_ represent values of their element type accessed via string keys.
* _Set types_ represent unordered sets of distinct values of their element type.
For each of these kinds and each distinct element type there is a distinct
collection type. For example, "list of string" is a distinct type from
@ -376,9 +376,9 @@ a type has a non-commutative _matches_ relationship with a _type specification_.
A type specification is, in practice, just a different interpretation of a
type such that:
- Any type _matches_ any type that it is identical to.
* Any type _matches_ any type that it is identical to.
- Any type _matches_ the dynamic pseudo-type.
* Any type _matches_ the dynamic pseudo-type.
For example, given a type specification "list of dynamic pseudo-type", the
concrete types "list of string" and "list of map" match, but the
@ -397,51 +397,51 @@ applications to provide functions that are interoperable with all syntaxes.
A _function_ is defined from the following elements:
- Zero or more _positional parameters_, each with a name used for documentation,
* Zero or more _positional parameters_, each with a name used for documentation,
a type specification for expected argument values, and a flag for whether
each of null values, unknown values, and values of the dynamic pseudo-type
are accepted.
- Zero or one _variadic parameters_, with the same structure as the _positional_
* Zero or one _variadic parameters_, with the same structure as the _positional_
parameters, which if present collects any additional arguments provided at
the function call site.
- A _result type definition_, which specifies the value type returned for each
* A _result type definition_, which specifies the value type returned for each
valid sequence of argument values.
- A _result value definition_, which specifies the value returned for each
* A _result value definition_, which specifies the value returned for each
valid sequence of argument values.
A _function call_, regardless of source syntax, consists of a sequence of
argument values. The argument values are each mapped to a corresponding
parameter as follows:
- For each of the function's positional parameters in sequence, take the next
* For each of the function's positional parameters in sequence, take the next
argument. If there are no more arguments, the call is erroneous.
- If the function has a variadic parameter, take all remaining arguments that
* If the function has a variadic parameter, take all remaining arguments that
where not yet assigned to a positional parameter and collect them into
a sequence of variadic arguments that each correspond to the variadic
parameter.
- If the function has _no_ variadic parameter, it is an error if any arguments
* If the function has _no_ variadic parameter, it is an error if any arguments
remain after taking one argument for each positional parameter.
After mapping each argument to a parameter, semantic checking proceeds
for each argument:
- If the argument value corresponding to a parameter does not match the
* If the argument value corresponding to a parameter does not match the
parameter's type specification, the call is erroneous.
- If the argument value corresponding to a parameter is null and the parameter
* If the argument value corresponding to a parameter is null and the parameter
is not specified as accepting nulls, the call is erroneous.
- If the argument value corresponding to a parameter is the dynamic value
* If the argument value corresponding to a parameter is the dynamic value
and the parameter is not specified as accepting values of the dynamic
pseudo-type, the call is valid but its _result type_ is forced to be the
dynamic pseudo type.
- If neither of the above conditions holds for any argument, the call is
* If neither of the above conditions holds for any argument, the call is
valid and the function's value type definition is used to determine the
call's _result type_. A function _may_ vary its result type depending on
the argument _values_ as well as the argument _types_; for example, a
@ -450,11 +450,11 @@ for each argument:
If semantic checking succeeds without error, the call is _executed_:
- For each argument, if its value is unknown and its corresponding parameter
* For each argument, if its value is unknown and its corresponding parameter
is not specified as accepting unknowns, the _result value_ is forced to be an
unknown value of the result type.
- If the previous condition does not apply, the function's result value
* If the previous condition does not apply, the function's result value
definition is used to determine the call's _result value_.
The result of a function call expression is either an error, if one of the
@ -631,20 +631,20 @@ diagnostics if they are applied to inappropriate expressions.
The following are the required static analysis functions:
- **Static List**: Require list/tuple construction syntax to be used and
* **Static List**: Require list/tuple construction syntax to be used and
return a list of expressions for each of the elements given.
- **Static Map**: Require map/object construction syntax to be used and
* **Static Map**: Require map/object construction syntax to be used and
return a list of key/value pairs -- both expressions -- for each of
the elements given. The usual constraint that a map key must be a string
must not apply to this analysis, thus allowing applications to interpret
arbitrary keys as they see fit.
- **Static Call**: Require function call syntax to be used and return an
* **Static Call**: Require function call syntax to be used and return an
object describing the called function name and a list of expressions
representing each of the call arguments.
- **Static Traversal**: Require a reference to a symbol in the variable
* **Static Traversal**: Require a reference to a symbol in the variable
scope and return a description of the path from the root scope to the
accessed attribute or index.
@ -670,18 +670,18 @@ with the goals of this specification.
The language-agnosticism of this specification assumes that certain behaviors
are implemented separately for each syntax:
- Matching of a body schema with the physical elements of a body in the
* Matching of a body schema with the physical elements of a body in the
source language, to determine correspondence between physical constructs
and schema elements.
- Implementing the _dynamic attributes_ body processing mode by either
* Implementing the _dynamic attributes_ body processing mode by either
interpreting all physical constructs as attributes or producing an error
if non-attribute constructs are present.
- Providing an evaluation function for all possible expressions that produces
* Providing an evaluation function for all possible expressions that produces
a value given an evaluation context.
- Providing the static analysis functionality described above in a manner that
* Providing the static analysis functionality described above in a manner that
makes sense within the convention of the syntax.
The suggested implementation strategy is to use an implementation language's

View File

@ -255,7 +255,66 @@ type TraverseAttr struct {
}
func (tn TraverseAttr) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {
return GetAttr(val, tn.Name, &tn.SrcRange)
if val.IsNull() {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Attempt to get attribute from null value",
Detail: "This value is null, so it does not have any attributes.",
Subject: &tn.SrcRange,
},
}
}
ty := val.Type()
switch {
case ty.IsObjectType():
if !ty.HasAttribute(tn.Name) {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: fmt.Sprintf("This object does not have an attribute named %q.", tn.Name),
Subject: &tn.SrcRange,
},
}
}
if !val.IsKnown() {
return cty.UnknownVal(ty.AttributeType(tn.Name)), nil
}
return val.GetAttr(tn.Name), nil
case ty.IsMapType():
if !val.IsKnown() {
return cty.UnknownVal(ty.ElementType()), nil
}
idx := cty.StringVal(tn.Name)
if val.HasIndex(idx).False() {
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Missing map element",
Detail: fmt.Sprintf("This map does not have an element with the key %q.", tn.Name),
Subject: &tn.SrcRange,
},
}
}
return val.Index(idx), nil
case ty == cty.DynamicPseudoType:
return cty.DynamicVal, nil
default:
return cty.DynamicVal, Diagnostics{
{
Severity: DiagError,
Summary: "Unsupported attribute",
Detail: "This value does not have any attributes.",
Subject: &tn.SrcRange,
},
}
}
}
func (tn TraverseAttr) SourceRange() Range {

View File

@ -1,4 +0,0 @@
// Package hcled provides functionality intended to help an application
// that embeds HCL to deliver relevant information to a text editor or IDE
// for navigating around and analyzing configuration files.
package hcled

View File

@ -1,34 +0,0 @@
package hcled
import (
"github.com/hashicorp/hcl2/hcl"
)
type contextStringer interface {
ContextString(offset int) string
}
// ContextString returns a string describing the context of the given byte
// offset, if available. An empty string is returned if no such information
// is available, or otherwise the returned string is in a form that depends
// on the language used to write the referenced file.
func ContextString(file *hcl.File, offset int) string {
if cser, ok := file.Nav.(contextStringer); ok {
return cser.ContextString(offset)
}
return ""
}
type contextDefRanger interface {
ContextDefRange(offset int) hcl.Range
}
func ContextDefRange(file *hcl.File, offset int) hcl.Range {
if cser, ok := file.Nav.(contextDefRanger); ok {
defRange := cser.ContextDefRange(offset)
if !defRange.Empty() {
return defRange
}
}
return file.Body.MissingItemRange()
}

View File

@ -325,10 +325,6 @@ func spaceAfterToken(subject, before, after *Token) bool {
case subject.Type == hclsyntax.TokenCBrace && after.Type == hclsyntax.TokenTemplateSeqEnd:
return true
// Don't add spaces between interpolated items
case subject.Type == hclsyntax.TokenTemplateSeqEnd && after.Type == hclsyntax.TokenTemplateInterp:
return false
case tokenBracketChange(subject) > 0:
// No spaces after open brackets
return false

View File

@ -47,23 +47,8 @@ func hilMapstructureWeakDecode(m interface{}, rawVal interface{}) error {
}
func InterfaceToVariable(input interface{}) (ast.Variable, error) {
if iv, ok := input.(ast.Variable); ok {
return iv, nil
}
// This is just to maintain backward compatibility
// after https://github.com/mitchellh/mapstructure/pull/98
if v, ok := input.([]ast.Variable); ok {
return ast.Variable{
Type: ast.TypeList,
Value: v,
}, nil
}
if v, ok := input.(map[string]ast.Variable); ok {
return ast.Variable{
Type: ast.TypeMap,
Value: v,
}, nil
if inputVariable, ok := input.(ast.Variable); ok {
return inputVariable, nil
}
var stringVal string

View File

@ -1,6 +0,0 @@
module github.com/hashicorp/hil
require (
github.com/mitchellh/mapstructure v1.1.2
github.com/mitchellh/reflectwalk v1.0.0
)

View File

@ -1,4 +0,0 @@
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=

View File

@ -1,353 +0,0 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. “Contributor”
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. “Contributor Version”
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributors Contribution.
1.3. “Contribution”
means Covered Software of a particular Contributor.
1.4. “Covered Software”
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. “Incompatible With Secondary Licenses”
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of version
1.1 or earlier of the License, but not also under the terms of a
Secondary License.
1.6. “Executable Form”
means any form of the work other than Source Code Form.
1.7. “Larger Work”
means a work that combines Covered Software with other material, in a separate
file or files, that is not Covered Software.
1.8. “License”
means this document.
1.9. “Licensable”
means having the right to grant, to the maximum extent possible, whether at the
time of the initial grant or subsequently, any and all of the rights conveyed by
this License.
1.10. “Modifications”
means any of the following:
a. any file in Source Code Form that results from an addition to, deletion
from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. “Patent Claims” of a Contributor
means any patent claim(s), including without limitation, method, process,
and apparatus claims, in any patent Licensable by such Contributor that
would be infringed, but for the grant of the License, by the making,
using, selling, offering for sale, having made, import, or transfer of
either its Contributions or its Contributor Version.
1.12. “Secondary License”
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. “Source Code Form”
means the form of the work preferred for making modifications.
1.14. “You” (or “Your”)
means an individual or a legal entity exercising rights under this
License. For legal entities, “You” includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, “control” means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or as
part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions
or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution become
effective for each Contribution on the date the Contributor first distributes
such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under this
License. No additional rights or licenses will be implied from the distribution
or licensing of Covered Software under this License. Notwithstanding Section
2.1(b) above, no patent license is granted by a Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third partys
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of its
Contributions.
This License does not grant any rights in the trademarks, service marks, or
logos of any Contributor (except as may be necessary to comply with the
notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this License
(see Section 10.2) or under the terms of a Secondary License (if permitted
under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its Contributions
are its original creation(s) or it has sufficient rights to grant the
rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under applicable
copyright doctrines of fair use, fair dealing, or other equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under the
terms of this License. You must inform recipients that the Source Code Form
of the Covered Software is governed by the terms of this License, and how
they can obtain a copy of this License. You may not attempt to alter or
restrict the recipients rights in the Source Code Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this License,
or sublicense it under different terms, provided that the license for
the Executable Form does not attempt to limit or alter the recipients
rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for the
Covered Software. If the Larger Work is a combination of Covered Software
with a work governed by one or more Secondary Licenses, and the Covered
Software is not Incompatible With Secondary Licenses, this License permits
You to additionally distribute such Covered Software under the terms of
such Secondary License(s), so that the recipient of the Larger Work may, at
their option, further distribute the Covered Software under the terms of
either this License or such Secondary License(s).
3.4. Notices
You may not remove or alter the substance of any license notices (including
copyright notices, patent notices, disclaimers of warranty, or limitations
of liability) contained within the Source Code Form of the Covered
Software, except that You may alter any license notices to the extent
required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on behalf
of any Contributor. You must make it absolutely clear that any such
warranty, support, indemnity, or liability obligation is offered by You
alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute, judicial
order, or regulation then You must: (a) comply with the terms of this License
to the maximum extent possible; and (b) describe the limitations and the code
they affect. Such description must be placed in a text file included with all
distributions of the Covered Software under this License. Except to the
extent prohibited by statute or regulation, such description must be
sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
if such Contributor fails to notify You of the non-compliance by some
reasonable means prior to 60 days after You have come back into compliance.
Moreover, Your grants from a particular Contributor are reinstated on an
ongoing basis if such Contributor notifies You of the non-compliance by
some reasonable means, this is the first time You have received notice of
non-compliance with this License from such Contributor, and You become
compliant prior to 30 days after Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions, counter-claims,
and cross-claims) alleging that a Contributor Version directly or
indirectly infringes any patent, then the rights granted to You by any and
all Contributors for the Covered Software under Section 2.1 of this License
shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an “as is” basis, without
warranty of any kind, either expressed, implied, or statutory, including,
without limitation, warranties that the Covered Software is free of defects,
merchantable, fit for a particular purpose or non-infringing. The entire
risk as to the quality and performance of the Covered Software is with You.
Should any Covered Software prove defective in any respect, You (not any
Contributor) assume the cost of any necessary servicing, repair, or
correction. This disclaimer of warranty constitutes an essential part of this
License. No use of any Covered Software is authorized under this License
except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from such
partys negligence to the extent applicable law prohibits such limitation.
Some jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts of
a jurisdiction where the defendant maintains its principal place of business
and such litigation shall be governed by laws of that jurisdiction, without
reference to its conflict-of-law provisions. Nothing in this Section shall
prevent a partys ability to bring cross-claims or counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Any law or regulation which provides that the language of a
contract shall be construed against the drafter shall not be used to construe
this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version of
the License under which You originally received the Covered Software, or
under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a modified
version of this License if you rename the license and remove any
references to the name of the license steward (except to note that such
modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - “Incompatible With Secondary Licenses” Notice
This Source Code Form is “Incompatible
With Secondary Licenses”, as defined by
the Mozilla Public License, v. 2.0.

View File

@ -1,138 +0,0 @@
package tfconfig
import (
"fmt"
legacyhclparser "github.com/hashicorp/hcl/hcl/parser"
"github.com/hashicorp/hcl2/hcl"
)
// Diagnostic describes a problem (error or warning) encountered during
// configuration loading.
type Diagnostic struct {
Severity DiagSeverity `json:"severity"`
Summary string `json:"summary"`
Detail string `json:"detail,omitempty"`
// Pos is not populated for all diagnostics, but when populated should
// indicate a particular line that the described problem relates to.
Pos *SourcePos `json:"pos,omitempty"`
}
// Diagnostics represents a sequence of diagnostics. This is the type that
// should be returned from a function that might generate diagnostics.
type Diagnostics []Diagnostic
// HasErrors returns true if there is at least one Diagnostic of severity
// DiagError in the receiever.
//
// If a function returns a Diagnostics without errors then the result can
// be assumed to be complete within the "best effort" constraints of this
// library. If errors are present then the caller may wish to employ more
// caution in relying on the result.
func (diags Diagnostics) HasErrors() bool {
for _, diag := range diags {
if diag.Severity == DiagError {
return true
}
}
return false
}
func (diags Diagnostics) Error() string {
switch len(diags) {
case 0:
return "no problems"
case 1:
return fmt.Sprintf("%s: %s", diags[0].Summary, diags[0].Detail)
default:
return fmt.Sprintf("%s: %s (and %d other messages)", diags[0].Summary, diags[0].Detail, len(diags)-1)
}
}
// Err returns an error representing the receiver if the receiver HasErrors, or
// nil otherwise.
//
// The returned error can be type-asserted back to a Diagnostics if needed.
func (diags Diagnostics) Err() error {
if diags.HasErrors() {
return diags
}
return nil
}
// DiagSeverity describes the severity of a Diagnostic.
type DiagSeverity rune
// DiagError indicates a problem that prevented proper processing of the
// configuration. In the precense of DiagError diagnostics the result is
// likely to be incomplete.
const DiagError DiagSeverity = 'E'
// DiagWarning indicates a problem that the user may wish to consider but
// that did not prevent proper processing of the configuration.
const DiagWarning DiagSeverity = 'W'
// MarshalJSON is an implementation of encoding/json.Marshaler
func (s DiagSeverity) MarshalJSON() ([]byte, error) {
switch s {
case DiagError:
return []byte(`"error"`), nil
case DiagWarning:
return []byte(`"warning"`), nil
default:
return []byte(`"invalid"`), nil
}
}
func diagnosticsHCL(diags hcl.Diagnostics) Diagnostics {
if len(diags) == 0 {
return nil
}
ret := make(Diagnostics, len(diags))
for i, diag := range diags {
ret[i] = Diagnostic{
Summary: diag.Summary,
Detail: diag.Detail,
}
switch diag.Severity {
case hcl.DiagError:
ret[i].Severity = DiagError
case hcl.DiagWarning:
ret[i].Severity = DiagWarning
}
if diag.Subject != nil {
pos := sourcePosHCL(*diag.Subject)
ret[i].Pos = &pos
}
}
return ret
}
func diagnosticsError(err error) Diagnostics {
if err == nil {
return nil
}
if posErr, ok := err.(*legacyhclparser.PosError); ok {
pos := sourcePosLegacyHCL(posErr.Pos, "")
return Diagnostics{
Diagnostic{
Severity: DiagError,
Summary: posErr.Err.Error(),
Pos: &pos,
},
}
}
return Diagnostics{
Diagnostic{
Severity: DiagError,
Summary: err.Error(),
},
}
}
func diagnosticsErrorf(format string, args ...interface{}) Diagnostics {
return diagnosticsError(fmt.Errorf(format, args...))
}

View File

@ -1,21 +0,0 @@
// Package tfconfig is a helper library that does careful, shallow parsing of
// Terraform modules to provide access to high-level metadata while
// remaining broadly compatible with configurations targeting various
// different Terraform versions.
//
// This packge focuses on describing top-level objects only, and in particular
// does not attempt any sort of processing that would require access to plugins.
// Currently it allows callers to extract high-level information about
// variables, outputs, resource blocks, provider dependencies, and Terraform
// Core dependencies.
//
// This package only works at the level of single modules. A full configuration
// is a tree of potentially several modules, some of which may be references
// to remote packages. There are some basic helpers for traversing calls to
// modules at relative local paths, however.
//
// This package employs a "best effort" parsing strategy, producing as complete
// a result as possible even though the input may not be entirely valid. The
// intended use-case is high-level analysis and indexing of externally-facing
// module characteristics, as opposed to validating or even applying the module.
package tfconfig

View File

@ -1,130 +0,0 @@
package tfconfig
import (
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"github.com/hashicorp/hcl2/hcl"
)
// LoadModule reads the directory at the given path and attempts to interpret
// it as a Terraform module.
func LoadModule(dir string) (*Module, Diagnostics) {
// For broad compatibility here we actually have two separate loader
// codepaths. The main one uses the new HCL parser and API and is intended
// for configurations from Terraform 0.12 onwards (though will work for
// many older configurations too), but we'll also fall back on one that
// uses the _old_ HCL implementation so we can deal with some edge-cases
// that are not valid in new HCL.
module, diags := loadModule(dir)
if diags.HasErrors() {
// Try using the legacy HCL parser and see if we fare better.
legacyModule, legacyDiags := loadModuleLegacyHCL(dir)
if !legacyDiags.HasErrors() {
legacyModule.init(legacyDiags)
return legacyModule, legacyDiags
}
}
module.init(diags)
return module, diags
}
// IsModuleDir checks if the given path contains terraform configuration files.
// This allows the caller to decide how to handle directories that do not have tf files.
func IsModuleDir(dir string) bool {
primaryPaths, _ := dirFiles(dir)
if len(primaryPaths) == 0 {
return false
}
return true
}
func (m *Module) init(diags Diagnostics) {
// Fill in any additional provider requirements that are implied by
// resource configurations, to avoid the caller from needing to apply
// this logic itself. Implied requirements don't have version constraints,
// but we'll make sure the requirement value is still non-nil in this
// case so callers can easily recognize it.
for _, r := range m.ManagedResources {
if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
m.RequiredProviders[r.Provider.Name] = []string{}
}
}
for _, r := range m.DataResources {
if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
m.RequiredProviders[r.Provider.Name] = []string{}
}
}
// We redundantly also reference the diagnostics from inside the module
// object, primarily so that we can easily included in JSON-serialized
// versions of the module object.
m.Diagnostics = diags
}
func dirFiles(dir string) (primary []string, diags hcl.Diagnostics) {
infos, err := ioutil.ReadDir(dir)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Failed to read module directory",
Detail: fmt.Sprintf("Module directory %s does not exist or cannot be read.", dir),
})
return
}
var override []string
for _, info := range infos {
if info.IsDir() {
// We only care about files
continue
}
name := info.Name()
ext := fileExt(name)
if ext == "" || isIgnoredFile(name) {
continue
}
baseName := name[:len(name)-len(ext)] // strip extension
isOverride := baseName == "override" || strings.HasSuffix(baseName, "_override")
fullPath := filepath.Join(dir, name)
if isOverride {
override = append(override, fullPath)
} else {
primary = append(primary, fullPath)
}
}
// We are assuming that any _override files will be logically named,
// and processing the files in alphabetical order. Primaries first, then overrides.
primary = append(primary, override...)
return
}
// fileExt returns the Terraform configuration extension of the given
// path, or a blank string if it is not a recognized extension.
func fileExt(path string) string {
if strings.HasSuffix(path, ".tf") {
return ".tf"
} else if strings.HasSuffix(path, ".tf.json") {
return ".tf.json"
} else {
return ""
}
}
// isIgnoredFile returns true if the given filename (which must not have a
// directory path ahead of it) should be ignored as e.g. an editor swap file.
func isIgnoredFile(name string) bool {
return strings.HasPrefix(name, ".") || // Unix-like hidden files
strings.HasSuffix(name, "~") || // vim
strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs
}

View File

@ -1,312 +0,0 @@
package tfconfig
import (
"encoding/json"
"fmt"
"strings"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/gohcl"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hclparse"
ctyjson "github.com/zclconf/go-cty/cty/json"
)
func loadModule(dir string) (*Module, Diagnostics) {
mod := newModule(dir)
primaryPaths, diags := dirFiles(dir)
parser := hclparse.NewParser()
for _, filename := range primaryPaths {
var file *hcl.File
var fileDiags hcl.Diagnostics
if strings.HasSuffix(filename, ".json") {
file, fileDiags = parser.ParseJSONFile(filename)
} else {
file, fileDiags = parser.ParseHCLFile(filename)
}
diags = append(diags, fileDiags...)
if file == nil {
continue
}
content, _, contentDiags := file.Body.PartialContent(rootSchema)
diags = append(diags, contentDiags...)
for _, block := range content.Blocks {
switch block.Type {
case "terraform":
content, _, contentDiags := block.Body.PartialContent(terraformBlockSchema)
diags = append(diags, contentDiags...)
if attr, defined := content.Attributes["required_version"]; defined {
var version string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
diags = append(diags, valDiags...)
if !valDiags.HasErrors() {
mod.RequiredCore = append(mod.RequiredCore, version)
}
}
for _, block := range content.Blocks {
// Our schema only allows required_providers here, so we
// assume that we'll only get that block type.
attrs, attrDiags := block.Body.JustAttributes()
diags = append(diags, attrDiags...)
for name, attr := range attrs {
var version string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
diags = append(diags, valDiags...)
if !valDiags.HasErrors() {
mod.RequiredProviders[name] = append(mod.RequiredProviders[name], version)
}
}
}
case "variable":
content, _, contentDiags := block.Body.PartialContent(variableSchema)
diags = append(diags, contentDiags...)
name := block.Labels[0]
v := &Variable{
Name: name,
Pos: sourcePosHCL(block.DefRange),
}
mod.Variables[name] = v
if attr, defined := content.Attributes["type"]; defined {
// We handle this particular attribute in a somewhat-tricky way:
// since Terraform may evolve its type expression syntax in
// future versions, we don't want to be overly-strict in how
// we handle it here, and so we'll instead just take the raw
// source provided by the user, using the source location
// information in the expression object.
//
// However, older versions of Terraform expected the type
// to be a string containing a keyword, so we'll need to
// handle that as a special case first for backward compatibility.
var typeExpr string
var typeExprAsStr string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &typeExprAsStr)
if !valDiags.HasErrors() {
typeExpr = typeExprAsStr
} else {
rng := attr.Expr.Range()
sourceFilename := rng.Filename
source, exists := parser.Sources()[sourceFilename]
if exists {
typeExpr = string(rng.SliceBytes(source))
} else {
// This should never happen, so we'll just warn about it and leave the type unspecified.
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Source code not available",
Detail: fmt.Sprintf("Source code is not available for the file %q, which declares the variable %q.", sourceFilename, name),
Subject: &block.DefRange,
})
typeExpr = ""
}
}
v.Type = typeExpr
}
if attr, defined := content.Attributes["description"]; defined {
var description string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &description)
diags = append(diags, valDiags...)
v.Description = description
}
if attr, defined := content.Attributes["default"]; defined {
// To avoid the caller needing to deal with cty here, we'll
// use its JSON encoding to convert into an
// approximately-equivalent plain Go interface{} value
// to return.
val, valDiags := attr.Expr.Value(nil)
diags = append(diags, valDiags...)
if val.IsWhollyKnown() { // should only be false if there are errors in the input
valJSON, err := ctyjson.Marshal(val, val.Type())
if err != nil {
// Should never happen, since all possible known
// values have a JSON mapping.
panic(fmt.Errorf("failed to serialize default value as JSON: %s", err))
}
var def interface{}
err = json.Unmarshal(valJSON, &def)
if err != nil {
// Again should never happen, because valJSON is
// guaranteed valid by ctyjson.Marshal.
panic(fmt.Errorf("failed to re-parse default value from JSON: %s", err))
}
v.Default = def
}
}
case "output":
content, _, contentDiags := block.Body.PartialContent(outputSchema)
diags = append(diags, contentDiags...)
name := block.Labels[0]
o := &Output{
Name: name,
Pos: sourcePosHCL(block.DefRange),
}
mod.Outputs[name] = o
if attr, defined := content.Attributes["description"]; defined {
var description string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &description)
diags = append(diags, valDiags...)
o.Description = description
}
case "provider":
content, _, contentDiags := block.Body.PartialContent(providerConfigSchema)
diags = append(diags, contentDiags...)
name := block.Labels[0]
if attr, defined := content.Attributes["version"]; defined {
var version string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
diags = append(diags, valDiags...)
if !valDiags.HasErrors() {
mod.RequiredProviders[name] = append(mod.RequiredProviders[name], version)
}
}
// Even if there wasn't an explicit version required, we still
// need an entry in our map to signal the unversioned dependency.
if _, exists := mod.RequiredProviders[name]; !exists {
mod.RequiredProviders[name] = []string{}
}
case "resource", "data":
content, _, contentDiags := block.Body.PartialContent(resourceSchema)
diags = append(diags, contentDiags...)
typeName := block.Labels[0]
name := block.Labels[1]
r := &Resource{
Type: typeName,
Name: name,
Pos: sourcePosHCL(block.DefRange),
}
var resourcesMap map[string]*Resource
switch block.Type {
case "resource":
r.Mode = ManagedResourceMode
resourcesMap = mod.ManagedResources
case "data":
r.Mode = DataResourceMode
resourcesMap = mod.DataResources
}
key := r.MapKey()
resourcesMap[key] = r
if attr, defined := content.Attributes["provider"]; defined {
// New style here is to provide this as a naked traversal
// expression, but we also support quoted references for
// older configurations that predated this convention.
traversal, travDiags := hcl.AbsTraversalForExpr(attr.Expr)
if travDiags.HasErrors() {
traversal = nil // in case we got any partial results
// Fall back on trying to parse as a string
var travStr string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &travStr)
if !valDiags.HasErrors() {
var strDiags hcl.Diagnostics
traversal, strDiags = hclsyntax.ParseTraversalAbs([]byte(travStr), "", hcl.Pos{})
if strDiags.HasErrors() {
traversal = nil
}
}
}
// If we get out here with a nil traversal then we didn't
// succeed in processing the input.
if len(traversal) > 0 {
providerName := traversal.RootName()
alias := ""
if len(traversal) > 1 {
if getAttr, ok := traversal[1].(hcl.TraverseAttr); ok {
alias = getAttr.Name
}
}
r.Provider = ProviderRef{
Name: providerName,
Alias: alias,
}
} else {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid provider reference",
Detail: "Provider argument requires a provider name followed by an optional alias, like \"aws.foo\".",
Subject: attr.Expr.Range().Ptr(),
})
}
} else {
// If provider _isn't_ set then we'll infer it from the
// resource type.
r.Provider = ProviderRef{
Name: resourceTypeDefaultProviderName(r.Type),
}
}
case "module":
content, _, contentDiags := block.Body.PartialContent(moduleCallSchema)
diags = append(diags, contentDiags...)
name := block.Labels[0]
mc := &ModuleCall{
Name: block.Labels[0],
Pos: sourcePosHCL(block.DefRange),
}
mod.ModuleCalls[name] = mc
if attr, defined := content.Attributes["source"]; defined {
var source string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &source)
diags = append(diags, valDiags...)
mc.Source = source
}
if attr, defined := content.Attributes["version"]; defined {
var version string
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
diags = append(diags, valDiags...)
mc.Version = version
}
default:
// Should never happen because our cases above should be
// exhaustive for our schema.
panic(fmt.Errorf("unhandled block type %q", block.Type))
}
}
}
return mod, diagnosticsHCL(diags)
}

View File

@ -1,322 +0,0 @@
package tfconfig
import (
"io/ioutil"
"strings"
legacyhcl "github.com/hashicorp/hcl"
legacyast "github.com/hashicorp/hcl/hcl/ast"
)
func loadModuleLegacyHCL(dir string) (*Module, Diagnostics) {
// This implementation is intentionally more quick-and-dirty than the
// main loader. In particular, it doesn't bother to keep careful track
// of multiple error messages because we always fall back on returning
// the main parser's error message if our fallback parsing produces
// an error, and thus the errors here are not seen by the end-caller.
mod := newModule(dir)
primaryPaths, diags := dirFiles(dir)
if diags.HasErrors() {
return mod, diagnosticsHCL(diags)
}
for _, filename := range primaryPaths {
src, err := ioutil.ReadFile(filename)
if err != nil {
return mod, diagnosticsErrorf("Error reading %s: %s", filename, err)
}
hclRoot, err := legacyhcl.Parse(string(src))
if err != nil {
return mod, diagnosticsErrorf("Error parsing %s: %s", filename, err)
}
list, ok := hclRoot.Node.(*legacyast.ObjectList)
if !ok {
return mod, diagnosticsErrorf("Error parsing %s: no root object", filename)
}
for _, item := range list.Filter("terraform").Items {
if len(item.Keys) > 0 {
item = &legacyast.ObjectItem{
Val: &legacyast.ObjectType{
List: &legacyast.ObjectList{
Items: []*legacyast.ObjectItem{item},
},
},
}
}
type TerraformBlock struct {
RequiredVersion string `hcl:"required_version"`
}
var block TerraformBlock
err = legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("terraform block: %s", err)
}
if block.RequiredVersion != "" {
mod.RequiredCore = append(mod.RequiredCore, block.RequiredVersion)
}
}
if vars := list.Filter("variable"); len(vars.Items) > 0 {
vars = vars.Children()
type VariableBlock struct {
Type string `hcl:"type"`
Default interface{}
Description string
Fields []string `hcl:",decodedFields"`
}
for _, item := range vars.Items {
unwrapLegacyHCLObjectKeysFromJSON(item, 1)
if len(item.Keys) != 1 {
return nil, diagnosticsErrorf("variable block at %s has no label", item.Pos())
}
name := item.Keys[0].Token.Value().(string)
var block VariableBlock
err := legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("invalid variable block at %s: %s", item.Pos(), err)
}
// Clean up legacy HCL decoding ambiguity by unwrapping list of maps
if ms, ok := block.Default.([]map[string]interface{}); ok {
def := make(map[string]interface{})
for _, m := range ms {
for k, v := range m {
def[k] = v
}
}
block.Default = def
}
v := &Variable{
Name: name,
Type: block.Type,
Description: block.Description,
Default: block.Default,
Pos: sourcePosLegacyHCL(item.Pos(), filename),
}
if _, exists := mod.Variables[name]; exists {
return nil, diagnosticsErrorf("duplicate variable block for %q", name)
}
mod.Variables[name] = v
}
}
if outputs := list.Filter("output"); len(outputs.Items) > 0 {
outputs = outputs.Children()
type OutputBlock struct {
Description string
}
for _, item := range outputs.Items {
unwrapLegacyHCLObjectKeysFromJSON(item, 1)
if len(item.Keys) != 1 {
return nil, diagnosticsErrorf("output block at %s has no label", item.Pos())
}
name := item.Keys[0].Token.Value().(string)
var block OutputBlock
err := legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("invalid output block at %s: %s", item.Pos(), err)
}
o := &Output{
Name: name,
Description: block.Description,
Pos: sourcePosLegacyHCL(item.Pos(), filename),
}
if _, exists := mod.Outputs[name]; exists {
return nil, diagnosticsErrorf("duplicate output block for %q", name)
}
mod.Outputs[name] = o
}
}
for _, blockType := range []string{"resource", "data"} {
if resources := list.Filter(blockType); len(resources.Items) > 0 {
resources = resources.Children()
type ResourceBlock struct {
Provider string
}
for _, item := range resources.Items {
unwrapLegacyHCLObjectKeysFromJSON(item, 2)
if len(item.Keys) != 2 {
return nil, diagnosticsErrorf("resource block at %s has wrong label count", item.Pos())
}
typeName := item.Keys[0].Token.Value().(string)
name := item.Keys[1].Token.Value().(string)
var mode ResourceMode
var rMap map[string]*Resource
switch blockType {
case "resource":
mode = ManagedResourceMode
rMap = mod.ManagedResources
case "data":
mode = DataResourceMode
rMap = mod.DataResources
}
var block ResourceBlock
err := legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("invalid resource block at %s: %s", item.Pos(), err)
}
var providerName, providerAlias string
if dotPos := strings.IndexByte(block.Provider, '.'); dotPos != -1 {
providerName = block.Provider[:dotPos]
providerAlias = block.Provider[dotPos+1:]
} else {
providerName = block.Provider
}
if providerName == "" {
providerName = resourceTypeDefaultProviderName(typeName)
}
r := &Resource{
Mode: mode,
Type: typeName,
Name: name,
Provider: ProviderRef{
Name: providerName,
Alias: providerAlias,
},
Pos: sourcePosLegacyHCL(item.Pos(), filename),
}
key := r.MapKey()
if _, exists := rMap[key]; exists {
return nil, diagnosticsErrorf("duplicate resource block for %q", key)
}
rMap[key] = r
}
}
}
if moduleCalls := list.Filter("module"); len(moduleCalls.Items) > 0 {
moduleCalls = moduleCalls.Children()
type ModuleBlock struct {
Source string
Version string
}
for _, item := range moduleCalls.Items {
unwrapLegacyHCLObjectKeysFromJSON(item, 1)
if len(item.Keys) != 1 {
return nil, diagnosticsErrorf("module block at %s has no label", item.Pos())
}
name := item.Keys[0].Token.Value().(string)
var block ModuleBlock
err := legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("module block at %s: %s", item.Pos(), err)
}
mc := &ModuleCall{
Name: name,
Source: block.Source,
Version: block.Version,
Pos: sourcePosLegacyHCL(item.Pos(), filename),
}
if _, exists := mod.ModuleCalls[name]; exists {
return nil, diagnosticsErrorf("duplicate module block for %q", name)
}
mod.ModuleCalls[name] = mc
}
}
if providerConfigs := list.Filter("provider"); len(providerConfigs.Items) > 0 {
providerConfigs = providerConfigs.Children()
type ProviderBlock struct {
Version string
}
for _, item := range providerConfigs.Items {
unwrapLegacyHCLObjectKeysFromJSON(item, 1)
if len(item.Keys) != 1 {
return nil, diagnosticsErrorf("provider block at %s has no label", item.Pos())
}
name := item.Keys[0].Token.Value().(string)
var block ProviderBlock
err := legacyhcl.DecodeObject(&block, item.Val)
if err != nil {
return nil, diagnosticsErrorf("invalid provider block at %s: %s", item.Pos(), err)
}
if block.Version != "" {
mod.RequiredProviders[name] = append(mod.RequiredProviders[name], block.Version)
}
// Even if there wasn't an explicit version required, we still
// need an entry in our map to signal the unversioned dependency.
if _, exists := mod.RequiredProviders[name]; !exists {
mod.RequiredProviders[name] = []string{}
}
}
}
}
return mod, nil
}
// unwrapLegacyHCLObjectKeysFromJSON cleans up an edge case that can occur when
// parsing JSON as input: if we're parsing JSON then directly nested
// items will show up as additional "keys".
//
// For objects that expect a fixed number of keys, this breaks the
// decoding process. This function unwraps the object into what it would've
// looked like if it came directly from HCL by specifying the number of keys
// you expect.
//
// Example:
//
// { "foo": { "baz": {} } }
//
// Will show up with Keys being: []string{"foo", "baz"}
// when we really just want the first two. This function will fix this.
func unwrapLegacyHCLObjectKeysFromJSON(item *legacyast.ObjectItem, depth int) {
if len(item.Keys) > depth && item.Keys[0].Token.JSON {
for len(item.Keys) > depth {
// Pop off the last key
n := len(item.Keys)
key := item.Keys[n-1]
item.Keys[n-1] = nil
item.Keys = item.Keys[:n-1]
// Wrap our value in a list
item.Val = &legacyast.ObjectType{
List: &legacyast.ObjectList{
Items: []*legacyast.ObjectItem{
&legacyast.ObjectItem{
Keys: []*legacyast.ObjectKey{key},
Val: item.Val,
},
},
},
}
}
}
}

View File

@ -1,35 +0,0 @@
package tfconfig
// Module is the top-level type representing a parsed and processed Terraform
// module.
type Module struct {
// Path is the local filesystem directory where the module was loaded from.
Path string `json:"path"`
Variables map[string]*Variable `json:"variables"`
Outputs map[string]*Output `json:"outputs"`
RequiredCore []string `json:"required_core,omitempty"`
RequiredProviders map[string][]string `json:"required_providers"`
ManagedResources map[string]*Resource `json:"managed_resources"`
DataResources map[string]*Resource `json:"data_resources"`
ModuleCalls map[string]*ModuleCall `json:"module_calls"`
// Diagnostics records any errors and warnings that were detected during
// loading, primarily for inclusion in serialized forms of the module
// since this slice is also returned as a second argument from LoadModule.
Diagnostics Diagnostics `json:"diagnostics,omitempty"`
}
func newModule(path string) *Module {
return &Module{
Path: path,
Variables: make(map[string]*Variable),
Outputs: make(map[string]*Output),
RequiredProviders: make(map[string][]string),
ManagedResources: make(map[string]*Resource),
DataResources: make(map[string]*Resource),
ModuleCalls: make(map[string]*ModuleCall),
}
}

View File

@ -1,11 +0,0 @@
package tfconfig
// ModuleCall represents a "module" block within a module. That is, a
// declaration of a child module from inside its parent.
type ModuleCall struct {
Name string `json:"name"`
Source string `json:"source"`
Version string `json:"version,omitempty"`
Pos SourcePos `json:"pos"`
}

View File

@ -1,9 +0,0 @@
package tfconfig
// Output represents a single output from a Terraform module.
type Output struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Pos SourcePos `json:"pos"`
}

Some files were not shown because too many files have changed in this diff Show More