From 8e66a0ffdad5407dbae50fbf17eed3ca28db3bea Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 13 Sep 2016 09:24:52 -0700 Subject: [PATCH 1/3] vendor: update grpc and protobuf Signed-off-by: Alexander Morozov Upstream-commit: afe23cea3d73fc4c5f90ff109edbddd339ea29ed Component: engine --- components/engine/hack/vendor.sh | 6 +- .../src/github.com/gogo/protobuf/LICENSE | 6 +- .../gogo/protobuf/gogoproto/Makefile | 6 +- .../github.com/gogo/protobuf/gogoproto/doc.go | 6 +- .../gogo/protobuf/gogoproto/gogo.pb.go | 146 +-- .../gogo/protobuf/gogoproto/gogo.proto | 6 +- .../gogo/protobuf/gogoproto/helper.go | 4 +- .../github.com/gogo/protobuf/proto/clone.go | 14 +- .../github.com/gogo/protobuf/proto/decode.go | 34 +- .../gogo/protobuf/proto/decode_gogo.go | 6 +- .../github.com/gogo/protobuf/proto/encode.go | 60 +- .../gogo/protobuf/proto/encode_gogo.go | 6 +- .../github.com/gogo/protobuf/proto/equal.go | 26 +- .../gogo/protobuf/proto/extensions.go | 409 ++++++--- .../gogo/protobuf/proto/extensions_gogo.go | 88 +- .../src/github.com/gogo/protobuf/proto/lib.go | 4 + .../gogo/protobuf/proto/lib_gogo.go | 6 +- .../gogo/protobuf/proto/message_set.go | 43 +- .../gogo/protobuf/proto/pointer_reflect.go | 7 +- .../gogo/protobuf/proto/pointer_unsafe.go | 6 +- .../protobuf/proto/pointer_unsafe_gogo.go | 21 +- .../gogo/protobuf/proto/properties.go | 53 +- .../gogo/protobuf/proto/properties_gogo.go | 6 +- .../gogo/protobuf/proto/skip_gogo.go | 6 +- .../github.com/gogo/protobuf/proto/text.go | 82 +- .../gogo/protobuf/proto/text_gogo.go | 6 +- .../gogo/protobuf/proto/text_parser.go | 75 +- .../protoc-gen-gogo/descriptor/Makefile | 3 + .../descriptor/descriptor.pb.go | 382 ++++---- ...gostring.go => descriptor_gostring.gen.go} | 73 +- .../protoc-gen-gogo/descriptor/helper.go | 4 +- .../gogo/protobuf/sortkeys/sortkeys.go | 4 +- .../github.com/golang/protobuf/proto/Makefile | 2 +- .../github.com/golang/protobuf/proto/clone.go | 12 +- .../golang/protobuf/proto/decode.go | 21 +- .../golang/protobuf/proto/encode.go | 60 +- .../github.com/golang/protobuf/proto/equal.go | 34 +- .../golang/protobuf/proto/extensions.go | 227 ++++- .../github.com/golang/protobuf/proto/lib.go | 6 +- .../golang/protobuf/proto/message_set.go | 43 +- .../golang/protobuf/proto/pointer_reflect.go | 7 +- .../golang/protobuf/proto/pointer_unsafe.go | 6 +- .../golang/protobuf/proto/properties.go | 56 +- .../github.com/golang/protobuf/proto/text.go | 148 ++- .../golang/protobuf/proto/text_parser.go | 183 +++- .../github.com/golang/protobuf/ptypes/any.go | 136 +++ .../golang/protobuf/ptypes/any/any.pb.go | 155 ++++ .../golang/protobuf/ptypes/any/any.proto | 140 +++ .../protobuf/ptypes/duration/duration.pb.go | 42 +- .../protobuf/ptypes/duration/duration.proto | 3 +- .../golang/protobuf/ptypes/regen.sh | 12 +- .../protobuf/ptypes/timestamp/timestamp.pb.go | 42 +- .../protobuf/ptypes/timestamp/timestamp.proto | 2 +- .../src/google.golang.org/grpc/.travis.yml | 16 +- .../src/google.golang.org/grpc/Makefile | 5 +- .../vendor/src/google.golang.org/grpc/PATENTS | 12 +- .../src/google.golang.org/grpc/README.md | 2 +- .../src/google.golang.org/grpc/backoff.go | 8 +- .../src/google.golang.org/grpc/balancer.go | 385 ++++++++ .../vendor/src/google.golang.org/grpc/call.go | 89 +- .../src/google.golang.org/grpc/clientconn.go | 844 +++++++++++------- .../grpc/credentials/credentials.go | 87 +- .../grpc/credentials/credentials_util_go17.go | 76 ++ .../credentials/credentials_util_pre_go17.go | 74 ++ .../grpc/credentials/oauth/oauth.go | 33 +- .../grpc/health/grpc_health_v1/health.pb.go | 44 +- .../grpc/metadata/metadata.go | 14 +- .../google.golang.org/grpc/naming/naming.go | 3 +- .../src/google.golang.org/grpc/picker.go | 243 ----- .../src/google.golang.org/grpc/rpc_util.go | 81 +- .../src/google.golang.org/grpc/server.go | 166 +++- .../src/google.golang.org/grpc/stream.go | 167 +++- .../src/google.golang.org/grpc/trace.go | 3 +- .../grpc/transport/control.go | 5 + .../google.golang.org/grpc/transport/go16.go | 46 + .../google.golang.org/grpc/transport/go17.go | 46 + .../grpc/transport/handler_server.go | 26 +- .../grpc/transport/http2_client.go | 265 ++++-- .../grpc/transport/http2_server.go | 93 +- .../grpc/transport/http_util.go | 113 ++- .../grpc/transport/pre_go16.go | 51 ++ .../grpc/transport/transport.go | 104 ++- 82 files changed, 4333 insertions(+), 1709 deletions(-) rename components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/{gostring.go => descriptor_gostring.gen.go} (92%) create mode 100644 components/engine/vendor/src/github.com/golang/protobuf/ptypes/any.go create mode 100644 components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.pb.go create mode 100644 components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.proto create mode 100644 components/engine/vendor/src/google.golang.org/grpc/balancer.go create mode 100644 components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_go17.go create mode 100644 components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_pre_go17.go delete mode 100644 components/engine/vendor/src/google.golang.org/grpc/picker.go create mode 100644 components/engine/vendor/src/google.golang.org/grpc/transport/go16.go create mode 100644 components/engine/vendor/src/google.golang.org/grpc/transport/go17.go create mode 100644 components/engine/vendor/src/google.golang.org/grpc/transport/pre_go16.go diff --git a/components/engine/hack/vendor.sh b/components/engine/hack/vendor.sh index 5efd4a444b..6e6f3e00c8 100755 --- a/components/engine/hack/vendor.sh +++ b/components/engine/hack/vendor.sh @@ -102,7 +102,7 @@ clone git github.com/pborman/uuid v1.0 # get desired notary commit, might also need to be updated in Dockerfile clone git github.com/docker/notary v0.3.0 -clone git google.golang.org/grpc ab0be5212fb225475f2087566eded7da5d727960 https://github.com/grpc/grpc-go.git +clone git google.golang.org/grpc v1.0.1-GA https://github.com/grpc/grpc-go.git clone git github.com/miekg/pkcs11 df8ae6ca730422dba20c768ff38ef7d79077a59f clone git github.com/docker/go v1.5.1-1-1-gbaf439e clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c @@ -114,7 +114,7 @@ clone git github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb2 clone git github.com/coreos/go-systemd v4 clone git github.com/godbus/dbus v4.0.0 clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 -clone git github.com/golang/protobuf 3c84672111d91bb5ac31719e112f9f7126a0e26e +clone git github.com/golang/protobuf 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a # gelf logging driver deps clone git github.com/Graylog2/go-gelf aab2f594e4585d43468ac57287b0dece9d806883 @@ -146,7 +146,7 @@ clone git github.com/docker/containerd 4c21ad662f71af56c0e6b29c0afef72df441d1ff # cluster clone git github.com/docker/swarmkit 27fbaef4ceed648bb575969ccc9083a6e104a719 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 -clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028 +clone git github.com/gogo/protobuf v0.3 clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a clone git github.com/google/certificate-transparency 0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341 clone git golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2 https://github.com/golang/crypto.git diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/LICENSE b/components/engine/vendor/src/github.com/gogo/protobuf/LICENSE index 335e38e19b..7be0cc7b62 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/LICENSE +++ b/components/engine/vendor/src/github.com/gogo/protobuf/LICENSE @@ -1,7 +1,7 @@ -Extensions for Protocol Buffers to create more go like structures. +Protocol Buffers for Go with Gadgets -Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -http://github.com/gogo/protobuf/gogoproto +Copyright (c) 2013, The GoGo Authors. All rights reserved. +http://github.com/gogo/protobuf Go support for Protocol Buffers - Google's data interchange format diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/Makefile b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/Makefile index 557f294933..395592a5da 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/Makefile +++ b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/Makefile @@ -1,7 +1,7 @@ -# Extensions for Protocol Buffers to create more go like structures. +# Protocol Buffers for Go with Gadgets # -# Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -# http://github.com/gogo/protobuf/gogoproto +# Copyright (c) 2013, The GoGo Authors. All rights reserved. +# http://github.com/gogo/protobuf # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/doc.go b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/doc.go index f0424d4f8a..5ecfae1135 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/doc.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/doc.go @@ -1,7 +1,7 @@ -// Extensions for Protocol Buffers to create more go like structures. +// Protocol Buffers for Go with Gadgets // -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.pb.go b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.pb.go index f97c2338e7..6da0e3e7f1 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.pb.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.pb.go @@ -24,7 +24,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package var E_GoprotoEnumPrefix = &proto.ExtensionDesc{ ExtendedType: (*google_protobuf.EnumOptions)(nil), @@ -587,75 +589,77 @@ func init() { proto.RegisterExtension(E_Castvalue) } +func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) } + var fileDescriptorGogo = []byte{ - // 1096 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x97, 0xcb, 0x6f, 0xdc, 0x54, - 0x14, 0x87, 0x85, 0x48, 0x95, 0x99, 0x93, 0x17, 0x99, 0x84, 0x50, 0x2a, 0x10, 0xed, 0x8e, 0x55, - 0xba, 0x42, 0xa8, 0xae, 0x10, 0x6a, 0xab, 0x34, 0x2a, 0x22, 0x10, 0x05, 0x52, 0x40, 0x2c, 0x46, - 0x9e, 0xc9, 0x8d, 0x3b, 0xe0, 0xf1, 0x35, 0xbe, 0x76, 0xd5, 0xb0, 0x43, 0xe5, 0x21, 0x84, 0x78, - 0x23, 0x41, 0x4b, 0xcb, 0x63, 0xc1, 0xfb, 0x59, 0x1e, 0x7b, 0x36, 0xc0, 0x9a, 0xff, 0x81, 0x0d, - 0x10, 0x5e, 0x52, 0x76, 0xd9, 0xf4, 0x1e, 0xfb, 0x1c, 0xcf, 0xb5, 0x67, 0xa4, 0x7b, 0x67, 0xe7, - 0x64, 0xee, 0xf7, 0xcd, 0xf5, 0x39, 0xbe, 0xe7, 0x37, 0x06, 0x08, 0x64, 0x20, 0x97, 0xe3, 0x44, - 0xa6, 0xb2, 0xd5, 0xc4, 0xeb, 0xfc, 0xf2, 0xd0, 0xe1, 0x40, 0xca, 0x20, 0x14, 0x47, 0xf3, 0xbf, - 0x3a, 0xd9, 0xf6, 0xd1, 0x2d, 0xa1, 0xba, 0x49, 0x2f, 0x4e, 0x65, 0x52, 0x2c, 0xf6, 0x1e, 0x80, - 0x05, 0x5a, 0xdc, 0x16, 0x51, 0xd6, 0x6f, 0xc7, 0x89, 0xd8, 0xee, 0x5d, 0x68, 0xdd, 0xb6, 0x5c, - 0x90, 0xcb, 0x4c, 0x2e, 0xaf, 0xe8, 0x4f, 0x1f, 0x8c, 0xd3, 0x9e, 0x8c, 0xd4, 0xc1, 0x6b, 0xbf, - 0xdf, 0x78, 0xf8, 0x86, 0x3b, 0x1b, 0x1b, 0xf3, 0x84, 0xe2, 0x67, 0xeb, 0x39, 0xe8, 0x6d, 0xc0, - 0xcd, 0x15, 0x9f, 0x4a, 0x93, 0x5e, 0x14, 0x88, 0xc4, 0x62, 0xfc, 0x99, 0x8c, 0x0b, 0x86, 0xf1, - 0x21, 0x42, 0xbd, 0x53, 0x30, 0x33, 0x8e, 0xeb, 0x17, 0x72, 0x4d, 0x0b, 0x53, 0xb2, 0x0a, 0x73, - 0xb9, 0xa4, 0x9b, 0xa9, 0x54, 0xf6, 0x23, 0xbf, 0x2f, 0x2c, 0x9a, 0x5f, 0x73, 0x4d, 0x73, 0x63, - 0x16, 0xb1, 0x53, 0x25, 0xe5, 0x9d, 0x85, 0x45, 0xfc, 0xcf, 0x79, 0x3f, 0xcc, 0x84, 0x69, 0x3b, - 0x32, 0xd2, 0x76, 0x16, 0x97, 0xb1, 0xf2, 0xb7, 0x8b, 0x13, 0xb9, 0x72, 0xa1, 0x14, 0x18, 0x5e, - 0xa3, 0x13, 0x81, 0x48, 0x53, 0x91, 0xa8, 0xb6, 0x1f, 0x86, 0x23, 0x36, 0x79, 0xba, 0x17, 0x96, - 0xc6, 0x4b, 0xbb, 0xd5, 0x4e, 0xac, 0x16, 0xe4, 0x89, 0x30, 0xf4, 0x36, 0xe1, 0x96, 0x11, 0x9d, - 0x75, 0x70, 0x5e, 0x26, 0xe7, 0xe2, 0x50, 0x77, 0x51, 0xbb, 0x0e, 0xfc, 0xff, 0xb2, 0x1f, 0x0e, - 0xce, 0x77, 0xc9, 0xd9, 0x22, 0x96, 0xdb, 0x82, 0xc6, 0xfb, 0x60, 0xfe, 0xbc, 0x48, 0x3a, 0x52, - 0x89, 0xb6, 0x78, 0x2a, 0xf3, 0x43, 0x07, 0xdd, 0x15, 0xd2, 0xcd, 0x11, 0xb8, 0x82, 0x1c, 0xba, - 0x8e, 0x41, 0x63, 0xdb, 0xef, 0x0a, 0x07, 0xc5, 0x55, 0x52, 0x4c, 0xe2, 0x7a, 0x44, 0x4f, 0xc0, - 0x74, 0x20, 0x8b, 0x5b, 0x72, 0xc0, 0xdf, 0x23, 0x7c, 0x8a, 0x19, 0x52, 0xc4, 0x32, 0xce, 0x42, - 0x3f, 0x75, 0xd9, 0xc1, 0xfb, 0xac, 0x60, 0x86, 0x14, 0x63, 0x94, 0xf5, 0x03, 0x56, 0x28, 0xa3, - 0x9e, 0xf7, 0xc2, 0x94, 0x8c, 0xc2, 0x1d, 0x19, 0xb9, 0x6c, 0xe2, 0x43, 0x32, 0x00, 0x21, 0x28, - 0x38, 0x0e, 0x4d, 0xd7, 0x46, 0x7c, 0x44, 0x78, 0x43, 0x70, 0x07, 0xf4, 0x39, 0xe3, 0x21, 0xa3, - 0x57, 0x38, 0x28, 0x3e, 0x26, 0xc5, 0xac, 0x81, 0xd1, 0x6d, 0xa4, 0x42, 0xa5, 0x81, 0x70, 0x91, - 0x7c, 0xc2, 0xb7, 0x41, 0x08, 0x95, 0xb2, 0x23, 0xa2, 0xee, 0x39, 0x37, 0xc3, 0xa7, 0x5c, 0x4a, - 0x66, 0x50, 0xa1, 0x27, 0x4f, 0xdf, 0x4f, 0xd4, 0x39, 0x3f, 0x74, 0x6a, 0xc7, 0x67, 0xe4, 0x98, - 0x2e, 0x21, 0xaa, 0x48, 0x16, 0x8d, 0xa3, 0xf9, 0x9c, 0x2b, 0x62, 0x60, 0x74, 0xf4, 0x54, 0xea, - 0x77, 0x42, 0xd1, 0x1e, 0xc7, 0xf6, 0x05, 0x1f, 0xbd, 0x82, 0x5d, 0x33, 0x8d, 0xba, 0xd3, 0xaa, - 0xf7, 0xb4, 0x93, 0xe6, 0x4b, 0xee, 0x74, 0x0e, 0x20, 0xfc, 0x18, 0xdc, 0x3a, 0x72, 0xd4, 0x3b, - 0xc8, 0xbe, 0x22, 0xd9, 0xd2, 0x88, 0x71, 0x4f, 0x23, 0x61, 0x5c, 0xe5, 0xd7, 0x3c, 0x12, 0x44, - 0xcd, 0xa5, 0xab, 0x96, 0x45, 0xca, 0xdf, 0x1e, 0xaf, 0x6a, 0xdf, 0x70, 0xd5, 0x0a, 0xb6, 0x52, - 0xb5, 0x87, 0x61, 0x89, 0x8c, 0xe3, 0xf5, 0xf5, 0x5b, 0x1e, 0xac, 0x05, 0xbd, 0x59, 0xed, 0xee, - 0xe3, 0x70, 0xa8, 0x2c, 0xe7, 0x85, 0x54, 0x44, 0x0a, 0x19, 0xbd, 0xe7, 0xd8, 0xc1, 0x7c, 0x8d, - 0xcc, 0x3c, 0xf1, 0x57, 0x4a, 0xc1, 0x9a, 0x1f, 0xa3, 0xfc, 0x51, 0x38, 0xc8, 0xf2, 0x2c, 0x4a, - 0x44, 0x57, 0x06, 0x91, 0x6e, 0xe3, 0x96, 0x83, 0xfa, 0xbb, 0x5a, 0xab, 0x36, 0x0d, 0x1c, 0xcd, - 0x67, 0xe0, 0xa6, 0xf2, 0xf7, 0x46, 0xbb, 0xd7, 0x8f, 0x65, 0x92, 0x5a, 0x8c, 0xdf, 0x73, 0xa7, - 0x4a, 0xee, 0x4c, 0x8e, 0x79, 0x2b, 0x30, 0x9b, 0xff, 0xe9, 0xfa, 0x48, 0xfe, 0x40, 0xa2, 0x99, - 0x01, 0x45, 0x83, 0xa3, 0x2b, 0xfb, 0xb1, 0x9f, 0xb8, 0xcc, 0xbf, 0x1f, 0x79, 0x70, 0x10, 0x52, - 0x3c, 0x7d, 0x73, 0xb5, 0x24, 0x6e, 0xdd, 0x31, 0x24, 0x59, 0x13, 0x4a, 0xf9, 0x41, 0xe9, 0x79, - 0x66, 0x8f, 0xce, 0x6c, 0x35, 0x88, 0xbd, 0xfb, 0xb1, 0x3c, 0xd5, 0xb8, 0xb4, 0xcb, 0x2e, 0xee, - 0x95, 0x15, 0xaa, 0xa4, 0xa5, 0x77, 0x1a, 0x66, 0x2a, 0x51, 0x69, 0x57, 0x3d, 0x4b, 0xaa, 0x69, - 0x33, 0x29, 0xbd, 0xbb, 0x60, 0x02, 0x63, 0xcf, 0x8e, 0x3f, 0x47, 0x78, 0xbe, 0xdc, 0xbb, 0x07, - 0x1a, 0x1c, 0x77, 0x76, 0xf4, 0x79, 0x42, 0x4b, 0x04, 0x71, 0x8e, 0x3a, 0x3b, 0xfe, 0x02, 0xe3, - 0x8c, 0x20, 0xee, 0x5e, 0xc2, 0x9f, 0x5e, 0x9a, 0xa0, 0x71, 0xc5, 0xb5, 0x3b, 0x0e, 0x93, 0x94, - 0x71, 0x76, 0xfa, 0x45, 0xfa, 0x72, 0x26, 0xbc, 0xbb, 0xe1, 0x80, 0x63, 0xc1, 0x5f, 0x26, 0xb4, - 0x58, 0xaf, 0x13, 0x64, 0xca, 0xc8, 0x35, 0x3b, 0xfe, 0x0a, 0xe1, 0x26, 0x85, 0x5b, 0xa7, 0x5c, - 0xb3, 0x0b, 0x5e, 0xe5, 0xad, 0x13, 0x81, 0x65, 0xe3, 0x48, 0xb3, 0xd3, 0xaf, 0x71, 0xd5, 0x19, - 0xd1, 0xa7, 0xa9, 0x59, 0x8e, 0x29, 0x3b, 0xff, 0x3a, 0xf1, 0x03, 0x06, 0x2b, 0x60, 0x8c, 0x49, - 0xbb, 0xe2, 0x0d, 0xae, 0x80, 0x41, 0xe1, 0x31, 0xaa, 0x47, 0x9f, 0xdd, 0xf4, 0x26, 0x1f, 0xa3, - 0x5a, 0xf2, 0x61, 0x37, 0xf3, 0x69, 0x61, 0x57, 0xbc, 0xc5, 0xdd, 0xcc, 0xd7, 0xe3, 0x36, 0xea, - 0x59, 0x62, 0x77, 0xbc, 0xcd, 0xdb, 0xa8, 0x45, 0x89, 0x4e, 0xa6, 0xd6, 0x70, 0x8e, 0xd8, 0x7d, - 0xef, 0x90, 0x6f, 0x7e, 0x28, 0x46, 0xbc, 0x47, 0x60, 0x69, 0x74, 0x86, 0xd8, 0xad, 0x97, 0xf6, - 0x6a, 0xbf, 0xfa, 0xcd, 0x08, 0xd1, 0x91, 0xb7, 0x38, 0x2a, 0x3f, 0xec, 0xda, 0xcb, 0x7b, 0xd5, - 0x17, 0x3b, 0x33, 0x3e, 0xf4, 0x2f, 0x34, 0x18, 0x8c, 0x6e, 0xbb, 0xeb, 0x0a, 0xb9, 0x0c, 0x08, - 0x8f, 0x06, 0x4d, 0x6e, 0x3b, 0x7f, 0x95, 0x8f, 0x06, 0x11, 0x1a, 0x6e, 0x44, 0x59, 0x18, 0xe2, - 0xc3, 0xd1, 0xba, 0x7d, 0x44, 0x4c, 0x88, 0x70, 0x8b, 0xd9, 0x3f, 0xf6, 0xe9, 0x60, 0x30, 0xa0, - 0x67, 0xe8, 0x01, 0xd1, 0xef, 0xe8, 0x1a, 0x58, 0xc8, 0x3f, 0xf7, 0x79, 0x20, 0xe0, 0x6a, 0x7d, - 0x9e, 0xa0, 0x78, 0x69, 0x4c, 0x77, 0x62, 0xeb, 0xb7, 0xfe, 0xb5, 0x5f, 0xbc, 0x83, 0x1a, 0xc8, - 0x40, 0x90, 0xbf, 0x75, 0x5a, 0x04, 0xbb, 0x55, 0x41, 0xfe, 0xa2, 0x79, 0x0c, 0x26, 0x9f, 0x50, - 0x32, 0x4a, 0xfd, 0xc0, 0x46, 0xff, 0x4d, 0x34, 0xaf, 0xc7, 0x82, 0xf5, 0x65, 0x22, 0xf4, 0xa5, - 0xb2, 0xb1, 0xff, 0x10, 0x5b, 0x02, 0x08, 0x77, 0x7d, 0x95, 0xba, 0xdc, 0xf7, 0xbf, 0x0c, 0x33, - 0x80, 0x9b, 0xc6, 0xeb, 0x27, 0xc5, 0x8e, 0x8d, 0xfd, 0x8f, 0x37, 0x4d, 0xeb, 0xf5, 0x00, 0x6c, - 0xe2, 0x65, 0xfe, 0xbe, 0x6d, 0x83, 0xff, 0x27, 0x78, 0x40, 0x9c, 0x3c, 0x02, 0x0b, 0xfa, 0x79, - 0xa9, 0x63, 0x27, 0x61, 0x55, 0xae, 0xca, 0xf5, 0xfc, 0x41, 0xbc, 0x1e, 0x00, 0x00, 0xff, 0xff, - 0x87, 0x5c, 0xee, 0x2b, 0x7e, 0x11, 0x00, 0x00, + // 1098 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x97, 0xc9, 0x6f, 0x1c, 0x45, + 0x14, 0x87, 0x85, 0x70, 0xe4, 0x99, 0xe7, 0x0d, 0x8f, 0x8d, 0x09, 0x11, 0x88, 0xe4, 0xc6, 0xc9, + 0x39, 0x45, 0x28, 0x65, 0x45, 0x96, 0x63, 0x39, 0xa3, 0x20, 0x0c, 0x23, 0x13, 0x07, 0x10, 0x87, + 0x51, 0xcf, 0xb8, 0xdc, 0x19, 0xe8, 0xee, 0x6a, 0xba, 0xba, 0xa3, 0x38, 0x37, 0x14, 0x16, 0x21, + 0xc4, 0x8e, 0x04, 0x09, 0x09, 0xcb, 0x81, 0x7d, 0x0d, 0xcb, 0x9d, 0x0b, 0x70, 0xe6, 0x7f, 0xe0, + 0x02, 0x98, 0x4d, 0xf2, 0xcd, 0x17, 0xf4, 0xba, 0xdf, 0xeb, 0xa9, 0x1e, 0x8f, 0x54, 0x35, 0xb7, + 0xf6, 0xb8, 0xbe, 0x6f, 0xaa, 0xdf, 0xeb, 0x7a, 0xbf, 0x69, 0x00, 0x5f, 0xf9, 0x6a, 0x31, 0x4e, + 0x54, 0xaa, 0x1a, 0x75, 0xbc, 0xce, 0x2f, 0x8f, 0x1c, 0xf5, 0x95, 0xf2, 0x03, 0x79, 0x3c, 0xff, + 0xab, 0x93, 0x6d, 0x1f, 0xdf, 0x92, 0xba, 0x9b, 0xf4, 0xe2, 0x54, 0x25, 0xc5, 0x62, 0xf1, 0x20, + 0xcc, 0xd1, 0xe2, 0xb6, 0x8c, 0xb2, 0xb0, 0x1d, 0x27, 0x72, 0xbb, 0x77, 0xa9, 0x71, 0xd7, 0x62, + 0x41, 0x2e, 0x32, 0xb9, 0xb8, 0x16, 0x65, 0xe1, 0x43, 0x71, 0xda, 0x53, 0x91, 0x3e, 0x7c, 0xf3, + 0xb7, 0x5b, 0x8f, 0xde, 0x72, 0x6f, 0x6d, 0x63, 0x96, 0x50, 0xfc, 0x5f, 0x2b, 0x07, 0xc5, 0x06, + 0xdc, 0x5e, 0xf1, 0xe9, 0x34, 0xe9, 0x45, 0xbe, 0x4c, 0x2c, 0xc6, 0x9f, 0xc8, 0x38, 0x67, 0x18, + 0x1f, 0x26, 0x54, 0xac, 0xc2, 0xd4, 0x28, 0xae, 0x9f, 0xc9, 0x35, 0x29, 0x4d, 0x49, 0x13, 0x66, + 0x72, 0x49, 0x37, 0xd3, 0xa9, 0x0a, 0x23, 0x2f, 0x94, 0x16, 0xcd, 0x2f, 0xb9, 0xa6, 0xbe, 0x31, + 0x8d, 0xd8, 0x6a, 0x49, 0x89, 0xf3, 0x30, 0x8f, 0x9f, 0x5c, 0xf4, 0x82, 0x4c, 0x9a, 0xb6, 0x63, + 0x43, 0x6d, 0xe7, 0x71, 0x19, 0x2b, 0x7f, 0xbd, 0x32, 0x96, 0x2b, 0xe7, 0x4a, 0x81, 0xe1, 0x35, + 0x3a, 0xe1, 0xcb, 0x34, 0x95, 0x89, 0x6e, 0x7b, 0x41, 0x30, 0x64, 0x93, 0x67, 0x7a, 0x41, 0x69, + 0xbc, 0xba, 0x5b, 0xed, 0x44, 0xb3, 0x20, 0x57, 0x82, 0x40, 0x6c, 0xc2, 0x1d, 0x43, 0x3a, 0xeb, + 0xe0, 0xbc, 0x46, 0xce, 0xf9, 0x03, 0xdd, 0x45, 0x6d, 0x0b, 0xf8, 0xf3, 0xb2, 0x1f, 0x0e, 0xce, + 0x77, 0xc8, 0xd9, 0x20, 0x96, 0xdb, 0x82, 0xc6, 0xfb, 0x61, 0xf6, 0xa2, 0x4c, 0x3a, 0x4a, 0xcb, + 0xb6, 0x7c, 0x2a, 0xf3, 0x02, 0x07, 0xdd, 0x75, 0xd2, 0xcd, 0x10, 0xb8, 0x86, 0x1c, 0xba, 0x4e, + 0x42, 0x6d, 0xdb, 0xeb, 0x4a, 0x07, 0xc5, 0x0d, 0x52, 0x8c, 0xe3, 0x7a, 0x44, 0x57, 0x60, 0xd2, + 0x57, 0xc5, 0x2d, 0x39, 0xe0, 0xef, 0x12, 0x3e, 0xc1, 0x0c, 0x29, 0x62, 0x15, 0x67, 0x81, 0x97, + 0xba, 0xec, 0xe0, 0x3d, 0x56, 0x30, 0x43, 0x8a, 0x11, 0xca, 0xfa, 0x3e, 0x2b, 0xb4, 0x51, 0xcf, + 0x65, 0x98, 0x50, 0x51, 0xb0, 0xa3, 0x22, 0x97, 0x4d, 0x7c, 0x40, 0x06, 0x20, 0x04, 0x05, 0x4b, + 0x50, 0x77, 0x6d, 0xc4, 0x87, 0x84, 0xd7, 0x24, 0x77, 0xa0, 0x09, 0x33, 0x3c, 0x64, 0x7a, 0x2a, + 0x72, 0x50, 0x7c, 0x44, 0x8a, 0x69, 0x03, 0xa3, 0xdb, 0x48, 0xa5, 0x4e, 0x7d, 0xe9, 0x22, 0xf9, + 0x98, 0x6f, 0x83, 0x10, 0x2a, 0x65, 0x47, 0x46, 0xdd, 0x0b, 0x6e, 0x86, 0x4f, 0xb8, 0x94, 0xcc, + 0xa0, 0x62, 0x15, 0xa6, 0x42, 0x2f, 0xd1, 0x17, 0xbc, 0xc0, 0xa9, 0x1d, 0x9f, 0x92, 0x63, 0xb2, + 0x84, 0xa8, 0x22, 0x59, 0x34, 0x8a, 0xe6, 0x33, 0xae, 0x88, 0x81, 0xd1, 0xd1, 0xd3, 0xa9, 0xd7, + 0x09, 0x64, 0x7b, 0x14, 0xdb, 0xe7, 0x7c, 0xf4, 0x0a, 0x76, 0xdd, 0x34, 0x2e, 0x41, 0x5d, 0xf7, + 0x2e, 0x3b, 0x69, 0xbe, 0xe0, 0x4e, 0xe7, 0x00, 0xc2, 0x8f, 0xc1, 0x9d, 0x43, 0x47, 0xbd, 0x83, + 0xec, 0x4b, 0x92, 0x2d, 0x0c, 0x19, 0xf7, 0x34, 0x12, 0x46, 0x55, 0x7e, 0xc5, 0x23, 0x41, 0x0e, + 0xb8, 0x5a, 0x30, 0x9f, 0x45, 0xda, 0xdb, 0x1e, 0xad, 0x6a, 0x5f, 0x73, 0xd5, 0x0a, 0xb6, 0x52, + 0xb5, 0x73, 0xb0, 0x40, 0xc6, 0xd1, 0xfa, 0xfa, 0x0d, 0x0f, 0xd6, 0x82, 0xde, 0xac, 0x76, 0xf7, + 0x71, 0x38, 0x52, 0x96, 0xf3, 0x52, 0x2a, 0x23, 0x8d, 0x4c, 0x3b, 0xf4, 0x62, 0x07, 0xf3, 0x4d, + 0x32, 0xf3, 0xc4, 0x5f, 0x2b, 0x05, 0xeb, 0x5e, 0x8c, 0xf2, 0x47, 0xe1, 0x30, 0xcb, 0xb3, 0x28, + 0x91, 0x5d, 0xe5, 0x47, 0xbd, 0xcb, 0x72, 0xcb, 0x41, 0xfd, 0xed, 0x40, 0xab, 0x36, 0x0d, 0x1c, + 0xcd, 0x67, 0xe1, 0xb6, 0xf2, 0xf7, 0x46, 0xbb, 0x17, 0xc6, 0x2a, 0x49, 0x2d, 0xc6, 0xef, 0xb8, + 0x53, 0x25, 0x77, 0x36, 0xc7, 0xc4, 0x1a, 0x4c, 0xe7, 0x7f, 0xba, 0x3e, 0x92, 0xdf, 0x93, 0x68, + 0xaa, 0x4f, 0xd1, 0xe0, 0xe8, 0xaa, 0x30, 0xf6, 0x12, 0x97, 0xf9, 0xf7, 0x03, 0x0f, 0x0e, 0x42, + 0x8a, 0xa7, 0x6f, 0x66, 0x20, 0x89, 0x1b, 0xf7, 0x1c, 0x90, 0xac, 0x4b, 0xad, 0x3d, 0xbf, 0xf4, + 0x3c, 0xbd, 0x47, 0x67, 0xb6, 0x1a, 0xc4, 0xe2, 0x01, 0x2c, 0x4f, 0x35, 0x2e, 0xed, 0xb2, 0x2b, + 0x7b, 0x65, 0x85, 0x2a, 0x69, 0x29, 0xce, 0xc0, 0x54, 0x25, 0x2a, 0xed, 0xaa, 0x67, 0x48, 0x35, + 0x69, 0x26, 0xa5, 0x38, 0x01, 0x63, 0x18, 0x7b, 0x76, 0xfc, 0x59, 0xc2, 0xf3, 0xe5, 0xe2, 0x14, + 0xd4, 0x38, 0xee, 0xec, 0xe8, 0x73, 0x84, 0x96, 0x08, 0xe2, 0x1c, 0x75, 0x76, 0xfc, 0x79, 0xc6, + 0x19, 0x41, 0xdc, 0xbd, 0x84, 0x3f, 0xbe, 0x38, 0x46, 0xe3, 0x8a, 0x6b, 0xb7, 0x04, 0xe3, 0x94, + 0x71, 0x76, 0xfa, 0x05, 0xfa, 0x72, 0x26, 0xc4, 0x7d, 0x70, 0xc8, 0xb1, 0xe0, 0x2f, 0x11, 0x5a, + 0xac, 0x17, 0xab, 0x30, 0x61, 0xe4, 0x9a, 0x1d, 0x7f, 0x99, 0x70, 0x93, 0xc2, 0xad, 0x53, 0xae, + 0xd9, 0x05, 0xaf, 0xf0, 0xd6, 0x89, 0xc0, 0xb2, 0x71, 0xa4, 0xd9, 0xe9, 0x57, 0xb9, 0xea, 0x8c, + 0x88, 0x65, 0xa8, 0x97, 0x63, 0xca, 0xce, 0xbf, 0x46, 0x7c, 0x9f, 0xc1, 0x0a, 0x18, 0x63, 0xd2, + 0xae, 0x78, 0x9d, 0x2b, 0x60, 0x50, 0x78, 0x8c, 0x06, 0xa3, 0xcf, 0x6e, 0x7a, 0x83, 0x8f, 0xd1, + 0x40, 0xf2, 0x61, 0x37, 0xf3, 0x69, 0x61, 0x57, 0xbc, 0xc9, 0xdd, 0xcc, 0xd7, 0xe3, 0x36, 0x06, + 0xb3, 0xc4, 0xee, 0x78, 0x8b, 0xb7, 0x31, 0x10, 0x25, 0xa2, 0x05, 0x8d, 0x83, 0x39, 0x62, 0xf7, + 0xbd, 0x4d, 0xbe, 0xd9, 0x03, 0x31, 0x22, 0x1e, 0x81, 0x85, 0xe1, 0x19, 0x62, 0xb7, 0x5e, 0xdd, + 0x1b, 0xf8, 0xd5, 0x6f, 0x46, 0x88, 0x38, 0xd7, 0xff, 0xd5, 0x6f, 0xe6, 0x87, 0x5d, 0x7b, 0x6d, + 0xaf, 0xfa, 0x62, 0x67, 0xc6, 0x87, 0x58, 0x01, 0xe8, 0x8f, 0x6e, 0xbb, 0xeb, 0x3a, 0xb9, 0x0c, + 0x08, 0x8f, 0x06, 0x4d, 0x6e, 0x3b, 0x7f, 0x83, 0x8f, 0x06, 0x11, 0x62, 0x09, 0x6a, 0x51, 0x16, + 0x04, 0xf8, 0x70, 0x34, 0xee, 0x1e, 0x12, 0x13, 0x32, 0xd8, 0x62, 0xf6, 0xf7, 0x7d, 0x3a, 0x18, + 0x0c, 0x88, 0x13, 0x70, 0x48, 0x86, 0x1d, 0xb9, 0x65, 0x23, 0xff, 0xd8, 0xe7, 0x81, 0x80, 0xab, + 0xc5, 0x32, 0x40, 0xf1, 0xd2, 0x98, 0xee, 0xc4, 0xd6, 0x6f, 0xfd, 0x73, 0xbf, 0x78, 0x07, 0x35, + 0x90, 0xbe, 0x20, 0x7f, 0xeb, 0xb4, 0x08, 0x76, 0xab, 0x82, 0xfc, 0x45, 0xf3, 0x24, 0x8c, 0x3f, + 0xa1, 0x55, 0x94, 0x7a, 0xbe, 0x8d, 0xfe, 0x8b, 0x68, 0x5e, 0x8f, 0x05, 0x0b, 0x55, 0x22, 0x53, + 0xcf, 0xd7, 0x36, 0xf6, 0x6f, 0x62, 0x4b, 0x00, 0xe1, 0xae, 0xa7, 0x53, 0x97, 0xfb, 0xfe, 0x87, + 0x61, 0x06, 0x70, 0xd3, 0x78, 0xfd, 0xa4, 0xdc, 0xb1, 0xb1, 0xff, 0xf2, 0xa6, 0x69, 0xbd, 0x38, + 0x05, 0x75, 0xbc, 0xcc, 0xdf, 0xb7, 0x6d, 0xf0, 0x7f, 0x04, 0xf7, 0x89, 0xd3, 0xc7, 0x60, 0xae, + 0xab, 0xc2, 0x41, 0xec, 0x34, 0x34, 0x55, 0x53, 0xb5, 0xf2, 0x07, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x87, 0x5c, 0xee, 0x2b, 0x7e, 0x11, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.proto b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.proto index e8e3edb61f..18a58c5d4c 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.proto +++ b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/gogo.proto @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/helper.go b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/helper.go index 8c29dbc0e1..670021fedd 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/helper.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/gogoproto/helper.go @@ -1,4 +1,6 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. // http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/clone.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/clone.go index 79edb86119..5d4cba4b51 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/clone.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/clone.go @@ -84,14 +84,20 @@ func mergeStruct(out, in reflect.Value) { mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } - if emIn, ok := in.Addr().Interface().(extensionsMap); ok { - emOut := out.Addr().Interface().(extensionsMap) - mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) - } else if emIn, ok := in.Addr().Interface().(extensionsBytes); ok { + if emIn, ok := in.Addr().Interface().(extensionsBytes); ok { emOut := out.Addr().Interface().(extensionsBytes) bIn := emIn.GetExtensions() bOut := emOut.GetExtensions() *bOut = append(*bOut, *bIn...) + } else if emIn, ok := extendable(in.Addr().Interface()); ok { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } } uf := in.FieldByName("XXX_unrecognized") diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode.go index cb5b213f9b..0d6634cc08 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode.go @@ -378,6 +378,11 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group wire := int(u & 0x7) if wire == WireEndGroup { if is_group { + if required > 0 { + // Not enough information to determine the exact field. + // (See below.) + return &RequiredNotSetError{"{Unknown}"} + } return nil // input is satisfied } return fmt.Errorf("proto: %s: wiretype end group for non-group", st) @@ -390,16 +395,20 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group if !ok { // Maybe it's an extension? if prop.extendable { - if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) { - if err = o.skip(st, tag, wire); err == nil { - if ee, eok := e.(extensionsMap); eok { - ext := ee.ExtensionMap()[int32(tag)] // may be missing - ext.enc = append(ext.enc, o.buf[oi:o.index]...) - ee.ExtensionMap()[int32(tag)] = ext - } else if ee, eok := e.(extensionsBytes); eok { - ext := ee.GetExtensions() + if e, eok := structPointer_Interface(base, st).(extensionsBytes); eok { + if isExtensionField(e, int32(tag)) { + if err = o.skip(st, tag, wire); err == nil { + ext := e.GetExtensions() *ext = append(*ext, o.buf[oi:o.index]...) } + continue + } + } else if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { + if err = o.skip(st, tag, wire); err == nil { + extmap := e.extensionsWrite() + ext := extmap[int32(tag)] // may be missing + ext.enc = append(ext.enc, o.buf[oi:o.index]...) + extmap[int32(tag)] = ext } continue } @@ -773,10 +782,11 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { } } keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() || !valelem.IsValid() { - // We did not decode the key or the value in the map entry. - // Either way, it's an invalid map entry. - return fmt.Errorf("proto: bad map data: missing key/val") + if !keyelem.IsValid() { + keyelem = reflect.Zero(p.mtype.Key()) + } + if !valelem.IsValid() { + valelem = reflect.Zero(p.mtype.Elem()) } v.SetMapIndex(keyelem, valelem) diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode_gogo.go index 603dabec3f..ecc63873e4 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/decode_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode.go index 231b07401a..8c1b8fd1f6 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode.go @@ -64,8 +64,16 @@ var ( // a struct with a repeated field containing a nil element. errRepeatedHasNil = errors.New("proto: repeated field has nil element") + // errOneofHasNil is the error returned if Marshal is called with + // a struct with a oneof field containing a nil element. + errOneofHasNil = errors.New("proto: oneof field has nil value") + // ErrNil is the error returned if Marshal is called with nil. ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") ) // The fundamental encoders that put bytes on the wire. @@ -74,6 +82,10 @@ var ( const maxVarintBytes = 10 // maximum length of a varint +// maxMarshalSize is the largest allowed size of an encoded protobuf, +// since C++ and Java use signed int32s for the size. +const maxMarshalSize = 1<<31 - 1 + // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum @@ -273,6 +285,9 @@ func (p *Buffer) Marshal(pb Message) error { stats.Encode++ } + if len(p.buf) > maxMarshalSize { + return ErrTooLarge + } return err } @@ -1058,10 +1073,25 @@ func size_slice_struct_group(p *Properties, base structPointer) (n int) { // Encode an extension map. func (o *Buffer) enc_map(p *Properties, base structPointer) error { - v := *structPointer_ExtMap(base, p.field) - if err := encodeExtensionMap(v); err != nil { + exts := structPointer_ExtMap(base, p.field) + if err := encodeExtensionsMap(*exts); err != nil { return err } + + return o.enc_map_body(*exts) +} + +func (o *Buffer) enc_exts(p *Properties, base structPointer) error { + exts := structPointer_Extensions(base, p.field) + if err := encodeExtensions(exts); err != nil { + return err + } + v, _ := exts.extensionsRead() + + return o.enc_map_body(v) +} + +func (o *Buffer) enc_map_body(v map[int32]Extension) error { // Fast-path for common cases: zero or one extensions. if len(v) <= 1 { for _, e := range v { @@ -1084,8 +1114,13 @@ func (o *Buffer) enc_map(p *Properties, base structPointer) error { } func size_map(p *Properties, base structPointer) int { - v := *structPointer_ExtMap(base, p.field) - return sizeExtensionMap(v) + v := structPointer_ExtMap(base, p.field) + return extensionsMapSize(*v) +} + +func size_exts(p *Properties, base structPointer) int { + v := structPointer_Extensions(base, p.field) + return extensionsSize(v) } // Encode a map field. @@ -1114,7 +1149,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { return err } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { + if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { return err } return nil @@ -1124,11 +1159,6 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { for _, key := range v.MapKeys() { val := v.MapIndex(key) - // The only illegal map entry values are nil message pointers. - if val.Kind() == reflect.Ptr && val.IsNil() { - return errors.New("proto: map has nil element") - } - keycopy.Set(key) valcopy.Set(val) @@ -1216,13 +1246,18 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { return err } } + if len(o.buf) > maxMarshalSize { + return ErrTooLarge + } } } // Do oneof fields. if prop.oneofMarshaler != nil { m := structPointer_Interface(base, prop.stype).(Message) - if err := prop.oneofMarshaler(m, o); err != nil { + if err := prop.oneofMarshaler(m, o); err == ErrNil { + return errOneofHasNil + } else if err != nil { return err } } @@ -1230,6 +1265,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { // Add unrecognized fields at the end. if prop.unrecField.IsValid() { v := *structPointer_Bytes(base, prop.unrecField) + if len(o.buf)+len(v) > maxMarshalSize { + return ErrTooLarge + } if len(v) > 0 { o.buf = append(o.buf, v...) } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode_gogo.go index f77cfb1eea..66e7e16303 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/encode_gogo.go @@ -1,7 +1,7 @@ -// Extensions for Protocol Buffers to create more go like structures. +// Protocol Buffers for Go with Gadgets // -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Go support for Protocol Buffers - Google's data interchange format // diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/equal.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/equal.go index f5db1def3c..8b16f951c7 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/equal.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/equal.go @@ -121,9 +121,16 @@ func equalStruct(v1, v2 reflect.Value) bool { } } + if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_InternalExtensions") + if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { + return false + } + } + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { em2 := v2.FieldByName("XXX_extensions") - if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { return false } } @@ -184,6 +191,13 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool { } return true case reflect.Ptr: + // Maps may have nil values in them, so check for nil. + if v1.IsNil() && v2.IsNil() { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } return equalAny(v1.Elem(), v2.Elem(), prop) case reflect.Slice: if v1.Type().Elem().Kind() == reflect.Uint8 { @@ -223,8 +237,14 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool { } // base is the struct type that the extensions are based on. -// em1 and em2 are extension maps. -func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool { +// x1 and x2 are InternalExtensions. +func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { + em1, _ := x1.extensionsRead() + em2, _ := x2.extensionsRead() + return equalExtMap(base, em1, em2) +} + +func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { if len(em1) != len(em2) { return false } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions.go index 6180347e39..f7384baa87 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions.go @@ -52,23 +52,112 @@ type ExtensionRange struct { Start, End int32 // both inclusive } -// extendableProto is an interface implemented by any protocol buffer that may be extended. +// extendableProto is an interface implemented by any protocol buffer generated by the current +// proto compiler that may be extended. type extendableProto interface { Message ExtensionRangeArray() []ExtensionRange + extensionsWrite() map[int32]Extension + extensionsRead() (map[int32]Extension, sync.Locker) } -type extensionsMap interface { - extendableProto +// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous +// version of the proto compiler that may be extended. +type extendableProtoV1 interface { + Message + ExtensionRangeArray() []ExtensionRange ExtensionMap() map[int32]Extension } type extensionsBytes interface { - extendableProto + Message + ExtensionRangeArray() []ExtensionRange GetExtensions() *[]byte } +// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. +type extensionAdapter struct { + extendableProtoV1 +} + +func (e extensionAdapter) extensionsWrite() map[int32]Extension { + return e.ExtensionMap() +} + +func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + return e.ExtensionMap(), notLocker{} +} + +// notLocker is a sync.Locker whose Lock and Unlock methods are nops. +type notLocker struct{} + +func (n notLocker) Lock() {} +func (n notLocker) Unlock() {} + +// extendable returns the extendableProto interface for the given generated proto message. +// If the proto message has the old extension format, it returns a wrapper that implements +// the extendableProto interface. +func extendable(p interface{}) (extendableProto, bool) { + if ep, ok := p.(extendableProto); ok { + return ep, ok + } + if ep, ok := p.(extendableProtoV1); ok { + return extensionAdapter{ep}, ok + } + return nil, false +} + +// XXX_InternalExtensions is an internal representation of proto extensions. +// +// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, +// thus gaining the unexported 'extensions' method, which can be called only from the proto package. +// +// The methods of XXX_InternalExtensions are not concurrency safe in general, +// but calls to logically read-only methods such as has and get may be executed concurrently. +type XXX_InternalExtensions struct { + // The struct must be indirect so that if a user inadvertently copies a + // generated message and its embedded XXX_InternalExtensions, they + // avoid the mayhem of a copied mutex. + // + // The mutex serializes all logically read-only operations to p.extensionMap. + // It is up to the client to ensure that write operations to p.extensionMap are + // mutually exclusive with other accesses. + p *struct { + mu sync.Mutex + extensionMap map[int32]Extension + } +} + +// extensionsWrite returns the extension map, creating it on first use. +func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { + if e.p == nil { + e.p = new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }) + e.p.extensionMap = make(map[int32]Extension) + } + return e.p.extensionMap +} + +// extensionsRead returns the extensions map for read-only use. It may be nil. +// The caller must hold the returned mutex's lock when accessing Elements within the map. +func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { + if e.p == nil { + return nil, nil + } + return e.p.extensionMap, &e.p.mu +} + +type extensionRange interface { + Message + ExtensionRangeArray() []ExtensionRange +} + var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() +var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() +var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem() +var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem() // ExtensionDesc represents an extension specification. // Used in generated code from the protocol compiler. @@ -101,20 +190,23 @@ type Extension struct { } // SetRawExtension is for testing only. -func SetRawExtension(base extendableProto, id int32, b []byte) { - if ebase, ok := base.(extensionsMap); ok { - ebase.ExtensionMap()[id] = Extension{enc: b} - } else if ebase, ok := base.(extensionsBytes); ok { +func SetRawExtension(base Message, id int32, b []byte) { + if ebase, ok := base.(extensionsBytes); ok { clearExtension(base, id) ext := ebase.GetExtensions() *ext = append(*ext, b...) - } else { - panic("unreachable") + return } + epb, ok := extendable(base) + if !ok { + return + } + extmap := epb.extensionsWrite() + extmap[id] = Extension{enc: b} } // isExtensionField returns true iff the given field number is in an extension range. -func isExtensionField(pb extendableProto, field int32) bool { +func isExtensionField(pb extensionRange, field int32) bool { for _, er := range pb.ExtensionRangeArray() { if er.Start <= field && field <= er.End { return true @@ -125,8 +217,12 @@ func isExtensionField(pb extendableProto, field int32) bool { // checkExtensionTypes checks that the given extension is valid for pb. func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + var pbi interface{} = pb // Check the extended type. - if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b { + if ea, ok := pbi.(extensionAdapter); ok { + pbi = ea.extendableProtoV1 + } + if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) } // Check the range. @@ -172,43 +268,57 @@ func extensionProperties(ed *ExtensionDesc) *Properties { return prop } -// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. -func encodeExtensionMap(m map[int32]Extension) error { +// encode encodes any unmarshaled (unencoded) extensions in e. +func encodeExtensions(e *XXX_InternalExtensions) error { + m, mu := e.extensionsRead() + if m == nil { + return nil // fast path + } + mu.Lock() + defer mu.Unlock() + return encodeExtensionsMap(m) +} + +// encode encodes any unmarshaled (unencoded) extensions in e. +func encodeExtensionsMap(m map[int32]Extension) error { for k, e := range m { - err := encodeExtension(&e) - if err != nil { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + continue + } + + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + et := reflect.TypeOf(e.desc.ExtensionType) + props := extensionProperties(e.desc) + + p := NewBuffer(nil) + // If e.value has type T, the encoder expects a *struct{ X T }. + // Pass a *T with a zero field and hope it all works out. + x := reflect.New(et) + x.Elem().Set(reflect.ValueOf(e.value)) + if err := props.enc(p, props, toStructPointer(x)); err != nil { return err } + e.enc = p.buf m[k] = e } return nil } -func encodeExtension(e *Extension) error { - if e.value == nil || e.desc == nil { - // Extension is only in its encoded form. - return nil +func extensionsSize(e *XXX_InternalExtensions) (n int) { + m, mu := e.extensionsRead() + if m == nil { + return 0 } - // We don't skip extensions that have an encoded form set, - // because the extension value may have been mutated after - // the last time this function was called. - - et := reflect.TypeOf(e.desc.ExtensionType) - props := extensionProperties(e.desc) - - p := NewBuffer(nil) - // If e.value has type T, the encoder expects a *struct{ X T }. - // Pass a *T with a zero field and hope it all works out. - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(e.value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - e.enc = p.buf - return nil + mu.Lock() + defer mu.Unlock() + return extensionsMapSize(m) } -func sizeExtensionMap(m map[int32]Extension) (n int) { +func extensionsMapSize(m map[int32]Extension) (n int) { for _, e := range m { if e.value == nil || e.desc == nil { // Extension is only in its encoded form. @@ -233,12 +343,8 @@ func sizeExtensionMap(m map[int32]Extension) (n int) { } // HasExtension returns whether the given extension is present in pb. -func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { - // TODO: Check types, field numbers, etc.? - if epb, doki := pb.(extensionsMap); doki { - _, ok := epb.ExtensionMap()[extension.Field] - return ok - } else if epb, doki := pb.(extensionsBytes); doki { +func HasExtension(pb Message, extension *ExtensionDesc) bool { + if epb, doki := pb.(extensionsBytes); doki { ext := epb.GetExtensions() buf := *ext o := 0 @@ -258,7 +364,19 @@ func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { } return false } - panic("unreachable") + // TODO: Check types, field numbers, etc.? + epb, ok := extendable(pb) + if !ok { + return false + } + extmap, mu := epb.extensionsRead() + if extmap == nil { + return false + } + mu.Lock() + _, ok = extmap[extension.Field] + mu.Unlock() + return ok } func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int { @@ -281,64 +399,32 @@ func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int { return -1 } -func clearExtension(pb extendableProto, fieldNum int32) { - if epb, doki := pb.(extensionsMap); doki { - delete(epb.ExtensionMap(), fieldNum) - } else if epb, doki := pb.(extensionsBytes); doki { +// ClearExtension removes the given extension from pb. +func ClearExtension(pb Message, extension *ExtensionDesc) { + clearExtension(pb, extension.Field) +} + +func clearExtension(pb Message, fieldNum int32) { + if epb, doki := pb.(extensionsBytes); doki { offset := 0 for offset != -1 { offset = deleteExtension(epb, fieldNum, offset) } - } else { - panic("unreachable") + return + } + epb, ok := extendable(pb) + if !ok { + return } -} - -// ClearExtension removes the given extension from pb. -func ClearExtension(pb extendableProto, extension *ExtensionDesc) { // TODO: Check types, field numbers, etc.? - clearExtension(pb, extension.Field) + extmap := epb.extensionsWrite() + delete(extmap, fieldNum) } // GetExtension parses and returns the given extension of pb. -// If the extension is not present it returns ErrMissingExtension. -func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { - if err := checkExtensionTypes(pb, extension); err != nil { - return nil, err - } - - if epb, doki := pb.(extensionsMap); doki { - emap := epb.ExtensionMap() - e, ok := emap[extension.Field] - if !ok { - // defaultExtensionValue returns the default value or - // ErrMissingExtension if there is no default. - return defaultExtensionValue(extension) - } - if e.value != nil { - // Already decoded. Check the descriptor, though. - if e.desc != extension { - // This shouldn't happen. If it does, it means that - // GetExtension was called twice with two different - // descriptors with the same field number. - return nil, errors.New("proto: descriptor conflict") - } - return e.value, nil - } - - v, err := decodeExtension(e.enc, extension) - if err != nil { - return nil, err - } - - // Remember the decoded version and drop the encoded version. - // That way it is safe to mutate what we return. - e.value = v - e.desc = extension - e.enc = nil - emap[extension.Field] = e - return e.value, nil - } else if epb, doki := pb.(extensionsBytes); doki { +// If the extension is not present and has no default value it returns ErrMissingExtension. +func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { + if epb, doki := pb.(extensionsBytes); doki { ext := epb.GetExtensions() o := 0 for o < len(*ext) { @@ -360,7 +446,50 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er } return defaultExtensionValue(extension) } - panic("unreachable") + epb, ok := extendable(pb) + if !ok { + return nil, errors.New("proto: not an extendable proto") + } + if err := checkExtensionTypes(epb, extension); err != nil { + return nil, err + } + + emap, mu := epb.extensionsRead() + if emap == nil { + return defaultExtensionValue(extension) + } + mu.Lock() + defer mu.Unlock() + e, ok := emap[extension.Field] + if !ok { + // defaultExtensionValue returns the default value or + // ErrMissingExtension if there is no default. + return defaultExtensionValue(extension) + } + + if e.value != nil { + // Already decoded. Check the descriptor, though. + if e.desc != extension { + // This shouldn't happen. If it does, it means that + // GetExtension was called twice with two different + // descriptors with the same field number. + return nil, errors.New("proto: descriptor conflict") + } + return e.value, nil + } + + v, err := decodeExtension(e.enc, extension) + if err != nil { + return nil, err + } + + // Remember the decoded version and drop the encoded version. + // That way it is safe to mutate what we return. + e.value = v + e.desc = extension + e.enc = nil + emap[extension.Field] = e + return e.value, nil } // defaultExtensionValue returns the default value for extension. @@ -434,14 +563,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { // GetExtensions returns a slice of the extensions present in pb that are also listed in es. // The returned slice has the same length as es; missing extensions will appear as nil elements. func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { - epb, ok := pb.(extendableProto) - if !ok { - err = errors.New("proto: not an extendable proto") - return - } extensions = make([]interface{}, len(es)) for i, e := range es { - extensions[i], err = GetExtension(epb, e) + extensions[i], err = GetExtension(pb, e) if err == ErrMissingExtension { err = nil } @@ -452,9 +576,55 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e return } +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing +// just the Field field, which defines the extension's field number. +func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { + epb, ok := extendable(pb) + if !ok { + return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + // SetExtension sets the specified extension of pb to the specified value. -func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { - if err := checkExtensionTypes(pb, extension); err != nil { +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + if epb, doki := pb.(extensionsBytes); doki { + ClearExtension(pb, extension) + ext := epb.GetExtensions() + et := reflect.TypeOf(extension.ExtensionType) + props := extensionProperties(extension) + p := NewBuffer(nil) + x := reflect.New(et) + x.Elem().Set(reflect.ValueOf(value)) + if err := props.enc(p, props, toStructPointer(x)); err != nil { + return err + } + *ext = append(*ext, p.buf...) + return nil + } + epb, ok := extendable(pb) + if !ok { + return errors.New("proto: not an extendable proto") + } + if err := checkExtensionTypes(epb, extension); err != nil { return err } typ := reflect.TypeOf(extension.ExtensionType) @@ -469,26 +639,27 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{ if reflect.ValueOf(value).IsNil() { return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) } - return setExtension(pb, extension, value) + + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: value} + return nil } -func setExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { - if epb, doki := pb.(extensionsMap); doki { - epb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value} - } else if epb, doki := pb.(extensionsBytes); doki { - ClearExtension(pb, extension) +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + if epb, doki := pb.(extensionsBytes); doki { ext := epb.GetExtensions() - et := reflect.TypeOf(extension.ExtensionType) - props := extensionProperties(extension) - p := NewBuffer(nil) - x := reflect.New(et) - x.Elem().Set(reflect.ValueOf(value)) - if err := props.enc(p, props, toStructPointer(x)); err != nil { - return err - } - *ext = append(*ext, p.buf...) + *ext = []byte{} + return + } + epb, ok := extendable(pb) + if !ok { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) } - return nil } // A global registry of extensions. diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions_gogo.go index 86b1fa2344..ea6478f009 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/extensions_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -33,9 +35,10 @@ import ( "reflect" "sort" "strings" + "sync" ) -func GetBoolExtension(pb extendableProto, extension *ExtensionDesc, ifnotset bool) bool { +func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool { if reflect.ValueOf(pb).IsNil() { return ifnotset } @@ -60,8 +63,12 @@ func (this *Extension) Compare(that *Extension) int { return bytes.Compare(this.enc, that.enc) } +func SizeOfInternalExtension(m extendableProto) (n int) { + return SizeOfExtensionMap(m.extensionsWrite()) +} + func SizeOfExtensionMap(m map[int32]Extension) (n int) { - return sizeExtensionMap(m) + return extensionsMapSize(m) } type sortableMapElem struct { @@ -94,6 +101,10 @@ func (this sortableExtensions) String() string { return "map[" + strings.Join(ss, ",") + "]" } +func StringFromInternalExtension(m extendableProto) string { + return StringFromExtensionsMap(m.extensionsWrite()) +} + func StringFromExtensionsMap(m map[int32]Extension) string { return newSortableExtensionsFromMap(m).String() } @@ -106,8 +117,12 @@ func StringFromExtensionsBytes(ext []byte) string { return StringFromExtensionsMap(m) } +func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) { + return EncodeExtensionMap(m.extensionsWrite(), data) +} + func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) { - if err := encodeExtensionMap(m); err != nil { + if err := encodeExtensionsMap(m); err != nil { return 0, err } keys := make([]int, 0, len(m)) @@ -125,7 +140,7 @@ func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) { if m[id].value == nil || m[id].desc == nil { return m[id].enc, nil } - if err := encodeExtensionMap(m); err != nil { + if err := encodeExtensionsMap(m); err != nil { return nil, err } return m[id].enc, nil @@ -189,15 +204,42 @@ func NewExtension(e []byte) Extension { return ee } -func AppendExtension(e extendableProto, tag int32, buf []byte) { - if ee, eok := e.(extensionsMap); eok { - ext := ee.ExtensionMap()[int32(tag)] // may be missing - ext.enc = append(ext.enc, buf...) - ee.ExtensionMap()[int32(tag)] = ext - } else if ee, eok := e.(extensionsBytes); eok { +func AppendExtension(e Message, tag int32, buf []byte) { + if ee, eok := e.(extensionsBytes); eok { ext := ee.GetExtensions() *ext = append(*ext, buf...) + return } + if ee, eok := e.(extendableProto); eok { + m := ee.extensionsWrite() + ext := m[int32(tag)] // may be missing + ext.enc = append(ext.enc, buf...) + m[int32(tag)] = ext + } +} + +func encodeExtension(e *Extension) error { + if e.value == nil || e.desc == nil { + // Extension is only in its encoded form. + return nil + } + // We don't skip extensions that have an encoded form set, + // because the extension value may have been mutated after + // the last time this function was called. + + et := reflect.TypeOf(e.desc.ExtensionType) + props := extensionProperties(e.desc) + + p := NewBuffer(nil) + // If e.value has type T, the encoder expects a *struct{ X T }. + // Pass a *T with a zero field and hope it all works out. + x := reflect.New(et) + x.Elem().Set(reflect.ValueOf(e.value)) + if err := props.enc(p, props, toStructPointer(x)); err != nil { + return err + } + e.enc = p.buf + return nil } func (this Extension) GoString() string { @@ -209,7 +251,7 @@ func (this Extension) GoString() string { return fmt.Sprintf("proto.NewExtension(%#v)", this.enc) } -func SetUnsafeExtension(pb extendableProto, fieldNum int32, value interface{}) error { +func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error { typ := reflect.TypeOf(pb).Elem() ext, ok := extensionMaps[typ] if !ok { @@ -219,10 +261,10 @@ func SetUnsafeExtension(pb extendableProto, fieldNum int32, value interface{}) e if !ok { return errors.New("proto: bad extension number; not in declared ranges") } - return setExtension(pb, desc, value) + return SetExtension(pb, desc, value) } -func GetUnsafeExtension(pb extendableProto, fieldNum int32) (interface{}, error) { +func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) { typ := reflect.TypeOf(pb).Elem() ext, ok := extensionMaps[typ] if !ok { @@ -234,3 +276,19 @@ func GetUnsafeExtension(pb extendableProto, fieldNum int32) (interface{}, error) } return GetExtension(pb, desc) } + +func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions { + x := &XXX_InternalExtensions{ + p: new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }), + } + x.p.extensionMap = m + return *x +} + +func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension { + pb := extendable.(extendableProto) + return pb.extensionsWrite() +} diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib.go index 2e35ae2d2a..2c30d70951 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib.go @@ -889,6 +889,10 @@ func isProto3Zero(v reflect.Value) bool { return false } +// ProtoPackageIsVersion2 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const GoGoProtoPackageIsVersion2 = true + // ProtoPackageIsVersion1 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the proto package. const GoGoProtoPackageIsVersion1 = true diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib_gogo.go index a6c2c06b23..4b4f7c909e 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/lib_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/message_set.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/message_set.go index e25e01e637..fd982decd6 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/message_set.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/message_set.go @@ -149,9 +149,21 @@ func skipVarint(buf []byte) []byte { // MarshalMessageSet encodes the extension map represented by m in the message set wire format. // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { - if err := encodeExtensionMap(m); err != nil { - return nil, err +func MarshalMessageSet(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + if err := encodeExtensions(exts); err != nil { + return nil, err + } + m, _ = exts.extensionsRead() + case map[int32]Extension: + if err := encodeExtensionsMap(exts); err != nil { + return nil, err + } + m = exts + default: + return nil, errors.New("proto: not an extension map") } // Sort extension IDs to provide a deterministic encoding. @@ -178,7 +190,17 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { +func UnmarshalMessageSet(buf []byte, exts interface{}) error { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + ms := new(messageSet) if err := Unmarshal(buf, ms); err != nil { return err @@ -209,7 +231,16 @@ func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { // MarshalMessageSetJSON encodes the extension map represented by m in JSON format. // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { +func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m, _ = exts.extensionsRead() + case map[int32]Extension: + m = exts + default: + return nil, errors.New("proto: not an extension map") + } var b bytes.Buffer b.WriteByte('{') @@ -252,7 +283,7 @@ func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { +func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { // Common-case fast path. if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { return nil diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_reflect.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_reflect.go index 749919d250..fb512e2e16 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_reflect.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_reflect.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build appengine +// +build appengine js // This file contains an implementation of proto field accesses using package reflect. // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can @@ -139,6 +139,11 @@ func structPointer_StringSlice(p structPointer, f field) *[]string { return structPointer_ifield(p, f).(*[]string) } +// Extensions returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return structPointer_ifield(p, f).(*XXX_InternalExtensions) +} + // ExtMap returns the address of an extension map field in the struct. func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return structPointer_ifield(p, f).(*map[int32]Extension) diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe.go index e9be0fe92e..6b5567d47c 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build !appengine +// +build !appengine,!js // This file contains the implementation of the proto field accesses using package unsafe. @@ -126,6 +126,10 @@ func structPointer_StringSlice(p structPointer, f field) *[]string { } // ExtMap returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go index 6bc85fa987..ad7c851793 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -70,16 +72,13 @@ func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) { func appendStructPointer(base structPointer, f field, typ reflect.Type) structPointer { size := typ.Elem().Size() - oldHeader := structPointer_GetSliceHeader(base, f) - newLen := oldHeader.Len + 1 - slice := reflect.MakeSlice(typ, newLen, newLen) - bas := toStructPointer(slice) - for i := 0; i < oldHeader.Len; i++ { - newElemptr := uintptr(bas) + uintptr(i)*size - oldElemptr := oldHeader.Data + uintptr(i)*size - copyUintPtr(oldElemptr, newElemptr, int(size)) - } + oldHeader := structPointer_GetSliceHeader(base, f) + oldSlice := reflect.NewAt(typ, unsafe.Pointer(oldHeader)).Elem() + newLen := oldHeader.Len + 1 + newSlice := reflect.MakeSlice(typ, newLen, newLen) + reflect.Copy(newSlice, oldSlice) + bas := toStructPointer(newSlice) oldHeader.Data = uintptr(bas) oldHeader.Len = newLen oldHeader.Cap = newLen diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties.go index 5e6a0b3ba7..3e4cad0381 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties.go @@ -1,7 +1,7 @@ -// Extensions for Protocol Buffers to create more go like structures. +// Protocol Buffers for Go with Gadgets // -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Go support for Protocol Buffers - Google's data interchange format // @@ -542,17 +542,13 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock p.dec = (*Buffer).dec_slice_int64 p.packedDec = (*Buffer).dec_slice_packed_int64 case reflect.Uint8: - p.enc = (*Buffer).enc_slice_byte p.dec = (*Buffer).dec_slice_byte - p.size = size_slice_byte - // This is a []byte, which is either a bytes field, - // or the value of a map field. In the latter case, - // we always encode an empty []byte, so we should not - // use the proto3 enc/size funcs. - // f == nil iff this is the key/value of a map field. - if p.proto3 && f != nil { + if p.proto3 { p.enc = (*Buffer).enc_proto3_slice_byte p.size = size_proto3_slice_byte + } else { + p.enc = (*Buffer).enc_slice_byte + p.size = size_slice_byte } case reflect.Float32, reflect.Float64: switch t2.Bits() { @@ -744,7 +740,9 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { propertiesMap[t] = prop // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) + prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || + reflect.PtrTo(t).Implements(extendableProtoV1Type) || + reflect.PtrTo(t).Implements(extendableBytesType) prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) @@ -756,7 +754,11 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { name := f.Name p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) - if f.Name == "XXX_extensions" { // special case + if f.Name == "XXX_InternalExtensions" { // special case + p.enc = (*Buffer).enc_exts + p.dec = nil // not needed + p.size = size_exts + } else if f.Name == "XXX_extensions" { // special case if len(f.Tag.Get("protobuf")) > 0 { p.enc = (*Buffer).enc_ext_slice_byte p.dec = nil // not needed @@ -766,13 +768,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { p.dec = nil // not needed p.size = size_map } - } - if f.Name == "XXX_unrecognized" { // special case + } else if f.Name == "XXX_unrecognized" { // special case prop.unrecField = toField(&f) } - oneof := f.Tag.Get("protobuf_oneof") != "" // special case - if oneof { + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { isOneofMessage = true + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof } prop.Prop[i] = p prop.order[i] = i @@ -783,7 +786,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } print("\n") } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof { + if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") } } @@ -921,3 +924,17 @@ func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] } // MessageType returns the message type (pointer to struct) for a named message. func MessageType(name string) reflect.Type { return protoTypes[name] } + +// A registry of all linked proto files. +var ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties_gogo.go index 8daf9f7768..4607a97541 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/properties_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/skip_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/skip_gogo.go index 4fe7e0815c..5a5fd93f7c 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/skip_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/skip_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text.go index e2b99b122d..b3e12e2684 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text.go @@ -1,7 +1,7 @@ -// Extensions for Protocol Buffers to create more go like structures. +// Protocol Buffers for Go with Gadgets // -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Go support for Protocol Buffers - Google's data interchange format // @@ -50,6 +50,7 @@ import ( "reflect" "sort" "strings" + "sync" ) var ( @@ -159,7 +160,7 @@ func (w *textWriter) indent() { w.ind++ } func (w *textWriter) unindent() { if w.ind == 0 { - log.Printf("proto: textWriter unindented too far") + log.Print("proto: textWriter unindented too far") return } w.ind-- @@ -335,7 +336,8 @@ func writeStruct(w *textWriter, sv reflect.Value) error { } inner := fv.Elem().Elem() // interface -> *T -> T tag := inner.Type().Field(0).Tag.Get("protobuf") - props.Parse(tag) // Overwrite the outer props. + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) // Write the value in the oneof, not the oneof itself. fv = inner.Field(0) @@ -386,7 +388,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error { pv = reflect.New(sv.Type()) pv.Elem().Set(sv) } - if pv.Type().Implements(extendableProtoType) { + if pv.Type().Implements(extensionRangeType) { if err := writeExtensions(w, pv); err != nil { return err } @@ -634,28 +636,37 @@ func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // pv is assumed to be a pointer to a protocol message struct that is extendable. func writeExtensions(w *textWriter, pv reflect.Value) error { emap := extensionMaps[pv.Type().Elem()] - ep := pv.Interface().(extendableProto) + e := pv.Interface().(Message) - // Order the extensions by ID. - // This isn't strictly necessary, but it will give us - // canonical output, which will also make testing easier. var m map[int32]Extension - if em, ok := ep.(extensionsMap); ok { - m = em.ExtensionMap() - } else if em, ok := ep.(extensionsBytes); ok { + var mu sync.Locker + if em, ok := e.(extensionsBytes); ok { eb := em.GetExtensions() var err error m, err = BytesToExtensionsMap(*eb) if err != nil { return err } + mu = notLocker{} + } else if _, ok := e.(extendableProto); ok { + ep, _ := extendable(e) + m, mu = ep.extensionsRead() + if m == nil { + return nil + } } + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + + mu.Lock() ids := make([]int32, 0, len(m)) for id := range m { ids = append(ids, id) } sort.Sort(int32Slice(ids)) + mu.Unlock() for _, extNum := range ids { ext := m[extNum] @@ -671,7 +682,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error { continue } - pb, err := GetExtension(ep, desc) + pb, err := GetExtension(e, desc) if err != nil { return fmt.Errorf("failed getting extension: %v", err) } @@ -727,7 +738,14 @@ func (w *textWriter) writeIndent() { w.complete = false } -func marshalText(w io.Writer, pb Message, compact bool) error { +// TextMarshaler is a configurable text format marshaler. +type TextMarshaler struct { + Compact bool // use compact text format (one line). +} + +// Marshal writes a given protocol buffer in text format. +// The only errors returned are from w. +func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error { val := reflect.ValueOf(pb) if pb == nil || val.IsNil() { w.Write([]byte("")) @@ -742,7 +760,7 @@ func marshalText(w io.Writer, pb Message, compact bool) error { aw := &textWriter{ w: ww, complete: true, - compact: compact, + compact: m.Compact, } if tm, ok := pb.(encoding.TextMarshaler); ok { @@ -769,25 +787,29 @@ func marshalText(w io.Writer, pb Message, compact bool) error { return nil } +// Text is the same as Marshal, but returns the string directly. +func (m *TextMarshaler) Text(pb Message) string { + var buf bytes.Buffer + m.Marshal(&buf, pb) + return buf.String() +} + +var ( + defaultTextMarshaler = TextMarshaler{} + compactTextMarshaler = TextMarshaler{Compact: true} +) + +// TODO: consider removing some of the Marshal functions below. + // MarshalText writes a given protocol buffer in text format. // The only errors returned are from w. -func MarshalText(w io.Writer, pb Message) error { - return marshalText(w, pb, false) -} +func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } // MarshalTextString is the same as MarshalText, but returns the string directly. -func MarshalTextString(pb Message) string { - var buf bytes.Buffer - marshalText(&buf, pb, false) - return buf.String() -} +func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } // CompactText writes a given protocol buffer in compact text format (one line). -func CompactText(w io.Writer, pb Message) error { return marshalText(w, pb, true) } +func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } // CompactTextString is the same as CompactText, but returns the string directly. -func CompactTextString(pb Message) string { - var buf bytes.Buffer - marshalText(&buf, pb, true) - return buf.String() -} +func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_gogo.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_gogo.go index cdb23373c3..5892674197 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_gogo.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_gogo.go @@ -1,5 +1,7 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_parser.go b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_parser.go index 61b4bc8cc8..bcd732c3c4 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_parser.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/proto/text_parser.go @@ -1,7 +1,7 @@ -// Extensions for Protocol Buffers to create more go like structures. +// Protocol Buffers for Go with Gadgets // -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. -// http://github.com/gogo/protobuf/gogoproto +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf // // Go support for Protocol Buffers - Google's data interchange format // @@ -519,7 +519,7 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { } reqFieldErr = err } - ep := sv.Addr().Interface().(extendableProto) + ep := sv.Addr().Interface().(Message) if !rep { SetExtension(ep, desc, ext.Interface()) } else { @@ -571,8 +571,9 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { // The map entry should be this sequence of tokens: // < key : KEY value : VALUE > - // Technically the "key" and "value" could come in any order, - // but in practice they won't. + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. tok := p.next() var terminator string @@ -584,32 +585,39 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { default: return p.errorf("expected '{' or '<', found %q", tok.value) } - if err := p.consumeToken("key"); err != nil { - return err - } - if err := p.consumeToken(":"); err != nil { - return err - } - if err := p.readAny(key, props.mkeyprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken("value"); err != nil { - return err - } - if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { - return err - } - if err := p.readAny(val, props.mvalprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken(terminator); err != nil { - return err + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.mkeyprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.mvalprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } } dst.SetMapIndex(key, val) @@ -632,7 +640,8 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { return err } reqFieldErr = err - } else if props.Required { + } + if props.Required { reqCount-- } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/Makefile b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/Makefile index d80ceffee2..f966d8b3a0 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/Makefile +++ b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/Makefile @@ -30,4 +30,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. regenerate: + go install github.com/gogo/protobuf/protoc-gen-gogo protoc --gogo_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto + go install github.com/gogo/protobuf/protoc-gen-gostring + protoc --gostring_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go index 342d65a425..341b59c53d 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go @@ -41,7 +41,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type FieldDescriptorProto_Type int32 @@ -955,9 +957,9 @@ type FileOptions struct { // suffixed package. JavananoUseDeprecatedPackage *bool `protobuf:"varint,38,opt,name=javanano_use_deprecated_package,json=javananoUseDeprecatedPackage" json:"javanano_use_deprecated_package,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *FileOptions) Reset() { *m = FileOptions{} } @@ -966,18 +968,12 @@ func (*FileOptions) ProtoMessage() {} func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{9} } var extRange_FileOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FileOptions } -func (m *FileOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_FileOptions_JavaMultipleFiles bool = false const Default_FileOptions_JavaGenerateEqualsAndHash bool = false @@ -1153,9 +1149,9 @@ type MessageOptions struct { // parser. MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *MessageOptions) Reset() { *m = MessageOptions{} } @@ -1164,18 +1160,12 @@ func (*MessageOptions) ProtoMessage() {} func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{10} } var extRange_MessageOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MessageOptions } -func (m *MessageOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_MessageOptions_MessageSetWireFormat bool = false const Default_MessageOptions_NoStandardDescriptorAccessor bool = false @@ -1275,9 +1265,9 @@ type FieldOptions struct { // For Google-internal migration only. Do not use. Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *FieldOptions) Reset() { *m = FieldOptions{} } @@ -1286,18 +1276,12 @@ func (*FieldOptions) ProtoMessage() {} func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{11} } var extRange_FieldOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_FieldOptions } -func (m *FieldOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL @@ -1364,9 +1348,9 @@ type EnumOptions struct { // is a formalization for deprecating enums. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *EnumOptions) Reset() { *m = EnumOptions{} } @@ -1375,18 +1359,12 @@ func (*EnumOptions) ProtoMessage() {} func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{12} } var extRange_EnumOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumOptions } -func (m *EnumOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_EnumOptions_Deprecated bool = false @@ -1418,9 +1396,9 @@ type EnumValueOptions struct { // this is a formalization for deprecating enum values. Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } @@ -1429,18 +1407,12 @@ func (*EnumValueOptions) ProtoMessage() {} func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{13} } var extRange_EnumValueOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_EnumValueOptions } -func (m *EnumValueOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_EnumValueOptions_Deprecated bool = false @@ -1465,9 +1437,9 @@ type ServiceOptions struct { // this is a formalization for deprecating services. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } @@ -1476,18 +1448,12 @@ func (*ServiceOptions) ProtoMessage() {} func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{14} } var extRange_ServiceOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_ServiceOptions } -func (m *ServiceOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_ServiceOptions_Deprecated bool = false @@ -1512,9 +1478,9 @@ type MethodOptions struct { // this is a formalization for deprecating methods. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. - UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` } func (m *MethodOptions) Reset() { *m = MethodOptions{} } @@ -1523,18 +1489,12 @@ func (*MethodOptions) ProtoMessage() {} func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{15} } var extRange_MethodOptions = []proto.ExtensionRange{ - {1000, 536870911}, + {Start: 1000, End: 536870911}, } func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange { return extRange_MethodOptions } -func (m *MethodOptions) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} const Default_MethodOptions_Deprecated bool = false @@ -1875,143 +1835,147 @@ func init() { proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value) } +func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) } + var fileDescriptorDescriptor = []byte{ - // 2192 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x73, 0xdb, 0xd6, - 0x11, 0x2f, 0xff, 0x8a, 0x5c, 0x52, 0x24, 0xf4, 0xac, 0xd8, 0xb4, 0x62, 0xc7, 0x31, 0x63, 0xc7, - 0x8e, 0xd3, 0xd2, 0x19, 0xb7, 0x49, 0x5c, 0xa5, 0x93, 0x0e, 0x45, 0xc2, 0x0a, 0x3d, 0x94, 0xc8, - 0x3e, 0x92, 0xad, 0x93, 0x0b, 0x06, 0x02, 0x1f, 0x29, 0xd8, 0x20, 0xc0, 0x02, 0xa0, 0x6d, 0xe5, - 0xd4, 0x99, 0x9e, 0xfa, 0x0d, 0x3a, 0x6d, 0xa7, 0x87, 0x5c, 0x32, 0xd3, 0x0f, 0xd0, 0x43, 0xef, - 0xbd, 0xf6, 0xd0, 0x73, 0x8f, 0x9d, 0x69, 0xbf, 0x41, 0xaf, 0xdd, 0xf7, 0x1e, 0x00, 0x02, 0x24, - 0x15, 0xab, 0x99, 0x49, 0x13, 0x5d, 0xc4, 0xb7, 0xfb, 0xdb, 0xc5, 0xbe, 0x7d, 0xbf, 0xb7, 0xbb, - 0x00, 0x28, 0x63, 0xe6, 0x19, 0xae, 0x39, 0xf7, 0x1d, 0xb7, 0x31, 0x77, 0x1d, 0xdf, 0x21, 0xd5, - 0xa9, 0xe3, 0x4c, 0x2d, 0x26, 0x57, 0x27, 0x8b, 0x49, 0xfd, 0x08, 0x76, 0x1e, 0x99, 0x16, 0x6b, - 0x47, 0xc0, 0x01, 0xf3, 0xc9, 0x43, 0xc8, 0x4e, 0x50, 0x58, 0x4b, 0xbd, 0x99, 0xb9, 0x5b, 0x7a, - 0x70, 0xab, 0xb1, 0x62, 0xd4, 0x48, 0x5a, 0xf4, 0xb9, 0x98, 0x0a, 0x8b, 0xfa, 0x3f, 0xb3, 0x70, - 0x69, 0x83, 0x96, 0x10, 0xc8, 0xda, 0xfa, 0x8c, 0x7b, 0x4c, 0xdd, 0x2d, 0x52, 0xf1, 0x9b, 0xd4, - 0x60, 0x6b, 0xae, 0x1b, 0xcf, 0xf4, 0x29, 0xab, 0xa5, 0x85, 0x38, 0x5c, 0x92, 0x37, 0x00, 0xc6, - 0x6c, 0xce, 0xec, 0x31, 0xb3, 0x8d, 0xb3, 0x5a, 0x06, 0xa3, 0x28, 0xd2, 0x98, 0x84, 0xbc, 0x0b, - 0x3b, 0xf3, 0xc5, 0x89, 0x65, 0x1a, 0x5a, 0x0c, 0x06, 0x08, 0xcb, 0x51, 0x45, 0x2a, 0xda, 0x4b, - 0xf0, 0x1d, 0xa8, 0xbe, 0x60, 0xfa, 0xb3, 0x38, 0xb4, 0x24, 0xa0, 0x15, 0x2e, 0x8e, 0x01, 0x5b, - 0x50, 0x9e, 0x31, 0xcf, 0xc3, 0x00, 0x34, 0xff, 0x6c, 0xce, 0x6a, 0x59, 0xb1, 0xfb, 0x37, 0xd7, - 0x76, 0xbf, 0xba, 0xf3, 0x52, 0x60, 0x35, 0x44, 0x23, 0xd2, 0x84, 0x22, 0xb3, 0x17, 0x33, 0xe9, - 0x21, 0x77, 0x4e, 0xfe, 0x54, 0x44, 0xac, 0x7a, 0x29, 0x70, 0xb3, 0xc0, 0xc5, 0x96, 0xc7, 0xdc, - 0xe7, 0xa6, 0xc1, 0x6a, 0x79, 0xe1, 0xe0, 0xce, 0x9a, 0x83, 0x81, 0xd4, 0xaf, 0xfa, 0x08, 0xed, - 0x70, 0x2b, 0x45, 0xf6, 0xd2, 0x67, 0xb6, 0x67, 0x3a, 0x76, 0x6d, 0x4b, 0x38, 0xb9, 0xbd, 0xe1, - 0x14, 0x99, 0x35, 0x5e, 0x75, 0xb1, 0xb4, 0x23, 0x1f, 0xc0, 0x96, 0x33, 0xf7, 0xf1, 0x97, 0x57, - 0x2b, 0xe0, 0xf9, 0x94, 0x1e, 0x5c, 0xdb, 0x48, 0x84, 0x9e, 0xc4, 0xd0, 0x10, 0x4c, 0x3a, 0xa0, - 0x78, 0xce, 0xc2, 0x35, 0x98, 0x66, 0x38, 0x63, 0xa6, 0x99, 0xf6, 0xc4, 0xa9, 0x15, 0x85, 0x83, - 0x1b, 0xeb, 0x1b, 0x11, 0xc0, 0x16, 0xe2, 0x3a, 0x08, 0xa3, 0x15, 0x2f, 0xb1, 0x26, 0x97, 0x21, - 0xef, 0x9d, 0xd9, 0xbe, 0xfe, 0xb2, 0x56, 0x16, 0x0c, 0x09, 0x56, 0xf5, 0xff, 0xe4, 0xa0, 0x7a, - 0x11, 0x8a, 0x7d, 0x04, 0xb9, 0x09, 0xdf, 0x25, 0x12, 0xec, 0x7f, 0xc8, 0x81, 0xb4, 0x49, 0x26, - 0x31, 0xff, 0x35, 0x93, 0xd8, 0x84, 0x92, 0xcd, 0x3c, 0x9f, 0x8d, 0x25, 0x23, 0x32, 0x17, 0xe4, - 0x14, 0x48, 0xa3, 0x75, 0x4a, 0x65, 0xbf, 0x16, 0xa5, 0x9e, 0x40, 0x35, 0x0a, 0x49, 0x73, 0x75, - 0x7b, 0x1a, 0x72, 0xf3, 0xfe, 0xab, 0x22, 0x69, 0xa8, 0xa1, 0x1d, 0xe5, 0x66, 0xb4, 0xc2, 0x12, - 0x6b, 0xd2, 0x06, 0x70, 0x6c, 0xe6, 0x4c, 0xf0, 0x7a, 0x19, 0x16, 0xf2, 0x64, 0x73, 0x96, 0x7a, - 0x1c, 0xb2, 0x96, 0x25, 0x47, 0x4a, 0x0d, 0x8b, 0xfc, 0x78, 0x49, 0xb5, 0xad, 0x73, 0x98, 0x72, - 0x24, 0x2f, 0xd9, 0x1a, 0xdb, 0x46, 0x50, 0x71, 0x19, 0xe7, 0x3d, 0xa6, 0x58, 0xee, 0xac, 0x28, - 0x82, 0x68, 0xbc, 0x72, 0x67, 0x34, 0x30, 0x93, 0x1b, 0xdb, 0x76, 0xe3, 0x4b, 0xf2, 0x16, 0x44, - 0x02, 0x4d, 0xd0, 0x0a, 0x44, 0x15, 0x2a, 0x87, 0xc2, 0x63, 0x94, 0xed, 0x3d, 0x84, 0x4a, 0x32, - 0x3d, 0x64, 0x17, 0x72, 0x9e, 0xaf, 0xbb, 0xbe, 0x60, 0x61, 0x8e, 0xca, 0x05, 0x51, 0x20, 0x83, - 0x45, 0x46, 0x54, 0xb9, 0x1c, 0xe5, 0x3f, 0xf7, 0x3e, 0x84, 0xed, 0xc4, 0xe3, 0x2f, 0x6a, 0x58, - 0xff, 0x6d, 0x1e, 0x76, 0x37, 0x71, 0x6e, 0x23, 0xfd, 0xf1, 0xfa, 0x20, 0x03, 0x4e, 0x98, 0x8b, - 0xbc, 0xe3, 0x1e, 0x82, 0x15, 0x32, 0x2a, 0x67, 0xe9, 0x27, 0xcc, 0x42, 0x36, 0xa5, 0xee, 0x56, - 0x1e, 0xbc, 0x7b, 0x21, 0x56, 0x37, 0xba, 0xdc, 0x84, 0x4a, 0x4b, 0xf2, 0x31, 0x64, 0x83, 0x12, - 0xc7, 0x3d, 0xdc, 0xbb, 0x98, 0x07, 0xce, 0x45, 0x2a, 0xec, 0xc8, 0xeb, 0x50, 0xe4, 0xff, 0x65, - 0x6e, 0xf3, 0x22, 0xe6, 0x02, 0x17, 0xf0, 0xbc, 0x92, 0x3d, 0x28, 0x08, 0x9a, 0x8d, 0x59, 0xd8, - 0x1a, 0xa2, 0x35, 0x3f, 0x98, 0x31, 0x9b, 0xe8, 0x0b, 0xcb, 0xd7, 0x9e, 0xeb, 0xd6, 0x82, 0x09, - 0xc2, 0xe0, 0xc1, 0x04, 0xc2, 0x9f, 0x73, 0x19, 0xb9, 0x01, 0x25, 0xc9, 0x4a, 0x13, 0x6d, 0x5e, - 0x8a, 0xea, 0x93, 0xa3, 0x92, 0xa8, 0x1d, 0x2e, 0xe1, 0x8f, 0x7f, 0xea, 0xe1, 0x5d, 0x08, 0x8e, - 0x56, 0x3c, 0x82, 0x0b, 0xc4, 0xe3, 0x3f, 0x5c, 0x2d, 0x7c, 0xd7, 0x37, 0x6f, 0x6f, 0x95, 0x8b, - 0xf5, 0x3f, 0xa7, 0x21, 0x2b, 0xee, 0x5b, 0x15, 0x4a, 0xc3, 0x4f, 0xfb, 0xaa, 0xd6, 0xee, 0x8d, - 0x0e, 0xba, 0xaa, 0x92, 0x22, 0x15, 0x00, 0x21, 0x78, 0xd4, 0xed, 0x35, 0x87, 0x4a, 0x3a, 0x5a, - 0x77, 0x8e, 0x87, 0x1f, 0xfc, 0x48, 0xc9, 0x44, 0x06, 0x23, 0x29, 0xc8, 0xc6, 0x01, 0x3f, 0x7c, - 0xa0, 0xe4, 0x90, 0x09, 0x65, 0xe9, 0xa0, 0xf3, 0x44, 0x6d, 0x23, 0x22, 0x9f, 0x94, 0x20, 0x66, - 0x8b, 0x6c, 0x43, 0x51, 0x48, 0x0e, 0x7a, 0xbd, 0xae, 0x52, 0x88, 0x7c, 0x0e, 0x86, 0xb4, 0x73, - 0x7c, 0xa8, 0x14, 0x23, 0x9f, 0x87, 0xb4, 0x37, 0xea, 0x2b, 0x10, 0x79, 0x38, 0x52, 0x07, 0x83, - 0xe6, 0xa1, 0xaa, 0x94, 0x22, 0xc4, 0xc1, 0xa7, 0x43, 0x75, 0xa0, 0x94, 0x13, 0x61, 0xe1, 0x23, - 0xb6, 0xa3, 0x47, 0xa8, 0xc7, 0xa3, 0x23, 0xa5, 0x42, 0x76, 0x60, 0x5b, 0x3e, 0x22, 0x0c, 0xa2, - 0xba, 0x22, 0xc2, 0x48, 0x95, 0x65, 0x20, 0xd2, 0xcb, 0x4e, 0x42, 0x80, 0x08, 0x52, 0x6f, 0x41, - 0x4e, 0xb0, 0x0b, 0x59, 0x5c, 0xe9, 0x36, 0x0f, 0xd4, 0xae, 0xd6, 0xeb, 0x0f, 0x3b, 0xbd, 0xe3, - 0x66, 0x17, 0x73, 0x17, 0xc9, 0xa8, 0xfa, 0xb3, 0x51, 0x87, 0xaa, 0x6d, 0xcc, 0x5f, 0x4c, 0xd6, - 0x57, 0x9b, 0x43, 0x94, 0x65, 0xea, 0xf7, 0x60, 0x77, 0x53, 0x9d, 0xd9, 0x74, 0x33, 0xea, 0x5f, - 0xa4, 0xe0, 0xd2, 0x86, 0x92, 0xb9, 0xf1, 0x16, 0xfd, 0x14, 0x72, 0x92, 0x69, 0xb2, 0x89, 0xbc, - 0xb3, 0xb1, 0xf6, 0x0a, 0xde, 0xad, 0x35, 0x12, 0x61, 0x17, 0x6f, 0xa4, 0x99, 0x73, 0x1a, 0x29, - 0x77, 0xb1, 0x46, 0xa7, 0x5f, 0xa7, 0xa0, 0x76, 0x9e, 0xef, 0x57, 0xdc, 0xf7, 0x74, 0xe2, 0xbe, - 0x7f, 0xb4, 0x1a, 0xc0, 0xcd, 0xf3, 0xf7, 0xb0, 0x16, 0xc5, 0x97, 0x29, 0xb8, 0xbc, 0x79, 0xde, - 0xd8, 0x18, 0xc3, 0xc7, 0x90, 0x9f, 0x31, 0xff, 0xd4, 0x09, 0x7b, 0xee, 0xdb, 0x1b, 0x2a, 0x39, - 0x57, 0xaf, 0xe6, 0x2a, 0xb0, 0x8a, 0xb7, 0x82, 0xcc, 0x79, 0x43, 0x83, 0x8c, 0x66, 0x2d, 0xd2, - 0xdf, 0xa4, 0xe1, 0xb5, 0x8d, 0xce, 0x37, 0x06, 0x7a, 0x1d, 0xc0, 0xb4, 0xe7, 0x0b, 0x5f, 0xf6, - 0x55, 0x59, 0x66, 0x8a, 0x42, 0x22, 0xae, 0x30, 0x2f, 0x21, 0x0b, 0x3f, 0xd2, 0x67, 0x84, 0x1e, - 0xa4, 0x48, 0x00, 0x1e, 0x2e, 0x03, 0xcd, 0x8a, 0x40, 0xdf, 0x38, 0x67, 0xa7, 0x6b, 0x2d, 0xeb, - 0x3d, 0x50, 0x0c, 0xcb, 0x64, 0xb6, 0xaf, 0x79, 0xbe, 0xcb, 0xf4, 0x99, 0x69, 0x4f, 0x45, 0x1d, - 0x2d, 0xec, 0xe7, 0x26, 0xba, 0xe5, 0x31, 0x5a, 0x95, 0xea, 0x41, 0xa8, 0xe5, 0x16, 0xa2, 0x59, - 0xb8, 0x31, 0x8b, 0x7c, 0xc2, 0x42, 0xaa, 0x23, 0x8b, 0xfa, 0xdf, 0xb7, 0xa0, 0x14, 0x9b, 0xce, - 0xc8, 0x4d, 0x28, 0x3f, 0xd5, 0x9f, 0xeb, 0x5a, 0x38, 0x71, 0xcb, 0x4c, 0x94, 0xb8, 0xac, 0x1f, - 0x4c, 0xdd, 0xef, 0xc1, 0xae, 0x80, 0xe0, 0x1e, 0xf1, 0x41, 0x86, 0xa5, 0x7b, 0x9e, 0x48, 0x5a, - 0x41, 0x40, 0x09, 0xd7, 0xf5, 0xb8, 0xaa, 0x15, 0x6a, 0xc8, 0xfb, 0x70, 0x49, 0x58, 0xcc, 0xb0, - 0xf0, 0x9a, 0x73, 0x8b, 0x69, 0xfc, 0x1d, 0xc0, 0x13, 0xf5, 0x34, 0x8a, 0x6c, 0x87, 0x23, 0x8e, - 0x02, 0x00, 0x8f, 0xc8, 0x23, 0x87, 0x70, 0x5d, 0x98, 0x4d, 0x99, 0xcd, 0x5c, 0xdd, 0x67, 0x1a, - 0xfb, 0xe5, 0x02, 0xb1, 0x9a, 0x6e, 0x8f, 0xb5, 0x53, 0xdd, 0x3b, 0xad, 0xed, 0xc6, 0x1d, 0x5c, - 0xe5, 0xd8, 0xc3, 0x00, 0xaa, 0x0a, 0x64, 0xd3, 0x1e, 0x7f, 0x82, 0x38, 0xb2, 0x0f, 0x97, 0x85, - 0x23, 0x4c, 0x0a, 0xee, 0x59, 0x33, 0x4e, 0x99, 0xf1, 0x4c, 0x5b, 0xf8, 0x93, 0x87, 0xb5, 0xd7, - 0xe3, 0x1e, 0x44, 0x90, 0x03, 0x81, 0x69, 0x71, 0xc8, 0x08, 0x11, 0x64, 0x00, 0x65, 0x7e, 0x1e, - 0x33, 0xf3, 0x73, 0x0c, 0xdb, 0x71, 0x45, 0x8f, 0xa8, 0x6c, 0xb8, 0xdc, 0xb1, 0x24, 0x36, 0x7a, - 0x81, 0xc1, 0x11, 0xce, 0xa7, 0xfb, 0xb9, 0x41, 0x5f, 0x55, 0xdb, 0xb4, 0x14, 0x7a, 0x79, 0xe4, - 0xb8, 0x9c, 0x53, 0x53, 0x27, 0xca, 0x71, 0x49, 0x72, 0x6a, 0xea, 0x84, 0x19, 0xc6, 0x7c, 0x19, - 0x86, 0xdc, 0x36, 0xbe, 0xbb, 0x04, 0xc3, 0xba, 0x57, 0x53, 0x12, 0xf9, 0x32, 0x8c, 0x43, 0x09, - 0x08, 0x68, 0xee, 0xe1, 0x95, 0x78, 0x6d, 0x99, 0xaf, 0xb8, 0xe1, 0xce, 0xda, 0x2e, 0x57, 0x4d, - 0xf1, 0x89, 0xf3, 0xb3, 0x75, 0x43, 0x92, 0x78, 0xe2, 0xfc, 0x6c, 0xd5, 0xec, 0xb6, 0x78, 0x01, - 0x73, 0x99, 0x81, 0x29, 0x1f, 0xd7, 0xae, 0xc4, 0xd1, 0x31, 0x05, 0xb9, 0x8f, 0x44, 0x36, 0x34, - 0x66, 0xeb, 0x27, 0x78, 0xf6, 0xba, 0x8b, 0x3f, 0xbc, 0xda, 0x8d, 0x38, 0xb8, 0x62, 0x18, 0xaa, - 0xd0, 0x36, 0x85, 0x92, 0xdc, 0x83, 0x1d, 0xe7, 0xe4, 0xa9, 0x21, 0xc9, 0xa5, 0xa1, 0x9f, 0x89, - 0xf9, 0xb2, 0x76, 0x4b, 0xa4, 0xa9, 0xca, 0x15, 0x82, 0x5a, 0x7d, 0x21, 0x26, 0xef, 0xa0, 0x73, - 0xef, 0x54, 0x77, 0xe7, 0xa2, 0x49, 0x7b, 0x98, 0x54, 0x56, 0xbb, 0x2d, 0xa1, 0x52, 0x7e, 0x1c, - 0x8a, 0x89, 0x0a, 0x37, 0xf8, 0xe6, 0x6d, 0xdd, 0x76, 0xb4, 0x85, 0xc7, 0xb4, 0x65, 0x88, 0xd1, - 0x59, 0xbc, 0xcd, 0xc3, 0xa2, 0xd7, 0x42, 0xd8, 0xc8, 0xc3, 0x62, 0x16, 0x82, 0xc2, 0xe3, 0x79, - 0x02, 0xbb, 0x0b, 0xdb, 0xb4, 0x91, 0xe2, 0xa8, 0xe1, 0xc6, 0xf2, 0xc2, 0xd6, 0xfe, 0xb5, 0x75, - 0xce, 0xd0, 0x3d, 0x8a, 0xa3, 0x25, 0x49, 0xe8, 0xa5, 0xc5, 0xba, 0xb0, 0xbe, 0x0f, 0xe5, 0x38, - 0x77, 0x48, 0x11, 0x24, 0x7b, 0xb0, 0xbb, 0x61, 0x47, 0x6d, 0xf5, 0xda, 0xbc, 0x17, 0x7e, 0xa6, - 0x62, 0x63, 0xc3, 0x9e, 0xdc, 0xed, 0x0c, 0x55, 0x8d, 0x8e, 0x8e, 0x87, 0x9d, 0x23, 0x55, 0xc9, - 0xdc, 0x2b, 0x16, 0xfe, 0xbd, 0xa5, 0xfc, 0x0a, 0xff, 0xd2, 0xf5, 0xbf, 0xa6, 0xa1, 0x92, 0x9c, - 0x83, 0xc9, 0x4f, 0xe0, 0x4a, 0xf8, 0xd2, 0xea, 0x31, 0x5f, 0x7b, 0x61, 0xba, 0x82, 0xce, 0x33, - 0x5d, 0x4e, 0x92, 0xd1, 0x49, 0xec, 0x06, 0x28, 0x7c, 0xbd, 0xff, 0x05, 0x62, 0x1e, 0x09, 0x08, - 0xe9, 0xc2, 0x0d, 0x4c, 0x19, 0xce, 0x9a, 0xf6, 0x58, 0x77, 0xc7, 0xda, 0xf2, 0x73, 0x81, 0xa6, - 0x1b, 0xc8, 0x03, 0xcf, 0x91, 0x9d, 0x24, 0xf2, 0x72, 0xcd, 0x76, 0x06, 0x01, 0x78, 0x59, 0x62, - 0x9b, 0x01, 0x74, 0x85, 0x35, 0x99, 0xf3, 0x58, 0x83, 0xb3, 0xd7, 0x4c, 0x9f, 0x23, 0x6d, 0x7c, - 0xf7, 0x4c, 0x4c, 0x6f, 0x05, 0x5a, 0x40, 0x81, 0xca, 0xd7, 0xdf, 0xdc, 0x19, 0xc4, 0xf3, 0xf8, - 0x8f, 0x0c, 0x94, 0xe3, 0x13, 0x1c, 0x1f, 0x88, 0x0d, 0x51, 0xe6, 0x53, 0xa2, 0x0a, 0xbc, 0xf5, - 0x95, 0xf3, 0x5e, 0xa3, 0xc5, 0xeb, 0xff, 0x7e, 0x5e, 0xce, 0x55, 0x54, 0x5a, 0xf2, 0xde, 0xcb, - 0xb9, 0xc6, 0xe4, 0xb4, 0x5e, 0xa0, 0xc1, 0x0a, 0x8b, 0x5d, 0xfe, 0xa9, 0x27, 0x7c, 0xe7, 0x85, - 0xef, 0x5b, 0x5f, 0xed, 0xfb, 0xf1, 0x40, 0x38, 0x2f, 0x3e, 0x1e, 0x68, 0xc7, 0x3d, 0x7a, 0xd4, - 0xec, 0xd2, 0xc0, 0x9c, 0x5c, 0x85, 0xac, 0xa5, 0x7f, 0x7e, 0x96, 0xec, 0x14, 0x42, 0x74, 0xd1, - 0xc4, 0xa3, 0x07, 0xfe, 0xc9, 0x23, 0x59, 0x9f, 0x85, 0xe8, 0x1b, 0xa4, 0xfe, 0x7d, 0xc8, 0x89, - 0x7c, 0x11, 0x80, 0x20, 0x63, 0xca, 0xf7, 0x48, 0x01, 0xb2, 0xad, 0x1e, 0xe5, 0xf4, 0x47, 0xbe, - 0x4b, 0xa9, 0xd6, 0xef, 0xa8, 0x2d, 0xbc, 0x01, 0xf5, 0xf7, 0x21, 0x2f, 0x93, 0xc0, 0xaf, 0x46, - 0x94, 0x06, 0x34, 0x92, 0xcb, 0xc0, 0x47, 0x2a, 0xd4, 0x8e, 0x8e, 0x0e, 0x54, 0xaa, 0xa4, 0xe3, - 0xc7, 0xfb, 0x97, 0x14, 0x94, 0x62, 0x03, 0x15, 0x6f, 0xe5, 0xba, 0x65, 0x39, 0x2f, 0x34, 0xdd, - 0x32, 0xb1, 0x42, 0xc9, 0xf3, 0x01, 0x21, 0x6a, 0x72, 0xc9, 0x45, 0xf3, 0xf7, 0x7f, 0xe1, 0xe6, - 0x1f, 0x53, 0xa0, 0xac, 0x0e, 0x63, 0x2b, 0x01, 0xa6, 0xbe, 0xd5, 0x00, 0xff, 0x90, 0x82, 0x4a, - 0x72, 0x02, 0x5b, 0x09, 0xef, 0xe6, 0xb7, 0x1a, 0xde, 0xef, 0x53, 0xb0, 0x9d, 0x98, 0xbb, 0xbe, - 0x53, 0xd1, 0xfd, 0x2e, 0x03, 0x97, 0x36, 0xd8, 0x61, 0x01, 0x92, 0x03, 0xaa, 0x9c, 0x99, 0x7f, - 0x70, 0x91, 0x67, 0x35, 0x78, 0xff, 0xeb, 0xeb, 0xae, 0x1f, 0xcc, 0xb3, 0xd8, 0x2f, 0xcd, 0x31, - 0x16, 0x55, 0x73, 0x62, 0xe2, 0xf8, 0x26, 0xdf, 0x58, 0xe4, 0xd4, 0x5a, 0x5d, 0xca, 0xe5, 0xeb, - 0xf1, 0xf7, 0x81, 0xcc, 0x1d, 0xcf, 0xf4, 0xcd, 0xe7, 0xfc, 0xf3, 0x5c, 0xf8, 0x22, 0xcd, 0xa7, - 0xd8, 0x2c, 0x55, 0x42, 0x4d, 0xc7, 0xf6, 0x23, 0xb4, 0xcd, 0xa6, 0xfa, 0x0a, 0x9a, 0x97, 0xa1, - 0x0c, 0x55, 0x42, 0x4d, 0x84, 0xc6, 0x41, 0x73, 0xec, 0x2c, 0xf8, 0x40, 0x20, 0x71, 0xbc, 0xea, - 0xa5, 0x68, 0x49, 0xca, 0x22, 0x48, 0x30, 0xb1, 0x2d, 0xdf, 0xe0, 0xcb, 0xb4, 0x24, 0x65, 0x12, - 0x72, 0x07, 0xaa, 0xfa, 0x74, 0xea, 0x72, 0xe7, 0xa1, 0x23, 0x39, 0x86, 0x56, 0x22, 0xb1, 0x00, - 0xee, 0x3d, 0x86, 0x42, 0x98, 0x07, 0xde, 0x58, 0x78, 0x26, 0xb0, 0xe7, 0x8b, 0xef, 0x28, 0x69, - 0xfe, 0x52, 0x6f, 0x87, 0x4a, 0x7c, 0xa8, 0xe9, 0x69, 0xcb, 0x0f, 0x7a, 0x69, 0xd4, 0x17, 0x68, - 0xc9, 0xf4, 0xa2, 0x2f, 0x38, 0xf5, 0x2f, 0xb1, 0xbd, 0x26, 0x3f, 0x48, 0x92, 0x36, 0x14, 0x2c, - 0x07, 0xf9, 0xc1, 0x2d, 0xe4, 0xd7, 0xf0, 0xbb, 0xaf, 0xf8, 0x86, 0xd9, 0xe8, 0x06, 0x78, 0x1a, - 0x59, 0xee, 0xfd, 0x2d, 0x05, 0x85, 0x50, 0x8c, 0x8d, 0x22, 0x3b, 0xd7, 0xfd, 0x53, 0xe1, 0x2e, - 0x77, 0x90, 0x56, 0x52, 0x54, 0xac, 0xb9, 0x1c, 0xa7, 0x19, 0x5b, 0x50, 0x20, 0x90, 0xf3, 0x35, - 0x3f, 0x57, 0x8b, 0xe9, 0x63, 0x31, 0xe0, 0x3a, 0xb3, 0x19, 0x9e, 0xa4, 0x17, 0x9e, 0x6b, 0x20, - 0x6f, 0x05, 0x62, 0xfe, 0x5d, 0xdc, 0x77, 0x75, 0xd3, 0x4a, 0x60, 0xb3, 0x02, 0xab, 0x84, 0x8a, - 0x08, 0xbc, 0x0f, 0x57, 0x43, 0xbf, 0x63, 0xe6, 0xeb, 0x38, 0x3c, 0x8f, 0x97, 0x46, 0x79, 0xf1, - 0xb5, 0xeb, 0x4a, 0x00, 0x68, 0x07, 0xfa, 0xd0, 0xf6, 0xe0, 0x09, 0x0e, 0xb2, 0xce, 0x6c, 0x35, - 0x13, 0x07, 0xca, 0xca, 0x7b, 0x97, 0xf7, 0x49, 0xea, 0x33, 0x58, 0x0e, 0x15, 0x5f, 0xa4, 0x33, - 0x87, 0xfd, 0x83, 0x3f, 0xa5, 0xf7, 0x0e, 0xa5, 0x5d, 0x3f, 0xcc, 0x20, 0x65, 0x13, 0x8b, 0x19, - 0x3c, 0x3b, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x78, 0x42, 0x69, 0x71, 0xb3, 0x18, 0x00, 0x00, + // 2211 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x73, 0xdb, 0xc6, + 0x15, 0x0f, 0xf8, 0x4f, 0xe4, 0x23, 0x45, 0xad, 0x56, 0x8a, 0x03, 0xcb, 0x76, 0x2c, 0x33, 0x76, + 0x2c, 0xdb, 0xad, 0x9c, 0x91, 0xff, 0x44, 0x51, 0x3a, 0xe9, 0x50, 0x24, 0xac, 0xd0, 0x43, 0x89, + 0x2c, 0x28, 0xb6, 0x4e, 0x2e, 0x98, 0x15, 0xb0, 0xa4, 0x60, 0x83, 0x0b, 0x14, 0x00, 0x6d, 0x2b, + 0x27, 0xcf, 0xf4, 0xd4, 0x6f, 0xd0, 0x69, 0x3b, 0x3d, 0xe4, 0x92, 0x99, 0x7e, 0x80, 0x1e, 0x7a, + 0xef, 0xb5, 0x87, 0x9e, 0x7b, 0xec, 0x4c, 0xfb, 0x0d, 0x7a, 0xed, 0xec, 0x2e, 0x00, 0x82, 0x7f, + 0x14, 0xab, 0x99, 0x49, 0xd3, 0x93, 0xb4, 0xbf, 0xf7, 0x7b, 0x8f, 0x6f, 0xdf, 0xfe, 0xb0, 0xef, + 0x01, 0x80, 0x2c, 0x1a, 0x98, 0xbe, 0xed, 0x85, 0xae, 0xbf, 0xed, 0xf9, 0x6e, 0xe8, 0xe2, 0x95, + 0xa1, 0xeb, 0x0e, 0x1d, 0x2a, 0x57, 0x27, 0xe3, 0x41, 0xed, 0x10, 0x56, 0x9f, 0xd8, 0x0e, 0x6d, + 0x26, 0xc4, 0x1e, 0x0d, 0xf1, 0x2e, 0xe4, 0x06, 0xb6, 0x43, 0x55, 0x65, 0x33, 0xbb, 0x55, 0xde, + 0xb9, 0xb9, 0x3d, 0xe3, 0xb4, 0x3d, 0xed, 0xd1, 0xe5, 0xb0, 0x2e, 0x3c, 0x6a, 0xff, 0xc8, 0xc1, + 0xda, 0x02, 0x2b, 0xc6, 0x90, 0x63, 0x64, 0xc4, 0x23, 0x2a, 0x5b, 0x25, 0x5d, 0xfc, 0x8f, 0x55, + 0x58, 0xf2, 0x88, 0xf9, 0x82, 0x0c, 0xa9, 0x9a, 0x11, 0x70, 0xbc, 0xc4, 0xef, 0x03, 0x58, 0xd4, + 0xa3, 0xcc, 0xa2, 0xcc, 0x3c, 0x53, 0xb3, 0x9b, 0xd9, 0xad, 0x92, 0x9e, 0x42, 0xf0, 0x3d, 0x58, + 0xf5, 0xc6, 0x27, 0x8e, 0x6d, 0x1a, 0x29, 0x1a, 0x6c, 0x66, 0xb7, 0xf2, 0x3a, 0x92, 0x86, 0xe6, + 0x84, 0x7c, 0x1b, 0x56, 0x5e, 0x51, 0xf2, 0x22, 0x4d, 0x2d, 0x0b, 0x6a, 0x95, 0xc3, 0x29, 0x62, + 0x03, 0x2a, 0x23, 0x1a, 0x04, 0x64, 0x48, 0x8d, 0xf0, 0xcc, 0xa3, 0x6a, 0x4e, 0xec, 0x7e, 0x73, + 0x6e, 0xf7, 0xb3, 0x3b, 0x2f, 0x47, 0x5e, 0xc7, 0x67, 0x1e, 0xc5, 0x75, 0x28, 0x51, 0x36, 0x1e, + 0xc9, 0x08, 0xf9, 0x73, 0xea, 0xa7, 0xb1, 0xf1, 0x68, 0x36, 0x4a, 0x91, 0xbb, 0x45, 0x21, 0x96, + 0x02, 0xea, 0xbf, 0xb4, 0x4d, 0xaa, 0x16, 0x44, 0x80, 0xdb, 0x73, 0x01, 0x7a, 0xd2, 0x3e, 0x1b, + 0x23, 0xf6, 0xc3, 0x0d, 0x28, 0xd1, 0xd7, 0x21, 0x65, 0x81, 0xed, 0x32, 0x75, 0x49, 0x04, 0xb9, + 0xb5, 0xe0, 0x14, 0xa9, 0x63, 0xcd, 0x86, 0x98, 0xf8, 0xe1, 0xc7, 0xb0, 0xe4, 0x7a, 0xa1, 0xed, + 0xb2, 0x40, 0x2d, 0x6e, 0x2a, 0x5b, 0xe5, 0x9d, 0xab, 0x0b, 0x85, 0xd0, 0x91, 0x1c, 0x3d, 0x26, + 0xe3, 0x16, 0xa0, 0xc0, 0x1d, 0xfb, 0x26, 0x35, 0x4c, 0xd7, 0xa2, 0x86, 0xcd, 0x06, 0xae, 0x5a, + 0x12, 0x01, 0xae, 0xcf, 0x6f, 0x44, 0x10, 0x1b, 0xae, 0x45, 0x5b, 0x6c, 0xe0, 0xea, 0xd5, 0x60, + 0x6a, 0x8d, 0x2f, 0x41, 0x21, 0x38, 0x63, 0x21, 0x79, 0xad, 0x56, 0x84, 0x42, 0xa2, 0x55, 0xed, + 0xdf, 0x79, 0x58, 0xb9, 0x88, 0xc4, 0x3e, 0x85, 0xfc, 0x80, 0xef, 0x52, 0xcd, 0xfc, 0x37, 0x35, + 0x90, 0x3e, 0xd3, 0x45, 0x2c, 0x7c, 0xc7, 0x22, 0xd6, 0xa1, 0xcc, 0x68, 0x10, 0x52, 0x4b, 0x2a, + 0x22, 0x7b, 0x41, 0x4d, 0x81, 0x74, 0x9a, 0x97, 0x54, 0xee, 0x3b, 0x49, 0xea, 0x19, 0xac, 0x24, + 0x29, 0x19, 0x3e, 0x61, 0xc3, 0x58, 0x9b, 0xf7, 0xdf, 0x96, 0xc9, 0xb6, 0x16, 0xfb, 0xe9, 0xdc, + 0x4d, 0xaf, 0xd2, 0xa9, 0x35, 0x6e, 0x02, 0xb8, 0x8c, 0xba, 0x03, 0xc3, 0xa2, 0xa6, 0xa3, 0x16, + 0xcf, 0xa9, 0x52, 0x87, 0x53, 0xe6, 0xaa, 0xe4, 0x4a, 0xd4, 0x74, 0xf0, 0x27, 0x13, 0xa9, 0x2d, + 0x9d, 0xa3, 0x94, 0x43, 0xf9, 0x90, 0xcd, 0xa9, 0xad, 0x0f, 0x55, 0x9f, 0x72, 0xdd, 0x53, 0x2b, + 0xda, 0x59, 0x49, 0x24, 0xb1, 0xfd, 0xd6, 0x9d, 0xe9, 0x91, 0x9b, 0xdc, 0xd8, 0xb2, 0x9f, 0x5e, + 0xe2, 0x0f, 0x20, 0x01, 0x0c, 0x21, 0x2b, 0x10, 0xb7, 0x50, 0x25, 0x06, 0x8f, 0xc8, 0x88, 0x6e, + 0xec, 0x42, 0x75, 0xba, 0x3c, 0x78, 0x1d, 0xf2, 0x41, 0x48, 0xfc, 0x50, 0xa8, 0x30, 0xaf, 0xcb, + 0x05, 0x46, 0x90, 0xa5, 0xcc, 0x12, 0xb7, 0x5c, 0x5e, 0xe7, 0xff, 0x6e, 0x7c, 0x0c, 0xcb, 0x53, + 0x3f, 0x7f, 0x51, 0xc7, 0xda, 0x6f, 0x0a, 0xb0, 0xbe, 0x48, 0x73, 0x0b, 0xe5, 0x7f, 0x09, 0x0a, + 0x6c, 0x3c, 0x3a, 0xa1, 0xbe, 0x9a, 0x15, 0x11, 0xa2, 0x15, 0xae, 0x43, 0xde, 0x21, 0x27, 0xd4, + 0x51, 0x73, 0x9b, 0xca, 0x56, 0x75, 0xe7, 0xde, 0x85, 0x54, 0xbd, 0xdd, 0xe6, 0x2e, 0xba, 0xf4, + 0xc4, 0x9f, 0x41, 0x2e, 0xba, 0xe2, 0x78, 0x84, 0xbb, 0x17, 0x8b, 0xc0, 0xb5, 0xa8, 0x0b, 0x3f, + 0x7c, 0x05, 0x4a, 0xfc, 0xaf, 0xac, 0x6d, 0x41, 0xe4, 0x5c, 0xe4, 0x00, 0xaf, 0x2b, 0xde, 0x80, + 0xa2, 0x90, 0x99, 0x45, 0xe3, 0xd6, 0x90, 0xac, 0xf9, 0xc1, 0x58, 0x74, 0x40, 0xc6, 0x4e, 0x68, + 0xbc, 0x24, 0xce, 0x98, 0x0a, 0xc1, 0x94, 0xf4, 0x4a, 0x04, 0xfe, 0x9c, 0x63, 0xf8, 0x3a, 0x94, + 0xa5, 0x2a, 0x6d, 0x66, 0xd1, 0xd7, 0xe2, 0xf6, 0xc9, 0xeb, 0x52, 0xa8, 0x2d, 0x8e, 0xf0, 0x9f, + 0x7f, 0x1e, 0xb8, 0x2c, 0x3e, 0x5a, 0xf1, 0x13, 0x1c, 0x10, 0x3f, 0xff, 0xf1, 0xec, 0xc5, 0x77, + 0x6d, 0xf1, 0xf6, 0x66, 0xb5, 0x58, 0xfb, 0x53, 0x06, 0x72, 0xe2, 0x79, 0x5b, 0x81, 0xf2, 0xf1, + 0x17, 0x5d, 0xcd, 0x68, 0x76, 0xfa, 0xfb, 0x6d, 0x0d, 0x29, 0xb8, 0x0a, 0x20, 0x80, 0x27, 0xed, + 0x4e, 0xfd, 0x18, 0x65, 0x92, 0x75, 0xeb, 0xe8, 0xf8, 0xf1, 0x43, 0x94, 0x4d, 0x1c, 0xfa, 0x12, + 0xc8, 0xa5, 0x09, 0x0f, 0x76, 0x50, 0x1e, 0x23, 0xa8, 0xc8, 0x00, 0xad, 0x67, 0x5a, 0xf3, 0xf1, + 0x43, 0x54, 0x98, 0x46, 0x1e, 0xec, 0xa0, 0x25, 0xbc, 0x0c, 0x25, 0x81, 0xec, 0x77, 0x3a, 0x6d, + 0x54, 0x4c, 0x62, 0xf6, 0x8e, 0xf5, 0xd6, 0xd1, 0x01, 0x2a, 0x25, 0x31, 0x0f, 0xf4, 0x4e, 0xbf, + 0x8b, 0x20, 0x89, 0x70, 0xa8, 0xf5, 0x7a, 0xf5, 0x03, 0x0d, 0x95, 0x13, 0xc6, 0xfe, 0x17, 0xc7, + 0x5a, 0x0f, 0x55, 0xa6, 0xd2, 0x7a, 0xb0, 0x83, 0x96, 0x93, 0x9f, 0xd0, 0x8e, 0xfa, 0x87, 0xa8, + 0x8a, 0x57, 0x61, 0x59, 0xfe, 0x44, 0x9c, 0xc4, 0xca, 0x0c, 0xf4, 0xf8, 0x21, 0x42, 0x93, 0x44, + 0x64, 0x94, 0xd5, 0x29, 0xe0, 0xf1, 0x43, 0x84, 0x6b, 0x0d, 0xc8, 0x0b, 0x75, 0x61, 0x0c, 0xd5, + 0x76, 0x7d, 0x5f, 0x6b, 0x1b, 0x9d, 0xee, 0x71, 0xab, 0x73, 0x54, 0x6f, 0x23, 0x65, 0x82, 0xe9, + 0xda, 0xcf, 0xfa, 0x2d, 0x5d, 0x6b, 0xa2, 0x4c, 0x1a, 0xeb, 0x6a, 0xf5, 0x63, 0xad, 0x89, 0xb2, + 0xb5, 0xbb, 0xb0, 0xbe, 0xe8, 0x9e, 0x59, 0xf4, 0x64, 0xd4, 0xbe, 0x56, 0x60, 0x6d, 0xc1, 0x95, + 0xb9, 0xf0, 0x29, 0xfa, 0x29, 0xe4, 0xa5, 0xd2, 0x64, 0x13, 0xb9, 0xb3, 0xf0, 0xee, 0x15, 0xba, + 0x9b, 0x6b, 0x24, 0xc2, 0x2f, 0xdd, 0x48, 0xb3, 0xe7, 0x34, 0x52, 0x1e, 0x62, 0x4e, 0x4e, 0xbf, + 0x52, 0x40, 0x3d, 0x2f, 0xf6, 0x5b, 0x9e, 0xf7, 0xcc, 0xd4, 0xf3, 0xfe, 0xe9, 0x6c, 0x02, 0x37, + 0xce, 0xdf, 0xc3, 0x5c, 0x16, 0xdf, 0x28, 0x70, 0x69, 0xf1, 0xbc, 0xb1, 0x30, 0x87, 0xcf, 0xa0, + 0x30, 0xa2, 0xe1, 0xa9, 0x1b, 0xf7, 0xdc, 0x0f, 0x17, 0xdc, 0xe4, 0xdc, 0x3c, 0x5b, 0xab, 0xc8, + 0x2b, 0xdd, 0x0a, 0xb2, 0xe7, 0x0d, 0x0d, 0x32, 0x9b, 0xb9, 0x4c, 0x7f, 0x9d, 0x81, 0x77, 0x17, + 0x06, 0x5f, 0x98, 0xe8, 0x35, 0x00, 0x9b, 0x79, 0xe3, 0x50, 0xf6, 0x55, 0x79, 0xcd, 0x94, 0x04, + 0x22, 0x1e, 0x61, 0x7e, 0x85, 0x8c, 0xc3, 0xc4, 0x9e, 0x15, 0x76, 0x90, 0x90, 0x20, 0xec, 0x4e, + 0x12, 0xcd, 0x89, 0x44, 0xdf, 0x3f, 0x67, 0xa7, 0x73, 0x2d, 0xeb, 0x23, 0x40, 0xa6, 0x63, 0x53, + 0x16, 0x1a, 0x41, 0xe8, 0x53, 0x32, 0xb2, 0xd9, 0x50, 0xdc, 0xa3, 0xc5, 0xbd, 0xfc, 0x80, 0x38, + 0x01, 0xd5, 0x57, 0xa4, 0xb9, 0x17, 0x5b, 0xb9, 0x87, 0x68, 0x16, 0x7e, 0xca, 0xa3, 0x30, 0xe5, + 0x21, 0xcd, 0x89, 0x47, 0xed, 0x6f, 0x4b, 0x50, 0x4e, 0x4d, 0x67, 0xf8, 0x06, 0x54, 0x9e, 0x93, + 0x97, 0xc4, 0x88, 0x27, 0x6e, 0x59, 0x89, 0x32, 0xc7, 0xba, 0xd1, 0xd4, 0xfd, 0x11, 0xac, 0x0b, + 0x8a, 0x3b, 0x0e, 0xa9, 0x6f, 0x98, 0x0e, 0x09, 0x02, 0x51, 0xb4, 0xa2, 0xa0, 0x62, 0x6e, 0xeb, + 0x70, 0x53, 0x23, 0xb6, 0xe0, 0x47, 0xb0, 0x26, 0x3c, 0x46, 0x63, 0x27, 0xb4, 0x3d, 0x87, 0x1a, + 0xfc, 0x1d, 0x20, 0x10, 0xf7, 0x69, 0x92, 0xd9, 0x2a, 0x67, 0x1c, 0x46, 0x04, 0x9e, 0x51, 0x80, + 0x0f, 0xe0, 0x9a, 0x70, 0x1b, 0x52, 0x46, 0x7d, 0x12, 0x52, 0x83, 0xfe, 0x72, 0x4c, 0x9c, 0xc0, + 0x20, 0xcc, 0x32, 0x4e, 0x49, 0x70, 0xaa, 0xae, 0xa7, 0x03, 0x5c, 0xe6, 0xdc, 0x83, 0x88, 0xaa, + 0x09, 0x66, 0x9d, 0x59, 0x9f, 0x93, 0xe0, 0x14, 0xef, 0xc1, 0x25, 0x11, 0x28, 0x08, 0x7d, 0x9b, + 0x0d, 0x0d, 0xf3, 0x94, 0x9a, 0x2f, 0x8c, 0x71, 0x38, 0xd8, 0x55, 0xaf, 0xa4, 0x23, 0x88, 0x24, + 0x7b, 0x82, 0xd3, 0xe0, 0x94, 0x7e, 0x38, 0xd8, 0xc5, 0x3d, 0xa8, 0xf0, 0xf3, 0x18, 0xd9, 0x5f, + 0x51, 0x63, 0xe0, 0xfa, 0xa2, 0x47, 0x54, 0x17, 0x3c, 0xdc, 0xa9, 0x22, 0x6e, 0x77, 0x22, 0x87, + 0x43, 0xd7, 0xa2, 0x7b, 0xf9, 0x5e, 0x57, 0xd3, 0x9a, 0x7a, 0x39, 0x8e, 0xf2, 0xc4, 0xf5, 0xb9, + 0xa6, 0x86, 0x6e, 0x52, 0xe3, 0xb2, 0xd4, 0xd4, 0xd0, 0x8d, 0x2b, 0xfc, 0x08, 0xd6, 0x4c, 0x53, + 0x6e, 0xdb, 0x36, 0x8d, 0x68, 0x58, 0x0f, 0x54, 0x34, 0x55, 0x2f, 0xd3, 0x3c, 0x90, 0x84, 0x48, + 0xe6, 0x01, 0xfe, 0x04, 0xde, 0x9d, 0xd4, 0x2b, 0xed, 0xb8, 0x3a, 0xb7, 0xcb, 0x59, 0xd7, 0x47, + 0xb0, 0xe6, 0x9d, 0xcd, 0x3b, 0xe2, 0xa9, 0x5f, 0xf4, 0xce, 0x66, 0xdd, 0x6e, 0x89, 0x17, 0x30, + 0x9f, 0x9a, 0x24, 0xa4, 0x96, 0xfa, 0x5e, 0x9a, 0x9d, 0x32, 0xe0, 0xfb, 0x80, 0x4c, 0xd3, 0xa0, + 0x8c, 0x9c, 0x38, 0xd4, 0x20, 0x3e, 0x65, 0x24, 0x50, 0xaf, 0xa7, 0xc9, 0x55, 0xd3, 0xd4, 0x84, + 0xb5, 0x2e, 0x8c, 0xf8, 0x2e, 0xac, 0xba, 0x27, 0xcf, 0x4d, 0x29, 0x2e, 0xc3, 0xf3, 0xe9, 0xc0, + 0x7e, 0xad, 0xde, 0x14, 0x65, 0x5a, 0xe1, 0x06, 0x21, 0xad, 0xae, 0x80, 0xf1, 0x1d, 0x40, 0x66, + 0x70, 0x4a, 0x7c, 0x4f, 0x34, 0xe9, 0xc0, 0x23, 0x26, 0x55, 0x6f, 0x49, 0xaa, 0xc4, 0x8f, 0x62, + 0x18, 0x6b, 0x70, 0x9d, 0x6f, 0x9e, 0x11, 0xe6, 0x1a, 0xe3, 0x80, 0x1a, 0x93, 0x14, 0x93, 0xb3, + 0xf8, 0x90, 0xa7, 0xa5, 0x5f, 0x8d, 0x69, 0xfd, 0x80, 0x36, 0x13, 0x52, 0x7c, 0x3c, 0xcf, 0x60, + 0x7d, 0xcc, 0x6c, 0x16, 0x52, 0xdf, 0xf3, 0x29, 0x77, 0x96, 0x0f, 0xac, 0xfa, 0xcf, 0xa5, 0x73, + 0x86, 0xee, 0x7e, 0x9a, 0x2d, 0x45, 0xa2, 0xaf, 0x8d, 0xe7, 0xc1, 0xda, 0x1e, 0x54, 0xd2, 0xda, + 0xc1, 0x25, 0x90, 0xea, 0x41, 0x0a, 0xef, 0xa8, 0x8d, 0x4e, 0x93, 0xf7, 0xc2, 0x2f, 0x35, 0x94, + 0xe1, 0x3d, 0xb9, 0xdd, 0x3a, 0xd6, 0x0c, 0xbd, 0x7f, 0x74, 0xdc, 0x3a, 0xd4, 0x50, 0xf6, 0x6e, + 0xa9, 0xf8, 0xaf, 0x25, 0xf4, 0xe6, 0xcd, 0x9b, 0x37, 0x99, 0xda, 0x5f, 0x32, 0x50, 0x9d, 0x9e, + 0x83, 0xf1, 0x4f, 0xe0, 0xbd, 0xf8, 0xa5, 0x35, 0xa0, 0xa1, 0xf1, 0xca, 0xf6, 0x85, 0x9c, 0x47, + 0x44, 0x4e, 0x92, 0xc9, 0x49, 0xac, 0x47, 0xac, 0x1e, 0x0d, 0x7f, 0x61, 0xfb, 0x5c, 0xac, 0x23, + 0x12, 0xe2, 0x36, 0x5c, 0x67, 0xae, 0x11, 0x84, 0x84, 0x59, 0xc4, 0xb7, 0x8c, 0xc9, 0xe7, 0x02, + 0x83, 0x98, 0x26, 0x0d, 0x02, 0x57, 0x76, 0x92, 0x24, 0xca, 0x55, 0xe6, 0xf6, 0x22, 0xf2, 0xe4, + 0x8a, 0xad, 0x47, 0xd4, 0x19, 0xd5, 0x64, 0xcf, 0x53, 0xcd, 0x15, 0x28, 0x8d, 0x88, 0x67, 0x50, + 0x16, 0xfa, 0x67, 0x62, 0x7a, 0x2b, 0xea, 0xc5, 0x11, 0xf1, 0x34, 0xbe, 0xfe, 0xfe, 0xce, 0x20, + 0x5d, 0xc7, 0xbf, 0x67, 0xa1, 0x92, 0x9e, 0xe0, 0xf8, 0x40, 0x6c, 0x8a, 0x6b, 0x5e, 0x11, 0xb7, + 0xc0, 0x07, 0xdf, 0x3a, 0xef, 0x6d, 0x37, 0xf8, 0xfd, 0xbf, 0x57, 0x90, 0x73, 0x95, 0x2e, 0x3d, + 0x79, 0xef, 0xe5, 0x5a, 0xa3, 0x72, 0x5a, 0x2f, 0xea, 0xd1, 0x0a, 0x1f, 0x40, 0xe1, 0x79, 0x20, + 0x62, 0x17, 0x44, 0xec, 0x9b, 0xdf, 0x1e, 0xfb, 0x69, 0x4f, 0x04, 0x2f, 0x3d, 0xed, 0x19, 0x47, + 0x1d, 0xfd, 0xb0, 0xde, 0xd6, 0x23, 0x77, 0x7c, 0x19, 0x72, 0x0e, 0xf9, 0xea, 0x6c, 0xba, 0x53, + 0x08, 0xe8, 0xa2, 0x85, 0xbf, 0x0c, 0xb9, 0x57, 0x94, 0xbc, 0x98, 0xbe, 0x9f, 0x05, 0xf4, 0x3d, + 0x4a, 0xff, 0x3e, 0xe4, 0x45, 0xbd, 0x30, 0x40, 0x54, 0x31, 0xf4, 0x0e, 0x2e, 0x42, 0xae, 0xd1, + 0xd1, 0xb9, 0xfc, 0x11, 0x54, 0x24, 0x6a, 0x74, 0x5b, 0x5a, 0x43, 0x43, 0x99, 0xda, 0x23, 0x28, + 0xc8, 0x22, 0xf0, 0x47, 0x23, 0x29, 0x03, 0x7a, 0x27, 0x5a, 0x46, 0x31, 0x94, 0xd8, 0xda, 0x3f, + 0xdc, 0xd7, 0x74, 0x94, 0x49, 0x1f, 0xef, 0x9f, 0x15, 0x28, 0xa7, 0x06, 0x2a, 0xde, 0xca, 0x89, + 0xe3, 0xb8, 0xaf, 0x0c, 0xe2, 0xd8, 0x24, 0x88, 0xce, 0x07, 0x04, 0x54, 0xe7, 0xc8, 0x45, 0xeb, + 0xf7, 0x3f, 0xd1, 0xe6, 0x1f, 0x14, 0x40, 0xb3, 0xc3, 0xd8, 0x4c, 0x82, 0xca, 0x0f, 0x9a, 0xe0, + 0xef, 0x15, 0xa8, 0x4e, 0x4f, 0x60, 0x33, 0xe9, 0xdd, 0xf8, 0x41, 0xd3, 0xfb, 0x9d, 0x02, 0xcb, + 0x53, 0x73, 0xd7, 0xff, 0x55, 0x76, 0xbf, 0xcd, 0xc2, 0xda, 0x02, 0x3f, 0x5c, 0x8f, 0x06, 0x54, + 0x39, 0x33, 0xff, 0xf8, 0x22, 0xbf, 0xb5, 0xcd, 0xfb, 0x5f, 0x97, 0xf8, 0x61, 0x34, 0xcf, 0xde, + 0x01, 0x64, 0x5b, 0x94, 0x85, 0xf6, 0xc0, 0xa6, 0x7e, 0xf4, 0x6e, 0x2c, 0xa7, 0xd6, 0x95, 0x09, + 0x2e, 0x5f, 0x8f, 0x7f, 0x04, 0xd8, 0x73, 0x03, 0x3b, 0xb4, 0x5f, 0x52, 0xc3, 0x66, 0xf1, 0x8b, + 0x34, 0x9f, 0x62, 0x73, 0x3a, 0x8a, 0x2d, 0x2d, 0x16, 0x26, 0x6c, 0x46, 0x87, 0x64, 0x86, 0xcd, + 0xaf, 0xa1, 0xac, 0x8e, 0x62, 0x4b, 0xc2, 0xbe, 0x01, 0x15, 0xcb, 0x1d, 0xf3, 0x81, 0x40, 0xf2, + 0xf8, 0xad, 0xa7, 0xe8, 0x65, 0x89, 0x25, 0x94, 0x68, 0x62, 0x9b, 0xbc, 0xc1, 0x57, 0xf4, 0xb2, + 0xc4, 0x24, 0xe5, 0x36, 0xac, 0x90, 0xe1, 0xd0, 0xe7, 0xc1, 0xe3, 0x40, 0x72, 0x0c, 0xad, 0x26, + 0xb0, 0x20, 0x6e, 0x3c, 0x85, 0x62, 0x5c, 0x07, 0xde, 0x58, 0x78, 0x25, 0x0c, 0x4f, 0x7e, 0x47, + 0xc9, 0xf0, 0x97, 0x7a, 0x16, 0x1b, 0x6f, 0x40, 0xc5, 0x0e, 0x8c, 0xc9, 0x07, 0xbd, 0xcc, 0x66, + 0x66, 0xab, 0xa8, 0x97, 0xed, 0x20, 0xf9, 0x82, 0x53, 0xfb, 0x26, 0x03, 0xd5, 0xe9, 0x0f, 0x92, + 0xb8, 0x09, 0x45, 0xc7, 0x35, 0x89, 0x10, 0x82, 0xfc, 0x1a, 0xbe, 0xf5, 0x96, 0x6f, 0x98, 0xdb, + 0xed, 0x88, 0xaf, 0x27, 0x9e, 0x1b, 0x7f, 0x55, 0xa0, 0x18, 0xc3, 0xf8, 0x12, 0xe4, 0x3c, 0x12, + 0x9e, 0x8a, 0x70, 0xf9, 0xfd, 0x0c, 0x52, 0x74, 0xb1, 0xe6, 0x78, 0xe0, 0x11, 0x26, 0x24, 0x10, + 0xe1, 0x7c, 0xcd, 0xcf, 0xd5, 0xa1, 0xc4, 0x12, 0x03, 0xae, 0x3b, 0x1a, 0x51, 0x16, 0x06, 0xf1, + 0xb9, 0x46, 0x78, 0x23, 0x82, 0xf1, 0x3d, 0x58, 0x0d, 0x7d, 0x62, 0x3b, 0x53, 0xdc, 0x9c, 0xe0, + 0xa2, 0xd8, 0x90, 0x90, 0xf7, 0xe0, 0x72, 0x1c, 0xd7, 0xa2, 0x21, 0x31, 0x4f, 0xa9, 0x35, 0x71, + 0x2a, 0x88, 0xaf, 0x5d, 0xef, 0x45, 0x84, 0x66, 0x64, 0x8f, 0x7d, 0xf7, 0x9f, 0xc1, 0x9a, 0xe9, + 0x8e, 0x66, 0x2b, 0xb1, 0x8f, 0x66, 0xde, 0xbb, 0x82, 0xcf, 0x95, 0x2f, 0x61, 0x32, 0x54, 0x7c, + 0x9d, 0xc9, 0x1e, 0x74, 0xf7, 0xff, 0x98, 0xd9, 0x38, 0x90, 0x7e, 0xdd, 0xb8, 0x82, 0x3a, 0x1d, + 0x38, 0xd4, 0xe4, 0xd5, 0xf9, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x42, 0x69, 0x71, 0xb3, + 0x18, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/gostring.go b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go similarity index 92% rename from components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/gostring.go rename to components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go index 76e2c95f9b..b175f555b8 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/gostring.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go @@ -1,12 +1,48 @@ +// Code generated by protoc-gen-gogo. +// source: descriptor.proto +// DO NOT EDIT! + +/* +Package descriptor is a generated protocol buffer package. + +It is generated from these files: + descriptor.proto + +It has these top-level messages: + FileDescriptorSet + FileDescriptorProto + DescriptorProto + FieldDescriptorProto + OneofDescriptorProto + EnumDescriptorProto + EnumValueDescriptorProto + ServiceDescriptorProto + MethodDescriptorProto + FileOptions + MessageOptions + FieldOptions + EnumOptions + EnumValueOptions + ServiceOptions + MethodOptions + UninterpretedOption + SourceCodeInfo +*/ package descriptor import fmt "fmt" - import strings "strings" import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" import sort "sort" import strconv "strconv" import reflect "reflect" +import proto "github.com/gogo/protobuf/proto" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf func (this *FileDescriptorSet) GoString() string { if this == nil { @@ -353,9 +389,7 @@ func (this *FileOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -383,9 +417,7 @@ func (this *MessageOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -419,9 +451,7 @@ func (this *FieldOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -443,9 +473,7 @@ func (this *EnumOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -464,9 +492,7 @@ func (this *EnumValueOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -485,9 +511,7 @@ func (this *ServiceOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -506,9 +530,7 @@ func (this *MethodOptions) GoString() string { if this.UninterpretedOption != nil { s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n") } - if this.XXX_extensions != nil { - s = append(s, "XXX_extensions: "+extensionToGoStringDescriptor(this.XXX_extensions)+",\n") - } + s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n") if this.XXX_unrecognized != nil { s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") } @@ -616,11 +638,12 @@ func valueToGoStringDescriptor(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringDescriptor(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringDescriptor(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -630,6 +653,6 @@ func extensionToGoStringDescriptor(e map[int32]github_com_gogo_protobuf_proto.Ex for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go index ab170f913a..861f4d028d 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go @@ -1,4 +1,6 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. // http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without diff --git a/components/engine/vendor/src/github.com/gogo/protobuf/sortkeys/sortkeys.go b/components/engine/vendor/src/github.com/gogo/protobuf/sortkeys/sortkeys.go index c52878dd59..ceadde6a5e 100644 --- a/components/engine/vendor/src/github.com/gogo/protobuf/sortkeys/sortkeys.go +++ b/components/engine/vendor/src/github.com/gogo/protobuf/sortkeys/sortkeys.go @@ -1,4 +1,6 @@ -// Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved. +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. // http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/Makefile b/components/engine/vendor/src/github.com/golang/protobuf/proto/Makefile index f1f06564a1..e2e0651a93 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/Makefile +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/Makefile @@ -39,5 +39,5 @@ test: install generate-test-pbs generate-test-pbs: make install make -C testdata - protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto + protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto make diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/clone.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/clone.go index e98ddec981..e392575b35 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/clone.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/clone.go @@ -84,9 +84,15 @@ func mergeStruct(out, in reflect.Value) { mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } - if emIn, ok := in.Addr().Interface().(extendableProto); ok { - emOut := out.Addr().Interface().(extendableProto) - mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) + if emIn, ok := extendable(in.Addr().Interface()); ok { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } } uf := in.FieldByName("XXX_unrecognized") diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/decode.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/decode.go index 5810782fd8..04dcb88130 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/decode.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/decode.go @@ -378,6 +378,11 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group wire := int(u & 0x7) if wire == WireEndGroup { if is_group { + if required > 0 { + // Not enough information to determine the exact field. + // (See below.) + return &RequiredNotSetError{"{Unknown}"} + } return nil // input is satisfied } return fmt.Errorf("proto: %s: wiretype end group for non-group", st) @@ -390,11 +395,12 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group if !ok { // Maybe it's an extension? if prop.extendable { - if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) { + if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { if err = o.skip(st, tag, wire); err == nil { - ext := e.ExtensionMap()[int32(tag)] // may be missing + extmap := e.extensionsWrite() + ext := extmap[int32(tag)] // may be missing ext.enc = append(ext.enc, o.buf[oi:o.index]...) - e.ExtensionMap()[int32(tag)] = ext + extmap[int32(tag)] = ext } continue } @@ -768,10 +774,11 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { } } keyelem, valelem := keyptr.Elem(), valptr.Elem() - if !keyelem.IsValid() || !valelem.IsValid() { - // We did not decode the key or the value in the map entry. - // Either way, it's an invalid map entry. - return fmt.Errorf("proto: bad map data: missing key/val") + if !keyelem.IsValid() { + keyelem = reflect.Zero(p.mtype.Key()) + } + if !valelem.IsValid() { + valelem = reflect.Zero(p.mtype.Elem()) } v.SetMapIndex(keyelem, valelem) diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/encode.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/encode.go index 231b07401a..8c1b8fd1f6 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/encode.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/encode.go @@ -64,8 +64,16 @@ var ( // a struct with a repeated field containing a nil element. errRepeatedHasNil = errors.New("proto: repeated field has nil element") + // errOneofHasNil is the error returned if Marshal is called with + // a struct with a oneof field containing a nil element. + errOneofHasNil = errors.New("proto: oneof field has nil value") + // ErrNil is the error returned if Marshal is called with nil. ErrNil = errors.New("proto: Marshal called with nil") + + // ErrTooLarge is the error returned if Marshal is called with a + // message that encodes to >2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") ) // The fundamental encoders that put bytes on the wire. @@ -74,6 +82,10 @@ var ( const maxVarintBytes = 10 // maximum length of a varint +// maxMarshalSize is the largest allowed size of an encoded protobuf, +// since C++ and Java use signed int32s for the size. +const maxMarshalSize = 1<<31 - 1 + // EncodeVarint returns the varint encoding of x. // This is the format for the // int32, int64, uint32, uint64, bool, and enum @@ -273,6 +285,9 @@ func (p *Buffer) Marshal(pb Message) error { stats.Encode++ } + if len(p.buf) > maxMarshalSize { + return ErrTooLarge + } return err } @@ -1058,10 +1073,25 @@ func size_slice_struct_group(p *Properties, base structPointer) (n int) { // Encode an extension map. func (o *Buffer) enc_map(p *Properties, base structPointer) error { - v := *structPointer_ExtMap(base, p.field) - if err := encodeExtensionMap(v); err != nil { + exts := structPointer_ExtMap(base, p.field) + if err := encodeExtensionsMap(*exts); err != nil { return err } + + return o.enc_map_body(*exts) +} + +func (o *Buffer) enc_exts(p *Properties, base structPointer) error { + exts := structPointer_Extensions(base, p.field) + if err := encodeExtensions(exts); err != nil { + return err + } + v, _ := exts.extensionsRead() + + return o.enc_map_body(v) +} + +func (o *Buffer) enc_map_body(v map[int32]Extension) error { // Fast-path for common cases: zero or one extensions. if len(v) <= 1 { for _, e := range v { @@ -1084,8 +1114,13 @@ func (o *Buffer) enc_map(p *Properties, base structPointer) error { } func size_map(p *Properties, base structPointer) int { - v := *structPointer_ExtMap(base, p.field) - return sizeExtensionMap(v) + v := structPointer_ExtMap(base, p.field) + return extensionsMapSize(*v) +} + +func size_exts(p *Properties, base structPointer) int { + v := structPointer_Extensions(base, p.field) + return extensionsSize(v) } // Encode a map field. @@ -1114,7 +1149,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { return err } - if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { + if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { return err } return nil @@ -1124,11 +1159,6 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { for _, key := range v.MapKeys() { val := v.MapIndex(key) - // The only illegal map entry values are nil message pointers. - if val.Kind() == reflect.Ptr && val.IsNil() { - return errors.New("proto: map has nil element") - } - keycopy.Set(key) valcopy.Set(val) @@ -1216,13 +1246,18 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { return err } } + if len(o.buf) > maxMarshalSize { + return ErrTooLarge + } } } // Do oneof fields. if prop.oneofMarshaler != nil { m := structPointer_Interface(base, prop.stype).(Message) - if err := prop.oneofMarshaler(m, o); err != nil { + if err := prop.oneofMarshaler(m, o); err == ErrNil { + return errOneofHasNil + } else if err != nil { return err } } @@ -1230,6 +1265,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { // Add unrecognized fields at the end. if prop.unrecField.IsValid() { v := *structPointer_Bytes(base, prop.unrecField) + if len(o.buf)+len(v) > maxMarshalSize { + return ErrTooLarge + } if len(v) > 0 { o.buf = append(o.buf, v...) } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/equal.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/equal.go index f5db1def3c..2ed1cf5966 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/equal.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/equal.go @@ -54,13 +54,17 @@ Equality is defined in this way: in a proto3 .proto file, fields are not "set"; specifically, zero length proto3 "bytes" fields are equal (nil == {}). - Two repeated fields are equal iff their lengths are the same, - and their corresponding elements are equal (a "bytes" field, - although represented by []byte, is not a repeated field) + and their corresponding elements are equal. Note a "bytes" field, + although represented by []byte, is not a repeated field and the + rule for the scalar fields described above applies. - Two unset fields are equal. - Two unknown field sets are equal if their current encoded state is equal. - Two extension sets are equal iff they have corresponding elements that are pairwise equal. + - Two map fields are equal iff their lengths are the same, + and they contain the same set of elements. Zero-length map + fields are equal. - Every other combination of things are not equal. The return value is undefined if a and b are not protocol buffers. @@ -121,9 +125,16 @@ func equalStruct(v1, v2 reflect.Value) bool { } } + if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() { + em2 := v2.FieldByName("XXX_InternalExtensions") + if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) { + return false + } + } + if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() { em2 := v2.FieldByName("XXX_extensions") - if !equalExtensions(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { + if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) { return false } } @@ -184,6 +195,13 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool { } return true case reflect.Ptr: + // Maps may have nil values in them, so check for nil. + if v1.IsNil() && v2.IsNil() { + return true + } + if v1.IsNil() != v2.IsNil() { + return false + } return equalAny(v1.Elem(), v2.Elem(), prop) case reflect.Slice: if v1.Type().Elem().Kind() == reflect.Uint8 { @@ -223,8 +241,14 @@ func equalAny(v1, v2 reflect.Value, prop *Properties) bool { } // base is the struct type that the extensions are based on. -// em1 and em2 are extension maps. -func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool { +// x1 and x2 are InternalExtensions. +func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool { + em1, _ := x1.extensionsRead() + em2, _ := x2.extensionsRead() + return equalExtMap(base, em1, em2) +} + +func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { if len(em1) != len(em2) { return false } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/extensions.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/extensions.go index 054f4f1df7..6b9b363746 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/extensions.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/extensions.go @@ -52,14 +52,99 @@ type ExtensionRange struct { Start, End int32 // both inclusive } -// extendableProto is an interface implemented by any protocol buffer that may be extended. +// extendableProto is an interface implemented by any protocol buffer generated by the current +// proto compiler that may be extended. type extendableProto interface { + Message + ExtensionRangeArray() []ExtensionRange + extensionsWrite() map[int32]Extension + extensionsRead() (map[int32]Extension, sync.Locker) +} + +// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous +// version of the proto compiler that may be extended. +type extendableProtoV1 interface { Message ExtensionRangeArray() []ExtensionRange ExtensionMap() map[int32]Extension } +// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto. +type extensionAdapter struct { + extendableProtoV1 +} + +func (e extensionAdapter) extensionsWrite() map[int32]Extension { + return e.ExtensionMap() +} + +func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) { + return e.ExtensionMap(), notLocker{} +} + +// notLocker is a sync.Locker whose Lock and Unlock methods are nops. +type notLocker struct{} + +func (n notLocker) Lock() {} +func (n notLocker) Unlock() {} + +// extendable returns the extendableProto interface for the given generated proto message. +// If the proto message has the old extension format, it returns a wrapper that implements +// the extendableProto interface. +func extendable(p interface{}) (extendableProto, bool) { + if ep, ok := p.(extendableProto); ok { + return ep, ok + } + if ep, ok := p.(extendableProtoV1); ok { + return extensionAdapter{ep}, ok + } + return nil, false +} + +// XXX_InternalExtensions is an internal representation of proto extensions. +// +// Each generated message struct type embeds an anonymous XXX_InternalExtensions field, +// thus gaining the unexported 'extensions' method, which can be called only from the proto package. +// +// The methods of XXX_InternalExtensions are not concurrency safe in general, +// but calls to logically read-only methods such as has and get may be executed concurrently. +type XXX_InternalExtensions struct { + // The struct must be indirect so that if a user inadvertently copies a + // generated message and its embedded XXX_InternalExtensions, they + // avoid the mayhem of a copied mutex. + // + // The mutex serializes all logically read-only operations to p.extensionMap. + // It is up to the client to ensure that write operations to p.extensionMap are + // mutually exclusive with other accesses. + p *struct { + mu sync.Mutex + extensionMap map[int32]Extension + } +} + +// extensionsWrite returns the extension map, creating it on first use. +func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension { + if e.p == nil { + e.p = new(struct { + mu sync.Mutex + extensionMap map[int32]Extension + }) + e.p.extensionMap = make(map[int32]Extension) + } + return e.p.extensionMap +} + +// extensionsRead returns the extensions map for read-only use. It may be nil. +// The caller must hold the returned mutex's lock when accessing Elements within the map. +func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) { + if e.p == nil { + return nil, nil + } + return e.p.extensionMap, &e.p.mu +} + var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem() +var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem() // ExtensionDesc represents an extension specification. // Used in generated code from the protocol compiler. @@ -92,8 +177,13 @@ type Extension struct { } // SetRawExtension is for testing only. -func SetRawExtension(base extendableProto, id int32, b []byte) { - base.ExtensionMap()[id] = Extension{enc: b} +func SetRawExtension(base Message, id int32, b []byte) { + epb, ok := extendable(base) + if !ok { + return + } + extmap := epb.extensionsWrite() + extmap[id] = Extension{enc: b} } // isExtensionField returns true iff the given field number is in an extension range. @@ -108,8 +198,12 @@ func isExtensionField(pb extendableProto, field int32) bool { // checkExtensionTypes checks that the given extension is valid for pb. func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error { + var pbi interface{} = pb // Check the extended type. - if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b { + if ea, ok := pbi.(extensionAdapter); ok { + pbi = ea.extendableProtoV1 + } + if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b { return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String()) } // Check the range. @@ -155,8 +249,19 @@ func extensionProperties(ed *ExtensionDesc) *Properties { return prop } -// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m. -func encodeExtensionMap(m map[int32]Extension) error { +// encode encodes any unmarshaled (unencoded) extensions in e. +func encodeExtensions(e *XXX_InternalExtensions) error { + m, mu := e.extensionsRead() + if m == nil { + return nil // fast path + } + mu.Lock() + defer mu.Unlock() + return encodeExtensionsMap(m) +} + +// encode encodes any unmarshaled (unencoded) extensions in e. +func encodeExtensionsMap(m map[int32]Extension) error { for k, e := range m { if e.value == nil || e.desc == nil { // Extension is only in its encoded form. @@ -184,7 +289,17 @@ func encodeExtensionMap(m map[int32]Extension) error { return nil } -func sizeExtensionMap(m map[int32]Extension) (n int) { +func extensionsSize(e *XXX_InternalExtensions) (n int) { + m, mu := e.extensionsRead() + if m == nil { + return 0 + } + mu.Lock() + defer mu.Unlock() + return extensionsMapSize(m) +} + +func extensionsMapSize(m map[int32]Extension) (n int) { for _, e := range m { if e.value == nil || e.desc == nil { // Extension is only in its encoded form. @@ -209,26 +324,51 @@ func sizeExtensionMap(m map[int32]Extension) (n int) { } // HasExtension returns whether the given extension is present in pb. -func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { +func HasExtension(pb Message, extension *ExtensionDesc) bool { // TODO: Check types, field numbers, etc.? - _, ok := pb.ExtensionMap()[extension.Field] + epb, ok := extendable(pb) + if !ok { + return false + } + extmap, mu := epb.extensionsRead() + if extmap == nil { + return false + } + mu.Lock() + _, ok = extmap[extension.Field] + mu.Unlock() return ok } // ClearExtension removes the given extension from pb. -func ClearExtension(pb extendableProto, extension *ExtensionDesc) { +func ClearExtension(pb Message, extension *ExtensionDesc) { + epb, ok := extendable(pb) + if !ok { + return + } // TODO: Check types, field numbers, etc.? - delete(pb.ExtensionMap(), extension.Field) + extmap := epb.extensionsWrite() + delete(extmap, extension.Field) } // GetExtension parses and returns the given extension of pb. // If the extension is not present and has no default value it returns ErrMissingExtension. -func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { - if err := checkExtensionTypes(pb, extension); err != nil { +func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { + epb, ok := extendable(pb) + if !ok { + return nil, errors.New("proto: not an extendable proto") + } + + if err := checkExtensionTypes(epb, extension); err != nil { return nil, err } - emap := pb.ExtensionMap() + emap, mu := epb.extensionsRead() + if emap == nil { + return defaultExtensionValue(extension) + } + mu.Lock() + defer mu.Unlock() e, ok := emap[extension.Field] if !ok { // defaultExtensionValue returns the default value or @@ -332,10 +472,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) { // GetExtensions returns a slice of the extensions present in pb that are also listed in es. // The returned slice has the same length as es; missing extensions will appear as nil elements. func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { - epb, ok := pb.(extendableProto) + epb, ok := extendable(pb) if !ok { - err = errors.New("proto: not an extendable proto") - return + return nil, errors.New("proto: not an extendable proto") } extensions = make([]interface{}, len(es)) for i, e := range es { @@ -350,9 +489,44 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e return } +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing +// just the Field field, which defines the extension's field number. +func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { + epb, ok := extendable(pb) + if !ok { + return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + if emap == nil { + return nil, nil + } + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + // SetExtension sets the specified extension of pb to the specified value. -func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { - if err := checkExtensionTypes(pb, extension); err != nil { +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + epb, ok := extendable(pb) + if !ok { + return errors.New("proto: not an extendable proto") + } + if err := checkExtensionTypes(epb, extension); err != nil { return err } typ := reflect.TypeOf(extension.ExtensionType) @@ -368,10 +542,23 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{ return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) } - pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value} + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: value} return nil } +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + epb, ok := extendable(pb) + if !ok { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) + } +} + // A global registry of extensions. // The generated code will register the generated descriptors by calling RegisterExtension. diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/lib.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/lib.go index 0de8f8dffd..ac4ddbc075 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/lib.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/lib.go @@ -308,7 +308,7 @@ func GetStats() Stats { return stats } // temporary Buffer and are fine for most applications. type Buffer struct { buf []byte // encode/decode byte stream - index int // write point + index int // read point // pools of basic types to amortize allocation. bools []bool @@ -889,6 +889,10 @@ func isProto3Zero(v reflect.Value) bool { return false } +// ProtoPackageIsVersion2 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion2 = true + // ProtoPackageIsVersion1 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the proto package. const ProtoPackageIsVersion1 = true diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/message_set.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/message_set.go index e25e01e637..fd982decd6 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/message_set.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/message_set.go @@ -149,9 +149,21 @@ func skipVarint(buf []byte) []byte { // MarshalMessageSet encodes the extension map represented by m in the message set wire format. // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { - if err := encodeExtensionMap(m); err != nil { - return nil, err +func MarshalMessageSet(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + if err := encodeExtensions(exts); err != nil { + return nil, err + } + m, _ = exts.extensionsRead() + case map[int32]Extension: + if err := encodeExtensionsMap(exts); err != nil { + return nil, err + } + m = exts + default: + return nil, errors.New("proto: not an extension map") } // Sort extension IDs to provide a deterministic encoding. @@ -178,7 +190,17 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) { // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { +func UnmarshalMessageSet(buf []byte, exts interface{}) error { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + ms := new(messageSet) if err := Unmarshal(buf, ms); err != nil { return err @@ -209,7 +231,16 @@ func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { // MarshalMessageSetJSON encodes the extension map represented by m in JSON format. // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { +func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m, _ = exts.extensionsRead() + case map[int32]Extension: + m = exts + default: + return nil, errors.New("proto: not an extension map") + } var b bytes.Buffer b.WriteByte('{') @@ -252,7 +283,7 @@ func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. -func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { +func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { // Common-case fast path. if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { return nil diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_reflect.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_reflect.go index 749919d250..fb512e2e16 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_reflect.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_reflect.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build appengine +// +build appengine js // This file contains an implementation of proto field accesses using package reflect. // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can @@ -139,6 +139,11 @@ func structPointer_StringSlice(p structPointer, f field) *[]string { return structPointer_ifield(p, f).(*[]string) } +// Extensions returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return structPointer_ifield(p, f).(*XXX_InternalExtensions) +} + // ExtMap returns the address of an extension map field in the struct. func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return structPointer_ifield(p, f).(*map[int32]Extension) diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_unsafe.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_unsafe.go index e9be0fe92e..6b5567d47c 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_unsafe.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -29,7 +29,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +build !appengine +// +build !appengine,!js // This file contains the implementation of the proto field accesses using package unsafe. @@ -126,6 +126,10 @@ func structPointer_StringSlice(p structPointer, f field) *[]string { } // ExtMap returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/properties.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/properties.go index 4fe2ec22e8..ec2289c005 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/properties.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/properties.go @@ -473,17 +473,13 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock p.dec = (*Buffer).dec_slice_int64 p.packedDec = (*Buffer).dec_slice_packed_int64 case reflect.Uint8: - p.enc = (*Buffer).enc_slice_byte p.dec = (*Buffer).dec_slice_byte - p.size = size_slice_byte - // This is a []byte, which is either a bytes field, - // or the value of a map field. In the latter case, - // we always encode an empty []byte, so we should not - // use the proto3 enc/size funcs. - // f == nil iff this is the key/value of a map field. - if p.proto3 && f != nil { + if p.proto3 { p.enc = (*Buffer).enc_proto3_slice_byte p.size = size_proto3_slice_byte + } else { + p.enc = (*Buffer).enc_slice_byte + p.size = size_slice_byte } case reflect.Float32, reflect.Float64: switch t2.Bits() { @@ -682,7 +678,8 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { propertiesMap[t] = prop // build properties - prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) + prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || + reflect.PtrTo(t).Implements(extendableProtoV1Type) prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) @@ -693,15 +690,22 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { name := f.Name p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) - if f.Name == "XXX_extensions" { // special case + if f.Name == "XXX_InternalExtensions" { // special case + p.enc = (*Buffer).enc_exts + p.dec = nil // not needed + p.size = size_exts + } else if f.Name == "XXX_extensions" { // special case p.enc = (*Buffer).enc_map p.dec = nil // not needed p.size = size_map - } - if f.Name == "XXX_unrecognized" { // special case + } else if f.Name == "XXX_unrecognized" { // special case prop.unrecField = toField(&f) } - oneof := f.Tag.Get("protobuf_oneof") != "" // special case + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof + } prop.Prop[i] = p prop.order[i] = i if debug { @@ -711,7 +715,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { } print("\n") } - if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof { + if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") } } @@ -840,7 +844,29 @@ func RegisterType(x Message, name string) { } // MessageName returns the fully-qualified proto name for the given message type. -func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] } +func MessageName(x Message) string { + type xname interface { + XXX_MessageName() string + } + if m, ok := x.(xname); ok { + return m.XXX_MessageName() + } + return revProtoTypes[reflect.TypeOf(x)] +} // MessageType returns the message type (pointer to struct) for a named message. func MessageType(name string) reflect.Type { return protoTypes[name] } + +// A registry of all linked proto files. +var ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/text.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/text.go index 1cbaf86d39..965876bf03 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/text.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/text.go @@ -154,7 +154,7 @@ func (w *textWriter) indent() { w.ind++ } func (w *textWriter) unindent() { if w.ind == 0 { - log.Printf("proto: textWriter unindented too far") + log.Print("proto: textWriter unindented too far") return } w.ind-- @@ -175,7 +175,93 @@ type raw interface { Bytes() []byte } -func writeStruct(w *textWriter, sv reflect.Value) error { +func requiresQuotes(u string) bool { + // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. + for _, ch := range u { + switch { + case ch == '.' || ch == '/' || ch == '_': + continue + case '0' <= ch && ch <= '9': + continue + case 'A' <= ch && ch <= 'Z': + continue + case 'a' <= ch && ch <= 'z': + continue + default: + return true + } + } + return false +} + +// isAny reports whether sv is a google.protobuf.Any message +func isAny(sv reflect.Value) bool { + type wkt interface { + XXX_WellKnownType() string + } + t, ok := sv.Addr().Interface().(wkt) + return ok && t.XXX_WellKnownType() == "Any" +} + +// writeProto3Any writes an expanded google.protobuf.Any message. +// +// It returns (false, nil) if sv value can't be unmarshaled (e.g. because +// required messages are not linked in). +// +// It returns (true, error) when sv was written in expanded format or an error +// was encountered. +func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { + turl := sv.FieldByName("TypeUrl") + val := sv.FieldByName("Value") + if !turl.IsValid() || !val.IsValid() { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + b, ok := val.Interface().([]byte) + if !ok { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + parts := strings.Split(turl.String(), "/") + mt := MessageType(parts[len(parts)-1]) + if mt == nil { + return false, nil + } + m := reflect.New(mt.Elem()) + if err := Unmarshal(b, m.Interface().(Message)); err != nil { + return false, nil + } + w.Write([]byte("[")) + u := turl.String() + if requiresQuotes(u) { + writeString(w, u) + } else { + w.Write([]byte(u)) + } + if w.compact { + w.Write([]byte("]:<")) + } else { + w.Write([]byte("]: <\n")) + w.ind++ + } + if err := tm.writeStruct(w, m.Elem()); err != nil { + return true, err + } + if w.compact { + w.Write([]byte("> ")) + } else { + w.ind-- + w.Write([]byte(">\n")) + } + return true, nil +} + +func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { + if tm.ExpandAny && isAny(sv) { + if canExpand, err := tm.writeProto3Any(w, sv); canExpand { + return err + } + } st := sv.Type() sprops := GetProperties(st) for i := 0; i < sv.NumField(); i++ { @@ -227,7 +313,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error { } continue } - if err := writeAny(w, v, props); err != nil { + if err := tm.writeAny(w, v, props); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -269,7 +355,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if err := writeAny(w, key, props.mkeyprop); err != nil { + if err := tm.writeAny(w, key, props.mkeyprop); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -286,7 +372,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error { return err } } - if err := writeAny(w, val, props.mvalprop); err != nil { + if err := tm.writeAny(w, val, props.mvalprop); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -358,7 +444,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error { } // Enums have a String method, so writeAny will work fine. - if err := writeAny(w, fv, props); err != nil { + if err := tm.writeAny(w, fv, props); err != nil { return err } @@ -369,8 +455,8 @@ func writeStruct(w *textWriter, sv reflect.Value) error { // Extensions (the XXX_extensions field). pv := sv.Addr() - if pv.Type().Implements(extendableProtoType) { - if err := writeExtensions(w, pv); err != nil { + if _, ok := extendable(pv.Interface()); ok { + if err := tm.writeExtensions(w, pv); err != nil { return err } } @@ -400,7 +486,7 @@ func writeRaw(w *textWriter, b []byte) error { } // writeAny writes an arbitrary field. -func writeAny(w *textWriter, v reflect.Value, props *Properties) error { +func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { v = reflect.Indirect(v) // Floats have special cases. @@ -427,7 +513,7 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error { switch v.Kind() { case reflect.Slice: // Should only be a []byte; repeated fields are handled in writeStruct. - if err := writeString(w, string(v.Interface().([]byte))); err != nil { + if err := writeString(w, string(v.Bytes())); err != nil { return err } case reflect.String: @@ -449,15 +535,15 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error { } } w.indent() - if tm, ok := v.Interface().(encoding.TextMarshaler); ok { - text, err := tm.MarshalText() + if etm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() if err != nil { return err } if _, err = w.Write(text); err != nil { return err } - } else if err := writeStruct(w, v); err != nil { + } else if err := tm.writeStruct(w, v); err != nil { return err } w.unindent() @@ -601,19 +687,24 @@ func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // writeExtensions writes all the extensions in pv. // pv is assumed to be a pointer to a protocol message struct that is extendable. -func writeExtensions(w *textWriter, pv reflect.Value) error { +func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { emap := extensionMaps[pv.Type().Elem()] - ep := pv.Interface().(extendableProto) + ep, _ := extendable(pv.Interface()) // Order the extensions by ID. // This isn't strictly necessary, but it will give us // canonical output, which will also make testing easier. - m := ep.ExtensionMap() + m, mu := ep.extensionsRead() + if m == nil { + return nil + } + mu.Lock() ids := make([]int32, 0, len(m)) for id := range m { ids = append(ids, id) } sort.Sort(int32Slice(ids)) + mu.Unlock() for _, extNum := range ids { ext := m[extNum] @@ -636,13 +727,13 @@ func writeExtensions(w *textWriter, pv reflect.Value) error { // Repeated extensions will appear as a slice. if !desc.repeated() { - if err := writeExtension(w, desc.Name, pb); err != nil { + if err := tm.writeExtension(w, desc.Name, pb); err != nil { return err } } else { v := reflect.ValueOf(pb) for i := 0; i < v.Len(); i++ { - if err := writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { return err } } @@ -651,7 +742,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error { return nil } -func writeExtension(w *textWriter, name string, pb interface{}) error { +func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { return err } @@ -660,7 +751,7 @@ func writeExtension(w *textWriter, name string, pb interface{}) error { return err } } - if err := writeAny(w, reflect.ValueOf(pb), nil); err != nil { + if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { return err } if err := w.WriteByte('\n'); err != nil { @@ -687,12 +778,13 @@ func (w *textWriter) writeIndent() { // TextMarshaler is a configurable text format marshaler. type TextMarshaler struct { - Compact bool // use compact text format (one line). + Compact bool // use compact text format (one line). + ExpandAny bool // expand google.protobuf.Any messages of known types } // Marshal writes a given protocol buffer in text format. // The only errors returned are from w. -func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error { +func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { val := reflect.ValueOf(pb) if pb == nil || val.IsNil() { w.Write([]byte("")) @@ -707,11 +799,11 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error { aw := &textWriter{ w: ww, complete: true, - compact: m.Compact, + compact: tm.Compact, } - if tm, ok := pb.(encoding.TextMarshaler); ok { - text, err := tm.MarshalText() + if etm, ok := pb.(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() if err != nil { return err } @@ -725,7 +817,7 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error { } // Dereference the received pointer so we don't have outer < and >. v := reflect.Indirect(val) - if err := writeStruct(aw, v); err != nil { + if err := tm.writeStruct(aw, v); err != nil { return err } if bw != nil { @@ -735,9 +827,9 @@ func (m *TextMarshaler) Marshal(w io.Writer, pb Message) error { } // Text is the same as Marshal, but returns the string directly. -func (m *TextMarshaler) Text(pb Message) string { +func (tm *TextMarshaler) Text(pb Message) string { var buf bytes.Buffer - m.Marshal(&buf, pb) + tm.Marshal(&buf, pb) return buf.String() } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/proto/text_parser.go b/components/engine/vendor/src/github.com/golang/protobuf/proto/text_parser.go index 451323262c..4fd0531293 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/proto/text_parser.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/proto/text_parser.go @@ -44,6 +44,9 @@ import ( "unicode/utf8" ) +// Error string emitted when deserializing Any and fields are already set +const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" + type ParseError struct { Message string Line int // 1-based line number @@ -163,7 +166,7 @@ func (p *textParser) advance() { p.cur.offset, p.cur.line = p.offset, p.line p.cur.unquoted = "" switch p.s[0] { - case '<', '>', '{', '}', ':', '[', ']', ';', ',': + case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': // Single symbol p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] case '"', '\'': @@ -451,7 +454,10 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { fieldSet := make(map[string]bool) // A struct is a sequence of "name: value", terminated by one of // '>' or '}', or the end of the input. A name may also be - // "[extension]". + // "[extension]" or "[type/url]". + // + // The whole struct can also be an expanded Any message, like: + // [type/url] < ... struct contents ... > for { tok := p.next() if tok.err != nil { @@ -461,33 +467,74 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { break } if tok.value == "[" { - // Looks like an extension. + // Looks like an extension or an Any. // // TODO: Check whether we need to handle // namespace rooted names (e.g. ".something.Foo"). - tok = p.next() - if tok.err != nil { - return tok.err + extName, err := p.consumeExtName() + if err != nil { + return err } + + if s := strings.LastIndex(extName, "/"); s >= 0 { + // If it contains a slash, it's an Any type URL. + messageName := extName[s+1:] + mt := MessageType(messageName) + if mt == nil { + return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) + } + tok = p.next() + if tok.err != nil { + return tok.err + } + // consume an optional colon + if tok.value == ":" { + tok = p.next() + if tok.err != nil { + return tok.err + } + } + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + v := reflect.New(mt.Elem()) + if pe := p.readStruct(v.Elem(), terminator); pe != nil { + return pe + } + b, err := Marshal(v.Interface().(Message)) + if err != nil { + return p.errorf("failed to marshal message of type %q: %v", messageName, err) + } + if fieldSet["type_url"] { + return p.errorf(anyRepeatedlyUnpacked, "type_url") + } + if fieldSet["value"] { + return p.errorf(anyRepeatedlyUnpacked, "value") + } + sv.FieldByName("TypeUrl").SetString(extName) + sv.FieldByName("Value").SetBytes(b) + fieldSet["type_url"] = true + fieldSet["value"] = true + continue + } + var desc *ExtensionDesc // This could be faster, but it's functional. // TODO: Do something smarter than a linear scan. for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { - if d.Name == tok.value { + if d.Name == extName { desc = d break } } if desc == nil { - return p.errorf("unrecognized extension %q", tok.value) - } - // Check the extension terminator. - tok = p.next() - if tok.err != nil { - return tok.err - } - if tok.value != "]" { - return p.errorf("unrecognized extension terminator %q", tok.value) + return p.errorf("unrecognized extension %q", extName) } props := &Properties{} @@ -514,7 +561,7 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { } reqFieldErr = err } - ep := sv.Addr().Interface().(extendableProto) + ep := sv.Addr().Interface().(Message) if !rep { SetExtension(ep, desc, ext.Interface()) } else { @@ -566,8 +613,9 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { // The map entry should be this sequence of tokens: // < key : KEY value : VALUE > - // Technically the "key" and "value" could come in any order, - // but in practice they won't. + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. tok := p.next() var terminator string @@ -579,32 +627,39 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { default: return p.errorf("expected '{' or '<', found %q", tok.value) } - if err := p.consumeToken("key"); err != nil { - return err - } - if err := p.consumeToken(":"); err != nil { - return err - } - if err := p.readAny(key, props.mkeyprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken("value"); err != nil { - return err - } - if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { - return err - } - if err := p.readAny(val, props.mvalprop); err != nil { - return err - } - if err := p.consumeOptionalSeparator(); err != nil { - return err - } - if err := p.consumeToken(terminator); err != nil { - return err + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.mkeyprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.mvalprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } } dst.SetMapIndex(key, val) @@ -627,7 +682,8 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { return err } reqFieldErr = err - } else if props.Required { + } + if props.Required { reqCount-- } @@ -643,6 +699,35 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error { return reqFieldErr } +// consumeExtName consumes extension name or expanded Any type URL and the +// following ']'. It returns the name or URL consumed. +func (p *textParser) consumeExtName() (string, error) { + tok := p.next() + if tok.err != nil { + return "", tok.err + } + + // If extension name or type url is quoted, it's a single token. + if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { + name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) + if err != nil { + return "", err + } + return name, p.consumeToken("]") + } + + // Consume everything up to "]" + var parts []string + for tok.value != "]" { + parts = append(parts, tok.value) + tok = p.next() + if tok.err != nil { + return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) + } + } + return strings.Join(parts, ""), nil +} + // consumeOptionalSeparator consumes an optional semicolon or comma. // It is used in readStruct to provide backward compatibility. func (p *textParser) consumeOptionalSeparator() error { @@ -707,12 +792,12 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error { fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) return p.readAny(fv.Index(fv.Len()-1), props) case reflect.Bool: - // Either "true", "false", 1 or 0. + // true/1/t/True or false/f/0/False. switch tok.value { - case "true", "1": + case "true", "1", "t", "True": fv.SetBool(true) return nil - case "false", "0": + case "false", "0", "f", "False": fv.SetBool(false) return nil } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any.go b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any.go new file mode 100644 index 0000000000..89e07ae192 --- /dev/null +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any.go @@ -0,0 +1,136 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// 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 ptypes + +// This file implements functions to marshal proto.Message to/from +// google.protobuf.Any message. + +import ( + "fmt" + "reflect" + "strings" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes/any" +) + +const googleApis = "type.googleapis.com/" + +// AnyMessageName returns the name of the message contained in a google.protobuf.Any message. +// +// Note that regular type assertions should be done using the Is +// function. AnyMessageName is provided for less common use cases like filtering a +// sequence of Any messages based on a set of allowed message type names. +func AnyMessageName(any *any.Any) (string, error) { + slash := strings.LastIndex(any.TypeUrl, "/") + if slash < 0 { + return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) + } + return any.TypeUrl[slash+1:], nil +} + +// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any. +func MarshalAny(pb proto.Message) (*any.Any, error) { + value, err := proto.Marshal(pb) + if err != nil { + return nil, err + } + return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil +} + +// DynamicAny is a value that can be passed to UnmarshalAny to automatically +// allocate a proto.Message for the type specified in a google.protobuf.Any +// message. The allocated message is stored in the embedded proto.Message. +// +// Example: +// +// var x ptypes.DynamicAny +// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } +// fmt.Printf("unmarshaled message: %v", x.Message) +type DynamicAny struct { + proto.Message +} + +// Empty returns a new proto.Message of the type specified in a +// google.protobuf.Any message. It returns an error if corresponding message +// type isn't linked in. +func Empty(any *any.Any) (proto.Message, error) { + aname, err := AnyMessageName(any) + if err != nil { + return nil, err + } + + t := proto.MessageType(aname) + if t == nil { + return nil, fmt.Errorf("any: message type %q isn't linked in", aname) + } + return reflect.New(t.Elem()).Interface().(proto.Message), nil +} + +// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any +// message and places the decoded result in pb. It returns an error if type of +// contents of Any message does not match type of pb message. +// +// pb can be a proto.Message, or a *DynamicAny. +func UnmarshalAny(any *any.Any, pb proto.Message) error { + if d, ok := pb.(*DynamicAny); ok { + if d.Message == nil { + var err error + d.Message, err = Empty(any) + if err != nil { + return err + } + } + return UnmarshalAny(any, d.Message) + } + + aname, err := AnyMessageName(any) + if err != nil { + return err + } + + mname := proto.MessageName(pb) + if aname != mname { + return fmt.Errorf("mismatched message type: got %q want %q", aname, mname) + } + return proto.Unmarshal(any.Value, pb) +} + +// Is returns true if any value contains a given message type. +func Is(any *any.Any, pb proto.Message) bool { + aname, err := AnyMessageName(any) + if err != nil { + return false + } + + return aname == proto.MessageName(pb) +} diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.pb.go b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.pb.go new file mode 100644 index 0000000000..f2c6906b91 --- /dev/null +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.pb.go @@ -0,0 +1,155 @@ +// Code generated by protoc-gen-go. +// source: github.com/golang/protobuf/ptypes/any/any.proto +// DO NOT EDIT! + +/* +Package any is a generated protocol buffer package. + +It is generated from these files: + github.com/golang/protobuf/ptypes/any/any.proto + +It has these top-level messages: + Any +*/ +package any + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +type Any struct { + // A URL/resource name whose content describes the type of the + // serialized protocol buffer message. + // + // For URLs which use the scheme `http`, `https`, or no scheme, the + // following restrictions and interpretations apply: + // + // * If no scheme is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // The name should be in a canonical form (e.g., leading "." is + // not accepted). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` + // Must be a valid serialized protocol buffer of the above specified type. + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *Any) Reset() { *m = Any{} } +func (m *Any) String() string { return proto.CompactTextString(m) } +func (*Any) ProtoMessage() {} +func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Any) XXX_WellKnownType() string { return "Any" } + +func init() { + proto.RegisterType((*Any)(nil), "google.protobuf.Any") +} + +func init() { proto.RegisterFile("github.com/golang/protobuf/ptypes/any/any.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 187 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, + 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcc, + 0xab, 0x04, 0x61, 0x3d, 0xb0, 0xb8, 0x10, 0x7f, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x1e, 0x4c, + 0x95, 0x92, 0x19, 0x17, 0xb3, 0x63, 0x5e, 0xa5, 0x90, 0x24, 0x17, 0x07, 0x48, 0x79, 0x7c, 0x69, + 0x51, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24, + 0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0xe1, + 0x38, 0x15, 0x71, 0x09, 0x27, 0xe7, 0xe7, 0xea, 0xa1, 0x19, 0xe7, 0xc4, 0xe1, 0x98, 0x57, 0x19, + 0x00, 0xe2, 0x04, 0x30, 0x46, 0xa9, 0x12, 0xe5, 0xb8, 0x05, 0x8c, 0x8c, 0x8b, 0x98, 0x98, 0xdd, + 0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x4c, 0x0b, 0x80, 0xaa, 0xd2, 0x0b, 0x4f, 0xcd, 0xc9, + 0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0xa9, 0x4e, 0x62, 0x03, 0x6b, 0x37, 0x06, 0x04, 0x00, + 0x00, 0xff, 0xff, 0xc6, 0x4d, 0x03, 0x23, 0xf6, 0x00, 0x00, 0x00, +} diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.proto b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.proto new file mode 100644 index 0000000000..81dcf46ccf --- /dev/null +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/any/any.proto @@ -0,0 +1,140 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/any"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option java_generate_equals_and_hash = true; +option objc_class_prefix = "GPB"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name whose content describes the type of the + // serialized protocol buffer message. + // + // For URLs which use the scheme `http`, `https`, or no scheme, the + // following restrictions and interpretations apply: + // + // * If no scheme is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // The name should be in a canonical form (e.g., leading "." is + // not accepted). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.pb.go index 3ac552e3d6..569748346d 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.pb.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-go. -// source: github.com/golang/protobuf/types/duration/duration.proto +// source: github.com/golang/protobuf/ptypes/duration/duration.proto // DO NOT EDIT! /* Package duration is a generated protocol buffer package. It is generated from these files: - github.com/golang/protobuf/types/duration/duration.proto + github.com/golang/protobuf/ptypes/duration/duration.proto It has these top-level messages: Duration @@ -24,7 +24,9 @@ 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. -const _ = proto.ProtoPackageIsVersion1 +// 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 // A Duration represents a signed, fixed-length span of time represented // as a count of seconds and fractions of seconds at nanosecond @@ -67,6 +69,7 @@ const _ = proto.ProtoPackageIsVersion1 // end.nanos -= 1000000000; // } // +// type Duration struct { // Signed seconds of the span of time. Must be from -315,576,000,000 // to +315,576,000,000 inclusive. @@ -84,23 +87,28 @@ func (m *Duration) Reset() { *m = Duration{} } func (m *Duration) String() string { return proto.CompactTextString(m) } func (*Duration) ProtoMessage() {} func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Duration) XXX_WellKnownType() string { return "Duration" } func init() { proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") } -var fileDescriptor0 = []byte{ - // 186 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x48, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, - 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, 0x2d, - 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x0a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, 0xd3, - 0x73, 0x52, 0xf5, 0x60, 0xca, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, 0xd8, - 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, - 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, 0x84, - 0xe3, 0x14, 0xc5, 0x25, 0x0c, 0x74, 0x81, 0x1e, 0x9a, 0x91, 0x4e, 0xbc, 0x30, 0x03, 0x03, 0x40, - 0x22, 0x01, 0x8c, 0x51, 0x1c, 0x30, 0x47, 0x2c, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0xec, 0x1e, 0xe0, - 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0xa2, 0x2b, 0x00, 0xaa, 0x4b, 0x2f, 0x3c, 0x35, 0x27, 0xc7, 0x3b, - 0x2f, 0xbf, 0x3c, 0x2f, 0x04, 0xe4, 0x81, 0x24, 0x36, 0xb0, 0x71, 0xc6, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x04, 0x47, 0x33, 0x15, 0xeb, 0x00, 0x00, 0x00, +func init() { + proto.RegisterFile("github.com/golang/protobuf/ptypes/duration/duration.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 189 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, + 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x29, + 0x2d, 0x4a, 0x2c, 0xc9, 0xcc, 0xcf, 0x83, 0x33, 0xf4, 0xc0, 0x2a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, + 0xd3, 0x73, 0x52, 0xf5, 0x60, 0xea, 0x95, 0xac, 0xb8, 0x38, 0x5c, 0xa0, 0x4a, 0x84, 0x24, 0xb8, + 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, + 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xd6, + 0x20, 0x08, 0xc7, 0xa9, 0x86, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x48, 0x27, 0x5e, 0x98, + 0x81, 0x01, 0x20, 0x91, 0x00, 0xc6, 0x28, 0x2d, 0xe2, 0xdd, 0xbb, 0x80, 0x91, 0x71, 0x11, 0x13, + 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xb9, 0x01, 0x50, 0xa5, 0x7a, 0xe1, 0xa9, + 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x2d, 0x49, 0x6c, 0x60, 0x33, 0x8c, 0x01, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x62, 0xfb, 0xb1, 0x51, 0x0e, 0x01, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.proto b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.proto index d2fbc88e52..96c1796d65 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.proto +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/duration/duration.proto @@ -31,9 +31,9 @@ syntax = "proto3"; package google.protobuf; -option go_package = "duration"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/duration"; option java_package = "com.google.protobuf"; option java_outer_classname = "DurationProto"; option java_multiple_files = true; @@ -81,6 +81,7 @@ option objc_class_prefix = "GPB"; // end.nanos -= 1000000000; // } // +// message Duration { // Signed seconds of the span of time. Must be from -315,576,000,000 diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/regen.sh b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/regen.sh index 4166d9e8fc..2a5b4e8bdc 100755 --- a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/regen.sh +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/regen.sh @@ -5,7 +5,7 @@ # see https://github.com/golang/protobuf for instructions. # You also need Go and Git installed. -PKG=github.com/golang/protobuf/types +PKG=github.com/golang/protobuf/ptypes UPSTREAM=https://github.com/google/protobuf UPSTREAM_SUBDIR=src/google/protobuf PROTO_FILES=' @@ -51,17 +51,11 @@ for f in $(cd $PKG && find * -name '*.proto'); do fi filename_map[$up]=$f done -# Pass 2: copy files, making necessary adjustments. +# Pass 2: copy files for up in "${!filename_map[@]}"; do f=${filename_map[$up]} shortname=$(basename $f | sed 's,\.proto$,,') - cat $tmpdir/$UPSTREAM_SUBDIR/$up | - # Adjust proto package. - # TODO(dsymonds): Upstream the go_package option instead. - sed '/^package /a option go_package = "'${shortname}'";' | - # Unfortunately "package struct" doesn't work. - sed '/option go_package/s,"struct","structpb",' | - cat > $PKG/$f + cp $tmpdir/$UPSTREAM_SUBDIR/$up $PKG/$f done # Run protoc once per package. diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go index ac27c4bebd..ffcc51594a 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-go. -// source: github.com/golang/protobuf/types/timestamp/timestamp.proto +// source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto // DO NOT EDIT! /* Package timestamp is a generated protocol buffer package. It is generated from these files: - github.com/golang/protobuf/types/timestamp/timestamp.proto + github.com/golang/protobuf/ptypes/timestamp/timestamp.proto It has these top-level messages: Timestamp @@ -24,7 +24,9 @@ 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. -const _ = proto.ProtoPackageIsVersion1 +// 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 // A Timestamp represents a point in time independent of any time zone // or calendar, represented as seconds and fractions of seconds at @@ -97,23 +99,29 @@ func (m *Timestamp) Reset() { *m = Timestamp{} } func (m *Timestamp) String() string { return proto.CompactTextString(m) } func (*Timestamp) ProtoMessage() {} func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } func init() { proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") } -var fileDescriptor0 = []byte{ - // 190 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4a, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, - 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, 0xcc, - 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x4a, 0x84, 0xf8, 0xd3, 0xf3, 0xf3, - 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x1a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, 0xb8, - 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, - 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0xa0, 0x38, 0x6b, 0x10, - 0x84, 0xe3, 0x14, 0xcf, 0x25, 0x0c, 0x74, 0x84, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, - 0x40, 0x42, 0x01, 0x8c, 0x51, 0x9c, 0x70, 0x77, 0x2c, 0x60, 0x64, 0xfc, 0xc1, 0xc8, 0xb8, 0x88, - 0x89, 0xd9, 0x3d, 0xc0, 0x69, 0x15, 0x93, 0x9c, 0x3b, 0x44, 0x6b, 0x00, 0x54, 0xab, 0x5e, 0x78, - 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0xc8, 0x23, 0x49, 0x6c, 0x60, 0x33, 0x8d, - 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xdd, 0x30, 0x93, 0xf3, 0x00, 0x00, 0x00, +func init() { + proto.RegisterFile("github.com/golang/protobuf/ptypes/timestamp/timestamp.proto", fileDescriptor0) +} + +var fileDescriptor0 = []byte{ + // 194 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28, + 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0xc9, + 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x40, 0xb0, 0xf4, 0xc0, 0x6a, 0x84, 0xf8, 0xd3, 0xf3, + 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0x60, 0x3a, 0x94, 0xac, 0xb9, 0x38, 0x43, 0x60, 0x6a, 0x84, 0x24, + 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, + 0x60, 0x5c, 0x21, 0x11, 0x2e, 0xd6, 0xbc, 0xc4, 0xbc, 0xfc, 0x62, 0x09, 0x26, 0x05, 0x46, 0x0d, + 0xd6, 0x20, 0x08, 0xc7, 0xa9, 0x91, 0x91, 0x4b, 0x38, 0x39, 0x3f, 0x57, 0x0f, 0xcd, 0x50, 0x27, + 0x3e, 0xb8, 0x91, 0x01, 0x20, 0xa1, 0x00, 0xc6, 0x28, 0x6d, 0x12, 0x1c, 0xbd, 0x80, 0x91, 0xf1, + 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, 0xc3, 0x03, + 0xa0, 0xca, 0xf5, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, 0xda, 0x92, + 0xd8, 0xc0, 0xe6, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x17, 0x5f, 0xb7, 0xdc, 0x17, 0x01, + 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto index cc6dc6ff0a..7992a85886 100644 --- a/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto +++ b/components/engine/vendor/src/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto @@ -31,10 +31,10 @@ syntax = "proto3"; package google.protobuf; -option go_package = "timestamp"; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/timestamp"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; diff --git a/components/engine/vendor/src/google.golang.org/grpc/.travis.yml b/components/engine/vendor/src/google.golang.org/grpc/.travis.yml index 9bc2c12793..d7108cd645 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/.travis.yml +++ b/components/engine/vendor/src/google.golang.org/grpc/.travis.yml @@ -1,17 +1,21 @@ language: go go: - - 1.5.3 - - 1.6 + - 1.5.4 + - 1.6.3 + +go_import_path: google.golang.org/grpc before_install: + - go get golang.org/x/tools/cmd/goimports + - go get github.com/golang/lint/golint - go get github.com/axw/gocov/gocov - go get github.com/mattn/goveralls - go get golang.org/x/tools/cmd/cover -install: - - mkdir -p "$GOPATH/src/google.golang.org" - - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/google.golang.org/grpc" - script: + - '! gofmt -s -d -l . 2>&1 | read' + - '! goimports -l . | read' + - '! golint ./... | grep -vE "(_string|\.pb)\.go:"' + - '! go tool vet -all . 2>&1 | grep -vE "constant [0-9]+ not a string in call to Errorf"' - make test testrace diff --git a/components/engine/vendor/src/google.golang.org/grpc/Makefile b/components/engine/vendor/src/google.golang.org/grpc/Makefile index d26eb9081f..03bb01f0b3 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/Makefile +++ b/components/engine/vendor/src/google.golang.org/grpc/Makefile @@ -21,8 +21,9 @@ proto: exit 1; \ fi go get -u -v github.com/golang/protobuf/protoc-gen-go - for file in $$(git ls-files '*.proto'); do \ - protoc -I $$(dirname $$file) --go_out=plugins=grpc:$$(dirname $$file) $$file; \ + # use $$dir as the root for all proto files in the same directory + for dir in $$(git ls-files '*.proto' | xargs -n1 dirname | uniq); do \ + protoc -I $$dir --go_out=plugins=grpc:$$dir $$dir/*.proto; \ done test: testdeps diff --git a/components/engine/vendor/src/google.golang.org/grpc/PATENTS b/components/engine/vendor/src/google.golang.org/grpc/PATENTS index 619f9dbfe6..69b47959fa 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/PATENTS +++ b/components/engine/vendor/src/google.golang.org/grpc/PATENTS @@ -1,22 +1,22 @@ Additional IP Rights Grant (Patents) "This implementation" means the copyrightable works distributed by -Google as part of the GRPC project. +Google as part of the gRPC project. Google hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, transfer and otherwise run, modify and propagate the contents of this -implementation of GRPC, where such license applies only to those patent +implementation of gRPC, where such license applies only to those patent claims, both currently owned or controlled by Google and acquired in the future, licensable by Google that are necessarily infringed by this -implementation of GRPC. This grant does not include claims that would be +implementation of gRPC. This grant does not include claims that would be infringed only as a consequence of further modification of this implementation. If you or your agent or exclusive licensee institute or order or agree to the institution of patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of GRPC or any code incorporated within this -implementation of GRPC constitutes direct or contributory patent +that this implementation of gRPC or any code incorporated within this +implementation of gRPC constitutes direct or contributory patent infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of GRPC +rights granted to you under this License for this implementation of gRPC shall terminate as of the date such litigation is filed. diff --git a/components/engine/vendor/src/google.golang.org/grpc/README.md b/components/engine/vendor/src/google.golang.org/grpc/README.md index 90e9453d52..660658bed3 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/README.md +++ b/components/engine/vendor/src/google.golang.org/grpc/README.md @@ -28,5 +28,5 @@ See [API documentation](https://godoc.org/google.golang.org/grpc) for package an Status ------ -Beta release +GA diff --git a/components/engine/vendor/src/google.golang.org/grpc/backoff.go b/components/engine/vendor/src/google.golang.org/grpc/backoff.go index dc4858ebe3..52f4f10fc2 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/backoff.go +++ b/components/engine/vendor/src/google.golang.org/grpc/backoff.go @@ -19,7 +19,7 @@ var ( // backoffStrategy defines the methodology for backing off after a grpc // connection failure. // -// This is unexported until the GRPC project decides whether or not to allow +// This is unexported until the gRPC project decides whether or not to allow // alternative backoff strategies. Once a decision is made, this type and its // method may be exported. type backoffStrategy interface { @@ -28,14 +28,14 @@ type backoffStrategy interface { backoff(retries int) time.Duration } -// BackoffConfig defines the parameters for the default GRPC backoff strategy. +// BackoffConfig defines the parameters for the default gRPC backoff strategy. type BackoffConfig struct { // MaxDelay is the upper bound of backoff delay. MaxDelay time.Duration // TODO(stevvooe): The following fields are not exported, as allowing - // changes would violate the current GRPC specification for backoff. If - // GRPC decides to allow more interesting backoff strategies, these fields + // changes would violate the current gRPC specification for backoff. If + // gRPC decides to allow more interesting backoff strategies, these fields // may be opened up in the future. // baseDelay is the amount of time to wait before retrying after the first diff --git a/components/engine/vendor/src/google.golang.org/grpc/balancer.go b/components/engine/vendor/src/google.golang.org/grpc/balancer.go new file mode 100644 index 0000000000..419e214611 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/balancer.go @@ -0,0 +1,385 @@ +/* + * + * Copyright 2016, 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 grpc + +import ( + "fmt" + "sync" + + "golang.org/x/net/context" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/naming" +) + +// Address represents a server the client connects to. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type Address struct { + // Addr is the server address on which a connection will be established. + Addr string + // Metadata is the information associated with Addr, which may be used + // to make load balancing decision. + Metadata interface{} +} + +// BalancerGetOptions configures a Get call. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type BalancerGetOptions struct { + // BlockingWait specifies whether Get should block when there is no + // connected address. + BlockingWait bool +} + +// Balancer chooses network addresses for RPCs. +// This is the EXPERIMENTAL API and may be changed or extended in the future. +type Balancer interface { + // Start does the initialization work to bootstrap a Balancer. For example, + // this function may start the name resolution and watch the updates. It will + // be called when dialing. + Start(target string) error + // Up informs the Balancer that gRPC has a connection to the server at + // addr. It returns down which is called once the connection to addr gets + // lost or closed. + // TODO: It is not clear how to construct and take advantage the meaningful error + // parameter for down. Need realistic demands to guide. + Up(addr Address) (down func(error)) + // Get gets the address of a server for the RPC corresponding to ctx. + // i) If it returns a connected address, gRPC internals issues the RPC on the + // connection to this address; + // ii) If it returns an address on which the connection is under construction + // (initiated by Notify(...)) but not connected, gRPC internals + // * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or + // Shutdown state; + // or + // * issues RPC on the connection otherwise. + // iii) If it returns an address on which the connection does not exist, gRPC + // internals treats it as an error and will fail the corresponding RPC. + // + // Therefore, the following is the recommended rule when writing a custom Balancer. + // If opts.BlockingWait is true, it should return a connected address or + // block if there is no connected address. It should respect the timeout or + // cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast + // RPCs), it should return an address it has notified via Notify(...) immediately + // instead of blocking. + // + // The function returns put which is called once the rpc has completed or failed. + // put can collect and report RPC stats to a remote load balancer. + // + // This function should only return the errors Balancer cannot recover by itself. + // gRPC internals will fail the RPC if an error is returned. + Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) + // Notify returns a channel that is used by gRPC internals to watch the addresses + // gRPC needs to connect. The addresses might be from a name resolver or remote + // load balancer. gRPC internals will compare it with the existing connected + // addresses. If the address Balancer notified is not in the existing connected + // addresses, gRPC starts to connect the address. If an address in the existing + // connected addresses is not in the notification list, the corresponding connection + // is shutdown gracefully. Otherwise, there are no operations to take. Note that + // the Address slice must be the full list of the Addresses which should be connected. + // It is NOT delta. + Notify() <-chan []Address + // Close shuts down the balancer. + Close() error +} + +// downErr implements net.Error. It is constructed by gRPC internals and passed to the down +// call of Balancer. +type downErr struct { + timeout bool + temporary bool + desc string +} + +func (e downErr) Error() string { return e.desc } +func (e downErr) Timeout() bool { return e.timeout } +func (e downErr) Temporary() bool { return e.temporary } + +func downErrorf(timeout, temporary bool, format string, a ...interface{}) downErr { + return downErr{ + timeout: timeout, + temporary: temporary, + desc: fmt.Sprintf(format, a...), + } +} + +// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch +// the name resolution updates and updates the addresses available correspondingly. +func RoundRobin(r naming.Resolver) Balancer { + return &roundRobin{r: r} +} + +type addrInfo struct { + addr Address + connected bool +} + +type roundRobin struct { + r naming.Resolver + w naming.Watcher + addrs []*addrInfo // all the addresses the client should potentially connect + mu sync.Mutex + addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to. + next int // index of the next address to return for Get() + waitCh chan struct{} // the channel to block when there is no connected address available + done bool // The Balancer is closed. +} + +func (rr *roundRobin) watchAddrUpdates() error { + updates, err := rr.w.Next() + if err != nil { + grpclog.Printf("grpc: the naming watcher stops working due to %v.\n", err) + return err + } + rr.mu.Lock() + defer rr.mu.Unlock() + for _, update := range updates { + addr := Address{ + Addr: update.Addr, + Metadata: update.Metadata, + } + switch update.Op { + case naming.Add: + var exist bool + for _, v := range rr.addrs { + if addr == v.addr { + exist = true + grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr) + break + } + } + if exist { + continue + } + rr.addrs = append(rr.addrs, &addrInfo{addr: addr}) + case naming.Delete: + for i, v := range rr.addrs { + if addr == v.addr { + copy(rr.addrs[i:], rr.addrs[i+1:]) + rr.addrs = rr.addrs[:len(rr.addrs)-1] + break + } + } + default: + grpclog.Println("Unknown update.Op ", update.Op) + } + } + // Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified. + open := make([]Address, len(rr.addrs)) + for i, v := range rr.addrs { + open[i] = v.addr + } + if rr.done { + return ErrClientConnClosing + } + rr.addrCh <- open + return nil +} + +func (rr *roundRobin) Start(target string) error { + if rr.r == nil { + // If there is no name resolver installed, it is not needed to + // do name resolution. In this case, target is added into rr.addrs + // as the only address available and rr.addrCh stays nil. + rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}}) + return nil + } + w, err := rr.r.Resolve(target) + if err != nil { + return err + } + rr.w = w + rr.addrCh = make(chan []Address) + go func() { + for { + if err := rr.watchAddrUpdates(); err != nil { + return + } + } + }() + return nil +} + +// Up sets the connected state of addr and sends notification if there are pending +// Get() calls. +func (rr *roundRobin) Up(addr Address) func(error) { + rr.mu.Lock() + defer rr.mu.Unlock() + var cnt int + for _, a := range rr.addrs { + if a.addr == addr { + if a.connected { + return nil + } + a.connected = true + } + if a.connected { + cnt++ + } + } + // addr is only one which is connected. Notify the Get() callers who are blocking. + if cnt == 1 && rr.waitCh != nil { + close(rr.waitCh) + rr.waitCh = nil + } + return func(err error) { + rr.down(addr, err) + } +} + +// down unsets the connected state of addr. +func (rr *roundRobin) down(addr Address, err error) { + rr.mu.Lock() + defer rr.mu.Unlock() + for _, a := range rr.addrs { + if addr == a.addr { + a.connected = false + break + } + } +} + +// Get returns the next addr in the rotation. +func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) { + var ch chan struct{} + rr.mu.Lock() + if rr.done { + rr.mu.Unlock() + err = ErrClientConnClosing + return + } + + if len(rr.addrs) > 0 { + if rr.next >= len(rr.addrs) { + rr.next = 0 + } + next := rr.next + for { + a := rr.addrs[next] + next = (next + 1) % len(rr.addrs) + if a.connected { + addr = a.addr + rr.next = next + rr.mu.Unlock() + return + } + if next == rr.next { + // Has iterated all the possible address but none is connected. + break + } + } + } + if !opts.BlockingWait { + if len(rr.addrs) == 0 { + rr.mu.Unlock() + err = fmt.Errorf("there is no address available") + return + } + // Returns the next addr on rr.addrs for failfast RPCs. + addr = rr.addrs[rr.next].addr + rr.next++ + rr.mu.Unlock() + return + } + // Wait on rr.waitCh for non-failfast RPCs. + if rr.waitCh == nil { + ch = make(chan struct{}) + rr.waitCh = ch + } else { + ch = rr.waitCh + } + rr.mu.Unlock() + for { + select { + case <-ctx.Done(): + err = ctx.Err() + return + case <-ch: + rr.mu.Lock() + if rr.done { + rr.mu.Unlock() + err = ErrClientConnClosing + return + } + + if len(rr.addrs) > 0 { + if rr.next >= len(rr.addrs) { + rr.next = 0 + } + next := rr.next + for { + a := rr.addrs[next] + next = (next + 1) % len(rr.addrs) + if a.connected { + addr = a.addr + rr.next = next + rr.mu.Unlock() + return + } + if next == rr.next { + // Has iterated all the possible address but none is connected. + break + } + } + } + // The newly added addr got removed by Down() again. + if rr.waitCh == nil { + ch = make(chan struct{}) + rr.waitCh = ch + } else { + ch = rr.waitCh + } + rr.mu.Unlock() + } + } +} + +func (rr *roundRobin) Notify() <-chan []Address { + return rr.addrCh +} + +func (rr *roundRobin) Close() error { + rr.mu.Lock() + defer rr.mu.Unlock() + rr.done = true + if rr.w != nil { + rr.w.Close() + } + if rr.waitCh != nil { + close(rr.waitCh) + rr.waitCh = nil + } + if rr.addrCh != nil { + close(rr.addrCh) + } + return nil +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/call.go b/components/engine/vendor/src/google.golang.org/grpc/call.go index 9d0fc8eeea..fea07998d7 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/call.go +++ b/components/engine/vendor/src/google.golang.org/grpc/call.go @@ -36,6 +36,7 @@ package grpc import ( "bytes" "io" + "math" "time" "golang.org/x/net/context" @@ -51,13 +52,20 @@ import ( func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { // Try to acquire header metadata from the server if there is any. var err error + defer func() { + if err != nil { + if _, ok := err.(transport.ConnectionError); !ok { + t.CloseStream(stream, err) + } + } + }() c.headerMD, err = stream.Header() if err != nil { return err } p := &parser{r: stream} for { - if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil { + if err = recv(p, dopts.codec, stream, dopts.dc, reply, math.MaxInt32); err != nil { if err == io.EOF { break } @@ -76,6 +84,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd } defer func() { if err != nil { + // If err is connection error, t will be closed, no need to close stream here. if _, ok := err.(transport.ConnectionError); !ok { t.CloseStream(stream, err) } @@ -90,7 +99,10 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err) } err = t.Write(stream, outBuf, opts) - if err != nil { + // t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method + // does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following + // recvResponse to get the final status. + if err != nil && err != io.EOF { return nil, err } // Sent successfully. @@ -101,7 +113,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd // Invoke is called by generated code. Also users can call Invoke directly when it // is really needed in their use cases. func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) { - var c callInfo + c := defaultCallInfo for _, o := range opts { if err := o.before(&c); err != nil { return toRPCErr(err) @@ -132,19 +144,16 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli Last: true, Delay: false, } - var ( - lastErr error // record the error that happened - ) for { var ( err error t transport.ClientTransport stream *transport.Stream + // Record the put handler from Balancer.Get(...). It is called once the + // RPC has completed or failed. + put func() ) - // TODO(zhaoq): Need a formal spec of retry strategy for non-failfast rpcs. - if lastErr != nil && c.failFast { - return toRPCErr(lastErr) - } + // TODO(zhaoq): Need a formal spec of fail-fast. callHdr := &transport.CallHdr{ Host: cc.authority, Method: method, @@ -152,39 +161,65 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli if cc.dopts.cp != nil { callHdr.SendCompress = cc.dopts.cp.Type() } - t, err = cc.dopts.picker.Pick(ctx) + gopts := BalancerGetOptions{ + BlockingWait: !c.failFast, + } + t, put, err = cc.getTransport(ctx, gopts) if err != nil { - if lastErr != nil { - // This was a retry; return the error from the last attempt. - return toRPCErr(lastErr) + // TODO(zhaoq): Probably revisit the error handling. + if _, ok := err.(*rpcError); ok { + return err } - return toRPCErr(err) + if err == errConnClosing || err == errConnUnavailable { + if c.failFast { + return Errorf(codes.Unavailable, "%v", err) + } + continue + } + // All the other errors are treated as Internal errors. + return Errorf(codes.Internal, "%v", err) } if c.traceInfo.tr != nil { c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true) } stream, err = sendRequest(ctx, cc.dopts.codec, cc.dopts.cp, callHdr, t, args, topts) if err != nil { - if _, ok := err.(transport.ConnectionError); ok { - lastErr = err - continue + if put != nil { + put() + put = nil } - if lastErr != nil { - return toRPCErr(lastErr) + // Retry a non-failfast RPC when + // i) there is a connection error; or + // ii) the server started to drain before this RPC was initiated. + if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { + if c.failFast { + return toRPCErr(err) + } + continue } return toRPCErr(err) } - // Receive the response - lastErr = recvResponse(cc.dopts, t, &c, stream, reply) - if _, ok := lastErr.(transport.ConnectionError); ok { - continue + err = recvResponse(cc.dopts, t, &c, stream, reply) + if err != nil { + if put != nil { + put() + put = nil + } + if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { + if c.failFast { + return toRPCErr(err) + } + continue + } + return toRPCErr(err) } if c.traceInfo.tr != nil { c.traceInfo.tr.LazyLog(&payload{sent: false, msg: reply}, true) } - t.CloseStream(stream, lastErr) - if lastErr != nil { - return toRPCErr(lastErr) + t.CloseStream(stream, nil) + if put != nil { + put() + put = nil } return Errorf(stream.StatusCode(), "%s", stream.StatusDesc()) } diff --git a/components/engine/vendor/src/google.golang.org/grpc/clientconn.go b/components/engine/vendor/src/google.golang.org/grpc/clientconn.go index 6de86e9e4c..27e74e6f22 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/clientconn.go +++ b/components/engine/vendor/src/google.golang.org/grpc/clientconn.go @@ -49,22 +49,33 @@ import ( ) var ( - // ErrUnspecTarget indicates that the target address is unspecified. - ErrUnspecTarget = errors.New("grpc: target is unspecified") - // ErrNoTransportSecurity indicates that there is no transport security + // ErrClientConnClosing indicates that the operation is illegal because + // the ClientConn is closing. + ErrClientConnClosing = errors.New("grpc: the client connection is closing") + // ErrClientConnTimeout indicates that the ClientConn cannot establish the + // underlying connections within the specified timeout. + ErrClientConnTimeout = errors.New("grpc: timed out when dialing") + + // errNoTransportSecurity indicates that there is no transport security // being set for ClientConn. Users should either set one or explicitly // call WithInsecure DialOption to disable security. - ErrNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)") - // ErrCredentialsMisuse indicates that users want to transmit security information - // (e.g., oauth2 token) which requires secure connection on an insecure + errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)") + // errTransportCredentialsMissing indicates that users want to transmit security + // information (e.g., oauth2 token) which requires secure connection on an insecure // connection. - ErrCredentialsMisuse = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportAuthenticator() to set)") - // ErrClientConnClosing indicates that the operation is illegal because - // the session is closing. - ErrClientConnClosing = errors.New("grpc: the client connection is closing") - // ErrClientConnTimeout indicates that the connection could not be - // established or re-established within the specified timeout. - ErrClientConnTimeout = errors.New("grpc: timed out trying to connect") + errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)") + // errCredentialsConflict indicates that grpc.WithTransportCredentials() + // and grpc.WithInsecure() are both called for a connection. + errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)") + // errNetworkIO indicates that the connection is down due to some network I/O error. + errNetworkIO = errors.New("grpc: failed with network I/O error") + // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs. + errConnDrain = errors.New("grpc: the connection is drained") + // errConnClosing indicates that the connection is closing. + errConnClosing = errors.New("grpc: the connection is closing") + // errConnUnavailable indicates that the connection is unavailable. + errConnUnavailable = errors.New("grpc: the connection is unavailable") + errNoAddr = errors.New("grpc: there is no address available to dial") // minimum time to give a connection to complete minConnectTimeout = 20 * time.Second ) @@ -76,9 +87,10 @@ type dialOptions struct { cp Compressor dc Decompressor bs backoffStrategy - picker Picker + balancer Balancer block bool insecure bool + timeout time.Duration copts transport.ConnectOptions } @@ -108,10 +120,10 @@ func WithDecompressor(dc Decompressor) DialOption { } } -// WithPicker returns a DialOption which sets a picker for connection selection. -func WithPicker(p Picker) DialOption { +// WithBalancer returns a DialOption which sets a load balancer. +func WithBalancer(b Balancer) DialOption { return func(o *dialOptions) { - o.picker = p + o.balancer = b } } @@ -136,7 +148,7 @@ func WithBackoffConfig(b BackoffConfig) DialOption { // withBackoff sets the backoff strategy used for retries after a // failed connection attempt. // -// This can be exported if arbitrary backoff strategies are allowed by GRPC. +// This can be exported if arbitrary backoff strategies are allowed by gRPC. func withBackoff(bs backoffStrategy) DialOption { return func(o *dialOptions) { o.bs = bs @@ -162,31 +174,37 @@ func WithInsecure() DialOption { // WithTransportCredentials returns a DialOption which configures a // connection level security credentials (e.g., TLS/SSL). -func WithTransportCredentials(creds credentials.TransportAuthenticator) DialOption { +func WithTransportCredentials(creds credentials.TransportCredentials) DialOption { return func(o *dialOptions) { - o.copts.AuthOptions = append(o.copts.AuthOptions, creds) + o.copts.TransportCredentials = creds } } // WithPerRPCCredentials returns a DialOption which sets // credentials which will place auth state on each outbound RPC. -func WithPerRPCCredentials(creds credentials.Credentials) DialOption { +func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption { return func(o *dialOptions) { - o.copts.AuthOptions = append(o.copts.AuthOptions, creds) + o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) } } -// WithTimeout returns a DialOption that configures a timeout for dialing a client connection. +// WithTimeout returns a DialOption that configures a timeout for dialing a ClientConn +// initially. This is valid if and only if WithBlock() is present. func WithTimeout(d time.Duration) DialOption { return func(o *dialOptions) { - o.copts.Timeout = d + o.timeout = d } } // WithDialer returns a DialOption that specifies a function to use for dialing network addresses. -func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption { +func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption { return func(o *dialOptions) { - o.copts.Dialer = f + o.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) { + if deadline, ok := ctx.Deadline(); ok { + return f(addr, deadline.Sub(time.Now())) + } + return f(addr, 0) + } } } @@ -197,30 +215,84 @@ func WithUserAgent(s string) DialOption { } } -// Dial creates a client connection the given target. +// Dial creates a client connection to the given target. func Dial(target string, opts ...DialOption) (*ClientConn, error) { + return DialContext(context.Background(), target, opts...) +} + +// DialContext creates a client connection to the given target +// using the supplied context. +func DialContext(ctx context.Context, target string, opts ...DialOption) (*ClientConn, error) { cc := &ClientConn{ target: target, + conns: make(map[Address]*addrConn), } + cc.ctx, cc.cancel = context.WithCancel(ctx) for _, opt := range opts { opt(&cc.dopts) } + + // Set defaults. if cc.dopts.codec == nil { - // Set the default codec. cc.dopts.codec = protoCodec{} } - if cc.dopts.bs == nil { cc.dopts.bs = DefaultBackoffConfig } - if cc.dopts.picker == nil { - cc.dopts.picker = &unicastPicker{ - target: target, + var ( + ok bool + addrs []Address + ) + if cc.dopts.balancer == nil { + // Connect to target directly if balancer is nil. + addrs = append(addrs, Address{Addr: target}) + } else { + if err := cc.dopts.balancer.Start(target); err != nil { + return nil, err + } + ch := cc.dopts.balancer.Notify() + if ch == nil { + // There is no name resolver installed. + addrs = append(addrs, Address{Addr: target}) + } else { + addrs, ok = <-ch + if !ok || len(addrs) == 0 { + return nil, errNoAddr + } } } - if err := cc.dopts.picker.Init(cc); err != nil { - return nil, err + waitC := make(chan error, 1) + go func() { + for _, a := range addrs { + if err := cc.resetAddrConn(a, false, nil); err != nil { + waitC <- err + return + } + } + close(waitC) + }() + var timeoutCh <-chan time.Time + if cc.dopts.timeout > 0 { + timeoutCh = time.After(cc.dopts.timeout) + } + select { + case err := <-waitC: + if err != nil { + cc.Close() + return nil, err + } + case <-cc.ctx.Done(): + cc.Close() + return nil, cc.ctx.Err() + case <-timeoutCh: + cc.Close() + return nil, ErrClientConnTimeout + } + // If balancer is nil or balancer.Notify() is nil, ok will be false here. + // The lbWatcher goroutine will not be created. + if ok { + go cc.lbWatcher() } colonPos := strings.LastIndex(target, ":") if colonPos == -1 { @@ -263,361 +335,511 @@ func (s ConnectivityState) String() string { } } -// ClientConn represents a client connection to an RPC service. +// ClientConn represents a client connection to an RPC server. type ClientConn struct { + ctx context.Context + cancel context.CancelFunc + target string authority string dopts dialOptions + + mu sync.RWMutex + conns map[Address]*addrConn } -// State returns the connectivity state of cc. -// This is EXPERIMENTAL API. -func (cc *ClientConn) State() (ConnectivityState, error) { - return cc.dopts.picker.State() +func (cc *ClientConn) lbWatcher() { + for addrs := range cc.dopts.balancer.Notify() { + var ( + add []Address // Addresses need to setup connections. + del []*addrConn // Connections need to tear down. + ) + cc.mu.Lock() + for _, a := range addrs { + if _, ok := cc.conns[a]; !ok { + add = append(add, a) + } + } + for k, c := range cc.conns { + var keep bool + for _, a := range addrs { + if k == a { + keep = true + break + } + } + if !keep { + del = append(del, c) + delete(cc.conns, c.addr) + } + } + cc.mu.Unlock() + for _, a := range add { + cc.resetAddrConn(a, true, nil) + } + for _, c := range del { + c.tearDown(errConnDrain) + } + } } -// WaitForStateChange blocks until the state changes to something other than the sourceState. -// It returns the new state or error. -// This is EXPERIMENTAL API. -func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { - return cc.dopts.picker.WaitForStateChange(ctx, sourceState) +// resetAddrConn creates an addrConn for addr and adds it to cc.conns. +// If there is an old addrConn for addr, it will be torn down, using tearDownErr as the reason. +// If tearDownErr is nil, errConnDrain will be used instead. +func (cc *ClientConn) resetAddrConn(addr Address, skipWait bool, tearDownErr error) error { + ac := &addrConn{ + cc: cc, + addr: addr, + dopts: cc.dopts, + } + ac.ctx, ac.cancel = context.WithCancel(cc.ctx) + ac.stateCV = sync.NewCond(&ac.mu) + if EnableTracing { + ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr) + } + if !ac.dopts.insecure { + if ac.dopts.copts.TransportCredentials == nil { + return errNoTransportSecurity + } + } else { + if ac.dopts.copts.TransportCredentials != nil { + return errCredentialsConflict + } + for _, cd := range ac.dopts.copts.PerRPCCredentials { + if cd.RequireTransportSecurity() { + return errTransportCredentialsMissing + } + } + } + // Track ac in cc. This needs to be done before any getTransport(...) is called. + cc.mu.Lock() + if cc.conns == nil { + cc.mu.Unlock() + return ErrClientConnClosing + } + stale := cc.conns[ac.addr] + cc.conns[ac.addr] = ac + cc.mu.Unlock() + if stale != nil { + // There is an addrConn alive on ac.addr already. This could be due to + // 1) a buggy Balancer notifies duplicated Addresses; + // 2) goaway was received, a new ac will replace the old ac. + // The old ac should be deleted from cc.conns, but the + // underlying transport should drain rather than close. + if tearDownErr == nil { + // tearDownErr is nil if resetAddrConn is called by + // 1) Dial + // 2) lbWatcher + // In both cases, the stale ac should drain, not close. + stale.tearDown(errConnDrain) + } else { + stale.tearDown(tearDownErr) + } + } + // skipWait may overwrite the decision in ac.dopts.block. + if ac.dopts.block && !skipWait { + if err := ac.resetTransport(false); err != nil { + if err != errConnClosing { + // Tear down ac and delete it from cc.conns. + cc.mu.Lock() + delete(cc.conns, ac.addr) + cc.mu.Unlock() + ac.tearDown(err) + } + if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { + return e.Origin() + } + return err + } + // Start to monitor the error status of transport. + go ac.transportMonitor() + } else { + // Start a goroutine connecting to the server asynchronously. + go func() { + if err := ac.resetTransport(false); err != nil { + grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err) + if err != errConnClosing { + // Keep this ac in cc.conns, to get the reason it's torn down. + ac.tearDown(err) + } + return + } + ac.transportMonitor() + }() + } + return nil } -// Close starts to tear down the ClientConn. +func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { + var ( + ac *addrConn + ok bool + put func() + ) + if cc.dopts.balancer == nil { + // If balancer is nil, there should be only one addrConn available. + cc.mu.RLock() + if cc.conns == nil { + cc.mu.RUnlock() + return nil, nil, toRPCErr(ErrClientConnClosing) + } + for _, ac = range cc.conns { + // Break after the first iteration to get the first addrConn. + ok = true + break + } + cc.mu.RUnlock() + } else { + var ( + addr Address + err error + ) + addr, put, err = cc.dopts.balancer.Get(ctx, opts) + if err != nil { + return nil, nil, toRPCErr(err) + } + cc.mu.RLock() + if cc.conns == nil { + cc.mu.RUnlock() + return nil, nil, toRPCErr(ErrClientConnClosing) + } + ac, ok = cc.conns[addr] + cc.mu.RUnlock() + } + if !ok { + if put != nil { + put() + } + return nil, nil, errConnClosing + } + t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait) + if err != nil { + if put != nil { + put() + } + return nil, nil, err + } + return t, put, nil +} + +// Close tears down the ClientConn and all underlying connections. func (cc *ClientConn) Close() error { - return cc.dopts.picker.Close() + cc.cancel() + + cc.mu.Lock() + if cc.conns == nil { + cc.mu.Unlock() + return ErrClientConnClosing + } + conns := cc.conns + cc.conns = nil + cc.mu.Unlock() + if cc.dopts.balancer != nil { + cc.dopts.balancer.Close() + } + for _, ac := range conns { + ac.tearDown(ErrClientConnClosing) + } + return nil } -// Conn is a client connection to a single destination. -type Conn struct { - target string - dopts dialOptions - resetChan chan int - shutdownChan chan struct{} - events trace.EventLog +// addrConn is a network connection to a given address. +type addrConn struct { + ctx context.Context + cancel context.CancelFunc + + cc *ClientConn + addr Address + dopts dialOptions + events trace.EventLog mu sync.Mutex state ConnectivityState stateCV *sync.Cond + down func(error) // the handler called when a connection is down. // ready is closed and becomes nil when a new transport is up or failed // due to timeout. ready chan struct{} transport transport.ClientTransport + + // The reason this addrConn is torn down. + tearDownErr error } -// NewConn creates a Conn. -func NewConn(cc *ClientConn) (*Conn, error) { - if cc.target == "" { - return nil, ErrUnspecTarget - } - c := &Conn{ - target: cc.target, - dopts: cc.dopts, - resetChan: make(chan int, 1), - shutdownChan: make(chan struct{}), - } - if EnableTracing { - c.events = trace.NewEventLog("grpc.ClientConn", c.target) - } - if !c.dopts.insecure { - var ok bool - for _, cd := range c.dopts.copts.AuthOptions { - if _, ok = cd.(credentials.TransportAuthenticator); ok { - break - } - } - if !ok { - return nil, ErrNoTransportSecurity - } - } else { - for _, cd := range c.dopts.copts.AuthOptions { - if cd.RequireTransportSecurity() { - return nil, ErrCredentialsMisuse - } - } - } - c.stateCV = sync.NewCond(&c.mu) - if c.dopts.block { - if err := c.resetTransport(false); err != nil { - c.Close() - return nil, err - } - // Start to monitor the error status of transport. - go c.transportMonitor() - } else { - // Start a goroutine connecting to the server asynchronously. - go func() { - if err := c.resetTransport(false); err != nil { - grpclog.Printf("Failed to dial %s: %v; please retry.", c.target, err) - c.Close() - return - } - c.transportMonitor() - }() - } - return c, nil -} - -// printf records an event in cc's event log, unless cc has been closed. -// REQUIRES cc.mu is held. -func (cc *Conn) printf(format string, a ...interface{}) { - if cc.events != nil { - cc.events.Printf(format, a...) +// printf records an event in ac's event log, unless ac has been closed. +// REQUIRES ac.mu is held. +func (ac *addrConn) printf(format string, a ...interface{}) { + if ac.events != nil { + ac.events.Printf(format, a...) } } -// errorf records an error in cc's event log, unless cc has been closed. -// REQUIRES cc.mu is held. -func (cc *Conn) errorf(format string, a ...interface{}) { - if cc.events != nil { - cc.events.Errorf(format, a...) +// errorf records an error in ac's event log, unless ac has been closed. +// REQUIRES ac.mu is held. +func (ac *addrConn) errorf(format string, a ...interface{}) { + if ac.events != nil { + ac.events.Errorf(format, a...) } } -// State returns the connectivity state of the Conn -func (cc *Conn) State() ConnectivityState { - cc.mu.Lock() - defer cc.mu.Unlock() - return cc.state +// getState returns the connectivity state of the Conn +func (ac *addrConn) getState() ConnectivityState { + ac.mu.Lock() + defer ac.mu.Unlock() + return ac.state } -// WaitForStateChange blocks until the state changes to something other than the sourceState. -func (cc *Conn) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { - cc.mu.Lock() - defer cc.mu.Unlock() - if sourceState != cc.state { - return cc.state, nil +// waitForStateChange blocks until the state changes to something other than the sourceState. +func (ac *addrConn) waitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { + ac.mu.Lock() + defer ac.mu.Unlock() + if sourceState != ac.state { + return ac.state, nil } done := make(chan struct{}) var err error go func() { select { case <-ctx.Done(): - cc.mu.Lock() + ac.mu.Lock() err = ctx.Err() - cc.stateCV.Broadcast() - cc.mu.Unlock() + ac.stateCV.Broadcast() + ac.mu.Unlock() case <-done: } }() defer close(done) - for sourceState == cc.state { - cc.stateCV.Wait() + for sourceState == ac.state { + ac.stateCV.Wait() if err != nil { - return cc.state, err + return ac.state, err } } - return cc.state, nil + return ac.state, nil } -// NotifyReset tries to signal the underlying transport needs to be reset due to -// for example a name resolution change in flight. -func (cc *Conn) NotifyReset() { - select { - case cc.resetChan <- 0: - default: - } -} - -func (cc *Conn) resetTransport(closeTransport bool) error { - var retries int - start := time.Now() - for { - cc.mu.Lock() - cc.printf("connecting") - if cc.state == Shutdown { - // cc.Close() has been invoked. - cc.mu.Unlock() - return ErrClientConnClosing +func (ac *addrConn) resetTransport(closeTransport bool) error { + for retries := 0; ; retries++ { + ac.mu.Lock() + ac.printf("connecting") + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + return errConnClosing } - cc.state = Connecting - cc.stateCV.Broadcast() - cc.mu.Unlock() - if closeTransport { - cc.transport.Close() + if ac.down != nil { + ac.down(downErrorf(false, true, "%v", errNetworkIO)) + ac.down = nil } - // Adjust timeout for the current try. - copts := cc.dopts.copts - if copts.Timeout < 0 { - cc.Close() - return ErrClientConnTimeout + ac.state = Connecting + ac.stateCV.Broadcast() + t := ac.transport + ac.mu.Unlock() + if closeTransport && t != nil { + t.Close() } - if copts.Timeout > 0 { - copts.Timeout -= time.Since(start) - if copts.Timeout <= 0 { - cc.Close() - return ErrClientConnTimeout - } - } - sleepTime := cc.dopts.bs.backoff(retries) - timeout := sleepTime - if timeout < minConnectTimeout { - timeout = minConnectTimeout - } - if copts.Timeout == 0 || copts.Timeout > timeout { - copts.Timeout = timeout + sleepTime := ac.dopts.bs.backoff(retries) + timeout := minConnectTimeout + if timeout < sleepTime { + timeout = sleepTime } + ctx, cancel := context.WithTimeout(ac.ctx, timeout) connectTime := time.Now() - addr, err := cc.dopts.picker.PickAddr() - var newTransport transport.ClientTransport - if err == nil { - newTransport, err = transport.NewClientTransport(addr, &copts) - } + newTransport, err := transport.NewClientTransport(ctx, ac.addr.Addr, ac.dopts.copts) if err != nil { - cc.mu.Lock() - if cc.state == Shutdown { - // cc.Close() has been invoked. - cc.mu.Unlock() - return ErrClientConnClosing + cancel() + + if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { + return err } - cc.errorf("transient failure: %v", err) - cc.state = TransientFailure - cc.stateCV.Broadcast() - if cc.ready != nil { - close(cc.ready) - cc.ready = nil + grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) + ac.mu.Lock() + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() + return errConnClosing } - cc.mu.Unlock() - sleepTime -= time.Since(connectTime) - if sleepTime < 0 { - sleepTime = 0 - } - // Fail early before falling into sleep. - if cc.dopts.copts.Timeout > 0 && cc.dopts.copts.Timeout < sleepTime+time.Since(start) { - cc.mu.Lock() - cc.errorf("connection timeout") - cc.mu.Unlock() - cc.Close() - return ErrClientConnTimeout + ac.errorf("transient failure: %v", err) + ac.state = TransientFailure + ac.stateCV.Broadcast() + if ac.ready != nil { + close(ac.ready) + ac.ready = nil } + ac.mu.Unlock() closeTransport = false - time.Sleep(sleepTime) - retries++ - grpclog.Printf("grpc: Conn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, cc.target) + select { + case <-time.After(sleepTime - time.Since(connectTime)): + case <-ac.ctx.Done(): + return ac.ctx.Err() + } continue } - cc.mu.Lock() - cc.printf("ready") - if cc.state == Shutdown { - // cc.Close() has been invoked. - cc.mu.Unlock() + ac.mu.Lock() + ac.printf("ready") + if ac.state == Shutdown { + // ac.tearDown(...) has been invoked. + ac.mu.Unlock() newTransport.Close() - return ErrClientConnClosing + return errConnClosing } - cc.state = Ready - cc.stateCV.Broadcast() - cc.transport = newTransport - if cc.ready != nil { - close(cc.ready) - cc.ready = nil + ac.state = Ready + ac.stateCV.Broadcast() + ac.transport = newTransport + if ac.ready != nil { + close(ac.ready) + ac.ready = nil } - cc.mu.Unlock() + if ac.cc.dopts.balancer != nil { + ac.down = ac.cc.dopts.balancer.Up(ac.addr) + } + ac.mu.Unlock() return nil } } -func (cc *Conn) reconnect() bool { - cc.mu.Lock() - if cc.state == Shutdown { - // cc.Close() has been invoked. - cc.mu.Unlock() - return false - } - cc.state = TransientFailure - cc.stateCV.Broadcast() - cc.mu.Unlock() - if err := cc.resetTransport(true); err != nil { - // The ClientConn is closing. - cc.mu.Lock() - cc.printf("transport exiting: %v", err) - cc.mu.Unlock() - grpclog.Printf("grpc: Conn.transportMonitor exits due to: %v", err) - return false - } - return true -} - // Run in a goroutine to track the error in transport and create the // new transport if an error happens. It returns when the channel is closing. -func (cc *Conn) transportMonitor() { +func (ac *addrConn) transportMonitor() { for { + ac.mu.Lock() + t := ac.transport + ac.mu.Unlock() select { - // shutdownChan is needed to detect the teardown when - // the ClientConn is idle (i.e., no RPC in flight). - case <-cc.shutdownChan: - return - case <-cc.resetChan: - if !cc.reconnect() { - return - } - case <-cc.transport.Error(): - if !cc.reconnect() { - return - } - // Tries to drain reset signal if there is any since it is out-dated. + // This is needed to detect the teardown when + // the addrConn is idle (i.e., no RPC in flight). + case <-ac.ctx.Done(): select { - case <-cc.resetChan: + case <-t.Error(): + t.Close() default: } - } - } -} - -// Wait blocks until i) the new transport is up or ii) ctx is done or iii) cc is closed. -func (cc *Conn) Wait(ctx context.Context) (transport.ClientTransport, error) { - for { - cc.mu.Lock() - switch { - case cc.state == Shutdown: - cc.mu.Unlock() - return nil, ErrClientConnClosing - case cc.state == Ready: - ct := cc.transport - cc.mu.Unlock() - return ct, nil - default: - ready := cc.ready - if ready == nil { - ready = make(chan struct{}) - cc.ready = ready - } - cc.mu.Unlock() + return + case <-t.GoAway(): + // If GoAway happens without any network I/O error, ac is closed without shutting down the + // underlying transport (the transport will be closed when all the pending RPCs finished or + // failed.). + // If GoAway and some network I/O error happen concurrently, ac and its underlying transport + // are closed. + // In both cases, a new ac is created. select { - case <-ctx.Done(): - return nil, transport.ContextErr(ctx.Err()) - // Wait until the new transport is ready or failed. - case <-ready: + case <-t.Error(): + ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) + default: + ac.cc.resetAddrConn(ac.addr, true, errConnDrain) + } + return + case <-t.Error(): + select { + case <-ac.ctx.Done(): + t.Close() + return + case <-t.GoAway(): + ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) + return + default: + } + ac.mu.Lock() + if ac.state == Shutdown { + // ac has been shutdown. + ac.mu.Unlock() + return + } + ac.state = TransientFailure + ac.stateCV.Broadcast() + ac.mu.Unlock() + if err := ac.resetTransport(true); err != nil { + ac.mu.Lock() + ac.printf("transport exiting: %v", err) + ac.mu.Unlock() + grpclog.Printf("grpc: addrConn.transportMonitor exits due to: %v", err) + if err != errConnClosing { + // Keep this ac in cc.conns, to get the reason it's torn down. + ac.tearDown(err) + } + return } } } } -// Close starts to tear down the Conn. Returns ErrClientConnClosing if -// it has been closed (mostly due to dial time-out). -// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in -// some edge cases (e.g., the caller opens and closes many ClientConn's in a -// tight loop. -func (cc *Conn) Close() error { - cc.mu.Lock() - defer cc.mu.Unlock() - if cc.state == Shutdown { - return ErrClientConnClosing +// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or +// iv) transport is in TransientFailure and there's no balancer/failfast is true. +func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) { + for { + ac.mu.Lock() + switch { + case ac.state == Shutdown: + if failfast || !hasBalancer { + // RPC is failfast or balancer is nil. This RPC should fail with ac.tearDownErr. + err := ac.tearDownErr + ac.mu.Unlock() + return nil, err + } + ac.mu.Unlock() + return nil, errConnClosing + case ac.state == Ready: + ct := ac.transport + ac.mu.Unlock() + return ct, nil + case ac.state == TransientFailure: + if failfast || hasBalancer { + ac.mu.Unlock() + return nil, errConnUnavailable + } + } + ready := ac.ready + if ready == nil { + ready = make(chan struct{}) + ac.ready = ready + } + ac.mu.Unlock() + select { + case <-ctx.Done(): + return nil, toRPCErr(ctx.Err()) + // Wait until the new transport is ready or failed. + case <-ready: + } } - cc.state = Shutdown - cc.stateCV.Broadcast() - if cc.events != nil { - cc.events.Finish() - cc.events = nil - } - if cc.ready != nil { - close(cc.ready) - cc.ready = nil - } - if cc.transport != nil { - cc.transport.Close() - } - if cc.shutdownChan != nil { - close(cc.shutdownChan) - } - return nil +} + +// tearDown starts to tear down the addrConn. +// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in +// some edge cases (e.g., the caller opens and closes many addrConn's in a +// tight loop. +// tearDown doesn't remove ac from ac.cc.conns. +func (ac *addrConn) tearDown(err error) { + ac.cancel() + + ac.mu.Lock() + defer ac.mu.Unlock() + if ac.down != nil { + ac.down(downErrorf(false, false, "%v", err)) + ac.down = nil + } + if err == errConnDrain && ac.transport != nil { + // GracefulClose(...) may be executed multiple times when + // i) receiving multiple GoAway frames from the server; or + // ii) there are concurrent name resolver/Balancer triggered + // address removal and GoAway. + ac.transport.GracefulClose() + } + if ac.state == Shutdown { + return + } + ac.state = Shutdown + ac.tearDownErr = err + ac.stateCV.Broadcast() + if ac.events != nil { + ac.events.Finish() + ac.events = nil + } + if ac.ready != nil { + close(ac.ready) + ac.ready = nil + } + if ac.transport != nil && err != errConnDrain { + ac.transport.Close() + } + return } diff --git a/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials.go b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials.go index 681f64e445..3f17b70628 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials.go +++ b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials.go @@ -44,7 +44,6 @@ import ( "io/ioutil" "net" "strings" - "time" "golang.org/x/net/context" ) @@ -54,9 +53,9 @@ var ( alpnProtoStr = []string{"h2"} ) -// Credentials defines the common interface all supported credentials must -// implement. -type Credentials interface { +// PerRPCCredentials defines the common interface for the credentials which need to +// attach security information to every RPC (e.g., oauth2). +type PerRPCCredentials interface { // GetRequestMetadata gets the current request metadata, refreshing // tokens if required. This should be called by the transport layer on // each request, and the data should be populated in headers or other @@ -66,7 +65,7 @@ type Credentials interface { // TODO(zhaoq): Define the set of the qualified keys instead of leaving // it as an arbitrary string. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) - // RequireTransportSecurity indicates whether the credentails requires + // RequireTransportSecurity indicates whether the credentials requires // transport security. RequireTransportSecurity() bool } @@ -87,20 +86,20 @@ type AuthInfo interface { AuthType() string } -// TransportAuthenticator defines the common interface for all the live gRPC wire +// TransportCredentials defines the common interface for all the live gRPC wire // protocols and supported transport security protocols (e.g., TLS, SSL). -type TransportAuthenticator interface { +type TransportCredentials interface { // ClientHandshake does the authentication handshake specified by the corresponding // authentication protocol on rawConn for clients. It returns the authenticated // connection and the corresponding auth information about the connection. - ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error) + // Implementations must use the provided context to implement timely cancellation. + ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) // ServerHandshake does the authentication handshake for servers. It returns // the authenticated connection and the corresponding auth information about // the connection. - ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) - // Info provides the ProtocolInfo of this TransportAuthenticator. + ServerHandshake(net.Conn) (net.Conn, AuthInfo, error) + // Info provides the ProtocolInfo of this TransportCredentials. Info() ProtocolInfo - Credentials } // TLSInfo contains the auth information for a TLS authenticated connection. @@ -109,6 +108,7 @@ type TLSInfo struct { State tls.ConnectionState } +// AuthType returns the type of TLSInfo as a string. func (t TLSInfo) AuthType() string { return "tls" } @@ -116,7 +116,7 @@ func (t TLSInfo) AuthType() string { // tlsCreds is the credentials required for authenticating a connection using TLS. type tlsCreds struct { // TLS configuration - config tls.Config + config *tls.Config } func (c tlsCreds) Info() ProtocolInfo { @@ -136,40 +136,28 @@ func (c *tlsCreds) RequireTransportSecurity() bool { return true } -type timeoutError struct{} - -func (timeoutError) Error() string { return "credentials: Dial timed out" } -func (timeoutError) Timeout() bool { return true } -func (timeoutError) Temporary() bool { return true } - -func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) { - // borrow some code from tls.DialWithDialer - var errChannel chan error - if timeout != 0 { - errChannel = make(chan error, 2) - time.AfterFunc(timeout, func() { - errChannel <- timeoutError{} - }) - } - if c.config.ServerName == "" { +func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) { + // use local cfg to avoid clobbering ServerName if using multiple endpoints + cfg := cloneTLSConfig(c.config) + if cfg.ServerName == "" { colonPos := strings.LastIndex(addr, ":") if colonPos == -1 { colonPos = len(addr) } - c.config.ServerName = addr[:colonPos] + cfg.ServerName = addr[:colonPos] } - conn := tls.Client(rawConn, &c.config) - if timeout == 0 { - err = conn.Handshake() - } else { - go func() { - errChannel <- conn.Handshake() - }() - err = <-errChannel - } - if err != nil { - rawConn.Close() - return nil, nil, err + conn := tls.Client(rawConn, cfg) + errChannel := make(chan error, 1) + go func() { + errChannel <- conn.Handshake() + }() + select { + case err := <-errChannel: + if err != nil { + return nil, nil, err + } + case <-ctx.Done(): + return nil, nil, ctx.Err() } // TODO(zhaoq): Omit the auth info for client now. It is more for // information than anything else. @@ -177,28 +165,27 @@ func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.D } func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { - conn := tls.Server(rawConn, &c.config) + conn := tls.Server(rawConn, c.config) if err := conn.Handshake(); err != nil { - rawConn.Close() return nil, nil, err } return conn, TLSInfo{conn.ConnectionState()}, nil } -// NewTLS uses c to construct a TransportAuthenticator based on TLS. -func NewTLS(c *tls.Config) TransportAuthenticator { - tc := &tlsCreds{*c} +// NewTLS uses c to construct a TransportCredentials based on TLS. +func NewTLS(c *tls.Config) TransportCredentials { + tc := &tlsCreds{cloneTLSConfig(c)} tc.config.NextProtos = alpnProtoStr return tc } // NewClientTLSFromCert constructs a TLS from the input certificate for client. -func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportAuthenticator { +func NewClientTLSFromCert(cp *x509.CertPool, serverName string) TransportCredentials { return NewTLS(&tls.Config{ServerName: serverName, RootCAs: cp}) } // NewClientTLSFromFile constructs a TLS from the input certificate file for client. -func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, error) { +func NewClientTLSFromFile(certFile, serverName string) (TransportCredentials, error) { b, err := ioutil.ReadFile(certFile) if err != nil { return nil, err @@ -211,13 +198,13 @@ func NewClientTLSFromFile(certFile, serverName string) (TransportAuthenticator, } // NewServerTLSFromCert constructs a TLS from the input certificate for server. -func NewServerTLSFromCert(cert *tls.Certificate) TransportAuthenticator { +func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials { return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}}) } // NewServerTLSFromFile constructs a TLS from the input certificate file and key // file for server. -func NewServerTLSFromFile(certFile, keyFile string) (TransportAuthenticator, error) { +func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, err diff --git a/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_go17.go b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_go17.go new file mode 100644 index 0000000000..9647b9ec83 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_go17.go @@ -0,0 +1,76 @@ +// +build go1.7 + +/* + * + * Copyright 2016, 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 credentials + +import ( + "crypto/tls" +) + +// cloneTLSConfig returns a shallow clone of the exported +// fields of cfg, ignoring the unexported sync.Once, which +// contains a mutex and must not be copied. +// +// If cfg is nil, a new zero tls.Config is returned. +// +// TODO replace this function with official clone function. +func cloneTLSConfig(cfg *tls.Config) *tls.Config { + if cfg == nil { + return &tls.Config{} + } + return &tls.Config{ + Rand: cfg.Rand, + Time: cfg.Time, + Certificates: cfg.Certificates, + NameToCertificate: cfg.NameToCertificate, + GetCertificate: cfg.GetCertificate, + RootCAs: cfg.RootCAs, + NextProtos: cfg.NextProtos, + ServerName: cfg.ServerName, + ClientAuth: cfg.ClientAuth, + ClientCAs: cfg.ClientCAs, + InsecureSkipVerify: cfg.InsecureSkipVerify, + CipherSuites: cfg.CipherSuites, + PreferServerCipherSuites: cfg.PreferServerCipherSuites, + SessionTicketsDisabled: cfg.SessionTicketsDisabled, + SessionTicketKey: cfg.SessionTicketKey, + ClientSessionCache: cfg.ClientSessionCache, + MinVersion: cfg.MinVersion, + MaxVersion: cfg.MaxVersion, + CurvePreferences: cfg.CurvePreferences, + DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, + Renegotiation: cfg.Renegotiation, + } +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_pre_go17.go b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_pre_go17.go new file mode 100644 index 0000000000..09b8d12c79 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/credentials/credentials_util_pre_go17.go @@ -0,0 +1,74 @@ +// +build !go1.7 + +/* + * + * Copyright 2016, 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 credentials + +import ( + "crypto/tls" +) + +// cloneTLSConfig returns a shallow clone of the exported +// fields of cfg, ignoring the unexported sync.Once, which +// contains a mutex and must not be copied. +// +// If cfg is nil, a new zero tls.Config is returned. +// +// TODO replace this function with official clone function. +func cloneTLSConfig(cfg *tls.Config) *tls.Config { + if cfg == nil { + return &tls.Config{} + } + return &tls.Config{ + Rand: cfg.Rand, + Time: cfg.Time, + Certificates: cfg.Certificates, + NameToCertificate: cfg.NameToCertificate, + GetCertificate: cfg.GetCertificate, + RootCAs: cfg.RootCAs, + NextProtos: cfg.NextProtos, + ServerName: cfg.ServerName, + ClientAuth: cfg.ClientAuth, + ClientCAs: cfg.ClientCAs, + InsecureSkipVerify: cfg.InsecureSkipVerify, + CipherSuites: cfg.CipherSuites, + PreferServerCipherSuites: cfg.PreferServerCipherSuites, + SessionTicketsDisabled: cfg.SessionTicketsDisabled, + SessionTicketKey: cfg.SessionTicketKey, + ClientSessionCache: cfg.ClientSessionCache, + MinVersion: cfg.MinVersion, + MaxVersion: cfg.MaxVersion, + CurvePreferences: cfg.CurvePreferences, + } +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/credentials/oauth/oauth.go b/components/engine/vendor/src/google.golang.org/grpc/credentials/oauth/oauth.go index 04943fdf03..8e68c4d73b 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/credentials/oauth/oauth.go +++ b/components/engine/vendor/src/google.golang.org/grpc/credentials/oauth/oauth.go @@ -45,7 +45,7 @@ import ( "google.golang.org/grpc/credentials" ) -// TokenSource supplies credentials from an oauth2.TokenSource. +// TokenSource supplies PerRPCCredentials from an oauth2.TokenSource. type TokenSource struct { oauth2.TokenSource } @@ -57,10 +57,11 @@ func (ts TokenSource) GetRequestMetadata(ctx context.Context, uri ...string) (ma return nil, err } return map[string]string{ - "authorization": token.TokenType + " " + token.AccessToken, + "authorization": token.Type() + " " + token.AccessToken, }, nil } +// RequireTransportSecurity indicates whether the credentails requires transport security. func (ts TokenSource) RequireTransportSecurity() bool { return true } @@ -69,7 +70,8 @@ type jwtAccess struct { jsonKey []byte } -func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, error) { +// NewJWTAccessFromFile creates PerRPCCredentials from the given keyFile. +func NewJWTAccessFromFile(keyFile string) (credentials.PerRPCCredentials, error) { jsonKey, err := ioutil.ReadFile(keyFile) if err != nil { return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) @@ -77,7 +79,8 @@ func NewJWTAccessFromFile(keyFile string) (credentials.Credentials, error) { return NewJWTAccessFromKey(jsonKey) } -func NewJWTAccessFromKey(jsonKey []byte) (credentials.Credentials, error) { +// NewJWTAccessFromKey creates PerRPCCredentials from the given jsonKey. +func NewJWTAccessFromKey(jsonKey []byte) (credentials.PerRPCCredentials, error) { return jwtAccess{jsonKey}, nil } @@ -99,13 +102,13 @@ func (j jwtAccess) RequireTransportSecurity() bool { return true } -// oauthAccess supplies credentials from a given token. +// oauthAccess supplies PerRPCCredentials from a given token. type oauthAccess struct { token oauth2.Token } -// NewOauthAccess constructs the credentials using a given token. -func NewOauthAccess(token *oauth2.Token) credentials.Credentials { +// NewOauthAccess constructs the PerRPCCredentials using a given token. +func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials { return oauthAccess{token: *token} } @@ -119,15 +122,15 @@ func (oa oauthAccess) RequireTransportSecurity() bool { return true } -// NewComputeEngine constructs the credentials that fetches access tokens from +// NewComputeEngine constructs the PerRPCCredentials that fetches access tokens from // Google Compute Engine (GCE)'s metadata server. It is only valid to use this // if your program is running on a GCE instance. // TODO(dsymonds): Deprecate and remove this. -func NewComputeEngine() credentials.Credentials { +func NewComputeEngine() credentials.PerRPCCredentials { return TokenSource{google.ComputeTokenSource("")} } -// serviceAccount represents credentials via JWT signing key. +// serviceAccount represents PerRPCCredentials via JWT signing key. type serviceAccount struct { config *jwt.Config } @@ -146,9 +149,9 @@ func (s serviceAccount) RequireTransportSecurity() bool { return true } -// NewServiceAccountFromKey constructs the credentials using the JSON key slice +// NewServiceAccountFromKey constructs the PerRPCCredentials using the JSON key slice // from a Google Developers service account. -func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Credentials, error) { +func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.PerRPCCredentials, error) { config, err := google.JWTConfigFromJSON(jsonKey, scope...) if err != nil { return nil, err @@ -156,9 +159,9 @@ func NewServiceAccountFromKey(jsonKey []byte, scope ...string) (credentials.Cred return serviceAccount{config: config}, nil } -// NewServiceAccountFromFile constructs the credentials using the JSON key file +// NewServiceAccountFromFile constructs the PerRPCCredentials using the JSON key file // of a Google Developers service account. -func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Credentials, error) { +func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.PerRPCCredentials, error) { jsonKey, err := ioutil.ReadFile(keyFile) if err != nil { return nil, fmt.Errorf("credentials: failed to read the service account key file: %v", err) @@ -168,7 +171,7 @@ func NewServiceAccountFromFile(keyFile string, scope ...string) (credentials.Cre // NewApplicationDefault returns "Application Default Credentials". For more // detail, see https://developers.google.com/accounts/docs/application-default-credentials. -func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.Credentials, error) { +func NewApplicationDefault(ctx context.Context, scope ...string) (credentials.PerRPCCredentials, error) { t, err := google.DefaultTokenSource(ctx, scope...) if err != nil { return nil, err diff --git a/components/engine/vendor/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go b/components/engine/vendor/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go index d9550c728b..0e6a9100af 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go +++ b/components/engine/vendor/src/google.golang.org/grpc/health/grpc_health_v1/health.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-go. -// source: health/grpc_health_v1/health.proto +// source: health.proto // DO NOT EDIT! /* Package grpc_health_v1 is a generated protocol buffer package. It is generated from these files: - health/grpc_health_v1/health.proto + health.proto It has these top-level messages: HealthCheckRequest @@ -30,7 +30,9 @@ 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. -const _ = proto.ProtoPackageIsVersion1 +// 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 HealthCheckResponse_ServingStatus int32 @@ -88,7 +90,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for Health service @@ -150,23 +152,25 @@ var _Health_serviceDesc = grpc.ServiceDesc{ Handler: _Health_Check_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor0, } +func init() { proto.RegisterFile("health.proto", fileDescriptor0) } + var fileDescriptor0 = []byte{ - // 209 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0xca, 0x48, 0x4d, 0xcc, - 0x29, 0xc9, 0xd0, 0x4f, 0x2f, 0x2a, 0x48, 0x8e, 0x87, 0xb0, 0xe3, 0xcb, 0x0c, 0xf5, 0x21, 0x2c, - 0xbd, 0x82, 0xa2, 0xfc, 0x92, 0x7c, 0x21, 0x3e, 0x90, 0xa4, 0x1e, 0x54, 0xa8, 0xcc, 0x50, 0x49, - 0x95, 0x4b, 0xc8, 0x03, 0xcc, 0x71, 0xce, 0x48, 0x4d, 0xce, 0x0e, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, - 0x2e, 0x11, 0xe2, 0xe7, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x95, 0x60, 0x54, 0x60, - 0xd4, 0xe0, 0x54, 0x9a, 0xc2, 0xc8, 0x25, 0x8c, 0xa2, 0xae, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, - 0xc8, 0x91, 0x8b, 0xad, 0xb8, 0x24, 0xb1, 0xa4, 0xb4, 0x18, 0xac, 0x8e, 0xcf, 0xc8, 0x50, 0x0f, - 0xd5, 0x7c, 0x3d, 0x2c, 0x9a, 0xf4, 0x82, 0x41, 0x46, 0xe7, 0xa5, 0x07, 0x83, 0x35, 0x2a, 0x59, - 0x71, 0xf1, 0xa2, 0x08, 0x08, 0x71, 0x73, 0xb1, 0x87, 0xfa, 0x79, 0xfb, 0xf9, 0x87, 0xfb, 0x09, - 0x30, 0x80, 0x38, 0xc1, 0xae, 0x41, 0x61, 0x9e, 0x7e, 0xee, 0x02, 0x8c, 0x40, 0x67, 0x71, 0xfb, - 0xf9, 0x87, 0xc4, 0xc3, 0x04, 0x98, 0x8c, 0xa2, 0xb8, 0xd8, 0x20, 0x16, 0x08, 0x05, 0x70, 0xb1, - 0x82, 0x2d, 0x11, 0x52, 0xc2, 0xeb, 0x02, 0xb0, 0xf7, 0xa4, 0x94, 0x89, 0x70, 0x65, 0x12, 0x1b, - 0x38, 0xc0, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xf7, 0x2e, 0x1f, 0x56, 0x01, 0x00, - 0x00, + // 204 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x48, 0x4d, 0xcc, + 0x29, 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x83, + 0x0a, 0x95, 0x19, 0x2a, 0xe9, 0x71, 0x09, 0x79, 0x80, 0x39, 0xce, 0x19, 0xa9, 0xc9, 0xd9, 0x41, + 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0x45, 0x65, 0x99, 0xc9, + 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0xd2, 0x1c, 0x46, 0x2e, 0x61, 0x14, + 0x0d, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x9e, 0x5c, 0x6c, 0xc5, 0x25, 0x89, 0x25, 0xa5, + 0xc5, 0x60, 0x0d, 0x7c, 0x46, 0x86, 0x7a, 0xa8, 0x16, 0xe9, 0x61, 0xd1, 0xa4, 0x17, 0x0c, 0x32, + 0x34, 0x2f, 0x3d, 0x18, 0xac, 0x31, 0x08, 0x6a, 0x80, 0x92, 0x15, 0x17, 0x2f, 0x8a, 0x84, 0x10, + 0x37, 0x17, 0x7b, 0xa8, 0x9f, 0xb7, 0x9f, 0x7f, 0xb8, 0x9f, 0x00, 0x03, 0x88, 0x13, 0xec, 0x1a, + 0x14, 0xe6, 0xe9, 0xe7, 0x2e, 0xc0, 0x28, 0xc4, 0xcf, 0xc5, 0xed, 0xe7, 0x1f, 0x12, 0x0f, 0x13, + 0x60, 0x32, 0x8a, 0xe2, 0x62, 0x83, 0x58, 0x24, 0x14, 0xc0, 0xc5, 0x0a, 0xb6, 0x4c, 0x48, 0x09, + 0xaf, 0x4b, 0xc0, 0xfe, 0x95, 0x52, 0x26, 0xc2, 0xb5, 0x49, 0x6c, 0xe0, 0x10, 0x34, 0x06, 0x04, + 0x00, 0x00, 0xff, 0xff, 0xac, 0x56, 0x2a, 0xcb, 0x51, 0x01, 0x00, 0x00, } diff --git a/components/engine/vendor/src/google.golang.org/grpc/metadata/metadata.go b/components/engine/vendor/src/google.golang.org/grpc/metadata/metadata.go index 52070dbeca..954c0f77c6 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/metadata/metadata.go +++ b/components/engine/vendor/src/google.golang.org/grpc/metadata/metadata.go @@ -60,15 +60,21 @@ func encodeKeyValue(k, v string) (string, string) { // DecodeKeyValue returns the original key and value corresponding to the // encoded data in k, v. +// If k is a binary header and v contains comma, v is split on comma before decoded, +// and the decoded v will be joined with comma before returned. func DecodeKeyValue(k, v string) (string, string, error) { if !strings.HasSuffix(k, binHdrSuffix) { return k, v, nil } - val, err := base64.StdEncoding.DecodeString(v) - if err != nil { - return "", "", err + vvs := strings.Split(v, ",") + for i, vv := range vvs { + val, err := base64.StdEncoding.DecodeString(vv) + if err != nil { + return "", "", err + } + vvs[i] = string(val) } - return k, string(val), nil + return k, strings.Join(vvs, ","), nil } // MD is a mapping from metadata keys to values. Users should use the following diff --git a/components/engine/vendor/src/google.golang.org/grpc/naming/naming.go b/components/engine/vendor/src/google.golang.org/grpc/naming/naming.go index 06605607c3..c2e0871e6f 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/naming/naming.go +++ b/components/engine/vendor/src/google.golang.org/grpc/naming/naming.go @@ -66,7 +66,8 @@ type Resolver interface { // Watcher watches for the updates on the specified target. type Watcher interface { // Next blocks until an update or error happens. It may return one or more - // updates. The first call should get the full set of the results. + // updates. The first call should get the full set of the results. It should + // return an error if and only if Watcher cannot recover. Next() ([]*Update, error) // Close closes the Watcher. Close() diff --git a/components/engine/vendor/src/google.golang.org/grpc/picker.go b/components/engine/vendor/src/google.golang.org/grpc/picker.go deleted file mode 100644 index 50f315b44f..0000000000 --- a/components/engine/vendor/src/google.golang.org/grpc/picker.go +++ /dev/null @@ -1,243 +0,0 @@ -/* - * - * Copyright 2014, 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 grpc - -import ( - "container/list" - "fmt" - "sync" - - "golang.org/x/net/context" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/naming" - "google.golang.org/grpc/transport" -) - -// Picker picks a Conn for RPC requests. -// This is EXPERIMENTAL and please do not implement your own Picker for now. -type Picker interface { - // Init does initial processing for the Picker, e.g., initiate some connections. - Init(cc *ClientConn) error - // Pick blocks until either a transport.ClientTransport is ready for the upcoming RPC - // or some error happens. - Pick(ctx context.Context) (transport.ClientTransport, error) - // PickAddr picks a peer address for connecting. This will be called repeated for - // connecting/reconnecting. - PickAddr() (string, error) - // State returns the connectivity state of the underlying connections. - State() (ConnectivityState, error) - // WaitForStateChange blocks until the state changes to something other than - // the sourceState. It returns the new state or error. - WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) - // Close closes all the Conn's owned by this Picker. - Close() error -} - -// unicastPicker is the default Picker which is used when there is no custom Picker -// specified by users. It always picks the same Conn. -type unicastPicker struct { - target string - conn *Conn -} - -func (p *unicastPicker) Init(cc *ClientConn) error { - c, err := NewConn(cc) - if err != nil { - return err - } - p.conn = c - return nil -} - -func (p *unicastPicker) Pick(ctx context.Context) (transport.ClientTransport, error) { - return p.conn.Wait(ctx) -} - -func (p *unicastPicker) PickAddr() (string, error) { - return p.target, nil -} - -func (p *unicastPicker) State() (ConnectivityState, error) { - return p.conn.State(), nil -} - -func (p *unicastPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { - return p.conn.WaitForStateChange(ctx, sourceState) -} - -func (p *unicastPicker) Close() error { - if p.conn != nil { - return p.conn.Close() - } - return nil -} - -// unicastNamingPicker picks an address from a name resolver to set up the connection. -type unicastNamingPicker struct { - cc *ClientConn - resolver naming.Resolver - watcher naming.Watcher - mu sync.Mutex - // The list of the addresses are obtained from watcher. - addrs *list.List - // It tracks the current picked addr by PickAddr(). The next PickAddr may - // push it forward on addrs. - pickedAddr *list.Element - conn *Conn -} - -// NewUnicastNamingPicker creates a Picker to pick addresses from a name resolver -// to connect. -func NewUnicastNamingPicker(r naming.Resolver) Picker { - return &unicastNamingPicker{ - resolver: r, - addrs: list.New(), - } -} - -type addrInfo struct { - addr string - // Set to true if this addrInfo needs to be deleted in the next PickAddrr() call. - deleting bool -} - -// processUpdates calls Watcher.Next() once and processes the obtained updates. -func (p *unicastNamingPicker) processUpdates() error { - updates, err := p.watcher.Next() - if err != nil { - return err - } - for _, update := range updates { - switch update.Op { - case naming.Add: - p.mu.Lock() - p.addrs.PushBack(&addrInfo{ - addr: update.Addr, - }) - p.mu.Unlock() - // Initial connection setup - if p.conn == nil { - conn, err := NewConn(p.cc) - if err != nil { - return err - } - p.conn = conn - } - case naming.Delete: - p.mu.Lock() - for e := p.addrs.Front(); e != nil; e = e.Next() { - if update.Addr == e.Value.(*addrInfo).addr { - if e == p.pickedAddr { - // Do not remove the element now if it is the current picked - // one. We leave the deletion to the next PickAddr() call. - e.Value.(*addrInfo).deleting = true - // Notify Conn to close it. All the live RPCs on this connection - // will be aborted. - p.conn.NotifyReset() - } else { - p.addrs.Remove(e) - } - } - } - p.mu.Unlock() - default: - grpclog.Println("Unknown update.Op ", update.Op) - } - } - return nil -} - -// monitor runs in a standalone goroutine to keep watching name resolution updates until the watcher -// is closed. -func (p *unicastNamingPicker) monitor() { - for { - if err := p.processUpdates(); err != nil { - return - } - } -} - -func (p *unicastNamingPicker) Init(cc *ClientConn) error { - w, err := p.resolver.Resolve(cc.target) - if err != nil { - return err - } - p.watcher = w - p.cc = cc - // Get the initial name resolution. - if err := p.processUpdates(); err != nil { - return err - } - go p.monitor() - return nil -} - -func (p *unicastNamingPicker) Pick(ctx context.Context) (transport.ClientTransport, error) { - return p.conn.Wait(ctx) -} - -func (p *unicastNamingPicker) PickAddr() (string, error) { - p.mu.Lock() - defer p.mu.Unlock() - if p.pickedAddr == nil { - p.pickedAddr = p.addrs.Front() - } else { - pa := p.pickedAddr - p.pickedAddr = pa.Next() - if pa.Value.(*addrInfo).deleting { - p.addrs.Remove(pa) - } - if p.pickedAddr == nil { - p.pickedAddr = p.addrs.Front() - } - } - if p.pickedAddr == nil { - return "", fmt.Errorf("there is no address available to pick") - } - return p.pickedAddr.Value.(*addrInfo).addr, nil -} - -func (p *unicastNamingPicker) State() (ConnectivityState, error) { - return 0, fmt.Errorf("State() is not supported for unicastNamingPicker") -} - -func (p *unicastNamingPicker) WaitForStateChange(ctx context.Context, sourceState ConnectivityState) (ConnectivityState, error) { - return 0, fmt.Errorf("WaitForStateChange is not supported for unicastNamingPciker") -} - -func (p *unicastNamingPicker) Close() error { - p.watcher.Close() - p.conn.Close() - return nil -} diff --git a/components/engine/vendor/src/google.golang.org/grpc/rpc_util.go b/components/engine/vendor/src/google.golang.org/grpc/rpc_util.go index 3192f01185..35ac9cc7b0 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/rpc_util.go +++ b/components/engine/vendor/src/google.golang.org/grpc/rpc_util.go @@ -61,7 +61,7 @@ type Codec interface { String() string } -// protoCodec is a Codec implemetation with protobuf. It is the default codec for gRPC. +// protoCodec is a Codec implementation with protobuf. It is the default codec for gRPC. type protoCodec struct{} func (protoCodec) Marshal(v interface{}) ([]byte, error) { @@ -141,6 +141,8 @@ type callInfo struct { traceInfo traceInfo // in trace.go } +var defaultCallInfo = callInfo{failFast: true} + // CallOption configures a Call before it starts or extracts information from // a Call after it completes. type CallOption interface { @@ -179,6 +181,19 @@ func Trailer(md *metadata.MD) CallOption { }) } +// FailFast configures the action to take when an RPC is attempted on broken +// connections or unreachable servers. If failfast is true, the RPC will fail +// immediately. Otherwise, the RPC client will block the call until a +// connection is available (or the call is canceled or times out) and will retry +// the call if it fails due to a transient error. Please refer to +// https://github.com/grpc/grpc/blob/master/doc/fail_fast.md +func FailFast(failFast bool) CallOption { + return beforeCall(func(c *callInfo) error { + c.failFast = failFast + return nil + }) +} + // The format of the payload: compressed or not? type payloadFormat uint8 @@ -187,7 +202,7 @@ const ( compressionMade ) -// parser reads complelete gRPC messages from the underlying reader. +// parser reads complete gRPC messages from the underlying reader. type parser struct { // r is the underlying reader. // See the comment on recvMsg for the permissible @@ -212,7 +227,7 @@ type parser struct { // No other error values or types must be returned, which also means // that the underlying io.Reader must not return an incompatible // error. -func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) { +func (p *parser) recvMsg(maxMsgSize int) (pf payloadFormat, msg []byte, err error) { if _, err := io.ReadFull(p.r, p.header[:]); err != nil { return 0, nil, err } @@ -223,6 +238,9 @@ func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) { if length == 0 { return pf, nil, nil } + if length > uint32(maxMsgSize) { + return 0, nil, Errorf(codes.Internal, "grpc: received message length %d exceeding the max size %d", length, maxMsgSize) + } // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead // of making it for each message: msg = make([]byte, int(length)) @@ -284,20 +302,17 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) er switch pf { case compressionNone: case compressionMade: - if recvCompress == "" { - return transport.StreamErrorf(codes.InvalidArgument, "grpc: invalid grpc-encoding %q with compression enabled", recvCompress) - } if dc == nil || recvCompress != dc.Type() { - return transport.StreamErrorf(codes.InvalidArgument, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) + return transport.StreamErrorf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) } default: - return transport.StreamErrorf(codes.InvalidArgument, "grpc: received unexpected payload format %d", pf) + return transport.StreamErrorf(codes.Internal, "grpc: received unexpected payload format %d", pf) } return nil } -func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}) error { - pf, d, err := p.recvMsg() +func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}, maxMsgSize int) error { + pf, d, err := p.recvMsg(maxMsgSize) if err != nil { return err } @@ -307,11 +322,16 @@ func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{ if pf == compressionMade { d, err = dc.Do(bytes.NewReader(d)) if err != nil { - return transport.StreamErrorf(codes.Internal, "grpc: failed to decompress the received message %v", err) + return Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) } } + if len(d) > maxMsgSize { + // TODO: Revisit the error code. Currently keep it consistent with java + // implementation. + return Errorf(codes.Internal, "grpc: received a message of %d bytes exceeding %d limit", len(d), maxMsgSize) + } if err := c.Unmarshal(d, m); err != nil { - return transport.StreamErrorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) + return Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) } return nil } @@ -322,7 +342,7 @@ type rpcError struct { desc string } -func (e rpcError) Error() string { +func (e *rpcError) Error() string { return fmt.Sprintf("rpc error: code = %d desc = %s", e.code, e.desc) } @@ -332,7 +352,7 @@ func Code(err error) codes.Code { if err == nil { return codes.OK } - if e, ok := err.(rpcError); ok { + if e, ok := err.(*rpcError); ok { return e.code } return codes.Unknown @@ -344,7 +364,7 @@ func ErrorDesc(err error) string { if err == nil { return "" } - if e, ok := err.(rpcError); ok { + if e, ok := err.(*rpcError); ok { return e.desc } return err.Error() @@ -356,7 +376,7 @@ func Errorf(c codes.Code, format string, a ...interface{}) error { if c == codes.OK { return nil } - return rpcError{ + return &rpcError{ code: c, desc: fmt.Sprintf(format, a...), } @@ -365,18 +385,37 @@ func Errorf(c codes.Code, format string, a ...interface{}) error { // toRPCErr converts an error into a rpcError. func toRPCErr(err error) error { switch e := err.(type) { - case rpcError: + case *rpcError: return err case transport.StreamError: - return rpcError{ + return &rpcError{ code: e.Code, desc: e.Desc, } case transport.ConnectionError: - return rpcError{ + return &rpcError{ code: codes.Internal, desc: e.Desc, } + default: + switch err { + case context.DeadlineExceeded: + return &rpcError{ + code: codes.DeadlineExceeded, + desc: err.Error(), + } + case context.Canceled: + return &rpcError{ + code: codes.Canceled, + desc: err.Error(), + } + case ErrClientConnClosing: + return &rpcError{ + code: codes.FailedPrecondition, + desc: err.Error(), + } + } + } return Errorf(codes.Unknown, "%v", err) } @@ -409,10 +448,10 @@ func convertCode(err error) codes.Code { return codes.Unknown } -// SupportPackageIsVersion2 is referenced from generated protocol buffer files +// SupportPackageIsVersion3 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the grpc package. // // This constant may be renamed in the future if a change in the generated code // requires a synchronised update of grpc-go and protoc-gen-go. This constant // should not be referenced from any other code. -const SupportPackageIsVersion2 = true +const SupportPackageIsVersion3 = true diff --git a/components/engine/vendor/src/google.golang.org/grpc/server.go b/components/engine/vendor/src/google.golang.org/grpc/server.go index d3a8073d9c..1ed8aac9eb 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/server.go +++ b/components/engine/vendor/src/google.golang.org/grpc/server.go @@ -73,6 +73,7 @@ type ServiceDesc struct { HandlerType interface{} Methods []MethodDesc Streams []StreamDesc + Metadata interface{} } // service consists of the information of the server serving this service and @@ -81,30 +82,38 @@ type service struct { server interface{} // the server for service methods md map[string]*MethodDesc sd map[string]*StreamDesc + mdata interface{} } // Server is a gRPC server to serve RPC requests. type Server struct { opts options - mu sync.Mutex // guards following - lis map[net.Listener]bool - conns map[io.Closer]bool + mu sync.Mutex // guards following + lis map[net.Listener]bool + conns map[io.Closer]bool + drain bool + // A CondVar to let GracefulStop() blocks until all the pending RPCs are finished + // and all the transport goes away. + cv *sync.Cond m map[string]*service // service name -> service info events trace.EventLog } type options struct { - creds credentials.Credentials + creds credentials.TransportCredentials codec Codec cp Compressor dc Decompressor + maxMsgSize int unaryInt UnaryServerInterceptor streamInt StreamServerInterceptor maxConcurrentStreams uint32 useHandlerImpl bool // use http.Handler-based server } +var defaultMaxMsgSize = 1024 * 1024 * 4 // use 4MB as the default message size limit + // A ServerOption sets options. type ServerOption func(*options) @@ -115,18 +124,28 @@ func CustomCodec(codec Codec) ServerOption { } } +// RPCCompressor returns a ServerOption that sets a compressor for outbound messages. func RPCCompressor(cp Compressor) ServerOption { return func(o *options) { o.cp = cp } } +// RPCDecompressor returns a ServerOption that sets a decompressor for inbound messages. func RPCDecompressor(dc Decompressor) ServerOption { return func(o *options) { o.dc = dc } } +// MaxMsgSize returns a ServerOption to set the max message size in bytes for inbound mesages. +// If this is not set, gRPC uses the default 4MB. +func MaxMsgSize(m int) ServerOption { + return func(o *options) { + o.maxMsgSize = m + } +} + // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number // of concurrent streams to each ServerTransport. func MaxConcurrentStreams(n uint32) ServerOption { @@ -136,7 +155,7 @@ func MaxConcurrentStreams(n uint32) ServerOption { } // Creds returns a ServerOption that sets credentials for server connections. -func Creds(c credentials.Credentials) ServerOption { +func Creds(c credentials.TransportCredentials) ServerOption { return func(o *options) { o.creds = c } @@ -169,6 +188,7 @@ func StreamInterceptor(i StreamServerInterceptor) ServerOption { // started to accept requests yet. func NewServer(opt ...ServerOption) *Server { var opts options + opts.maxMsgSize = defaultMaxMsgSize for _, o := range opt { o(&opts) } @@ -182,6 +202,7 @@ func NewServer(opt ...ServerOption) *Server { conns: make(map[io.Closer]bool), m: make(map[string]*service), } + s.cv = sync.NewCond(&s.mu) if EnableTracing { _, file, line, _ := runtime.Caller(1) s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) @@ -228,6 +249,7 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) { server: ss, md: make(map[string]*MethodDesc), sd: make(map[string]*StreamDesc), + mdata: sd.Metadata, } for i := range sd.Methods { d := &sd.Methods[i] @@ -240,6 +262,52 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) { s.m[sd.ServiceName] = srv } +// MethodInfo contains the information of an RPC including its method name and type. +type MethodInfo struct { + // Name is the method name only, without the service name or package name. + Name string + // IsClientStream indicates whether the RPC is a client streaming RPC. + IsClientStream bool + // IsServerStream indicates whether the RPC is a server streaming RPC. + IsServerStream bool +} + +// ServiceInfo contains unary RPC method info, streaming RPC methid info and metadata for a service. +type ServiceInfo struct { + Methods []MethodInfo + // Metadata is the metadata specified in ServiceDesc when registering service. + Metadata interface{} +} + +// GetServiceInfo returns a map from service names to ServiceInfo. +// Service names include the package names, in the form of .. +func (s *Server) GetServiceInfo() map[string]ServiceInfo { + ret := make(map[string]ServiceInfo) + for n, srv := range s.m { + methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd)) + for m := range srv.md { + methods = append(methods, MethodInfo{ + Name: m, + IsClientStream: false, + IsServerStream: false, + }) + } + for m, d := range srv.sd { + methods = append(methods, MethodInfo{ + Name: m, + IsClientStream: d.ClientStreams, + IsServerStream: d.ServerStreams, + }) + } + + ret[n] = ServiceInfo{ + Methods: methods, + Metadata: srv.mdata, + } + } + return ret +} + var ( // ErrServerStopped indicates that the operation is now illegal because of // the server being stopped. @@ -247,30 +315,33 @@ var ( ) func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { - creds, ok := s.opts.creds.(credentials.TransportAuthenticator) - if !ok { + if s.opts.creds == nil { return rawConn, nil, nil } - return creds.ServerHandshake(rawConn) + return s.opts.creds.ServerHandshake(rawConn) } // Serve accepts incoming connections on the listener lis, creating a new // ServerTransport and service goroutine for each. The service goroutines // read gRPC requests and then call the registered handlers to reply to them. -// Service returns when lis.Accept fails. +// Service returns when lis.Accept fails. lis will be closed when +// this method returns. func (s *Server) Serve(lis net.Listener) error { s.mu.Lock() s.printf("serving") if s.lis == nil { s.mu.Unlock() + lis.Close() return ErrServerStopped } s.lis[lis] = true s.mu.Unlock() defer func() { - lis.Close() s.mu.Lock() - delete(s.lis, lis) + if s.lis != nil && s.lis[lis] { + lis.Close() + delete(s.lis, lis) + } s.mu.Unlock() }() for { @@ -414,7 +485,7 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea func (s *Server) addConn(c io.Closer) bool { s.mu.Lock() defer s.mu.Unlock() - if s.conns == nil { + if s.conns == nil || s.drain { return false } s.conns[c] = true @@ -426,6 +497,7 @@ func (s *Server) removeConn(c io.Closer) { defer s.mu.Unlock() if s.conns != nil { delete(s.conns, c) + s.cv.Signal() } } @@ -460,9 +532,13 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } }() } + if s.opts.cp != nil { + // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. + stream.SetSendCompress(s.opts.cp.Type()) + } p := &parser{r: stream} for { - pf, req, err := p.recvMsg() + pf, req, err := p.recvMsg(s.opts.maxMsgSize) if err == io.EOF { // The entire stream is done (for unary RPC only). return err @@ -472,6 +548,10 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } if err != nil { switch err := err.(type) { + case *rpcError: + if err := t.WriteStatus(stream, err.code, err.desc); err != nil { + grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) + } case transport.ConnectionError: // Nothing to do here. case transport.StreamError: @@ -511,6 +591,12 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. return err } } + if len(req) > s.opts.maxMsgSize { + // TODO: Revisit the error code. Currently keep it consistent with + // java implementation. + statusCode = codes.Internal + statusDesc = fmt.Sprintf("grpc: server received a message of %d bytes exceeding %d limit", len(req), s.opts.maxMsgSize) + } if err := s.opts.codec.Unmarshal(req, v); err != nil { return err } @@ -521,7 +607,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) if appErr != nil { - if err, ok := appErr.(rpcError); ok { + if err, ok := appErr.(*rpcError); ok { statusCode = err.code statusDesc = err.desc } else { @@ -545,9 +631,6 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. Last: true, Delay: false, } - if s.opts.cp != nil { - stream.SetSendCompress(s.opts.cp.Type()) - } if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: @@ -573,13 +656,14 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp stream.SetSendCompress(s.opts.cp.Type()) } ss := &serverStream{ - t: t, - s: stream, - p: &parser{r: stream}, - codec: s.opts.codec, - cp: s.opts.cp, - dc: s.opts.dc, - trInfo: trInfo, + t: t, + s: stream, + p: &parser{r: stream}, + codec: s.opts.codec, + cp: s.opts.cp, + dc: s.opts.dc, + maxMsgSize: s.opts.maxMsgSize, + trInfo: trInfo, } if ss.cp != nil { ss.cbuf = new(bytes.Buffer) @@ -609,7 +693,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler) } if appErr != nil { - if err, ok := appErr.(rpcError); ok { + if err, ok := appErr.(*rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else if err, ok := appErr.(transport.StreamError); ok { @@ -711,14 +795,16 @@ func (s *Server) Stop() { s.mu.Lock() listeners := s.lis s.lis = nil - cs := s.conns + st := s.conns s.conns = nil + // interrupt GracefulStop if Stop and GracefulStop are called concurrently. + s.cv.Signal() s.mu.Unlock() for lis := range listeners { lis.Close() } - for c := range cs { + for c := range st { c.Close() } @@ -730,6 +816,32 @@ func (s *Server) Stop() { s.mu.Unlock() } +// GracefulStop stops the gRPC server gracefully. It stops the server to accept new +// connections and RPCs and blocks until all the pending RPCs are finished. +func (s *Server) GracefulStop() { + s.mu.Lock() + defer s.mu.Unlock() + if s.drain == true || s.conns == nil { + return + } + s.drain = true + for lis := range s.lis { + lis.Close() + } + s.lis = nil + for c := range s.conns { + c.(transport.ServerTransport).Drain() + } + for len(s.conns) != 0 { + s.cv.Wait() + } + s.conns = nil + if s.events != nil { + s.events.Finish() + s.events = nil + } +} + func init() { internal.TestingCloseConns = func(arg interface{}) { arg.(*Server).testingCloseConns() diff --git a/components/engine/vendor/src/google.golang.org/grpc/stream.go b/components/engine/vendor/src/google.golang.org/grpc/stream.go index 565fc3cd0d..51df3f01da 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/stream.go +++ b/components/engine/vendor/src/google.golang.org/grpc/stream.go @@ -37,6 +37,7 @@ import ( "bytes" "errors" "io" + "math" "sync" "time" @@ -79,17 +80,14 @@ type Stream interface { RecvMsg(m interface{}) error } -// ClientStream defines the interface a client stream has to satify. +// ClientStream defines the interface a client stream has to satisfy. type ClientStream interface { // Header returns the header metadata received from the server if there // is any. It blocks if the metadata is not ready to read. Header() (metadata.MD, error) - // Trailer returns the trailer metadata from the server. It must be called - // after stream.Recv() returns non-nil error (including io.EOF) for - // bi-directional streaming and server streaming or stream.CloseAndRecv() - // returns for client streaming in order to receive trailer metadata if - // present. Otherwise, it could returns an empty MD even though trailer - // is present. + // Trailer returns the trailer metadata from the server, if there is any. + // It must only be called after stream.CloseAndRecv has returned, or + // stream.Recv has returned a non-nil error (including io.EOF). Trailer() metadata.MD // CloseSend closes the send direction of the stream. It closes the stream // when non-nil error is met. @@ -99,16 +97,18 @@ type ClientStream interface { // NewClientStream creates a new Stream for the client side. This is called // by generated code. -func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) { +func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { var ( t transport.ClientTransport - err error + s *transport.Stream + put func() ) - t, err = cc.dopts.picker.Pick(ctx) - if err != nil { - return nil, toRPCErr(err) + c := defaultCallInfo + for _, o := range opts { + if err := o.before(&c); err != nil { + return nil, toRPCErr(err) + } } - // TODO(zhaoq): CallOption is omitted. Add support when it is needed. callHdr := &transport.CallHdr{ Host: cc.authority, Method: method, @@ -117,40 +117,98 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth if cc.dopts.cp != nil { callHdr.SendCompress = cc.dopts.cp.Type() } + var trInfo traceInfo + if EnableTracing { + trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) + trInfo.firstLine.client = true + if deadline, ok := ctx.Deadline(); ok { + trInfo.firstLine.deadline = deadline.Sub(time.Now()) + } + trInfo.tr.LazyLog(&trInfo.firstLine, false) + ctx = trace.NewContext(ctx, trInfo.tr) + defer func() { + if err != nil { + // Need to call tr.finish() if error is returned. + // Because tr will not be returned to caller. + trInfo.tr.LazyPrintf("RPC: [%v]", err) + trInfo.tr.SetError() + trInfo.tr.Finish() + } + }() + } + gopts := BalancerGetOptions{ + BlockingWait: !c.failFast, + } + for { + t, put, err = cc.getTransport(ctx, gopts) + if err != nil { + // TODO(zhaoq): Probably revisit the error handling. + if _, ok := err.(*rpcError); ok { + return nil, err + } + if err == errConnClosing || err == errConnUnavailable { + if c.failFast { + return nil, Errorf(codes.Unavailable, "%v", err) + } + continue + } + // All the other errors are treated as Internal errors. + return nil, Errorf(codes.Internal, "%v", err) + } + + s, err = t.NewStream(ctx, callHdr) + if err != nil { + if put != nil { + put() + put = nil + } + if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { + if c.failFast { + return nil, toRPCErr(err) + } + continue + } + return nil, toRPCErr(err) + } + break + } cs := &clientStream{ - desc: desc, - codec: cc.dopts.codec, - cp: cc.dopts.cp, - dc: cc.dopts.dc, + opts: opts, + c: c, + desc: desc, + codec: cc.dopts.codec, + cp: cc.dopts.cp, + dc: cc.dopts.dc, + + put: put, + t: t, + s: s, + p: &parser{r: s}, + tracing: EnableTracing, + trInfo: trInfo, } if cc.dopts.cp != nil { - callHdr.SendCompress = cc.dopts.cp.Type() cs.cbuf = new(bytes.Buffer) } - if cs.tracing { - cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) - cs.trInfo.firstLine.client = true - if deadline, ok := ctx.Deadline(); ok { - cs.trInfo.firstLine.deadline = deadline.Sub(time.Now()) - } - cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false) - ctx = trace.NewContext(ctx, cs.trInfo.tr) - } - s, err := t.NewStream(ctx, callHdr) - if err != nil { - cs.finish(err) - return nil, toRPCErr(err) - } - cs.t = t - cs.s = s - cs.p = &parser{r: s} - // Listen on ctx.Done() to detect cancellation when there is no pending - // I/O operations on this stream. + // Listen on ctx.Done() to detect cancellation and s.Done() to detect normal termination + // when there is no pending I/O operations on this stream. go func() { select { case <-t.Error(): // Incur transport error, simply exit. + case <-s.Done(): + // TODO: The trace of the RPC is terminated here when there is no pending + // I/O, which is probably not the optimal solution. + if s.StatusCode() == codes.OK { + cs.finish(nil) + } else { + cs.finish(Errorf(s.StatusCode(), "%s", s.StatusDesc())) + } + cs.closeTransportStream(nil) + case <-s.GoAway(): + cs.finish(errConnDrain) + cs.closeTransportStream(errConnDrain) case <-s.Context().Done(): err := s.Context().Err() cs.finish(err) @@ -162,6 +220,8 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth // clientStream implements a client side Stream. type clientStream struct { + opts []CallOption + c callInfo t transport.ClientTransport s *transport.Stream p *parser @@ -174,6 +234,7 @@ type clientStream struct { tracing bool // set to EnableTracing when the clientStream is created. mu sync.Mutex + put func() closed bool // trInfo.tr is set when the clientStream is created (if EnableTracing is true), // and is set to nil when the clientStream's finish method is called. @@ -210,7 +271,17 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { if err != nil { cs.finish(err) } - if err == nil || err == io.EOF { + if err == nil { + return + } + if err == io.EOF { + // Specialize the process for server streaming. SendMesg is only called + // once when creating the stream object. io.EOF needs to be skipped when + // the rpc is early finished (before the stream object is created.). + // TODO: It is probably better to move this into the generated code. + if !cs.desc.ClientStreams && cs.desc.ServerStreams { + err = nil + } return } if _, ok := err.(transport.ConnectionError); !ok { @@ -231,7 +302,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { } func (cs *clientStream) RecvMsg(m interface{}) (err error) { - err = recv(cs.p, cs.codec, cs.s, cs.dc, m) + err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) defer func() { // err != nil indicates the termination of the stream. if err != nil { @@ -250,7 +321,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { return } // Special handling for client streaming rpc. - err = recv(cs.p, cs.codec, cs.s, cs.dc, m) + err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) cs.closeTransportStream(err) if err == nil { return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) @@ -285,7 +356,7 @@ func (cs *clientStream) CloseSend() (err error) { } }() if err == nil || err == io.EOF { - return + return nil } if _, ok := err.(transport.ConnectionError); !ok { cs.closeTransportStream(err) @@ -306,11 +377,18 @@ func (cs *clientStream) closeTransportStream(err error) { } func (cs *clientStream) finish(err error) { + cs.mu.Lock() + defer cs.mu.Unlock() + for _, o := range cs.opts { + o.after(&cs.c) + } + if cs.put != nil { + cs.put() + cs.put = nil + } if !cs.tracing { return } - cs.mu.Lock() - defer cs.mu.Unlock() if cs.trInfo.tr != nil { if err == nil || err == io.EOF { cs.trInfo.tr.LazyPrintf("RPC: [OK]") @@ -344,6 +422,7 @@ type serverStream struct { cp Compressor dc Decompressor cbuf *bytes.Buffer + maxMsgSize int statusCode codes.Code statusDesc string trInfo *traceInfo @@ -410,5 +489,5 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { ss.mu.Unlock() } }() - return recv(ss.p, ss.codec, ss.s, ss.dc, m) + return recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxMsgSize) } diff --git a/components/engine/vendor/src/google.golang.org/grpc/trace.go b/components/engine/vendor/src/google.golang.org/grpc/trace.go index cde04fbfc9..f6747e1dfa 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/trace.go +++ b/components/engine/vendor/src/google.golang.org/grpc/trace.go @@ -101,9 +101,8 @@ type payload struct { func (p payload) String() string { if p.sent { return fmt.Sprintf("sent: %v", p.msg) - } else { - return fmt.Sprintf("recv: %v", p.msg) } + return fmt.Sprintf("recv: %v", p.msg) } type fmtStringer struct { diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/control.go b/components/engine/vendor/src/google.golang.org/grpc/transport/control.go index 7e9bdf3350..4ef0830b56 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/control.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/control.go @@ -72,6 +72,11 @@ type resetStream struct { func (*resetStream) item() {} +type goAway struct { +} + +func (*goAway) item() {} + type flushIO struct { } diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/go16.go b/components/engine/vendor/src/google.golang.org/grpc/transport/go16.go new file mode 100644 index 0000000000..ee1c46bad5 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/go16.go @@ -0,0 +1,46 @@ +// +build go1.6,!go1.7 + +/* + * Copyright 2016, 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 transport + +import ( + "net" + + "golang.org/x/net/context" +) + +// dialContext connects to the address on the named network. +func dialContext(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address) +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/go17.go b/components/engine/vendor/src/google.golang.org/grpc/transport/go17.go new file mode 100644 index 0000000000..356f13ff19 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/go17.go @@ -0,0 +1,46 @@ +// +build go1.7 + +/* + * Copyright 2016, 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 transport + +import ( + "net" + + "golang.org/x/net/context" +) + +// dialContext connects to the address on the named network. +func dialContext(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, address) +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/handler_server.go b/components/engine/vendor/src/google.golang.org/grpc/transport/handler_server.go index fef541dba4..30e21ac0f4 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/handler_server.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/handler_server.go @@ -65,7 +65,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr if r.Method != "POST" { return nil, errors.New("invalid gRPC request method") } - if !strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { + if !validContentType(r.Header.Get("Content-Type")) { return nil, errors.New("invalid gRPC request content-type") } if _, ok := w.(http.Flusher); !ok { @@ -83,7 +83,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr } if v := r.Header.Get("grpc-timeout"); v != "" { - to, err := timeoutDecode(v) + to, err := decodeTimeout(v) if err != nil { return nil, StreamErrorf(codes.Internal, "malformed time-out: %v", err) } @@ -92,9 +92,12 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr } var metakv []string + if r.Host != "" { + metakv = append(metakv, ":authority", r.Host) + } for k, vv := range r.Header { k = strings.ToLower(k) - if isReservedHeader(k) { + if isReservedHeader(k) && !isWhitelistedPseudoHeader(k) { continue } for _, v := range vv { @@ -108,7 +111,6 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr } } metakv = append(metakv, k, v) - } } st.headerMD = metadata.Pairs(metakv...) @@ -192,10 +194,14 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, statusCode codes.Code, h := ht.rw.Header() h.Set("Grpc-Status", fmt.Sprintf("%d", statusCode)) if statusDesc != "" { - h.Set("Grpc-Message", statusDesc) + h.Set("Grpc-Message", encodeGrpcMessage(statusDesc)) } if md := s.Trailer(); len(md) > 0 { for k, vv := range md { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } for _, v := range vv { // http2 ResponseWriter mechanism to // send undeclared Trailers after the @@ -249,6 +255,10 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error { ht.writeCommonHeaders(s) h := ht.rw.Header() for k, vv := range md { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } for _, v := range vv { h.Add(k, v) } @@ -302,7 +312,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) { Addr: ht.RemoteAddr(), } if req.TLS != nil { - pr.AuthInfo = credentials.TLSInfo{*req.TLS} + pr.AuthInfo = credentials.TLSInfo{State: *req.TLS} } ctx = metadata.NewContext(ctx, ht.headerMD) ctx = peer.NewContext(ctx, pr) @@ -360,6 +370,10 @@ func (ht *serverHandlerTransport) runStream() { } } +func (ht *serverHandlerTransport) Drain() { + panic("Drain() is not implemented") +} + // mapRecvMsgError returns the non-nil err into the appropriate // error value as expected by callers of *grpc.parser.recvMsg. // In particular, in can only be: diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/http2_client.go b/components/engine/vendor/src/google.golang.org/grpc/transport/http2_client.go index 8082fdc8e7..5819cb8a43 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/http2_client.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/http2_client.go @@ -35,7 +35,7 @@ package transport import ( "bytes" - "errors" + "fmt" "io" "math" "net" @@ -72,6 +72,9 @@ type http2Client struct { shutdownChan chan struct{} // errorChan is closed to notify the I/O error to the caller. errorChan chan struct{} + // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor) + // that the server sent GoAway on this transport. + goAway chan struct{} framer *framer hBuf *bytes.Buffer // the buffer for HPACK encoding @@ -89,7 +92,7 @@ type http2Client struct { // The scheme used: https if TLS is on, http otherwise. scheme string - authCreds []credentials.Credentials + creds []credentials.PerRPCCredentials mu sync.Mutex // guard the following variables state transportState // the state of underlying connection @@ -98,48 +101,44 @@ type http2Client struct { maxStreams int // the per-stream outbound flow control window size set by the peer. streamSendQuota uint32 + // goAwayID records the Last-Stream-ID in the GoAway frame from the server. + goAwayID uint32 + // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame. + prevGoAwayID uint32 +} + +func dial(fn func(context.Context, string) (net.Conn, error), ctx context.Context, addr string) (net.Conn, error) { + if fn != nil { + return fn(ctx, addr) + } + return dialContext(ctx, "tcp", addr) } // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 // and starts to receive messages on it. Non-nil error returns if construction // fails. -func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err error) { - if opts.Dialer == nil { - // Set the default Dialer. - opts.Dialer = func(addr string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout("tcp", addr, timeout) - } - } +func newHTTP2Client(ctx context.Context, addr string, opts ConnectOptions) (_ ClientTransport, err error) { scheme := "http" - startT := time.Now() - timeout := opts.Timeout - conn, connErr := opts.Dialer(addr, timeout) + conn, connErr := dial(opts.Dialer, ctx, addr) if connErr != nil { - return nil, ConnectionErrorf("transport: %v", connErr) + return nil, ConnectionErrorf(true, connErr, "transport: %v", connErr) } - var authInfo credentials.AuthInfo - for _, c := range opts.AuthOptions { - if ccreds, ok := c.(credentials.TransportAuthenticator); ok { - scheme = "https" - // TODO(zhaoq): Now the first TransportAuthenticator is used if there are - // multiple ones provided. Revisit this if it is not appropriate. Probably - // place the ClientTransport construction into a separate function to make - // things clear. - if timeout > 0 { - timeout -= time.Since(startT) - } - conn, authInfo, connErr = ccreds.ClientHandshake(addr, conn, timeout) - break - } - } - if connErr != nil { - return nil, ConnectionErrorf("transport: %v", connErr) - } - defer func() { + // Any further errors will close the underlying connection + defer func(conn net.Conn) { if err != nil { conn.Close() } - }() + }(conn) + var authInfo credentials.AuthInfo + if creds := opts.TransportCredentials; creds != nil { + scheme = "https" + conn, authInfo, connErr = creds.ClientHandshake(ctx, addr, conn) + } + if connErr != nil { + // Credentials handshake error is not a temporary error (unless the error + // was the connection closing). + return nil, ConnectionErrorf(connErr == io.EOF, connErr, "transport: %v", connErr) + } ua := primaryUA if opts.UserAgent != "" { ua = opts.UserAgent + " " + ua @@ -155,6 +154,7 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e writableChan: make(chan int, 1), shutdownChan: make(chan struct{}), errorChan: make(chan struct{}), + goAway: make(chan struct{}), framer: newFramer(conn), hBuf: &buf, hEnc: hpack.NewEncoder(&buf), @@ -164,7 +164,7 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e scheme: scheme, state: reachable, activeStreams: make(map[uint32]*Stream), - authCreds: opts.AuthOptions, + creds: opts.PerRPCCredentials, maxStreams: math.MaxInt32, streamSendQuota: defaultWindowSize, } @@ -176,26 +176,29 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e n, err := t.conn.Write(clientPreface) if err != nil { t.Close() - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } if n != len(clientPreface) { t.Close() - return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) + return nil, ConnectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) } if initialWindowSize != defaultWindowSize { - err = t.framer.writeSettings(true, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)}) + err = t.framer.writeSettings(true, http2.Setting{ + ID: http2.SettingInitialWindowSize, + Val: uint32(initialWindowSize), + }) } else { err = t.framer.writeSettings(true) } if err != nil { t.Close() - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } // Adjust the connection flow control window if needed. if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil { t.Close() - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } } go t.controller() @@ -207,6 +210,8 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { // TODO(zhaoq): Handle uint32 overflow of Stream.id. s := &Stream{ id: t.nextID, + done: make(chan struct{}), + goAway: make(chan struct{}), method: callHdr.Method, sendCompress: callHdr.SendCompress, buf: newRecvBuffer(), @@ -221,8 +226,9 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { // Make a stream be able to cancel the pending operations by itself. s.ctx, s.cancel = context.WithCancel(ctx) s.dec = &recvBufferReader{ - ctx: s.ctx, - recv: s.buf, + ctx: s.ctx, + goAway: s.goAway, + recv: s.buf, } return s } @@ -249,7 +255,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea } ctx = peer.NewContext(ctx, pr) authData := make(map[string]string) - for _, c := range t.authCreds { + for _, c := range t.creds { // Construct URI required to get auth request metadata. var port string if pos := strings.LastIndex(t.target, ":"); pos != -1 { @@ -272,6 +278,14 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea } } t.mu.Lock() + if t.activeStreams == nil { + t.mu.Unlock() + return nil, ErrConnClosing + } + if t.state == draining { + t.mu.Unlock() + return nil, ErrStreamDrain + } if t.state != reachable { t.mu.Unlock() return nil, ErrConnClosing @@ -279,7 +293,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea checkStreamsQuota := t.streamsQuota != nil t.mu.Unlock() if checkStreamsQuota { - sq, err := wait(ctx, t.shutdownChan, t.streamsQuota.acquire()) + sq, err := wait(ctx, nil, nil, t.shutdownChan, t.streamsQuota.acquire()) if err != nil { return nil, err } @@ -288,11 +302,23 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea t.streamsQuota.add(sq - 1) } } - if _, err := wait(ctx, t.shutdownChan, t.writableChan); err != nil { - // t.streamsQuota will be updated when t.CloseStream is invoked. + if _, err := wait(ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { + // Return the quota back now because there is no stream returned to the caller. + if _, ok := err.(StreamError); ok && checkStreamsQuota { + t.streamsQuota.add(1) + } return nil, err } t.mu.Lock() + if t.state == draining { + t.mu.Unlock() + if checkStreamsQuota { + t.streamsQuota.add(1) + } + // Need to make t writable again so that the rpc in flight can still proceed. + t.writableChan <- 0 + return nil, ErrStreamDrain + } if t.state != reachable { t.mu.Unlock() return nil, ErrConnClosing @@ -327,7 +353,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) } if timeout > 0 { - t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: timeoutEncode(timeout)}) + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)}) } for k, v := range authData { // Capital header names are illegal in HTTP/2. @@ -341,6 +367,10 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea if md, ok := metadata.FromContext(ctx); ok { hasMD = true for k, v := range md { + // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set. + if isReservedHeader(k) { + continue + } for _, entry := range v { t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) } @@ -378,7 +408,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea } if err != nil { t.notifyError(err) - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } } t.writableChan <- 0 @@ -390,19 +420,24 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea func (t *http2Client) CloseStream(s *Stream, err error) { var updateStreams bool t.mu.Lock() + if t.activeStreams == nil { + t.mu.Unlock() + return + } if t.streamsQuota != nil { updateStreams = true } delete(t.activeStreams, s.id) + if t.state == draining && len(t.activeStreams) == 0 { + // The transport is draining and s is the last live stream on t. + t.mu.Unlock() + t.Close() + return + } t.mu.Unlock() if updateStreams { t.streamsQuota.add(1) } - // In case stream sending and receiving are invoked in separate - // goroutines (e.g., bi-directional streaming), the caller needs - // to call cancel on the stream to interrupt the blocking on - // other goroutines. - s.cancel() s.mu.Lock() if q := s.fc.resetPendingData(); q > 0 { if n := t.fc.onRead(q); n > 0 { @@ -429,12 +464,12 @@ func (t *http2Client) CloseStream(s *Stream, err error) { // accessed any more. func (t *http2Client) Close() (err error) { t.mu.Lock() - if t.state == reachable { - close(t.errorChan) - } if t.state == closing { t.mu.Unlock() - return errors.New("transport: Close() was already called") + return + } + if t.state == reachable || t.state == draining { + close(t.errorChan) } t.state = closing t.mu.Unlock() @@ -457,6 +492,50 @@ func (t *http2Client) Close() (err error) { return } +func (t *http2Client) GracefulClose() error { + t.mu.Lock() + switch t.state { + case unreachable: + // The server may close the connection concurrently. t is not available for + // any streams. Close it now. + t.mu.Unlock() + t.Close() + return nil + case closing: + t.mu.Unlock() + return nil + } + // Notify the streams which were initiated after the server sent GOAWAY. + select { + case <-t.goAway: + n := t.prevGoAwayID + if n == 0 && t.nextID > 1 { + n = t.nextID - 2 + } + m := t.goAwayID + 2 + if m == 2 { + m = 1 + } + for i := m; i <= n; i += 2 { + if s, ok := t.activeStreams[i]; ok { + close(s.goAway) + } + } + default: + } + if t.state == draining { + t.mu.Unlock() + return nil + } + t.state = draining + active := len(t.activeStreams) + t.mu.Unlock() + if active == 0 { + return t.Close() + } + return nil +} + // Write formats the data into HTTP2 data frame(s) and sends it out. The caller // should proceed only if Write returns nil. // TODO(zhaoq): opts.Delay is ignored in this implementation. Support it later @@ -469,15 +548,15 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { size := http2MaxFrameLen s.sendQuotaPool.add(0) // Wait until the stream has some quota to send the data. - sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) + sq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, s.sendQuotaPool.acquire()) if err != nil { return err } t.sendQuotaPool.add(0) // Wait until the transport has some quota to send the data. - tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) + tq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.sendQuotaPool.acquire()) if err != nil { - if _, ok := err.(StreamError); ok { + if _, ok := err.(StreamError); ok || err == io.EOF { t.sendQuotaPool.cancel() } return err @@ -509,8 +588,8 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { // Indicate there is a writer who is about to write a data frame. t.framer.adjustNumWriters(1) // Got some quota. Try to acquire writing privilege on the transport. - if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { - if _, ok := err.(StreamError); ok { + if _, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.writableChan); err != nil { + if _, ok := err.(StreamError); ok || err == io.EOF { // Return the connection quota back. t.sendQuotaPool.add(len(p)) } @@ -543,7 +622,7 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { // invoked. if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil { t.notifyError(err) - return ConnectionErrorf("transport: %v", err) + return ConnectionErrorf(true, err, "transport: %v", err) } if t.framer.adjustNumWriters(-1) == 0 { t.framer.flushWrite() @@ -558,11 +637,7 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { } s.mu.Lock() if s.state != streamDone { - if s.state == streamReadDone { - s.state = streamDone - } else { - s.state = streamWriteDone - } + s.state = streamWriteDone } s.mu.Unlock() return nil @@ -595,7 +670,7 @@ func (t *http2Client) updateWindow(s *Stream, n uint32) { func (t *http2Client) handleData(f *http2.DataFrame) { size := len(f.Data()) if err := t.fc.onData(uint32(size)); err != nil { - t.notifyError(ConnectionErrorf("%v", err)) + t.notifyError(ConnectionErrorf(true, err, "%v", err)) return } // Select the right stream to dispatch. @@ -620,6 +695,7 @@ func (t *http2Client) handleData(f *http2.DataFrame) { s.state = streamDone s.statusCode = codes.Internal s.statusDesc = err.Error() + close(s.done) s.mu.Unlock() s.write(recvMsg{err: io.EOF}) t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl}) @@ -637,13 +713,14 @@ func (t *http2Client) handleData(f *http2.DataFrame) { // the read direction is closed, and set the status appropriately. if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) { s.mu.Lock() - if s.state == streamWriteDone { - s.state = streamDone - } else { - s.state = streamReadDone + if s.state == streamDone { + s.mu.Unlock() + return } + s.state = streamDone s.statusCode = codes.Internal s.statusDesc = "server closed the stream without sending trailers" + close(s.done) s.mu.Unlock() s.write(recvMsg{err: io.EOF}) } @@ -669,6 +746,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { grpclog.Println("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error ", f.ErrCode) s.statusCode = codes.Unknown } + s.statusDesc = fmt.Sprintf("stream terminated by RST_STREAM with error code: %d", f.ErrCode) + close(s.done) s.mu.Unlock() s.write(recvMsg{err: io.EOF}) } @@ -693,7 +772,32 @@ func (t *http2Client) handlePing(f *http2.PingFrame) { } func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { - // TODO(zhaoq): GoAwayFrame handler to be implemented + t.mu.Lock() + if t.state == reachable || t.state == draining { + if f.LastStreamID > 0 && f.LastStreamID%2 != 1 { + t.mu.Unlock() + t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: stream ID %d is even", f.LastStreamID)) + return + } + select { + case <-t.goAway: + id := t.goAwayID + // t.goAway has been closed (i.e.,multiple GoAways). + if id < f.LastStreamID { + t.mu.Unlock() + t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: previously recv GOAWAY frame with LastStramID %d, currently recv %d", id, f.LastStreamID)) + return + } + t.prevGoAwayID = id + t.goAwayID = f.LastStreamID + t.mu.Unlock() + return + default: + } + t.goAwayID = f.LastStreamID + close(t.goAway) + } + t.mu.Unlock() } func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) { @@ -745,11 +849,11 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { if len(state.mdata) > 0 { s.trailer = state.mdata } - s.state = streamDone s.statusCode = state.statusCode s.statusDesc = state.statusDesc + close(s.done) + s.state = streamDone s.mu.Unlock() - s.write(recvMsg{err: io.EOF}) } @@ -902,13 +1006,22 @@ func (t *http2Client) Error() <-chan struct{} { return t.errorChan } +func (t *http2Client) GoAway() <-chan struct{} { + return t.goAway +} + func (t *http2Client) notifyError(err error) { t.mu.Lock() - defer t.mu.Unlock() // make sure t.errorChan is closed only once. + if t.state == draining { + t.mu.Unlock() + t.Close() + return + } if t.state == reachable { t.state = unreachable close(t.errorChan) grpclog.Printf("transport: http2Client.notifyError got notified that the client transport was broken %v.", err) } + t.mu.Unlock() } diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/http2_server.go b/components/engine/vendor/src/google.golang.org/grpc/transport/http2_server.go index 21b631168c..16010d55fb 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/http2_server.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/http2_server.go @@ -100,18 +100,23 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI if maxStreams == 0 { maxStreams = math.MaxUint32 } else { - settings = append(settings, http2.Setting{http2.SettingMaxConcurrentStreams, maxStreams}) + settings = append(settings, http2.Setting{ + ID: http2.SettingMaxConcurrentStreams, + Val: maxStreams, + }) } if initialWindowSize != defaultWindowSize { - settings = append(settings, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)}) + settings = append(settings, http2.Setting{ + ID: http2.SettingInitialWindowSize, + Val: uint32(initialWindowSize)}) } if err := framer.writeSettings(true, settings...); err != nil { - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } // Adjust the connection flow control window if needed. if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { if err := framer.writeWindowUpdate(true, 0, delta); err != nil { - return nil, ConnectionErrorf("transport: %v", err) + return nil, ConnectionErrorf(true, err, "transport: %v", err) } } var buf bytes.Buffer @@ -137,7 +142,7 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI } // operateHeader takes action on the decoded headers. -func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) { +func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) (close bool) { buf := newRecvBuffer() s := &Stream{ id: frame.Header().StreamID, @@ -200,6 +205,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) return } + if s.id%2 != 1 || s.id <= t.maxStreamID { + t.mu.Unlock() + // illegal gRPC stream id. + grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", s.id) + return true + } + t.maxStreamID = s.id s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) t.activeStreams[s.id] = s t.mu.Unlock() @@ -207,6 +219,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( t.updateWindow(s, uint32(n)) } handle(s) + return } // HandleStreams receives incoming streams using the given handler. This is @@ -226,6 +239,10 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { } frame, err := t.framer.readFrame() + if err == io.EOF || err == io.ErrUnexpectedEOF { + t.Close() + return + } if err != nil { grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) t.Close() @@ -252,20 +269,20 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { t.controlBuf.put(&resetStream{se.StreamID, se.Code}) continue } + if err == io.EOF || err == io.ErrUnexpectedEOF { + t.Close() + return + } + grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) t.Close() return } switch frame := frame.(type) { case *http2.MetaHeadersFrame: - id := frame.Header().StreamID - if id%2 != 1 || id <= t.maxStreamID { - // illegal gRPC stream id. - grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", id) + if t.operateHeaders(frame, handle) { t.Close() break } - t.maxStreamID = id - t.operateHeaders(frame, handle) case *http2.DataFrame: t.handleData(frame) case *http2.RSTStreamFrame: @@ -277,7 +294,7 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { case *http2.WindowUpdateFrame: t.handleWindowUpdate(frame) case *http2.GoAwayFrame: - break + // TODO: Handle GoAway from the client appropriately. default: grpclog.Printf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame) } @@ -359,11 +376,7 @@ func (t *http2Server) handleData(f *http2.DataFrame) { // Received the end of stream from the client. s.mu.Lock() if s.state != streamDone { - if s.state == streamWriteDone { - s.state = streamDone - } else { - s.state = streamReadDone - } + s.state = streamReadDone } s.mu.Unlock() s.write(recvMsg{err: io.EOF}) @@ -435,7 +448,7 @@ func (t *http2Server) writeHeaders(s *Stream, b *bytes.Buffer, endStream bool) e } if err != nil { t.Close() - return ConnectionErrorf("transport: %v", err) + return ConnectionErrorf(true, err, "transport: %v", err) } } return nil @@ -450,7 +463,7 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { } s.headerOk = true s.mu.Unlock() - if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { return err } t.hBuf.Reset() @@ -460,6 +473,10 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) } for k, v := range md { + if isReservedHeader(k) { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + continue + } for _, entry := range v { t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) } @@ -486,7 +503,7 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s headersSent = true } s.mu.Unlock() - if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { return err } t.hBuf.Reset() @@ -499,9 +516,13 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s Name: "grpc-status", Value: strconv.Itoa(int(statusCode)), }) - t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: statusDesc}) + t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(statusDesc)}) // Attach the trailer metadata. for k, v := range s.trailer { + // Clients don't tolerate reading restricted headers after some non restricted ones were sent. + if isReservedHeader(k) { + continue + } for _, entry := range v { t.hEnc.WriteField(hpack.HeaderField{Name: k, Value: entry}) } @@ -531,7 +552,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { } s.mu.Unlock() if writeHeaderFrame { - if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { return err } t.hBuf.Reset() @@ -547,7 +568,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { } if err := t.framer.writeHeaders(false, p); err != nil { t.Close() - return ConnectionErrorf("transport: %v", err) + return ConnectionErrorf(true, err, "transport: %v", err) } t.writableChan <- 0 } @@ -559,13 +580,13 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { size := http2MaxFrameLen s.sendQuotaPool.add(0) // Wait until the stream has some quota to send the data. - sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) + sq, err := wait(s.ctx, nil, nil, t.shutdownChan, s.sendQuotaPool.acquire()) if err != nil { return err } t.sendQuotaPool.add(0) // Wait until the transport has some quota to send the data. - tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) + tq, err := wait(s.ctx, nil, nil, t.shutdownChan, t.sendQuotaPool.acquire()) if err != nil { if _, ok := err.(StreamError); ok { t.sendQuotaPool.cancel() @@ -591,7 +612,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { t.framer.adjustNumWriters(1) // Got some quota. Try to acquire writing privilege on the // transport. - if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { + if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { if _, ok := err.(StreamError); ok { // Return the connection quota back. t.sendQuotaPool.add(ps) @@ -621,7 +642,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { } if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil { t.Close() - return ConnectionErrorf("transport: %v", err) + return ConnectionErrorf(true, err, "transport: %v", err) } if t.framer.adjustNumWriters(-1) == 0 { t.framer.flushWrite() @@ -666,6 +687,17 @@ func (t *http2Server) controller() { } case *resetStream: t.framer.writeRSTStream(true, i.streamID, i.code) + case *goAway: + t.mu.Lock() + if t.state == closing { + t.mu.Unlock() + // The transport is closing. + return + } + sid := t.maxStreamID + t.state = draining + t.mu.Unlock() + t.framer.writeGoAway(true, sid, http2.ErrCodeNo, nil) case *flushIO: t.framer.flushWrite() case *ping: @@ -711,6 +743,9 @@ func (t *http2Server) Close() (err error) { func (t *http2Server) closeStream(s *Stream) { t.mu.Lock() delete(t.activeStreams, s.id) + if t.state == draining && len(t.activeStreams) == 0 { + defer t.Close() + } t.mu.Unlock() // In case stream sending and receiving are invoked in separate // goroutines (e.g., bi-directional streaming), cancel needs to be @@ -733,3 +768,7 @@ func (t *http2Server) closeStream(s *Stream) { func (t *http2Server) RemoteAddr() net.Addr { return t.conn.RemoteAddr() } + +func (t *http2Server) Drain() { + t.controlBuf.put(&goAway{}) +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/http_util.go b/components/engine/vendor/src/google.golang.org/grpc/transport/http_util.go index 7a3594acea..79da512640 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/http_util.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/http_util.go @@ -35,6 +35,7 @@ package transport import ( "bufio" + "bytes" "fmt" "io" "net" @@ -52,7 +53,7 @@ import ( const ( // The primary user agent - primaryUA = "grpc-go/0.11" + primaryUA = "grpc-go/1.0" // http2MaxFrameLen specifies the max length of a HTTP2 frame. http2MaxFrameLen = 16384 // 16KB frame // http://http2.github.io/http2-spec/#SettingValues @@ -127,16 +128,40 @@ func isReservedHeader(hdr string) bool { } } +// isWhitelistedPseudoHeader checks whether hdr belongs to HTTP2 pseudoheaders +// that should be propagated into metadata visible to users. +func isWhitelistedPseudoHeader(hdr string) bool { + switch hdr { + case ":authority": + return true + default: + return false + } +} + func (d *decodeState) setErr(err error) { if d.err == nil { d.err = err } } +func validContentType(t string) bool { + e := "application/grpc" + if !strings.HasPrefix(t, e) { + return false + } + // Support variations on the content-type + // (e.g. "application/grpc+blah", "application/grpc;blah"). + if len(t) > len(e) && t[len(e)] != '+' && t[len(e)] != ';' { + return false + } + return true +} + func (d *decodeState) processHeaderField(f hpack.HeaderField) { switch f.Name { case "content-type": - if !strings.Contains(f.Value, "application/grpc") { + if !validContentType(f.Value) { d.setErr(StreamErrorf(codes.FailedPrecondition, "transport: received the unexpected content-type %q", f.Value)) return } @@ -150,11 +175,11 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) { } d.statusCode = codes.Code(code) case "grpc-message": - d.statusDesc = f.Value + d.statusDesc = decodeGrpcMessage(f.Value) case "grpc-timeout": d.timeoutSet = true var err error - d.timeout, err = timeoutDecode(f.Value) + d.timeout, err = decodeTimeout(f.Value) if err != nil { d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err)) return @@ -162,7 +187,7 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) { case ":path": d.method = f.Value default: - if !isReservedHeader(f.Name) { + if !isReservedHeader(f.Name) || isWhitelistedPseudoHeader(f.Name) { if f.Name == "user-agent" { i := strings.LastIndex(f.Value, " ") if i == -1 { @@ -227,7 +252,7 @@ func div(d, r time.Duration) int64 { } // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it. -func timeoutEncode(t time.Duration) string { +func encodeTimeout(t time.Duration) string { if d := div(t, time.Nanosecond); d <= maxTimeoutValue { return strconv.FormatInt(d, 10) + "n" } @@ -247,7 +272,7 @@ func timeoutEncode(t time.Duration) string { return strconv.FormatInt(div(t, time.Hour), 10) + "H" } -func timeoutDecode(s string) (time.Duration, error) { +func decodeTimeout(s string) (time.Duration, error) { size := len(s) if size < 2 { return 0, fmt.Errorf("transport: timeout string is too short: %q", s) @@ -264,6 +289,80 @@ func timeoutDecode(s string) (time.Duration, error) { return d * time.Duration(t), nil } +const ( + spaceByte = ' ' + tildaByte = '~' + percentByte = '%' +) + +// encodeGrpcMessage is used to encode status code in header field +// "grpc-message". +// It checks to see if each individual byte in msg is an +// allowable byte, and then either percent encoding or passing it through. +// When percent encoding, the byte is converted into hexadecimal notation +// with a '%' prepended. +func encodeGrpcMessage(msg string) string { + if msg == "" { + return "" + } + lenMsg := len(msg) + for i := 0; i < lenMsg; i++ { + c := msg[i] + if !(c >= spaceByte && c < tildaByte && c != percentByte) { + return encodeGrpcMessageUnchecked(msg) + } + } + return msg +} + +func encodeGrpcMessageUnchecked(msg string) string { + var buf bytes.Buffer + lenMsg := len(msg) + for i := 0; i < lenMsg; i++ { + c := msg[i] + if c >= spaceByte && c < tildaByte && c != percentByte { + buf.WriteByte(c) + } else { + buf.WriteString(fmt.Sprintf("%%%02X", c)) + } + } + return buf.String() +} + +// decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage. +func decodeGrpcMessage(msg string) string { + if msg == "" { + return "" + } + lenMsg := len(msg) + for i := 0; i < lenMsg; i++ { + if msg[i] == percentByte && i+2 < lenMsg { + return decodeGrpcMessageUnchecked(msg) + } + } + return msg +} + +func decodeGrpcMessageUnchecked(msg string) string { + var buf bytes.Buffer + lenMsg := len(msg) + for i := 0; i < lenMsg; i++ { + c := msg[i] + if c == percentByte && i+2 < lenMsg { + parsed, err := strconv.ParseInt(msg[i+1:i+3], 16, 8) + if err != nil { + buf.WriteByte(c) + } else { + buf.WriteByte(byte(parsed)) + i += 2 + } + } else { + buf.WriteByte(c) + } + } + return buf.String() +} + type framer struct { numWriters int32 reader io.Reader diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/pre_go16.go b/components/engine/vendor/src/google.golang.org/grpc/transport/pre_go16.go new file mode 100644 index 0000000000..33d91c17c4 --- /dev/null +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/pre_go16.go @@ -0,0 +1,51 @@ +// +build !go1.6 + +/* + * Copyright 2016, 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 transport + +import ( + "net" + "time" + + "golang.org/x/net/context" +) + +// dialContext connects to the address on the named network. +func dialContext(ctx context.Context, network, address string) (net.Conn, error) { + var dialer net.Dialer + if deadline, ok := ctx.Deadline(); ok { + dialer.Timeout = deadline.Sub(time.Now()) + } + return dialer.Dial(network, address) +} diff --git a/components/engine/vendor/src/google.golang.org/grpc/transport/transport.go b/components/engine/vendor/src/google.golang.org/grpc/transport/transport.go index 87fdf532ca..d59e511372 100644 --- a/components/engine/vendor/src/google.golang.org/grpc/transport/transport.go +++ b/components/engine/vendor/src/google.golang.org/grpc/transport/transport.go @@ -44,7 +44,6 @@ import ( "io" "net" "sync" - "time" "golang.org/x/net/context" "golang.org/x/net/trace" @@ -120,10 +119,11 @@ func (b *recvBuffer) get() <-chan item { // recvBufferReader implements io.Reader interface to read the data from // recvBuffer. type recvBufferReader struct { - ctx context.Context - recv *recvBuffer - last *bytes.Reader // Stores the remaining data in the previous calls. - err error + ctx context.Context + goAway chan struct{} + recv *recvBuffer + last *bytes.Reader // Stores the remaining data in the previous calls. + err error } // Read reads the next len(p) bytes from last. If last is drained, it tries to @@ -141,6 +141,8 @@ func (r *recvBufferReader) Read(p []byte) (n int, err error) { select { case <-r.ctx.Done(): return 0, ContextErr(r.ctx.Err()) + case <-r.goAway: + return 0, ErrStreamDrain case i := <-r.recv.get(): r.recv.load() m := i.(*recvMsg) @@ -158,7 +160,7 @@ const ( streamActive streamState = iota streamWriteDone // EndStream sent streamReadDone // EndStream received - streamDone // sendDone and recvDone or RSTStreamFrame is sent or received. + streamDone // the entire stream is finished. ) // Stream represents an RPC in the transport layer. @@ -169,6 +171,10 @@ type Stream struct { // ctx is the associated context of the stream. ctx context.Context cancel context.CancelFunc + // done is closed when the final status arrives. + done chan struct{} + // goAway is closed when the server sent GoAways signal before this stream was initiated. + goAway chan struct{} // method records the associated RPC method of the stream. method string recvCompress string @@ -214,6 +220,18 @@ func (s *Stream) SetSendCompress(str string) { s.sendCompress = str } +// Done returns a chanel which is closed when it receives the final status +// from the server. +func (s *Stream) Done() <-chan struct{} { + return s.done +} + +// GoAway returns a channel which is closed when the server sent GoAways signal +// before this stream was initiated. +func (s *Stream) GoAway() <-chan struct{} { + return s.goAway +} + // Header acquires the key-value pairs of header metadata once it // is available. It blocks until i) the metadata is ready or ii) there is no // header metadata or iii) the stream is cancelled/expired. @@ -221,6 +239,8 @@ func (s *Stream) Header() (metadata.MD, error) { select { case <-s.ctx.Done(): return nil, ContextErr(s.ctx.Err()) + case <-s.goAway: + return nil, ErrStreamDrain case <-s.headerChan: return s.header.Copy(), nil } @@ -321,6 +341,7 @@ const ( reachable transportState = iota unreachable closing + draining ) // NewServerTransport creates a ServerTransport with conn or non-nil error @@ -334,17 +355,17 @@ type ConnectOptions struct { // UserAgent is the application user agent. UserAgent string // Dialer specifies how to dial a network address. - Dialer func(string, time.Duration) (net.Conn, error) - // AuthOptions stores the credentials required to setup a client connection and/or issue RPCs. - AuthOptions []credentials.Credentials - // Timeout specifies the timeout for dialing a client connection. - Timeout time.Duration + Dialer func(context.Context, string) (net.Conn, error) + // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. + PerRPCCredentials []credentials.PerRPCCredentials + // TransportCredentials stores the Authenticator required to setup a client connection. + TransportCredentials credentials.TransportCredentials } // NewClientTransport establishes the transport with the required ConnectOptions // and returns it to the caller. -func NewClientTransport(target string, opts *ConnectOptions) (ClientTransport, error) { - return newHTTP2Client(target, opts) +func NewClientTransport(ctx context.Context, target string, opts ConnectOptions) (ClientTransport, error) { + return newHTTP2Client(ctx, target, opts) } // Options provides additional hints and information for message @@ -391,6 +412,10 @@ type ClientTransport interface { // is called only once. Close() error + // GracefulClose starts to tear down the transport. It stops accepting + // new RPCs and wait the completion of the pending RPCs. + GracefulClose() error + // Write sends the data for the given stream. A nil stream indicates // the write is to be performed on the transport as a whole. Write(s *Stream, data []byte, opts *Options) error @@ -410,6 +435,11 @@ type ClientTransport interface { // and create a new one) in error case. It should not return nil // once the transport is initiated. Error() <-chan struct{} + + // GoAway returns a channel that is closed when ClientTranspor + // receives the draining signal from the server (e.g., GOAWAY frame in + // HTTP/2). + GoAway() <-chan struct{} } // ServerTransport is the common interface for all gRPC server-side transport @@ -441,6 +471,9 @@ type ServerTransport interface { // RemoteAddr returns the remote network address. RemoteAddr() net.Addr + + // Drain notifies the client this ServerTransport stops accepting new RPCs. + Drain() } // StreamErrorf creates an StreamError with the specified error code and description. @@ -452,9 +485,11 @@ func StreamErrorf(c codes.Code, format string, a ...interface{}) StreamError { } // ConnectionErrorf creates an ConnectionError with the specified error description. -func ConnectionErrorf(format string, a ...interface{}) ConnectionError { +func ConnectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError { return ConnectionError{ Desc: fmt.Sprintf(format, a...), + temp: temp, + err: e, } } @@ -462,14 +497,36 @@ func ConnectionErrorf(format string, a ...interface{}) ConnectionError { // entire connection and the retry of all the active streams. type ConnectionError struct { Desc string + temp bool + err error } func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: desc = %q", e.Desc) } -// Define some common ConnectionErrors. -var ErrConnClosing = ConnectionError{Desc: "transport is closing"} +// Temporary indicates if this connection error is temporary or fatal. +func (e ConnectionError) Temporary() bool { + return e.temp +} + +// Origin returns the original error of this connection error. +func (e ConnectionError) Origin() error { + // Never return nil error here. + // If the original error is nil, return itself. + if e.err == nil { + return e + } + return e.err +} + +var ( + // ErrConnClosing indicates that the transport is closing. + ErrConnClosing = ConnectionError{Desc: "transport is closing", temp: true} + // ErrStreamDrain indicates that the stream is rejected by the server because + // the server stops accepting new RPCs. + ErrStreamDrain = StreamErrorf(codes.Unavailable, "the server stops accepting new RPCs") +) // StreamError is an error that only affects one stream within a connection. type StreamError struct { @@ -494,12 +551,25 @@ func ContextErr(err error) StreamError { // wait blocks until it can receive from ctx.Done, closing, or proceed. // If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. +// If it receives from done, it returns 0, io.EOF if ctx is not done; otherwise +// it return the StreamError for ctx.Err. +// If it receives from goAway, it returns 0, ErrStreamDrain. // If it receives from closing, it returns 0, ErrConnClosing. // If it receives from proceed, it returns the received integer, nil. -func wait(ctx context.Context, closing <-chan struct{}, proceed <-chan int) (int, error) { +func wait(ctx context.Context, done, goAway, closing <-chan struct{}, proceed <-chan int) (int, error) { select { case <-ctx.Done(): return 0, ContextErr(ctx.Err()) + case <-done: + // User cancellation has precedence. + select { + case <-ctx.Done(): + return 0, ContextErr(ctx.Err()) + default: + } + return 0, io.EOF + case <-goAway: + return 0, ErrStreamDrain case <-closing: return 0, ErrConnClosing case i := <-proceed: From 53ebd11affe79074848df47e47661033be85ea20 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 13 Sep 2016 09:28:01 -0700 Subject: [PATCH 2/3] vendor: update containerd and swarmkit Signed-off-by: Alexander Morozov Upstream-commit: eeceb0ccc8318ecbf577147363666b959959450e Component: engine --- components/engine/Dockerfile | 2 +- components/engine/Dockerfile.aarch64 | 2 +- components/engine/Dockerfile.armhf | 2 +- components/engine/Dockerfile.ppc64le | 2 +- components/engine/Dockerfile.s390x | 2 +- components/engine/Dockerfile.simple | 2 +- components/engine/hack/vendor.sh | 4 +- .../containerd/api/grpc/types/api.pb.go | 15 +- .../types/reference/image_reference.go | 34 - .../github.com/docker/swarmkit/agent/agent.go | 75 +- .../docker/swarmkit/agent/config.go | 2 +- .../docker/swarmkit/agent/exec/controller.go | 9 +- .../github.com/docker/swarmkit/agent/node.go | 44 +- .../docker/swarmkit/agent/session.go | 131 +- .../docker/swarmkit/agent/worker.go | 96 +- .../github.com/docker/swarmkit/api/ca.pb.go | 216 ++- .../docker/swarmkit/api/control.pb.go | 1355 +++++++++-------- .../docker/swarmkit/api/dispatcher.pb.go | 950 ++++++++++-- .../docker/swarmkit/api/dispatcher.proto | 50 +- .../swarmkit/api/duration/duration.pb.go | 13 +- .../docker/swarmkit/api/health.pb.go | 92 +- .../docker/swarmkit/api/objects.pb.go | 299 ++-- .../docker/swarmkit/api/objects.proto | 4 + .../github.com/docker/swarmkit/api/raft.pb.go | 264 ++-- .../github.com/docker/swarmkit/api/raft.proto | 2 +- .../docker/swarmkit/api/resource.pb.go | 138 +- .../docker/swarmkit/api/snapshot.pb.go | 9 +- .../docker/swarmkit/api/specs.pb.go | 96 +- .../swarmkit/api/timestamp/timestamp.pb.go | 13 +- .../docker/swarmkit/api/types.pb.go | 1182 +++++++------- .../docker/swarmkit/api/types.proto | 52 +- .../docker/swarmkit/ca/certificates.go | 39 +- .../github.com/docker/swarmkit/ca/config.go | 73 +- .../github.com/docker/swarmkit/ca/server.go | 8 +- .../docker/swarmkit/ca/transport.go | 46 +- .../swarmkit/manager/allocator/network.go | 8 + .../networkallocator/portallocator.go | 13 +- .../manager/controlapi/hackpicker/cluster.go | 12 - .../controlapi/hackpicker/raftpicker.go | 141 -- .../swarmkit/manager/controlapi/service.go | 13 +- .../swarmkit/manager/dispatcher/dispatcher.go | 282 +++- .../docker/swarmkit/manager/manager.go | 40 +- .../swarmkit/manager/orchestrator/restart.go | 7 +- .../swarmkit/manager/orchestrator/updater.go | 236 ++- .../swarmkit/manager/raftpicker/cluster.go | 12 - .../swarmkit/manager/raftpicker/raftpicker.go | 127 -- .../manager/raftselector/raftselector.go | 20 + .../manager/scheduler/indexed_node_heap.go | 153 -- .../swarmkit/manager/scheduler/nodeinfo.go | 61 +- .../swarmkit/manager/scheduler/nodeset.go | 115 ++ .../swarmkit/manager/scheduler/scheduler.go | 189 ++- .../manager/state/raft/membership/cluster.go | 3 + .../swarmkit/manager/state/raft/raft.go | 170 ++- .../swarmkit/manager/state/raft/util.go | 2 +- .../swarmkit/manager/state/raft/wait.go | 15 +- .../swarmkit/manager/state/watch/watch.go | 25 +- .../swarmkit/protobuf/plugin/plugin.pb.go | 13 +- 57 files changed, 4312 insertions(+), 2668 deletions(-) delete mode 100644 components/engine/vendor/src/github.com/docker/engine-api/types/reference/image_reference.go delete mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/cluster.go delete mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/raftpicker.go delete mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/cluster.go delete mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/raftpicker.go create mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/raftselector/raftselector.go delete mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go create mode 100644 components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go diff --git a/components/engine/Dockerfile b/components/engine/Dockerfile index 1a96e4dae8..21f59d341e 100644 --- a/components/engine/Dockerfile +++ b/components/engine/Dockerfile @@ -243,7 +243,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/Dockerfile.aarch64 b/components/engine/Dockerfile.aarch64 index 78b1bf08b8..deddb3abe9 100644 --- a/components/engine/Dockerfile.aarch64 +++ b/components/engine/Dockerfile.aarch64 @@ -186,7 +186,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/Dockerfile.armhf b/components/engine/Dockerfile.armhf index 2c11144c5b..4b58fedb7d 100644 --- a/components/engine/Dockerfile.armhf +++ b/components/engine/Dockerfile.armhf @@ -184,7 +184,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/Dockerfile.ppc64le b/components/engine/Dockerfile.ppc64le index 28ebb8a1ed..df6c6833ed 100644 --- a/components/engine/Dockerfile.ppc64le +++ b/components/engine/Dockerfile.ppc64le @@ -204,7 +204,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/Dockerfile.s390x b/components/engine/Dockerfile.s390x index cf024a69bc..9ca8569708 100644 --- a/components/engine/Dockerfile.s390x +++ b/components/engine/Dockerfile.s390x @@ -196,7 +196,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/Dockerfile.simple b/components/engine/Dockerfile.simple index 623bf43750..b2f182b423 100644 --- a/components/engine/Dockerfile.simple +++ b/components/engine/Dockerfile.simple @@ -68,7 +68,7 @@ RUN set -x \ && rm -rf "$GOPATH" # Install containerd -ENV CONTAINERD_COMMIT 4c21ad662f71af56c0e6b29c0afef72df441d1ff +ENV CONTAINERD_COMMIT 2545227b0357eb55e369fa0072baef9ad91cdb69 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone https://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \ diff --git a/components/engine/hack/vendor.sh b/components/engine/hack/vendor.sh index 6e6f3e00c8..bd770437b3 100755 --- a/components/engine/hack/vendor.sh +++ b/components/engine/hack/vendor.sh @@ -141,10 +141,10 @@ clone git google.golang.org/cloud dae7e3d993bc3812a2185af60552bb6b847e52a0 https clone git github.com/docker/docker-credential-helpers v0.3.0 # containerd -clone git github.com/docker/containerd 4c21ad662f71af56c0e6b29c0afef72df441d1ff +clone git github.com/docker/containerd 2545227b0357eb55e369fa0072baef9ad91cdb69 # cluster -clone git github.com/docker/swarmkit 27fbaef4ceed648bb575969ccc9083a6e104a719 +clone git github.com/docker/swarmkit 191acc1bbdb13d8ea3b8059dda14a12f8c3903f2 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 clone git github.com/gogo/protobuf v0.3 clone git github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a diff --git a/components/engine/vendor/src/github.com/docker/containerd/api/grpc/types/api.pb.go b/components/engine/vendor/src/github.com/docker/containerd/api/grpc/types/api.pb.go index 58dc3e8b83..2d09d51cd0 100644 --- a/components/engine/vendor/src/github.com/docker/containerd/api/grpc/types/api.pb.go +++ b/components/engine/vendor/src/github.com/docker/containerd/api/grpc/types/api.pb.go @@ -75,7 +75,9 @@ 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. -const _ = proto.ProtoPackageIsVersion1 +// 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 GetServerVersionRequest struct { } @@ -223,7 +225,7 @@ func (*Rlimit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } type User struct { Uid uint32 `protobuf:"varint,1,opt,name=uid" json:"uid,omitempty"` Gid uint32 `protobuf:"varint,2,opt,name=gid" json:"gid,omitempty"` - AdditionalGids []uint32 `protobuf:"varint,3,rep,name=additionalGids" json:"additionalGids,omitempty"` + AdditionalGids []uint32 `protobuf:"varint,3,rep,packed,name=additionalGids" json:"additionalGids,omitempty"` } func (m *User) Reset() { *m = User{} } @@ -385,7 +387,7 @@ type Container struct { Processes []*Process `protobuf:"bytes,3,rep,name=processes" json:"processes,omitempty"` Status string `protobuf:"bytes,4,opt,name=status" json:"status,omitempty"` Labels []string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty"` - Pids []uint32 `protobuf:"varint,6,rep,name=pids" json:"pids,omitempty"` + Pids []uint32 `protobuf:"varint,6,rep,packed,name=pids" json:"pids,omitempty"` Runtime string `protobuf:"bytes,7,opt,name=runtime" json:"runtime,omitempty"` } @@ -628,7 +630,7 @@ func (*NetworkStats) Descriptor() ([]byte, []int) { return fileDescriptor0, []in type CpuUsage struct { TotalUsage uint64 `protobuf:"varint,1,opt,name=total_usage,json=totalUsage" json:"total_usage,omitempty"` - PercpuUsage []uint64 `protobuf:"varint,2,rep,name=percpu_usage,json=percpuUsage" json:"percpu_usage,omitempty"` + PercpuUsage []uint64 `protobuf:"varint,2,rep,packed,name=percpu_usage,json=percpuUsage" json:"percpu_usage,omitempty"` UsageInKernelmode uint64 `protobuf:"varint,3,opt,name=usage_in_kernelmode,json=usageInKernelmode" json:"usage_in_kernelmode,omitempty"` UsageInUsermode uint64 `protobuf:"varint,4,opt,name=usage_in_usermode,json=usageInUsermode" json:"usage_in_usermode,omitempty"` } @@ -978,7 +980,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for API service @@ -1432,8 +1434,11 @@ var _API_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, + Metadata: fileDescriptor0, } +func init() { proto.RegisterFile("api.proto", fileDescriptor0) } + var fileDescriptor0 = []byte{ // 2604 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x59, 0x4b, 0x6f, 0x1c, 0x5b, diff --git a/components/engine/vendor/src/github.com/docker/engine-api/types/reference/image_reference.go b/components/engine/vendor/src/github.com/docker/engine-api/types/reference/image_reference.go deleted file mode 100644 index be9cf8ebed..0000000000 --- a/components/engine/vendor/src/github.com/docker/engine-api/types/reference/image_reference.go +++ /dev/null @@ -1,34 +0,0 @@ -package reference - -import ( - distreference "github.com/docker/distribution/reference" -) - -// Parse parses the given references and returns the repository and -// tag (if present) from it. If there is an error during parsing, it will -// return an error. -func Parse(ref string) (string, string, error) { - distributionRef, err := distreference.ParseNamed(ref) - if err != nil { - return "", "", err - } - - tag := GetTagFromNamedRef(distributionRef) - return distributionRef.Name(), tag, nil -} - -// GetTagFromNamedRef returns a tag from the specified reference. -// This function is necessary as long as the docker "server" api makes the distinction between repository -// and tags. -func GetTagFromNamedRef(ref distreference.Named) string { - var tag string - switch x := ref.(type) { - case distreference.Digested: - tag = x.Digest().String() - case distreference.NamedTagged: - tag = x.Tag() - default: - tag = "latest" - } - return tag -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/agent.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/agent.go index 284d078ebf..8f686a0a07 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/agent.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/agent.go @@ -15,6 +15,7 @@ import ( const ( initialSessionFailureBackoff = 100 * time.Millisecond maxSessionFailureBackoff = 8 * time.Second + nodeUpdatePeriod = 20 * time.Second ) // Agent implements the primary node functionality for a member of a swarm @@ -134,9 +135,18 @@ func (a *Agent) run(ctx context.Context) { log.G(ctx).Debugf("(*Agent).run") defer log.G(ctx).Debugf("(*Agent).run exited") + // get the node description + nodeDescription, err := a.nodeDescriptionWithHostname(ctx) + if err != nil { + log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Errorf("agent: node description unavailable") + } + // nodeUpdateTicker is used to periodically check for updates to node description + nodeUpdateTicker := time.NewTicker(nodeUpdatePeriod) + defer nodeUpdateTicker.Stop() + var ( backoff time.Duration - session = newSession(ctx, a, backoff, "") // start the initial session + session = newSession(ctx, a, backoff, "", nodeDescription) // start the initial session registered = session.registered ready = a.ready // first session ready sessionq chan sessionOperation @@ -158,9 +168,16 @@ func (a *Agent) run(ctx context.Context) { select { case operation := <-sessionq: operation.response <- operation.fn(session) - case msg := <-session.tasks: - if err := a.worker.Assign(ctx, msg.Tasks); err != nil { - log.G(ctx).WithError(err).Error("task assignment failed") + case msg := <-session.assignments: + switch msg.Type { + case api.AssignmentsMessage_COMPLETE: + if err := a.worker.AssignTasks(ctx, msg.UpdateTasks); err != nil { + log.G(ctx).WithError(err).Error("failed to synchronize worker assignments") + } + case api.AssignmentsMessage_INCREMENTAL: + if err := a.worker.UpdateTasks(ctx, msg.UpdateTasks, msg.RemoveTasks); err != nil { + log.G(ctx).WithError(err).Error("failed to update worker assignments") + } } case msg := <-session.messages: if err := a.handleSessionMessage(ctx, msg); err != nil { @@ -197,10 +214,42 @@ func (a *Agent) run(ctx context.Context) { log.G(ctx).Debugf("agent: rebuild session") // select a session registration delay from backoff range. - delay := time.Duration(rand.Int63n(int64(backoff))) - session = newSession(ctx, a, delay, session.sessionID) + delay := time.Duration(0) + if backoff > 0 { + delay = time.Duration(rand.Int63n(int64(backoff))) + } + session = newSession(ctx, a, delay, session.sessionID, nodeDescription) registered = session.registered sessionq = a.sessionq + case <-nodeUpdateTicker.C: + // skip this case if the registration isn't finished + if registered != nil { + continue + } + // get the current node description + newNodeDescription, err := a.nodeDescriptionWithHostname(ctx) + if err != nil { + log.G(ctx).WithError(err).WithField("agent", a.config.Executor).Errorf("agent: updated node description unavailable") + } + + // if newNodeDescription is nil, it will cause a panic when + // trying to create a session. Typically this can happen + // if the engine goes down + if newNodeDescription == nil { + continue + } + + // if the node description has changed, update it to the new one + // and close the session. The old session will be stopped and a + // new one will be created with the updated description + if !reflect.DeepEqual(nodeDescription, newNodeDescription) { + nodeDescription = newNodeDescription + // close the session + log.G(ctx).Info("agent: found node update") + if err := session.close(); err != nil { + log.G(ctx).WithError(err).Error("agent: closing session for node update failed") + } + } case <-a.stopped: // TODO(stevvooe): Wait on shutdown and cleanup. May need to pump // this loop a few times. @@ -315,7 +364,8 @@ func (a *Agent) UpdateTaskStatus(ctx context.Context, taskID string, status *api if err == errTaskUnknown { err = nil // dispatcher no longer cares about this task. } else { - log.G(ctx).WithError(err).Error("sending task status update failed") + log.G(ctx).WithError(err).Error("closing session after fatal error") + session.close() } } else { log.G(ctx).Debug("task status reported") @@ -337,6 +387,17 @@ func (a *Agent) UpdateTaskStatus(ctx context.Context, taskID string, status *api } } +// nodeDescriptionWithHostname retrieves node description, and overrides hostname if available +func (a *Agent) nodeDescriptionWithHostname(ctx context.Context) (*api.NodeDescription, error) { + desc, err := a.config.Executor.Describe(ctx) + + // Override hostname + if a.config.Hostname != "" && desc != nil { + desc.Hostname = a.config.Hostname + } + return desc, err +} + // nodesEqual returns true if the node states are functionaly equal, ignoring status, // version and other superfluous fields. // diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/config.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/config.go index aac6b2e0f9..a2f5deb99e 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/config.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/config.go @@ -29,7 +29,7 @@ type Config struct { NotifyRoleChange chan<- api.NodeRole // Credentials is credentials for grpc connection to manager. - Credentials credentials.TransportAuthenticator + Credentials credentials.TransportCredentials } func (c *Config) validate() error { diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/exec/controller.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/exec/controller.go index 021b01fe17..e1ad502de8 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/exec/controller.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/exec/controller.go @@ -147,7 +147,7 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus, if cs, ok := err.(ContainerStatuser); ok { var err error containerStatus, err = cs.ContainerStatus(ctx) - if err != nil { + if err != nil && !contextDoneError(err) { log.G(ctx).WithError(err).Error("error resolving container status on fatal") } } @@ -207,7 +207,7 @@ func Do(ctx context.Context, task *api.Task, ctlr Controller) (*api.TaskStatus, var err error containerStatus, err = cctlr.ContainerStatus(ctx) - if err != nil { + if err != nil && !contextDoneError(err) { log.G(ctx).WithError(err).Error("container status unavailable") } @@ -297,3 +297,8 @@ func logStateChange(ctx context.Context, desired, previous, next api.TaskState) log.G(ctx).WithFields(fields).Debug("state changed") } } + +func contextDoneError(err error) bool { + cause := errors.Cause(err) + return cause == context.Canceled || cause == context.DeadlineExceeded +} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/node.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/node.go index 2877149217..897656849b 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/node.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/node.go @@ -120,7 +120,7 @@ func NewNode(c *NodeConfig) (*Node, error) { n := &Node{ remotes: newPersistentRemotes(stateFile, p...), - role: ca.AgentRole, + role: ca.WorkerRole, config: c, started: make(chan struct{}), stopped: make(chan struct{}), @@ -194,7 +194,9 @@ func (n *Node) run(ctx context.Context) (err error) { select { case <-ctx.Done(): case resp := <-issueResponseChan: - logrus.Debugf("Requesting certificate for NodeID: %v", resp.NodeID) + log.G(log.WithModule(ctx, "tls")).WithFields(logrus.Fields{ + "node.id": resp.NodeID, + }).Debugf("requesting certificate") n.Lock() n.nodeID = resp.NodeID n.nodeMembership = resp.NodeMembership @@ -233,7 +235,7 @@ func (n *Node) run(ctx context.Context) (err error) { case apirole := <-n.roleChangeReq: n.Lock() lastRole := n.role - role := ca.AgentRole + role := ca.WorkerRole if apirole == api.NodeRoleManager { role = ca.ManagerRole } @@ -242,7 +244,7 @@ func (n *Node) run(ctx context.Context) (err error) { continue } // switch role to agent immediately to shutdown manager early - if role == ca.AgentRole { + if role == ca.WorkerRole { n.role = role n.roleCond.Broadcast() } @@ -343,7 +345,7 @@ func (n *Node) Err(ctx context.Context) error { } } -func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.TransportAuthenticator, ready chan<- struct{}) error { +func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.TransportCredentials, ready chan<- struct{}) error { select { case <-ctx.Done(): case <-n.remotes.WaitSelect(ctx): @@ -588,7 +590,7 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig return err } - remoteAddr, _ := n.remotes.Select(n.nodeID) + remoteAddr, _ := n.remotes.Select(n.NodeID()) m, err := manager.New(&manager.Config{ ForceNewCluster: n.config.ForceNewCluster, ProtoAddr: map[string]string{ @@ -607,8 +609,9 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig return err } done := make(chan struct{}) + var runErr error go func() { - m.Run(context.Background()) // todo: store error + runErr = m.Run(context.Background()) close(done) }() @@ -624,14 +627,31 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig go func(ready chan struct{}) { select { case <-ready: - n.remotes.Observe(api.Peer{NodeID: n.nodeID, Addr: n.config.ListenRemoteAPI}, remotes.DefaultObservationWeight) + n.remotes.Observe(api.Peer{NodeID: n.NodeID(), Addr: n.config.ListenRemoteAPI}, remotes.DefaultObservationWeight) case <-connCtx.Done(): } }(ready) ready = nil } - err = n.waitRole(ctx, ca.AgentRole) + roleChanged := make(chan error) + waitCtx, waitCancel := context.WithCancel(ctx) + go func() { + err := n.waitRole(waitCtx, ca.WorkerRole) + roleChanged <- err + }() + + select { + case <-done: + // Fail out if m.Run() returns error, otherwise wait for + // role change. + if runErr != nil { + err = runErr + } else { + err = <-roleChanged + } + case err = <-roleChanged: + } n.Lock() n.manager = nil @@ -646,6 +666,7 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig } connCancel() n.setControlSocket(nil) + waitCancel() if err != nil { return err @@ -672,17 +693,18 @@ func newPersistentRemotes(f string, peers ...api.Peer) *persistentRemotes { func (s *persistentRemotes) Observe(peer api.Peer, weight int) { s.Lock() + defer s.Unlock() s.Remotes.Observe(peer, weight) s.c.Broadcast() if err := s.save(); err != nil { logrus.Errorf("error writing cluster state file: %v", err) - s.Unlock() return } - s.Unlock() return } func (s *persistentRemotes) Remove(peers ...api.Peer) { + s.Lock() + defer s.Unlock() s.Remotes.Remove(peers...) if err := s.save(); err != nil { logrus.Errorf("error writing cluster state file: %v", err) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/session.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/session.go index 43c0dc881c..fc1a4582ce 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/session.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/session.go @@ -2,8 +2,10 @@ package agent import ( "errors" + "sync" "time" + "github.com/Sirupsen/logrus" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/protobuf/ptypes" @@ -31,26 +33,27 @@ type session struct { conn *grpc.ClientConn addr string - agent *Agent - sessionID string - session api.Dispatcher_SessionClient - errs chan error - messages chan *api.SessionMessage - tasks chan *api.TasksMessage + agent *Agent + sessionID string + session api.Dispatcher_SessionClient + errs chan error + messages chan *api.SessionMessage + assignments chan *api.AssignmentsMessage registered chan struct{} // closed registration closed chan struct{} + closeOnce sync.Once } -func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionID string) *session { +func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionID string, description *api.NodeDescription) *session { s := &session{ - agent: agent, - sessionID: sessionID, - errs: make(chan error, 1), - messages: make(chan *api.SessionMessage), - tasks: make(chan *api.TasksMessage), - registered: make(chan struct{}), - closed: make(chan struct{}), + agent: agent, + sessionID: sessionID, + errs: make(chan error, 1), + messages: make(chan *api.SessionMessage), + assignments: make(chan *api.AssignmentsMessage), + registered: make(chan struct{}), + closed: make(chan struct{}), } peer, err := agent.config.Managers.Select() if err != nil { @@ -68,14 +71,14 @@ func newSession(ctx context.Context, agent *Agent, delay time.Duration, sessionI s.addr = peer.Addr s.conn = cc - go s.run(ctx, delay) + go s.run(ctx, delay, description) return s } -func (s *session) run(ctx context.Context, delay time.Duration) { +func (s *session) run(ctx context.Context, delay time.Duration, description *api.NodeDescription) { time.Sleep(delay) // delay before registering. - if err := s.start(ctx); err != nil { + if err := s.start(ctx, description); err != nil { select { case s.errs <- err: case <-s.closed: @@ -94,24 +97,14 @@ func (s *session) run(ctx context.Context, delay time.Duration) { } // start begins the session and returns the first SessionMessage. -func (s *session) start(ctx context.Context) error { +func (s *session) start(ctx context.Context, description *api.NodeDescription) error { log.G(ctx).Debugf("(*session).start") - description, err := s.agent.config.Executor.Describe(ctx) - if err != nil { - log.G(ctx).WithError(err).WithField("executor", s.agent.config.Executor). - Errorf("node description unavailable") - return err - } - // Override hostname - if s.agent.config.Hostname != "" { - description.Hostname = s.agent.config.Hostname - } - errChan := make(chan error, 1) var ( msg *api.SessionMessage stream api.Dispatcher_SessionClient + err error ) // Note: we don't defer cancellation of this context, because the // streaming RPC is used after this function returned. We only cancel @@ -215,22 +208,68 @@ func (s *session) handleSessionMessage(ctx context.Context, msg *api.SessionMess } func (s *session) watch(ctx context.Context) error { - log.G(ctx).Debugf("(*session).watch") - client := api.NewDispatcherClient(s.conn) - watch, err := client.Tasks(ctx, &api.TasksRequest{ - SessionID: s.sessionID}) - if err != nil { - return err - } + log := log.G(ctx).WithFields(logrus.Fields{"method": "(*session).watch"}) + log.Debugf("") + var ( + resp *api.AssignmentsMessage + assignmentWatch api.Dispatcher_AssignmentsClient + tasksWatch api.Dispatcher_TasksClient + streamReference string + tasksFallback bool + err error + ) + client := api.NewDispatcherClient(s.conn) for { - resp, err := watch.Recv() - if err != nil { - return err + // If this is the first time we're running the loop, or there was a reference mismatch + // attempt to get the assignmentWatch + if assignmentWatch == nil && !tasksFallback { + assignmentWatch, err = client.Assignments(ctx, &api.AssignmentsRequest{SessionID: s.sessionID}) + if err != nil { + return err + } + } + // We have an assignmentWatch, let's try to receive an AssignmentMessage + if assignmentWatch != nil { + // If we get a code = 12 desc = unknown method Assignments, try to use tasks + resp, err = assignmentWatch.Recv() + if err != nil { + if grpc.Code(err) != codes.Unimplemented { + return err + } + tasksFallback = true + assignmentWatch = nil + log.WithError(err).Infof("falling back to Tasks") + } + } + + // This code is here for backwards compatibility (so that newer clients can use the + // older method Tasks) + if tasksWatch == nil && tasksFallback { + tasksWatch, err = client.Tasks(ctx, &api.TasksRequest{SessionID: s.sessionID}) + if err != nil { + return err + } + } + if tasksWatch != nil { + var taskResp *api.TasksMessage + taskResp, err = tasksWatch.Recv() + if err != nil { + return err + } + resp = &api.AssignmentsMessage{Type: api.AssignmentsMessage_COMPLETE, UpdateTasks: taskResp.Tasks} + } + + // If there seems to be a gap in the stream, let's break out of the inner for and + // re-sync (by calling Assignments again). + if streamReference != "" && streamReference != resp.AppliesTo { + assignmentWatch = nil + } else { + streamReference = resp.ResultsIn } select { - case s.tasks <- resp: + case s.assignments <- resp: case <-s.closed: return errSessionClosed case <-ctx.Done(): @@ -241,7 +280,6 @@ func (s *session) watch(ctx context.Context) error { // sendTaskStatus uses the current session to send the status of a single task. func (s *session) sendTaskStatus(ctx context.Context, taskID string, status *api.TaskStatus) error { - client := api.NewDispatcherClient(s.conn) if _, err := client.UpdateTaskStatus(ctx, &api.UpdateTaskStatusRequest{ SessionID: s.sessionID, @@ -302,15 +340,14 @@ func (s *session) sendTaskStatuses(ctx context.Context, updates ...*api.UpdateTa } func (s *session) close() error { - select { - case <-s.closed: - return errSessionClosed - default: + s.closeOnce.Do(func() { if s.conn != nil { s.agent.config.Managers.ObserveIfExists(api.Peer{Addr: s.addr}, -remotes.DefaultObservationWeight) s.conn.Close() } + close(s.closed) - return nil - } + }) + + return nil } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/agent/worker.go b/components/engine/vendor/src/github.com/docker/swarmkit/agent/worker.go index 80e9ab07ab..f19c9c957b 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/agent/worker.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/agent/worker.go @@ -17,9 +17,13 @@ type Worker interface { // Init prepares the worker for task assignment. Init(ctx context.Context) error - // Assign the set of tasks to the worker. Tasks outside of this set will be - // removed. - Assign(ctx context.Context, tasks []*api.Task) error + // AssignTasks assigns a complete set of tasks to a worker. Any task not included in + // this set will be removed. + AssignTasks(ctx context.Context, tasks []*api.Task) error + + // UpdateTasks updates an incremental set of tasks to the worker. Any task not included + // either in added or removed will remain untouched. + UpdateTasks(ctx context.Context, added []*api.Task, removed []string) error // Listen to updates about tasks controlled by the worker. When first // called, the reporter will receive all updates for all tasks controlled @@ -86,14 +90,37 @@ func (w *worker) Init(ctx context.Context) error { }) } -// Assign the set of tasks to the worker. Any tasks not previously known will +// AssignTasks assigns the set of tasks to the worker. Any tasks not previously known will // be started. Any tasks that are in the task set and already running will be // updated, if possible. Any tasks currently running on the // worker outside the task set will be terminated. -func (w *worker) Assign(ctx context.Context, tasks []*api.Task) error { +func (w *worker) AssignTasks(ctx context.Context, tasks []*api.Task) error { w.mu.Lock() defer w.mu.Unlock() + log.G(ctx).WithFields(logrus.Fields{ + "len(tasks)": len(tasks), + }).Debug("(*worker).AssignTasks") + + return reconcileTaskState(ctx, w, tasks, nil, true) +} + +// UpdateTasks the set of tasks to the worker. +// Tasks in the added set will be added to the worker, and tasks in the removed set +// will be removed from the worker +func (w *worker) UpdateTasks(ctx context.Context, added []*api.Task, removed []string) error { + w.mu.Lock() + defer w.mu.Unlock() + + log.G(ctx).WithFields(logrus.Fields{ + "len(added)": len(added), + "len(removed)": len(removed), + }).Debug("(*worker).UpdateTasks") + + return reconcileTaskState(ctx, w, added, removed, false) +} + +func reconcileTaskState(ctx context.Context, w *worker, added []*api.Task, removed []string, fullSnapshot bool) error { tx, err := w.db.Begin(true) if err != nil { log.G(ctx).WithError(err).Error("failed starting transaction against task database") @@ -101,10 +128,9 @@ func (w *worker) Assign(ctx context.Context, tasks []*api.Task) error { } defer tx.Rollback() - log.G(ctx).WithField("len(tasks)", len(tasks)).Debug("(*worker).Assign") assigned := map[string]struct{}{} - for _, task := range tasks { + for _, task := range added { log.G(ctx).WithFields( logrus.Fields{ "task.id": task.ID, @@ -135,35 +161,59 @@ func (w *worker) Assign(ctx context.Context, tasks []*api.Task) error { return err } } else { - task.Status = *status // overwrite the stale manager status with ours. + task.Status = *status } - w.startTask(ctx, tx, task) } assigned[task.ID] = struct{}{} } - for id, tm := range w.taskManagers { - if _, ok := assigned[id]; ok { - continue + closeManager := func(tm *taskManager) { + // when a task is no longer assigned, we shutdown the task manager for + // it and leave cleanup to the sweeper. + if err := tm.Close(); err != nil { + log.G(ctx).WithError(err).Error("error closing task manager") } + } - ctx := log.WithLogger(ctx, log.G(ctx).WithField("task.id", id)) - if err := SetTaskAssignment(tx, id, false); err != nil { + removeTaskAssignment := func(taskID string) error { + ctx := log.WithLogger(ctx, log.G(ctx).WithField("task.id", taskID)) + if err := SetTaskAssignment(tx, taskID, false); err != nil { log.G(ctx).WithError(err).Error("error setting task assignment in database") - continue } + return err + } - delete(w.taskManagers, id) - - go func(tm *taskManager) { - // when a task is no longer assigned, we shutdown the task manager for - // it and leave cleanup to the sweeper. - if err := tm.Close(); err != nil { - log.G(ctx).WithError(err).Error("error closing task manager") + // If this was a complete set of assignments, we're going to remove all the remaining + // tasks. + if fullSnapshot { + for id, tm := range w.taskManagers { + if _, ok := assigned[id]; ok { + continue } - }(tm) + + err := removeTaskAssignment(id) + if err == nil { + delete(w.taskManagers, id) + go closeManager(tm) + } + } + } else { + // If this was an incremental set of assignments, we're going to remove only the tasks + // in the removed set + for _, taskID := range removed { + err := removeTaskAssignment(taskID) + if err != nil { + continue + } + + tm, ok := w.taskManagers[taskID] + if ok { + delete(w.taskManagers, taskID) + go closeManager(tm) + } + } } return tx.Commit() diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/ca.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/ca.pb.go index faae786c4c..3262fe4f66 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/ca.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/ca.pb.go @@ -21,10 +21,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -285,11 +286,12 @@ func valueToGoStringCa(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringCa(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringCa(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -299,7 +301,7 @@ func extensionToGoStringCa(e map[int32]github_com_gogo_protobuf_proto.Extension) for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -309,7 +311,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for CA service @@ -371,7 +373,8 @@ var _CA_serviceDesc = grpc.ServiceDesc{ Handler: _CA_GetRootCACertificate_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorCa, } // Client API for NodeCA service @@ -467,7 +470,8 @@ var _NodeCA_serviceDesc = grpc.ServiceDesc{ Handler: _NodeCA_NodeCertificateStatus_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorCa, } func (m *NodeCertificateStatusRequest) Marshal() (data []byte, err error) { @@ -668,12 +672,11 @@ func encodeVarintCa(data []byte, offset int, v uint64) int { type raftProxyCAServer struct { local CAServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyCAServer(local CAServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) CAServer { +func NewRaftProxyCAServer(local CAServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) CAServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -695,7 +698,6 @@ func NewRaftProxyCAServer(local CAServer, connSelector raftpicker.Interface, clu return &raftProxyCAServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -710,44 +712,68 @@ func (p *raftProxyCAServer) runCtxMods(ctx context.Context) (context.Context, er } return ctx, nil } +func (p *raftProxyCAServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyCAServer) GetRootCACertificate(ctx context.Context, r *GetRootCACertificateRequest) (*GetRootCACertificateResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetRootCACertificate(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetRootCACertificate(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewCAClient(conn).GetRootCACertificate(ctx, r) + resp, err := NewCAClient(conn).GetRootCACertificate(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetRootCACertificate(ctx, r) + } + return nil, err + } + return NewCAClient(conn).GetRootCACertificate(modCtx, r) + } + return resp, err } type raftProxyNodeCAServer struct { local NodeCAServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyNodeCAServer(local NodeCAServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) NodeCAServer { +func NewRaftProxyNodeCAServer(local NodeCAServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) NodeCAServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -769,7 +795,6 @@ func NewRaftProxyNodeCAServer(local NodeCAServer, connSelector raftpicker.Interf return &raftProxyNodeCAServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -784,63 +809,90 @@ func (p *raftProxyNodeCAServer) runCtxMods(ctx context.Context) (context.Context } return ctx, nil } +func (p *raftProxyNodeCAServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyNodeCAServer) IssueNodeCertificate(ctx context.Context, r *IssueNodeCertificateRequest) (*IssueNodeCertificateResponse, error) { - if p.cluster.IsLeader() { - return p.local.IssueNodeCertificate(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.IssueNodeCertificate(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewNodeCAClient(conn).IssueNodeCertificate(ctx, r) + resp, err := NewNodeCAClient(conn).IssueNodeCertificate(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.IssueNodeCertificate(ctx, r) + } + return nil, err + } + return NewNodeCAClient(conn).IssueNodeCertificate(modCtx, r) + } + return resp, err } func (p *raftProxyNodeCAServer) NodeCertificateStatus(ctx context.Context, r *NodeCertificateStatusRequest) (*NodeCertificateStatusResponse, error) { - if p.cluster.IsLeader() { - return p.local.NodeCertificateStatus(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.NodeCertificateStatus(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewNodeCAClient(conn).NodeCertificateStatus(ctx, r) + resp, err := NewNodeCAClient(conn).NodeCertificateStatus(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.NodeCertificateStatus(ctx, r) + } + return nil, err + } + return NewNodeCAClient(conn).NodeCertificateStatus(modCtx, r) + } + return resp, err } func (m *NodeCertificateStatusRequest) Size() (n int) { @@ -1655,6 +1707,8 @@ var ( ErrIntOverflowCa = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("ca.proto", fileDescriptorCa) } + var fileDescriptorCa = []byte{ // 493 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x94, 0xcf, 0x6e, 0xd3, 0x40, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/control.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/control.pb.go index 4ab914a863..9994ff6e32 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/control.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/control.pb.go @@ -22,10 +22,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -1961,11 +1962,12 @@ func valueToGoStringControl(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringControl(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringControl(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -1975,7 +1977,7 @@ func extensionToGoStringControl(e map[int32]github_com_gogo_protobuf_proto.Exten for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -1985,7 +1987,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for Control service @@ -2641,7 +2643,8 @@ var _Control_serviceDesc = grpc.ServiceDesc{ Handler: _Control_UpdateCluster_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorControl, } func (m *GetNodeRequest) Marshal() (data []byte, err error) { @@ -4239,12 +4242,11 @@ func encodeVarintControl(data []byte, offset int, v uint64) int { type raftProxyControlServer struct { local ControlServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyControlServer(local ControlServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) ControlServer { +func NewRaftProxyControlServer(local ControlServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) ControlServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -4266,7 +4268,6 @@ func NewRaftProxyControlServer(local ControlServer, connSelector raftpicker.Inte return &raftProxyControlServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -4281,556 +4282,617 @@ func (p *raftProxyControlServer) runCtxMods(ctx context.Context) (context.Contex } return ctx, nil } +func (p *raftProxyControlServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyControlServer) GetNode(ctx context.Context, r *GetNodeRequest) (*GetNodeResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetNode(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetNode(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).GetNode(ctx, r) + resp, err := NewControlClient(conn).GetNode(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetNode(ctx, r) + } + return nil, err + } + return NewControlClient(conn).GetNode(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) ListNodes(ctx context.Context, r *ListNodesRequest) (*ListNodesResponse, error) { - if p.cluster.IsLeader() { - return p.local.ListNodes(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ListNodes(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).ListNodes(ctx, r) + resp, err := NewControlClient(conn).ListNodes(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ListNodes(ctx, r) + } + return nil, err + } + return NewControlClient(conn).ListNodes(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) UpdateNode(ctx context.Context, r *UpdateNodeRequest) (*UpdateNodeResponse, error) { - if p.cluster.IsLeader() { - return p.local.UpdateNode(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.UpdateNode(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).UpdateNode(ctx, r) + resp, err := NewControlClient(conn).UpdateNode(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.UpdateNode(ctx, r) + } + return nil, err + } + return NewControlClient(conn).UpdateNode(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) RemoveNode(ctx context.Context, r *RemoveNodeRequest) (*RemoveNodeResponse, error) { - if p.cluster.IsLeader() { - return p.local.RemoveNode(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.RemoveNode(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).RemoveNode(ctx, r) + resp, err := NewControlClient(conn).RemoveNode(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.RemoveNode(ctx, r) + } + return nil, err + } + return NewControlClient(conn).RemoveNode(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) GetTask(ctx context.Context, r *GetTaskRequest) (*GetTaskResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetTask(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetTask(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).GetTask(ctx, r) + resp, err := NewControlClient(conn).GetTask(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetTask(ctx, r) + } + return nil, err + } + return NewControlClient(conn).GetTask(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) ListTasks(ctx context.Context, r *ListTasksRequest) (*ListTasksResponse, error) { - if p.cluster.IsLeader() { - return p.local.ListTasks(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ListTasks(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).ListTasks(ctx, r) + resp, err := NewControlClient(conn).ListTasks(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ListTasks(ctx, r) + } + return nil, err + } + return NewControlClient(conn).ListTasks(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) RemoveTask(ctx context.Context, r *RemoveTaskRequest) (*RemoveTaskResponse, error) { - if p.cluster.IsLeader() { - return p.local.RemoveTask(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.RemoveTask(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).RemoveTask(ctx, r) + resp, err := NewControlClient(conn).RemoveTask(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.RemoveTask(ctx, r) + } + return nil, err + } + return NewControlClient(conn).RemoveTask(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) GetService(ctx context.Context, r *GetServiceRequest) (*GetServiceResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetService(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetService(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).GetService(ctx, r) + resp, err := NewControlClient(conn).GetService(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetService(ctx, r) + } + return nil, err + } + return NewControlClient(conn).GetService(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) ListServices(ctx context.Context, r *ListServicesRequest) (*ListServicesResponse, error) { - if p.cluster.IsLeader() { - return p.local.ListServices(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ListServices(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).ListServices(ctx, r) + resp, err := NewControlClient(conn).ListServices(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ListServices(ctx, r) + } + return nil, err + } + return NewControlClient(conn).ListServices(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) CreateService(ctx context.Context, r *CreateServiceRequest) (*CreateServiceResponse, error) { - if p.cluster.IsLeader() { - return p.local.CreateService(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.CreateService(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).CreateService(ctx, r) + resp, err := NewControlClient(conn).CreateService(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.CreateService(ctx, r) + } + return nil, err + } + return NewControlClient(conn).CreateService(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) UpdateService(ctx context.Context, r *UpdateServiceRequest) (*UpdateServiceResponse, error) { - if p.cluster.IsLeader() { - return p.local.UpdateService(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.UpdateService(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).UpdateService(ctx, r) + resp, err := NewControlClient(conn).UpdateService(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.UpdateService(ctx, r) + } + return nil, err + } + return NewControlClient(conn).UpdateService(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) RemoveService(ctx context.Context, r *RemoveServiceRequest) (*RemoveServiceResponse, error) { - if p.cluster.IsLeader() { - return p.local.RemoveService(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.RemoveService(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).RemoveService(ctx, r) + resp, err := NewControlClient(conn).RemoveService(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.RemoveService(ctx, r) + } + return nil, err + } + return NewControlClient(conn).RemoveService(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) GetNetwork(ctx context.Context, r *GetNetworkRequest) (*GetNetworkResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetNetwork(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetNetwork(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).GetNetwork(ctx, r) + resp, err := NewControlClient(conn).GetNetwork(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetNetwork(ctx, r) + } + return nil, err + } + return NewControlClient(conn).GetNetwork(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) ListNetworks(ctx context.Context, r *ListNetworksRequest) (*ListNetworksResponse, error) { - if p.cluster.IsLeader() { - return p.local.ListNetworks(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ListNetworks(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).ListNetworks(ctx, r) + resp, err := NewControlClient(conn).ListNetworks(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ListNetworks(ctx, r) + } + return nil, err + } + return NewControlClient(conn).ListNetworks(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) CreateNetwork(ctx context.Context, r *CreateNetworkRequest) (*CreateNetworkResponse, error) { - if p.cluster.IsLeader() { - return p.local.CreateNetwork(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.CreateNetwork(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).CreateNetwork(ctx, r) + resp, err := NewControlClient(conn).CreateNetwork(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.CreateNetwork(ctx, r) + } + return nil, err + } + return NewControlClient(conn).CreateNetwork(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) RemoveNetwork(ctx context.Context, r *RemoveNetworkRequest) (*RemoveNetworkResponse, error) { - if p.cluster.IsLeader() { - return p.local.RemoveNetwork(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.RemoveNetwork(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).RemoveNetwork(ctx, r) + resp, err := NewControlClient(conn).RemoveNetwork(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.RemoveNetwork(ctx, r) + } + return nil, err + } + return NewControlClient(conn).RemoveNetwork(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) GetCluster(ctx context.Context, r *GetClusterRequest) (*GetClusterResponse, error) { - if p.cluster.IsLeader() { - return p.local.GetCluster(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.GetCluster(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).GetCluster(ctx, r) + resp, err := NewControlClient(conn).GetCluster(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.GetCluster(ctx, r) + } + return nil, err + } + return NewControlClient(conn).GetCluster(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) ListClusters(ctx context.Context, r *ListClustersRequest) (*ListClustersResponse, error) { - if p.cluster.IsLeader() { - return p.local.ListClusters(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ListClusters(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).ListClusters(ctx, r) + resp, err := NewControlClient(conn).ListClusters(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ListClusters(ctx, r) + } + return nil, err + } + return NewControlClient(conn).ListClusters(modCtx, r) + } + return resp, err } func (p *raftProxyControlServer) UpdateCluster(ctx context.Context, r *UpdateClusterRequest) (*UpdateClusterResponse, error) { - if p.cluster.IsLeader() { - return p.local.UpdateCluster(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.UpdateCluster(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewControlClient(conn).UpdateCluster(ctx, r) + resp, err := NewControlClient(conn).UpdateCluster(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.UpdateCluster(ctx, r) + } + return nil, err + } + return NewControlClient(conn).UpdateCluster(modCtx, r) + } + return resp, err } func (m *GetNodeRequest) Size() (n int) { @@ -6379,50 +6441,55 @@ func (m *ListNodesRequest_Filters) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthControl - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthControl + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 4: if wireType != 0 { @@ -7499,50 +7566,55 @@ func (m *ListTasksRequest_Filters) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthControl - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthControl + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 4: if wireType != 2 { @@ -8674,50 +8746,55 @@ func (m *ListServicesRequest_Filters) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthControl - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthControl + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 4: if wireType != 2 { @@ -9601,50 +9678,55 @@ func (m *ListNetworksRequest_Filters) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthControl - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthControl + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 4: if wireType != 2 { @@ -10175,50 +10257,55 @@ func (m *ListClustersRequest_Filters) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowControl - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthControl - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowControl + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthControl + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 4: if wireType != 2 { @@ -10804,6 +10891,8 @@ var ( ErrIntOverflowControl = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("control.proto", fileDescriptorControl) } + var fileDescriptorControl = []byte{ // 1521 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x59, 0x4f, 0x6f, 0x1b, 0x45, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.pb.go index 818933dd31..d3b96b534b 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.pb.go @@ -22,10 +22,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -34,6 +35,31 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// AssignmentType specifies whether this assignment message carries +// the full state, or is an update to an existing state. +type AssignmentsMessage_Type int32 + +const ( + AssignmentsMessage_COMPLETE AssignmentsMessage_Type = 0 + AssignmentsMessage_INCREMENTAL AssignmentsMessage_Type = 1 +) + +var AssignmentsMessage_Type_name = map[int32]string{ + 0: "COMPLETE", + 1: "INCREMENTAL", +} +var AssignmentsMessage_Type_value = map[string]int32{ + "COMPLETE": 0, + "INCREMENTAL": 1, +} + +func (x AssignmentsMessage_Type) String() string { + return proto.EnumName(AssignmentsMessage_Type_name, int32(x)) +} +func (AssignmentsMessage_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptorDispatcher, []int{9, 0} +} + // SessionRequest starts a session. type SessionRequest struct { Description *NodeDescription `protobuf:"bytes,1,opt,name=description" json:"description,omitempty"` @@ -180,6 +206,41 @@ func (m *TasksMessage) Reset() { *m = TasksMessage{} } func (*TasksMessage) ProtoMessage() {} func (*TasksMessage) Descriptor() ([]byte, []int) { return fileDescriptorDispatcher, []int{7} } +type AssignmentsRequest struct { + SessionID string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (m *AssignmentsRequest) Reset() { *m = AssignmentsRequest{} } +func (*AssignmentsRequest) ProtoMessage() {} +func (*AssignmentsRequest) Descriptor() ([]byte, []int) { return fileDescriptorDispatcher, []int{8} } + +type AssignmentsMessage struct { + Type AssignmentsMessage_Type `protobuf:"varint,1,opt,name=type,proto3,enum=docker.swarmkit.v1.AssignmentsMessage_Type" json:"type,omitempty"` + // AppliesTo references the previous ResultsIn value, to chain + // incremental updates together. For the first update in a stream, + // AppliesTo is empty. If AppliesTo does not match the previously + // received ResultsIn, the consumer of the stream should start a new + // Assignments stream to re-sync. + AppliesTo string `protobuf:"bytes,2,opt,name=applies_to,json=appliesTo,proto3" json:"applies_to,omitempty"` + // ResultsIn identifies the result of this assignments message, to + // match against the next message's AppliesTo value and protect + // against missed messages. + ResultsIn string `protobuf:"bytes,3,opt,name=results_in,json=resultsIn,proto3" json:"results_in,omitempty"` + // UpdateTasks is a set of new or updated tasks to run on this node. + // In the first assignments message, it contains all of the tasks + // to run on this node. Tasks outside of this set running on the node + // should be terminated. + UpdateTasks []*Task `protobuf:"bytes,4,rep,name=update_tasks,json=updateTasks" json:"update_tasks,omitempty"` + // RemoveTasks is a set of previously-assigned task IDs to remove from the + // assignment set. It is not used in the first assignments message of + // a stream. + RemoveTasks []string `protobuf:"bytes,5,rep,name=remove_tasks,json=removeTasks" json:"remove_tasks,omitempty"` +} + +func (m *AssignmentsMessage) Reset() { *m = AssignmentsMessage{} } +func (*AssignmentsMessage) ProtoMessage() {} +func (*AssignmentsMessage) Descriptor() ([]byte, []int) { return fileDescriptorDispatcher, []int{9} } + func init() { proto.RegisterType((*SessionRequest)(nil), "docker.swarmkit.v1.SessionRequest") proto.RegisterType((*SessionMessage)(nil), "docker.swarmkit.v1.SessionMessage") @@ -190,6 +251,9 @@ func init() { proto.RegisterType((*UpdateTaskStatusResponse)(nil), "docker.swarmkit.v1.UpdateTaskStatusResponse") proto.RegisterType((*TasksRequest)(nil), "docker.swarmkit.v1.TasksRequest") proto.RegisterType((*TasksMessage)(nil), "docker.swarmkit.v1.TasksMessage") + proto.RegisterType((*AssignmentsRequest)(nil), "docker.swarmkit.v1.AssignmentsRequest") + proto.RegisterType((*AssignmentsMessage)(nil), "docker.swarmkit.v1.AssignmentsMessage") + proto.RegisterEnum("docker.swarmkit.v1.AssignmentsMessage_Type", AssignmentsMessage_Type_name, AssignmentsMessage_Type_value) } type authenticatedWrapperDispatcherServer struct { @@ -236,6 +300,14 @@ func (p *authenticatedWrapperDispatcherServer) Tasks(r *TasksRequest, stream Dis return p.local.Tasks(r, stream) } +func (p *authenticatedWrapperDispatcherServer) Assignments(r *AssignmentsRequest, stream Dispatcher_AssignmentsServer) error { + + if err := p.authorize(stream.Context(), []string{"swarm-worker", "swarm-manager"}); err != nil { + return err + } + return p.local.Assignments(r, stream) +} + func (m *SessionRequest) Copy() *SessionRequest { if m == nil { return nil @@ -371,6 +443,46 @@ func (m *TasksMessage) Copy() *TasksMessage { return o } +func (m *AssignmentsRequest) Copy() *AssignmentsRequest { + if m == nil { + return nil + } + + o := &AssignmentsRequest{ + SessionID: m.SessionID, + } + + return o +} + +func (m *AssignmentsMessage) Copy() *AssignmentsMessage { + if m == nil { + return nil + } + + o := &AssignmentsMessage{ + Type: m.Type, + AppliesTo: m.AppliesTo, + ResultsIn: m.ResultsIn, + } + + if m.UpdateTasks != nil { + o.UpdateTasks = make([]*Task, 0, len(m.UpdateTasks)) + for _, v := range m.UpdateTasks { + o.UpdateTasks = append(o.UpdateTasks, v.Copy()) + } + } + + if m.RemoveTasks != nil { + o.RemoveTasks = make([]string, 0, len(m.RemoveTasks)) + for _, v := range m.RemoveTasks { + o.RemoveTasks = append(o.RemoveTasks, v) + } + } + + return o +} + func (this *SessionRequest) GoString() string { if this == nil { return "nil" @@ -480,6 +592,32 @@ func (this *TasksMessage) GoString() string { s = append(s, "}") return strings.Join(s, "") } +func (this *AssignmentsRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&api.AssignmentsRequest{") + s = append(s, "SessionID: "+fmt.Sprintf("%#v", this.SessionID)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *AssignmentsMessage) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 9) + s = append(s, "&api.AssignmentsMessage{") + s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") + s = append(s, "AppliesTo: "+fmt.Sprintf("%#v", this.AppliesTo)+",\n") + s = append(s, "ResultsIn: "+fmt.Sprintf("%#v", this.ResultsIn)+",\n") + if this.UpdateTasks != nil { + s = append(s, "UpdateTasks: "+fmt.Sprintf("%#v", this.UpdateTasks)+",\n") + } + s = append(s, "RemoveTasks: "+fmt.Sprintf("%#v", this.RemoveTasks)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} func valueToGoStringDispatcher(v interface{}, typ string) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -488,11 +626,12 @@ func valueToGoStringDispatcher(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringDispatcher(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringDispatcher(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -502,7 +641,7 @@ func extensionToGoStringDispatcher(e map[int32]github_com_gogo_protobuf_proto.Ex for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -512,7 +651,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for Dispatcher service @@ -541,6 +680,11 @@ type DispatcherClient interface { // of tasks which should be run on node, if task is not present in that list, // it should be terminated. Tasks(ctx context.Context, in *TasksRequest, opts ...grpc.CallOption) (Dispatcher_TasksClient, error) + // Assignments is a stream of assignments such as tasks and secrets for node. + // The first message in the stream contains all of the tasks and secrets + // that are relevant to the node. Future messages in the stream are updates to + // the set of assignments. + Assignments(ctx context.Context, in *AssignmentsRequest, opts ...grpc.CallOption) (Dispatcher_AssignmentsClient, error) } type dispatcherClient struct { @@ -633,6 +777,38 @@ func (x *dispatcherTasksClient) Recv() (*TasksMessage, error) { return m, nil } +func (c *dispatcherClient) Assignments(ctx context.Context, in *AssignmentsRequest, opts ...grpc.CallOption) (Dispatcher_AssignmentsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Dispatcher_serviceDesc.Streams[2], c.cc, "/docker.swarmkit.v1.Dispatcher/Assignments", opts...) + if err != nil { + return nil, err + } + x := &dispatcherAssignmentsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Dispatcher_AssignmentsClient interface { + Recv() (*AssignmentsMessage, error) + grpc.ClientStream +} + +type dispatcherAssignmentsClient struct { + grpc.ClientStream +} + +func (x *dispatcherAssignmentsClient) Recv() (*AssignmentsMessage, error) { + m := new(AssignmentsMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // Server API for Dispatcher service type DispatcherServer interface { @@ -660,6 +836,11 @@ type DispatcherServer interface { // of tasks which should be run on node, if task is not present in that list, // it should be terminated. Tasks(*TasksRequest, Dispatcher_TasksServer) error + // Assignments is a stream of assignments such as tasks and secrets for node. + // The first message in the stream contains all of the tasks and secrets + // that are relevant to the node. Future messages in the stream are updates to + // the set of assignments. + Assignments(*AssignmentsRequest, Dispatcher_AssignmentsServer) error } func RegisterDispatcherServer(s *grpc.Server, srv DispatcherServer) { @@ -744,6 +925,27 @@ func (x *dispatcherTasksServer) Send(m *TasksMessage) error { return x.ServerStream.SendMsg(m) } +func _Dispatcher_Assignments_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(AssignmentsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(DispatcherServer).Assignments(m, &dispatcherAssignmentsServer{stream}) +} + +type Dispatcher_AssignmentsServer interface { + Send(*AssignmentsMessage) error + grpc.ServerStream +} + +type dispatcherAssignmentsServer struct { + grpc.ServerStream +} + +func (x *dispatcherAssignmentsServer) Send(m *AssignmentsMessage) error { + return x.ServerStream.SendMsg(m) +} + var _Dispatcher_serviceDesc = grpc.ServiceDesc{ ServiceName: "docker.swarmkit.v1.Dispatcher", HandlerType: (*DispatcherServer)(nil), @@ -768,7 +970,13 @@ var _Dispatcher_serviceDesc = grpc.ServiceDesc{ Handler: _Dispatcher_Tasks_Handler, ServerStreams: true, }, + { + StreamName: "Assignments", + Handler: _Dispatcher_Assignments_Handler, + ServerStreams: true, + }, }, + Metadata: fileDescriptorDispatcher, } func (m *SessionRequest) Marshal() (data []byte, err error) { @@ -1055,6 +1263,92 @@ func (m *TasksMessage) MarshalTo(data []byte) (int, error) { return i, nil } +func (m *AssignmentsRequest) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *AssignmentsRequest) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.SessionID) > 0 { + data[i] = 0xa + i++ + i = encodeVarintDispatcher(data, i, uint64(len(m.SessionID))) + i += copy(data[i:], m.SessionID) + } + return i, nil +} + +func (m *AssignmentsMessage) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *AssignmentsMessage) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Type != 0 { + data[i] = 0x8 + i++ + i = encodeVarintDispatcher(data, i, uint64(m.Type)) + } + if len(m.AppliesTo) > 0 { + data[i] = 0x12 + i++ + i = encodeVarintDispatcher(data, i, uint64(len(m.AppliesTo))) + i += copy(data[i:], m.AppliesTo) + } + if len(m.ResultsIn) > 0 { + data[i] = 0x1a + i++ + i = encodeVarintDispatcher(data, i, uint64(len(m.ResultsIn))) + i += copy(data[i:], m.ResultsIn) + } + if len(m.UpdateTasks) > 0 { + for _, msg := range m.UpdateTasks { + data[i] = 0x22 + i++ + i = encodeVarintDispatcher(data, i, uint64(msg.Size())) + n, err := msg.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.RemoveTasks) > 0 { + for _, s := range m.RemoveTasks { + data[i] = 0x2a + i++ + l = len(s) + for l >= 1<<7 { + data[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + data[i] = uint8(l) + i++ + i += copy(data[i:], s) + } + } + return i, nil +} + func encodeFixed64Dispatcher(data []byte, offset int, v uint64) int { data[offset] = uint8(v) data[offset+1] = uint8(v >> 8) @@ -1085,12 +1379,11 @@ func encodeVarintDispatcher(data []byte, offset int, v uint64) int { type raftProxyDispatcherServer struct { local DispatcherServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyDispatcherServer(local DispatcherServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) DispatcherServer { +func NewRaftProxyDispatcherServer(local DispatcherServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) DispatcherServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -1112,7 +1405,6 @@ func NewRaftProxyDispatcherServer(local DispatcherServer, connSelector raftpicke return &raftProxyDispatcherServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -1127,33 +1419,44 @@ func (p *raftProxyDispatcherServer) runCtxMods(ctx context.Context) (context.Con } return ctx, nil } +func (p *raftProxyDispatcherServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyDispatcherServer) Session(r *SessionRequest, stream Dispatcher_SessionServer) error { - if p.cluster.IsLeader() { - return p.local.Session(r, stream) - } - ctx, err := p.runCtxMods(stream.Context()) + ctx := stream.Context() + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return err - } - conn, err := p.connSelector.Conn() - if err != nil { - return err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Session(r, stream) } - }() - + return err + } + ctx, err = p.runCtxMods(ctx) + if err != nil { + return err + } clientStream, err := NewDispatcherClient(conn).Session(ctx, r) if err != nil { @@ -1177,88 +1480,80 @@ func (p *raftProxyDispatcherServer) Session(r *SessionRequest, stream Dispatcher func (p *raftProxyDispatcherServer) Heartbeat(ctx context.Context, r *HeartbeatRequest) (*HeartbeatResponse, error) { - if p.cluster.IsLeader() { - return p.local.Heartbeat(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Heartbeat(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewDispatcherClient(conn).Heartbeat(ctx, r) + resp, err := NewDispatcherClient(conn).Heartbeat(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.Heartbeat(ctx, r) + } + return nil, err + } + return NewDispatcherClient(conn).Heartbeat(modCtx, r) + } + return resp, err } func (p *raftProxyDispatcherServer) UpdateTaskStatus(ctx context.Context, r *UpdateTaskStatusRequest) (*UpdateTaskStatusResponse, error) { - if p.cluster.IsLeader() { - return p.local.UpdateTaskStatus(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.UpdateTaskStatus(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewDispatcherClient(conn).UpdateTaskStatus(ctx, r) + resp, err := NewDispatcherClient(conn).UpdateTaskStatus(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.UpdateTaskStatus(ctx, r) + } + return nil, err + } + return NewDispatcherClient(conn).UpdateTaskStatus(modCtx, r) + } + return resp, err } func (p *raftProxyDispatcherServer) Tasks(r *TasksRequest, stream Dispatcher_TasksServer) error { - if p.cluster.IsLeader() { - return p.local.Tasks(r, stream) - } - ctx, err := p.runCtxMods(stream.Context()) + ctx := stream.Context() + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return err - } - conn, err := p.connSelector.Conn() - if err != nil { - return err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Tasks(r, stream) } - }() - + return err + } + ctx, err = p.runCtxMods(ctx) + if err != nil { + return err + } clientStream, err := NewDispatcherClient(conn).Tasks(ctx, r) if err != nil { @@ -1280,6 +1575,41 @@ func (p *raftProxyDispatcherServer) Tasks(r *TasksRequest, stream Dispatcher_Tas return nil } +func (p *raftProxyDispatcherServer) Assignments(r *AssignmentsRequest, stream Dispatcher_AssignmentsServer) error { + + ctx := stream.Context() + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.Assignments(r, stream) + } + return err + } + ctx, err = p.runCtxMods(ctx) + if err != nil { + return err + } + clientStream, err := NewDispatcherClient(conn).Assignments(ctx, r) + + if err != nil { + return err + } + + for { + msg, err := clientStream.Recv() + if err == io.EOF { + break + } + if err != nil { + return err + } + if err := stream.Send(msg); err != nil { + return err + } + } + return nil +} + func (m *SessionRequest) Size() (n int) { var l int _ = l @@ -1396,6 +1726,45 @@ func (m *TasksMessage) Size() (n int) { return n } +func (m *AssignmentsRequest) Size() (n int) { + var l int + _ = l + l = len(m.SessionID) + if l > 0 { + n += 1 + l + sovDispatcher(uint64(l)) + } + return n +} + +func (m *AssignmentsMessage) Size() (n int) { + var l int + _ = l + if m.Type != 0 { + n += 1 + sovDispatcher(uint64(m.Type)) + } + l = len(m.AppliesTo) + if l > 0 { + n += 1 + l + sovDispatcher(uint64(l)) + } + l = len(m.ResultsIn) + if l > 0 { + n += 1 + l + sovDispatcher(uint64(l)) + } + if len(m.UpdateTasks) > 0 { + for _, e := range m.UpdateTasks { + l = e.Size() + n += 1 + l + sovDispatcher(uint64(l)) + } + } + if len(m.RemoveTasks) > 0 { + for _, s := range m.RemoveTasks { + l = len(s) + n += 1 + l + sovDispatcher(uint64(l)) + } + } + return n +} + func sovDispatcher(x uint64) (n int) { for { n++ @@ -1504,6 +1873,30 @@ func (this *TasksMessage) String() string { }, "") return s } +func (this *AssignmentsRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&AssignmentsRequest{`, + `SessionID:` + fmt.Sprintf("%v", this.SessionID) + `,`, + `}`, + }, "") + return s +} +func (this *AssignmentsMessage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&AssignmentsMessage{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `AppliesTo:` + fmt.Sprintf("%v", this.AppliesTo) + `,`, + `ResultsIn:` + fmt.Sprintf("%v", this.ResultsIn) + `,`, + `UpdateTasks:` + strings.Replace(fmt.Sprintf("%v", this.UpdateTasks), "Task", "Task", 1) + `,`, + `RemoveTasks:` + fmt.Sprintf("%v", this.RemoveTasks) + `,`, + `}`, + }, "") + return s +} func valueToStringDispatcher(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -2389,6 +2782,272 @@ func (m *TasksMessage) Unmarshal(data []byte) error { } return nil } +func (m *AssignmentsRequest) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AssignmentsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssignmentsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDispatcher + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SessionID = string(data[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipDispatcher(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthDispatcher + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AssignmentsMessage) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AssignmentsMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssignmentsMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Type |= (AssignmentsMessage_Type(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppliesTo", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDispatcher + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppliesTo = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResultsIn", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDispatcher + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResultsIn = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdateTasks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthDispatcher + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UpdateTasks = append(m.UpdateTasks, &Task{}) + if err := m.UpdateTasks[len(m.UpdateTasks)-1].Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RemoveTasks", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDispatcher + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthDispatcher + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RemoveTasks = append(m.RemoveTasks, string(data[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipDispatcher(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthDispatcher + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipDispatcher(data []byte) (n int, err error) { l := len(data) iNdEx := 0 @@ -2494,47 +3153,60 @@ var ( ErrIntOverflowDispatcher = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("dispatcher.proto", fileDescriptorDispatcher) } + var fileDescriptorDispatcher = []byte{ - // 645 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x95, 0xdf, 0x6a, 0x13, 0x4f, - 0x14, 0xc7, 0x3b, 0x69, 0x9a, 0xfe, 0x72, 0xd2, 0xfe, 0x88, 0x63, 0xb1, 0xcb, 0x52, 0xb7, 0x71, - 0xab, 0x50, 0xb0, 0x6e, 0x35, 0x82, 0x17, 0x52, 0x44, 0x42, 0x0a, 0x86, 0xe2, 0x1f, 0xb6, 0x6a, - 0x2f, 0xcb, 0x24, 0x7b, 0x48, 0xd7, 0xd8, 0x9d, 0x75, 0x66, 0x62, 0xcd, 0x85, 0x20, 0x88, 0xb7, - 0x22, 0x5e, 0xf9, 0x14, 0x3e, 0x47, 0xf1, 0xca, 0x4b, 0xaf, 0x8a, 0xcd, 0x03, 0x88, 0x8f, 0x20, - 0xbb, 0x3b, 0x9b, 0xd6, 0x74, 0x53, 0x9b, 0x5e, 0x65, 0xfe, 0x7c, 0xcf, 0xf7, 0x7c, 0x38, 0xe7, - 0x4c, 0x16, 0xca, 0x9e, 0x2f, 0x43, 0xa6, 0x5a, 0x3b, 0x28, 0x9c, 0x50, 0x70, 0xc5, 0x29, 0xf5, - 0x78, 0xab, 0x83, 0xc2, 0x91, 0x7b, 0x4c, 0xec, 0x76, 0x7c, 0xe5, 0xbc, 0xbe, 0x65, 0x96, 0x54, - 0x2f, 0x44, 0x99, 0x08, 0xcc, 0x59, 0xde, 0x7c, 0x81, 0x2d, 0x95, 0x6e, 0xe7, 0xda, 0xbc, 0xcd, - 0xe3, 0xe5, 0x6a, 0xb4, 0xd2, 0xa7, 0x17, 0xc3, 0x97, 0xdd, 0xb6, 0x1f, 0xac, 0x26, 0x3f, 0xfa, - 0x70, 0xde, 0xeb, 0x0a, 0xa6, 0x7c, 0x1e, 0xac, 0xa6, 0x8b, 0xe4, 0xc2, 0xfe, 0x40, 0xe0, 0xff, - 0x4d, 0x94, 0xd2, 0xe7, 0x81, 0x8b, 0xaf, 0xba, 0x28, 0x15, 0x5d, 0x87, 0x92, 0x87, 0xb2, 0x25, - 0xfc, 0x30, 0xd2, 0x19, 0xa4, 0x42, 0x96, 0x4b, 0xd5, 0x25, 0xe7, 0x24, 0x9c, 0xf3, 0x88, 0x7b, - 0x58, 0x3f, 0x92, 0xba, 0xc7, 0xe3, 0xe8, 0x0a, 0x80, 0x4c, 0x8c, 0xb7, 0x7d, 0xcf, 0xc8, 0x55, - 0xc8, 0x72, 0xb1, 0x36, 0xdb, 0x3f, 0x58, 0x2c, 0xea, 0x74, 0x8d, 0xba, 0x5b, 0xd4, 0x82, 0x86, - 0x67, 0xbf, 0xcf, 0x0d, 0x38, 0x1e, 0xa2, 0x94, 0xac, 0x8d, 0x43, 0x06, 0xe4, 0x74, 0x03, 0xba, - 0x02, 0xf9, 0x80, 0x7b, 0x18, 0x27, 0x2a, 0x55, 0x8d, 0x51, 0xb8, 0x6e, 0xac, 0xa2, 0x6b, 0xf0, - 0xdf, 0x2e, 0x0b, 0x58, 0x1b, 0x85, 0x34, 0x26, 0x2b, 0x93, 0xcb, 0xa5, 0x6a, 0x25, 0x2b, 0x62, - 0x0b, 0xfd, 0xf6, 0x8e, 0x42, 0xef, 0x09, 0xa2, 0x70, 0x07, 0x11, 0x74, 0x0b, 0x2e, 0x05, 0xa8, - 0xf6, 0xb8, 0xe8, 0x6c, 0x37, 0x39, 0x57, 0x52, 0x09, 0x16, 0x6e, 0x77, 0xb0, 0x27, 0x8d, 0x7c, - 0xec, 0x75, 0x25, 0xcb, 0x6b, 0x3d, 0x68, 0x89, 0x5e, 0x5c, 0x9a, 0x0d, 0xec, 0xb9, 0x73, 0xda, - 0xa0, 0x96, 0xc6, 0x6f, 0x60, 0x4f, 0xda, 0xf7, 0xa1, 0xfc, 0x00, 0x99, 0x50, 0x4d, 0x64, 0x2a, - 0x6d, 0xc7, 0x58, 0x65, 0xb0, 0x1f, 0xc3, 0x85, 0x63, 0x0e, 0x32, 0xe4, 0x81, 0x44, 0x7a, 0x17, - 0x0a, 0x21, 0x0a, 0x9f, 0x7b, 0xba, 0x99, 0x0b, 0x59, 0x7c, 0x75, 0x3d, 0x18, 0xb5, 0xfc, 0xfe, - 0xc1, 0xe2, 0x84, 0xab, 0x23, 0xec, 0x4f, 0x39, 0x98, 0x7f, 0x16, 0x7a, 0x4c, 0xe1, 0x53, 0x26, - 0x3b, 0x9b, 0x8a, 0xa9, 0xae, 0x3c, 0x17, 0x1a, 0x7d, 0x0e, 0xd3, 0xdd, 0xd8, 0x28, 0x2d, 0xf9, - 0x5a, 0x16, 0xc6, 0x88, 0x5c, 0xce, 0xd1, 0x49, 0xa2, 0x70, 0x53, 0x33, 0x93, 0x43, 0x79, 0xf8, - 0x92, 0x2e, 0xc1, 0xb4, 0x62, 0xb2, 0x73, 0x84, 0x05, 0xfd, 0x83, 0xc5, 0x42, 0x24, 0x6b, 0xd4, - 0xdd, 0x42, 0x74, 0xd5, 0xf0, 0xe8, 0x1d, 0x28, 0xc8, 0x38, 0x48, 0x0f, 0x8d, 0x95, 0xc5, 0x73, - 0x8c, 0x44, 0xab, 0x6d, 0x13, 0x8c, 0x93, 0x94, 0x49, 0xa9, 0xed, 0x35, 0x98, 0x89, 0x4e, 0xcf, - 0x57, 0x22, 0xfb, 0x9e, 0x8e, 0x4e, 0x9f, 0x80, 0x03, 0x53, 0x11, 0xab, 0x34, 0x48, 0x5c, 0x30, - 0x63, 0x14, 0xa0, 0x9b, 0xc8, 0xaa, 0x1f, 0xf3, 0x00, 0xf5, 0xc1, 0xdf, 0x0a, 0x7d, 0x03, 0xd3, - 0x3a, 0x0d, 0xb5, 0xb3, 0x42, 0xff, 0x7e, 0xf8, 0xe6, 0x69, 0x1a, 0x4d, 0x64, 0x2f, 0x7d, 0xfb, - 0xfa, 0xeb, 0x4b, 0xee, 0x32, 0xcc, 0xc4, 0x9a, 0x1b, 0xd1, 0x08, 0xa3, 0x80, 0xd9, 0x64, 0xa7, - 0x1f, 0xc8, 0x4d, 0x42, 0xdf, 0x42, 0x71, 0x30, 0x86, 0xf4, 0x6a, 0x96, 0xef, 0xf0, 0x9c, 0x9b, - 0xd7, 0xfe, 0xa1, 0xd2, 0x05, 0x3e, 0x0b, 0x00, 0xfd, 0x4c, 0xa0, 0x3c, 0xdc, 0x22, 0x7a, 0x7d, - 0x8c, 0x71, 0x33, 0x57, 0xce, 0x26, 0x1e, 0x07, 0x4a, 0xc0, 0x54, 0xdc, 0x5c, 0x5a, 0x19, 0xd5, - 0xc6, 0x41, 0xf6, 0xd1, 0x8a, 0xf1, 0xfa, 0x50, 0x5b, 0xd8, 0x3f, 0xb4, 0x26, 0x7e, 0x1c, 0x5a, - 0x13, 0xbf, 0x0f, 0x2d, 0xf2, 0xae, 0x6f, 0x91, 0xfd, 0xbe, 0x45, 0xbe, 0xf7, 0x2d, 0xf2, 0xb3, - 0x6f, 0x91, 0x66, 0x21, 0xfe, 0x06, 0xdc, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0xa3, 0xfc, 0x50, - 0xc8, 0x8b, 0x06, 0x00, 0x00, + // 820 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xce, 0x38, 0x8e, 0x53, 0xbf, 0xeb, 0x14, 0x33, 0x54, 0x74, 0x65, 0xb5, 0x1b, 0x77, 0x43, + 0x23, 0x4b, 0x0d, 0x9b, 0x62, 0x24, 0x0e, 0x10, 0x01, 0x75, 0x6d, 0x09, 0xab, 0x4d, 0x5a, 0x6d, + 0x0d, 0x3d, 0x5a, 0x6b, 0xef, 0x2b, 0x77, 0x71, 0xbc, 0xb3, 0xcc, 0xcc, 0xb6, 0xf8, 0x80, 0x84, + 0x04, 0x48, 0x1c, 0x11, 0xa7, 0x8a, 0x1f, 0xc1, 0xef, 0x88, 0x38, 0x71, 0xe4, 0x14, 0x11, 0xff, + 0x00, 0xc4, 0x4f, 0xa8, 0x76, 0x77, 0xd6, 0x71, 0x9d, 0x75, 0xe2, 0xe4, 0xe4, 0xd9, 0x77, 0x9e, + 0xe7, 0x99, 0x47, 0xef, 0x97, 0xa1, 0xec, 0x7a, 0x22, 0x70, 0x64, 0xff, 0x05, 0x72, 0x2b, 0xe0, + 0x4c, 0x32, 0x4a, 0x5d, 0xd6, 0x1f, 0x22, 0xb7, 0xc4, 0x2b, 0x87, 0x8f, 0x86, 0x9e, 0xb4, 0x5e, + 0x7e, 0x54, 0xd1, 0xe4, 0x38, 0x40, 0x91, 0x00, 0x2a, 0x1b, 0xac, 0xf7, 0x2d, 0xf6, 0x65, 0xfa, + 0x79, 0x63, 0xc0, 0x06, 0x2c, 0x3e, 0xee, 0x46, 0x27, 0x15, 0x7d, 0x2f, 0x38, 0x0c, 0x07, 0x9e, + 0xbf, 0x9b, 0xfc, 0xa8, 0xe0, 0x4d, 0x37, 0xe4, 0x8e, 0xf4, 0x98, 0xbf, 0x9b, 0x1e, 0x92, 0x0b, + 0xf3, 0x17, 0x02, 0xd7, 0x9f, 0xa1, 0x10, 0x1e, 0xf3, 0x6d, 0xfc, 0x2e, 0x44, 0x21, 0x69, 0x0b, + 0x34, 0x17, 0x45, 0x9f, 0x7b, 0x41, 0x84, 0xd3, 0x49, 0x95, 0xd4, 0xb4, 0xfa, 0x96, 0x75, 0xd6, + 0x9c, 0x75, 0xc0, 0x5c, 0x6c, 0x9e, 0x42, 0xed, 0x59, 0x1e, 0xdd, 0x01, 0x10, 0x89, 0x70, 0xd7, + 0x73, 0xf5, 0x5c, 0x95, 0xd4, 0x8a, 0x8d, 0x8d, 0xc9, 0xf1, 0x66, 0x51, 0x3d, 0xd7, 0x6e, 0xda, + 0x45, 0x05, 0x68, 0xbb, 0xe6, 0x4f, 0xb9, 0xa9, 0x8f, 0x7d, 0x14, 0xc2, 0x19, 0xe0, 0x9c, 0x00, + 0x39, 0x5f, 0x80, 0xee, 0x40, 0xde, 0x67, 0x2e, 0xc6, 0x0f, 0x69, 0x75, 0x7d, 0x91, 0x5d, 0x3b, + 0x46, 0xd1, 0x3d, 0xb8, 0x36, 0x72, 0x7c, 0x67, 0x80, 0x5c, 0xe8, 0xab, 0xd5, 0xd5, 0x9a, 0x56, + 0xaf, 0x66, 0x31, 0x9e, 0xa3, 0x37, 0x78, 0x21, 0xd1, 0x7d, 0x8a, 0xc8, 0xed, 0x29, 0x83, 0x3e, + 0x87, 0xf7, 0x7d, 0x94, 0xaf, 0x18, 0x1f, 0x76, 0x7b, 0x8c, 0x49, 0x21, 0xb9, 0x13, 0x74, 0x87, + 0x38, 0x16, 0x7a, 0x3e, 0xd6, 0xba, 0x93, 0xa5, 0xd5, 0xf2, 0xfb, 0x7c, 0x1c, 0xa7, 0xe6, 0x11, + 0x8e, 0xed, 0x1b, 0x4a, 0xa0, 0x91, 0xf2, 0x1f, 0xe1, 0x58, 0x98, 0x5f, 0x42, 0xf9, 0x2b, 0x74, + 0xb8, 0xec, 0xa1, 0x23, 0xd3, 0x72, 0x5c, 0x2a, 0x0d, 0xe6, 0x13, 0x78, 0x77, 0x46, 0x41, 0x04, + 0xcc, 0x17, 0x48, 0x3f, 0x85, 0x42, 0x80, 0xdc, 0x63, 0xae, 0x2a, 0xe6, 0xad, 0x2c, 0x7f, 0x4d, + 0xd5, 0x18, 0x8d, 0xfc, 0xd1, 0xf1, 0xe6, 0x8a, 0xad, 0x18, 0xe6, 0x6f, 0x39, 0xb8, 0xf9, 0x75, + 0xe0, 0x3a, 0x12, 0x3b, 0x8e, 0x18, 0x3e, 0x93, 0x8e, 0x0c, 0xc5, 0x95, 0xac, 0xd1, 0x6f, 0x60, + 0x3d, 0x8c, 0x85, 0xd2, 0x94, 0xef, 0x65, 0xd9, 0x58, 0xf0, 0x96, 0x75, 0x1a, 0x49, 0x10, 0x76, + 0x2a, 0x56, 0x61, 0x50, 0x9e, 0xbf, 0xa4, 0x5b, 0xb0, 0x2e, 0x1d, 0x31, 0x3c, 0xb5, 0x05, 0x93, + 0xe3, 0xcd, 0x42, 0x04, 0x6b, 0x37, 0xed, 0x42, 0x74, 0xd5, 0x76, 0xe9, 0x27, 0x50, 0x10, 0x31, + 0x49, 0x35, 0x8d, 0x91, 0xe5, 0x67, 0xc6, 0x89, 0x42, 0x9b, 0x15, 0xd0, 0xcf, 0xba, 0x4c, 0x52, + 0x6d, 0xee, 0x41, 0x29, 0x8a, 0x5e, 0x2d, 0x45, 0xe6, 0xe7, 0x8a, 0x9d, 0x8e, 0x80, 0x05, 0x6b, + 0x91, 0x57, 0xa1, 0x93, 0x38, 0x61, 0xfa, 0x22, 0x83, 0x76, 0x02, 0x33, 0x1b, 0x40, 0x1f, 0x08, + 0xe1, 0x0d, 0xfc, 0x11, 0xfa, 0xf2, 0x8a, 0x1e, 0xfe, 0xc8, 0xbd, 0x25, 0x92, 0x5a, 0xf9, 0x02, + 0xf2, 0xd1, 0x2a, 0x8a, 0xe9, 0xd7, 0xeb, 0xf7, 0xb2, 0x9c, 0x9c, 0x65, 0x59, 0x9d, 0x71, 0x80, + 0x76, 0x4c, 0xa4, 0xb7, 0x01, 0x9c, 0x20, 0x38, 0xf4, 0x50, 0x74, 0x25, 0x4b, 0xf6, 0x81, 0x5d, + 0x54, 0x91, 0x0e, 0x8b, 0xae, 0x39, 0x8a, 0xf0, 0x50, 0x8a, 0xae, 0xe7, 0xeb, 0xab, 0xc9, 0xb5, + 0x8a, 0xb4, 0x7d, 0xfa, 0x19, 0x94, 0x92, 0x7a, 0x77, 0x93, 0x84, 0xe4, 0x2f, 0x48, 0x88, 0x16, + 0x4e, 0x2b, 0x24, 0xe8, 0x1d, 0x28, 0x71, 0x1c, 0xb1, 0x97, 0x29, 0x79, 0xad, 0xba, 0x5a, 0x2b, + 0xda, 0x5a, 0x12, 0x8b, 0x21, 0xe6, 0x5d, 0xc8, 0x47, 0x5e, 0x69, 0x09, 0xae, 0x3d, 0x7c, 0xb2, + 0xff, 0xf4, 0x71, 0xab, 0xd3, 0x2a, 0xaf, 0xd0, 0x77, 0x40, 0x6b, 0x1f, 0x3c, 0xb4, 0x5b, 0xfb, + 0xad, 0x83, 0xce, 0x83, 0xc7, 0x65, 0x52, 0x7f, 0xbd, 0x06, 0xd0, 0x9c, 0xee, 0x6d, 0xfa, 0x3d, + 0xac, 0xab, 0x1c, 0x52, 0x33, 0xcb, 0xca, 0xdb, 0x9b, 0xb5, 0x72, 0x1e, 0x46, 0x65, 0xcc, 0xdc, + 0xfa, 0xeb, 0xcf, 0xff, 0x5e, 0xe7, 0x6e, 0x43, 0x29, 0xc6, 0x7c, 0x18, 0xed, 0x08, 0xe4, 0xb0, + 0x91, 0x7c, 0xa9, 0x0d, 0x74, 0x9f, 0xd0, 0x1f, 0xa0, 0x38, 0x9d, 0x73, 0xfa, 0x41, 0x96, 0xee, + 0xfc, 0x22, 0xa9, 0xdc, 0xbd, 0x00, 0xa5, 0x3a, 0x78, 0x19, 0x03, 0xf4, 0x77, 0x02, 0xe5, 0xf9, + 0x19, 0xa0, 0xf7, 0x2e, 0x31, 0xcf, 0x95, 0x9d, 0xe5, 0xc0, 0x97, 0x31, 0x15, 0xc2, 0x5a, 0x52, + 0xef, 0xea, 0xa2, 0xb6, 0x98, 0xbe, 0xbe, 0x18, 0x91, 0xd6, 0x61, 0x7b, 0x89, 0x17, 0x7f, 0xcd, + 0x91, 0xfb, 0x84, 0xfe, 0x4c, 0x40, 0x9b, 0x69, 0x7d, 0xba, 0x7d, 0xc1, 0x6c, 0xa4, 0x1e, 0xb6, + 0x97, 0x9b, 0xa1, 0x25, 0x3b, 0xa2, 0x71, 0xeb, 0xe8, 0xc4, 0x58, 0xf9, 0xe7, 0xc4, 0x58, 0xf9, + 0xff, 0xc4, 0x20, 0x3f, 0x4e, 0x0c, 0x72, 0x34, 0x31, 0xc8, 0xdf, 0x13, 0x83, 0xfc, 0x3b, 0x31, + 0x48, 0xaf, 0x10, 0xff, 0xdd, 0x7f, 0xfc, 0x26, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xb7, 0x47, 0x6b, + 0x76, 0x08, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.proto b/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.proto index acb8c72c33..40c1e33804 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.proto +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/dispatcher.proto @@ -47,13 +47,22 @@ service Dispatcher { // maybe dispatch, al likes this // it should be terminated. rpc Tasks(TasksRequest) returns (stream TasksMessage) { option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" }; + option deprecated = true; + }; + + // Assignments is a stream of assignments such as tasks and secrets for node. + // The first message in the stream contains all of the tasks and secrets + // that are relevant to the node. Future messages in the stream are updates to + // the set of assignments. + rpc Assignments(AssignmentsRequest) returns (stream AssignmentsMessage) { + option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" }; }; } // SessionRequest starts a session. message SessionRequest { NodeDescription description = 1; - // SessionID can be provided to attempt resuming an exising session. If the + // SessionID can be provided to attempt resuming an exising session. If the // SessionID is empty or invalid, a new SessionID will be assigned. // // See SessionMessage.SessionID for details. @@ -115,7 +124,7 @@ message SessionMessage { repeated WeightedPeer managers = 3; // Symmetric encryption key distributed by the lead manager. Used by agents - // for securing network bootstrapping and communication. + // for securing network bootstrapping and communication. repeated EncryptionKey network_bootstrap_keys = 4; } @@ -157,3 +166,40 @@ message TasksMessage { repeated Task tasks = 1; } +message AssignmentsRequest { + string session_id = 1 [(gogoproto.customname) = "SessionID"]; +} + +message AssignmentsMessage { + // AssignmentType specifies whether this assignment message carries + // the full state, or is an update to an existing state. + enum Type { + COMPLETE = 0; + INCREMENTAL = 1; + } + + Type type = 1; + + // AppliesTo references the previous ResultsIn value, to chain + // incremental updates together. For the first update in a stream, + // AppliesTo is empty. If AppliesTo does not match the previously + // received ResultsIn, the consumer of the stream should start a new + // Assignments stream to re-sync. + string applies_to = 2; + + // ResultsIn identifies the result of this assignments message, to + // match against the next message's AppliesTo value and protect + // against missed messages. + string results_in = 3; + + // UpdateTasks is a set of new or updated tasks to run on this node. + // In the first assignments message, it contains all of the tasks + // to run on this node. Tasks outside of this set running on the node + // should be terminated. + repeated Task update_tasks = 4; + + // RemoveTasks is a set of previously-assigned task IDs to remove from the + // assignment set. It is not used in the first assignments message of + // a stream. + repeated string remove_tasks = 5; +} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/duration/duration.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/duration/duration.pb.go index 2295b78181..d70317b809 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/duration/duration.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/duration/duration.pb.go @@ -32,7 +32,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package // A Duration represents a signed, fixed-length span of time represented // as a count of seconds and fractions of seconds at nanosecond @@ -128,11 +130,12 @@ func valueToGoStringDuration(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringDuration(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringDuration(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -142,7 +145,7 @@ func extensionToGoStringDuration(e map[int32]github_com_gogo_protobuf_proto.Exte for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *Duration) Marshal() (data []byte, err error) { @@ -438,6 +441,8 @@ var ( ErrIntOverflowDuration = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("duration.proto", fileDescriptorDuration) } + var fileDescriptorDuration = []byte{ // 201 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0x29, 0x2d, 0x4a, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/health.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/health.pb.go index b81455bebe..13c40143df 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/health.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/health.pb.go @@ -21,10 +21,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -153,11 +154,12 @@ func valueToGoStringHealth(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringHealth(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringHealth(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -167,7 +169,7 @@ func extensionToGoStringHealth(e map[int32]github_com_gogo_protobuf_proto.Extens for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -177,7 +179,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for Health service @@ -239,7 +241,8 @@ var _Health_serviceDesc = grpc.ServiceDesc{ Handler: _Health_Check_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorHealth, } func (m *HealthCheckRequest) Marshal() (data []byte, err error) { @@ -319,12 +322,11 @@ func encodeVarintHealth(data []byte, offset int, v uint64) int { type raftProxyHealthServer struct { local HealthServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyHealthServer(local HealthServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) HealthServer { +func NewRaftProxyHealthServer(local HealthServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) HealthServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -346,7 +348,6 @@ func NewRaftProxyHealthServer(local HealthServer, connSelector raftpicker.Interf return &raftProxyHealthServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -361,34 +362,59 @@ func (p *raftProxyHealthServer) runCtxMods(ctx context.Context) (context.Context } return ctx, nil } +func (p *raftProxyHealthServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyHealthServer) Check(ctx context.Context, r *HealthCheckRequest) (*HealthCheckResponse, error) { - if p.cluster.IsLeader() { - return p.local.Check(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Check(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewHealthClient(conn).Check(ctx, r) + resp, err := NewHealthClient(conn).Check(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.Check(ctx, r) + } + return nil, err + } + return NewHealthClient(conn).Check(modCtx, r) + } + return resp, err } func (m *HealthCheckRequest) Size() (n int) { @@ -704,6 +730,8 @@ var ( ErrIntOverflowHealth = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("health.proto", fileDescriptorHealth) } + var fileDescriptorHealth = []byte{ // 291 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x48, 0x4d, 0xcc, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.pb.go index e2671b6b7c..522fbac542 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.pb.go @@ -66,6 +66,9 @@ type Service struct { ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Meta Meta `protobuf:"bytes,2,opt,name=meta" json:"meta"` Spec ServiceSpec `protobuf:"bytes,3,opt,name=spec" json:"spec"` + // PreviousSpec is the previous service spec that was in place before + // "Spec". + PreviousSpec *ServiceSpec `protobuf:"bytes,6,opt,name=previous_spec,json=previousSpec" json:"previous_spec,omitempty"` // Runtime state of service endpoint. This may be different // from the spec version because the user may not have entered // the optional fields like node_port or virtual_ip and it @@ -284,6 +287,7 @@ func (m *Service) Copy() *Service { ID: m.ID, Meta: *m.Meta.Copy(), Spec: *m.Spec.Copy(), + PreviousSpec: m.PreviousSpec.Copy(), Endpoint: m.Endpoint.Copy(), UpdateStatus: m.UpdateStatus.Copy(), } @@ -468,11 +472,14 @@ func (this *Service) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 9) + s := make([]string, 0, 10) s = append(s, "&api.Service{") s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") s = append(s, "Meta: "+strings.Replace(this.Meta.GoString(), `&`, ``, 1)+",\n") s = append(s, "Spec: "+strings.Replace(this.Spec.GoString(), `&`, ``, 1)+",\n") + if this.PreviousSpec != nil { + s = append(s, "PreviousSpec: "+fmt.Sprintf("%#v", this.PreviousSpec)+",\n") + } if this.Endpoint != nil { s = append(s, "Endpoint: "+fmt.Sprintf("%#v", this.Endpoint)+",\n") } @@ -596,11 +603,12 @@ func valueToGoStringObjects(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringObjects(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringObjects(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -610,7 +618,7 @@ func extensionToGoStringObjects(e map[int32]github_com_gogo_protobuf_proto.Exten for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *Meta) Marshal() (data []byte, err error) { @@ -802,6 +810,16 @@ func (m *Service) MarshalTo(data []byte) (int, error) { } i += n14 } + if m.PreviousSpec != nil { + data[i] = 0x32 + i++ + i = encodeVarintObjects(data, i, uint64(m.PreviousSpec.Size())) + n15, err := m.PreviousSpec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n15 + } return i, nil } @@ -824,11 +842,11 @@ func (m *Endpoint) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n15, err := m.Spec.MarshalTo(data[i:]) + n16, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } if len(m.Ports) > 0 { for _, msg := range m.Ports { @@ -911,19 +929,19 @@ func (m *Task) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintObjects(data, i, uint64(m.Meta.Size())) - n16, err := m.Meta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n16 - data[i] = 0x1a - i++ - i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n17, err := m.Spec.MarshalTo(data[i:]) + n17, err := m.Meta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n17 + data[i] = 0x1a + i++ + i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) + n18, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n18 if len(m.ServiceID) > 0 { data[i] = 0x22 i++ @@ -944,27 +962,27 @@ func (m *Task) MarshalTo(data []byte) (int, error) { data[i] = 0x3a i++ i = encodeVarintObjects(data, i, uint64(m.Annotations.Size())) - n18, err := m.Annotations.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n18 - data[i] = 0x42 - i++ - i = encodeVarintObjects(data, i, uint64(m.ServiceAnnotations.Size())) - n19, err := m.ServiceAnnotations.MarshalTo(data[i:]) + n19, err := m.Annotations.MarshalTo(data[i:]) if err != nil { return 0, err } i += n19 - data[i] = 0x4a + data[i] = 0x42 i++ - i = encodeVarintObjects(data, i, uint64(m.Status.Size())) - n20, err := m.Status.MarshalTo(data[i:]) + i = encodeVarintObjects(data, i, uint64(m.ServiceAnnotations.Size())) + n20, err := m.ServiceAnnotations.MarshalTo(data[i:]) if err != nil { return 0, err } i += n20 + data[i] = 0x4a + i++ + i = encodeVarintObjects(data, i, uint64(m.Status.Size())) + n21, err := m.Status.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n21 if m.DesiredState != 0 { data[i] = 0x50 i++ @@ -986,21 +1004,21 @@ func (m *Task) MarshalTo(data []byte) (int, error) { data[i] = 0x62 i++ i = encodeVarintObjects(data, i, uint64(m.Endpoint.Size())) - n21, err := m.Endpoint.MarshalTo(data[i:]) + n22, err := m.Endpoint.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n21 + i += n22 } if m.LogDriver != nil { data[i] = 0x6a i++ i = encodeVarintObjects(data, i, uint64(m.LogDriver.Size())) - n22, err := m.LogDriver.MarshalTo(data[i:]) + n23, err := m.LogDriver.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n22 + i += n23 } return i, nil } @@ -1024,11 +1042,11 @@ func (m *NetworkAttachment) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintObjects(data, i, uint64(m.Network.Size())) - n23, err := m.Network.MarshalTo(data[i:]) + n24, err := m.Network.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n23 + i += n24 } if len(m.Addresses) > 0 { for _, s := range m.Addresses { @@ -1087,38 +1105,38 @@ func (m *Network) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintObjects(data, i, uint64(m.Meta.Size())) - n24, err := m.Meta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n24 - data[i] = 0x1a - i++ - i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n25, err := m.Spec.MarshalTo(data[i:]) + n25, err := m.Meta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n25 + data[i] = 0x1a + i++ + i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) + n26, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n26 if m.DriverState != nil { data[i] = 0x22 i++ i = encodeVarintObjects(data, i, uint64(m.DriverState.Size())) - n26, err := m.DriverState.MarshalTo(data[i:]) + n27, err := m.DriverState.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n26 + i += n27 } if m.IPAM != nil { data[i] = 0x2a i++ i = encodeVarintObjects(data, i, uint64(m.IPAM.Size())) - n27, err := m.IPAM.MarshalTo(data[i:]) + n28, err := m.IPAM.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n27 + i += n28 } return i, nil } @@ -1147,27 +1165,27 @@ func (m *Cluster) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintObjects(data, i, uint64(m.Meta.Size())) - n28, err := m.Meta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n28 - data[i] = 0x1a - i++ - i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n29, err := m.Spec.MarshalTo(data[i:]) + n29, err := m.Meta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n29 - data[i] = 0x22 + data[i] = 0x1a i++ - i = encodeVarintObjects(data, i, uint64(m.RootCA.Size())) - n30, err := m.RootCA.MarshalTo(data[i:]) + i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) + n30, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } i += n30 + data[i] = 0x22 + i++ + i = encodeVarintObjects(data, i, uint64(m.RootCA.Size())) + n31, err := m.RootCA.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n31 if len(m.NetworkBootstrapKeys) > 0 { for _, msg := range m.NetworkBootstrapKeys { data[i] = 0x2a @@ -1281,6 +1299,10 @@ func (m *Service) Size() (n int) { l = m.UpdateStatus.Size() n += 1 + l + sovObjects(uint64(l)) } + if m.PreviousSpec != nil { + l = m.PreviousSpec.Size() + n += 1 + l + sovObjects(uint64(l)) + } return n } @@ -1489,6 +1511,7 @@ func (this *Service) String() string { `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "ServiceSpec", "ServiceSpec", 1), `&`, ``, 1) + `,`, `Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "Endpoint", "Endpoint", 1) + `,`, `UpdateStatus:` + strings.Replace(fmt.Sprintf("%v", this.UpdateStatus), "UpdateStatus", "UpdateStatus", 1) + `,`, + `PreviousSpec:` + strings.Replace(fmt.Sprintf("%v", this.PreviousSpec), "ServiceSpec", "ServiceSpec", 1) + `,`, `}`, }, "") return s @@ -2215,6 +2238,39 @@ func (m *Service) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PreviousSpec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowObjects + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthObjects + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PreviousSpec == nil { + m.PreviousSpec = &ServiceSpec{} + } + if err := m.PreviousSpec.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipObjects(data[iNdEx:]) @@ -3581,70 +3637,73 @@ var ( ErrIntOverflowObjects = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("objects.proto", fileDescriptorObjects) } + var fileDescriptorObjects = []byte{ - // 1009 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6e, 0x1b, 0x45, - 0x1c, 0xce, 0xda, 0x1b, 0xdb, 0xfb, 0x73, 0x1c, 0x89, 0xa1, 0xaa, 0xb6, 0x21, 0xd8, 0xc1, 0x15, - 0xa8, 0x87, 0xca, 0x15, 0xa5, 0x20, 0x2a, 0x5a, 0x21, 0xff, 0x13, 0x58, 0x25, 0x10, 0x4d, 0x4b, - 0x7a, 0x5c, 0x4d, 0x76, 0xa7, 0x66, 0xb1, 0xbd, 0xb3, 0x9a, 0x19, 0xbb, 0xf2, 0x0d, 0xf1, 0x00, - 0x48, 0xbc, 0x00, 0xaf, 0xc2, 0x35, 0x07, 0x0e, 0x1c, 0x39, 0x59, 0xc4, 0x37, 0x4e, 0xf0, 0x08, - 0x68, 0x66, 0x67, 0xed, 0x8d, 0xbc, 0x0e, 0x8d, 0x84, 0x72, 0x9b, 0xd9, 0xf9, 0xbe, 0x6f, 0x7e, - 0xff, 0x67, 0xa1, 0xc6, 0xce, 0xbe, 0xa7, 0xbe, 0x14, 0xad, 0x98, 0x33, 0xc9, 0x10, 0x0a, 0x98, + // 1029 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xce, 0xda, 0x1b, 0xdb, 0xfb, 0x3a, 0x8e, 0xc4, 0x50, 0x55, 0xdb, 0x10, 0xec, 0xe0, 0x0a, + 0xd4, 0x43, 0xe5, 0x8a, 0x52, 0x10, 0x15, 0xad, 0x90, 0xbf, 0x04, 0x56, 0x09, 0x44, 0xd3, 0x92, + 0x1e, 0x57, 0x93, 0xdd, 0xa9, 0x59, 0x6c, 0xef, 0xac, 0x66, 0xc6, 0xae, 0x7c, 0x43, 0xfc, 0x00, + 0x7e, 0x02, 0x7f, 0x85, 0x6b, 0x0e, 0x1c, 0xb8, 0xc1, 0xc9, 0x22, 0xbe, 0x71, 0x82, 0x9f, 0x80, + 0x66, 0x76, 0xd6, 0xde, 0xc8, 0xeb, 0x90, 0x4a, 0x28, 0xb7, 0x99, 0x9d, 0xe7, 0x79, 0xde, 0xcf, + 0x79, 0x77, 0xa0, 0xc6, 0xce, 0xbe, 0xa7, 0xbe, 0x14, 0xad, 0x98, 0x33, 0xc9, 0x10, 0x0a, 0x98, 0x3f, 0xa2, 0xbc, 0x25, 0x5e, 0x13, 0x3e, 0x19, 0x85, 0xb2, 0x35, 0xfb, 0xf0, 0xa0, 0x2a, 0xe7, 0x31, 0x35, 0x80, 0x83, 0xaa, 0x88, 0xa9, 0x9f, 0x6e, 0xee, 0xc8, 0x70, 0x42, 0x85, 0x24, 0x93, 0xf8, 0xc1, 0x6a, 0x65, 0x8e, 0x6e, 0x0d, 0xd9, 0x90, 0xe9, 0xe5, 0x03, 0xb5, 0x4a, 0xbe, 0x36, - 0x7f, 0xb5, 0xc0, 0x3e, 0xa6, 0x92, 0xa0, 0xcf, 0xa0, 0x3c, 0xa3, 0x5c, 0x84, 0x2c, 0x72, 0xad, - 0x23, 0xeb, 0x5e, 0xf5, 0xe1, 0x3b, 0xad, 0xcd, 0x9b, 0x5b, 0xa7, 0x09, 0xa4, 0x63, 0x9f, 0x2f, - 0x1a, 0x3b, 0x38, 0x65, 0xa0, 0x27, 0x00, 0x3e, 0xa7, 0x44, 0xd2, 0xc0, 0x23, 0xd2, 0x2d, 0x68, - 0xfe, 0xbb, 0x79, 0xfc, 0x17, 0xa9, 0x51, 0xd8, 0x31, 0x84, 0xb6, 0x54, 0xec, 0x69, 0x1c, 0xa4, - 0xec, 0xe2, 0x1b, 0xb1, 0x0d, 0xa1, 0x2d, 0x9b, 0x7f, 0x15, 0xc1, 0xfe, 0x9a, 0x05, 0x14, 0xdd, - 0x86, 0x42, 0x18, 0x68, 0xe3, 0x9d, 0x4e, 0x69, 0xb9, 0x68, 0x14, 0x06, 0x3d, 0x5c, 0x08, 0x03, - 0xf4, 0x10, 0xec, 0x09, 0x95, 0xc4, 0x98, 0xe5, 0xe6, 0x09, 0xab, 0x08, 0x18, 0x9f, 0x34, 0x16, - 0x7d, 0x02, 0xb6, 0x0a, 0xab, 0x31, 0xe6, 0x30, 0x8f, 0xa3, 0xee, 0x7c, 0x1e, 0x53, 0x3f, 0xe5, - 0x29, 0x3c, 0xea, 0x43, 0x35, 0xa0, 0xc2, 0xe7, 0x61, 0x2c, 0x55, 0x24, 0x6d, 0x4d, 0xbf, 0xbb, - 0x8d, 0xde, 0x5b, 0x43, 0x71, 0x96, 0x87, 0x9e, 0x40, 0x49, 0x48, 0x22, 0xa7, 0xc2, 0xdd, 0xd5, - 0x0a, 0xf5, 0xad, 0x06, 0x68, 0x94, 0x31, 0xc1, 0x70, 0xd0, 0x97, 0xb0, 0x3f, 0x21, 0x11, 0x19, - 0x52, 0xee, 0x19, 0x95, 0x92, 0x56, 0x79, 0x2f, 0xd7, 0xf5, 0x04, 0x99, 0x08, 0xe1, 0xda, 0x24, - 0xbb, 0x45, 0x7d, 0x00, 0x22, 0x25, 0xf1, 0xbf, 0x9b, 0xd0, 0x48, 0xba, 0x65, 0xad, 0xf2, 0x7e, - 0xae, 0x2d, 0x54, 0xbe, 0x66, 0x7c, 0xd4, 0x5e, 0x81, 0x71, 0x86, 0x88, 0xbe, 0x80, 0xaa, 0x4f, - 0xb9, 0x0c, 0x5f, 0x85, 0x3e, 0x91, 0xd4, 0xad, 0x68, 0x9d, 0x46, 0x9e, 0x4e, 0x77, 0x0d, 0x33, - 0x4e, 0x65, 0x99, 0xcd, 0x9f, 0x0b, 0x50, 0x7e, 0x4e, 0xf9, 0x2c, 0xf4, 0xff, 0xdf, 0x74, 0x3f, - 0xbe, 0x94, 0xee, 0x5c, 0xcb, 0xcc, 0xb5, 0x1b, 0x19, 0xff, 0x14, 0x2a, 0x34, 0x0a, 0x62, 0x16, - 0x46, 0xd2, 0xa4, 0x3b, 0xb7, 0x5a, 0xfa, 0x06, 0x83, 0x57, 0x68, 0xd4, 0x87, 0x5a, 0x52, 0xc5, - 0xde, 0xa5, 0x5c, 0x1f, 0xe5, 0xd1, 0xbf, 0xd5, 0x40, 0x93, 0xa4, 0xbd, 0x69, 0x66, 0xd7, 0xfc, - 0xa5, 0x00, 0x95, 0x54, 0x1d, 0x3d, 0x32, 0x8e, 0x58, 0xdb, 0xa5, 0x52, 0xac, 0xf2, 0xc4, 0xf8, - 0xf0, 0x08, 0x76, 0x63, 0xc6, 0xa5, 0x70, 0x0b, 0x47, 0xc5, 0x6d, 0xd5, 0x76, 0xc2, 0xb8, 0xec, - 0xb2, 0xe8, 0x55, 0x38, 0xc4, 0x09, 0x18, 0xbd, 0x84, 0xea, 0x2c, 0xe4, 0x72, 0x4a, 0xc6, 0x5e, - 0x18, 0x0b, 0xb7, 0xa8, 0xb9, 0x1f, 0x5c, 0x75, 0x65, 0xeb, 0x34, 0xc1, 0x0f, 0x4e, 0x3a, 0xfb, - 0xcb, 0x45, 0x03, 0x56, 0x5b, 0x81, 0xc1, 0x48, 0x0d, 0x62, 0x71, 0x70, 0x0c, 0xce, 0xea, 0x04, - 0xdd, 0x07, 0x88, 0x92, 0xe2, 0xf2, 0x56, 0xe9, 0xae, 0x2d, 0x17, 0x0d, 0xc7, 0x94, 0xdc, 0xa0, - 0x87, 0x1d, 0x03, 0x18, 0x04, 0x08, 0x81, 0x4d, 0x82, 0x80, 0xeb, 0xe4, 0x3b, 0x58, 0xaf, 0x9b, - 0xbf, 0xed, 0x82, 0xfd, 0x82, 0x88, 0xd1, 0x4d, 0x0f, 0x08, 0x75, 0xe7, 0x46, 0xb9, 0xdc, 0x07, - 0x10, 0x49, 0x25, 0x29, 0x77, 0xec, 0xb5, 0x3b, 0xa6, 0xbe, 0x94, 0x3b, 0x06, 0x90, 0xb8, 0x23, - 0xc6, 0x4c, 0xea, 0xca, 0xb0, 0xb1, 0x5e, 0xa3, 0xbb, 0x50, 0x8e, 0x58, 0xa0, 0xe9, 0x25, 0x4d, - 0x87, 0xe5, 0xa2, 0x51, 0x52, 0xc3, 0x60, 0xd0, 0xc3, 0x25, 0x75, 0x34, 0x08, 0x54, 0xc7, 0x91, - 0x28, 0x62, 0x92, 0xa8, 0x71, 0x22, 0x4c, 0xe7, 0xe6, 0xd6, 0x75, 0x7b, 0x0d, 0x4b, 0x3b, 0x2e, - 0xc3, 0x44, 0xa7, 0xf0, 0x76, 0x6a, 0x6f, 0x56, 0xb0, 0x72, 0x1d, 0x41, 0x64, 0x14, 0x32, 0x27, - 0x99, 0x09, 0xe7, 0x6c, 0x9f, 0x70, 0x3a, 0x82, 0x79, 0x13, 0xae, 0x03, 0xb5, 0x80, 0x8a, 0x90, - 0xd3, 0x40, 0xf7, 0x0e, 0x75, 0xe1, 0xc8, 0xba, 0xb7, 0xbf, 0xe5, 0xd1, 0x30, 0x22, 0x14, 0xef, - 0x19, 0x8e, 0xde, 0xa1, 0x36, 0x54, 0x4c, 0xdd, 0x08, 0xb7, 0xaa, 0x6b, 0xf7, 0x0d, 0x27, 0xdb, - 0x8a, 0x76, 0xa9, 0xf7, 0xf7, 0xae, 0xd5, 0xfb, 0x8f, 0x01, 0xc6, 0x6c, 0xe8, 0x05, 0x3c, 0x9c, - 0x51, 0xee, 0xd6, 0x34, 0xf7, 0x20, 0x8f, 0xdb, 0xd3, 0x08, 0xec, 0x8c, 0xd9, 0x30, 0x59, 0x36, - 0x7f, 0xb4, 0xe0, 0xad, 0x0d, 0xa3, 0xd0, 0xc7, 0x50, 0x36, 0x66, 0x5d, 0xf5, 0x7c, 0x1b, 0x1e, - 0x4e, 0xb1, 0xe8, 0x10, 0x1c, 0xd5, 0x23, 0x54, 0x08, 0x9a, 0x74, 0xbf, 0x83, 0xd7, 0x1f, 0x90, - 0x0b, 0x65, 0x32, 0x0e, 0x89, 0x3a, 0x2b, 0xea, 0xb3, 0x74, 0xdb, 0xfc, 0xa9, 0x00, 0x65, 0x23, - 0x76, 0xd3, 0x83, 0xd8, 0x5c, 0xbb, 0xd1, 0x59, 0x4f, 0x61, 0x2f, 0x09, 0xa7, 0x29, 0x09, 0xfb, - 0x3f, 0x83, 0x5a, 0x4d, 0xf0, 0x49, 0x39, 0x3c, 0x05, 0x3b, 0x8c, 0xc9, 0xc4, 0x0c, 0xe1, 0xdc, - 0x9b, 0x07, 0x27, 0xed, 0xe3, 0x6f, 0xe2, 0xa4, 0xb2, 0x2b, 0xcb, 0x45, 0xc3, 0x56, 0x1f, 0xb0, - 0xa6, 0x35, 0xff, 0x2e, 0x40, 0xb9, 0x3b, 0x9e, 0x0a, 0x49, 0xf9, 0x4d, 0x07, 0xc4, 0x5c, 0xbb, - 0x11, 0x90, 0x2e, 0x94, 0x39, 0x63, 0xd2, 0xf3, 0xc9, 0x55, 0xb1, 0xc0, 0x8c, 0xc9, 0x6e, 0xbb, - 0xb3, 0xaf, 0x88, 0x6a, 0x90, 0x24, 0x7b, 0x5c, 0x52, 0xd4, 0x2e, 0x41, 0x2f, 0xe1, 0x76, 0x3a, - 0x7e, 0xcf, 0x18, 0x93, 0x42, 0x72, 0x12, 0x7b, 0x23, 0x3a, 0x57, 0xaf, 0x55, 0x71, 0xdb, 0x3f, - 0x45, 0x3f, 0xf2, 0xf9, 0x5c, 0x07, 0xea, 0x19, 0x9d, 0xe3, 0x5b, 0x46, 0xa0, 0x93, 0xf2, 0x9f, - 0xd1, 0xb9, 0x40, 0x9f, 0xc3, 0x21, 0x5d, 0xc1, 0x94, 0xa2, 0x37, 0x26, 0x13, 0xf5, 0xb0, 0x78, - 0xfe, 0x98, 0xf9, 0x23, 0x3d, 0xdb, 0x6c, 0x7c, 0x87, 0x66, 0xa5, 0xbe, 0x4a, 0x10, 0x5d, 0x05, - 0xe8, 0x1c, 0x9e, 0x5f, 0xd4, 0x77, 0xfe, 0xb8, 0xa8, 0xef, 0xfc, 0x73, 0x51, 0xb7, 0x7e, 0x58, - 0xd6, 0xad, 0xf3, 0x65, 0xdd, 0xfa, 0x7d, 0x59, 0xb7, 0xfe, 0x5c, 0xd6, 0xad, 0xb3, 0x92, 0xfe, - 0xbd, 0xfd, 0xe8, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0x49, 0xe6, 0x55, 0x4e, 0x0b, 0x00, - 0x00, + 0x7f, 0xb1, 0xc0, 0x3e, 0xa6, 0x92, 0xa0, 0xcf, 0xa0, 0x3c, 0xa3, 0x5c, 0x84, 0x2c, 0x72, 0xad, + 0x23, 0xeb, 0x5e, 0xf5, 0xe1, 0x3b, 0xad, 0x4d, 0xcb, 0xad, 0xd3, 0x04, 0xd2, 0xb1, 0xcf, 0x17, + 0x8d, 0x1d, 0x9c, 0x32, 0xd0, 0x13, 0x00, 0x9f, 0x53, 0x22, 0x69, 0xe0, 0x11, 0xe9, 0x16, 0x34, + 0xff, 0xdd, 0x3c, 0xfe, 0x8b, 0xd4, 0x29, 0xec, 0x18, 0x42, 0x5b, 0x2a, 0xf6, 0x34, 0x0e, 0x52, + 0x76, 0xf1, 0x5a, 0x6c, 0x43, 0x68, 0xcb, 0xe6, 0x5f, 0x45, 0xb0, 0xbf, 0x66, 0x01, 0x45, 0xb7, + 0xa1, 0x10, 0x06, 0xda, 0x79, 0xa7, 0x53, 0x5a, 0x2e, 0x1a, 0x85, 0x41, 0x0f, 0x17, 0xc2, 0x00, + 0x3d, 0x04, 0x7b, 0x42, 0x25, 0x31, 0x6e, 0xb9, 0x79, 0xc2, 0x2a, 0x03, 0x26, 0x26, 0x8d, 0x45, + 0x9f, 0x80, 0xad, 0xd2, 0x6a, 0x9c, 0x39, 0xcc, 0xe3, 0x28, 0x9b, 0xcf, 0x63, 0xea, 0xa7, 0x3c, + 0x85, 0x47, 0x7d, 0xa8, 0x06, 0x54, 0xf8, 0x3c, 0x8c, 0xa5, 0xca, 0xa4, 0xad, 0xe9, 0x77, 0xb7, + 0xd1, 0x7b, 0x6b, 0x28, 0xce, 0xf2, 0xd0, 0x13, 0x28, 0x09, 0x49, 0xe4, 0x54, 0xb8, 0xbb, 0x5a, + 0xa1, 0xbe, 0xd5, 0x01, 0x8d, 0x32, 0x2e, 0x18, 0x0e, 0xfa, 0x12, 0xf6, 0x27, 0x24, 0x22, 0x43, + 0xca, 0x3d, 0xa3, 0x52, 0xd2, 0x2a, 0xef, 0xe5, 0x86, 0x9e, 0x20, 0x13, 0x21, 0x5c, 0x9b, 0x64, + 0xb7, 0xa8, 0x0f, 0x40, 0xa4, 0x24, 0xfe, 0x77, 0x13, 0x1a, 0x49, 0xb7, 0xac, 0x55, 0xde, 0xcf, + 0xf5, 0x85, 0xca, 0xd7, 0x8c, 0x8f, 0xda, 0x2b, 0x30, 0xce, 0x10, 0xd1, 0x17, 0x50, 0xf5, 0x29, + 0x97, 0xe1, 0xab, 0xd0, 0x27, 0x92, 0xba, 0x15, 0xad, 0xd3, 0xc8, 0xd3, 0xe9, 0xae, 0x61, 0x26, + 0xa8, 0x2c, 0xb3, 0xf9, 0x7b, 0x01, 0xca, 0xcf, 0x29, 0x9f, 0x85, 0xfe, 0xff, 0x5b, 0xee, 0xc7, + 0x97, 0xca, 0x9d, 0xeb, 0x99, 0x31, 0xbb, 0x51, 0xf1, 0x4f, 0xa1, 0x42, 0xa3, 0x20, 0x66, 0x61, + 0x24, 0x4d, 0xb9, 0x73, 0xbb, 0xa5, 0x6f, 0x30, 0x78, 0x85, 0x46, 0x7d, 0xa8, 0x25, 0x5d, 0xec, + 0x5d, 0xaa, 0xf5, 0x51, 0x1e, 0xfd, 0x5b, 0x0d, 0x34, 0x45, 0xda, 0x9b, 0x66, 0x76, 0xa8, 0x07, + 0xb5, 0x98, 0xd3, 0x59, 0xc8, 0xa6, 0xc2, 0xd3, 0x41, 0x94, 0xae, 0x15, 0x04, 0xde, 0x4b, 0x59, + 0x6a, 0xd7, 0xfc, 0xb9, 0x00, 0x95, 0xd4, 0x47, 0xf4, 0xc8, 0xa4, 0xc3, 0xda, 0xee, 0x50, 0x8a, + 0xd5, 0x52, 0x49, 0x26, 0x1e, 0xc1, 0x6e, 0xcc, 0xb8, 0x14, 0x6e, 0xe1, 0xa8, 0xb8, 0xad, 0x67, + 0x4f, 0x18, 0x97, 0x5d, 0x16, 0xbd, 0x0a, 0x87, 0x38, 0x01, 0xa3, 0x97, 0x50, 0x9d, 0x85, 0x5c, + 0x4e, 0xc9, 0xd8, 0x0b, 0x63, 0xe1, 0x16, 0x35, 0xf7, 0x83, 0xab, 0x4c, 0xb6, 0x4e, 0x13, 0xfc, + 0xe0, 0xa4, 0xb3, 0xbf, 0x5c, 0x34, 0x60, 0xb5, 0x15, 0x18, 0x8c, 0xd4, 0x20, 0x16, 0x07, 0xc7, + 0xe0, 0xac, 0x4e, 0xd0, 0x7d, 0x80, 0x28, 0x69, 0x51, 0x6f, 0xd5, 0x34, 0xb5, 0xe5, 0xa2, 0xe1, + 0x98, 0xc6, 0x1d, 0xf4, 0xb0, 0x63, 0x00, 0x83, 0x00, 0x21, 0xb0, 0x49, 0x10, 0x70, 0xdd, 0x42, + 0x0e, 0xd6, 0xeb, 0xe6, 0xaf, 0xbb, 0x60, 0xbf, 0x20, 0x62, 0x74, 0xd3, 0x63, 0x46, 0xd9, 0xdc, + 0x68, 0xba, 0xfb, 0x00, 0x22, 0x29, 0xa5, 0x0a, 0xc7, 0x5e, 0x87, 0x63, 0x0a, 0xac, 0xc2, 0x31, + 0x80, 0x24, 0x1c, 0x31, 0x66, 0x52, 0xf7, 0x97, 0x8d, 0xf5, 0x1a, 0xdd, 0x85, 0x72, 0xc4, 0x02, + 0x4d, 0x2f, 0x69, 0x3a, 0x2c, 0x17, 0x8d, 0x92, 0x1a, 0x29, 0x83, 0x1e, 0x2e, 0xa9, 0xa3, 0x41, + 0xa0, 0xee, 0x2d, 0x89, 0x22, 0x26, 0x89, 0x1a, 0x4a, 0xc2, 0xdc, 0xff, 0xdc, 0xc6, 0x6a, 0xaf, + 0x61, 0xe9, 0xbd, 0xcd, 0x30, 0xd1, 0x29, 0xbc, 0x9d, 0xfa, 0x9b, 0x15, 0xac, 0xbc, 0x89, 0x20, + 0x32, 0x0a, 0x99, 0x93, 0xcc, 0x9c, 0x74, 0xb6, 0xcf, 0x49, 0x9d, 0xc1, 0xbc, 0x39, 0xd9, 0x81, + 0x5a, 0x40, 0x45, 0xc8, 0x69, 0xa0, 0x6f, 0x20, 0x75, 0xe1, 0xc8, 0xba, 0xb7, 0xbf, 0xe5, 0xd7, + 0x63, 0x44, 0x28, 0xde, 0x33, 0x1c, 0xbd, 0x43, 0x6d, 0xa8, 0x98, 0xbe, 0x11, 0x6e, 0x55, 0xf7, + 0xee, 0x35, 0xe7, 0xe3, 0x8a, 0x76, 0x69, 0x82, 0xec, 0xbd, 0xd1, 0x04, 0x79, 0x0c, 0x30, 0x66, + 0x43, 0x2f, 0xe0, 0xe1, 0x8c, 0x72, 0xb7, 0xa6, 0xb9, 0x07, 0x79, 0xdc, 0x9e, 0x46, 0x60, 0x67, + 0xcc, 0x86, 0xc9, 0xb2, 0xf9, 0xa3, 0x05, 0x6f, 0x6d, 0x38, 0x85, 0x3e, 0x86, 0xb2, 0x71, 0xeb, + 0xaa, 0x47, 0x80, 0xe1, 0xe1, 0x14, 0x8b, 0x0e, 0xc1, 0x51, 0x77, 0x84, 0x0a, 0x41, 0x93, 0xdb, + 0xef, 0xe0, 0xf5, 0x07, 0xe4, 0x42, 0x99, 0x8c, 0x43, 0xa2, 0xce, 0x8a, 0xfa, 0x2c, 0xdd, 0x36, + 0x7f, 0x2a, 0x40, 0xd9, 0x88, 0xdd, 0xf4, 0x38, 0x37, 0x66, 0x37, 0x6e, 0xd6, 0x53, 0xd8, 0x4b, + 0xd2, 0x69, 0x5a, 0xc2, 0xfe, 0xcf, 0xa4, 0x56, 0x13, 0x7c, 0xd2, 0x0e, 0x4f, 0xc1, 0x0e, 0x63, + 0x32, 0x31, 0xa3, 0x3c, 0xd7, 0xf2, 0xe0, 0xa4, 0x7d, 0xfc, 0x4d, 0x9c, 0x74, 0x76, 0x65, 0xb9, + 0x68, 0xd8, 0xea, 0x03, 0xd6, 0xb4, 0xe6, 0xdf, 0x05, 0x28, 0x77, 0xc7, 0x53, 0x21, 0x29, 0xbf, + 0xe9, 0x84, 0x18, 0xb3, 0x1b, 0x09, 0xe9, 0x42, 0x99, 0x33, 0x26, 0x3d, 0x9f, 0x5c, 0x95, 0x0b, + 0xcc, 0x98, 0xec, 0xb6, 0x3b, 0xfb, 0x8a, 0xa8, 0x06, 0x49, 0xb2, 0xc7, 0x25, 0x45, 0xed, 0x12, + 0xf4, 0x12, 0x6e, 0xa7, 0xe3, 0xf7, 0x8c, 0x31, 0x29, 0x24, 0x27, 0xb1, 0x37, 0xa2, 0x73, 0xf5, + 0xcf, 0x2b, 0x6e, 0x7b, 0x99, 0xf4, 0x23, 0x9f, 0xcf, 0x75, 0xa2, 0x9e, 0xd1, 0x39, 0xbe, 0x65, + 0x04, 0x3a, 0x29, 0xff, 0x19, 0x9d, 0x0b, 0xf4, 0x39, 0x1c, 0xd2, 0x15, 0x4c, 0x29, 0x7a, 0x63, + 0x32, 0x51, 0x3f, 0x16, 0xcf, 0x1f, 0x33, 0x7f, 0xa4, 0x67, 0x9b, 0x8d, 0xef, 0xd0, 0xac, 0xd4, + 0x57, 0x09, 0xa2, 0xab, 0x00, 0x9d, 0xc3, 0xf3, 0x8b, 0xfa, 0xce, 0x1f, 0x17, 0xf5, 0x9d, 0x7f, + 0x2e, 0xea, 0xd6, 0x0f, 0xcb, 0xba, 0x75, 0xbe, 0xac, 0x5b, 0xbf, 0x2d, 0xeb, 0xd6, 0x9f, 0xcb, + 0xba, 0x75, 0x56, 0xd2, 0x8f, 0xe4, 0x8f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x6a, 0xb2, 0x97, + 0xcc, 0x94, 0x0b, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.proto b/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.proto index b28fa935b5..2864637dd8 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.proto +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/objects.proto @@ -57,6 +57,10 @@ message Service { ServiceSpec spec = 3 [(gogoproto.nullable) = false]; + // PreviousSpec is the previous service spec that was in place before + // "Spec". + ServiceSpec previous_spec = 6; + // Runtime state of service endpoint. This may be different // from the spec version because the user may not have entered // the optional fields like node_port or virtual_ip and it diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.pb.go index 1cb2e3173f..c597b44d85 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.pb.go @@ -23,10 +23,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -163,7 +164,7 @@ func (m *InternalRaftRequest) Reset() { *m = InternalRaftRequ func (*InternalRaftRequest) ProtoMessage() {} func (*InternalRaftRequest) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{9} } -// StoreAction defines a taret and operation to apply on the storage system. +// StoreAction defines a target and operation to apply on the storage system. type StoreAction struct { Action StoreActionKind `protobuf:"varint,1,opt,name=action,proto3,enum=docker.swarmkit.v1.StoreActionKind" json:"action,omitempty"` // Types that are valid to be assigned to Target: @@ -797,11 +798,12 @@ func valueToGoStringRaft(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringRaft(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringRaft(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -811,7 +813,7 @@ func extensionToGoStringRaft(e map[int32]github_com_gogo_protobuf_proto.Extensio for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -821,7 +823,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for Raft service @@ -922,7 +924,8 @@ var _Raft_serviceDesc = grpc.ServiceDesc{ Handler: _Raft_ResolveAddress_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorRaft, } // Client API for RaftMembership service @@ -1022,7 +1025,8 @@ var _RaftMembership_serviceDesc = grpc.ServiceDesc{ Handler: _RaftMembership_Leave_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorRaft, } func (m *RaftMember) Marshal() (data []byte, err error) { @@ -1438,12 +1442,11 @@ func encodeVarintRaft(data []byte, offset int, v uint64) int { type raftProxyRaftServer struct { local RaftServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyRaftServer(local RaftServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) RaftServer { +func NewRaftProxyRaftServer(local RaftServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) RaftServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -1465,7 +1468,6 @@ func NewRaftProxyRaftServer(local RaftServer, connSelector raftpicker.Interface, return &raftProxyRaftServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -1480,73 +1482,99 @@ func (p *raftProxyRaftServer) runCtxMods(ctx context.Context) (context.Context, } return ctx, nil } +func (p *raftProxyRaftServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyRaftServer) ProcessRaftMessage(ctx context.Context, r *ProcessRaftMessageRequest) (*ProcessRaftMessageResponse, error) { - if p.cluster.IsLeader() { - return p.local.ProcessRaftMessage(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ProcessRaftMessage(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewRaftClient(conn).ProcessRaftMessage(ctx, r) + resp, err := NewRaftClient(conn).ProcessRaftMessage(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ProcessRaftMessage(ctx, r) + } + return nil, err + } + return NewRaftClient(conn).ProcessRaftMessage(modCtx, r) + } + return resp, err } func (p *raftProxyRaftServer) ResolveAddress(ctx context.Context, r *ResolveAddressRequest) (*ResolveAddressResponse, error) { - if p.cluster.IsLeader() { - return p.local.ResolveAddress(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.ResolveAddress(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewRaftClient(conn).ResolveAddress(ctx, r) + resp, err := NewRaftClient(conn).ResolveAddress(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.ResolveAddress(ctx, r) + } + return nil, err + } + return NewRaftClient(conn).ResolveAddress(modCtx, r) + } + return resp, err } type raftProxyRaftMembershipServer struct { local RaftMembershipServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyRaftMembershipServer(local RaftMembershipServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) RaftMembershipServer { +func NewRaftProxyRaftMembershipServer(local RaftMembershipServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) RaftMembershipServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -1568,7 +1596,6 @@ func NewRaftProxyRaftMembershipServer(local RaftMembershipServer, connSelector r return &raftProxyRaftMembershipServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -1583,63 +1610,90 @@ func (p *raftProxyRaftMembershipServer) runCtxMods(ctx context.Context) (context } return ctx, nil } +func (p *raftProxyRaftMembershipServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyRaftMembershipServer) Join(ctx context.Context, r *JoinRequest) (*JoinResponse, error) { - if p.cluster.IsLeader() { - return p.local.Join(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Join(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewRaftMembershipClient(conn).Join(ctx, r) + resp, err := NewRaftMembershipClient(conn).Join(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.Join(ctx, r) + } + return nil, err + } + return NewRaftMembershipClient(conn).Join(modCtx, r) + } + return resp, err } func (p *raftProxyRaftMembershipServer) Leave(ctx context.Context, r *LeaveRequest) (*LeaveResponse, error) { - if p.cluster.IsLeader() { - return p.local.Leave(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.Leave(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewRaftMembershipClient(conn).Leave(ctx, r) + resp, err := NewRaftMembershipClient(conn).Leave(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.Leave(ctx, r) + } + return nil, err + } + return NewRaftMembershipClient(conn).Leave(modCtx, r) + } + return resp, err } func (m *RaftMember) Size() (n int) { @@ -3205,6 +3259,8 @@ var ( ErrIntOverflowRaft = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("raft.proto", fileDescriptorRaft) } + var fileDescriptorRaft = []byte{ // 868 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x95, 0x4f, 0x73, 0xdb, 0x44, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.proto b/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.proto index 911de323f4..e5a0ffb4d8 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.proto +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/raft.proto @@ -115,7 +115,7 @@ enum StoreActionKind { STORE_ACTION_REMOVE = 3 [(gogoproto.enumvalue_customname) = "StoreActionKindRemove"]; } -// StoreAction defines a taret and operation to apply on the storage system. +// StoreAction defines a target and operation to apply on the storage system. message StoreAction { StoreActionKind action = 1; oneof target { diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/resource.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/resource.pb.go index fd7416635e..52d1e4e4ab 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/resource.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/resource.pb.go @@ -21,10 +21,11 @@ import ( grpc "google.golang.org/grpc" ) -import raftpicker "github.com/docker/swarmkit/manager/raftpicker" +import raftselector "github.com/docker/swarmkit/manager/raftselector" import codes "google.golang.org/grpc/codes" import metadata "google.golang.org/grpc/metadata" import transport "google.golang.org/grpc/transport" +import time "time" import io "io" @@ -197,11 +198,12 @@ func valueToGoStringResource(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringResource(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringResource(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -211,7 +213,7 @@ func extensionToGoStringResource(e map[int32]github_com_gogo_protobuf_proto.Exte for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } @@ -221,7 +223,7 @@ 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.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for ResourceAllocator service @@ -316,7 +318,8 @@ var _ResourceAllocator_serviceDesc = grpc.ServiceDesc{ Handler: _ResourceAllocator_DetachNetwork_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptorResource, } func (m *AttachNetworkRequest) Marshal() (data []byte, err error) { @@ -449,12 +452,11 @@ func encodeVarintResource(data []byte, offset int, v uint64) int { type raftProxyResourceAllocatorServer struct { local ResourceAllocatorServer - connSelector raftpicker.Interface - cluster raftpicker.RaftCluster + connSelector raftselector.ConnProvider ctxMods []func(context.Context) (context.Context, error) } -func NewRaftProxyResourceAllocatorServer(local ResourceAllocatorServer, connSelector raftpicker.Interface, cluster raftpicker.RaftCluster, ctxMod func(context.Context) (context.Context, error)) ResourceAllocatorServer { +func NewRaftProxyResourceAllocatorServer(local ResourceAllocatorServer, connSelector raftselector.ConnProvider, ctxMod func(context.Context) (context.Context, error)) ResourceAllocatorServer { redirectChecker := func(ctx context.Context) (context.Context, error) { s, ok := transport.StreamFromContext(ctx) if !ok { @@ -476,7 +478,6 @@ func NewRaftProxyResourceAllocatorServer(local ResourceAllocatorServer, connSele return &raftProxyResourceAllocatorServer{ local: local, - cluster: cluster, connSelector: connSelector, ctxMods: mods, } @@ -491,63 +492,90 @@ func (p *raftProxyResourceAllocatorServer) runCtxMods(ctx context.Context) (cont } return ctx, nil } +func (p *raftProxyResourceAllocatorServer) pollNewLeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ticker.C: + conn, err := p.connSelector.LeaderConn(ctx) + if err != nil { + return nil, err + } + + client := NewHealthClient(conn) + + resp, err := client.Check(ctx, &HealthCheckRequest{Service: "Raft"}) + if err != nil || resp.Status != HealthCheckResponse_SERVING { + continue + } + return conn, nil + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} func (p *raftProxyResourceAllocatorServer) AttachNetwork(ctx context.Context, r *AttachNetworkRequest) (*AttachNetworkResponse, error) { - if p.cluster.IsLeader() { - return p.local.AttachNetwork(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.AttachNetwork(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewResourceAllocatorClient(conn).AttachNetwork(ctx, r) + resp, err := NewResourceAllocatorClient(conn).AttachNetwork(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.AttachNetwork(ctx, r) + } + return nil, err + } + return NewResourceAllocatorClient(conn).AttachNetwork(modCtx, r) + } + return resp, err } func (p *raftProxyResourceAllocatorServer) DetachNetwork(ctx context.Context, r *DetachNetworkRequest) (*DetachNetworkResponse, error) { - if p.cluster.IsLeader() { - return p.local.DetachNetwork(ctx, r) - } - ctx, err := p.runCtxMods(ctx) + conn, err := p.connSelector.LeaderConn(ctx) if err != nil { - return nil, err - } - conn, err := p.connSelector.Conn() - if err != nil { - return nil, err - } - - defer func() { - if err != nil { - errStr := err.Error() - if strings.Contains(errStr, grpc.ErrClientConnClosing.Error()) || - strings.Contains(errStr, grpc.ErrClientConnTimeout.Error()) || - strings.Contains(errStr, "connection error") || - grpc.Code(err) == codes.Internal { - p.connSelector.Reset() - } + if err == raftselector.ErrIsLeader { + return p.local.DetachNetwork(ctx, r) } - }() + return nil, err + } + modCtx, err := p.runCtxMods(ctx) + if err != nil { + return nil, err + } - return NewResourceAllocatorClient(conn).DetachNetwork(ctx, r) + resp, err := NewResourceAllocatorClient(conn).DetachNetwork(modCtx, r) + if err != nil { + if !strings.Contains(err.Error(), "is closing") && !strings.Contains(err.Error(), "the connection is unavailable") && !strings.Contains(err.Error(), "connection error") { + return resp, err + } + conn, err := p.pollNewLeaderConn(ctx) + if err != nil { + if err == raftselector.ErrIsLeader { + return p.local.DetachNetwork(ctx, r) + } + return nil, err + } + return NewResourceAllocatorClient(conn).DetachNetwork(modCtx, r) + } + return resp, err } func (m *AttachNetworkRequest) Size() (n int) { @@ -1076,6 +1104,8 @@ var ( ErrIntOverflowResource = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("resource.proto", fileDescriptorResource) } + var fileDescriptorResource = []byte{ // 373 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2b, 0x4a, 0x2d, 0xce, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/snapshot.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/snapshot.pb.go index 6fdcd9707e..a6f49f95c0 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/snapshot.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/snapshot.pb.go @@ -222,11 +222,12 @@ func valueToGoStringSnapshot(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringSnapshot(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringSnapshot(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -236,7 +237,7 @@ func extensionToGoStringSnapshot(e map[int32]github_com_gogo_protobuf_proto.Exte for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *StoreSnapshot) Marshal() (data []byte, err error) { @@ -1085,6 +1086,8 @@ var ( ErrIntOverflowSnapshot = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("snapshot.proto", fileDescriptorSnapshot) } + var fileDescriptorSnapshot = []byte{ // 396 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0xbd, 0x6e, 0xdb, 0x30, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/specs.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/specs.pb.go index d5d2a00bf2..eea1d552e0 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/specs.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/specs.pb.go @@ -1047,11 +1047,12 @@ func valueToGoStringSpecs(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringSpecs(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringSpecs(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -1061,7 +1062,7 @@ func extensionToGoStringSpecs(e map[int32]github_com_gogo_protobuf_proto.Extensi for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *NodeSpec) Marshal() (data []byte, err error) { @@ -3252,50 +3253,55 @@ func (m *ContainerSpec) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpecs - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpecs - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthSpecs - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthSpecs + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 3: if wireType != 2 { @@ -4339,6 +4345,8 @@ var ( ErrIntOverflowSpecs = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("specs.proto", fileDescriptorSpecs) } + var fileDescriptorSpecs = []byte{ // 1397 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0xdb, 0xc6, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/timestamp/timestamp.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/timestamp/timestamp.pb.go index 98cf0ac222..e5567326e5 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/timestamp/timestamp.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/timestamp/timestamp.pb.go @@ -32,7 +32,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package // A Timestamp represents a point in time independent of any time zone // or calendar, represented as seconds and fractions of seconds at @@ -141,11 +143,12 @@ func valueToGoStringTimestamp(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringTimestamp(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringTimestamp(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -155,7 +158,7 @@ func extensionToGoStringTimestamp(e map[int32]github_com_gogo_protobuf_proto.Ext for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *Timestamp) Marshal() (data []byte, err error) { @@ -451,6 +454,8 @@ var ( ErrIntOverflowTimestamp = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("timestamp.proto", fileDescriptorTimestamp) } + var fileDescriptorTimestamp = []byte{ // 205 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0xc9, 0xcc, 0x4d, diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/types.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/api/types.pb.go index dbd8286cdc..bdb2e67da4 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/types.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/types.pb.go @@ -121,6 +121,8 @@ UpdateTaskStatusResponse TasksRequest TasksMessage + AssignmentsRequest + AssignmentsMessage NodeCertificateStatusRequest NodeCertificateStatusResponse IssueNodeCertificateRequest @@ -175,7 +177,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package // TaskState enumerates the states that a task progresses through within an // agent. States are designed to be monotonically increasing, such that if two @@ -408,15 +412,24 @@ type UpdateConfig_FailureAction int32 const ( UpdateConfig_PAUSE UpdateConfig_FailureAction = 0 UpdateConfig_CONTINUE UpdateConfig_FailureAction = 1 + // NOTE: Automated rollback triggered as a failure action is an + // experimental feature that is not yet exposed to the end + // user. Currently, rollbacks must be initiated manually + // through the API by setting Spec to PreviousSpec. We may + // decide to expose automatic rollback in the future based on + // user feedback, or remove this feature otherwise. + UpdateConfig_ROLLBACK UpdateConfig_FailureAction = 2 ) var UpdateConfig_FailureAction_name = map[int32]string{ 0: "PAUSE", 1: "CONTINUE", + 2: "ROLLBACK", } var UpdateConfig_FailureAction_value = map[string]int32{ "PAUSE": 0, "CONTINUE": 1, + "ROLLBACK": 2, } func (x UpdateConfig_FailureAction) String() string { @@ -429,10 +442,13 @@ func (UpdateConfig_FailureAction) EnumDescriptor() ([]byte, []int) { type UpdateStatus_UpdateState int32 const ( - UpdateStatus_UNKNOWN UpdateStatus_UpdateState = 0 - UpdateStatus_UPDATING UpdateStatus_UpdateState = 1 - UpdateStatus_PAUSED UpdateStatus_UpdateState = 2 - UpdateStatus_COMPLETED UpdateStatus_UpdateState = 3 + UpdateStatus_UNKNOWN UpdateStatus_UpdateState = 0 + UpdateStatus_UPDATING UpdateStatus_UpdateState = 1 + UpdateStatus_PAUSED UpdateStatus_UpdateState = 2 + UpdateStatus_COMPLETED UpdateStatus_UpdateState = 3 + UpdateStatus_ROLLBACK_STARTED UpdateStatus_UpdateState = 4 + UpdateStatus_ROLLBACK_PAUSED UpdateStatus_UpdateState = 5 + UpdateStatus_ROLLBACK_COMPLETED UpdateStatus_UpdateState = 6 ) var UpdateStatus_UpdateState_name = map[int32]string{ @@ -440,12 +456,18 @@ var UpdateStatus_UpdateState_name = map[int32]string{ 1: "UPDATING", 2: "PAUSED", 3: "COMPLETED", + 4: "ROLLBACK_STARTED", + 5: "ROLLBACK_PAUSED", + 6: "ROLLBACK_COMPLETED", } var UpdateStatus_UpdateState_value = map[string]int32{ - "UNKNOWN": 0, - "UPDATING": 1, - "PAUSED": 2, - "COMPLETED": 3, + "UNKNOWN": 0, + "UPDATING": 1, + "PAUSED": 2, + "COMPLETED": 3, + "ROLLBACK_STARTED": 4, + "ROLLBACK_PAUSED": 5, + "ROLLBACK_COMPLETED": 6, } func (x UpdateStatus_UpdateState) String() string { @@ -804,10 +826,34 @@ type UpdateConfig struct { // Amount of time between updates. Delay docker_swarmkit_v11.Duration `protobuf:"bytes,2,opt,name=delay" json:"delay"` // FailureAction is the action to take when an update failures. - // Currently, a failure is defined as a single updated task failing to - // reach the RUNNING state. In the future, there will be configuration - // to define what is treated as a failure (see #486 for a proposal). FailureAction UpdateConfig_FailureAction `protobuf:"varint,3,opt,name=failure_action,json=failureAction,proto3,enum=docker.swarmkit.v1.UpdateConfig_FailureAction" json:"failure_action,omitempty"` + // Monitor indicates how long to monitor a task for failure after it is + // created. If the task fails by ending up in one of the states + // REJECTED, COMPLETED, or FAILED, within Monitor from its creation, + // this counts as a failure. If it fails after Monitor, it does not + // count as a failure. If Monitor is unspecified, a default value will + // be used. + Monitor *docker_swarmkit_v11.Duration `protobuf:"bytes,4,opt,name=monitor" json:"monitor,omitempty"` + // AllowedFailureFraction is the fraction of tasks that may fail during + // an update before the failure action is invoked. Any task created by + // the current update which ends up in one of the states REJECTED, + // COMPLETED or FAILED within Monitor from its creation counts as a + // failure. The number of failures is divided by the number of tasks + // being updated, and if this fraction is greater than + // AllowedFailureFraction, the failure action is invoked. + // + // If the failure action is CONTINUE, there is no effect. + // If the failure action is PAUSE, no more tasks will be updated until + // another update is started. + // If the failure action is ROLLBACK, the orchestrator will attempt to + // roll back to the previous service spec. If the AllowedFailureFraction + // threshold is hit during the rollback, the rollback will pause. + // + // TODO(aaronl): Should there be a separate failure threshold for + // rollbacks? Should there be a failure action for rollbacks (to allow + // them to do something other than pause when the rollback encounters + // errors)? + AllowedFailureFraction float32 `protobuf:"fixed32,5,opt,name=allowed_failure_fraction,json=allowedFailureFraction,proto3" json:"allowed_failure_fraction,omitempty"` } func (m *UpdateConfig) Reset() { *m = UpdateConfig{} } @@ -817,11 +863,13 @@ func (*UpdateConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, // UpdateStatus is the status of an update in progress. type UpdateStatus struct { // State is the state of this update. It indicates whether the - // update is in progress, completed, or is paused. + // update is in progress, completed, paused, rolling back, or + // finished rolling back. State UpdateStatus_UpdateState `protobuf:"varint,1,opt,name=state,proto3,enum=docker.swarmkit.v1.UpdateStatus_UpdateState" json:"state,omitempty"` // StartedAt is the time at which the update was started. StartedAt *docker_swarmkit_v1.Timestamp `protobuf:"bytes,2,opt,name=started_at,json=startedAt" json:"started_at,omitempty"` - // CompletedAt is the time at which the update completed. + // CompletedAt is the time at which the update completed successfully, + // paused, or finished rolling back. CompletedAt *docker_swarmkit_v1.Timestamp `protobuf:"bytes,3,opt,name=completed_at,json=completedAt" json:"completed_at,omitempty"` // Message explains how the update got into its current state. For // example, if the update is paused, it will explain what is preventing @@ -1594,9 +1642,11 @@ func (m *UpdateConfig) Copy() *UpdateConfig { } o := &UpdateConfig{ - Parallelism: m.Parallelism, - Delay: *m.Delay.Copy(), - FailureAction: m.FailureAction, + Parallelism: m.Parallelism, + Delay: *m.Delay.Copy(), + FailureAction: m.FailureAction, + Monitor: m.Monitor.Copy(), + AllowedFailureFraction: m.AllowedFailureFraction, } return o @@ -2270,11 +2320,15 @@ func (this *UpdateConfig) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 7) + s := make([]string, 0, 9) s = append(s, "&api.UpdateConfig{") s = append(s, "Parallelism: "+fmt.Sprintf("%#v", this.Parallelism)+",\n") s = append(s, "Delay: "+strings.Replace(this.Delay.GoString(), `&`, ``, 1)+",\n") s = append(s, "FailureAction: "+fmt.Sprintf("%#v", this.FailureAction)+",\n") + if this.Monitor != nil { + s = append(s, "Monitor: "+fmt.Sprintf("%#v", this.Monitor)+",\n") + } + s = append(s, "AllowedFailureFraction: "+fmt.Sprintf("%#v", this.AllowedFailureFraction)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -2663,11 +2717,12 @@ func valueToGoStringTypes(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringTypes(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringTypes(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -2677,7 +2732,7 @@ func extensionToGoStringTypes(e map[int32]github_com_gogo_protobuf_proto.Extensi for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *Version) Marshal() (data []byte, err error) { @@ -3331,6 +3386,21 @@ func (m *UpdateConfig) MarshalTo(data []byte) (int, error) { i++ i = encodeVarintTypes(data, i, uint64(m.FailureAction)) } + if m.Monitor != nil { + data[i] = 0x22 + i++ + i = encodeVarintTypes(data, i, uint64(m.Monitor.Size())) + n13, err := m.Monitor.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n13 + } + if m.AllowedFailureFraction != 0 { + data[i] = 0x2d + i++ + i = encodeFixed32Types(data, i, uint32(math.Float32bits(float32(m.AllowedFailureFraction)))) + } return i, nil } @@ -3358,21 +3428,21 @@ func (m *UpdateStatus) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintTypes(data, i, uint64(m.StartedAt.Size())) - n13, err := m.StartedAt.MarshalTo(data[i:]) + n14, err := m.StartedAt.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n13 + i += n14 } if m.CompletedAt != nil { data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.CompletedAt.Size())) - n14, err := m.CompletedAt.MarshalTo(data[i:]) + n15, err := m.CompletedAt.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n14 + i += n15 } if len(m.Message) > 0 { data[i] = 0x22 @@ -3436,11 +3506,11 @@ func (m *TaskStatus) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Timestamp.Size())) - n15, err := m.Timestamp.MarshalTo(data[i:]) + n16, err := m.Timestamp.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } if m.State != 0 { data[i] = 0x10 @@ -3460,11 +3530,11 @@ func (m *TaskStatus) MarshalTo(data []byte) (int, error) { i += copy(data[i:], m.Err) } if m.RuntimeStatus != nil { - nn16, err := m.RuntimeStatus.MarshalTo(data[i:]) + nn17, err := m.RuntimeStatus.MarshalTo(data[i:]) if err != nil { return 0, err } - i += nn16 + i += nn17 } return i, nil } @@ -3475,11 +3545,11 @@ func (m *TaskStatus_Container) MarshalTo(data []byte) (int, error) { data[i] = 0x2a i++ i = encodeVarintTypes(data, i, uint64(m.Container.Size())) - n17, err := m.Container.MarshalTo(data[i:]) + n18, err := m.Container.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n17 + i += n18 } return i, nil } @@ -3694,11 +3764,11 @@ func (m *IPAMOptions) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Driver.Size())) - n18, err := m.Driver.MarshalTo(data[i:]) + n19, err := m.Driver.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n18 + i += n19 } if len(m.Configs) > 0 { for _, msg := range m.Configs { @@ -3764,11 +3834,11 @@ func (m *WeightedPeer) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Peer.Size())) - n19, err := m.Peer.MarshalTo(data[i:]) + n20, err := m.Peer.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n19 + i += n20 } if m.Weight != 0 { data[i] = 0x10 @@ -3871,11 +3941,11 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) MarshalTo(data []byte) (int, erro data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.Secret.Size())) - n20, err := m.Secret.MarshalTo(data[i:]) + n21, err := m.Secret.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n20 + i += n21 } return i, nil } @@ -3975,11 +4045,11 @@ func (m *CAConfig) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.NodeCertExpiry.Size())) - n21, err := m.NodeCertExpiry.MarshalTo(data[i:]) + n22, err := m.NodeCertExpiry.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n21 + i += n22 } if len(m.ExternalCAs) > 0 { for _, msg := range m.ExternalCAs { @@ -4038,11 +4108,11 @@ func (m *TaskDefaults) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.LogDriver.Size())) - n22, err := m.LogDriver.MarshalTo(data[i:]) + n23, err := m.LogDriver.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n22 + i += n23 } return i, nil } @@ -4066,11 +4136,11 @@ func (m *DispatcherConfig) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.HeartbeatPeriod.Size())) - n23, err := m.HeartbeatPeriod.MarshalTo(data[i:]) + n24, err := m.HeartbeatPeriod.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n23 + i += n24 } return i, nil } @@ -4217,11 +4287,11 @@ func (m *RootCA) MarshalTo(data []byte) (int, error) { data[i] = 0x22 i++ i = encodeVarintTypes(data, i, uint64(m.JoinTokens.Size())) - n24, err := m.JoinTokens.MarshalTo(data[i:]) + n25, err := m.JoinTokens.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n24 + i += n25 return i, nil } @@ -4254,11 +4324,11 @@ func (m *Certificate) MarshalTo(data []byte) (int, error) { data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.Status.Size())) - n25, err := m.Status.MarshalTo(data[i:]) + n26, err := m.Status.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n25 + i += n26 if len(m.Certificate) > 0 { data[i] = 0x22 i++ @@ -4657,6 +4727,13 @@ func (m *UpdateConfig) Size() (n int) { if m.FailureAction != 0 { n += 1 + sovTypes(uint64(m.FailureAction)) } + if m.Monitor != nil { + l = m.Monitor.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.AllowedFailureFraction != 0 { + n += 5 + } return n } @@ -5347,6 +5424,8 @@ func (this *UpdateConfig) String() string { `Parallelism:` + fmt.Sprintf("%v", this.Parallelism) + `,`, `Delay:` + strings.Replace(strings.Replace(this.Delay.String(), "Duration", "docker_swarmkit_v11.Duration", 1), `&`, ``, 1) + `,`, `FailureAction:` + fmt.Sprintf("%v", this.FailureAction) + `,`, + `Monitor:` + strings.Replace(fmt.Sprintf("%v", this.Monitor), "Duration", "docker_swarmkit_v11.Duration", 1) + `,`, + `AllowedFailureFraction:` + fmt.Sprintf("%v", this.AllowedFailureFraction) + `,`, `}`, }, "") return s @@ -5899,50 +5978,55 @@ func (m *Annotations) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex default: iNdEx = preIndex @@ -6509,50 +6593,55 @@ func (m *EngineDescription) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 3: if wireType != 2 { @@ -7509,50 +7598,55 @@ func (m *Mount_VolumeOptions) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Labels == nil { m.Labels = make(map[string]string) } - m.Labels[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Labels[mapkey] = mapvalue + } else { + var mapvalue string + m.Labels[mapkey] = mapvalue + } iNdEx = postIndex case 3: if wireType != 2 { @@ -7947,6 +8041,53 @@ func (m *UpdateConfig) Unmarshal(data []byte) error { break } } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Monitor", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Monitor == nil { + m.Monitor = &docker_swarmkit_v11.Duration{} + } + if err := m.Monitor.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedFailureFraction", wireType) + } + var v uint32 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + iNdEx += 4 + v = uint32(data[iNdEx-4]) + v |= uint32(data[iNdEx-3]) << 8 + v |= uint32(data[iNdEx-2]) << 16 + v |= uint32(data[iNdEx-1]) << 24 + m.AllowedFailureFraction = float32(math.Float32frombits(v)) default: iNdEx = preIndex skippy, err := skipTypes(data[iNdEx:]) @@ -8779,50 +8920,55 @@ func (m *IPAMConfig) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Reserved == nil { m.Reserved = make(map[string]string) } - m.Reserved[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Reserved[mapkey] = mapvalue + } else { + var mapvalue string + m.Reserved[mapkey] = mapvalue + } iNdEx = postIndex default: iNdEx = preIndex @@ -9105,50 +9251,55 @@ func (m *Driver) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Options == nil { m.Options = make(map[string]string) } - m.Options[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Options[mapkey] = mapvalue + } else { + var mapvalue string + m.Options[mapkey] = mapvalue + } iNdEx = postIndex default: iNdEx = preIndex @@ -10049,50 +10200,55 @@ func (m *ExternalCA) Unmarshal(data []byte) error { } mapkey := string(data[iNdEx:postStringIndexmapkey]) iNdEx = postStringIndexmapkey - var valuekey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(data[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue if m.Options == nil { m.Options = make(map[string]string) } - m.Options[mapkey] = mapvalue + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(data[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Options[mapkey] = mapvalue + } else { + var mapvalue string + m.Options[mapkey] = mapvalue + } iNdEx = postIndex default: iNdEx = preIndex @@ -11547,222 +11703,228 @@ var ( ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) } + var fileDescriptorTypes = []byte{ - // 3442 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0x4d, 0x6c, 0x1b, 0x49, - 0x76, 0x16, 0x7f, 0x45, 0x3e, 0x52, 0x72, 0xbb, 0xec, 0xf5, 0xc8, 0x1c, 0x8f, 0xc4, 0x69, 0x8f, - 0x77, 0xbc, 0xb3, 0x13, 0xce, 0x8c, 0x66, 0x13, 0x78, 0xc7, 0xc9, 0xce, 0xb4, 0x48, 0xca, 0xe6, - 0x5a, 0xa2, 0x88, 0x22, 0x69, 0x63, 0x10, 0x20, 0x44, 0xa9, 0xbb, 0x44, 0xf6, 0xa8, 0xd9, 0xc5, - 0x74, 0x17, 0x25, 0x33, 0x41, 0x00, 0x27, 0x97, 0x04, 0x3a, 0xe5, 0x1e, 0x08, 0x8b, 0x20, 0x41, - 0x6e, 0x39, 0xe4, 0x14, 0x20, 0x27, 0x1f, 0xe7, 0xb8, 0x41, 0x80, 0x60, 0x91, 0x00, 0x42, 0x46, - 0x39, 0xe6, 0xb2, 0x40, 0x0e, 0x7b, 0x48, 0x0e, 0x41, 0xfd, 0x74, 0xf3, 0xc7, 0xb4, 0xc6, 0x93, - 0xdd, 0x13, 0xbb, 0x5e, 0x7d, 0xef, 0xd5, 0xab, 0xaa, 0x57, 0xaf, 0xbe, 0x57, 0x84, 0x02, 0x9f, - 0x8c, 0x68, 0x58, 0x19, 0x05, 0x8c, 0x33, 0x84, 0x1c, 0x66, 0x1f, 0xd3, 0xa0, 0x12, 0x9e, 0x92, - 0x60, 0x78, 0xec, 0xf2, 0xca, 0xc9, 0x27, 0xa5, 0xdb, 0xdc, 0x1d, 0xd2, 0x90, 0x93, 0xe1, 0xe8, - 0xa3, 0xf8, 0x4b, 0xc1, 0x4b, 0x6f, 0x39, 0xe3, 0x80, 0x70, 0x97, 0xf9, 0x1f, 0x45, 0x1f, 0xba, - 0xe3, 0x66, 0x9f, 0xf5, 0x99, 0xfc, 0xfc, 0x48, 0x7c, 0x29, 0xa9, 0xb9, 0x05, 0xab, 0x4f, 0x69, - 0x10, 0xba, 0xcc, 0x47, 0x37, 0x21, 0xe3, 0xfa, 0x0e, 0x7d, 0xbe, 0x91, 0x28, 0x27, 0xee, 0xa7, - 0xb1, 0x6a, 0x98, 0x7f, 0x9d, 0x80, 0x82, 0xe5, 0xfb, 0x8c, 0x4b, 0x5b, 0x21, 0x42, 0x90, 0xf6, - 0xc9, 0x90, 0x4a, 0x50, 0x1e, 0xcb, 0x6f, 0x54, 0x85, 0xac, 0x47, 0x0e, 0xa9, 0x17, 0x6e, 0x24, - 0xcb, 0xa9, 0xfb, 0x85, 0xed, 0x1f, 0x56, 0x5e, 0xf5, 0xb9, 0x32, 0x63, 0xa4, 0xb2, 0x27, 0xd1, - 0x75, 0x9f, 0x07, 0x13, 0xac, 0x55, 0x4b, 0x3f, 0x86, 0xc2, 0x8c, 0x18, 0x19, 0x90, 0x3a, 0xa6, - 0x13, 0x3d, 0x8c, 0xf8, 0x14, 0xfe, 0x9d, 0x10, 0x6f, 0x4c, 0x37, 0x92, 0x52, 0xa6, 0x1a, 0x9f, - 0x25, 0x1f, 0x24, 0xcc, 0x2f, 0x21, 0x8f, 0x69, 0xc8, 0xc6, 0x81, 0x4d, 0x43, 0xf4, 0x03, 0xc8, - 0xfb, 0xc4, 0x67, 0x3d, 0x7b, 0x34, 0x0e, 0xa5, 0x7a, 0x6a, 0xa7, 0x78, 0x79, 0xb1, 0x95, 0x6b, - 0x12, 0x9f, 0x55, 0x5b, 0xdd, 0x10, 0xe7, 0x44, 0x77, 0x75, 0x34, 0x0e, 0xd1, 0xbb, 0x50, 0x1c, - 0xd2, 0x21, 0x0b, 0x26, 0xbd, 0xc3, 0x09, 0xa7, 0xa1, 0x34, 0x9c, 0xc2, 0x05, 0x25, 0xdb, 0x11, - 0x22, 0xf3, 0x2f, 0x13, 0x70, 0x33, 0xb2, 0x8d, 0xe9, 0x1f, 0x8e, 0xdd, 0x80, 0x0e, 0xa9, 0xcf, - 0x43, 0xf4, 0xdb, 0x90, 0xf5, 0xdc, 0xa1, 0xcb, 0xd5, 0x18, 0x85, 0xed, 0x77, 0x96, 0xcd, 0x39, - 0xf6, 0x0a, 0x6b, 0x30, 0xb2, 0xa0, 0x18, 0xd0, 0x90, 0x06, 0x27, 0x6a, 0x25, 0xe4, 0x90, 0xdf, - 0xaa, 0x3c, 0xa7, 0x62, 0xee, 0x42, 0xae, 0xe5, 0x11, 0x7e, 0xc4, 0x82, 0x21, 0x32, 0xa1, 0x48, - 0x02, 0x7b, 0xe0, 0x72, 0x6a, 0xf3, 0x71, 0x10, 0xed, 0xca, 0x9c, 0x0c, 0xdd, 0x82, 0x24, 0x53, - 0x03, 0xe5, 0x77, 0xb2, 0x97, 0x17, 0x5b, 0xc9, 0x83, 0x36, 0x4e, 0xb2, 0xd0, 0x7c, 0x08, 0xd7, - 0x5b, 0xde, 0xb8, 0xef, 0xfa, 0x35, 0x1a, 0xda, 0x81, 0x3b, 0x12, 0xd6, 0xc5, 0xf6, 0x8a, 0xe0, - 0x8b, 0xb6, 0x57, 0x7c, 0xc7, 0x5b, 0x9e, 0x9c, 0x6e, 0xb9, 0xf9, 0xe7, 0x49, 0xb8, 0x5e, 0xf7, - 0xfb, 0xae, 0x4f, 0x67, 0xb5, 0xef, 0xc1, 0x3a, 0x95, 0xc2, 0xde, 0x89, 0x0a, 0x2a, 0x6d, 0x67, - 0x4d, 0x49, 0xa3, 0x48, 0x6b, 0x2c, 0xc4, 0xcb, 0x27, 0xcb, 0xa6, 0xff, 0x8a, 0xf5, 0x65, 0x51, - 0x83, 0xea, 0xb0, 0x3a, 0x92, 0x93, 0x08, 0x37, 0x52, 0xd2, 0xd6, 0xbd, 0x65, 0xb6, 0x5e, 0x99, - 0xe7, 0x4e, 0xfa, 0xeb, 0x8b, 0xad, 0x15, 0x1c, 0xe9, 0xfe, 0x3a, 0xc1, 0xf7, 0x9f, 0x09, 0xb8, - 0xd6, 0x64, 0xce, 0xdc, 0x3a, 0x94, 0x20, 0x37, 0x60, 0x21, 0x9f, 0x39, 0x28, 0x71, 0x1b, 0x3d, - 0x80, 0xdc, 0x48, 0x6f, 0x9f, 0xde, 0xfd, 0x3b, 0xcb, 0x5d, 0x56, 0x18, 0x1c, 0xa3, 0xd1, 0x43, - 0xc8, 0x07, 0x51, 0x4c, 0x6c, 0xa4, 0xde, 0x24, 0x70, 0xa6, 0x78, 0xf4, 0x7b, 0x90, 0x55, 0x9b, - 0xb0, 0x91, 0x96, 0x9a, 0xf7, 0xde, 0x68, 0xcd, 0xb1, 0x56, 0x32, 0x7f, 0x91, 0x00, 0x03, 0x93, - 0x23, 0xbe, 0x4f, 0x87, 0x87, 0x34, 0x68, 0x73, 0xc2, 0xc7, 0x21, 0xba, 0x05, 0x59, 0x8f, 0x12, - 0x87, 0x06, 0x72, 0x92, 0x39, 0xac, 0x5b, 0xa8, 0x2b, 0x82, 0x9c, 0xd8, 0x03, 0x72, 0xe8, 0x7a, - 0x2e, 0x9f, 0xc8, 0x69, 0xae, 0x2f, 0xdf, 0xe5, 0x45, 0x9b, 0x15, 0x3c, 0xa3, 0x88, 0xe7, 0xcc, - 0xa0, 0x0d, 0x58, 0x1d, 0xd2, 0x30, 0x24, 0x7d, 0x2a, 0x67, 0x9f, 0xc7, 0x51, 0xd3, 0x7c, 0x08, - 0xc5, 0x59, 0x3d, 0x54, 0x80, 0xd5, 0x6e, 0xf3, 0x49, 0xf3, 0xe0, 0x59, 0xd3, 0x58, 0x41, 0xd7, - 0xa0, 0xd0, 0x6d, 0xe2, 0xba, 0x55, 0x7d, 0x6c, 0xed, 0xec, 0xd5, 0x8d, 0x04, 0x5a, 0x83, 0xfc, - 0xb4, 0x99, 0x34, 0x7f, 0x96, 0x00, 0x10, 0x1b, 0xa8, 0x27, 0xf5, 0x19, 0x64, 0x42, 0x4e, 0xb8, - 0xda, 0xb8, 0xf5, 0xed, 0xf7, 0x96, 0x79, 0x3d, 0x85, 0x57, 0xc4, 0x0f, 0xc5, 0x4a, 0x65, 0xd6, - 0xc3, 0xe4, 0xa2, 0x87, 0x19, 0x89, 0x9c, 0x77, 0x2d, 0x07, 0xe9, 0x9a, 0xf8, 0x4a, 0xa0, 0x3c, - 0x64, 0x70, 0xdd, 0xaa, 0x7d, 0x69, 0x24, 0x91, 0x01, 0xc5, 0x5a, 0xa3, 0x5d, 0x3d, 0x68, 0x36, - 0xeb, 0xd5, 0x4e, 0xbd, 0x66, 0xa4, 0xcc, 0x7b, 0x90, 0x69, 0x0c, 0x49, 0x9f, 0xa2, 0x3b, 0x22, - 0x02, 0x8e, 0x68, 0x40, 0x7d, 0x3b, 0x0a, 0xac, 0xa9, 0xc0, 0xfc, 0x79, 0x1e, 0x32, 0xfb, 0x6c, - 0xec, 0x73, 0xb4, 0x3d, 0x73, 0x8a, 0xd7, 0xb7, 0x37, 0x97, 0x4d, 0x41, 0x02, 0x2b, 0x9d, 0xc9, - 0x88, 0xea, 0x53, 0x7e, 0x0b, 0xb2, 0x2a, 0x56, 0xb4, 0xeb, 0xba, 0x25, 0xe4, 0x9c, 0x04, 0x7d, - 0xca, 0xf5, 0xa2, 0xeb, 0x16, 0xba, 0x0f, 0xb9, 0x80, 0x12, 0x87, 0xf9, 0xde, 0x44, 0x86, 0x54, - 0x4e, 0xa5, 0x59, 0x4c, 0x89, 0x73, 0xe0, 0x7b, 0x13, 0x1c, 0xf7, 0xa2, 0xc7, 0x50, 0x3c, 0x74, - 0x7d, 0xa7, 0xc7, 0x46, 0x2a, 0xe7, 0x65, 0x5e, 0x1f, 0x80, 0xca, 0xab, 0x1d, 0xd7, 0x77, 0x0e, - 0x14, 0x18, 0x17, 0x0e, 0xa7, 0x0d, 0xd4, 0x84, 0xf5, 0x13, 0xe6, 0x8d, 0x87, 0x34, 0xb6, 0x95, - 0x95, 0xb6, 0xde, 0x7f, 0xbd, 0xad, 0xa7, 0x12, 0x1f, 0x59, 0x5b, 0x3b, 0x99, 0x6d, 0xa2, 0x27, - 0xb0, 0xc6, 0x87, 0xa3, 0xa3, 0x30, 0x36, 0xb7, 0x2a, 0xcd, 0x7d, 0xff, 0x8a, 0x05, 0x13, 0xf0, - 0xc8, 0x5a, 0x91, 0xcf, 0xb4, 0x4a, 0x7f, 0x96, 0x82, 0xc2, 0x8c, 0xe7, 0xa8, 0x0d, 0x85, 0x51, - 0xc0, 0x46, 0xa4, 0x2f, 0xf3, 0xb6, 0xde, 0x8b, 0x4f, 0xde, 0x68, 0xd6, 0x95, 0xd6, 0x54, 0x11, - 0xcf, 0x5a, 0x31, 0xcf, 0x93, 0x50, 0x98, 0xe9, 0x44, 0x1f, 0x40, 0x0e, 0xb7, 0x70, 0xe3, 0xa9, - 0xd5, 0xa9, 0x1b, 0x2b, 0xa5, 0x3b, 0x67, 0xe7, 0xe5, 0x0d, 0x69, 0x6d, 0xd6, 0x40, 0x2b, 0x70, - 0x4f, 0x44, 0xe8, 0xdd, 0x87, 0xd5, 0x08, 0x9a, 0x28, 0xbd, 0x7d, 0x76, 0x5e, 0x7e, 0x6b, 0x11, - 0x3a, 0x83, 0xc4, 0xed, 0xc7, 0x16, 0xae, 0xd7, 0x8c, 0xe4, 0x72, 0x24, 0x6e, 0x0f, 0x48, 0x40, - 0x1d, 0xf4, 0x7d, 0xc8, 0x6a, 0x60, 0xaa, 0x54, 0x3a, 0x3b, 0x2f, 0xdf, 0x5a, 0x04, 0x4e, 0x71, - 0xb8, 0xbd, 0x67, 0x3d, 0xad, 0x1b, 0xe9, 0xe5, 0x38, 0xdc, 0xf6, 0xc8, 0x09, 0x45, 0xef, 0x41, - 0x46, 0xc1, 0x32, 0xa5, 0xdb, 0x67, 0xe7, 0xe5, 0xef, 0xbd, 0x62, 0x4e, 0xa0, 0x4a, 0x1b, 0x7f, - 0xf1, 0x37, 0x9b, 0x2b, 0xff, 0xf4, 0xb7, 0x9b, 0xc6, 0x62, 0x77, 0xe9, 0x7f, 0x13, 0xb0, 0x36, - 0xb7, 0xe5, 0xc8, 0x84, 0xac, 0xcf, 0x6c, 0x36, 0x52, 0xe9, 0x3c, 0xb7, 0x03, 0x97, 0x17, 0x5b, - 0xd9, 0x26, 0xab, 0xb2, 0xd1, 0x04, 0xeb, 0x1e, 0xf4, 0x64, 0xe1, 0x42, 0xfa, 0xf4, 0x0d, 0xe3, - 0x69, 0xe9, 0x95, 0xf4, 0x39, 0xac, 0x39, 0x81, 0x7b, 0x42, 0x83, 0x9e, 0xcd, 0xfc, 0x23, 0xb7, - 0xaf, 0x53, 0x75, 0x69, 0x99, 0xcd, 0x9a, 0x04, 0xe2, 0xa2, 0x52, 0xa8, 0x4a, 0xfc, 0xaf, 0x71, - 0x19, 0x95, 0x9e, 0x42, 0x71, 0x36, 0x42, 0xd1, 0x3b, 0x00, 0xa1, 0xfb, 0x47, 0x54, 0xf3, 0x1b, - 0xc9, 0x86, 0x70, 0x5e, 0x48, 0x24, 0xbb, 0x41, 0xef, 0x43, 0x7a, 0xc8, 0x1c, 0x65, 0x27, 0xb3, - 0x73, 0x43, 0xdc, 0x89, 0xff, 0x76, 0xb1, 0x55, 0x60, 0x61, 0x65, 0xd7, 0xf5, 0xe8, 0x3e, 0x73, - 0x28, 0x96, 0x00, 0xf3, 0x04, 0xd2, 0x22, 0x55, 0xa0, 0xb7, 0x21, 0xbd, 0xd3, 0x68, 0xd6, 0x8c, - 0x95, 0xd2, 0xf5, 0xb3, 0xf3, 0xf2, 0x9a, 0x5c, 0x12, 0xd1, 0x21, 0x62, 0x17, 0x6d, 0x41, 0xf6, - 0xe9, 0xc1, 0x5e, 0x77, 0x5f, 0x84, 0xd7, 0x8d, 0xb3, 0xf3, 0xf2, 0xb5, 0xb8, 0x5b, 0x2d, 0x1a, - 0x7a, 0x07, 0x32, 0x9d, 0xfd, 0xd6, 0x6e, 0xdb, 0x48, 0x96, 0xd0, 0xd9, 0x79, 0x79, 0x3d, 0xee, - 0x97, 0x3e, 0x97, 0xae, 0xeb, 0x5d, 0xcd, 0xc7, 0x72, 0xf3, 0x7f, 0x92, 0xb0, 0x86, 0x05, 0xbf, - 0x0d, 0x78, 0x8b, 0x79, 0xae, 0x3d, 0x41, 0x2d, 0xc8, 0xdb, 0xcc, 0x77, 0xdc, 0x99, 0x33, 0xb5, - 0xfd, 0x9a, 0x4b, 0x70, 0xaa, 0x15, 0xb5, 0xaa, 0x91, 0x26, 0x9e, 0x1a, 0x41, 0xdb, 0x90, 0x71, - 0xa8, 0x47, 0x26, 0x57, 0xdd, 0xc6, 0x35, 0xcd, 0xa5, 0xb1, 0x82, 0x4a, 0xe6, 0x48, 0x9e, 0xf7, - 0x08, 0xe7, 0x74, 0x38, 0xe2, 0xea, 0x36, 0x4e, 0xe3, 0xc2, 0x90, 0x3c, 0xb7, 0xb4, 0x08, 0xfd, - 0x08, 0xb2, 0xa7, 0xae, 0xef, 0xb0, 0x53, 0x7d, 0xe1, 0x5e, 0x6d, 0x57, 0x63, 0xcd, 0x33, 0x71, - 0xcf, 0x2e, 0x38, 0x2b, 0x56, 0xbd, 0x79, 0xd0, 0xac, 0x47, 0xab, 0xae, 0xfb, 0x0f, 0xfc, 0x26, - 0xf3, 0xc5, 0x89, 0x81, 0x83, 0x66, 0x6f, 0xd7, 0x6a, 0xec, 0x75, 0xb1, 0x58, 0xf9, 0x9b, 0x67, - 0xe7, 0x65, 0x23, 0x86, 0xec, 0x12, 0xd7, 0x13, 0x24, 0xf0, 0x36, 0xa4, 0xac, 0xe6, 0x97, 0x46, - 0xb2, 0x64, 0x9c, 0x9d, 0x97, 0x8b, 0x71, 0xb7, 0xe5, 0x4f, 0xa6, 0x87, 0x69, 0x71, 0x5c, 0xf3, - 0xbf, 0x12, 0x50, 0xec, 0x8e, 0x1c, 0xc2, 0xa9, 0x8a, 0x4c, 0x54, 0x86, 0xc2, 0x88, 0x04, 0xc4, - 0xf3, 0xa8, 0xe7, 0x86, 0x43, 0x5d, 0x28, 0xcc, 0x8a, 0xd0, 0x83, 0xef, 0xb0, 0x98, 0x9a, 0x84, - 0xe9, 0x25, 0xed, 0xc2, 0xfa, 0x91, 0x72, 0xb6, 0x47, 0x6c, 0xb9, 0xbb, 0x29, 0xb9, 0xbb, 0x95, - 0x65, 0x26, 0x66, 0xbd, 0xaa, 0xe8, 0x39, 0x5a, 0x52, 0x0b, 0xaf, 0x1d, 0xcd, 0x36, 0xcd, 0xfb, - 0xb0, 0x36, 0xd7, 0x2f, 0x6e, 0xda, 0x96, 0xd5, 0x6d, 0xd7, 0x8d, 0x15, 0x54, 0x84, 0x5c, 0xf5, - 0xa0, 0xd9, 0x69, 0x34, 0xbb, 0x75, 0x23, 0x61, 0xfe, 0x43, 0x32, 0x9a, 0xad, 0x66, 0x02, 0x3b, - 0xf3, 0x4c, 0xe0, 0xc3, 0xd7, 0x3b, 0xa2, 0xb9, 0xc0, 0xb4, 0x11, 0x33, 0x82, 0xdf, 0x05, 0x90, - 0x8b, 0x4a, 0x9d, 0x1e, 0xe1, 0x57, 0xb1, 0xfd, 0x4e, 0x54, 0xc7, 0xe1, 0xbc, 0x56, 0xb0, 0x38, - 0xfa, 0x02, 0x8a, 0x36, 0x1b, 0x8e, 0x3c, 0xaa, 0xf5, 0x53, 0x6f, 0xa2, 0x5f, 0x88, 0x55, 0x2c, - 0x3e, 0xcb, 0x48, 0xd2, 0xf3, 0x8c, 0xa4, 0x0a, 0x85, 0x19, 0x7f, 0xe7, 0x79, 0x49, 0x11, 0x72, - 0xdd, 0x56, 0xcd, 0xea, 0x34, 0x9a, 0x8f, 0x8c, 0x04, 0x02, 0xc8, 0xca, 0x15, 0xab, 0x19, 0x49, - 0xc1, 0x9d, 0xaa, 0x07, 0xfb, 0xad, 0xbd, 0xba, 0x62, 0x26, 0x7f, 0x02, 0xd7, 0xaa, 0xcc, 0xe7, - 0xc4, 0xf5, 0x63, 0x52, 0xb8, 0x2d, 0x7c, 0xd6, 0xa2, 0x9e, 0xeb, 0xa8, 0xbc, 0xb5, 0x73, 0xed, - 0xf2, 0x62, 0xab, 0x10, 0x43, 0x1b, 0x35, 0xe1, 0x65, 0xd4, 0x70, 0x44, 0x74, 0x8e, 0x5c, 0x47, - 0xa7, 0xa1, 0xd5, 0xcb, 0x8b, 0xad, 0x54, 0xab, 0x51, 0xc3, 0x42, 0x86, 0xde, 0x86, 0x3c, 0x7d, - 0xee, 0xf2, 0x9e, 0x2d, 0xf2, 0x94, 0x98, 0x7f, 0x06, 0xe7, 0x84, 0xa0, 0x2a, 0xd2, 0xd2, 0x9f, - 0x26, 0x01, 0x3a, 0x24, 0x3c, 0xd6, 0x43, 0x3f, 0x84, 0x7c, 0x5c, 0x0e, 0x5f, 0x55, 0x96, 0xcd, - 0xac, 0x75, 0x8c, 0x47, 0x9f, 0x46, 0xbb, 0xad, 0xd8, 0xea, 0x72, 0x45, 0x3d, 0xd6, 0x32, 0xc2, - 0x37, 0x4f, 0x49, 0x45, 0xd6, 0xa6, 0x41, 0xa0, 0x17, 0x5d, 0x7c, 0xa2, 0xaa, 0xcc, 0x5c, 0x6a, - 0xce, 0x9a, 0x03, 0xdd, 0x5d, 0x36, 0xc8, 0xc2, 0x82, 0x3e, 0x5e, 0xc1, 0x53, 0xbd, 0x1d, 0x03, - 0xd6, 0x83, 0xb1, 0x2f, 0xbc, 0xee, 0x85, 0xb2, 0xdb, 0x74, 0xe1, 0xad, 0x26, 0xe5, 0xa7, 0x2c, - 0x38, 0xb6, 0x38, 0x27, 0xf6, 0x40, 0x94, 0xa7, 0xfa, 0xb8, 0x4e, 0xa9, 0x5b, 0x62, 0x8e, 0xba, - 0x6d, 0xc0, 0x2a, 0xf1, 0x5c, 0x12, 0x52, 0x75, 0xdf, 0xe5, 0x71, 0xd4, 0x14, 0x04, 0x93, 0x38, - 0x4e, 0x40, 0xc3, 0x90, 0xaa, 0x82, 0x2a, 0x8f, 0xa7, 0x02, 0xf3, 0x5f, 0x92, 0x00, 0x8d, 0x96, - 0xb5, 0xaf, 0xcd, 0xd7, 0x20, 0x7b, 0x44, 0x86, 0xae, 0x37, 0xb9, 0xea, 0x80, 0x4c, 0xf1, 0x15, - 0x4b, 0x19, 0xda, 0x95, 0x3a, 0x58, 0xeb, 0x4a, 0xde, 0x39, 0x3e, 0xf4, 0x29, 0x8f, 0x79, 0xa7, - 0x6c, 0x89, 0x4b, 0x2e, 0x20, 0x7e, 0xbc, 0xb0, 0xaa, 0x21, 0x5c, 0xef, 0x13, 0x4e, 0x4f, 0xc9, - 0x24, 0x8a, 0x67, 0xdd, 0x44, 0x8f, 0x05, 0x1f, 0x15, 0x65, 0x32, 0x75, 0x36, 0x32, 0xf2, 0x16, - 0xff, 0x36, 0x7f, 0xb0, 0x86, 0xab, 0xeb, 0x3b, 0xd6, 0x2e, 0x3d, 0x94, 0x77, 0xce, 0xb4, 0xeb, - 0x3b, 0x95, 0x83, 0x1f, 0xc3, 0xda, 0xdc, 0x3c, 0x5f, 0x21, 0xfc, 0x8d, 0xd6, 0xd3, 0x1f, 0x19, - 0x69, 0xfd, 0xf5, 0x3b, 0x46, 0xd6, 0xfc, 0xef, 0x04, 0x40, 0x8b, 0x05, 0xd1, 0xa6, 0x2d, 0x7f, - 0x60, 0xc9, 0xc9, 0xe7, 0x1a, 0x9b, 0x79, 0x3a, 0x3c, 0x97, 0x32, 0xde, 0xa9, 0x15, 0x41, 0x20, - 0x25, 0x1c, 0xc7, 0x8a, 0x68, 0x0b, 0x0a, 0x6a, 0xff, 0x7b, 0x23, 0x16, 0xa8, 0x5c, 0xb2, 0x86, - 0x41, 0x89, 0x84, 0xa6, 0xa8, 0xde, 0x47, 0xe3, 0x43, 0xcf, 0x0d, 0x07, 0xd4, 0x51, 0x98, 0xb4, - 0xc4, 0xac, 0xc5, 0x52, 0x01, 0x33, 0x6b, 0x90, 0x8b, 0xac, 0xa3, 0x0d, 0x48, 0x75, 0xaa, 0x2d, - 0x63, 0xa5, 0x74, 0xed, 0xec, 0xbc, 0x5c, 0x88, 0xc4, 0x9d, 0x6a, 0x4b, 0xf4, 0x74, 0x6b, 0x2d, - 0x23, 0x31, 0xdf, 0xd3, 0xad, 0xb5, 0x4a, 0x69, 0x71, 0xdf, 0x98, 0x7f, 0x95, 0x80, 0xac, 0x62, - 0x3f, 0x4b, 0x67, 0x6c, 0xc1, 0x6a, 0xc4, 0xc9, 0x15, 0x25, 0x7b, 0xff, 0xf5, 0xf4, 0xa9, 0xa2, - 0xd9, 0x8e, 0xda, 0xc7, 0x48, 0xaf, 0xf4, 0x19, 0x14, 0x67, 0x3b, 0xbe, 0xd3, 0x2e, 0xfe, 0x31, - 0x14, 0x44, 0xa0, 0x44, 0x34, 0x6a, 0x1b, 0xb2, 0x8a, 0xa1, 0xe9, 0xac, 0x72, 0x15, 0x97, 0xd3, - 0x48, 0xf4, 0x00, 0x56, 0x15, 0xff, 0x8b, 0x5e, 0x26, 0x36, 0xaf, 0x0e, 0x47, 0x1c, 0xc1, 0xcd, - 0xcf, 0x21, 0xdd, 0xa2, 0x34, 0x40, 0x77, 0x61, 0xd5, 0x67, 0x0e, 0x9d, 0x26, 0x51, 0x4d, 0x5d, - 0x1d, 0xda, 0xa8, 0x09, 0xea, 0xea, 0xd0, 0x86, 0x23, 0x16, 0x4f, 0x1c, 0xd0, 0xe8, 0x71, 0x46, - 0x7c, 0x9b, 0x1d, 0x28, 0x3e, 0xa3, 0x6e, 0x7f, 0xc0, 0xa9, 0x23, 0x0d, 0x7d, 0x08, 0xe9, 0x11, - 0x8d, 0x9d, 0xdf, 0x58, 0x1a, 0x3a, 0x94, 0x06, 0x58, 0xa2, 0xc4, 0x81, 0x3c, 0x95, 0xda, 0xfa, - 0x3d, 0x4c, 0xb7, 0xcc, 0xbf, 0x4f, 0xc2, 0x7a, 0x23, 0x0c, 0xc7, 0xc4, 0xb7, 0xa3, 0x1b, 0xf2, - 0x27, 0xf3, 0x37, 0xe4, 0xfd, 0xa5, 0x33, 0x9c, 0x53, 0x99, 0xaf, 0x97, 0x75, 0x92, 0x4c, 0xc6, - 0x49, 0xd2, 0xfc, 0x3a, 0x11, 0x15, 0xca, 0xf7, 0x66, 0xce, 0x4d, 0x69, 0xe3, 0xec, 0xbc, 0x7c, - 0x73, 0xd6, 0x12, 0xed, 0xfa, 0xc7, 0x3e, 0x3b, 0xf5, 0xd1, 0xbb, 0xa2, 0x70, 0x6e, 0xd6, 0x9f, - 0x19, 0x89, 0xd2, 0xad, 0xb3, 0xf3, 0x32, 0x9a, 0x03, 0x61, 0xea, 0xd3, 0x53, 0x61, 0xa9, 0x55, - 0x6f, 0xd6, 0xc4, 0x65, 0x96, 0x5c, 0x62, 0xa9, 0x45, 0x7d, 0xc7, 0xf5, 0xfb, 0xe8, 0x2e, 0x64, - 0x1b, 0xed, 0x76, 0x57, 0x96, 0x32, 0x6f, 0x9d, 0x9d, 0x97, 0x6f, 0xcc, 0xa1, 0x44, 0x83, 0x3a, - 0x02, 0x24, 0xa8, 0x56, 0xbd, 0x66, 0xa4, 0x97, 0x80, 0x04, 0xd3, 0xa0, 0x8e, 0x8e, 0xf0, 0x7f, - 0x4f, 0x82, 0x61, 0xd9, 0x36, 0x1d, 0x71, 0xd1, 0xaf, 0xe9, 0x6b, 0x07, 0x72, 0x23, 0xf1, 0xe5, - 0x4a, 0x3a, 0x2e, 0xc2, 0xe2, 0xc1, 0xd2, 0xc7, 0xd2, 0x05, 0xbd, 0x0a, 0x66, 0x1e, 0xb5, 0x9c, - 0xa1, 0x1b, 0x86, 0xa2, 0x4c, 0x93, 0x32, 0x1c, 0x5b, 0x2a, 0xfd, 0x32, 0x01, 0x37, 0x96, 0x20, - 0xd0, 0xc7, 0x90, 0x0e, 0x98, 0x17, 0x6d, 0xcf, 0x9d, 0xd7, 0x3d, 0x65, 0x08, 0x55, 0x2c, 0x91, - 0x68, 0x13, 0x80, 0x8c, 0x39, 0x23, 0x72, 0x7c, 0xb9, 0x31, 0x39, 0x3c, 0x23, 0x41, 0xcf, 0x20, - 0x1b, 0x52, 0x3b, 0xa0, 0x11, 0x17, 0xf9, 0xfc, 0xff, 0xeb, 0x7d, 0xa5, 0x2d, 0xcd, 0x60, 0x6d, - 0xae, 0x54, 0x81, 0xac, 0x92, 0x88, 0x88, 0x76, 0x08, 0x27, 0xd2, 0xe9, 0x22, 0x96, 0xdf, 0x22, - 0x50, 0x88, 0xd7, 0x8f, 0x02, 0x85, 0x78, 0x7d, 0xf3, 0x67, 0x49, 0x80, 0xfa, 0x73, 0x4e, 0x03, - 0x9f, 0x78, 0x55, 0x0b, 0xd5, 0x67, 0x32, 0xa4, 0x9a, 0xed, 0x0f, 0x96, 0x3e, 0x70, 0xc5, 0x1a, - 0x95, 0xaa, 0xb5, 0x24, 0x47, 0xde, 0x86, 0xd4, 0x38, 0xf0, 0xf4, 0x63, 0xa9, 0x24, 0x22, 0x5d, - 0xbc, 0x87, 0x85, 0x0c, 0xd5, 0xa7, 0x19, 0x29, 0xf5, 0xfa, 0x57, 0xee, 0x99, 0x01, 0x7e, 0xf3, - 0x59, 0xe9, 0x43, 0x80, 0xa9, 0xd7, 0x68, 0x13, 0x32, 0xd5, 0xdd, 0x76, 0x7b, 0xcf, 0x58, 0x51, - 0xd5, 0xd6, 0xb4, 0x4b, 0x8a, 0xcd, 0xbf, 0x4b, 0x40, 0xae, 0x6a, 0xe9, 0x5b, 0x65, 0x17, 0x0c, - 0x99, 0x4b, 0x6c, 0x1a, 0xf0, 0x1e, 0x7d, 0x3e, 0x72, 0x83, 0x89, 0x4e, 0x07, 0x57, 0xd7, 0x25, - 0xeb, 0x42, 0xab, 0x4a, 0x03, 0x5e, 0x97, 0x3a, 0x08, 0x43, 0x91, 0xea, 0x29, 0xf6, 0x6c, 0x12, - 0x25, 0xe7, 0xcd, 0xab, 0x97, 0x42, 0xb1, 0xbf, 0x69, 0x3b, 0xc4, 0x85, 0xc8, 0x48, 0x95, 0x84, - 0xe6, 0x53, 0xb8, 0x71, 0x10, 0xd8, 0x03, 0x1a, 0x72, 0x35, 0xa8, 0x76, 0xf9, 0x73, 0xb8, 0xc3, - 0x49, 0x78, 0xdc, 0x1b, 0xb8, 0x21, 0x67, 0xc1, 0xa4, 0x17, 0x50, 0x4e, 0x7d, 0xd1, 0xdf, 0x93, - 0x6f, 0xe9, 0xba, 0x9a, 0xbd, 0x2d, 0x30, 0x8f, 0x15, 0x04, 0x47, 0x88, 0x3d, 0x01, 0x30, 0x1b, - 0x50, 0x14, 0x84, 0xad, 0x46, 0x8f, 0xc8, 0xd8, 0xe3, 0x21, 0xfa, 0x31, 0x80, 0xc7, 0xfa, 0xbd, - 0x37, 0xce, 0xe4, 0x79, 0x8f, 0xf5, 0xd5, 0xa7, 0xf9, 0xfb, 0x60, 0xd4, 0xdc, 0x70, 0x44, 0xb8, - 0x3d, 0x88, 0xca, 0x74, 0xf4, 0x08, 0x8c, 0x01, 0x25, 0x01, 0x3f, 0xa4, 0x84, 0xf7, 0x46, 0x34, - 0x70, 0x99, 0xf3, 0x46, 0x4b, 0x7a, 0x2d, 0xd6, 0x6a, 0x49, 0x25, 0xf3, 0x57, 0x09, 0x00, 0x4c, - 0x8e, 0x22, 0x02, 0xf0, 0x43, 0xb8, 0x1e, 0xfa, 0x64, 0x14, 0x0e, 0x18, 0xef, 0xb9, 0x3e, 0xa7, - 0xc1, 0x09, 0xf1, 0x74, 0xa9, 0x65, 0x44, 0x1d, 0x0d, 0x2d, 0x47, 0x1f, 0x02, 0x3a, 0xa6, 0x74, - 0xd4, 0x63, 0x9e, 0xd3, 0x8b, 0x3a, 0xd5, 0x63, 0x7f, 0x1a, 0x1b, 0xa2, 0xe7, 0xc0, 0x73, 0xda, - 0x91, 0x1c, 0xed, 0xc0, 0xa6, 0x58, 0x01, 0xea, 0xf3, 0xc0, 0xa5, 0x61, 0xef, 0x88, 0x05, 0xbd, - 0xd0, 0x63, 0xa7, 0xbd, 0x23, 0xe6, 0x79, 0xec, 0x94, 0x06, 0x51, 0x21, 0x5b, 0xf2, 0x58, 0xbf, - 0xae, 0x40, 0xbb, 0x2c, 0x68, 0x7b, 0xec, 0x74, 0x37, 0x42, 0x08, 0x96, 0x30, 0x9d, 0x36, 0x77, - 0xed, 0xe3, 0x88, 0x25, 0xc4, 0xd2, 0x8e, 0x6b, 0x1f, 0xa3, 0xbb, 0xb0, 0x46, 0x3d, 0x2a, 0x4b, - 0x2e, 0x85, 0xca, 0x48, 0x54, 0x31, 0x12, 0x0a, 0x90, 0xf9, 0x5b, 0x90, 0x6f, 0x79, 0xc4, 0x96, - 0x7f, 0xa9, 0x88, 0xe2, 0xd2, 0x66, 0xbe, 0x08, 0x02, 0xd7, 0xe7, 0x2a, 0x3b, 0xe6, 0xf1, 0xac, - 0xc8, 0xfc, 0x09, 0xc0, 0x4f, 0x99, 0xeb, 0x77, 0xd8, 0x31, 0xf5, 0xe5, 0xeb, 0xb3, 0x60, 0xbd, - 0x7a, 0x2b, 0xf3, 0x58, 0xb7, 0x24, 0x27, 0x27, 0x3e, 0xe9, 0xd3, 0x20, 0x7e, 0x84, 0x55, 0x4d, - 0x71, 0xb9, 0x64, 0x31, 0x63, 0xbc, 0x6a, 0xa1, 0x32, 0x64, 0x6d, 0xd2, 0x8b, 0x4e, 0x5e, 0x71, - 0x27, 0x7f, 0x79, 0xb1, 0x95, 0xa9, 0x5a, 0x4f, 0xe8, 0x04, 0x67, 0x6c, 0xf2, 0x84, 0x4e, 0xc4, - 0xed, 0x6b, 0x13, 0x79, 0x5e, 0xa4, 0x99, 0xa2, 0xba, 0x7d, 0xab, 0x96, 0x38, 0x0c, 0x38, 0x6b, - 0x13, 0xf1, 0x8b, 0x3e, 0x86, 0xa2, 0x06, 0xf5, 0x06, 0x24, 0x1c, 0x28, 0xae, 0xba, 0xb3, 0x7e, - 0x79, 0xb1, 0x05, 0x0a, 0xf9, 0x98, 0x84, 0x03, 0x0c, 0x0a, 0x2d, 0xbe, 0x51, 0x1d, 0x0a, 0x5f, - 0x31, 0xd7, 0xef, 0x71, 0x39, 0x09, 0xfd, 0x36, 0xb0, 0xf4, 0xfc, 0x4c, 0xa7, 0xaa, 0x0b, 0x65, - 0xf8, 0x2a, 0x96, 0x98, 0xff, 0x9a, 0x80, 0x82, 0xb0, 0xe9, 0x1e, 0xb9, 0xb6, 0xb8, 0x2d, 0xbf, - 0x7b, 0xa6, 0xbf, 0x0d, 0x29, 0x3b, 0x0c, 0xf4, 0xdc, 0x64, 0xaa, 0xab, 0xb6, 0x31, 0x16, 0x32, - 0xf4, 0x05, 0x64, 0x55, 0x71, 0xa1, 0x93, 0xbc, 0xf9, 0xed, 0xf7, 0xba, 0x76, 0x51, 0xeb, 0xc9, - 0xbd, 0x9c, 0x7a, 0x27, 0x67, 0x59, 0xc4, 0xb3, 0x22, 0x74, 0x0b, 0x92, 0xb6, 0x2f, 0x83, 0x42, - 0xff, 0x2b, 0x55, 0x6d, 0xe2, 0xa4, 0xed, 0x9b, 0xff, 0x9c, 0x80, 0xb5, 0xba, 0x6f, 0x07, 0x13, - 0x99, 0x24, 0xc5, 0x46, 0xdc, 0x81, 0x7c, 0x38, 0x3e, 0x0c, 0x27, 0x21, 0xa7, 0xc3, 0xe8, 0xd1, - 0x3b, 0x16, 0xa0, 0x06, 0xe4, 0x89, 0xd7, 0x67, 0x81, 0xcb, 0x07, 0x43, 0xcd, 0x8d, 0x97, 0x27, - 0xe6, 0x59, 0x9b, 0x15, 0x2b, 0x52, 0xc1, 0x53, 0xed, 0x28, 0x15, 0xa7, 0xa4, 0xb3, 0x32, 0x15, - 0xbf, 0x0b, 0x45, 0x8f, 0x0c, 0x05, 0x15, 0xee, 0x89, 0x92, 0x4b, 0xce, 0x23, 0x8d, 0x0b, 0x5a, - 0x26, 0xca, 0x48, 0xd3, 0x84, 0x7c, 0x6c, 0x0c, 0x5d, 0x83, 0x82, 0x55, 0x6f, 0xf7, 0x3e, 0xd9, - 0x7e, 0xd0, 0x7b, 0x54, 0xdd, 0x37, 0x56, 0x34, 0x13, 0xf8, 0xc7, 0x04, 0xac, 0xed, 0xab, 0x18, - 0xd4, 0xc4, 0xe9, 0x2e, 0xac, 0x06, 0xe4, 0x88, 0x47, 0xd4, 0x2e, 0xad, 0x82, 0x4b, 0x24, 0x01, - 0x41, 0xed, 0x44, 0xd7, 0x72, 0x6a, 0x37, 0xf3, 0x97, 0x4b, 0xea, 0xca, 0xbf, 0x5c, 0xd2, 0xbf, - 0x91, 0xbf, 0x5c, 0x3e, 0xf8, 0x55, 0x0a, 0xf2, 0x71, 0xd1, 0x2b, 0x42, 0x46, 0x30, 0xad, 0x15, - 0xf5, 0x88, 0x14, 0xcb, 0x9b, 0x92, 0x63, 0xe5, 0xad, 0xbd, 0xbd, 0x83, 0xaa, 0xd5, 0xa9, 0xd7, - 0x8c, 0x2f, 0x14, 0x15, 0x8b, 0x01, 0x96, 0xe7, 0x31, 0xb1, 0xe9, 0x0e, 0x32, 0xa7, 0x54, 0xec, - 0x85, 0x7e, 0xaa, 0x8a, 0x51, 0x11, 0x0f, 0x7b, 0x0f, 0x72, 0x56, 0xbb, 0xdd, 0x78, 0xd4, 0xac, - 0xd7, 0x8c, 0x97, 0x89, 0xd2, 0xf7, 0xce, 0xce, 0xcb, 0xd7, 0xa7, 0xa6, 0xc2, 0xd0, 0xed, 0xfb, - 0xd4, 0x91, 0xa8, 0x6a, 0xb5, 0xde, 0x12, 0xe3, 0xbd, 0x48, 0x2e, 0xa2, 0x24, 0x01, 0x91, 0xcf, - 0xce, 0xf9, 0x16, 0xae, 0xb7, 0x2c, 0x2c, 0x46, 0x7c, 0x99, 0x5c, 0xf0, 0xab, 0x15, 0xd0, 0x11, - 0x09, 0xc4, 0x98, 0x9b, 0xd1, 0xdf, 0x2f, 0x2f, 0x52, 0xea, 0x69, 0x72, 0x5a, 0xe9, 0x53, 0xe2, - 0x4c, 0xc4, 0x68, 0xed, 0x8e, 0x85, 0xe5, 0x83, 0xc8, 0xcb, 0xd4, 0xc2, 0x68, 0x6d, 0x4e, 0x02, - 0x2e, 0xac, 0x98, 0xb0, 0x8a, 0xbb, 0xcd, 0xa6, 0x9c, 0x5d, 0x7a, 0x61, 0x76, 0x78, 0xec, 0xfb, - 0x02, 0x73, 0x0f, 0x72, 0xd1, 0x03, 0x8a, 0xf1, 0x32, 0xbd, 0xe0, 0x50, 0x35, 0x7a, 0xb9, 0x91, - 0x03, 0x3e, 0xee, 0x76, 0xe4, 0xbf, 0x43, 0x2f, 0x32, 0x8b, 0x03, 0x0e, 0xc6, 0xdc, 0x11, 0xe4, - 0xb7, 0x1c, 0xb3, 0xd1, 0x97, 0x19, 0x45, 0x02, 0x62, 0x8c, 0xa2, 0xa2, 0xc2, 0x0e, 0xae, 0xff, - 0x54, 0xfd, 0x91, 0xf4, 0x22, 0xbb, 0x60, 0x07, 0xd3, 0xaf, 0xa8, 0xcd, 0xa9, 0x33, 0x7d, 0x79, - 0x8d, 0xbb, 0x3e, 0xf8, 0x03, 0xc8, 0x45, 0x09, 0x03, 0x6d, 0x42, 0xf6, 0xd9, 0x01, 0x7e, 0x52, - 0xc7, 0xc6, 0x8a, 0x5a, 0x9d, 0xa8, 0xe7, 0x99, 0xca, 0xb8, 0x65, 0x58, 0xdd, 0xb7, 0x9a, 0xd6, - 0xa3, 0x3a, 0x8e, 0x5e, 0x7e, 0x23, 0x80, 0x8e, 0xfa, 0x92, 0xa1, 0x07, 0x88, 0x6d, 0xee, 0xdc, - 0xf9, 0xfa, 0x9b, 0xcd, 0x95, 0x5f, 0x7c, 0xb3, 0xb9, 0xf2, 0xcb, 0x6f, 0x36, 0x13, 0x2f, 0x2e, - 0x37, 0x13, 0x5f, 0x5f, 0x6e, 0x26, 0x7e, 0x7e, 0xb9, 0x99, 0xf8, 0x8f, 0xcb, 0xcd, 0xc4, 0x61, - 0x56, 0x32, 0xb2, 0x4f, 0xff, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xe8, 0x50, 0x18, 0x0a, 0x21, - 0x00, 0x00, + // 3518 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0x4d, 0x6c, 0x23, 0x47, + 0x76, 0x16, 0x7f, 0x45, 0x3e, 0x52, 0x9a, 0x9e, 0x9a, 0xd9, 0xb1, 0x86, 0x1e, 0x4b, 0x74, 0x8f, + 0x67, 0x3d, 0xeb, 0x75, 0x68, 0x5b, 0xde, 0x18, 0xb3, 0x9e, 0x64, 0xed, 0x16, 0x49, 0xcd, 0x70, + 0x47, 0xa2, 0x88, 0xa2, 0x38, 0x03, 0x23, 0x40, 0x1a, 0xa5, 0xee, 0x12, 0xd5, 0x56, 0xb3, 0x8b, + 0xe9, 0x2e, 0x4a, 0xc3, 0x04, 0x01, 0x26, 0x39, 0x24, 0x81, 0x4e, 0xb9, 0x07, 0xc2, 0x22, 0x48, + 0x90, 0x5b, 0xce, 0x01, 0x72, 0xf2, 0xd1, 0xc7, 0x0d, 0x02, 0x04, 0x8b, 0x04, 0x10, 0x62, 0xe5, + 0x98, 0xcb, 0x02, 0x41, 0xb0, 0x87, 0xe4, 0x10, 0xd4, 0x4f, 0x37, 0x7f, 0x86, 0x23, 0x8f, 0xb3, + 0x7b, 0x62, 0xd7, 0xab, 0xef, 0xbd, 0x7a, 0x55, 0xf5, 0xea, 0xd5, 0xf7, 0x8a, 0x50, 0xe2, 0xe3, + 0x21, 0x8d, 0x6a, 0xc3, 0x90, 0x71, 0x86, 0x90, 0xcb, 0x9c, 0x63, 0x1a, 0xd6, 0xa2, 0x53, 0x12, + 0x0e, 0x8e, 0x3d, 0x5e, 0x3b, 0xf9, 0xa8, 0x72, 0x9b, 0x7b, 0x03, 0x1a, 0x71, 0x32, 0x18, 0x7e, + 0x90, 0x7c, 0x29, 0x78, 0xe5, 0x0d, 0x77, 0x14, 0x12, 0xee, 0xb1, 0xe0, 0x83, 0xf8, 0x43, 0x77, + 0xdc, 0xec, 0xb3, 0x3e, 0x93, 0x9f, 0x1f, 0x88, 0x2f, 0x25, 0x35, 0x37, 0x60, 0xf9, 0x29, 0x0d, + 0x23, 0x8f, 0x05, 0xe8, 0x26, 0xe4, 0xbc, 0xc0, 0xa5, 0xcf, 0xd7, 0x52, 0xd5, 0xd4, 0xfd, 0x2c, + 0x56, 0x0d, 0xf3, 0xaf, 0x53, 0x50, 0xb2, 0x82, 0x80, 0x71, 0x69, 0x2b, 0x42, 0x08, 0xb2, 0x01, + 0x19, 0x50, 0x09, 0x2a, 0x62, 0xf9, 0x8d, 0xea, 0x90, 0xf7, 0xc9, 0x01, 0xf5, 0xa3, 0xb5, 0x74, + 0x35, 0x73, 0xbf, 0xb4, 0xf9, 0xc3, 0xda, 0xcb, 0x3e, 0xd7, 0xa6, 0x8c, 0xd4, 0x76, 0x24, 0xba, + 0x19, 0xf0, 0x70, 0x8c, 0xb5, 0x6a, 0xe5, 0xc7, 0x50, 0x9a, 0x12, 0x23, 0x03, 0x32, 0xc7, 0x74, + 0xac, 0x87, 0x11, 0x9f, 0xc2, 0xbf, 0x13, 0xe2, 0x8f, 0xe8, 0x5a, 0x5a, 0xca, 0x54, 0xe3, 0xd3, + 0xf4, 0x83, 0x94, 0xf9, 0x05, 0x14, 0x31, 0x8d, 0xd8, 0x28, 0x74, 0x68, 0x84, 0x7e, 0x00, 0xc5, + 0x80, 0x04, 0xcc, 0x76, 0x86, 0xa3, 0x48, 0xaa, 0x67, 0xb6, 0xca, 0x97, 0x17, 0x1b, 0x85, 0x36, + 0x09, 0x58, 0xbd, 0xd3, 0x8b, 0x70, 0x41, 0x74, 0xd7, 0x87, 0xa3, 0x08, 0xbd, 0x0d, 0xe5, 0x01, + 0x1d, 0xb0, 0x70, 0x6c, 0x1f, 0x8c, 0x39, 0x8d, 0xa4, 0xe1, 0x0c, 0x2e, 0x29, 0xd9, 0x96, 0x10, + 0x99, 0x7f, 0x99, 0x82, 0x9b, 0xb1, 0x6d, 0x4c, 0xff, 0x60, 0xe4, 0x85, 0x74, 0x40, 0x03, 0x1e, + 0xa1, 0xdf, 0x86, 0xbc, 0xef, 0x0d, 0x3c, 0xae, 0xc6, 0x28, 0x6d, 0xbe, 0xb5, 0x68, 0xce, 0x89, + 0x57, 0x58, 0x83, 0x91, 0x05, 0xe5, 0x90, 0x46, 0x34, 0x3c, 0x51, 0x2b, 0x21, 0x87, 0xfc, 0x56, + 0xe5, 0x19, 0x15, 0x73, 0x1b, 0x0a, 0x1d, 0x9f, 0xf0, 0x43, 0x16, 0x0e, 0x90, 0x09, 0x65, 0x12, + 0x3a, 0x47, 0x1e, 0xa7, 0x0e, 0x1f, 0x85, 0xf1, 0xae, 0xcc, 0xc8, 0xd0, 0x2d, 0x48, 0x33, 0x35, + 0x50, 0x71, 0x2b, 0x7f, 0x79, 0xb1, 0x91, 0xde, 0xeb, 0xe2, 0x34, 0x8b, 0xcc, 0x87, 0x70, 0xbd, + 0xe3, 0x8f, 0xfa, 0x5e, 0xd0, 0xa0, 0x91, 0x13, 0x7a, 0x43, 0x61, 0x5d, 0x6c, 0xaf, 0x08, 0xbe, + 0x78, 0x7b, 0xc5, 0x77, 0xb2, 0xe5, 0xe9, 0xc9, 0x96, 0x9b, 0x7f, 0x9e, 0x86, 0xeb, 0xcd, 0xa0, + 0xef, 0x05, 0x74, 0x5a, 0xfb, 0x1e, 0xac, 0x52, 0x29, 0xb4, 0x4f, 0x54, 0x50, 0x69, 0x3b, 0x2b, + 0x4a, 0x1a, 0x47, 0x5a, 0x6b, 0x2e, 0x5e, 0x3e, 0x5a, 0x34, 0xfd, 0x97, 0xac, 0x2f, 0x8a, 0x1a, + 0xd4, 0x84, 0xe5, 0xa1, 0x9c, 0x44, 0xb4, 0x96, 0x91, 0xb6, 0xee, 0x2d, 0xb2, 0xf5, 0xd2, 0x3c, + 0xb7, 0xb2, 0x5f, 0x5f, 0x6c, 0x2c, 0xe1, 0x58, 0xf7, 0xd7, 0x09, 0xbe, 0xff, 0x48, 0xc1, 0xb5, + 0x36, 0x73, 0x67, 0xd6, 0xa1, 0x02, 0x85, 0x23, 0x16, 0xf1, 0xa9, 0x83, 0x92, 0xb4, 0xd1, 0x03, + 0x28, 0x0c, 0xf5, 0xf6, 0xe9, 0xdd, 0xbf, 0xb3, 0xd8, 0x65, 0x85, 0xc1, 0x09, 0x1a, 0x3d, 0x84, + 0x62, 0x18, 0xc7, 0xc4, 0x5a, 0xe6, 0x75, 0x02, 0x67, 0x82, 0x47, 0xbf, 0x0b, 0x79, 0xb5, 0x09, + 0x6b, 0x59, 0xa9, 0x79, 0xef, 0xb5, 0xd6, 0x1c, 0x6b, 0x25, 0xf3, 0x17, 0x29, 0x30, 0x30, 0x39, + 0xe4, 0xbb, 0x74, 0x70, 0x40, 0xc3, 0x2e, 0x27, 0x7c, 0x14, 0xa1, 0x5b, 0x90, 0xf7, 0x29, 0x71, + 0x69, 0x28, 0x27, 0x59, 0xc0, 0xba, 0x85, 0x7a, 0x22, 0xc8, 0x89, 0x73, 0x44, 0x0e, 0x3c, 0xdf, + 0xe3, 0x63, 0x39, 0xcd, 0xd5, 0xc5, 0xbb, 0x3c, 0x6f, 0xb3, 0x86, 0xa7, 0x14, 0xf1, 0x8c, 0x19, + 0xb4, 0x06, 0xcb, 0x03, 0x1a, 0x45, 0xa4, 0x4f, 0xe5, 0xec, 0x8b, 0x38, 0x6e, 0x9a, 0x0f, 0xa1, + 0x3c, 0xad, 0x87, 0x4a, 0xb0, 0xdc, 0x6b, 0x3f, 0x69, 0xef, 0x3d, 0x6b, 0x1b, 0x4b, 0xe8, 0x1a, + 0x94, 0x7a, 0x6d, 0xdc, 0xb4, 0xea, 0x8f, 0xad, 0xad, 0x9d, 0xa6, 0x91, 0x42, 0x2b, 0x50, 0x9c, + 0x34, 0xd3, 0xe6, 0xcf, 0x52, 0x00, 0x62, 0x03, 0xf5, 0xa4, 0x3e, 0x85, 0x5c, 0xc4, 0x09, 0x57, + 0x1b, 0xb7, 0xba, 0xf9, 0xce, 0x22, 0xaf, 0x27, 0xf0, 0x9a, 0xf8, 0xa1, 0x58, 0xa9, 0x4c, 0x7b, + 0x98, 0x9e, 0xf7, 0x30, 0x27, 0x91, 0xb3, 0xae, 0x15, 0x20, 0xdb, 0x10, 0x5f, 0x29, 0x54, 0x84, + 0x1c, 0x6e, 0x5a, 0x8d, 0x2f, 0x8c, 0x34, 0x32, 0xa0, 0xdc, 0x68, 0x75, 0xeb, 0x7b, 0xed, 0x76, + 0xb3, 0xbe, 0xdf, 0x6c, 0x18, 0x19, 0xf3, 0x1e, 0xe4, 0x5a, 0x03, 0xd2, 0xa7, 0xe8, 0x8e, 0x88, + 0x80, 0x43, 0x1a, 0xd2, 0xc0, 0x89, 0x03, 0x6b, 0x22, 0x30, 0x7f, 0x5e, 0x84, 0xdc, 0x2e, 0x1b, + 0x05, 0x1c, 0x6d, 0x4e, 0x9d, 0xe2, 0xd5, 0xcd, 0xf5, 0x45, 0x53, 0x90, 0xc0, 0xda, 0xfe, 0x78, + 0x48, 0xf5, 0x29, 0xbf, 0x05, 0x79, 0x15, 0x2b, 0xda, 0x75, 0xdd, 0x12, 0x72, 0x4e, 0xc2, 0x3e, + 0xe5, 0x7a, 0xd1, 0x75, 0x0b, 0xdd, 0x87, 0x42, 0x48, 0x89, 0xcb, 0x02, 0x7f, 0x2c, 0x43, 0xaa, + 0xa0, 0xd2, 0x2c, 0xa6, 0xc4, 0xdd, 0x0b, 0xfc, 0x31, 0x4e, 0x7a, 0xd1, 0x63, 0x28, 0x1f, 0x78, + 0x81, 0x6b, 0xb3, 0xa1, 0xca, 0x79, 0xb9, 0x57, 0x07, 0xa0, 0xf2, 0x6a, 0xcb, 0x0b, 0xdc, 0x3d, + 0x05, 0xc6, 0xa5, 0x83, 0x49, 0x03, 0xb5, 0x61, 0xf5, 0x84, 0xf9, 0xa3, 0x01, 0x4d, 0x6c, 0xe5, + 0xa5, 0xad, 0x77, 0x5f, 0x6d, 0xeb, 0xa9, 0xc4, 0xc7, 0xd6, 0x56, 0x4e, 0xa6, 0x9b, 0xe8, 0x09, + 0xac, 0xf0, 0xc1, 0xf0, 0x30, 0x4a, 0xcc, 0x2d, 0x4b, 0x73, 0xdf, 0xbf, 0x62, 0xc1, 0x04, 0x3c, + 0xb6, 0x56, 0xe6, 0x53, 0xad, 0xca, 0x9f, 0x66, 0xa0, 0x34, 0xe5, 0x39, 0xea, 0x42, 0x69, 0x18, + 0xb2, 0x21, 0xe9, 0xcb, 0xbc, 0xad, 0xf7, 0xe2, 0xa3, 0xd7, 0x9a, 0x75, 0xad, 0x33, 0x51, 0xc4, + 0xd3, 0x56, 0xcc, 0xf3, 0x34, 0x94, 0xa6, 0x3a, 0xd1, 0x7b, 0x50, 0xc0, 0x1d, 0xdc, 0x7a, 0x6a, + 0xed, 0x37, 0x8d, 0xa5, 0xca, 0x9d, 0xb3, 0xf3, 0xea, 0x9a, 0xb4, 0x36, 0x6d, 0xa0, 0x13, 0x7a, + 0x27, 0x22, 0xf4, 0xee, 0xc3, 0x72, 0x0c, 0x4d, 0x55, 0xde, 0x3c, 0x3b, 0xaf, 0xbe, 0x31, 0x0f, + 0x9d, 0x42, 0xe2, 0xee, 0x63, 0x0b, 0x37, 0x1b, 0x46, 0x7a, 0x31, 0x12, 0x77, 0x8f, 0x48, 0x48, + 0x5d, 0xf4, 0x7d, 0xc8, 0x6b, 0x60, 0xa6, 0x52, 0x39, 0x3b, 0xaf, 0xde, 0x9a, 0x07, 0x4e, 0x70, + 0xb8, 0xbb, 0x63, 0x3d, 0x6d, 0x1a, 0xd9, 0xc5, 0x38, 0xdc, 0xf5, 0xc9, 0x09, 0x45, 0xef, 0x40, + 0x4e, 0xc1, 0x72, 0x95, 0xdb, 0x67, 0xe7, 0xd5, 0xef, 0xbd, 0x64, 0x4e, 0xa0, 0x2a, 0x6b, 0x7f, + 0xf1, 0x37, 0xeb, 0x4b, 0xff, 0xf8, 0xb7, 0xeb, 0xc6, 0x7c, 0x77, 0xe5, 0x7f, 0x53, 0xb0, 0x32, + 0xb3, 0xe5, 0xc8, 0x84, 0x7c, 0xc0, 0x1c, 0x36, 0x54, 0xe9, 0xbc, 0xb0, 0x05, 0x97, 0x17, 0x1b, + 0xf9, 0x36, 0xab, 0xb3, 0xe1, 0x18, 0xeb, 0x1e, 0xf4, 0x64, 0xee, 0x42, 0xfa, 0xf8, 0x35, 0xe3, + 0x69, 0xe1, 0x95, 0xf4, 0x19, 0xac, 0xb8, 0xa1, 0x77, 0x42, 0x43, 0xdb, 0x61, 0xc1, 0xa1, 0xd7, + 0xd7, 0xa9, 0xba, 0xb2, 0xc8, 0x66, 0x43, 0x02, 0x71, 0x59, 0x29, 0xd4, 0x25, 0xfe, 0xd7, 0xb8, + 0x8c, 0x2a, 0x4f, 0xa1, 0x3c, 0x1d, 0xa1, 0xe8, 0x2d, 0x80, 0xc8, 0xfb, 0x43, 0xaa, 0xf9, 0x8d, + 0x64, 0x43, 0xb8, 0x28, 0x24, 0x92, 0xdd, 0xa0, 0x77, 0x21, 0x3b, 0x60, 0xae, 0xb2, 0x93, 0xdb, + 0xba, 0x21, 0xee, 0xc4, 0x7f, 0xbd, 0xd8, 0x28, 0xb1, 0xa8, 0xb6, 0xed, 0xf9, 0x74, 0x97, 0xb9, + 0x14, 0x4b, 0x80, 0x79, 0x02, 0x59, 0x91, 0x2a, 0xd0, 0x9b, 0x90, 0xdd, 0x6a, 0xb5, 0x1b, 0xc6, + 0x52, 0xe5, 0xfa, 0xd9, 0x79, 0x75, 0x45, 0x2e, 0x89, 0xe8, 0x10, 0xb1, 0x8b, 0x36, 0x20, 0xff, + 0x74, 0x6f, 0xa7, 0xb7, 0x2b, 0xc2, 0xeb, 0xc6, 0xd9, 0x79, 0xf5, 0x5a, 0xd2, 0xad, 0x16, 0x0d, + 0xbd, 0x05, 0xb9, 0xfd, 0xdd, 0xce, 0x76, 0xd7, 0x48, 0x57, 0xd0, 0xd9, 0x79, 0x75, 0x35, 0xe9, + 0x97, 0x3e, 0x57, 0xae, 0xeb, 0x5d, 0x2d, 0x26, 0x72, 0xf3, 0x7f, 0xd2, 0xb0, 0x82, 0x05, 0xbf, + 0x0d, 0x79, 0x87, 0xf9, 0x9e, 0x33, 0x46, 0x1d, 0x28, 0x3a, 0x2c, 0x70, 0xbd, 0xa9, 0x33, 0xb5, + 0xf9, 0x8a, 0x4b, 0x70, 0xa2, 0x15, 0xb7, 0xea, 0xb1, 0x26, 0x9e, 0x18, 0x41, 0x9b, 0x90, 0x73, + 0xa9, 0x4f, 0xc6, 0x57, 0xdd, 0xc6, 0x0d, 0xcd, 0xa5, 0xb1, 0x82, 0x4a, 0xe6, 0x48, 0x9e, 0xdb, + 0x84, 0x73, 0x3a, 0x18, 0x72, 0x75, 0x1b, 0x67, 0x71, 0x69, 0x40, 0x9e, 0x5b, 0x5a, 0x84, 0x7e, + 0x04, 0xf9, 0x53, 0x2f, 0x70, 0xd9, 0xa9, 0xbe, 0x70, 0xaf, 0xb6, 0xab, 0xb1, 0xe6, 0x99, 0xb8, + 0x67, 0xe7, 0x9c, 0x15, 0xab, 0xde, 0xde, 0x6b, 0x37, 0xe3, 0x55, 0xd7, 0xfd, 0x7b, 0x41, 0x9b, + 0x05, 0xe2, 0xc4, 0xc0, 0x5e, 0xdb, 0xde, 0xb6, 0x5a, 0x3b, 0x3d, 0x2c, 0x56, 0xfe, 0xe6, 0xd9, + 0x79, 0xd5, 0x48, 0x20, 0xdb, 0xc4, 0xf3, 0x05, 0x09, 0xbc, 0x0d, 0x19, 0xab, 0xfd, 0x85, 0x91, + 0xae, 0x18, 0x67, 0xe7, 0xd5, 0x72, 0xd2, 0x6d, 0x05, 0xe3, 0xc9, 0x61, 0x9a, 0x1f, 0xd7, 0xfc, + 0xcf, 0x34, 0x94, 0x7b, 0x43, 0x97, 0x70, 0xaa, 0x22, 0x13, 0x55, 0xa1, 0x34, 0x24, 0x21, 0xf1, + 0x7d, 0xea, 0x7b, 0xd1, 0x40, 0x17, 0x0a, 0xd3, 0x22, 0xf4, 0xe0, 0x3b, 0x2c, 0xa6, 0x26, 0x61, + 0x7a, 0x49, 0x7b, 0xb0, 0x7a, 0xa8, 0x9c, 0xb5, 0x89, 0x23, 0x77, 0x37, 0x23, 0x77, 0xb7, 0xb6, + 0xc8, 0xc4, 0xb4, 0x57, 0x35, 0x3d, 0x47, 0x4b, 0x6a, 0xe1, 0x95, 0xc3, 0xe9, 0x26, 0xfa, 0x04, + 0x96, 0x07, 0x2c, 0xf0, 0x38, 0x0b, 0x5f, 0x6b, 0x1f, 0x62, 0x30, 0x7a, 0x00, 0x6b, 0xc4, 0xf7, + 0xd9, 0x29, 0x75, 0xed, 0xd8, 0xad, 0xc3, 0x50, 0x3b, 0x26, 0x2e, 0xb0, 0x34, 0xbe, 0xa5, 0xfb, + 0xf5, 0xf0, 0xdb, 0xba, 0xd7, 0xfc, 0x04, 0x56, 0x66, 0x3c, 0x12, 0x77, 0x7b, 0xc7, 0xea, 0x75, + 0x9b, 0xc6, 0x12, 0x2a, 0x43, 0xa1, 0xbe, 0xd7, 0xde, 0x6f, 0xb5, 0x7b, 0x82, 0x88, 0x94, 0xa1, + 0x80, 0xf7, 0x76, 0x76, 0xb6, 0xac, 0xfa, 0x13, 0x23, 0x6d, 0xfe, 0x77, 0xb2, 0xda, 0x9a, 0x89, + 0x6c, 0xcd, 0x32, 0x91, 0xf7, 0x5f, 0xbd, 0x10, 0x9a, 0x8b, 0x4c, 0x1a, 0x09, 0x23, 0xf9, 0x1d, + 0x00, 0xb9, 0xa9, 0xd4, 0xb5, 0x09, 0xbf, 0xaa, 0xda, 0xd8, 0x8f, 0xeb, 0x48, 0x5c, 0xd4, 0x0a, + 0x16, 0x47, 0x9f, 0x43, 0xd9, 0x61, 0x83, 0xa1, 0x4f, 0xb5, 0x7e, 0xe6, 0x75, 0xf4, 0x4b, 0x89, + 0x8a, 0xc5, 0xa7, 0x19, 0x51, 0x76, 0x96, 0x11, 0xfd, 0x59, 0x0a, 0x4a, 0x53, 0x0e, 0xcf, 0x12, + 0xa3, 0x32, 0x14, 0x7a, 0x9d, 0x86, 0xb5, 0xdf, 0x6a, 0x3f, 0x32, 0x52, 0x08, 0x20, 0x2f, 0x17, + 0xb0, 0x61, 0xa4, 0x05, 0x79, 0xab, 0xef, 0xed, 0x76, 0x76, 0x9a, 0x92, 0x1a, 0xa1, 0x9b, 0x60, + 0xc4, 0x4b, 0x68, 0x77, 0xf7, 0x2d, 0x2c, 0xa4, 0x59, 0x74, 0x03, 0xae, 0x25, 0x52, 0xad, 0x99, + 0x43, 0xb7, 0x00, 0x25, 0xc2, 0x89, 0x89, 0xbc, 0xf9, 0xc7, 0x70, 0xad, 0xce, 0x02, 0x4e, 0xbc, + 0x20, 0x21, 0xb6, 0x9b, 0x62, 0xde, 0x5a, 0x64, 0x7b, 0xae, 0xca, 0xbd, 0x5b, 0xd7, 0x2e, 0x2f, + 0x36, 0x4a, 0x09, 0xb4, 0xd5, 0x10, 0x33, 0x8d, 0x1b, 0xae, 0x38, 0x61, 0x43, 0xcf, 0xd5, 0xa9, + 0x74, 0xf9, 0xf2, 0x62, 0x23, 0xd3, 0x69, 0x35, 0xb0, 0x90, 0xa1, 0x37, 0xa1, 0x48, 0x9f, 0x7b, + 0xdc, 0x76, 0x44, 0xae, 0x15, 0x6b, 0x98, 0xc3, 0x05, 0x21, 0xa8, 0x8b, 0xd4, 0xfa, 0x27, 0x69, + 0x80, 0x7d, 0x12, 0x1d, 0xeb, 0xa1, 0x1f, 0x42, 0x31, 0x29, 0xe9, 0xaf, 0x2a, 0x2d, 0xa7, 0xf6, + 0x2b, 0xc1, 0xa3, 0x8f, 0xe3, 0x88, 0x51, 0x8c, 0x7b, 0xb1, 0xa2, 0x1e, 0x6b, 0x11, 0x69, 0x9d, + 0xa5, 0xd5, 0xe2, 0xe6, 0xa1, 0x61, 0xa8, 0x37, 0x4e, 0x7c, 0xa2, 0xba, 0xcc, 0xbe, 0x6a, 0xce, + 0x9a, 0xc7, 0xdd, 0x5d, 0x34, 0xc8, 0xdc, 0x82, 0x3e, 0x5e, 0xc2, 0x13, 0xbd, 0x2d, 0x03, 0x56, + 0xc3, 0x51, 0x20, 0xbc, 0xb6, 0x23, 0xd9, 0x6d, 0x7a, 0xf0, 0x46, 0x9b, 0xf2, 0x53, 0x16, 0x1e, + 0x5b, 0x9c, 0x13, 0xe7, 0x48, 0x94, 0xd8, 0x3a, 0xe5, 0x4c, 0xe8, 0x67, 0x6a, 0x86, 0x7e, 0xae, + 0xc1, 0x32, 0xf1, 0x3d, 0x12, 0x51, 0x75, 0x67, 0x17, 0x71, 0xdc, 0x14, 0x24, 0x99, 0xb8, 0x6e, + 0x48, 0xa3, 0x88, 0xaa, 0xa2, 0xb0, 0x88, 0x27, 0x02, 0xf3, 0x9f, 0xd3, 0x00, 0xad, 0x8e, 0xb5, + 0xab, 0xcd, 0x37, 0x20, 0x7f, 0x48, 0x06, 0x9e, 0x3f, 0xbe, 0xea, 0x90, 0x4d, 0xf0, 0x35, 0x4b, + 0x19, 0xda, 0x96, 0x3a, 0x58, 0xeb, 0x4a, 0xee, 0x3c, 0x3a, 0x08, 0x28, 0x4f, 0xb8, 0xb3, 0x6c, + 0x89, 0x8b, 0x3a, 0x24, 0x41, 0xb2, 0xb0, 0xaa, 0x21, 0x5c, 0xef, 0x13, 0x4e, 0x4f, 0xc9, 0x38, + 0x3e, 0x13, 0xba, 0x89, 0x1e, 0x0b, 0x4e, 0x2d, 0x4a, 0x7d, 0xea, 0xae, 0xe5, 0x24, 0x13, 0xf9, + 0x36, 0x7f, 0xb0, 0x86, 0x2b, 0x0a, 0x92, 0x68, 0x57, 0x1e, 0xca, 0x7b, 0x73, 0xd2, 0xf5, 0x9d, + 0x4a, 0xda, 0x0f, 0x61, 0x65, 0x66, 0x9e, 0x2f, 0x15, 0x2d, 0xad, 0xce, 0xd3, 0x1f, 0x19, 0x59, + 0xfd, 0xf5, 0x89, 0x91, 0x37, 0xff, 0x2b, 0x05, 0xd0, 0x61, 0x61, 0xbc, 0x69, 0x8b, 0x1f, 0x89, + 0x0a, 0xf2, 0xc9, 0xc9, 0x61, 0xbe, 0x0e, 0xcf, 0x85, 0xac, 0x7d, 0x62, 0x45, 0x90, 0x60, 0x09, + 0xc7, 0x89, 0x22, 0xda, 0x80, 0x92, 0xda, 0x7f, 0x7b, 0xc8, 0x42, 0x95, 0x8f, 0x56, 0x30, 0x28, + 0x91, 0xd0, 0x44, 0xf7, 0x60, 0x75, 0x38, 0x3a, 0xf0, 0xbd, 0xe8, 0x88, 0xba, 0x0a, 0x93, 0x95, + 0x98, 0x95, 0x44, 0x2a, 0x60, 0x66, 0x03, 0x0a, 0xb1, 0x75, 0xb4, 0x06, 0x99, 0xfd, 0x7a, 0xc7, + 0x58, 0xaa, 0x5c, 0x3b, 0x3b, 0xaf, 0x96, 0x62, 0xf1, 0x7e, 0xbd, 0x23, 0x7a, 0x7a, 0x8d, 0x8e, + 0x91, 0x9a, 0xed, 0xe9, 0x35, 0x3a, 0x95, 0xac, 0xb8, 0x33, 0xcd, 0xbf, 0x4a, 0x41, 0x5e, 0x31, + 0xb8, 0x85, 0x33, 0xb6, 0x60, 0x39, 0xae, 0x2b, 0x14, 0xad, 0x7c, 0xf7, 0xd5, 0x14, 0xb0, 0xa6, + 0x19, 0x9b, 0xda, 0xc7, 0x58, 0xaf, 0xf2, 0x29, 0x94, 0xa7, 0x3b, 0xbe, 0xd3, 0x2e, 0xfe, 0x11, + 0x94, 0x44, 0xa0, 0xc4, 0x54, 0x70, 0x13, 0xf2, 0x8a, 0x65, 0xea, 0xac, 0x72, 0x15, 0x1f, 0xd5, + 0x48, 0xf4, 0x00, 0x96, 0x15, 0x87, 0x8d, 0x5f, 0x57, 0xd6, 0xaf, 0x0e, 0x47, 0x1c, 0xc3, 0xcd, + 0xcf, 0x20, 0xdb, 0xa1, 0x34, 0x44, 0x77, 0x61, 0x39, 0x60, 0x2e, 0x9d, 0x24, 0x51, 0x4d, 0xbf, + 0x5d, 0xda, 0x6a, 0x08, 0xfa, 0xed, 0xd2, 0x96, 0x2b, 0x16, 0x4f, 0x1c, 0xd0, 0xf8, 0x81, 0x49, + 0x7c, 0x9b, 0xfb, 0x50, 0x7e, 0x46, 0xbd, 0xfe, 0x11, 0xa7, 0xae, 0x34, 0xf4, 0x3e, 0x64, 0x87, + 0x34, 0x71, 0x7e, 0x6d, 0x61, 0xe8, 0x50, 0x1a, 0x62, 0x89, 0x12, 0x07, 0xf2, 0x54, 0x6a, 0xeb, + 0x37, 0x3d, 0xdd, 0x32, 0xff, 0x3e, 0x0d, 0xab, 0xad, 0x28, 0x1a, 0x91, 0xc0, 0x89, 0x6f, 0xd9, + 0x9f, 0xcc, 0xde, 0xb2, 0xf7, 0x17, 0xce, 0x70, 0x46, 0x65, 0xb6, 0xe6, 0xd7, 0x49, 0x32, 0x9d, + 0x24, 0x49, 0xf3, 0xeb, 0x54, 0x5c, 0xec, 0xdf, 0x9b, 0x3a, 0x37, 0x95, 0xb5, 0xb3, 0xf3, 0xea, + 0xcd, 0x69, 0x4b, 0xb4, 0x17, 0x1c, 0x07, 0xec, 0x34, 0x40, 0x6f, 0x8b, 0xe2, 0xbf, 0xdd, 0x7c, + 0x66, 0xa4, 0x2a, 0xb7, 0xce, 0xce, 0xab, 0x68, 0x06, 0x84, 0x69, 0x40, 0x4f, 0x85, 0xa5, 0x4e, + 0xb3, 0xdd, 0x10, 0xf7, 0x61, 0x7a, 0x81, 0xa5, 0x0e, 0x0d, 0x5c, 0x2f, 0xe8, 0xa3, 0xbb, 0x90, + 0x6f, 0x75, 0xbb, 0x3d, 0x59, 0x8e, 0xbd, 0x71, 0x76, 0x5e, 0xbd, 0x31, 0x83, 0x12, 0x0d, 0xea, + 0x0a, 0x90, 0xa0, 0x8b, 0xe2, 0xa6, 0x5c, 0x00, 0x12, 0xdc, 0x85, 0xba, 0x3a, 0xc2, 0xff, 0x2d, + 0x0d, 0x86, 0xe5, 0x38, 0x74, 0xc8, 0x45, 0xbf, 0xa6, 0xe0, 0xfb, 0x50, 0x18, 0x8a, 0x2f, 0x4f, + 0x96, 0x14, 0x22, 0x2c, 0x1e, 0x2c, 0x7c, 0xf0, 0x9d, 0xd3, 0xab, 0x61, 0xe6, 0x53, 0xcb, 0x1d, + 0x78, 0x51, 0x24, 0x4a, 0x4d, 0x29, 0xc3, 0x89, 0xa5, 0xca, 0x2f, 0x53, 0x70, 0x63, 0x01, 0x02, + 0x7d, 0x08, 0xd9, 0x90, 0xf9, 0xf1, 0xf6, 0xdc, 0x79, 0xd5, 0x73, 0x8c, 0x50, 0xc5, 0x12, 0x89, + 0xd6, 0x01, 0xc8, 0x88, 0x33, 0x22, 0xc7, 0x97, 0x1b, 0x53, 0xc0, 0x53, 0x12, 0xf4, 0x0c, 0xf2, + 0x11, 0x75, 0x42, 0x1a, 0xf3, 0x99, 0xcf, 0xfe, 0xbf, 0xde, 0xd7, 0xba, 0xd2, 0x0c, 0xd6, 0xe6, + 0x2a, 0x35, 0xc8, 0x2b, 0x89, 0x88, 0x68, 0x97, 0x70, 0x22, 0x9d, 0x2e, 0x63, 0xf9, 0x2d, 0x02, + 0x85, 0xf8, 0xfd, 0x38, 0x50, 0x88, 0xdf, 0x37, 0x7f, 0x96, 0x06, 0x68, 0x3e, 0xe7, 0x34, 0x0c, + 0x88, 0x5f, 0xb7, 0x50, 0x73, 0x2a, 0x43, 0xaa, 0xd9, 0xfe, 0x60, 0xe1, 0x23, 0x5d, 0xa2, 0x51, + 0xab, 0x5b, 0x0b, 0x72, 0xe4, 0x6d, 0xc8, 0x8c, 0x42, 0x5f, 0x3f, 0xf8, 0x4a, 0x22, 0xd2, 0xc3, + 0x3b, 0x58, 0xc8, 0x50, 0x73, 0x92, 0x91, 0x32, 0xaf, 0x7e, 0xa9, 0x9f, 0x1a, 0xe0, 0x37, 0x9f, + 0x95, 0xde, 0x07, 0x98, 0x78, 0x8d, 0xd6, 0x21, 0x57, 0xdf, 0xee, 0x76, 0x77, 0x8c, 0x25, 0x55, + 0x31, 0x4e, 0xba, 0xa4, 0xd8, 0xfc, 0xbb, 0x14, 0x14, 0xea, 0x96, 0xbe, 0x55, 0xb6, 0xc1, 0x90, + 0xb9, 0xc4, 0xa1, 0x21, 0xb7, 0xe9, 0xf3, 0xa1, 0x17, 0x8e, 0x75, 0x3a, 0xb8, 0x9a, 0xd3, 0xaf, + 0x0a, 0xad, 0x3a, 0x0d, 0x79, 0x53, 0xea, 0x20, 0x0c, 0x65, 0xaa, 0xa7, 0x68, 0x3b, 0x24, 0x4e, + 0xce, 0xeb, 0x57, 0x2f, 0x85, 0x62, 0x7f, 0x93, 0x76, 0x84, 0x4b, 0xb1, 0x91, 0x3a, 0x89, 0xcc, + 0xa7, 0x70, 0x63, 0x2f, 0x74, 0x8e, 0x68, 0xc4, 0xd5, 0xa0, 0xda, 0xe5, 0xcf, 0xe0, 0x0e, 0x27, + 0xd1, 0xb1, 0x7d, 0xe4, 0x45, 0x9c, 0x85, 0x63, 0x3b, 0xa4, 0x9c, 0x06, 0xa2, 0xdf, 0x96, 0xff, + 0x07, 0xe8, 0x8a, 0xfc, 0xb6, 0xc0, 0x3c, 0x56, 0x10, 0x1c, 0x23, 0x76, 0x04, 0xc0, 0x6c, 0x41, + 0x59, 0x10, 0xb6, 0x06, 0x3d, 0x24, 0x23, 0x9f, 0x47, 0xe8, 0xc7, 0x00, 0x3e, 0xeb, 0xdb, 0xaf, + 0x9d, 0xc9, 0x8b, 0x3e, 0xeb, 0xab, 0x4f, 0xf3, 0xf7, 0xc0, 0x68, 0x78, 0xd1, 0x90, 0x70, 0xe7, + 0x28, 0x7e, 0x6a, 0x40, 0x8f, 0xc0, 0x38, 0xa2, 0x24, 0xe4, 0x07, 0x94, 0x70, 0x7b, 0x48, 0x43, + 0x8f, 0xb9, 0xaf, 0xb5, 0xa4, 0xd7, 0x12, 0xad, 0x8e, 0x54, 0x32, 0x7f, 0x95, 0x02, 0xc0, 0xe4, + 0x30, 0x26, 0x00, 0x3f, 0x84, 0xeb, 0x51, 0x40, 0x86, 0xd1, 0x11, 0xe3, 0xb6, 0x17, 0x70, 0x1a, + 0x9e, 0x10, 0x5f, 0x97, 0x8b, 0x46, 0xdc, 0xd1, 0xd2, 0x72, 0xf4, 0x3e, 0xa0, 0x63, 0x4a, 0x87, + 0x36, 0xf3, 0x5d, 0x3b, 0xee, 0x54, 0x7f, 0x58, 0x64, 0xb1, 0x21, 0x7a, 0xf6, 0x7c, 0xb7, 0x1b, + 0xcb, 0xd1, 0x16, 0xac, 0x8b, 0x15, 0xa0, 0x01, 0x0f, 0x3d, 0x1a, 0xd9, 0x87, 0x2c, 0xb4, 0x23, + 0x9f, 0x9d, 0xda, 0x87, 0x4c, 0x96, 0x63, 0x61, 0x5c, 0x8c, 0x57, 0x7c, 0xd6, 0x6f, 0x2a, 0xd0, + 0x36, 0x0b, 0xbb, 0x3e, 0x3b, 0xdd, 0x8e, 0x11, 0x82, 0x25, 0x4c, 0xa6, 0xcd, 0x3d, 0xe7, 0x38, + 0x66, 0x09, 0x89, 0x74, 0xdf, 0x73, 0x8e, 0xd1, 0x5d, 0x58, 0xa1, 0x3e, 0x95, 0x45, 0x9c, 0x42, + 0xe5, 0x24, 0xaa, 0x1c, 0x0b, 0x05, 0xc8, 0xfc, 0x2d, 0x28, 0x76, 0x7c, 0xe2, 0xc8, 0xbf, 0x85, + 0x44, 0x81, 0xec, 0xb0, 0x40, 0x04, 0x81, 0x17, 0x70, 0x95, 0x1d, 0x8b, 0x78, 0x5a, 0x64, 0xfe, + 0x04, 0xe0, 0xa7, 0xcc, 0x0b, 0xf6, 0xd9, 0x31, 0x0d, 0xe4, 0x0b, 0xba, 0x60, 0xbd, 0x7a, 0x2b, + 0x8b, 0x58, 0xb7, 0x24, 0x27, 0x27, 0x01, 0xe9, 0xd3, 0x30, 0x79, 0x48, 0x56, 0x4d, 0x71, 0xb9, + 0xe4, 0x31, 0x63, 0xbc, 0x6e, 0xa1, 0x2a, 0xe4, 0x1d, 0x62, 0xc7, 0x27, 0xaf, 0xbc, 0x55, 0xbc, + 0xbc, 0xd8, 0xc8, 0xd5, 0xad, 0x27, 0x74, 0x8c, 0x73, 0x0e, 0x79, 0x42, 0xc7, 0xe2, 0xf6, 0x75, + 0x88, 0x3c, 0x2f, 0xd2, 0x4c, 0x59, 0xdd, 0xbe, 0x75, 0x4b, 0x1c, 0x06, 0x9c, 0x77, 0x88, 0xf8, + 0x45, 0x1f, 0x42, 0x59, 0x83, 0xec, 0x23, 0x12, 0x1d, 0x29, 0xae, 0xba, 0xb5, 0x7a, 0x79, 0xb1, + 0x01, 0x0a, 0xf9, 0x98, 0x44, 0x47, 0x18, 0x14, 0x5a, 0x7c, 0xa3, 0x26, 0x94, 0xbe, 0x64, 0x5e, + 0x60, 0x73, 0x39, 0x09, 0x5d, 0x57, 0x2f, 0x3c, 0x3f, 0x93, 0xa9, 0xea, 0x62, 0x1f, 0xbe, 0x4c, + 0x24, 0xe6, 0xbf, 0xa4, 0xa0, 0x24, 0x6c, 0x7a, 0x87, 0x9e, 0x23, 0x6e, 0xcb, 0xef, 0x9e, 0xe9, + 0x6f, 0x43, 0xc6, 0x89, 0x42, 0x3d, 0x37, 0x99, 0xea, 0xea, 0x5d, 0x8c, 0x85, 0x0c, 0x7d, 0x0e, + 0x79, 0x55, 0x5c, 0xe8, 0x24, 0x6f, 0x7e, 0xfb, 0xbd, 0xae, 0x5d, 0xd4, 0x7a, 0x72, 0x2f, 0x27, + 0xde, 0xc9, 0x59, 0x96, 0xf1, 0xb4, 0x08, 0xdd, 0x82, 0xb4, 0xa3, 0x5e, 0x03, 0xf4, 0x3f, 0x6b, + 0xf5, 0x36, 0x4e, 0x3b, 0x81, 0xf9, 0x4f, 0x29, 0x58, 0x69, 0x06, 0x4e, 0x38, 0x96, 0x49, 0x52, + 0x6c, 0xc4, 0x1d, 0x28, 0x46, 0xa3, 0x83, 0x68, 0x1c, 0x71, 0x3a, 0x88, 0x1f, 0xee, 0x13, 0x01, + 0x6a, 0x41, 0x91, 0xf8, 0x7d, 0x16, 0x7a, 0xfc, 0x68, 0xa0, 0xb9, 0xf1, 0xe2, 0xc4, 0x3c, 0x6d, + 0xb3, 0x66, 0xc5, 0x2a, 0x78, 0xa2, 0x1d, 0xa7, 0xe2, 0x8c, 0x74, 0x56, 0xa6, 0xe2, 0xb7, 0xa1, + 0xec, 0x93, 0x81, 0xa0, 0xc2, 0xb6, 0x28, 0xb9, 0xe4, 0x3c, 0xb2, 0xb8, 0xa4, 0x65, 0xa2, 0x8c, + 0x34, 0x4d, 0x28, 0x26, 0xc6, 0xd0, 0x35, 0x28, 0x59, 0xcd, 0xae, 0xfd, 0xd1, 0xe6, 0x03, 0xfb, + 0x51, 0x7d, 0xd7, 0x58, 0xd2, 0x4c, 0xe0, 0x1f, 0x52, 0xb0, 0xb2, 0xab, 0x62, 0x50, 0x13, 0xa7, + 0xbb, 0xb0, 0x1c, 0x92, 0x43, 0x1e, 0x53, 0xbb, 0xac, 0x0a, 0x2e, 0x91, 0x04, 0x04, 0xb5, 0x13, + 0x5d, 0x8b, 0xa9, 0xdd, 0xd4, 0xdf, 0x46, 0x99, 0x2b, 0xff, 0x36, 0xca, 0xfe, 0x46, 0xfe, 0x36, + 0x7a, 0xef, 0x57, 0x19, 0x28, 0x26, 0x45, 0xaf, 0x08, 0x19, 0xc1, 0xb4, 0x96, 0xd4, 0x43, 0x58, + 0x22, 0x6f, 0x4b, 0x8e, 0x55, 0xb4, 0x76, 0x76, 0xf6, 0xea, 0xd6, 0x7e, 0xb3, 0x61, 0x7c, 0xae, + 0xa8, 0x58, 0x02, 0xb0, 0x7c, 0x9f, 0x89, 0x4d, 0x77, 0x91, 0x39, 0xa1, 0x62, 0x2f, 0xf4, 0x73, + 0x5b, 0x82, 0x8a, 0x79, 0xd8, 0x3b, 0x50, 0xb0, 0xba, 0xdd, 0xd6, 0xa3, 0x76, 0xb3, 0x61, 0x7c, + 0x95, 0xaa, 0x7c, 0xef, 0xec, 0xbc, 0x7a, 0x7d, 0x62, 0x2a, 0x8a, 0xbc, 0x7e, 0x40, 0x5d, 0x89, + 0xaa, 0xd7, 0x9b, 0x1d, 0x31, 0xde, 0x8b, 0xf4, 0x3c, 0x4a, 0x12, 0x10, 0xf9, 0x74, 0x5e, 0xec, + 0xe0, 0x66, 0xc7, 0xc2, 0x62, 0xc4, 0xaf, 0xd2, 0x73, 0x7e, 0x75, 0x42, 0x3a, 0x24, 0xa1, 0x18, + 0x73, 0x3d, 0xfe, 0x0b, 0xe9, 0x45, 0x46, 0x3d, 0xaf, 0x4e, 0x2a, 0x7d, 0x4a, 0xdc, 0xb1, 0x18, + 0x4d, 0xbe, 0x90, 0x48, 0x33, 0x99, 0xb9, 0xd1, 0xba, 0x9c, 0x84, 0x5c, 0x58, 0x31, 0x61, 0x19, + 0xf7, 0xda, 0x6d, 0x39, 0xbb, 0xec, 0xdc, 0xec, 0xf0, 0x28, 0x08, 0x04, 0xe6, 0x1e, 0x14, 0xe2, + 0x07, 0x14, 0xe3, 0xab, 0xec, 0x9c, 0x43, 0xf5, 0xf8, 0xf5, 0x47, 0x0e, 0xf8, 0xb8, 0xb7, 0x2f, + 0xff, 0xe1, 0x7a, 0x91, 0x9b, 0x1f, 0xf0, 0x68, 0xc4, 0x5d, 0x41, 0x7e, 0xab, 0x09, 0x1b, 0xfd, + 0x2a, 0xa7, 0x48, 0x40, 0x82, 0x51, 0x54, 0x54, 0xd8, 0xc1, 0xcd, 0x9f, 0xaa, 0x3f, 0xc3, 0x5e, + 0xe4, 0xe7, 0xec, 0x60, 0xfa, 0x25, 0x75, 0x38, 0x75, 0x27, 0xaf, 0xc7, 0x49, 0xd7, 0x7b, 0xbf, + 0x0f, 0x85, 0x38, 0x61, 0xa0, 0x75, 0xc8, 0x3f, 0xdb, 0xc3, 0x4f, 0x9a, 0xd8, 0x58, 0x52, 0xab, + 0x13, 0xf7, 0x3c, 0x53, 0x19, 0xb7, 0x0a, 0xcb, 0xbb, 0x56, 0xdb, 0x7a, 0xd4, 0xc4, 0xf1, 0xeb, + 0x75, 0x0c, 0xd0, 0x51, 0x5f, 0x31, 0xf4, 0x00, 0x89, 0xcd, 0xad, 0x3b, 0x5f, 0x7f, 0xb3, 0xbe, + 0xf4, 0x8b, 0x6f, 0xd6, 0x97, 0x7e, 0xf9, 0xcd, 0x7a, 0xea, 0xc5, 0xe5, 0x7a, 0xea, 0xeb, 0xcb, + 0xf5, 0xd4, 0xcf, 0x2f, 0xd7, 0x53, 0xff, 0x7e, 0xb9, 0x9e, 0x3a, 0xc8, 0x4b, 0x46, 0xf6, 0xf1, + 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x36, 0x79, 0x51, 0x3a, 0xce, 0x21, 0x00, 0x00, } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/api/types.proto b/components/engine/vendor/src/github.com/docker/swarmkit/api/types.proto index 61087ada38..76724b2c8e 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/api/types.proto +++ b/components/engine/vendor/src/github.com/docker/swarmkit/api/types.proto @@ -281,15 +281,46 @@ message UpdateConfig { enum FailureAction { PAUSE = 0; CONTINUE = 1; - // TODO(aaronl): Add ROLLBACK as a supported failure mode. - // (#486) + // NOTE: Automated rollback triggered as a failure action is an + // experimental feature that is not yet exposed to the end + // user. Currently, rollbacks must be initiated manually + // through the API by setting Spec to PreviousSpec. We may + // decide to expose automatic rollback in the future based on + // user feedback, or remove this feature otherwise. + ROLLBACK = 2; } // FailureAction is the action to take when an update failures. - // Currently, a failure is defined as a single updated task failing to - // reach the RUNNING state. In the future, there will be configuration - // to define what is treated as a failure (see #486 for a proposal). FailureAction failure_action = 3; + + // Monitor indicates how long to monitor a task for failure after it is + // created. If the task fails by ending up in one of the states + // REJECTED, COMPLETED, or FAILED, within Monitor from its creation, + // this counts as a failure. If it fails after Monitor, it does not + // count as a failure. If Monitor is unspecified, a default value will + // be used. + Duration monitor = 4; + + // AllowedFailureFraction is the fraction of tasks that may fail during + // an update before the failure action is invoked. Any task created by + // the current update which ends up in one of the states REJECTED, + // COMPLETED or FAILED within Monitor from its creation counts as a + // failure. The number of failures is divided by the number of tasks + // being updated, and if this fraction is greater than + // AllowedFailureFraction, the failure action is invoked. + // + // If the failure action is CONTINUE, there is no effect. + // If the failure action is PAUSE, no more tasks will be updated until + // another update is started. + // If the failure action is ROLLBACK, the orchestrator will attempt to + // roll back to the previous service spec. If the AllowedFailureFraction + // threshold is hit during the rollback, the rollback will pause. + // + // TODO(aaronl): Should there be a separate failure threshold for + // rollbacks? Should there be a failure action for rollbacks (to allow + // them to do something other than pause when the rollback encounters + // errors)? + float allowed_failure_fraction = 5; } // UpdateStatus is the status of an update in progress. @@ -299,18 +330,21 @@ message UpdateStatus { UPDATING = 1; PAUSED = 2; COMPLETED = 3; - // TODO(aaronl): add ROLLING_BACK, ROLLED_BACK as part of - // rollback support. + ROLLBACK_STARTED = 4; + ROLLBACK_PAUSED = 5; // if a rollback fails + ROLLBACK_COMPLETED = 6; } // State is the state of this update. It indicates whether the - // update is in progress, completed, or is paused. + // update is in progress, completed, paused, rolling back, or + // finished rolling back. UpdateState state = 1; // StartedAt is the time at which the update was started. Timestamp started_at = 2; - // CompletedAt is the time at which the update completed. + // CompletedAt is the time at which the update completed successfully, + // paused, or finished rolling back. Timestamp completed_at = 3; // TODO(aaronl): Consider adding a timestamp showing when the most diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/ca/certificates.go b/components/engine/vendor/src/github.com/docker/swarmkit/ca/certificates.go index 5b302bdd2c..4283f7f3f0 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/ca/certificates.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/ca/certificates.go @@ -16,7 +16,6 @@ import ( "path/filepath" "time" - log "github.com/Sirupsen/logrus" cfcsr "github.com/cloudflare/cfssl/csr" "github.com/cloudflare/cfssl/helpers" "github.com/cloudflare/cfssl/initca" @@ -117,8 +116,7 @@ func (rca *RootCA) CanSign() bool { func (rca *RootCA) IssueAndSaveNewCertificates(paths CertPaths, cn, ou, org string) (*tls.Certificate, error) { csr, key, err := GenerateAndWriteNewKey(paths) if err != nil { - log.Debugf("error when generating new node certs: %v", err) - return nil, err + return nil, fmt.Errorf("error when generating new node certs: %v", err) } if !rca.CanSign() { @@ -128,8 +126,7 @@ func (rca *RootCA) IssueAndSaveNewCertificates(paths CertPaths, cn, ou, org stri // Obtain a signed Certificate certChain, err := rca.ParseValidateAndSignCSR(csr, cn, ou, org) if err != nil { - log.Debugf("failed to sign node certificate: %v", err) - return nil, err + return nil, fmt.Errorf("failed to sign node certificate: %v", err) } // Ensure directory exists @@ -149,20 +146,18 @@ func (rca *RootCA) IssueAndSaveNewCertificates(paths CertPaths, cn, ou, org stri return nil, err } - log.Debugf("locally issued new TLS certificate for node ID: %s and role: %s", cn, ou) return &tlsKeyPair, nil } // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is // available, or by requesting them from the remote server at remoteAddr. -func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, token string, remotes remotes.Remotes, transport credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) { +func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, token string, remotes remotes.Remotes, transport credentials.TransportCredentials, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) { // Create a new key/pair and CSR for the new manager // Write the new CSR and the new key to a temporary location so we can survive crashes on rotation tempPaths := genTempPaths(paths) csr, key, err := GenerateAndWriteNewKey(tempPaths) if err != nil { - log.Debugf("error when generating new node certs: %v", err) - return nil, err + return nil, fmt.Errorf("error when generating new node certs: %v", err) } // Get the remote manager to issue a CA signed certificate for this node @@ -174,7 +169,6 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert if err == nil { break } - log.Warningf("error fetching signed node certificate: %v", err) } if err != nil { return nil, err @@ -206,10 +200,6 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert return nil, err } - if len(X509Cert.Subject.OrganizationalUnit) != 0 { - log.Infof("Downloaded new TLS credentials with role: %s.", X509Cert.Subject.OrganizationalUnit[0]) - } - // Ensure directory exists err = os.MkdirAll(filepath.Dir(paths.Cert), 0755) if err != nil { @@ -259,8 +249,7 @@ func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string) cert, err := rca.Signer.Sign(signRequest) if err != nil { - log.Debugf("failed to sign node certificate: %v", err) - return nil, err + return nil, fmt.Errorf("failed to sign node certificate: %v", err) } return rca.AppendFirstRootPEM(cert) @@ -342,8 +331,7 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er if err != nil { priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev) if err != nil { - log.Debug("Malformed private key %v", err) - return RootCA{}, err + return RootCA{}, fmt.Errorf("Malformed private key: %v", err) } } @@ -414,12 +402,7 @@ func GetLocalRootCA(baseDir string) (RootCA, error) { key = nil } - rootCA, err := NewRootCA(cert, key, DefaultNodeCertExpiration) - if err == nil { - log.Debugf("successfully loaded the Root CA: %s", paths.RootCA.Cert) - } - - return rootCA, err + return NewRootCA(cert, key, DefaultNodeCertExpiration) } // GetRemoteCA returns the remote endpoint's CA certificate @@ -552,8 +535,7 @@ func GenerateAndSignNewTLSCert(rootCA RootCA, cn, ou, org string, paths CertPath // Obtain a signed Certificate certChain, err := rootCA.ParseValidateAndSignCSR(csr, cn, ou, org) if err != nil { - log.Debugf("failed to sign node certificate: %v", err) - return nil, err + return nil, fmt.Errorf("failed to sign node certificate: %v", err) } // Ensure directory exists @@ -603,7 +585,7 @@ func GenerateAndWriteNewKey(paths CertPaths) (csr, key []byte, err error) { // GetRemoteSignedCertificate submits a CSR to a remote CA server address, // and that is part of a CA identified by a specific certificate pool. -func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, r remotes.Remotes, creds credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) { +func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, r remotes.Remotes, creds credentials.TransportCredentials, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) { if rootCAPool == nil { return nil, fmt.Errorf("valid root CA pool required") } @@ -653,7 +635,6 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r Max: 30 * time.Second, }) - log.Infof("Waiting for TLS certificate to be issued...") // Exponential backoff with Max of 30 seconds to wait for a new retry for { // Send the Request and retrieve the certificate @@ -694,7 +675,6 @@ func readCertExpiration(paths CertPaths) (time.Duration, error) { // Read the Cert cert, err := ioutil.ReadFile(paths.Cert) if err != nil { - log.Debugf("failed to read certificate file: %s", paths.Cert) return time.Hour, err } @@ -730,7 +710,6 @@ func generateNewCSR() (csr, key []byte, err error) { csr, key, err = cfcsr.ParseRequest(req) if err != nil { - log.Debugf(`failed to generate CSR`) return } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/ca/config.go b/components/engine/vendor/src/github.com/docker/swarmkit/ca/config.go index 43e8f850f6..c18540bd6e 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/ca/config.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/ca/config.go @@ -15,11 +15,12 @@ import ( "sync" "time" - log "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus" cfconfig "github.com/cloudflare/cfssl/config" "github.com/docker/distribution/digest" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/identity" + "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/remotes" "golang.org/x/net/context" @@ -35,8 +36,8 @@ const ( rootCN = "swarm-ca" // ManagerRole represents the Manager node type, and is used for authorization to endpoints ManagerRole = "swarm-manager" - // AgentRole represents the Agent node type, and is used for authorization to endpoints - AgentRole = "swarm-worker" + // WorkerRole represents the Worker node type, and is used for authorization to endpoints + WorkerRole = "swarm-worker" // CARole represents the CA node type, and is used for clients attempting to get new certificates issued CARole = "swarm-ca" @@ -184,6 +185,7 @@ func getCAHashFromToken(token string) (digest.Digest, error) { // Every node requires at least a set of TLS certificates with which to join the cluster with. // In the case of a manager, these certificates will be used both for client and server credentials. func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, proposedRole string, remotes remotes.Remotes, nodeInfo chan<- api.IssueNodeCertificateResponse) (*SecurityConfig, error) { + ctx = log.WithModule(ctx, "tls") paths := NewConfigPaths(baseCertDir) var ( @@ -196,9 +198,9 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose rootCA, err = GetLocalRootCA(baseCertDir) switch err { case nil: - log.Debugf("loaded local CA certificate: %s.", paths.RootCA.Cert) + log.G(ctx).Debug("loaded CA certificate") case ErrNoLocalRootCA: - log.Debugf("no valid local CA certificate found: %v", err) + log.G(ctx).WithError(err).Debugf("failed to load local CA certificate") // Get a digest for the optional CA hash string that we've been provided // If we were provided a non-empty string, and it is an invalid hash, return @@ -221,7 +223,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose if err == nil { break } - log.Warningf("failed to retrieve remote root CA certificate: %v", err) + log.G(ctx).WithError(err).Errorf("failed to retrieve remote root CA certificate") } if err != nil { return nil, err @@ -232,7 +234,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose return nil, err } - log.Debugf("downloaded remote CA certificate.") + log.G(ctx).Debugf("retrieved remote CA certificate: %s", paths.RootCA.Cert) default: return nil, err } @@ -242,7 +244,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose // load our certificates. clientTLSCreds, serverTLSCreds, err = LoadTLSCreds(rootCA, paths.Node) if err != nil { - log.Debugf("no valid local TLS credentials found: %v", err) + log.G(ctx).WithError(err).Debugf("no node credentials found in: %s", paths.Node.Cert) var ( tlsKeyPair *tls.Certificate @@ -262,17 +264,27 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose } tlsKeyPair, err = rootCA.IssueAndSaveNewCertificates(paths.Node, cn, proposedRole, org) if err != nil { + log.G(ctx).WithFields(logrus.Fields{ + "node.id": cn, + "node.role": proposedRole, + }).WithError(err).Errorf("failed to issue and save new certificate") return nil, err } + + log.G(ctx).WithFields(logrus.Fields{ + "node.id": cn, + "node.role": proposedRole, + }).Debug("issued new TLS certificate") } else { // There was an error loading our Credentials, let's get a new certificate issued // Last argument is nil because at this point we don't have any valid TLS creds tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, paths.Node, token, remotes, nil, nodeInfo) if err != nil { + log.G(ctx).WithError(err).Error("failed to request save new certificate") return nil, err } } - // Create the Server TLS Credentials for this node. These will not be used by agents. + // Create the Server TLS Credentials for this node. These will not be used by workers. serverTLSCreds, err = rootCA.NewServerTLSCredentials(tlsKeyPair) if err != nil { return nil, err @@ -284,7 +296,10 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose if err != nil { return nil, err } - log.Debugf("new TLS credentials generated: %s.", paths.Node.Cert) + log.G(ctx).WithFields(logrus.Fields{ + "node.id": clientTLSCreds.NodeID(), + "node.role": clientTLSCreds.Role(), + }).Debugf("new node credentials generated: %s", paths.Node.Cert) } else { if nodeInfo != nil { nodeInfo <- api.IssueNodeCertificateResponse{ @@ -292,7 +307,10 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, propose NodeMembership: api.NodeMembershipAccepted, } } - log.Debugf("loaded local TLS credentials: %s.", paths.Node.Cert) + log.G(ctx).WithFields(logrus.Fields{ + "node.id": clientTLSCreds.NodeID(), + "node.role": clientTLSCreds.Role(), + }).Debug("loaded node credentials") } return NewSecurityConfig(&rootCA, clientTLSCreds, serverTLSCreds), nil @@ -308,6 +326,11 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, var retry time.Duration defer close(updates) for { + ctx = log.WithModule(ctx, "tls") + log := log.G(ctx).WithFields(logrus.Fields{ + "node.id": s.ClientTLSCreds.NodeID(), + "node.role": s.ClientTLSCreds.Role(), + }) // Our starting default will be 5 minutes retry = 5 * time.Minute @@ -323,21 +346,27 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, // If we have an expired certificate, we let's stick with the starting default in // the hope that this is a temporary clock skew. if expiresIn.Minutes() < 0 { - log.Debugf("failed to create a new client TLS config: %v", err) - updates <- CertificateUpdate{Err: fmt.Errorf("TLS Certificate is expired")} + log.WithError(err).Errorf("failed to create a new client TLS config") + updates <- CertificateUpdate{Err: fmt.Errorf("TLS certificate is expired")} } else { // Random retry time between 50% and 80% of the total time to expiration retry = calculateRandomExpiry(expiresIn) } } + log.WithFields(logrus.Fields{ + "time": time.Now().Add(retry), + }).Debugf("next certificate renewal scheduled") + select { case <-time.After(retry): + log.Infof("renewing certificate") case <-renew: + log.Infof("forced certificate renewal") case <-ctx.Done(): + log.Infof("shuting down certificate renewal routine") return } - log.Infof("Renewing TLS Certificate.") // Let's request new certs. Renewals don't require a token. rootCA := s.RootCA() @@ -348,25 +377,25 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, s.ClientTLSCreds, nil) if err != nil { - log.Debugf("failed to renew the TLS Certificate: %v", err) + log.WithError(err).Errorf("failed to renew the certificate") updates <- CertificateUpdate{Err: err} continue } clientTLSConfig, err := NewClientTLSConfig(tlsKeyPair, rootCA.Pool, CARole) if err != nil { - log.Debugf("failed to create a new client TLS config: %v", err) + log.WithError(err).Errorf("failed to create a new client config") updates <- CertificateUpdate{Err: err} } serverTLSConfig, err := NewServerTLSConfig(tlsKeyPair, rootCA.Pool) if err != nil { - log.Debugf("failed to create a new server TLS config: %v", err) + log.WithError(err).Errorf("failed to create a new server config") updates <- CertificateUpdate{Err: err} } err = s.ClientTLSCreds.LoadNewTLSConfig(clientTLSConfig) if err != nil { - log.Debugf("failed to update the client TLS credentials: %v", err) + log.WithError(err).Errorf("failed to update the client credentials") updates <- CertificateUpdate{Err: err} } @@ -380,7 +409,7 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string, err = s.ServerTLSCreds.LoadNewTLSConfig(serverTLSConfig) if err != nil { - log.Debugf("failed to update the server TLS credentials: %v", err) + log.WithError(err).Errorf("failed to update the server TLS credentials") updates <- CertificateUpdate{Err: err} } @@ -478,7 +507,7 @@ func LoadTLSCreds(rootCA RootCA, paths CertPaths) (*MutableTLSCreds, *MutableTLS } // Load the Certificates also as client credentials. - // Both Agents and Managers always connect to remote Managers, + // Both workers and managers always connect to remote managers, // so ServerName is always set to ManagerRole here. clientTLSCreds, err := rootCA.NewClientTLSCredentials(&keyPair, ManagerRole) if err != nil { @@ -561,7 +590,7 @@ func ParseRole(apiRole api.NodeRole) (string, error) { case api.NodeRoleManager: return ManagerRole, nil case api.NodeRoleWorker: - return AgentRole, nil + return WorkerRole, nil default: return "", fmt.Errorf("failed to parse api role: %v", apiRole) } @@ -572,7 +601,7 @@ func FormatRole(role string) (api.NodeRole, error) { switch strings.ToLower(role) { case strings.ToLower(ManagerRole): return api.NodeRoleManager, nil - case strings.ToLower(AgentRole): + case strings.ToLower(WorkerRole): return api.NodeRoleWorker, nil default: return 0, fmt.Errorf("failed to parse role: %s", role) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/ca/server.go b/components/engine/vendor/src/github.com/docker/swarmkit/ca/server.go index 3df0674eea..c7d5a94c22 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/ca/server.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/ca/server.go @@ -149,14 +149,14 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod } defer s.doneTask() - // If the remote node is an Agent (either forwarded by a manager, or calling directly), - // issue a renew agent certificate entry with the correct ID - nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{AgentRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization()) + // If the remote node is a worker (either forwarded by a manager, or calling directly), + // issue a renew worker certificate entry with the correct ID + nodeID, err := AuthorizeForwardedRoleAndOrg(ctx, []string{WorkerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization()) if err == nil { return s.issueRenewCertificate(ctx, nodeID, request.CSR) } - // If the remote node is a Manager (either forwarded by another manager, or calling directly), + // If the remote node is a manager (either forwarded by another manager, or calling directly), // issue a renew certificate entry with the correct ID nodeID, err = AuthorizeForwardedRoleAndOrg(ctx, []string{ManagerRole}, []string{ManagerRole}, s.securityConfig.ClientTLSCreds.Organization()) if err == nil { diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/ca/transport.go b/components/engine/vendor/src/github.com/docker/swarmkit/ca/transport.go index aa9884d173..ab208664d3 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/ca/transport.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/ca/transport.go @@ -8,7 +8,6 @@ import ( "net" "strings" "sync" - "time" "google.golang.org/grpc/credentials" @@ -33,12 +32,12 @@ type MutableTLSCreds struct { // TLS configuration config *tls.Config // TLS Credentials - tlsCreds credentials.TransportAuthenticator + tlsCreds credentials.TransportCredentials // store the subject for easy access subject pkix.Name } -// Info implements the credentials.TransportAuthenticator interface +// Info implements the credentials.TransportCredentials interface func (c *MutableTLSCreds) Info() credentials.ProtocolInfo { return credentials.ProtocolInfo{ SecurityProtocol: "tls", @@ -46,26 +45,19 @@ func (c *MutableTLSCreds) Info() credentials.ProtocolInfo { } } -// GetRequestMetadata implements the credentials.TransportAuthenticator interface +// GetRequestMetadata implements the credentials.TransportCredentials interface func (c *MutableTLSCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return nil, nil } -// RequireTransportSecurity implements the credentials.TransportAuthenticator interface +// RequireTransportSecurity implements the credentials.TransportCredentials interface func (c *MutableTLSCreds) RequireTransportSecurity() bool { return true } -// ClientHandshake implements the credentials.TransportAuthenticator interface -func (c *MutableTLSCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, credentials.AuthInfo, error) { +// ClientHandshake implements the credentials.TransportCredentials interface +func (c *MutableTLSCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { // borrow all the code from the original TLS credentials - var errChannel chan error - if timeout != 0 { - errChannel = make(chan error, 2) - time.AfterFunc(timeout, func() { - errChannel <- timeoutError{} - }) - } c.Lock() if c.config.ServerName == "" { colonPos := strings.LastIndex(addr, ":") @@ -80,23 +72,23 @@ func (c *MutableTLSCreds) ClientHandshake(addr string, rawConn net.Conn, timeout // would create a deadlock otherwise c.Unlock() var err error - if timeout == 0 { - err = conn.Handshake() - } else { - go func() { - errChannel <- conn.Handshake() - }() - err = <-errChannel + errChannel := make(chan error, 1) + go func() { + errChannel <- conn.Handshake() + }() + select { + case err = <-errChannel: + case <-ctx.Done(): + err = ctx.Err() } if err != nil { rawConn.Close() return nil, nil, err } - return conn, nil, nil } -// ServerHandshake implements the credentials.TransportAuthenticator interface +// ServerHandshake implements the credentials.TransportCredentials interface func (c *MutableTLSCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { c.Lock() conn := tls.Server(rawConn, c.config) @@ -132,7 +124,7 @@ func (c *MutableTLSCreds) Config() *tls.Config { return c.config } -// Role returns the OU for the certificate encapsulated in this TransportAuthenticator +// Role returns the OU for the certificate encapsulated in this TransportCredentials func (c *MutableTLSCreds) Role() string { c.Lock() defer c.Unlock() @@ -140,7 +132,7 @@ func (c *MutableTLSCreds) Role() string { return c.subject.OrganizationalUnit[0] } -// Organization returns the O for the certificate encapsulated in this TransportAuthenticator +// Organization returns the O for the certificate encapsulated in this TransportCredentials func (c *MutableTLSCreds) Organization() string { c.Lock() defer c.Unlock() @@ -148,7 +140,7 @@ func (c *MutableTLSCreds) Organization() string { return c.subject.Organization[0] } -// NodeID returns the CN for the certificate encapsulated in this TransportAuthenticator +// NodeID returns the CN for the certificate encapsulated in this TransportCredentials func (c *MutableTLSCreds) NodeID() string { c.Lock() defer c.Unlock() @@ -156,7 +148,7 @@ func (c *MutableTLSCreds) NodeID() string { return c.subject.CommonName } -// NewMutableTLS uses c to construct a mutable TransportAuthenticator based on TLS. +// NewMutableTLS uses c to construct a mutable TransportCredentials based on TLS. func NewMutableTLS(c *tls.Config) (*MutableTLSCreds, error) { originalTC := credentials.NewTLS(c) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/network.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/network.go index 3e21d425c1..e1b40c8b91 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/network.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/network.go @@ -564,7 +564,9 @@ func (a *Allocator) allocateNode(ctx context.Context, nc *networkContext, node * func (a *Allocator) allocateService(ctx context.Context, nc *networkContext, s *api.Service) error { if s.Spec.Endpoint != nil { + // service has user-defined endpoint if s.Endpoint == nil { + // service currently has no allocated endpoint, need allocated. s.Endpoint = &api.Endpoint{ Spec: s.Spec.Endpoint.Copy(), } @@ -587,6 +589,12 @@ func (a *Allocator) allocateService(ctx context.Context, nc *networkContext, s * &api.Endpoint_VirtualIP{NetworkID: nc.ingressNetwork.ID}) } } + } else if s.Endpoint != nil { + // service has no user-defined endpoints while has already allocated network resources, + // need deallocated. + if err := nc.nwkAllocator.ServiceDeallocate(s); err != nil { + return err + } } if err := nc.nwkAllocator.ServiceAllocate(s); err != nil { diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go index 10843b73e4..cbc12575f1 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/portallocator.go @@ -155,7 +155,18 @@ func (pa *portAllocator) serviceDeallocatePorts(s *api.Service) { } func (pa *portAllocator) isPortsAllocated(s *api.Service) bool { - if s.Endpoint == nil { + // If service has no user-defined endpoint and allocated endpoint, + // we assume it is allocated and return true. + if s.Endpoint == nil && s.Spec.Endpoint == nil { + return true + } + + // If service has allocated endpoint while has no user-defined endpoint, + // we assume allocated endpoints are redudant, and they need deallocated. + // If service has no allocated endpoint while has user-defined endpoint, + // we assume it is not allocated. + if (s.Endpoint != nil && s.Spec.Endpoint == nil) || + (s.Endpoint == nil && s.Spec.Endpoint != nil) { return false } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/cluster.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/cluster.go deleted file mode 100644 index 60d9ba6cdd..0000000000 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/cluster.go +++ /dev/null @@ -1,12 +0,0 @@ -package hackpicker - -// AddrSelector is interface which should track cluster for its leader address. -type AddrSelector interface { - LeaderAddr() (string, error) -} - -// RaftCluster is interface which combines useful methods for clustering. -type RaftCluster interface { - AddrSelector - IsLeader() bool -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/raftpicker.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/raftpicker.go deleted file mode 100644 index baa11542f3..0000000000 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/hackpicker/raftpicker.go +++ /dev/null @@ -1,141 +0,0 @@ -// Package hackpicker is temporary solution to provide more seamless experience -// for controlapi. It has drawback of slow reaction to leader change, but it -// tracks leader automatically without erroring out to client. -package hackpicker - -import ( - "sync" - - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/transport" -) - -// picker always picks address of cluster leader. -type picker struct { - mu sync.Mutex - addr string - raft AddrSelector - conn *grpc.Conn - cc *grpc.ClientConn -} - -// Init does initial processing for the Picker, e.g., initiate some connections. -func (p *picker) Init(cc *grpc.ClientConn) error { - p.cc = cc - return nil -} - -func (p *picker) initConn() error { - if p.conn == nil { - conn, err := grpc.NewConn(p.cc) - if err != nil { - return err - } - p.conn = conn - } - return nil -} - -// Pick blocks until either a transport.ClientTransport is ready for the upcoming RPC -// or some error happens. -func (p *picker) Pick(ctx context.Context) (transport.ClientTransport, error) { - p.mu.Lock() - if err := p.initConn(); err != nil { - p.mu.Unlock() - return nil, err - } - p.mu.Unlock() - - addr, err := p.raft.LeaderAddr() - if err != nil { - return nil, err - } - p.mu.Lock() - if p.addr != addr { - p.addr = addr - p.conn.NotifyReset() - } - p.mu.Unlock() - return p.conn.Wait(ctx) -} - -// PickAddr picks a peer address for connecting. This will be called repeated for -// connecting/reconnecting. -func (p *picker) PickAddr() (string, error) { - addr, err := p.raft.LeaderAddr() - if err != nil { - return "", err - } - p.mu.Lock() - p.addr = addr - p.mu.Unlock() - return addr, nil -} - -// State returns the connectivity state of the underlying connections. -func (p *picker) State() (grpc.ConnectivityState, error) { - return p.conn.State(), nil -} - -// WaitForStateChange blocks until the state changes to something other than -// the sourceState. It returns the new state or error. -func (p *picker) WaitForStateChange(ctx context.Context, sourceState grpc.ConnectivityState) (grpc.ConnectivityState, error) { - return p.conn.WaitForStateChange(ctx, sourceState) -} - -// Reset the current connection and force a reconnect to another address. -func (p *picker) Reset() error { - p.conn.NotifyReset() - return nil -} - -// Close closes all the Conn's owned by this Picker. -func (p *picker) Close() error { - return p.conn.Close() -} - -// ConnSelector is struct for obtaining connection with raftpicker. -type ConnSelector struct { - mu sync.Mutex - cc *grpc.ClientConn - cluster RaftCluster - opts []grpc.DialOption -} - -// NewConnSelector returns new ConnSelector with cluster and grpc.DialOpts which -// will be used for Dial on first call of Conn. -func NewConnSelector(cluster RaftCluster, opts ...grpc.DialOption) *ConnSelector { - return &ConnSelector{ - cluster: cluster, - opts: opts, - } -} - -// Conn returns *grpc.ClientConn with picker which picks raft cluster leader. -// Internal connection estabilished lazily on this call. -// It can return error if cluster wasn't ready at the moment of initial call. -func (c *ConnSelector) Conn() (*grpc.ClientConn, error) { - c.mu.Lock() - defer c.mu.Unlock() - if c.cc != nil { - return c.cc, nil - } - addr, err := c.cluster.LeaderAddr() - if err != nil { - return nil, err - } - picker := &picker{raft: c.cluster, addr: addr} - opts := append(c.opts, grpc.WithPicker(picker)) - cc, err := grpc.Dial(addr, opts...) - if err != nil { - return nil, err - } - c.cc = cc - return c.cc, nil -} - -// Reset does nothing for hackpicker. -func (c *ConnSelector) Reset() error { - return nil -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go index 656533d970..9336462562 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go @@ -5,7 +5,7 @@ import ( "reflect" "strconv" - "github.com/docker/engine-api/types/reference" + "github.com/docker/distribution/reference" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/identity" "github.com/docker/swarmkit/manager/scheduler" @@ -133,7 +133,7 @@ func validateTask(taskSpec api.TaskSpec) error { return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: image reference must be provided") } - if _, _, err := reference.Parse(container.Image); err != nil { + if _, err := reference.ParseNamed(container.Image); err != nil { return grpc.Errorf(codes.InvalidArgument, "ContainerSpec: %q is not a valid repository/tag", container.Image) } return nil @@ -149,13 +149,13 @@ func validateEndpointSpec(epSpec *api.EndpointSpec) error { return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: ports can't be used with dnsrr mode") } - portSet := make(map[api.PortConfig]struct{}) + portSet := make(map[uint32]struct{}) for _, port := range epSpec.Ports { - if _, ok := portSet[*port]; ok { - return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: duplicate ports provided") + if _, ok := portSet[port.PublishedPort]; ok { + return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: duplicate published ports provided") } - portSet[*port] = struct{}{} + portSet[port.PublishedPort] = struct{}{} } return nil @@ -350,6 +350,7 @@ func (s *Server) UpdateService(ctx context.Context, request *api.UpdateServiceRe return errModeChangeNotAllowed } service.Meta.Version = *request.ServiceVersion + service.PreviousSpec = service.Spec.Copy() service.Spec = *request.Spec.Copy() // Reset update status diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go index 765651983f..9ae3e0b66a 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go @@ -3,6 +3,7 @@ package dispatcher import ( "errors" "fmt" + "strconv" "sync" "time" @@ -41,6 +42,9 @@ const ( // into a single transaction. A fraction of a second feels about // right. maxBatchInterval = 100 * time.Millisecond + + modificationBatchLimit = 100 + batchingWaitTime = 100 * time.Millisecond ) var ( @@ -127,8 +131,6 @@ func New(cluster Cluster, c *Config) *Dispatcher { nodes: newNodeStore(c.HeartbeatPeriod, c.HeartbeatEpsilon, c.GracePeriodMultiplier, c.RateLimitPeriod), store: cluster.MemoryStore(), cluster: cluster, - mgrQueue: watch.NewQueue(), - keyMgrQueue: watch.NewQueue(), taskUpdates: make(map[string]*api.TaskStatus), nodeUpdates: make(map[string]nodeUpdate), processUpdatesTrigger: make(chan struct{}, 1), @@ -195,6 +197,9 @@ func (d *Dispatcher) Run(ctx context.Context) error { d.mu.Unlock() return err } + // set queues here to guarantee that Close will close them + d.mgrQueue = watch.NewQueue() + d.keyMgrQueue = watch.NewQueue() peerWatcher, peerCancel := d.cluster.SubscribePeers() defer peerCancel() @@ -351,6 +356,37 @@ func (d *Dispatcher) isRunning() bool { return true } +// updateNode updates the description of a node and sets status to READY +// this is used during registration when a new node description is provided +// and during node updates when the node description changes +func (d *Dispatcher) updateNode(nodeID string, description *api.NodeDescription) error { + d.nodeUpdatesLock.Lock() + d.nodeUpdates[nodeID] = nodeUpdate{status: &api.NodeStatus{State: api.NodeStatus_READY}, description: description} + numUpdates := len(d.nodeUpdates) + d.nodeUpdatesLock.Unlock() + + if numUpdates >= maxBatchItems { + select { + case d.processUpdatesTrigger <- struct{}{}: + case <-d.ctx.Done(): + return d.ctx.Err() + } + + } + + // Wait until the node update batch happens before unblocking register. + d.processUpdatesLock.Lock() + select { + case <-d.ctx.Done(): + return d.ctx.Err() + default: + } + d.processUpdatesCond.Wait() + d.processUpdatesLock.Unlock() + + return nil +} + // register is used for registration of node with particular dispatcher. func (d *Dispatcher) register(ctx context.Context, nodeID string, description *api.NodeDescription) (string, error) { // prevent register until we're ready to accept it @@ -371,30 +407,10 @@ func (d *Dispatcher) register(ctx context.Context, nodeID string, description *a return "", ErrNodeNotFound } - d.nodeUpdatesLock.Lock() - d.nodeUpdates[nodeID] = nodeUpdate{status: &api.NodeStatus{State: api.NodeStatus_READY}, description: description} - numUpdates := len(d.nodeUpdates) - d.nodeUpdatesLock.Unlock() - - if numUpdates >= maxBatchItems { - select { - case d.processUpdatesTrigger <- struct{}{}: - case <-d.ctx.Done(): - return "", d.ctx.Err() - } - + if err := d.updateNode(nodeID, description); err != nil { + return "", err } - // Wait until the node update batch happens before unblocking register. - d.processUpdatesLock.Lock() - select { - case <-d.ctx.Done(): - return "", d.ctx.Err() - default: - } - d.processUpdatesCond.Wait() - d.processUpdatesLock.Unlock() - expireFunc := func() { nodeStatus := api.NodeStatus{State: api.NodeStatus_DOWN, Message: "heartbeat failure"} log.G(ctx).Debugf("heartbeat expiration") @@ -657,14 +673,10 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe } // bursty events should be processed in batches and sent out snapshot - const ( - modificationBatchLimit = 200 - eventPausedGap = 50 * time.Millisecond - ) var ( - modificationCnt int - eventPausedTimer *time.Timer - eventPausedTimeout <-chan time.Time + modificationCnt int + batchingTimer *time.Timer + batchingTimeout <-chan time.Time ) batchingLoop: @@ -692,13 +704,13 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe delete(tasksMap, v.Task.ID) modificationCnt++ } - if eventPausedTimer != nil { - eventPausedTimer.Reset(eventPausedGap) + if batchingTimer != nil { + batchingTimer.Reset(batchingWaitTime) } else { - eventPausedTimer = time.NewTimer(eventPausedGap) - eventPausedTimeout = eventPausedTimer.C + batchingTimer = time.NewTimer(batchingWaitTime) + batchingTimeout = batchingTimer.C } - case <-eventPausedTimeout: + case <-batchingTimeout: break batchingLoop case <-stream.Context().Done(): return stream.Context().Err() @@ -707,8 +719,198 @@ func (d *Dispatcher) Tasks(r *api.TasksRequest, stream api.Dispatcher_TasksServe } } - if eventPausedTimer != nil { - eventPausedTimer.Stop() + if batchingTimer != nil { + batchingTimer.Stop() + } + } +} + +// Assignments is a stream of assignments for a node. Each message contains +// either full list of tasks and secrets for the node, or an incremental update. +func (d *Dispatcher) Assignments(r *api.AssignmentsRequest, stream api.Dispatcher_AssignmentsServer) error { + nodeInfo, err := ca.RemoteNode(stream.Context()) + if err != nil { + return err + } + nodeID := nodeInfo.NodeID + + if err := d.isRunningLocked(); err != nil { + return err + } + + fields := logrus.Fields{ + "node.id": nodeID, + "node.session": r.SessionID, + "method": "(*Dispatcher).Assignments", + } + if nodeInfo.ForwardedBy != nil { + fields["forwarder.id"] = nodeInfo.ForwardedBy.NodeID + } + log := log.G(stream.Context()).WithFields(fields) + log.Debugf("") + + if _, err = d.nodes.GetWithSession(nodeID, r.SessionID); err != nil { + return err + } + + var ( + sequence int64 + appliesTo string + initial api.AssignmentsMessage + ) + tasksMap := make(map[string]*api.Task) + + sendMessage := func(msg api.AssignmentsMessage, assignmentType api.AssignmentsMessage_Type) error { + sequence++ + msg.AppliesTo = appliesTo + msg.ResultsIn = strconv.FormatInt(sequence, 10) + appliesTo = msg.ResultsIn + msg.Type = assignmentType + + if err := stream.Send(&msg); err != nil { + return err + } + return nil + } + + // TODO(aaronl): Also send node secrets that should be exposed to + // this node. + nodeTasks, cancel, err := store.ViewAndWatch( + d.store, + func(readTx store.ReadTx) error { + tasks, err := store.FindTasks(readTx, store.ByNodeID(nodeID)) + if err != nil { + return err + } + + for _, t := range tasks { + // We only care about tasks that are ASSIGNED or + // higher. If the state is below ASSIGNED, the + // task may not meet the constraints for this + // node, so we have to be careful about sending + // secrets associated with it. + if t.Status.State < api.TaskStateAssigned { + continue + } + + tasksMap[t.ID] = t + initial.UpdateTasks = append(initial.UpdateTasks, t) + } + return nil + }, + state.EventUpdateTask{Task: &api.Task{NodeID: nodeID}, + Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}}, + state.EventDeleteTask{Task: &api.Task{NodeID: nodeID}, + Checks: []state.TaskCheckFunc{state.TaskCheckNodeID}}, + ) + if err != nil { + return err + } + defer cancel() + + if err := sendMessage(initial, api.AssignmentsMessage_COMPLETE); err != nil { + return err + } + + for { + // Check for session expiration + if _, err := d.nodes.GetWithSession(nodeID, r.SessionID); err != nil { + return err + } + + // bursty events should be processed in batches and sent out together + var ( + update api.AssignmentsMessage + modificationCnt int + batchingTimer *time.Timer + batchingTimeout <-chan time.Time + updateTasks = make(map[string]*api.Task) + removeTasks = make(map[string]struct{}) + ) + + oneModification := func() { + modificationCnt++ + + if batchingTimer != nil { + batchingTimer.Reset(batchingWaitTime) + } else { + batchingTimer = time.NewTimer(batchingWaitTime) + batchingTimeout = batchingTimer.C + } + } + + // The batching loop waits for 50 ms after the most recent + // change, or until modificationBatchLimit is reached. The + // worst case latency is modificationBatchLimit * batchingWaitTime, + // which is 10 seconds. + batchingLoop: + for modificationCnt < modificationBatchLimit { + select { + case event := <-nodeTasks: + switch v := event.(type) { + // We don't monitor EventCreateTask because tasks are + // never created in the ASSIGNED state. First tasks are + // created by the orchestrator, then the scheduler moves + // them to ASSIGNED. If this ever changes, we will need + // to monitor task creations as well. + case state.EventUpdateTask: + // We only care about tasks that are ASSIGNED or + // higher. + if v.Task.Status.State < api.TaskStateAssigned { + continue + } + + if oldTask, exists := tasksMap[v.Task.ID]; exists { + // States ASSIGNED and below are set by the orchestrator/scheduler, + // not the agent, so tasks in these states need to be sent to the + // agent even if nothing else has changed. + if equality.TasksEqualStable(oldTask, v.Task) && v.Task.Status.State > api.TaskStateAssigned { + // this update should not trigger a task change for the agent + tasksMap[v.Task.ID] = v.Task + continue + } + } + tasksMap[v.Task.ID] = v.Task + updateTasks[v.Task.ID] = v.Task + + oneModification() + case state.EventDeleteTask: + + if _, exists := tasksMap[v.Task.ID]; !exists { + continue + } + + removeTasks[v.Task.ID] = struct{}{} + + delete(tasksMap, v.Task.ID) + + oneModification() + } + case <-batchingTimeout: + break batchingLoop + case <-stream.Context().Done(): + return stream.Context().Err() + case <-d.ctx.Done(): + return d.ctx.Err() + } + } + + if batchingTimer != nil { + batchingTimer.Stop() + } + + if modificationCnt > 0 { + for id, task := range updateTasks { + if _, ok := removeTasks[id]; !ok { + update.UpdateTasks = append(update.UpdateTasks, task) + } + } + for id := range removeTasks { + update.RemoveTasks = append(update.RemoveTasks, id) + } + if err := sendMessage(update, api.AssignmentsMessage_INCREMENTAL); err != nil { + return err + } } } } @@ -787,6 +989,10 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio } } else { sessionID = r.SessionID + // update the node description + if err := d.updateNode(nodeID, r.Description); err != nil { + return err + } } fields := logrus.Fields{ diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/manager.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/manager.go index 6c95e8ada7..7f9dbad98f 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/manager.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/manager.go @@ -9,7 +9,6 @@ import ( "path/filepath" "sync" "syscall" - "time" "github.com/Sirupsen/logrus" "github.com/docker/go-events" @@ -18,12 +17,10 @@ import ( "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/allocator" "github.com/docker/swarmkit/manager/controlapi" - "github.com/docker/swarmkit/manager/controlapi/hackpicker" "github.com/docker/swarmkit/manager/dispatcher" "github.com/docker/swarmkit/manager/health" "github.com/docker/swarmkit/manager/keymanager" "github.com/docker/swarmkit/manager/orchestrator" - "github.com/docker/swarmkit/manager/raftpicker" "github.com/docker/swarmkit/manager/resourceapi" "github.com/docker/swarmkit/manager/scheduler" "github.com/docker/swarmkit/manager/state/raft" @@ -92,7 +89,6 @@ type Manager struct { server *grpc.Server localserver *grpc.Server RaftNode *raft.Node - connSelector *raftpicker.ConnSelector mu sync.Mutex @@ -250,25 +246,6 @@ func (m *Manager) Run(parent context.Context) error { go m.handleLeadershipEvents(ctx, leadershipCh) - proxyOpts := []grpc.DialOption{ - grpc.WithTimeout(5 * time.Second), - grpc.WithTransportCredentials(m.config.SecurityConfig.ClientTLSCreds), - } - - cs := raftpicker.NewConnSelector(m.RaftNode, proxyOpts...) - m.connSelector = cs - - // We need special connSelector for controlapi because it provides automatic - // leader tracking. - // Other APIs are using connSelector which errors out on leader change, but - // allows to react quickly to reelections. - controlAPIProxyOpts := []grpc.DialOption{ - grpc.WithBackoffMaxDelay(time.Second), - grpc.WithTransportCredentials(m.config.SecurityConfig.ClientTLSCreds), - } - - controlAPIConnSelector := hackpicker.NewConnSelector(m.RaftNode, controlAPIProxyOpts...) - authorize := func(ctx context.Context, roles []string) error { // Authorize the remote roles, ensure they can only be forwarded by managers _, err := ca.AuthorizeForwardedRoleAndOrg(ctx, roles, []string{ca.ManagerRole}, m.config.SecurityConfig.ClientTLSCreds.Organization()) @@ -289,11 +266,11 @@ func (m *Manager) Run(parent context.Context) error { authenticatedHealthAPI := api.NewAuthenticatedWrapperHealthServer(healthServer, authorize) authenticatedRaftMembershipAPI := api.NewAuthenticatedWrapperRaftMembershipServer(m.RaftNode, authorize) - proxyDispatcherAPI := api.NewRaftProxyDispatcherServer(authenticatedDispatcherAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo) - proxyCAAPI := api.NewRaftProxyCAServer(authenticatedCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo) - proxyNodeCAAPI := api.NewRaftProxyNodeCAServer(authenticatedNodeCAAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo) - proxyRaftMembershipAPI := api.NewRaftProxyRaftMembershipServer(authenticatedRaftMembershipAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo) - proxyResourceAPI := api.NewRaftProxyResourceAllocatorServer(authenticatedResourceAPI, cs, m.RaftNode, ca.WithMetadataForwardTLSInfo) + proxyDispatcherAPI := api.NewRaftProxyDispatcherServer(authenticatedDispatcherAPI, m.RaftNode, ca.WithMetadataForwardTLSInfo) + proxyCAAPI := api.NewRaftProxyCAServer(authenticatedCAAPI, m.RaftNode, ca.WithMetadataForwardTLSInfo) + proxyNodeCAAPI := api.NewRaftProxyNodeCAServer(authenticatedNodeCAAPI, m.RaftNode, ca.WithMetadataForwardTLSInfo) + proxyRaftMembershipAPI := api.NewRaftProxyRaftMembershipServer(authenticatedRaftMembershipAPI, m.RaftNode, ca.WithMetadataForwardTLSInfo) + proxyResourceAPI := api.NewRaftProxyResourceAllocatorServer(authenticatedResourceAPI, m.RaftNode, ca.WithMetadataForwardTLSInfo) // localProxyControlAPI is a special kind of proxy. It is only wired up // to receive requests from a trusted local socket, and these requests @@ -302,7 +279,7 @@ func (m *Manager) Run(parent context.Context) error { // this manager rather than forwarded requests (it has no TLS // information to put in the metadata map). forwardAsOwnRequest := func(ctx context.Context) (context.Context, error) { return ctx, nil } - localProxyControlAPI := api.NewRaftProxyControlServer(baseControlAPI, controlAPIConnSelector, m.RaftNode, forwardAsOwnRequest) + localProxyControlAPI := api.NewRaftProxyControlServer(baseControlAPI, m.RaftNode, forwardAsOwnRequest) // Everything registered on m.server should be an authenticated // wrapper, or a proxy wrapping an authenticated wrapper! @@ -318,7 +295,7 @@ func (m *Manager) Run(parent context.Context) error { api.RegisterControlServer(m.localserver, localProxyControlAPI) api.RegisterHealthServer(m.localserver, localHealthServer) - errServe := make(chan error, 2) + errServe := make(chan error, len(m.listeners)) for proto, l := range m.listeners { go m.serveListener(ctx, errServe, proto, l) } @@ -433,9 +410,6 @@ func (m *Manager) Stop(ctx context.Context) { m.keyManager.Stop() } - if m.connSelector != nil { - m.connSelector.Stop() - } m.RaftNode.Shutdown() // some time after this point, Run will receive an error from one of these m.server.Stop() diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go index bddc798c27..b4022ad9e7 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go @@ -346,7 +346,8 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask close(doneCh) }() - oldTaskTimeout := time.After(r.taskTimeout) + oldTaskTimer := time.NewTimer(r.taskTimeout) + defer oldTaskTimer.Stop() // Wait for the delay to elapse, if one is specified. if delay != 0 { @@ -357,10 +358,10 @@ func (r *RestartSupervisor) DelayStart(ctx context.Context, _ store.Tx, oldTask } } - if waitStop { + if waitStop && oldTask != nil { select { case <-watch: - case <-oldTaskTimeout: + case <-oldTaskTimer.C: case <-ctx.Done(): return } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go index 97cb2fe328..fd90a80c5c 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go @@ -1,6 +1,7 @@ package orchestrator import ( + "errors" "fmt" "reflect" "sync" @@ -17,6 +18,8 @@ import ( "github.com/docker/swarmkit/protobuf/ptypes" ) +const defaultMonitor = 30 * time.Second + // UpdateSupervisor supervises a set of updates. It's responsible for keeping track of updates, // shutting them down and replacing them. type UpdateSupervisor struct { @@ -49,7 +52,7 @@ func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, ser id := service.ID if update, ok := u.updates[id]; ok { - if !update.isServiceDirty(service) { + if reflect.DeepEqual(service.Spec, update.newService.Spec) { // There's already an update working towards this goal. return } @@ -87,6 +90,9 @@ type Updater struct { cluster *api.Cluster newService *api.Service + updatedTasks map[string]time.Time // task ID to creation time + updatedTasksMu sync.Mutex + // stopChan signals to the state machine to stop running. stopChan chan struct{} // doneChan is closed when the state machine terminates. @@ -96,13 +102,14 @@ type Updater struct { // NewUpdater creates a new Updater. func NewUpdater(store *store.MemoryStore, restartSupervisor *RestartSupervisor, cluster *api.Cluster, newService *api.Service) *Updater { return &Updater{ - store: store, - watchQueue: store.WatchQueue(), - restarts: restartSupervisor, - cluster: cluster.Copy(), - newService: newService.Copy(), - stopChan: make(chan struct{}), - doneChan: make(chan struct{}), + store: store, + watchQueue: store.WatchQueue(), + restarts: restartSupervisor, + cluster: cluster.Copy(), + newService: newService.Copy(), + updatedTasks: make(map[string]time.Time), + stopChan: make(chan struct{}), + doneChan: make(chan struct{}), } } @@ -119,7 +126,9 @@ func (u *Updater) Run(ctx context.Context, slots []slot) { service := u.newService // If the update is in a PAUSED state, we should not do anything. - if service.UpdateStatus != nil && service.UpdateStatus.State == api.UpdateStatus_PAUSED { + if service.UpdateStatus != nil && + (service.UpdateStatus.State == api.UpdateStatus_PAUSED || + service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_PAUSED) { return } @@ -131,7 +140,9 @@ func (u *Updater) Run(ctx context.Context, slots []slot) { } // Abort immediately if all tasks are clean. if len(dirtySlots) == 0 { - if service.UpdateStatus != nil && service.UpdateStatus.State == api.UpdateStatus_UPDATING { + if service.UpdateStatus != nil && + (service.UpdateStatus.State == api.UpdateStatus_UPDATING || + service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED) { u.completeUpdate(ctx, service.ID) } return @@ -163,9 +174,26 @@ func (u *Updater) Run(ctx context.Context, slots []slot) { }() } + failureAction := api.UpdateConfig_PAUSE + allowedFailureFraction := float32(0) + monitoringPeriod := defaultMonitor + + if service.Spec.Update != nil { + failureAction = service.Spec.Update.FailureAction + allowedFailureFraction = service.Spec.Update.AllowedFailureFraction + + if service.Spec.Update.Monitor != nil { + var err error + monitoringPeriod, err = ptypes.Duration(service.Spec.Update.Monitor) + if err != nil { + monitoringPeriod = defaultMonitor + } + } + } + var failedTaskWatch chan events.Event - if service.Spec.Update == nil || service.Spec.Update.FailureAction == api.UpdateConfig_PAUSE { + if failureAction != api.UpdateConfig_CONTINUE { var cancelWatch func() failedTaskWatch, cancelWatch = state.Watch( u.store.WatchQueue(), @@ -178,6 +206,49 @@ func (u *Updater) Run(ctx context.Context, slots []slot) { } stopped := false + failedTasks := make(map[string]struct{}) + totalFailures := 0 + + failureTriggersAction := func(failedTask *api.Task) bool { + // Ignore tasks we have already seen as failures. + if _, found := failedTasks[failedTask.ID]; found { + return false + } + + // If this failed/completed task is one that we + // created as part of this update, we should + // follow the failure action. + u.updatedTasksMu.Lock() + startedAt, found := u.updatedTasks[failedTask.ID] + u.updatedTasksMu.Unlock() + + if found && (startedAt.IsZero() || time.Since(startedAt) <= monitoringPeriod) { + failedTasks[failedTask.ID] = struct{}{} + totalFailures++ + if float32(totalFailures)/float32(len(dirtySlots)) > allowedFailureFraction { + switch failureAction { + case api.UpdateConfig_PAUSE: + stopped = true + message := fmt.Sprintf("update paused due to failure or early termination of task %s", failedTask.ID) + u.pauseUpdate(ctx, service.ID, message) + return true + case api.UpdateConfig_ROLLBACK: + // Never roll back a rollback + if service.UpdateStatus != nil && service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED { + message := fmt.Sprintf("rollback paused due to failure or early termination of task %s", failedTask.ID) + u.pauseUpdate(ctx, service.ID, message) + return true + } + stopped = true + message := fmt.Sprintf("update rolled back due to failure or early termination of task %s", failedTask.ID) + u.rollbackUpdate(ctx, service.ID, message) + return true + } + } + } + + return false + } slotsLoop: for _, slot := range dirtySlots { @@ -189,15 +260,7 @@ slotsLoop: stopped = true break slotsLoop case ev := <-failedTaskWatch: - failedTask := ev.(state.EventUpdateTask).Task - - // If this failed/completed task has a spec matching - // the one we're updating to, we should pause the - // update. - if !u.isTaskDirty(failedTask) { - stopped = true - message := fmt.Sprintf("update paused due to failure or early termination of task %s", failedTask.ID) - u.pauseUpdate(ctx, service.ID, message) + if failureTriggersAction(ev.(state.EventUpdateTask).Task) { break slotsLoop } case slotQueue <- slot: @@ -209,6 +272,29 @@ slotsLoop: close(slotQueue) wg.Wait() + if !stopped { + // Keep watching for task failures for one more monitoringPeriod, + // before declaring the update complete. + doneMonitoring := time.After(monitoringPeriod) + monitorLoop: + for { + select { + case <-u.stopChan: + stopped = true + break monitorLoop + case <-doneMonitoring: + break monitorLoop + case ev := <-failedTaskWatch: + if failureTriggersAction(ev.(state.EventUpdateTask).Task) { + break monitorLoop + } + } + } + } + + // TODO(aaronl): Potentially roll back the service if not enough tasks + // have reached RUNNING by this point. + if !stopped { u.completeUpdate(ctx, service.ID) } @@ -237,9 +323,13 @@ func (u *Updater) worker(ctx context.Context, queue <-chan slot) { } } if runningTask != nil { - u.useExistingTask(ctx, slot, runningTask) + if err := u.useExistingTask(ctx, slot, runningTask); err != nil { + log.G(ctx).WithError(err).Error("update failed") + } } else if cleanTask != nil { - u.useExistingTask(ctx, slot, cleanTask) + if err := u.useExistingTask(ctx, slot, cleanTask); err != nil { + log.G(ctx).WithError(err).Error("update failed") + } } else { updated := newTask(u.cluster, u.newService, slot[0].Slot) updated.DesiredState = api.TaskStateReady @@ -275,10 +365,22 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) }) defer cancel() + // Create an empty entry for this task, so the updater knows a failure + // should count towards the failure count. The timestamp is added + // if/when the task reaches RUNNING. + u.updatedTasksMu.Lock() + u.updatedTasks[updated.ID] = time.Time{} + u.updatedTasksMu.Unlock() + var delayStartCh <-chan struct{} // Atomically create the updated task and bring down the old one. _, err := u.store.Batch(func(batch *store.Batch) error { - err := batch.Update(func(tx store.Tx) error { + oldTask, err := u.removeOldTasks(ctx, batch, slot) + if err != nil { + return err + } + + err = batch.Update(func(tx store.Tx) error { if err := store.CreateTask(tx, updated); err != nil { return err } @@ -288,7 +390,6 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) return err } - oldTask := u.removeOldTasks(ctx, batch, slot) delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, updated.ID, 0, true) return nil @@ -309,6 +410,9 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) case e := <-taskUpdates: updated = e.(state.EventUpdateTask).Task if updated.Status.State >= api.TaskStateRunning { + u.updatedTasksMu.Lock() + u.updatedTasks[updated.ID] = time.Now() + u.updatedTasksMu.Unlock() return nil } case <-u.stopChan: @@ -317,7 +421,7 @@ func (u *Updater) updateTask(ctx context.Context, slot slot, updated *api.Task) } } -func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api.Task) { +func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api.Task) error { var removeTasks []*api.Task for _, t := range slot { if t != existing { @@ -327,7 +431,14 @@ func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api. if len(removeTasks) != 0 || existing.DesiredState != api.TaskStateRunning { var delayStartCh <-chan struct{} _, err := u.store.Batch(func(batch *store.Batch) error { - oldTask := u.removeOldTasks(ctx, batch, removeTasks) + var oldTask *api.Task + if len(removeTasks) != 0 { + var err error + oldTask, err = u.removeOldTasks(ctx, batch, removeTasks) + if err != nil { + return err + } + } if existing.DesiredState != api.TaskStateRunning { delayStartCh = u.restarts.DelayStart(ctx, nil, oldTask, existing.ID, 0, true) @@ -335,19 +446,24 @@ func (u *Updater) useExistingTask(ctx context.Context, slot slot, existing *api. return nil }) if err != nil { - log.G(ctx).WithError(err).Error("updater batch transaction failed") + return err } if delayStartCh != nil { <-delayStartCh } } + + return nil } // removeOldTasks shuts down the given tasks and returns one of the tasks that -// was shut down, or nil. -func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, removeTasks []*api.Task) *api.Task { - var removedTask *api.Task +// was shut down, or an error. +func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, removeTasks []*api.Task) (*api.Task, error) { + var ( + lastErr error + removedTask *api.Task + ) for _, original := range removeTasks { err := batch.Update(func(tx store.Tx) error { t := store.GetTask(tx, original.ID) @@ -361,13 +477,16 @@ func (u *Updater) removeOldTasks(ctx context.Context, batch *store.Batch, remove return store.UpdateTask(tx, t) }) if err != nil { - log.G(ctx).WithError(err).Errorf("shutting down stale task %s failed", original.ID) + lastErr = err } else { removedTask = original } } - return removedTask + if removedTask == nil { + return nil, lastErr + } + return removedTask, nil } func (u *Updater) isTaskDirty(t *api.Task) bool { @@ -375,11 +494,6 @@ func (u *Updater) isTaskDirty(t *api.Task) bool { (t.Endpoint != nil && !reflect.DeepEqual(u.newService.Spec.Endpoint, t.Endpoint.Spec)) } -func (u *Updater) isServiceDirty(service *api.Service) bool { - return !reflect.DeepEqual(u.newService.Spec.Task, service.Spec.Task) || - !reflect.DeepEqual(u.newService.Spec.Endpoint, service.Spec.Endpoint) -} - func (u *Updater) isSlotDirty(slot slot) bool { return len(slot) > 1 || (len(slot) == 1 && u.isTaskDirty(slot[0])) } @@ -421,7 +535,11 @@ func (u *Updater) pauseUpdate(ctx context.Context, serviceID, message string) { return nil } - service.UpdateStatus.State = api.UpdateStatus_PAUSED + if service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED { + service.UpdateStatus.State = api.UpdateStatus_ROLLBACK_PAUSED + } else { + service.UpdateStatus.State = api.UpdateStatus_PAUSED + } service.UpdateStatus.Message = message return store.UpdateService(tx, service) @@ -432,6 +550,38 @@ func (u *Updater) pauseUpdate(ctx context.Context, serviceID, message string) { } } +func (u *Updater) rollbackUpdate(ctx context.Context, serviceID, message string) { + log.G(ctx).Debugf("starting rollback of service %s", serviceID) + + var service *api.Service + err := u.store.Update(func(tx store.Tx) error { + service = store.GetService(tx, serviceID) + if service == nil { + return nil + } + if service.UpdateStatus == nil { + // The service was updated since we started this update + return nil + } + + service.UpdateStatus.State = api.UpdateStatus_ROLLBACK_STARTED + service.UpdateStatus.Message = message + + if service.PreviousSpec == nil { + return errors.New("cannot roll back service because no previous spec is available") + } + service.Spec = *service.PreviousSpec + service.PreviousSpec = nil + + return store.UpdateService(tx, service) + }) + + if err != nil { + log.G(ctx).WithError(err).Errorf("failed to start rollback of service %s", serviceID) + return + } +} + func (u *Updater) completeUpdate(ctx context.Context, serviceID string) { log.G(ctx).Debugf("update of service %s complete", serviceID) @@ -444,9 +594,13 @@ func (u *Updater) completeUpdate(ctx context.Context, serviceID string) { // The service was changed since we started this update return nil } - - service.UpdateStatus.State = api.UpdateStatus_COMPLETED - service.UpdateStatus.Message = "update completed" + if service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED { + service.UpdateStatus.State = api.UpdateStatus_ROLLBACK_COMPLETED + service.UpdateStatus.Message = "rollback completed" + } else { + service.UpdateStatus.State = api.UpdateStatus_COMPLETED + service.UpdateStatus.Message = "update completed" + } service.UpdateStatus.CompletedAt = ptypes.MustTimestampProto(time.Now()) return store.UpdateService(tx, service) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/cluster.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/cluster.go deleted file mode 100644 index 86e5e080f5..0000000000 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/cluster.go +++ /dev/null @@ -1,12 +0,0 @@ -package raftpicker - -// AddrSelector is interface which should track cluster for its leader address. -type AddrSelector interface { - LeaderAddr() (string, error) -} - -// RaftCluster is interface which combines useful methods for clustering. -type RaftCluster interface { - AddrSelector - IsLeader() bool -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/raftpicker.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/raftpicker.go deleted file mode 100644 index 03b75d097b..0000000000 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftpicker/raftpicker.go +++ /dev/null @@ -1,127 +0,0 @@ -package raftpicker - -import ( - "sync" - "time" - - "github.com/Sirupsen/logrus" - - "google.golang.org/grpc" -) - -// Interface is interface to replace implementation with controlapi/hackpicker. -// TODO: it should be done cooler. -type Interface interface { - Conn() (*grpc.ClientConn, error) - Reset() error -} - -// ConnSelector is struct for obtaining connection connected to cluster leader. -type ConnSelector struct { - mu sync.Mutex - cluster RaftCluster - opts []grpc.DialOption - - cc *grpc.ClientConn - addr string - - stop chan struct{} -} - -// NewConnSelector returns new ConnSelector with cluster and grpc.DialOpts which -// will be used for connection create. -func NewConnSelector(cluster RaftCluster, opts ...grpc.DialOption) *ConnSelector { - cs := &ConnSelector{ - cluster: cluster, - opts: opts, - stop: make(chan struct{}), - } - go cs.updateLoop() - return cs -} - -// Conn returns *grpc.ClientConn which connected to cluster leader. -// It can return error if cluster wasn't ready at the moment of initial call. -func (c *ConnSelector) Conn() (*grpc.ClientConn, error) { - c.mu.Lock() - defer c.mu.Unlock() - if c.cc != nil { - return c.cc, nil - } - addr, err := c.cluster.LeaderAddr() - if err != nil { - return nil, err - } - cc, err := grpc.Dial(addr, c.opts...) - if err != nil { - return nil, err - } - c.cc = cc - c.addr = addr - return cc, nil -} - -// Reset recreates underlying connection. -func (c *ConnSelector) Reset() error { - c.mu.Lock() - defer c.mu.Unlock() - if c.cc != nil { - c.cc.Close() - c.cc = nil - } - addr, err := c.cluster.LeaderAddr() - if err != nil { - logrus.WithError(err).Errorf("error obtaining leader address") - return err - } - cc, err := grpc.Dial(addr, c.opts...) - if err != nil { - logrus.WithError(err).Errorf("error reestabilishing connection to leader") - return err - } - c.cc = cc - c.addr = addr - return nil -} - -// Stop cancels updating connection loop. -func (c *ConnSelector) Stop() { - close(c.stop) -} - -func (c *ConnSelector) updateConn() error { - addr, err := c.cluster.LeaderAddr() - if err != nil { - return err - } - c.mu.Lock() - defer c.mu.Unlock() - if c.addr != addr { - if c.cc != nil { - c.cc.Close() - c.cc = nil - } - conn, err := grpc.Dial(addr, c.opts...) - if err != nil { - return err - } - c.cc = conn - c.addr = addr - } - return nil -} - -func (c *ConnSelector) updateLoop() { - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - if err := c.updateConn(); err != nil { - logrus.WithError(err).Errorf("error reestabilishing connection to leader") - } - case <-c.stop: - return - } - } -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftselector/raftselector.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftselector/raftselector.go new file mode 100644 index 0000000000..89e7918a3d --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/raftselector/raftselector.go @@ -0,0 +1,20 @@ +package raftselector + +import ( + "errors" + + "golang.org/x/net/context" + + "google.golang.org/grpc" +) + +// ConnProvider is basic interface for connecting API package(raft proxy in particular) +// to manager/state/raft package without import cycles. It provides only one +// method for obtaining connection to leader. +type ConnProvider interface { + LeaderConn(ctx context.Context) (*grpc.ClientConn, error) +} + +// ErrIsLeader is returned from LeaderConn method when current machine is leader. +// It's just shim between packages to avoid import cycles. +var ErrIsLeader = errors.New("current node is leader") diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go deleted file mode 100644 index 0cc5c0b37b..0000000000 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go +++ /dev/null @@ -1,153 +0,0 @@ -package scheduler - -import ( - "container/heap" - "errors" - - "github.com/docker/swarmkit/api" -) - -var errNodeNotFound = errors.New("node not found in scheduler heap") - -// A nodeHeap implements heap.Interface for nodes. It also includes an index -// by node id. -type nodeHeap struct { - heap []NodeInfo - index map[string]int // map from node id to heap index -} - -func (nh nodeHeap) Len() int { - return len(nh.heap) -} - -func (nh nodeHeap) Less(i, j int) bool { - return len(nh.heap[i].Tasks) < len(nh.heap[j].Tasks) -} - -func (nh nodeHeap) Swap(i, j int) { - nh.heap[i], nh.heap[j] = nh.heap[j], nh.heap[i] - nh.index[nh.heap[i].ID] = i - nh.index[nh.heap[j].ID] = j -} - -func (nh *nodeHeap) Push(x interface{}) { - n := len(nh.heap) - item := x.(NodeInfo) - nh.index[item.ID] = n - nh.heap = append(nh.heap, item) -} - -func (nh *nodeHeap) Pop() interface{} { - old := nh.heap - n := len(old) - item := old[n-1] - delete(nh.index, item.ID) - nh.heap = old[0 : n-1] - return item -} - -func (nh *nodeHeap) alloc(n int) { - nh.heap = make([]NodeInfo, 0, n) - nh.index = make(map[string]int, n) -} - -// nodeInfo returns the NodeInfo struct for a given node identified by its ID. -func (nh *nodeHeap) nodeInfo(nodeID string) (NodeInfo, error) { - index, ok := nh.index[nodeID] - if ok { - return nh.heap[index], nil - } - return NodeInfo{}, errNodeNotFound -} - -// addOrUpdateNode sets the number of tasks for a given node. It adds the node -// to the heap if it wasn't already tracked. -func (nh *nodeHeap) addOrUpdateNode(n NodeInfo) { - index, ok := nh.index[n.ID] - if ok { - nh.heap[index] = n - heap.Fix(nh, index) - } else { - heap.Push(nh, n) - } -} - -// updateNode sets the number of tasks for a given node. It ignores the update -// if the node isn't already tracked in the heap. -func (nh *nodeHeap) updateNode(n NodeInfo) { - index, ok := nh.index[n.ID] - if ok { - nh.heap[index] = n - heap.Fix(nh, index) - } -} - -func (nh *nodeHeap) remove(nodeID string) { - index, ok := nh.index[nodeID] - if ok { - heap.Remove(nh, index) - } -} - -func (nh *nodeHeap) findMin(meetsConstraints func(*NodeInfo) bool, scanAllNodes bool) (*api.Node, int) { - if scanAllNodes { - return nh.scanAllToFindMin(meetsConstraints) - } - return nh.searchHeapToFindMin(meetsConstraints) -} - -// Scan All nodes to find the best node which meets the constraints && has lightest workloads -func (nh *nodeHeap) scanAllToFindMin(meetsConstraints func(*NodeInfo) bool) (*api.Node, int) { - var bestNode *api.Node - minTasks := int(^uint(0) >> 1) // max int - - for i := 0; i < len(nh.heap); i++ { - heapEntry := &nh.heap[i] - if meetsConstraints(heapEntry) && len(heapEntry.Tasks) < minTasks { - bestNode = heapEntry.Node - minTasks = len(heapEntry.Tasks) - } - } - - return bestNode, minTasks -} - -// Search in heap to find the best node which meets the constraints && has lightest workloads -func (nh *nodeHeap) searchHeapToFindMin(meetsConstraints func(*NodeInfo) bool) (*api.Node, int) { - var bestNode *api.Node - minTasks := int(^uint(0) >> 1) // max int - - if nh == nil || len(nh.heap) == 0 { - return bestNode, minTasks - } - - // push root to stack for search - stack := []int{0} - - for len(stack) != 0 { - // pop an element - idx := stack[len(stack)-1] - stack = stack[0 : len(stack)-1] - - heapEntry := &nh.heap[idx] - - if len(heapEntry.Tasks) >= minTasks { - continue - } - - if meetsConstraints(heapEntry) { - // meet constraints, update results - bestNode = heapEntry.Node - minTasks = len(heapEntry.Tasks) - } else { - // otherwise, push 2 children to stack for further search - if 2*idx+1 < len(nh.heap) { - stack = append(stack, 2*idx+1) - } - if 2*idx+2 < len(nh.heap) { - stack = append(stack, 2*idx+2) - } - } - } - return bestNode, minTasks -} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go index cc7f9b026e..5f45fd6581 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go @@ -5,15 +5,18 @@ import "github.com/docker/swarmkit/api" // NodeInfo contains a node and some additional metadata. type NodeInfo struct { *api.Node - Tasks map[string]*api.Task - AvailableResources api.Resources + Tasks map[string]*api.Task + DesiredRunningTasksCount int + DesiredRunningTasksCountByService map[string]int + AvailableResources api.Resources } func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api.Resources) NodeInfo { nodeInfo := NodeInfo{ - Node: n, - Tasks: make(map[string]*api.Task), - AvailableResources: availableResources, + Node: n, + Tasks: make(map[string]*api.Task), + DesiredRunningTasksCountByService: make(map[string]int), + AvailableResources: availableResources, } for _, t := range tasks { @@ -22,15 +25,23 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api return nodeInfo } +// addTask removes a task from nodeInfo if it's tracked there, and returns true +// if nodeInfo was modified. func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool { if nodeInfo.Tasks == nil { return false } - if _, ok := nodeInfo.Tasks[t.ID]; !ok { + oldTask, ok := nodeInfo.Tasks[t.ID] + if !ok { return false } delete(nodeInfo.Tasks, t.ID) + if oldTask.DesiredState == api.TaskStateRunning { + nodeInfo.DesiredRunningTasksCount-- + nodeInfo.DesiredRunningTasksCountByService[t.ServiceID]-- + } + reservations := taskReservations(t.Spec) nodeInfo.AvailableResources.MemoryBytes += reservations.MemoryBytes nodeInfo.AvailableResources.NanoCPUs += reservations.NanoCPUs @@ -38,19 +49,43 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool { return true } +// addTask adds or updates a task on nodeInfo, and returns true if nodeInfo was +// modified. func (nodeInfo *NodeInfo) addTask(t *api.Task) bool { if nodeInfo.Tasks == nil { nodeInfo.Tasks = make(map[string]*api.Task) } - if _, ok := nodeInfo.Tasks[t.ID]; !ok { - nodeInfo.Tasks[t.ID] = t - reservations := taskReservations(t.Spec) - nodeInfo.AvailableResources.MemoryBytes -= reservations.MemoryBytes - nodeInfo.AvailableResources.NanoCPUs -= reservations.NanoCPUs - return true + if nodeInfo.DesiredRunningTasksCountByService == nil { + nodeInfo.DesiredRunningTasksCountByService = make(map[string]int) } - return false + oldTask, ok := nodeInfo.Tasks[t.ID] + if ok { + if t.DesiredState == api.TaskStateRunning && oldTask.DesiredState != api.TaskStateRunning { + nodeInfo.Tasks[t.ID] = t + nodeInfo.DesiredRunningTasksCount++ + nodeInfo.DesiredRunningTasksCountByService[t.ServiceID]++ + return true + } else if t.DesiredState != api.TaskStateRunning && oldTask.DesiredState == api.TaskStateRunning { + nodeInfo.Tasks[t.ID] = t + nodeInfo.DesiredRunningTasksCount-- + nodeInfo.DesiredRunningTasksCountByService[t.ServiceID]-- + return true + } + return false + } + + nodeInfo.Tasks[t.ID] = t + reservations := taskReservations(t.Spec) + nodeInfo.AvailableResources.MemoryBytes -= reservations.MemoryBytes + nodeInfo.AvailableResources.NanoCPUs -= reservations.NanoCPUs + + if t.DesiredState == api.TaskStateRunning { + nodeInfo.DesiredRunningTasksCount++ + nodeInfo.DesiredRunningTasksCountByService[t.ServiceID]++ + } + + return true } func taskReservations(spec api.TaskSpec) (reservations api.Resources) { diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go new file mode 100644 index 0000000000..d47b9c6fbb --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeset.go @@ -0,0 +1,115 @@ +package scheduler + +import ( + "container/heap" + "errors" +) + +var errNodeNotFound = errors.New("node not found in scheduler dataset") + +type nodeSet struct { + nodes map[string]NodeInfo // map from node id to node info +} + +func (ns *nodeSet) alloc(n int) { + ns.nodes = make(map[string]NodeInfo, n) +} + +// nodeInfo returns the NodeInfo struct for a given node identified by its ID. +func (ns *nodeSet) nodeInfo(nodeID string) (NodeInfo, error) { + node, ok := ns.nodes[nodeID] + if ok { + return node, nil + } + return NodeInfo{}, errNodeNotFound +} + +// addOrUpdateNode sets the number of tasks for a given node. It adds the node +// to the set if it wasn't already tracked. +func (ns *nodeSet) addOrUpdateNode(n NodeInfo) { + ns.nodes[n.ID] = n +} + +// updateNode sets the number of tasks for a given node. It ignores the update +// if the node isn't already tracked in the set. +func (ns *nodeSet) updateNode(n NodeInfo) { + _, ok := ns.nodes[n.ID] + if ok { + ns.nodes[n.ID] = n + } +} + +func (ns *nodeSet) remove(nodeID string) { + delete(ns.nodes, nodeID) +} + +type nodeMaxHeap struct { + nodes []NodeInfo + lessFunc func(*NodeInfo, *NodeInfo) bool + length int +} + +func (h nodeMaxHeap) Len() int { + return h.length +} + +func (h nodeMaxHeap) Swap(i, j int) { + h.nodes[i], h.nodes[j] = h.nodes[j], h.nodes[i] +} + +func (h nodeMaxHeap) Less(i, j int) bool { + // reversed to make a max-heap + return h.lessFunc(&h.nodes[j], &h.nodes[i]) +} + +func (h *nodeMaxHeap) Push(x interface{}) { + h.nodes = append(h.nodes, x.(NodeInfo)) + h.length++ +} + +func (h *nodeMaxHeap) Pop() interface{} { + h.length-- + // return value is never used + return nil +} + +// findBestNodes returns n nodes (or < n if fewer nodes are available) that +// rank best (lowest) according to the sorting function. +func (ns *nodeSet) findBestNodes(n int, meetsConstraints func(*NodeInfo) bool, nodeLess func(*NodeInfo, *NodeInfo) bool) []NodeInfo { + if n == 0 { + return []NodeInfo{} + } + + nodeHeap := nodeMaxHeap{lessFunc: nodeLess} + + // TODO(aaronl): Is is possible to avoid checking constraints on every + // node? Perhaps we should try to schedule with n*2 nodes that weren't + // prescreened, and repeat the selection if there weren't enough nodes + // meeting the constraints. + for _, node := range ns.nodes { + // If there are fewer then n nodes in the heap, we add this + // node if it meets the constraints. Otherwise, the heap has + // n nodes, and if this node is better than the worst node in + // the heap, we replace the worst node and then fix the heap. + if nodeHeap.Len() < n { + if meetsConstraints(&node) { + heap.Push(&nodeHeap, node) + } + } else if nodeLess(&node, &nodeHeap.nodes[0]) { + if meetsConstraints(&node) { + nodeHeap.nodes[0] = node + heap.Fix(&nodeHeap, 0) + } + } + } + + // Popping every element orders the nodes from best to worst. The + // first pop gets the worst node (since this a max-heap), and puts it + // at position n-1. Then the next pop puts the next-worst at n-2, and + // so on. + for nodeHeap.Len() > 0 { + heap.Pop(&nodeHeap) + } + + return nodeHeap.nodes +} diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go index 2cb95135b9..1b29a2ac05 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go @@ -1,7 +1,6 @@ package scheduler import ( - "container/heap" "container/list" "time" @@ -24,7 +23,7 @@ type Scheduler struct { unassignedTasks *list.List // preassignedTasks already have NodeID, need resource validation preassignedTasks map[string]*api.Task - nodeHeap nodeHeap + nodeSet nodeSet allTasks map[string]*api.Task pipeline *Pipeline @@ -32,11 +31,6 @@ type Scheduler struct { stopChan chan struct{} // doneChan is closed when the state machine terminates doneChan chan struct{} - - // This currently exists only for benchmarking. It tells the scheduler - // scan the whole heap instead of taking the minimum-valued node - // blindly. - scanAllNodes bool } // New creates a new scheduler. @@ -83,7 +77,7 @@ func (s *Scheduler) setupTasksList(tx store.ReadTx) error { tasksByNode[t.NodeID][t.ID] = t } - if err := s.buildNodeHeap(tx, tasksByNode); err != nil { + if err := s.buildNodeSet(tx, tasksByNode); err != nil { return err } @@ -152,7 +146,7 @@ func (s *Scheduler) Run(ctx context.Context) error { s.createOrUpdateNode(v.Node) pendingChanges++ case state.EventDeleteNode: - s.nodeHeap.remove(v.Node.ID) + s.nodeSet.remove(v.Node.ID) case state.EventCommit: if commitDebounceTimer != nil { if time.Since(debouncingStarted) > maxLatency { @@ -210,9 +204,9 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int { return 0 } - nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID) if err == nil && nodeInfo.addTask(t) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } return 0 @@ -257,9 +251,9 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int { } s.allTasks[t.ID] = t - nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID) if err == nil && nodeInfo.addTask(t) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } return 0 @@ -268,14 +262,14 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int { func (s *Scheduler) deleteTask(ctx context.Context, t *api.Task) { delete(s.allTasks, t.ID) delete(s.preassignedTasks, t.ID) - nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + nodeInfo, err := s.nodeSet.nodeInfo(t.NodeID) if err == nil && nodeInfo.removeTask(t) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } } func (s *Scheduler) createOrUpdateNode(n *api.Node) { - nodeInfo, _ := s.nodeHeap.nodeInfo(n.ID) + nodeInfo, _ := s.nodeSet.nodeInfo(n.ID) var resources api.Resources if n.Description != nil && n.Description.Resources != nil { resources = *n.Description.Resources @@ -288,7 +282,7 @@ func (s *Scheduler) createOrUpdateNode(n *api.Node) { } nodeInfo.Node = n nodeInfo.AvailableResources = resources - s.nodeHeap.addOrUpdateNode(nodeInfo) + s.nodeSet.addOrUpdateNode(nodeInfo) } func (s *Scheduler) processPreassignedTasks(ctx context.Context) { @@ -308,44 +302,60 @@ func (s *Scheduler) processPreassignedTasks(ctx context.Context) { } for _, decision := range failed { s.allTasks[decision.old.ID] = decision.old - nodeInfo, err := s.nodeHeap.nodeInfo(decision.new.NodeID) + nodeInfo, err := s.nodeSet.nodeInfo(decision.new.NodeID) if err == nil && nodeInfo.removeTask(decision.new) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } } } // tick attempts to schedule the queue. func (s *Scheduler) tick(ctx context.Context) { + tasksByCommonSpec := make(map[string]map[string]*api.Task) schedulingDecisions := make(map[string]schedulingDecision, s.unassignedTasks.Len()) var next *list.Element for e := s.unassignedTasks.Front(); e != nil; e = next { next = e.Next() - id := e.Value.(*api.Task).ID - if _, ok := schedulingDecisions[id]; ok { - s.unassignedTasks.Remove(e) - continue - } t := s.allTasks[e.Value.(*api.Task).ID] if t == nil || t.NodeID != "" { // task deleted or already assigned s.unassignedTasks.Remove(e) continue } - if newT := s.scheduleTask(ctx, t); newT != nil { - schedulingDecisions[id] = schedulingDecision{old: t, new: newT} - s.unassignedTasks.Remove(e) + + // Group common tasks with common specs by marshalling the spec + // into taskKey and using it as a map key. + // TODO(aaronl): Once specs are versioned, this will allow a + // much more efficient fast path. + fieldsToMarshal := api.Task{ + ServiceID: t.ServiceID, + Spec: t.Spec, } + marshalled, err := fieldsToMarshal.Marshal() + if err != nil { + panic(err) + } + taskGroupKey := string(marshalled) + + if tasksByCommonSpec[taskGroupKey] == nil { + tasksByCommonSpec[taskGroupKey] = make(map[string]*api.Task) + } + tasksByCommonSpec[taskGroupKey][t.ID] = t + s.unassignedTasks.Remove(e) + } + + for _, taskGroup := range tasksByCommonSpec { + s.scheduleTaskGroup(ctx, taskGroup, schedulingDecisions) } _, failed := s.applySchedulingDecisions(ctx, schedulingDecisions) for _, decision := range failed { s.allTasks[decision.old.ID] = decision.old - nodeInfo, err := s.nodeHeap.nodeInfo(decision.new.NodeID) + nodeInfo, err := s.nodeSet.nodeInfo(decision.new.NodeID) if err == nil && nodeInfo.removeTask(decision.new) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } // enqueue task for next scheduling attempt @@ -401,11 +411,11 @@ func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDeci return } -// taskFitNode checks if a node has enough resource to accommodate a task +// taskFitNode checks if a node has enough resources to accommodate a task. func (s *Scheduler) taskFitNode(ctx context.Context, t *api.Task, nodeID string) *api.Task { - nodeInfo, err := s.nodeHeap.nodeInfo(nodeID) + nodeInfo, err := s.nodeSet.nodeInfo(nodeID) if err != nil { - // node does not exist in heap (it may have been deleted) + // node does not exist in set (it may have been deleted) return nil } s.pipeline.SetTask(t) @@ -422,57 +432,118 @@ func (s *Scheduler) taskFitNode(ctx context.Context, t *api.Task, nodeID string) s.allTasks[t.ID] = &newT if nodeInfo.addTask(&newT) { - s.nodeHeap.updateNode(nodeInfo) + s.nodeSet.updateNode(nodeInfo) } return &newT } -// scheduleTask schedules a single task. -func (s *Scheduler) scheduleTask(ctx context.Context, t *api.Task) *api.Task { +// scheduleTaskGroup schedules a batch of tasks that are part of the same +// service and share the same version of the spec. +func (s *Scheduler) scheduleTaskGroup(ctx context.Context, taskGroup map[string]*api.Task, schedulingDecisions map[string]schedulingDecision) { + // Pick at task at random from taskGroup to use for constraint + // evaluation. It doesn't matter which one we pick because all the + // tasks in the group are equal in terms of the fields the constraint + // filters consider. + var t *api.Task + for _, t = range taskGroup { + break + } + s.pipeline.SetTask(t) - n, _ := s.nodeHeap.findMin(s.pipeline.Process, s.scanAllNodes) - if n == nil { - log.G(ctx).WithField("task.id", t.ID).Debug("No suitable node available for task") - return nil + + nodeLess := func(a *NodeInfo, b *NodeInfo) bool { + tasksByServiceA := a.DesiredRunningTasksCountByService[t.ServiceID] + tasksByServiceB := b.DesiredRunningTasksCountByService[t.ServiceID] + + if tasksByServiceA < tasksByServiceB { + return true + } + if tasksByServiceA > tasksByServiceB { + return false + } + + // Total number of tasks breaks ties. + return a.DesiredRunningTasksCount < b.DesiredRunningTasksCount } - log.G(ctx).WithField("task.id", t.ID).Debugf("Assigning to node %s", n.ID) - newT := *t - newT.NodeID = n.ID - newT.Status = api.TaskStatus{ - State: api.TaskStateAssigned, - Timestamp: ptypes.MustTimestampProto(time.Now()), - Message: "scheduler assigned task to node", + nodes := s.nodeSet.findBestNodes(len(taskGroup), s.pipeline.Process, nodeLess) + if len(nodes) == 0 { + for _, t := range taskGroup { + log.G(ctx).WithField("task.id", t.ID).Debug("no suitable node available for task") + s.enqueue(t) + } + return } - s.allTasks[t.ID] = &newT - nodeInfo, err := s.nodeHeap.nodeInfo(n.ID) - if err == nil && nodeInfo.addTask(&newT) { - s.nodeHeap.updateNode(nodeInfo) + failedConstraints := make(map[int]bool) // key is index in nodes slice + nodeIter := 0 + for taskID, t := range taskGroup { + n := &nodes[nodeIter%len(nodes)] + + log.G(ctx).WithField("task.id", t.ID).Debugf("assigning to node %s", n.ID) + newT := *t + newT.NodeID = n.ID + newT.Status = api.TaskStatus{ + State: api.TaskStateAssigned, + Timestamp: ptypes.MustTimestampProto(time.Now()), + Message: "scheduler assigned task to node", + } + s.allTasks[t.ID] = &newT + + nodeInfo, err := s.nodeSet.nodeInfo(n.ID) + if err == nil && nodeInfo.addTask(&newT) { + s.nodeSet.updateNode(nodeInfo) + nodes[nodeIter%len(nodes)] = nodeInfo + } + + schedulingDecisions[taskID] = schedulingDecision{old: t, new: &newT} + delete(taskGroup, taskID) + + if nodeIter+1 < len(nodes) { + // First pass fills the nodes until they have the same + // number of tasks from this service. + nextNode := nodes[(nodeIter+1)%len(nodes)] + if nodeLess(&nextNode, &nodeInfo) { + nodeIter++ + continue + } + } else { + // In later passes, we just assign one task at a time + // to each node that still meets the constraints. + nodeIter++ + } + + origNodeIter := nodeIter + for failedConstraints[nodeIter%len(nodes)] || !s.pipeline.Process(&nodes[nodeIter%len(nodes)]) { + failedConstraints[nodeIter%len(nodes)] = true + nodeIter++ + if nodeIter-origNodeIter == len(nodes) { + // None of the nodes meet the constraints anymore. + for _, t := range taskGroup { + log.G(ctx).WithField("task.id", t.ID).Debug("no suitable node available for task") + s.enqueue(t) + } + return + } + } } - return &newT } -func (s *Scheduler) buildNodeHeap(tx store.ReadTx, tasksByNode map[string]map[string]*api.Task) error { +func (s *Scheduler) buildNodeSet(tx store.ReadTx, tasksByNode map[string]map[string]*api.Task) error { nodes, err := store.FindNodes(tx, store.All) if err != nil { return err } - s.nodeHeap.alloc(len(nodes)) + s.nodeSet.alloc(len(nodes)) - i := 0 for _, n := range nodes { var resources api.Resources if n.Description != nil && n.Description.Resources != nil { resources = *n.Description.Resources } - s.nodeHeap.heap = append(s.nodeHeap.heap, newNodeInfo(n, tasksByNode[n.ID], resources)) - s.nodeHeap.index[n.ID] = i - i++ + s.nodeSet.addOrUpdateNode(newNodeInfo(n, tasksByNode[n.ID], resources)) } - heap.Init(&s.nodeHeap) - return nil } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go index 04b2f77a05..c3962b0235 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go @@ -74,6 +74,9 @@ func (c *Cluster) Tick() { m.tick++ if m.tick > c.heartbeatTicks { m.active = false + if m.Conn != nil { + m.Conn.Close() + } } } } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go index 6dd338b742..33689db110 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go @@ -26,6 +26,7 @@ import ( "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/ca" "github.com/docker/swarmkit/log" + "github.com/docker/swarmkit/manager/raftselector" "github.com/docker/swarmkit/manager/state/raft/membership" "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/manager/state/watch" @@ -82,7 +83,7 @@ type Node struct { Server *grpc.Server Ctx context.Context cancel func() - tlsCredentials credentials.TransportAuthenticator + tlsCredentials credentials.TransportCredentials Address string StateDir string @@ -152,7 +153,7 @@ type NewNodeOptions struct { // SendTimeout is the timeout on the sending messages to other raft // nodes. Leave this as 0 to get the default value. SendTimeout time.Duration - TLSCredentials credentials.TransportAuthenticator + TLSCredentials credentials.TransportCredentials } func init() { @@ -176,7 +177,7 @@ func NewNode(ctx context.Context, opts NewNodeOptions) *Node { n := &Node{ Ctx: ctx, cancel: cancel, - cluster: membership.NewCluster(cfg.ElectionTick), + cluster: membership.NewCluster(2 * cfg.ElectionTick), tlsCredentials: opts.TLSCredentials, raftStore: raftStore, Address: opts.Addr, @@ -395,6 +396,41 @@ func (n *Node) Run(ctx context.Context) error { n.confState = rd.Snapshot.Metadata.ConfState } + // If we cease to be the leader, we must cancel any + // proposals that are currently waiting for a quorum to + // acknowledge them. It is still possible for these to + // become committed, but if that happens we will apply + // them as any follower would. + + // It is important that we cancel these proposals before + // calling processCommitted, so processCommitted does + // not deadlock. + + if rd.SoftState != nil { + if wasLeader && rd.SoftState.RaftState != raft.StateLeader { + wasLeader = false + if atomic.LoadUint32(&n.signalledLeadership) == 1 { + atomic.StoreUint32(&n.signalledLeadership, 0) + n.leadershipBroadcast.Publish(IsFollower) + } + + // It is important that we set n.signalledLeadership to 0 + // before calling n.wait.cancelAll. When a new raft + // request is registered, it checks n.signalledLeadership + // afterwards, and cancels the registration if it is 0. + // If cancelAll was called first, this call might run + // before the new request registers, but + // signalledLeadership would be set after the check. + // Setting signalledLeadership before calling cancelAll + // ensures that if a new request is registered during + // this transition, it will either be cancelled by + // cancelAll, or by its own check of signalledLeadership. + n.wait.cancelAll() + } else if !wasLeader && rd.SoftState.RaftState == raft.StateLeader { + wasLeader = true + } + } + // Process committed entries for _, entry := range rd.CommittedEntries { if err := n.processCommitted(entry); err != nil { @@ -409,25 +445,6 @@ func (n *Node) Run(ctx context.Context) error { n.doSnapshot(&raftConfig) } - // If we cease to be the leader, we must cancel - // any proposals that are currently waiting for - // a quorum to acknowledge them. It is still - // possible for these to become committed, but - // if that happens we will apply them as any - // follower would. - if rd.SoftState != nil { - if wasLeader && rd.SoftState.RaftState != raft.StateLeader { - wasLeader = false - n.wait.cancelAll() - if atomic.LoadUint32(&n.signalledLeadership) == 1 { - atomic.StoreUint32(&n.signalledLeadership, 0) - n.leadershipBroadcast.Publish(IsFollower) - } - } else if !wasLeader && rd.SoftState.RaftState == raft.StateLeader { - wasLeader = true - } - } - if wasLeader && atomic.LoadUint32(&n.signalledLeadership) != 1 { // If all the entries in the log have become // committed, broadcast our leadership status. @@ -539,11 +556,11 @@ func (n *Node) Leader() (uint64, error) { defer n.stopMu.RUnlock() if !n.IsMember() { - return 0, ErrNoRaftMember + return raft.None, ErrNoRaftMember } leader := n.leader() - if leader == 0 { - return 0, ErrNoClusterLeader + if leader == raft.None { + return raft.None, ErrNoClusterLeader } return leader, nil @@ -658,6 +675,12 @@ func (n *Node) checkHealth(ctx context.Context, addr string, timeout time.Durati return err } + if timeout != 0 { + tctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + ctx = tctx + } + client := api.NewHealthClient(conn) defer conn.Close() @@ -828,25 +851,54 @@ func (n *Node) ResolveAddress(ctx context.Context, msg *api.ResolveAddressReques return &api.ResolveAddressResponse{Addr: member.Addr}, nil } -// LeaderAddr returns address of current cluster leader. -// With this method Node satisfies raftpicker.AddrSelector interface. -func (n *Node) LeaderAddr() (string, error) { - ctx, cancel := context.WithTimeout(n.Ctx, 10*time.Second) - defer cancel() - if err := WaitForLeader(ctx, n); err != nil { - return "", ErrNoClusterLeader +func (n *Node) getLeaderConn() (*grpc.ClientConn, error) { + leader, err := n.Leader() + if err != nil { + return nil, err } - n.stopMu.RLock() - defer n.stopMu.RUnlock() - if !n.IsMember() { - return "", ErrNoRaftMember + + if leader == n.Config.ID { + return nil, raftselector.ErrIsLeader } - ms := n.cluster.Members() - l := ms[n.leader()] + l := n.cluster.GetMember(leader) if l == nil { - return "", ErrNoClusterLeader + return nil, fmt.Errorf("no leader found") + } + if !n.cluster.Active(leader) { + return nil, fmt.Errorf("leader marked as inactive") + } + if l.Conn == nil { + return nil, fmt.Errorf("no connection to leader in member list") + } + return l.Conn, nil +} + +// LeaderConn returns current connection to cluster leader or raftselector.ErrIsLeader +// if current machine is leader. +func (n *Node) LeaderConn(ctx context.Context) (*grpc.ClientConn, error) { + cc, err := n.getLeaderConn() + if err == nil { + return cc, nil + } + if err == raftselector.ErrIsLeader { + return nil, err + } + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + cc, err := n.getLeaderConn() + if err == nil { + return cc, nil + } + if err == raftselector.ErrIsLeader { + return nil, err + } + case <-ctx.Done(): + return nil, ctx.Err() + } } - return l.Addr, nil } // registerNode registers a new node on the cluster memberlist @@ -943,7 +995,7 @@ func (n *Node) GetMemberlist() map[uint64]*api.RaftMember { members := n.cluster.Members() leaderID, err := n.Leader() if err != nil { - leaderID = 0 + leaderID = raft.None } for id, member := range members { @@ -1163,7 +1215,11 @@ func (n *Node) processInternalRaftRequest(ctx context.Context, r *api.InternalRa r.ID = n.reqIDGen.Next() - ch := n.wait.register(r.ID, cb) + // This must be derived from the context which is cancelled by stop() + // to avoid a deadlock on shutdown. + waitCtx, cancel := context.WithCancel(n.Ctx) + + ch := n.wait.register(r.ID, cb, cancel) // Do this check after calling register to avoid a race. if atomic.LoadUint32(&n.signalledLeadership) != 1 { @@ -1182,24 +1238,19 @@ func (n *Node) processInternalRaftRequest(ctx context.Context, r *api.InternalRa return nil, ErrRequestTooLarge } - // This must use the context which is cancelled by stop() to avoid a - // deadlock on shutdown. - err = n.Propose(n.Ctx, data) + err = n.Propose(waitCtx, data) if err != nil { n.wait.cancel(r.ID) return nil, err } select { - case x, ok := <-ch: - if ok { - res := x.(*applyResult) - return res.resp, res.err - } - return nil, ErrLostLeadership - case <-n.Ctx.Done(): + case x := <-ch: + res := x.(*applyResult) + return res.resp, res.err + case <-waitCtx.Done(): n.wait.cancel(r.ID) - return nil, ErrStopped + return nil, ErrLostLeadership case <-ctx.Done(): n.wait.cancel(r.ID) return nil, ctx.Err() @@ -1211,10 +1262,12 @@ func (n *Node) processInternalRaftRequest(ctx context.Context, r *api.InternalRa // until the change is performed or there is an error. func (n *Node) configure(ctx context.Context, cc raftpb.ConfChange) error { cc.ID = n.reqIDGen.Next() - ch := n.wait.register(cc.ID, nil) + + ctx, cancel := context.WithCancel(ctx) + ch := n.wait.register(cc.ID, nil, cancel) if err := n.ProposeConfChange(ctx, cc); err != nil { - n.wait.trigger(cc.ID, nil) + n.wait.cancel(cc.ID) return err } @@ -1228,7 +1281,7 @@ func (n *Node) configure(ctx context.Context, cc raftpb.ConfChange) error { } return nil case <-ctx.Done(): - n.wait.trigger(cc.ID, nil) + n.wait.cancel(cc.ID) return ctx.Err() case <-n.Ctx.Done(): return ErrStopped @@ -1271,6 +1324,11 @@ func (n *Node) processEntry(entry raftpb.Entry) error { // position and cancelling the transaction. Create a new // transaction to commit the data. + // It should not be possible for processInternalRaftRequest + // to be running in this situation, but out of caution we + // cancel any current invocations to avoid a deadlock. + n.wait.cancelAll() + err := n.memoryStore.ApplyStoreActions(r.Action) if err != nil { log.G(context.Background()).Errorf("error applying actions from raft: %v", err) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go index 5f069055ab..4127fb8d12 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/util.go @@ -13,7 +13,7 @@ import ( ) // dial returns a grpc client connection -func dial(addr string, protocol string, creds credentials.TransportAuthenticator, timeout time.Duration) (*grpc.ClientConn, error) { +func dial(addr string, protocol string, creds credentials.TransportCredentials, timeout time.Duration) (*grpc.ClientConn, error) { grpcOptions := []grpc.DialOption{ grpc.WithBackoffMaxDelay(2 * time.Second), grpc.WithTransportCredentials(creds), diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/wait.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/wait.go index 297f0cf970..ecd39284c4 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/wait.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/raft/wait.go @@ -10,6 +10,8 @@ type waitItem struct { ch chan interface{} // callback which is called synchronously when the wait is triggered cb func() + // callback which is called to cancel a waiter + cancel func() } type wait struct { @@ -21,13 +23,13 @@ func newWait() *wait { return &wait{m: make(map[uint64]waitItem)} } -func (w *wait) register(id uint64, cb func()) <-chan interface{} { +func (w *wait) register(id uint64, cb func(), cancel func()) <-chan interface{} { w.l.Lock() defer w.l.Unlock() _, ok := w.m[id] if !ok { ch := make(chan interface{}, 1) - w.m[id] = waitItem{ch: ch, cb: cb} + w.m[id] = waitItem{ch: ch, cb: cb, cancel: cancel} return ch } panic(fmt.Sprintf("duplicate id %x", id)) @@ -43,7 +45,6 @@ func (w *wait) trigger(id uint64, x interface{}) bool { waitItem.cb() } waitItem.ch <- x - close(waitItem.ch) return true } return false @@ -54,8 +55,8 @@ func (w *wait) cancel(id uint64) { waitItem, ok := w.m[id] delete(w.m, id) w.l.Unlock() - if ok { - close(waitItem.ch) + if ok && waitItem.cancel != nil { + waitItem.cancel() } } @@ -65,6 +66,8 @@ func (w *wait) cancelAll() { for id, waitItem := range w.m { delete(w.m, id) - close(waitItem.ch) + if waitItem.cancel != nil { + waitItem.cancel() + } } } diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/watch/watch.go b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/watch/watch.go index 98392d57f0..a468237015 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/watch/watch.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/manager/state/watch/watch.go @@ -6,6 +6,29 @@ import ( "github.com/docker/go-events" ) +// dropErrClosed is a sink that suppresses ErrSinkClosed from Write, to avoid +// debug log messages that may be confusing. It is possible that the queue +// will try to write an event to its destination channel while the queue is +// being removed from the broadcaster. Since the channel is closed before the +// queue, there is a narrow window when this is possible. In some event-based +// dropping events when a sink is removed from a broadcaster is a problem, but +// for the usage in this watch package that's the expected behavior. +type dropErrClosed struct { + sink events.Sink +} + +func (s dropErrClosed) Write(event events.Event) error { + err := s.sink.Write(event) + if err == events.ErrSinkClosed { + return nil + } + return err +} + +func (s dropErrClosed) Close() error { + return s.sink.Close() +} + // Queue is the structure used to publish events and watch for them. type Queue struct { mu sync.Mutex @@ -35,7 +58,7 @@ func (q *Queue) Watch() (eventq chan events.Event, cancel func()) { // close the channel. func (q *Queue) CallbackWatch(matcher events.Matcher) (eventq chan events.Event, cancel func()) { ch := events.NewChannel(0) - sink := events.Sink(events.NewQueue(ch)) + sink := events.Sink(events.NewQueue(dropErrClosed{sink: ch})) if matcher != nil { sink = events.NewFilter(sink, matcher) diff --git a/components/engine/vendor/src/github.com/docker/swarmkit/protobuf/plugin/plugin.pb.go b/components/engine/vendor/src/github.com/docker/swarmkit/protobuf/plugin/plugin.pb.go index 762ac088a9..7f2feacaa3 100644 --- a/components/engine/vendor/src/github.com/docker/swarmkit/protobuf/plugin/plugin.pb.go +++ b/components/engine/vendor/src/github.com/docker/swarmkit/protobuf/plugin/plugin.pb.go @@ -33,7 +33,9 @@ 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. -const _ = proto.GoGoProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type TLSAuthorization struct { // Roles contains the acceptable TLS OU roles for the handler. @@ -96,11 +98,12 @@ func valueToGoStringPlugin(v interface{}, typ string) string { pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) } -func extensionToGoStringPlugin(e map[int32]github_com_gogo_protobuf_proto.Extension) string { +func extensionToGoStringPlugin(m github_com_gogo_protobuf_proto.Message) string { + e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m) if e == nil { return "nil" } - s := "map[int32]proto.Extension{" + s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{" keys := make([]int, 0, len(e)) for k := range e { keys = append(keys, int(k)) @@ -110,7 +113,7 @@ func extensionToGoStringPlugin(e map[int32]github_com_gogo_protobuf_proto.Extens for _, k := range keys { ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) } - s += strings.Join(ss, ",") + "}" + s += strings.Join(ss, ",") + "})" return s } func (m *TLSAuthorization) Marshal() (data []byte, err error) { @@ -443,6 +446,8 @@ var ( ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow") ) +func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) } + var fileDescriptorPlugin = []byte{ // 259 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d, From caffc36efd94818206d7559781a3b5208d90530e Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 13 Sep 2016 09:28:31 -0700 Subject: [PATCH 3/3] libcontainerd: do not use failfast for events stream New grpc uses failfast by default, but that code was written with other default in mind, so just preserve it for now. Signed-off-by: Alexander Morozov Upstream-commit: 5fb383243234dfebc468207cfd7f64eca1b7f849 Component: engine --- components/engine/libcontainerd/remote_linux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/libcontainerd/remote_linux.go b/components/engine/libcontainerd/remote_linux.go index e7fcb257b6..10253dacb1 100644 --- a/components/engine/libcontainerd/remote_linux.go +++ b/components/engine/libcontainerd/remote_linux.go @@ -279,7 +279,7 @@ func (r *remote) startEventsMonitor() error { er := &containerd.EventsRequest{ Timestamp: tsp, } - events, err := r.apiClient.Events(context.Background(), er) + events, err := r.apiClient.Events(context.Background(), er, grpc.FailFast(false)) if err != nil { return err }