From 3e711e63dc1d3b623977b7b593605fc6c60891fc Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Sat, 20 Jan 2018 09:57:11 -0800 Subject: [PATCH] update dependencies --- Gopkg.lock | 307 ++++++++++-- vendor/github.com/aws/aws-sdk-go/CHANGELOG.md | 33 ++ .../aws/aws-sdk-go/aws/endpoints/defaults.go | 13 +- .../github.com/aws/aws-sdk-go/aws/version.go | 2 +- .../github.com/hashicorp/go-plugin/client.go | 36 +- .../hashicorp/go-plugin/client_test.go | 44 ++ .../hashicorp/go-plugin/grpc_broker.go | 455 ++++++++++++++++++ .../hashicorp/go-plugin/grpc_broker.pb.go | 190 ++++++++ .../hashicorp/go-plugin/grpc_broker.proto | 14 + .../hashicorp/go-plugin/grpc_client.go | 38 +- .../hashicorp/go-plugin/grpc_client_test.go | 25 + .../hashicorp/go-plugin/grpc_server.go | 9 +- .../github.com/hashicorp/go-plugin/plugin.go | 8 +- .../hashicorp/go-plugin/plugin_test.go | 88 +++- .../github.com/hashicorp/go-plugin/testing.go | 36 ++ .../hashicorp/hcl2/hcl/hclsyntax/parser.go | 46 +- .../hcl2/hcl/hclsyntax/parser_template.go | 4 +- .../hcl2/hcl/hclsyntax/parser_test.go | 250 ++++++++++ .../github.com/jmespath/go-jmespath/Makefile | 2 +- vendor/github.com/jmespath/go-jmespath/api.go | 37 ++ .../jmespath/go-jmespath/api_test.go | 32 ++ .../jmespath/go-jmespath/functions.go | 128 ++--- .../jmespath/go-jmespath/interpreter_test.go | 20 +- .../jmespath/go-jmespath/lexer_test.go | 98 ++-- .../github.com/jmespath/go-jmespath/parser.go | 4 +- .../jmespath/go-jmespath/util_test.go | 2 +- vendor/github.com/mitchellh/cli/cli.go | 2 +- vendor/github.com/oklog/run/.gitignore | 14 + vendor/github.com/oklog/run/.travis.yml | 12 + vendor/github.com/oklog/run/LICENSE | 201 ++++++++ vendor/github.com/oklog/run/README.md | 73 +++ vendor/github.com/oklog/run/example_test.go | 95 ++++ vendor/github.com/oklog/run/group.go | 62 +++ vendor/github.com/oklog/run/group_test.go | 57 +++ vendor/golang.org/x/sys/unix/mkpost.go | 2 +- .../x/sys/unix/ztypes_linux_s390x.go | 6 +- vendor/google.golang.org/grpc/rpc_util.go | 2 +- .../grpc/transport/http2_client.go | 13 +- 38 files changed, 2256 insertions(+), 204 deletions(-) create mode 100644 vendor/github.com/hashicorp/go-plugin/grpc_broker.go create mode 100644 vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go create mode 100644 vendor/github.com/hashicorp/go-plugin/grpc_broker.proto create mode 100644 vendor/github.com/jmespath/go-jmespath/api_test.go create mode 100644 vendor/github.com/oklog/run/.gitignore create mode 100644 vendor/github.com/oklog/run/.travis.yml create mode 100644 vendor/github.com/oklog/run/LICENSE create mode 100644 vendor/github.com/oklog/run/README.md create mode 100644 vendor/github.com/oklog/run/example_test.go create mode 100644 vendor/github.com/oklog/run/group.go create mode 100644 vendor/github.com/oklog/run/group_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 770c503..317bcb1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,4 +1,5 @@ -memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + [[projects]] branch = "master" @@ -8,7 +9,10 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/Xe/ln" - packages = [".","ex"] + packages = [ + ".", + "ex" + ] revision = "466e05b2ef3e48ce08a367b6aaac09ee29a124e5" version = "v0.1" @@ -33,7 +37,10 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/aead/chacha20" - packages = [".","chacha"] + packages = [ + ".", + "chacha" + ] revision = "8d6ce0550041f9d97e7f15ec27ed489f8bbbb0fb" [[projects]] @@ -45,7 +52,10 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/alecthomas/template" - packages = [".","parse"] + packages = [ + ".", + "parse" + ] revision = "a0175ee3bccc567396460bf5acd36800cb10c49c" [[projects]] @@ -74,15 +84,48 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/asdine/storm" - packages = [".","codec","codec/json","index","internal","q"] + packages = [ + ".", + "codec", + "codec/json", + "index", + "internal", + "q" + ] revision = "68fc73b635f890fe7ba2f3b15ce80c85b28a744f" version = "v2.0.2" [[projects]] name = "github.com/aws/aws-sdk-go" - packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3","service/sts"] - revision = "fe3adbda9bc845e750e3e5767c0a14dff202b2cc" - version = "v1.12.62" + packages = [ + "aws", + "aws/awserr", + "aws/awsutil", + "aws/client", + "aws/client/metadata", + "aws/corehandlers", + "aws/credentials", + "aws/credentials/ec2rolecreds", + "aws/credentials/endpointcreds", + "aws/credentials/stscreds", + "aws/defaults", + "aws/ec2metadata", + "aws/endpoints", + "aws/request", + "aws/session", + "aws/signer/v4", + "internal/shareddefaults", + "private/protocol", + "private/protocol/query", + "private/protocol/query/queryutil", + "private/protocol/rest", + "private/protocol/restxml", + "private/protocol/xml/xmlutil", + "service/s3", + "service/sts" + ] + revision = "9ed0c8de252f04ac45a65358377103d5a1aa2d92" + version = "v1.12.66" [[projects]] branch = "master" @@ -99,7 +142,10 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/bifurcation/mint" - packages = [".","syntax"] + packages = [ + ".", + "syntax" + ] revision = "350f685c15fb6b89af795dafe64fad68950948e0" [[projects]] @@ -159,12 +205,22 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/golang/protobuf" - packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"] + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845" [[projects]] name = "github.com/google/gops" - packages = ["agent","internal","signal"] + packages = [ + "agent", + "internal", + "signal" + ] revision = "57e77c5c37da1f4e1af49f9d1fe760f146c1579e" version = "v0.3.2" @@ -183,7 +239,10 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/hashicorp/go-getter" - packages = [".","helper/url"] + packages = [ + ".", + "helper/url" + ] revision = "961f56d2e93379b7d9c578e998d09257509a6f97" [[projects]] @@ -202,7 +261,7 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" branch = "master" name = "github.com/hashicorp/go-plugin" packages = ["."] - revision = "e37881a3f1a07fce82b3d99ce0342a72e53386bc" + revision = "1fc09c47b843b73705f51ffb0520e3ac1bfecf99" [[projects]] branch = "master" @@ -219,30 +278,77 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/hashicorp/golang-lru" - packages = [".","simplelru"] + packages = [ + ".", + "simplelru" + ] revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" [[projects]] branch = "master" name = "github.com/hashicorp/hcl" - packages = [".","hcl/ast","hcl/parser","hcl/scanner","hcl/strconv","hcl/token","json/parser","json/scanner","json/token"] + packages = [ + ".", + "hcl/ast", + "hcl/parser", + "hcl/scanner", + "hcl/strconv", + "hcl/token", + "json/parser", + "json/scanner", + "json/token" + ] revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" [[projects]] branch = "master" name = "github.com/hashicorp/hcl2" - packages = ["gohcl","hcl","hcl/hclsyntax","hcl/json","hcldec","hclparse"] - revision = "883a81b4902ecdc60cd9d77eae4c228792827c13" + packages = [ + "gohcl", + "hcl", + "hcl/hclsyntax", + "hcl/json", + "hcldec", + "hclparse" + ] + revision = "83451bb547db5e521b21cdf02fc0018c5790f6d5" [[projects]] branch = "master" name = "github.com/hashicorp/hil" - packages = [".","ast","parser","scanner"] + packages = [ + ".", + "ast", + "parser", + "scanner" + ] revision = "fa9f258a92500514cc8e9c67020487709df92432" [[projects]] name = "github.com/hashicorp/terraform" - packages = ["config","config/configschema","config/hcl2shim","config/module","dag","flatmap","helper/hashcode","helper/hilmapstructure","helper/schema","moduledeps","plugin","plugin/discovery","registry","registry/regsrc","registry/response","svchost","svchost/auth","svchost/disco","terraform","tfdiags","version"] + packages = [ + "config", + "config/configschema", + "config/hcl2shim", + "config/module", + "dag", + "flatmap", + "helper/hashcode", + "helper/hilmapstructure", + "helper/schema", + "moduledeps", + "plugin", + "plugin/discovery", + "registry", + "registry/regsrc", + "registry/response", + "svchost", + "svchost/auth", + "svchost/disco", + "terraform", + "tfdiags", + "version" + ] revision = "a6008b8a48a749c7c167453b9cf55ffd572b9a5d" version = "v0.11.2" @@ -255,12 +361,14 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/jmespath/go-jmespath" packages = ["."] - revision = "3433f3ea46d9f8019119e7dd41274e112a2359a9" - version = "0.2.2" + revision = "0b12d6b5" [[projects]] name = "github.com/joho/godotenv" - packages = [".","autoload"] + packages = [ + ".", + "autoload" + ] revision = "a79fa1e548e2c689c241d10173efd51e5d689d5b" version = "v1.2.0" @@ -314,7 +422,19 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/lucas-clemente/quic-go" - packages = [".","ackhandler","congestion","h2quic","internal/crypto","internal/flowcontrol","internal/handshake","internal/protocol","internal/utils","internal/wire","qerr"] + packages = [ + ".", + "ackhandler", + "congestion", + "h2quic", + "internal/crypto", + "internal/flowcontrol", + "internal/handshake", + "internal/protocol", + "internal/utils", + "internal/wire", + "qerr" + ] revision = "ded0eb4f6f30a8049bd334a26ff7ff728648fe13" version = "v0.6.0" @@ -326,7 +446,15 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/magefile/mage" - packages = ["build","mage","mg","parse","parse/srcimporter","sh","types"] + packages = [ + "build", + "mage", + "mg", + "parse", + "parse/srcimporter", + "sh", + "types" + ] revision = "ab3ca2f6f85577d7ec82e0a6df721147a2e737f9" version = "v2.0.1" @@ -346,7 +474,7 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" branch = "master" name = "github.com/mitchellh/cli" packages = ["."] - revision = "33edc47170b5df54d2588696d590c5e20ee583fe" + revision = "518dc677a1e1222682f4e7db06721942cb8e9e4c" [[projects]] branch = "master" @@ -396,6 +524,12 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" packages = ["ulid"] revision = "b270c2c35fc775243f87c58cf3f6969c5d9369d6" +[[projects]] + name = "github.com/oklog/run" + packages = ["."] + revision = "4dadeb3030eda0273a12382bb2348ffc7c9d1a39" + version = "v1.0.0" + [[projects]] name = "github.com/oklog/ulid" packages = ["."] @@ -416,7 +550,12 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/posener/complete" - packages = [".","cmd","cmd/install","match"] + packages = [ + ".", + "cmd", + "cmd/install", + "match" + ] revision = "dc2bc5a81accba8782bebea28628224643a8286a" version = "v1.1" @@ -452,7 +591,12 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "github.com/ulikunitz/xz" - packages = [".","internal/hash","internal/xlog","lzma"] + packages = [ + ".", + "internal/hash", + "internal/xlog", + "lzma" + ] revision = "0c6b41e72360850ca4f98dc341fd999726ea007f" version = "v0.5.4" @@ -471,7 +615,15 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "github.com/zclconf/go-cty" - packages = ["cty","cty/convert","cty/function","cty/function/stdlib","cty/gocty","cty/json","cty/set"] + packages = [ + "cty", + "cty/convert", + "cty/function", + "cty/function/stdlib", + "cty/gocty", + "cty/json", + "cty/set" + ] revision = "709e4033eeb037dc543dbc2048065dfb814ce316" [[projects]] @@ -483,25 +635,76 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] branch = "master" name = "golang.org/x/crypto" - packages = ["acme","acme/autocert","bcrypt","blowfish","cast5","curve25519","hkdf","nacl/secretbox","openpgp","openpgp/armor","openpgp/elgamal","openpgp/errors","openpgp/packet","openpgp/s2k","pbkdf2","poly1305","salsa20","salsa20/salsa","tea","twofish","xtea"] - revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac" + packages = [ + "acme", + "acme/autocert", + "bcrypt", + "blowfish", + "cast5", + "curve25519", + "hkdf", + "nacl/secretbox", + "openpgp", + "openpgp/armor", + "openpgp/elgamal", + "openpgp/errors", + "openpgp/packet", + "openpgp/s2k", + "pbkdf2", + "poly1305", + "salsa20", + "salsa20/salsa", + "tea", + "twofish", + "xtea" + ] + revision = "a6600008915114d9c087fad9f03d75087b1a74df" [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["bpf","context","html","html/atom","http2","http2/hpack","idna","internal/iana","internal/socket","internal/timeseries","ipv4","lex/httplex","trace"] + packages = [ + "bpf", + "context", + "html", + "html/atom", + "http2", + "http2/hpack", + "idna", + "internal/iana", + "internal/socket", + "internal/timeseries", + "ipv4", + "lex/httplex", + "trace" + ] revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "fff93fa7cd278d84afc205751523809c464168ab" + revision = "2c42eef0765b9837fbdab12011af7830f55f88f0" [[projects]] branch = "master" name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] @@ -512,12 +715,44 @@ memo = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" [[projects]] name = "google.golang.org/grpc" - packages = [".","balancer","balancer/base","balancer/roundrobin","codes","connectivity","credentials","encoding","grpclb/grpc_lb_v1/messages","grpclog","health","health/grpc_health_v1","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"] - revision = "7cea4cc846bcf00cbb27595b07da5de875ef7de9" - version = "v1.9.1" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "health", + "health/grpc_health_v1", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport" + ] + revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef" + version = "v1.9.2" [[projects]] name = "gopkg.in/alecthomas/kingpin.v2" packages = ["."] revision = "947dcec5ba9c011838740e680966fd7087a71d0d" version = "v2.2.6" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a11e1692755a705514dbd401ba4795821d1ac221d6f9100124c38a29db98c568" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md index a141f57..986c5e5 100644 --- a/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md @@ -1,3 +1,36 @@ +Release v1.12.66 (2018-01-19) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/glue`: Updates service API and documentation + * New AWS Glue DataCatalog APIs to manage table versions and a new feature to skip archiving of the old table version when updating table. +* `service/transcribe`: Adds new service + +Release v1.12.65 (2018-01-18) +=== + +### Service Client Updates +* `service/sagemaker`: Updates service API and documentation + * CreateTrainingJob and CreateEndpointConfig now supports KMS Key for volume encryption. + +Release v1.12.64 (2018-01-17) +=== + +### Service Client Updates +* `service/autoscaling-plans`: Updates service documentation +* `service/ec2`: Updates service documentation + * Documentation updates for EC2 + +Release v1.12.63 (2018-01-17) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service API and documentation +* `service/autoscaling-plans`: Adds new service +* `service/rds`: Updates service API and documentation + * With this release you can now integrate RDS DB instances with CloudWatch Logs. We have added parameters to the operations for creating and modifying DB instances (for example CreateDBInstance) to allow you to take advantage of this capability through the CLI and API. Once you enable this feature, a stream of log events will publish to CloudWatch Logs for each log type you enable. + Release v1.12.62 (2018-01-15) === diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go index 709f648..5470a8c 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go @@ -1044,10 +1044,13 @@ var awsPartition = partition{ Endpoints: endpoints{ "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, "eu-central-1": endpoint{}, "eu-west-1": endpoint{}, "us-east-1": endpoint{}, "us-east-2": endpoint{}, + "us-west-1": endpoint{}, "us-west-2": endpoint{}, }, }, @@ -1094,10 +1097,11 @@ var awsPartition = partition{ "glue": service{ Endpoints: endpoints{ - "eu-west-1": endpoint{}, - "us-east-1": endpoint{}, - "us-east-2": endpoint{}, - "us-west-2": endpoint{}, + "ap-northeast-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, }, }, "greengrass": service{ @@ -1490,6 +1494,7 @@ var awsPartition = partition{ Endpoints: endpoints{ "eu-west-1": endpoint{}, "us-east-1": endpoint{}, + "us-east-2": endpoint{}, "us-west-2": endpoint{}, }, }, diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index 6b7bd46..7bd32f3 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.12.62" +const SDKVersion = "1.12.66" diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go index c3cbc45..b3e3b78 100644 --- a/vendor/github.com/hashicorp/go-plugin/client.go +++ b/vendor/github.com/hashicorp/go-plugin/client.go @@ -2,6 +2,7 @@ package plugin import ( "bufio" + "context" "crypto/subtle" "crypto/tls" "errors" @@ -79,6 +80,7 @@ type Client struct { client ClientProtocol protocol Protocol logger hclog.Logger + doneCtx context.Context } // ClientConfig is the configuration used to initialize a new @@ -310,7 +312,7 @@ func (c *Client) Client() (ClientProtocol, error) { c.client, err = newRPCClient(c) case ProtocolGRPC: - c.client, err = newGRPCClient(c) + c.client, err = newGRPCClient(c.doneCtx, c) default: return nil, fmt.Errorf("unknown server protocol: %s", c.protocol) @@ -423,6 +425,9 @@ func (c *Client) Start() (addr net.Addr, err error) { // Create the logging channel for when we kill c.doneLogging = make(chan struct{}) + // Create a context for when we kill + var ctxCancel context.CancelFunc + c.doneCtx, ctxCancel = context.WithCancel(context.Background()) if c.config.Reattach != nil { // Verify the process still exists. If not, then it is an error @@ -457,6 +462,9 @@ func (c *Client) Start() (addr net.Addr, err error) { // Close the logging channel since that doesn't work on reattach close(c.doneLogging) + + // Cancel the context + ctxCancel() }(p.Pid) // Set the address and process @@ -535,6 +543,9 @@ func (c *Client) Start() (addr net.Addr, err error) { // Mark that we exited close(exitCh) + // Cancel the context, marking that we exited + ctxCancel() + // Set that we exited, which takes a lock c.l.Lock() defer c.l.Unlock() @@ -707,18 +718,29 @@ func (c *Client) Protocol() Protocol { return c.protocol } +func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) { + return func(_ string, _ time.Duration) (net.Conn, error) { + // Connect to the client + conn, err := net.Dial(addr.Network(), addr.String()) + if err != nil { + return nil, err + } + if tcpConn, ok := conn.(*net.TCPConn); ok { + // Make sure to set keep alive so that the connection doesn't die + tcpConn.SetKeepAlive(true) + } + + return conn, nil + } +} + // dialer is compatible with grpc.WithDialer and creates the connection // to the plugin. func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) { - // Connect to the client - conn, err := net.Dial(c.address.Network(), c.address.String()) + conn, err := netAddrDialer(c.address)("", timeout) if err != nil { return nil, err } - if tcpConn, ok := conn.(*net.TCPConn); ok { - // Make sure to set keep alive so that the connection doesn't die - tcpConn.SetKeepAlive(true) - } // If we have a TLS config we wrap our connection. We only do this // for net/rpc since gRPC uses its own mechanism for TLS. diff --git a/vendor/github.com/hashicorp/go-plugin/client_test.go b/vendor/github.com/hashicorp/go-plugin/client_test.go index c767a25..1747868 100644 --- a/vendor/github.com/hashicorp/go-plugin/client_test.go +++ b/vendor/github.com/hashicorp/go-plugin/client_test.go @@ -172,6 +172,50 @@ func TestClient_testInterface(t *testing.T) { } } +func TestClient_grpc_servercrash(t *testing.T) { + process := helperProcess("test-grpc") + c := NewClient(&ClientConfig{ + Cmd: process, + HandshakeConfig: testHandshake, + Plugins: testPluginMap, + AllowedProtocols: []Protocol{ProtocolGRPC}, + }) + defer c.Kill() + + if _, err := c.Start(); err != nil { + t.Fatalf("err: %s", err) + } + + if v := c.Protocol(); v != ProtocolGRPC { + t.Fatalf("bad: %s", v) + } + + // Grab the RPC client + client, err := c.Client() + if err != nil { + t.Fatalf("err should be nil, got %s", err) + } + + // Grab the impl + raw, err := client.Dispense("test") + if err != nil { + t.Fatalf("err should be nil, got %s", err) + } + + _, ok := raw.(testInterface) + if !ok { + t.Fatalf("bad: %#v", raw) + } + + c.process.Kill() + + select { + case <-c.doneCtx.Done(): + case <-time.After(time.Second * 2): + t.Fatal("Context was not closed") + } +} + func TestClient_grpc(t *testing.T) { process := helperProcess("test-grpc") c := NewClient(&ClientConfig{ diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go new file mode 100644 index 0000000..49fd21c --- /dev/null +++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go @@ -0,0 +1,455 @@ +package plugin + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + "log" + "net" + "sync" + "sync/atomic" + "time" + + "github.com/oklog/run" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +// streamer interface is used in the broker to send/receive connection +// information. +type streamer interface { + Send(*ConnInfo) error + Recv() (*ConnInfo, error) + Close() +} + +// sendErr is used to pass errors back during a send. +type sendErr struct { + i *ConnInfo + ch chan error +} + +// gRPCBrokerServer is used by the plugin to start a stream and to send +// connection information to/from the plugin. Implements GRPCBrokerServer and +// streamer interfaces. +type gRPCBrokerServer struct { + // 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 *ConnInfo + + // quit closes down the stream. + quit chan struct{} + + // o is used to ensure we close the quit channel only once. + o sync.Once +} + +func newGRPCBrokerServer() *gRPCBrokerServer { + return &gRPCBrokerServer{ + send: make(chan *sendErr), + recv: make(chan *ConnInfo), + quit: make(chan struct{}), + } +} + +// 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 GRPCBroker_StartStreamServer) error { + doneCh := stream.Context().Done() + defer s.Close() + + // Proccess send stream + go func() { + for { + select { + case <-doneCh: + return + case <-s.quit: + return + case se := <-s.send: + err := stream.Send(se.i) + se.ch <- err + } + } + }() + + // Process receive stream + for { + i, err := stream.Recv() + if err != nil { + return err + } + select { + case <-doneCh: + return nil + case <-s.quit: + return nil + case s.recv <- i: + } + } + + return nil +} + +// Send is used by the GRPCBroker to pass connection information into the stream +// to the client. +func (s *gRPCBrokerServer) Send(i *ConnInfo) error { + ch := make(chan error) + defer close(ch) + + select { + case <-s.quit: + return errors.New("broker closed") + case s.send <- &sendErr{ + i: i, + ch: ch, + }: + } + + return <-ch +} + +// 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() (*ConnInfo, error) { + select { + case <-s.quit: + return nil, errors.New("broker closed") + case i := <-s.recv: + return i, nil + } +} + +// Close closes the quit channel, shutting down the stream. +func (s *gRPCBrokerServer) Close() { + s.o.Do(func() { + close(s.quit) + }) +} + +// gRPCBrokerClientImpl is used by the client to start a stream and to send +// connection information to/from the client. Implements GRPCBrokerClient and +// streamer interfaces. +type gRPCBrokerClientImpl struct { + // client is the underlying GRPC client used to make calls to the server. + client 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 *ConnInfo + + // quit closes down the stream. + quit chan struct{} + + // o is used to ensure we close the quit channel only once. + o sync.Once +} + +func newGRPCBrokerClient(conn *grpc.ClientConn) *gRPCBrokerClientImpl { + return &gRPCBrokerClientImpl{ + client: NewGRPCBrokerClient(conn), + send: make(chan *sendErr), + recv: make(chan *ConnInfo), + quit: make(chan struct{}), + } +} + +// StartStream implements the GRPCBrokerClient interface and will block until +// the quit channel is closed or the context reports Done. The stream will pass +// connection information to/from the plugin. +func (s *gRPCBrokerClientImpl) StartStream() error { + ctx, cancelFunc := context.WithCancel(context.Background()) + defer cancelFunc() + defer s.Close() + + stream, err := s.client.StartStream(ctx) + if err != nil { + return err + } + doneCh := stream.Context().Done() + + go func() { + for { + select { + case <-doneCh: + return + case <-s.quit: + return + case se := <-s.send: + err := stream.Send(se.i) + se.ch <- err + } + } + }() + + for { + i, err := stream.Recv() + if err != nil { + return err + } + select { + case <-doneCh: + return nil + case <-s.quit: + return nil + case s.recv <- i: + } + } + + return nil +} + +// Send is used by the GRPCBroker to pass connection information into the stream +// to the plugin. +func (s *gRPCBrokerClientImpl) Send(i *ConnInfo) error { + ch := make(chan error) + defer close(ch) + + select { + case <-s.quit: + return errors.New("broker closed") + case s.send <- &sendErr{ + i: i, + ch: ch, + }: + } + + return <-ch +} + +// Recv is used by the GRPCBroker to pass connection information that has been +// sent from the plugin to the broker. +func (s *gRPCBrokerClientImpl) Recv() (*ConnInfo, error) { + select { + case <-s.quit: + return nil, errors.New("broker closed") + case i := <-s.recv: + return i, nil + } +} + +// Close closes the quit channel, shutting down the stream. +func (s *gRPCBrokerClientImpl) Close() { + s.o.Do(func() { + close(s.quit) + }) +} + +// GRPCBroker is responsible for brokering connections by unique ID. +// +// It is used by plugins to create multiple gRPC connections and data +// streams between the plugin process and the host process. +// +// This allows a plugin to request a channel with a specific ID to connect to +// or accept a connection from, and the broker handles the details of +// holding these channels open while they're being negotiated. +// +// The Plugin interface has access to these for both Server and Client. +// The broker can be used by either (optionally) to reserve and connect to +// new streams. This is useful for complex args and return values, +// or anything else you might need a data stream for. +type GRPCBroker struct { + nextId uint32 + streamer streamer + streams map[uint32]*gRPCBrokerPending + tls *tls.Config + doneCh chan struct{} + o sync.Once + + sync.Mutex +} + +type gRPCBrokerPending struct { + ch chan *ConnInfo + doneCh chan struct{} +} + +func newGRPCBroker(s streamer, tls *tls.Config) *GRPCBroker { + return &GRPCBroker{ + streamer: s, + streams: make(map[uint32]*gRPCBrokerPending), + tls: tls, + doneCh: make(chan struct{}), + } +} + +// Accept accepts a connection by ID. +// +// This should not be called multiple times with the same ID at one time. +func (b *GRPCBroker) Accept(id uint32) (net.Listener, error) { + listener, err := serverListener() + if err != nil { + return nil, err + } + + err = b.streamer.Send(&ConnInfo{ + ServiceId: id, + Network: listener.Addr().Network(), + Address: listener.Addr().String(), + }) + if err != nil { + return nil, err + } + + return listener, nil +} + +// AcceptAndServe is used to accept a specific stream ID and immediately +// serve a gRPC server on that stream ID. This is used to easily serve +// complex arguments. Each AcceptAndServe call opens a new listener socket and +// sends the connection info down the stream to the dialer. Since a new +// connection is opened every call, these calls should be used sparingly. +// Multiple gRPC server implementations can be registered to a single +// AcceptAndServe call. +func (b *GRPCBroker) AcceptAndServe(id uint32, s func([]grpc.ServerOption) *grpc.Server) { + listener, err := b.Accept(id) + if err != nil { + log.Printf("[ERR] plugin: plugin acceptAndServe error: %s", err) + return + } + defer listener.Close() + + var opts []grpc.ServerOption + if b.tls != nil { + opts = []grpc.ServerOption{grpc.Creds(credentials.NewTLS(b.tls))} + } + + server := s(opts) + + // Here we use a run group to close this goroutine if the server is shutdown + // or the broker is shutdown. + var g run.Group + { + // Serve on the listener, if shutting down call GracefulStop. + g.Add(func() error { + return server.Serve(listener) + }, func(err error) { + server.GracefulStop() + }) + } + { + // block on the closeCh or the doneCh. If we are shutting down close the + // closeCh. + closeCh := make(chan struct{}) + g.Add(func() error { + select { + case <-b.doneCh: + case <-closeCh: + } + return nil + }, func(err error) { + close(closeCh) + }) + } + + // Block until we are done + g.Run() +} + +// Close closes the stream and all servers. +func (b *GRPCBroker) Close() error { + b.streamer.Close() + b.o.Do(func() { + close(b.doneCh) + }) + return nil +} + +// Dial opens a connection by ID. +func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { + var c *ConnInfo + + // Open the stream + p := b.getStream(id) + select { + case c = <-p.ch: + close(p.doneCh) + case <-time.After(5 * time.Second): + return nil, fmt.Errorf("timeout waiting for connection info") + } + + var addr net.Addr + switch c.Network { + case "tcp": + addr, err = net.ResolveTCPAddr("tcp", c.Address) + case "unix": + addr, err = net.ResolveUnixAddr("unix", c.Address) + default: + err = fmt.Errorf("Unknown address type: %s", c.Address) + } + if err != nil { + return nil, err + } + + return dialGRPCConn(b.tls, netAddrDialer(addr)) +} + +// NextId returns a unique ID to use next. +// +// It is possible for very long-running plugin hosts to wrap this value, +// though it would require a very large amount of calls. In practice +// we've never seen it happen. +func (m *GRPCBroker) NextId() uint32 { + return atomic.AddUint32(&m.nextId, 1) +} + +// Run starts the brokering and should be executed in a goroutine, since it +// blocks forever, or until the session closes. +// +// Uses of GRPCBroker never need to call this. It is called internally by +// the plugin host/client. +func (m *GRPCBroker) Run() { + for { + stream, err := m.streamer.Recv() + if err != nil { + // Once we receive an error, just exit + break + } + + // Initialize the waiter + p := m.getStream(stream.ServiceId) + select { + case p.ch <- stream: + default: + } + + go m.timeoutWait(stream.ServiceId, p) + } +} + +func (m *GRPCBroker) getStream(id uint32) *gRPCBrokerPending { + m.Lock() + defer m.Unlock() + + p, ok := m.streams[id] + if ok { + return p + } + + m.streams[id] = &gRPCBrokerPending{ + ch: make(chan *ConnInfo, 1), + doneCh: make(chan struct{}), + } + return m.streams[id] +} + +func (m *GRPCBroker) timeoutWait(id uint32, p *gRPCBrokerPending) { + // Wait for the stream to either be picked up and connected, or + // for a timeout. + select { + case <-p.doneCh: + case <-time.After(5 * time.Second): + } + + m.Lock() + defer m.Unlock() + + // Delete the stream so no one else can grab it + delete(m.streams, id) +} diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go b/vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go new file mode 100644 index 0000000..d490daf --- /dev/null +++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go @@ -0,0 +1,190 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: grpc_broker.proto + +/* +Package plugin is a generated protocol buffer package. + +It is generated from these files: + grpc_broker.proto + +It has these top-level messages: + ConnInfo +*/ +package plugin + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type ConnInfo struct { + ServiceId uint32 `protobuf:"varint,1,opt,name=service_id,json=serviceId" json:"service_id,omitempty"` + Network string `protobuf:"bytes,2,opt,name=network" json:"network,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` +} + +func (m *ConnInfo) Reset() { *m = ConnInfo{} } +func (m *ConnInfo) String() string { return proto.CompactTextString(m) } +func (*ConnInfo) ProtoMessage() {} +func (*ConnInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *ConnInfo) GetServiceId() uint32 { + if m != nil { + return m.ServiceId + } + return 0 +} + +func (m *ConnInfo) GetNetwork() string { + if m != nil { + return m.Network + } + return "" +} + +func (m *ConnInfo) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func init() { + proto.RegisterType((*ConnInfo)(nil), "plugin.ConnInfo") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for GRPCBroker service + +type GRPCBrokerClient interface { + StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) +} + +type gRPCBrokerClient struct { + cc *grpc.ClientConn +} + +func NewGRPCBrokerClient(cc *grpc.ClientConn) GRPCBrokerClient { + return &gRPCBrokerClient{cc} +} + +func (c *gRPCBrokerClient) StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) { + stream, err := grpc.NewClientStream(ctx, &_GRPCBroker_serviceDesc.Streams[0], c.cc, "/plugin.GRPCBroker/StartStream", opts...) + if err != nil { + return nil, err + } + x := &gRPCBrokerStartStreamClient{stream} + return x, nil +} + +type GRPCBroker_StartStreamClient interface { + Send(*ConnInfo) error + Recv() (*ConnInfo, error) + grpc.ClientStream +} + +type gRPCBrokerStartStreamClient struct { + grpc.ClientStream +} + +func (x *gRPCBrokerStartStreamClient) Send(m *ConnInfo) error { + return x.ClientStream.SendMsg(m) +} + +func (x *gRPCBrokerStartStreamClient) Recv() (*ConnInfo, error) { + m := new(ConnInfo) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for GRPCBroker service + +type GRPCBrokerServer interface { + StartStream(GRPCBroker_StartStreamServer) error +} + +func RegisterGRPCBrokerServer(s *grpc.Server, srv GRPCBrokerServer) { + s.RegisterService(&_GRPCBroker_serviceDesc, srv) +} + +func _GRPCBroker_StartStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GRPCBrokerServer).StartStream(&gRPCBrokerStartStreamServer{stream}) +} + +type GRPCBroker_StartStreamServer interface { + Send(*ConnInfo) error + Recv() (*ConnInfo, error) + grpc.ServerStream +} + +type gRPCBrokerStartStreamServer struct { + grpc.ServerStream +} + +func (x *gRPCBrokerStartStreamServer) Send(m *ConnInfo) error { + return x.ServerStream.SendMsg(m) +} + +func (x *gRPCBrokerStartStreamServer) Recv() (*ConnInfo, error) { + m := new(ConnInfo) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _GRPCBroker_serviceDesc = grpc.ServiceDesc{ + ServiceName: "plugin.GRPCBroker", + HandlerType: (*GRPCBrokerServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "StartStream", + Handler: _GRPCBroker_StartStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc_broker.proto", +} + +func init() { proto.RegisterFile("grpc_broker.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 170 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, 0x93, 0xd8, 0xc0, 0x4e, 0x36, 0x06, 0x04, 0x00, 0x00, + 0xff, 0xff, 0x7b, 0x5d, 0xfb, 0xe1, 0xc7, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.proto b/vendor/github.com/hashicorp/go-plugin/grpc_broker.proto new file mode 100644 index 0000000..f578348 --- /dev/null +++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package plugin; + +message ConnInfo { + uint32 service_id = 1; + string network = 2; + string address = 3; +} + +service GRPCBroker { + rpc StartStream(stream ConnInfo) returns (stream ConnInfo); +} + + diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_client.go b/vendor/github.com/hashicorp/go-plugin/grpc_client.go index 3bcf95e..44294d0 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_client.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_client.go @@ -1,7 +1,10 @@ package plugin import ( + "crypto/tls" "fmt" + "net" + "time" "golang.org/x/net/context" "google.golang.org/grpc" @@ -9,14 +12,12 @@ import ( "google.golang.org/grpc/health/grpc_health_v1" ) -// newGRPCClient creates a new GRPCClient. The Client argument is expected -// to be successfully started already with a lock held. -func newGRPCClient(c *Client) (*GRPCClient, error) { +func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, error)) (*grpc.ClientConn, error) { // Build dialing options. opts := make([]grpc.DialOption, 0, 5) // We use a custom dialer so that we can connect over unix domain sockets - opts = append(opts, grpc.WithDialer(c.dialer)) + opts = append(opts, grpc.WithDialer(dialer)) // go-plugin expects to block the connection opts = append(opts, grpc.WithBlock()) @@ -26,11 +27,11 @@ func newGRPCClient(c *Client) (*GRPCClient, error) { // If we have no TLS configuration set, we need to explicitly tell grpc // that we're connecting with an insecure connection. - if c.config.TLSConfig == nil { + if tls == nil { opts = append(opts, grpc.WithInsecure()) } else { opts = append(opts, grpc.WithTransportCredentials( - credentials.NewTLS(c.config.TLSConfig))) + credentials.NewTLS(tls))) } // Connect. Note the first parameter is unused because we use a custom @@ -40,9 +41,28 @@ func newGRPCClient(c *Client) (*GRPCClient, error) { return nil, err } + return conn, nil +} + +// newGRPCClient creates a new GRPCClient. The Client argument is expected +// to be successfully started already with a lock held. +func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) { + conn, err := dialGRPCConn(c.config.TLSConfig, c.dialer) + if err != nil { + return nil, err + } + + // Start the broker. + brokerGRPCClient := newGRPCBrokerClient(conn) + broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig) + go broker.Run() + go brokerGRPCClient.StartStream() + return &GRPCClient{ Conn: conn, Plugins: c.config.Plugins, + doneCtx: doneCtx, + broker: broker, }, nil } @@ -50,10 +70,14 @@ func newGRPCClient(c *Client) (*GRPCClient, error) { type GRPCClient struct { Conn *grpc.ClientConn Plugins map[string]Plugin + + doneCtx context.Context + broker *GRPCBroker } // ClientProtocol impl. func (c *GRPCClient) Close() error { + c.broker.Close() return c.Conn.Close() } @@ -69,7 +93,7 @@ func (c *GRPCClient) Dispense(name string) (interface{}, error) { return nil, fmt.Errorf("plugin %q doesn't support gRPC", name) } - return p.GRPCClient(c.Conn) + return p.GRPCClient(c.doneCtx, c.broker, c.Conn) } // ClientProtocol impl. diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_client_test.go b/vendor/github.com/hashicorp/go-plugin/grpc_client_test.go index e3b526f..5566f8b 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_client_test.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_client_test.go @@ -1,7 +1,11 @@ package plugin import ( + "context" "testing" + + "github.com/hashicorp/go-plugin/test/grpc" + "google.golang.org/grpc" ) func TestGRPCClient_App(t *testing.T) { @@ -24,6 +28,27 @@ func TestGRPCClient_App(t *testing.T) { if result != 42 { t.Fatalf("bad: %#v", result) } + + err = impl.Bidirectional() + if err != nil { + t.Fatal(err) + } +} + +func TestGRPCConn_BidirectionalPing(t *testing.T) { + conn, _ := TestGRPCConn(t, func(s *grpc.Server) { + grpctest.RegisterPingPongServer(s, &pingPongServer{}) + }) + defer conn.Close() + pingPongClient := grpctest.NewPingPongClient(conn) + + pResp, err := pingPongClient.Ping(context.Background(), &grpctest.PingRequest{}) + if err != nil { + t.Fatal(err) + } + if pResp.Msg != "pong" { + t.Fatal("Bad PingPong") + } } func TestGRPCClient_Ping(t *testing.T) { diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_server.go b/vendor/github.com/hashicorp/go-plugin/grpc_server.go index 177a0cd..9ec751e 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_server.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_server.go @@ -51,6 +51,7 @@ type GRPCServer struct { config GRPCServerConfig server *grpc.Server + broker *GRPCBroker } // ServerProtocol impl. @@ -68,6 +69,12 @@ func (s *GRPCServer) Init() error { GRPCServiceName, grpc_health_v1.HealthCheckResponse_SERVING) grpc_health_v1.RegisterHealthServer(s.server, healthCheck) + // Register the broker service + brokerServer := newGRPCBrokerServer() + RegisterGRPCBrokerServer(s.server, brokerServer) + s.broker = newGRPCBroker(brokerServer, s.TLS) + go s.broker.Run() + // Register all our plugins onto the gRPC server. for k, raw := range s.Plugins { p, ok := raw.(GRPCPlugin) @@ -75,7 +82,7 @@ func (s *GRPCServer) Init() error { return fmt.Errorf("%q is not a GRPC-compatibile plugin", k) } - if err := p.GRPCServer(s.server); err != nil { + if err := p.GRPCServer(s.broker, s.server); err != nil { return fmt.Errorf("error registring %q: %s", k, err) } } diff --git a/vendor/github.com/hashicorp/go-plugin/plugin.go b/vendor/github.com/hashicorp/go-plugin/plugin.go index 6b7bdd1..79d9674 100644 --- a/vendor/github.com/hashicorp/go-plugin/plugin.go +++ b/vendor/github.com/hashicorp/go-plugin/plugin.go @@ -9,6 +9,7 @@ package plugin import ( + "context" "errors" "net/rpc" @@ -33,11 +34,12 @@ type GRPCPlugin interface { // GRPCServer should register this plugin for serving with the // given GRPCServer. Unlike Plugin.Server, this is only called once // since gRPC plugins serve singletons. - GRPCServer(*grpc.Server) error + GRPCServer(*GRPCBroker, *grpc.Server) error // GRPCClient should return the interface implementation for the plugin - // you're serving via gRPC. - GRPCClient(*grpc.ClientConn) (interface{}, error) + // you're serving via gRPC. The provided context will be canceled by + // go-plugin in the event of the plugin process exiting. + GRPCClient(context.Context, *GRPCBroker, *grpc.ClientConn) (interface{}, error) } // NetRPCUnsupportedPlugin implements Plugin but returns errors for the diff --git a/vendor/github.com/hashicorp/go-plugin/plugin_test.go b/vendor/github.com/hashicorp/go-plugin/plugin_test.go index e59d614..c1d6d4c 100644 --- a/vendor/github.com/hashicorp/go-plugin/plugin_test.go +++ b/vendor/github.com/hashicorp/go-plugin/plugin_test.go @@ -3,6 +3,7 @@ package plugin import ( "crypto/tls" "crypto/x509" + "errors" "fmt" "io/ioutil" "log" @@ -32,6 +33,7 @@ var testHandshake = HandshakeConfig{ type testInterface interface { Double(int) int PrintKV(string, interface{}) + Bidirectional() error } // testInterfacePlugin is the implementation of Plugin to create @@ -48,13 +50,13 @@ func (p *testInterfacePlugin) Client(b *MuxBroker, c *rpc.Client) (interface{}, return &testInterfaceClient{Client: c}, nil } -func (p *testInterfacePlugin) GRPCServer(s *grpc.Server) error { - grpctest.RegisterTestServer(s, &testGRPCServer{Impl: p.impl()}) +func (p *testInterfacePlugin) GRPCServer(b *GRPCBroker, s *grpc.Server) error { + grpctest.RegisterTestServer(s, &testGRPCServer{broker: b, Impl: p.impl()}) return nil } -func (p *testInterfacePlugin) GRPCClient(c *grpc.ClientConn) (interface{}, error) { - return &testGRPCClient{Client: grpctest.NewTestClient(c)}, nil +func (p *testInterfacePlugin) GRPCClient(doneCtx context.Context, b *GRPCBroker, c *grpc.ClientConn) (interface{}, error) { + return &testGRPCClient{broker: b, Client: grpctest.NewTestClient(c)}, nil } func (p *testInterfacePlugin) impl() testInterface { @@ -82,6 +84,10 @@ func (i *testInterfaceImpl) PrintKV(key string, value interface{}) { i.logger.Info("PrintKV called", key, value) } +func (i *testInterfaceImpl) Bidirectional() error { + return nil +} + // testInterfaceClient implements testInterface to communicate over RPC type testInterfaceClient struct { Client *rpc.Client @@ -107,6 +113,10 @@ func (impl *testInterfaceClient) PrintKV(key string, value interface{}) { } } +func (impl *testInterfaceClient) Bidirectional() error { + return nil +} + // testInterfaceServer is the RPC server for testInterfaceClient type testInterfaceServer struct { Broker *MuxBroker @@ -130,7 +140,8 @@ var testPluginMap = map[string]Plugin{ // testGRPCServer is the implementation of our GRPC service. type testGRPCServer struct { - Impl testInterface + Impl testInterface + broker *GRPCBroker } func (s *testGRPCServer) Double( @@ -160,10 +171,46 @@ func (s *testGRPCServer) PrintKV( return &grpctest.PrintKVResponse{}, nil } +func (s *testGRPCServer) Bidirectional(ctx context.Context, req *grpctest.BidirectionalRequest) (*grpctest.BidirectionalResponse, error) { + conn, err := s.broker.Dial(req.Id) + if err != nil { + return nil, err + } + + pingPongClient := grpctest.NewPingPongClient(conn) + resp, err := pingPongClient.Ping(ctx, &grpctest.PingRequest{}) + if err != nil { + return nil, err + } + if resp.Msg != "pong" { + return nil, errors.New("Bad PingPong") + } + + nextID := s.broker.NextId() + go s.broker.AcceptAndServe(nextID, func(opts []grpc.ServerOption) *grpc.Server { + s := grpc.NewServer(opts...) + grpctest.RegisterPingPongServer(s, &pingPongServer{}) + return s + }) + + return &grpctest.BidirectionalResponse{ + Id: nextID, + }, nil +} + +type pingPongServer struct{} + +func (p *pingPongServer) Ping(ctx context.Context, req *grpctest.PingRequest) (*grpctest.PongResponse, error) { + return &grpctest.PongResponse{ + Msg: "pong", + }, nil +} + // testGRPCClient is an implementation of TestInterface that communicates // over gRPC. type testGRPCClient struct { Client grpctest.TestClient + broker *GRPCBroker } func (c *testGRPCClient) Double(v int) int { @@ -200,6 +247,37 @@ func (c *testGRPCClient) PrintKV(key string, value interface{}) { } } +func (c *testGRPCClient) Bidirectional() error { + nextID := c.broker.NextId() + go c.broker.AcceptAndServe(nextID, func(opts []grpc.ServerOption) *grpc.Server { + s := grpc.NewServer(opts...) + grpctest.RegisterPingPongServer(s, &pingPongServer{}) + return s + }) + + resp, err := c.Client.Bidirectional(context.Background(), &grpctest.BidirectionalRequest{ + Id: nextID, + }) + if err != nil { + return err + } + + conn, err := c.broker.Dial(resp.Id) + if err != nil { + return err + } + + pingPongClient := grpctest.NewPingPongClient(conn) + pResp, err := pingPongClient.Ping(context.Background(), &grpctest.PingRequest{}) + if err != nil { + return err + } + if pResp.Msg != "pong" { + return errors.New("Bad PingPong") + } + return nil +} + func helperProcess(s ...string) *exec.Cmd { cs := []string{"-test.run=TestHelperProcess", "--"} cs = append(cs, s...) diff --git a/vendor/github.com/hashicorp/go-plugin/testing.go b/vendor/github.com/hashicorp/go-plugin/testing.go index c6bf7c4..2dcd35c 100644 --- a/vendor/github.com/hashicorp/go-plugin/testing.go +++ b/vendor/github.com/hashicorp/go-plugin/testing.go @@ -2,6 +2,7 @@ package plugin import ( "bytes" + "context" "net" "net/rpc" @@ -77,6 +78,35 @@ func TestPluginRPCConn(t testing.T, ps map[string]Plugin) (*RPCClient, *RPCServe return client, server } +// TestGRPCConn returns a gRPC client conn and grpc server that are connected +// together and configured. The register function is used to register services +// prior to the Serve call. This is used to test gRPC connections. +func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) { + // Create a listener + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("err: %s", err) + } + + server := grpc.NewServer() + register(server) + go server.Serve(l) + + // Connect to the server + conn, err := grpc.Dial( + l.Addr().String(), + grpc.WithBlock(), + grpc.WithInsecure()) + if err != nil { + t.Fatalf("err: %s", err) + } + + // Connection successful, close the listener + l.Close() + + return conn, server +} + // TestPluginGRPCConn returns a plugin gRPC client and server that are connected // together and configured. This is used to test gRPC connections. func TestPluginGRPCConn(t testing.T, ps map[string]Plugin) (*GRPCClient, *GRPCServer) { @@ -110,10 +140,16 @@ func TestPluginGRPCConn(t testing.T, ps map[string]Plugin) (*GRPCClient, *GRPCSe // Connection successful, close the listener l.Close() + brokerGRPCClient := newGRPCBrokerClient(conn) + broker := newGRPCBroker(brokerGRPCClient, nil) + go broker.Run() + go brokerGRPCClient.StartStream() // Create the client client := &GRPCClient{ Conn: conn, Plugins: ps, + broker: broker, + doneCtx: context.Background(), } return client, server diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go index 0f81ddf..93b5664 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go @@ -627,7 +627,7 @@ Traversal: if lit, isLit := keyExpr.(*LiteralValueExpr); isLit { litKey, _ := lit.Value(nil) rng := hcl.RangeBetween(open.Range, close.Range) - step := &hcl.TraverseIndex{ + step := hcl.TraverseIndex{ Key: litKey, SrcRange: rng, } @@ -1531,7 +1531,7 @@ Character: var detail string switch { - case len(ch) == 1 && (ch[0] == '$' || ch[0] == '!'): + case len(ch) == 1 && (ch[0] == '$' || ch[0] == '%'): detail = fmt.Sprintf( "The characters \"\\%s\" do not form a recognized escape sequence. To escape a \"%s{\" template sequence, use \"%s%s{\".", ch, ch, ch, ch, @@ -1562,7 +1562,7 @@ Character: esc = esc[:0] continue Character - case '$', '!': + case '$', '%': switch len(esc) { case 1: if len(ch) == 1 && ch[0] == esc[0] { @@ -1602,8 +1602,8 @@ Character: case '$': esc = append(esc, '$') continue Character - case '!': - esc = append(esc, '!') + case '%': + esc = append(esc, '%') continue Character } } @@ -1611,6 +1611,42 @@ Character: } } + // if we still have an outstanding "esc" when we fall out here then + // the literal ended with an unterminated escape sequence, which we + // must now deal with. + if len(esc) > 0 { + if esc[0] == '\\' { + // An incomplete backslash sequence is an error, since it suggests + // that e.g. the user started writing a \uXXXX sequence but didn't + // provide enough hex digits. + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid escape sequence", + Detail: fmt.Sprintf("The characters %q do not form a recognized escape sequence.", esc), + Subject: &hcl.Range{ + Filename: tok.Range.Filename, + Start: hcl.Pos{ + Line: pos.Line, + Column: pos.Column, + Byte: pos.Byte, + }, + End: hcl.Pos{ + Line: pos.Line, + Column: pos.Column + len(esc), + Byte: pos.Byte + len(esc), + }, + }, + }) + + } + // This might also be an incomplete $${ or %%{ escape sequence, but + // that's treated as a literal rather than an error since those only + // count as escape sequences when all three characters are present. + + ret = append(ret, esc...) + esc = nil + } + return string(ret), diags } diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_template.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_template.go index e04c8e0..3711067 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_template.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_template.go @@ -435,7 +435,7 @@ Token: }) case TokenTemplateControl: - // if the opener is !{~ then we want to eat any trailing whitespace + // if the opener is %{~ then we want to eat any trailing whitespace // in the preceding literal token, assuming it is indeed a literal // token. if canTrimPrev && len(next.Bytes) == 3 && next.Bytes[2] == '~' && len(parts) > 0 { @@ -452,7 +452,7 @@ Token: diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "Invalid template directive", - Detail: "A template directive keyword (\"if\", \"for\", etc) is expected at the beginning of a !{ sequence.", + Detail: "A template directive keyword (\"if\", \"for\", etc) is expected at the beginning of a %{ sequence.", Subject: &kw.Range, Context: hcl.RangeBetween(next.Range, kw.Range).Ptr(), }) diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_test.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_test.go index df08cf7..ee16c6d 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_test.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser_test.go @@ -465,6 +465,256 @@ block "valid" {} }, }, }, + { + "a = \"hello $${true}\"\n", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &TemplateExpr{ + Parts: []Expression{ + &LiteralValueExpr{ + Val: cty.StringVal("hello ${true}"), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, + }, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + }, + }, + }, + { + "a = \"hello %%{true}\"\n", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &TemplateExpr{ + Parts: []Expression{ + &LiteralValueExpr{ + Val: cty.StringVal("hello %{true}"), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, + }, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, + }, + }, + }, + { + "a = \"hello $$\"\n", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &TemplateExpr{ + Parts: []Expression{ + &LiteralValueExpr{ + Val: cty.StringVal("hello $$"), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, + }, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + }, + }, + }, + { + "a = \"hello %%\"\n", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &TemplateExpr{ + Parts: []Expression{ + &LiteralValueExpr{ + Val: cty.StringVal("hello %%"), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, + }, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, + }, + }, + }, + { + "a = \"hello!\"\n", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &TemplateExpr{ + Parts: []Expression{ + &LiteralValueExpr{ + Val: cty.StringVal("hello!"), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, + }, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, + End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, + }, + }, + }, { "a = foo.bar\n", 0, diff --git a/vendor/github.com/jmespath/go-jmespath/Makefile b/vendor/github.com/jmespath/go-jmespath/Makefile index ad17bf0..a828d28 100644 --- a/vendor/github.com/jmespath/go-jmespath/Makefile +++ b/vendor/github.com/jmespath/go-jmespath/Makefile @@ -35,7 +35,7 @@ buildfuzz: go-fuzz-build github.com/jmespath/go-jmespath/fuzz fuzz: buildfuzz - go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/corpus + go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/testdata bench: go test -bench . -cpuprofile cpu.out diff --git a/vendor/github.com/jmespath/go-jmespath/api.go b/vendor/github.com/jmespath/go-jmespath/api.go index 67df3fc..9cfa988 100644 --- a/vendor/github.com/jmespath/go-jmespath/api.go +++ b/vendor/github.com/jmespath/go-jmespath/api.go @@ -1,5 +1,42 @@ package jmespath +import "strconv" + +// JmesPath is the epresentation of a compiled JMES path query. A JmesPath is +// safe for concurrent use by multiple goroutines. +type JMESPath struct { + ast ASTNode + intr *treeInterpreter +} + +// Compile parses a JMESPath expression and returns, if successful, a JMESPath +// object that can be used to match against data. +func Compile(expression string) (*JMESPath, error) { + parser := NewParser() + ast, err := parser.Parse(expression) + if err != nil { + return nil, err + } + jmespath := &JMESPath{ast: ast, intr: newInterpreter()} + return jmespath, nil +} + +// MustCompile is like Compile but panics if the expression cannot be parsed. +// It simplifies safe initialization of global variables holding compiled +// JMESPaths. +func MustCompile(expression string) *JMESPath { + jmespath, err := Compile(expression) + if err != nil { + panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error()) + } + return jmespath +} + +// Search evaluates a JMESPath expression against input data and returns the result. +func (jp *JMESPath) Search(data interface{}) (interface{}, error) { + return jp.intr.Execute(jp.ast, data) +} + // Search evaluates a JMESPath expression against input data and returns the result. func Search(expression string, data interface{}) (interface{}, error) { intr := newInterpreter() diff --git a/vendor/github.com/jmespath/go-jmespath/api_test.go b/vendor/github.com/jmespath/go-jmespath/api_test.go new file mode 100644 index 0000000..b0b106d --- /dev/null +++ b/vendor/github.com/jmespath/go-jmespath/api_test.go @@ -0,0 +1,32 @@ +package jmespath + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestValidPrecompiledExpressionSearches(t *testing.T) { + assert := assert.New(t) + data := make(map[string]interface{}) + data["foo"] = "bar" + precompiled, err := Compile("foo") + assert.Nil(err) + result, err := precompiled.Search(data) + assert.Nil(err) + assert.Equal("bar", result) +} + +func TestInvalidPrecompileErrors(t *testing.T) { + assert := assert.New(t) + _, err := Compile("not a valid expression") + assert.NotNil(err) +} + +func TestInvalidMustCompilePanics(t *testing.T) { + defer func() { + r := recover() + assert.NotNil(t, r) + }() + MustCompile("not a valid expression") +} diff --git a/vendor/github.com/jmespath/go-jmespath/functions.go b/vendor/github.com/jmespath/go-jmespath/functions.go index 8a3f2ef..9b7cd89 100644 --- a/vendor/github.com/jmespath/go-jmespath/functions.go +++ b/vendor/github.com/jmespath/go-jmespath/functions.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math" + "reflect" "sort" "strconv" "strings" @@ -124,197 +125,197 @@ type functionCaller struct { func newFunctionCaller() *functionCaller { caller := &functionCaller{} caller.functionTable = map[string]functionEntry{ - "length": functionEntry{ + "length": { name: "length", arguments: []argSpec{ - argSpec{types: []jpType{jpString, jpArray, jpObject}}, + {types: []jpType{jpString, jpArray, jpObject}}, }, handler: jpfLength, }, - "starts_with": functionEntry{ + "starts_with": { name: "starts_with", arguments: []argSpec{ - argSpec{types: []jpType{jpString}}, - argSpec{types: []jpType{jpString}}, + {types: []jpType{jpString}}, + {types: []jpType{jpString}}, }, handler: jpfStartsWith, }, - "abs": functionEntry{ + "abs": { name: "abs", arguments: []argSpec{ - argSpec{types: []jpType{jpNumber}}, + {types: []jpType{jpNumber}}, }, handler: jpfAbs, }, - "avg": functionEntry{ + "avg": { name: "avg", arguments: []argSpec{ - argSpec{types: []jpType{jpArrayNumber}}, + {types: []jpType{jpArrayNumber}}, }, handler: jpfAvg, }, - "ceil": functionEntry{ + "ceil": { name: "ceil", arguments: []argSpec{ - argSpec{types: []jpType{jpNumber}}, + {types: []jpType{jpNumber}}, }, handler: jpfCeil, }, - "contains": functionEntry{ + "contains": { name: "contains", arguments: []argSpec{ - argSpec{types: []jpType{jpArray, jpString}}, - argSpec{types: []jpType{jpAny}}, + {types: []jpType{jpArray, jpString}}, + {types: []jpType{jpAny}}, }, handler: jpfContains, }, - "ends_with": functionEntry{ + "ends_with": { name: "ends_with", arguments: []argSpec{ - argSpec{types: []jpType{jpString}}, - argSpec{types: []jpType{jpString}}, + {types: []jpType{jpString}}, + {types: []jpType{jpString}}, }, handler: jpfEndsWith, }, - "floor": functionEntry{ + "floor": { name: "floor", arguments: []argSpec{ - argSpec{types: []jpType{jpNumber}}, + {types: []jpType{jpNumber}}, }, handler: jpfFloor, }, - "map": functionEntry{ + "map": { name: "amp", arguments: []argSpec{ - argSpec{types: []jpType{jpExpref}}, - argSpec{types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, + {types: []jpType{jpArray}}, }, handler: jpfMap, hasExpRef: true, }, - "max": functionEntry{ + "max": { name: "max", arguments: []argSpec{ - argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, + {types: []jpType{jpArrayNumber, jpArrayString}}, }, handler: jpfMax, }, - "merge": functionEntry{ + "merge": { name: "merge", arguments: []argSpec{ - argSpec{types: []jpType{jpObject}, variadic: true}, + {types: []jpType{jpObject}, variadic: true}, }, handler: jpfMerge, }, - "max_by": functionEntry{ + "max_by": { name: "max_by", arguments: []argSpec{ - argSpec{types: []jpType{jpArray}}, - argSpec{types: []jpType{jpExpref}}, + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, }, handler: jpfMaxBy, hasExpRef: true, }, - "sum": functionEntry{ + "sum": { name: "sum", arguments: []argSpec{ - argSpec{types: []jpType{jpArrayNumber}}, + {types: []jpType{jpArrayNumber}}, }, handler: jpfSum, }, - "min": functionEntry{ + "min": { name: "min", arguments: []argSpec{ - argSpec{types: []jpType{jpArrayNumber, jpArrayString}}, + {types: []jpType{jpArrayNumber, jpArrayString}}, }, handler: jpfMin, }, - "min_by": functionEntry{ + "min_by": { name: "min_by", arguments: []argSpec{ - argSpec{types: []jpType{jpArray}}, - argSpec{types: []jpType{jpExpref}}, + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, }, handler: jpfMinBy, hasExpRef: true, }, - "type": functionEntry{ + "type": { name: "type", arguments: []argSpec{ - argSpec{types: []jpType{jpAny}}, + {types: []jpType{jpAny}}, }, handler: jpfType, }, - "keys": functionEntry{ + "keys": { name: "keys", arguments: []argSpec{ - argSpec{types: []jpType{jpObject}}, + {types: []jpType{jpObject}}, }, handler: jpfKeys, }, - "values": functionEntry{ + "values": { name: "values", arguments: []argSpec{ - argSpec{types: []jpType{jpObject}}, + {types: []jpType{jpObject}}, }, handler: jpfValues, }, - "sort": functionEntry{ + "sort": { name: "sort", arguments: []argSpec{ - argSpec{types: []jpType{jpArrayString, jpArrayNumber}}, + {types: []jpType{jpArrayString, jpArrayNumber}}, }, handler: jpfSort, }, - "sort_by": functionEntry{ + "sort_by": { name: "sort_by", arguments: []argSpec{ - argSpec{types: []jpType{jpArray}}, - argSpec{types: []jpType{jpExpref}}, + {types: []jpType{jpArray}}, + {types: []jpType{jpExpref}}, }, handler: jpfSortBy, hasExpRef: true, }, - "join": functionEntry{ + "join": { name: "join", arguments: []argSpec{ - argSpec{types: []jpType{jpString}}, - argSpec{types: []jpType{jpArrayString}}, + {types: []jpType{jpString}}, + {types: []jpType{jpArrayString}}, }, handler: jpfJoin, }, - "reverse": functionEntry{ + "reverse": { name: "reverse", arguments: []argSpec{ - argSpec{types: []jpType{jpArray, jpString}}, + {types: []jpType{jpArray, jpString}}, }, handler: jpfReverse, }, - "to_array": functionEntry{ + "to_array": { name: "to_array", arguments: []argSpec{ - argSpec{types: []jpType{jpAny}}, + {types: []jpType{jpAny}}, }, handler: jpfToArray, }, - "to_string": functionEntry{ + "to_string": { name: "to_string", arguments: []argSpec{ - argSpec{types: []jpType{jpAny}}, + {types: []jpType{jpAny}}, }, handler: jpfToString, }, - "to_number": functionEntry{ + "to_number": { name: "to_number", arguments: []argSpec{ - argSpec{types: []jpType{jpAny}}, + {types: []jpType{jpAny}}, }, handler: jpfToNumber, }, - "not_null": functionEntry{ + "not_null": { name: "not_null", arguments: []argSpec{ - argSpec{types: []jpType{jpAny}, variadic: true}, + {types: []jpType{jpAny}, variadic: true}, }, handler: jpfNotNull, }, @@ -357,7 +358,7 @@ func (a *argSpec) typeCheck(arg interface{}) error { return nil } case jpArray: - if _, ok := arg.([]interface{}); ok { + if isSliceType(arg) { return nil } case jpObject: @@ -409,8 +410,9 @@ func jpfLength(arguments []interface{}) (interface{}, error) { arg := arguments[0] if c, ok := arg.(string); ok { return float64(utf8.RuneCountInString(c)), nil - } else if c, ok := arg.([]interface{}); ok { - return float64(len(c)), nil + } else if isSliceType(arg) { + v := reflect.ValueOf(arg) + return float64(v.Len()), nil } else if c, ok := arg.(map[string]interface{}); ok { return float64(len(c)), nil } diff --git a/vendor/github.com/jmespath/go-jmespath/interpreter_test.go b/vendor/github.com/jmespath/go-jmespath/interpreter_test.go index 5b529c4..11c6d0a 100644 --- a/vendor/github.com/jmespath/go-jmespath/interpreter_test.go +++ b/vendor/github.com/jmespath/go-jmespath/interpreter_test.go @@ -69,7 +69,7 @@ func TestCanSupportUserDefinedStructsRef(t *testing.T) { func TestCanSupportStructWithSliceAll(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}} + data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("B[].Foo", data) assert.Nil(err) assert.Equal([]interface{}{"f1", "correct"}, result) @@ -77,7 +77,7 @@ func TestCanSupportStructWithSliceAll(t *testing.T) { func TestCanSupportStructWithSlicingExpression(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}} + data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("B[:].Foo", data) assert.Nil(err) assert.Equal([]interface{}{"f1", "correct"}, result) @@ -85,7 +85,7 @@ func TestCanSupportStructWithSlicingExpression(t *testing.T) { func TestCanSupportStructWithFilterProjection(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}} + data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("B[? `true` ].Foo", data) assert.Nil(err) assert.Equal([]interface{}{"f1", "correct"}, result) @@ -93,7 +93,7 @@ func TestCanSupportStructWithFilterProjection(t *testing.T) { func TestCanSupportStructWithSlice(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}} + data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("B[-1].Foo", data) assert.Nil(err) assert.Equal("correct", result) @@ -109,7 +109,7 @@ func TestCanSupportStructWithOrExpressions(t *testing.T) { func TestCanSupportStructWithSlicePointer(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", C: []*scalars{&scalars{"f1", "b1"}, &scalars{"correct", "b2"}}} + data := sliceType{A: "foo", C: []*scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("C[-1].Foo", data) assert.Nil(err) assert.Equal("correct", result) @@ -128,7 +128,7 @@ func TestWillAutomaticallyCapitalizeFieldNames(t *testing.T) { func TestCanSupportStructWithSliceLowerCased(t *testing.T) { assert := assert.New(t) - data := sliceType{A: "foo", B: []scalars{scalars{"f1", "b1"}, scalars{"correct", "b2"}}} + data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := Search("b[-1].foo", data) assert.Nil(err) assert.Equal("correct", result) @@ -173,6 +173,14 @@ func TestCanSupportProjectionsWithStructs(t *testing.T) { assert.Equal([]interface{}{"first", "second", "third"}, result) } +func TestCanSupportSliceOfStructsWithFunctions(t *testing.T) { + assert := assert.New(t) + data := []scalars{scalars{"a1", "b1"}, scalars{"a2", "b2"}} + result, err := Search("length(@)", data) + assert.Nil(err) + assert.Equal(result.(float64), 2.0) +} + func BenchmarkInterpretSingleFieldStruct(b *testing.B) { intr := newInterpreter() parser := NewParser() diff --git a/vendor/github.com/jmespath/go-jmespath/lexer_test.go b/vendor/github.com/jmespath/go-jmespath/lexer_test.go index 7a9a9ee..d13a042 100644 --- a/vendor/github.com/jmespath/go-jmespath/lexer_test.go +++ b/vendor/github.com/jmespath/go-jmespath/lexer_test.go @@ -11,63 +11,63 @@ var lexingTests = []struct { expression string expected []token }{ - {"*", []token{token{tStar, "*", 0, 1}}}, - {".", []token{token{tDot, ".", 0, 1}}}, - {"[?", []token{token{tFilter, "[?", 0, 2}}}, - {"[]", []token{token{tFlatten, "[]", 0, 2}}}, - {"(", []token{token{tLparen, "(", 0, 1}}}, - {")", []token{token{tRparen, ")", 0, 1}}}, - {"[", []token{token{tLbracket, "[", 0, 1}}}, - {"]", []token{token{tRbracket, "]", 0, 1}}}, - {"{", []token{token{tLbrace, "{", 0, 1}}}, - {"}", []token{token{tRbrace, "}", 0, 1}}}, - {"||", []token{token{tOr, "||", 0, 2}}}, - {"|", []token{token{tPipe, "|", 0, 1}}}, - {"29", []token{token{tNumber, "29", 0, 2}}}, - {"2", []token{token{tNumber, "2", 0, 1}}}, - {"0", []token{token{tNumber, "0", 0, 1}}}, - {"-20", []token{token{tNumber, "-20", 0, 3}}}, - {"foo", []token{token{tUnquotedIdentifier, "foo", 0, 3}}}, - {`"bar"`, []token{token{tQuotedIdentifier, "bar", 0, 3}}}, + {"*", []token{{tStar, "*", 0, 1}}}, + {".", []token{{tDot, ".", 0, 1}}}, + {"[?", []token{{tFilter, "[?", 0, 2}}}, + {"[]", []token{{tFlatten, "[]", 0, 2}}}, + {"(", []token{{tLparen, "(", 0, 1}}}, + {")", []token{{tRparen, ")", 0, 1}}}, + {"[", []token{{tLbracket, "[", 0, 1}}}, + {"]", []token{{tRbracket, "]", 0, 1}}}, + {"{", []token{{tLbrace, "{", 0, 1}}}, + {"}", []token{{tRbrace, "}", 0, 1}}}, + {"||", []token{{tOr, "||", 0, 2}}}, + {"|", []token{{tPipe, "|", 0, 1}}}, + {"29", []token{{tNumber, "29", 0, 2}}}, + {"2", []token{{tNumber, "2", 0, 1}}}, + {"0", []token{{tNumber, "0", 0, 1}}}, + {"-20", []token{{tNumber, "-20", 0, 3}}}, + {"foo", []token{{tUnquotedIdentifier, "foo", 0, 3}}}, + {`"bar"`, []token{{tQuotedIdentifier, "bar", 0, 3}}}, // Escaping the delimiter - {`"bar\"baz"`, []token{token{tQuotedIdentifier, `bar"baz`, 0, 7}}}, - {",", []token{token{tComma, ",", 0, 1}}}, - {":", []token{token{tColon, ":", 0, 1}}}, - {"<", []token{token{tLT, "<", 0, 1}}}, - {"<=", []token{token{tLTE, "<=", 0, 2}}}, - {">", []token{token{tGT, ">", 0, 1}}}, - {">=", []token{token{tGTE, ">=", 0, 2}}}, - {"==", []token{token{tEQ, "==", 0, 2}}}, - {"!=", []token{token{tNE, "!=", 0, 2}}}, - {"`[0, 1, 2]`", []token{token{tJSONLiteral, "[0, 1, 2]", 1, 9}}}, - {"'foo'", []token{token{tStringLiteral, "foo", 1, 3}}}, - {"'a'", []token{token{tStringLiteral, "a", 1, 1}}}, - {`'foo\'bar'`, []token{token{tStringLiteral, "foo'bar", 1, 7}}}, - {"@", []token{token{tCurrent, "@", 0, 1}}}, - {"&", []token{token{tExpref, "&", 0, 1}}}, + {`"bar\"baz"`, []token{{tQuotedIdentifier, `bar"baz`, 0, 7}}}, + {",", []token{{tComma, ",", 0, 1}}}, + {":", []token{{tColon, ":", 0, 1}}}, + {"<", []token{{tLT, "<", 0, 1}}}, + {"<=", []token{{tLTE, "<=", 0, 2}}}, + {">", []token{{tGT, ">", 0, 1}}}, + {">=", []token{{tGTE, ">=", 0, 2}}}, + {"==", []token{{tEQ, "==", 0, 2}}}, + {"!=", []token{{tNE, "!=", 0, 2}}}, + {"`[0, 1, 2]`", []token{{tJSONLiteral, "[0, 1, 2]", 1, 9}}}, + {"'foo'", []token{{tStringLiteral, "foo", 1, 3}}}, + {"'a'", []token{{tStringLiteral, "a", 1, 1}}}, + {`'foo\'bar'`, []token{{tStringLiteral, "foo'bar", 1, 7}}}, + {"@", []token{{tCurrent, "@", 0, 1}}}, + {"&", []token{{tExpref, "&", 0, 1}}}, // Quoted identifier unicode escape sequences - {`"\u2713"`, []token{token{tQuotedIdentifier, "✓", 0, 3}}}, - {`"\\"`, []token{token{tQuotedIdentifier, `\`, 0, 1}}}, - {"`\"foo\"`", []token{token{tJSONLiteral, "\"foo\"", 1, 5}}}, + {`"\u2713"`, []token{{tQuotedIdentifier, "✓", 0, 3}}}, + {`"\\"`, []token{{tQuotedIdentifier, `\`, 0, 1}}}, + {"`\"foo\"`", []token{{tJSONLiteral, "\"foo\"", 1, 5}}}, // Combinations of tokens. {"foo.bar", []token{ - token{tUnquotedIdentifier, "foo", 0, 3}, - token{tDot, ".", 3, 1}, - token{tUnquotedIdentifier, "bar", 4, 3}, + {tUnquotedIdentifier, "foo", 0, 3}, + {tDot, ".", 3, 1}, + {tUnquotedIdentifier, "bar", 4, 3}, }}, {"foo[0]", []token{ - token{tUnquotedIdentifier, "foo", 0, 3}, - token{tLbracket, "[", 3, 1}, - token{tNumber, "0", 4, 1}, - token{tRbracket, "]", 5, 1}, + {tUnquotedIdentifier, "foo", 0, 3}, + {tLbracket, "[", 3, 1}, + {tNumber, "0", 4, 1}, + {tRbracket, "]", 5, 1}, }}, {"foo[?a 0 { - s.header = state.mdata + // Headers frame is not actually a trailers-only frame. + if !endStream { + s.recvCompress = state.encoding + if len(state.mdata) > 0 { + s.header = state.mdata + } } close(s.headerChan) s.headerDone = true