From 6b9e71f4186ae1e65d59611e3dc69e9162230c8e Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Thu, 17 Oct 2024 11:37:12 -0700 Subject: [PATCH] [v2] Set config all at once (#718) We currently issue one `SetAllConfig` RPC for each user-specified config. This is slow but it has important correctness guarantees: 1. The order we apply config matters -- if the user specifies `foo: foo` followed by `foo: bar`, the net result must always be `foo: bar`. 2. The Pulumi CLI (and therefore Automation API) only allows specifying `--path` on an all-or-nothing basis. This is bad for us because we potentially have a blend of path and non-path keys. Ideally we would be able to supply all of our configs to the automation API in a single call, and in the case where _all_ of our config keys are path-like (or all are not path-like) we actually can do that because we no longer have limitation (2). This PR makes that possible in the general case by transforming our config keys in a way that allows us to treat them as if they are all path-like. In particular: * The agent's `SetAllConfig` handler is modified to take a list of configs instead of a map in order to preserve config order. The top-level `path` param is also removed and handled on a per-key basis. * While resolving configs, we escape any non-path keys so subsequent path parsing treats them as verbatim. For example `foo.bar` gets escaped as `["foo.bar"]`. * We can then supply all of our keys at once to Automation API with `Path: true`. * If there are no configs to set then the operator doesn't invoke `SetAllConfig`. Fixes https://github.com/pulumi/pulumi-kubernetes-operator/issues/650 --- agent/pkg/proto/agent.pb.go | 672 +++++++++--------- agent/pkg/proto/agent.proto | 19 +- agent/pkg/server/grpc_test.go | 7 +- agent/pkg/server/server.go | 77 +- agent/pkg/server/server_test.go | 174 +++-- .../server/testdata/simple/Pulumi.nested.yaml | 11 + operator/internal/controller/auto/utils.go | 13 +- .../controller/auto/workspace_controller.go | 21 +- 8 files changed, 559 insertions(+), 435 deletions(-) create mode 100644 agent/pkg/server/testdata/simple/Pulumi.nested.yaml diff --git a/agent/pkg/proto/agent.pb.go b/agent/pkg/proto/agent.pb.go index 747934ed..5d0a89f6 100644 --- a/agent/pkg/proto/agent.pb.go +++ b/agent/pkg/proto/agent.pb.go @@ -405,8 +405,7 @@ type SetAllConfigRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Path *bool `protobuf:"varint,1,opt,name=path,proto3,oneof" json:"path,omitempty"` // Parse the keys as paths in a map or list rather than raw strings - Config map[string]*ConfigValue `protobuf:"bytes,2,rep,name=config,proto3" json:"config,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // a map of ConfigValue used by Pulumi programs + Config []*ConfigItem `protobuf:"bytes,1,rep,name=config,proto3" json:"config,omitempty"` } func (x *SetAllConfigRequest) Reset() { @@ -441,35 +440,30 @@ func (*SetAllConfigRequest) Descriptor() ([]byte, []int) { return file_agent_proto_rawDescGZIP(), []int{7} } -func (x *SetAllConfigRequest) GetPath() bool { - if x != nil && x.Path != nil { - return *x.Path - } - return false -} - -func (x *SetAllConfigRequest) GetConfig() map[string]*ConfigValue { +func (x *SetAllConfigRequest) GetConfig() []*ConfigItem { if x != nil { return x.Config } return nil } -type ConfigValue struct { +type ConfigItem struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // The config's key. + Path *bool `protobuf:"varint,2,opt,name=path,proto3,oneof" json:"path,omitempty"` // Parse the key as a paths in a map or list rather than as a raw string. // Types that are assignable to V: // - // *ConfigValue_Value - // *ConfigValue_ValueFrom - V isConfigValue_V `protobuf_oneof:"v"` - Secret *bool `protobuf:"varint,3,opt,name=secret,proto3,oneof" json:"secret,omitempty"` + // *ConfigItem_Value + // *ConfigItem_ValueFrom + V isConfigItem_V `protobuf_oneof:"v"` + Secret *bool `protobuf:"varint,5,opt,name=secret,proto3,oneof" json:"secret,omitempty"` // Whether the config is a secret. } -func (x *ConfigValue) Reset() { - *x = ConfigValue{} +func (x *ConfigItem) Reset() { + *x = ConfigItem{} if protoimpl.UnsafeEnabled { mi := &file_agent_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -477,13 +471,13 @@ func (x *ConfigValue) Reset() { } } -func (x *ConfigValue) String() string { +func (x *ConfigItem) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ConfigValue) ProtoMessage() {} +func (*ConfigItem) ProtoMessage() {} -func (x *ConfigValue) ProtoReflect() protoreflect.Message { +func (x *ConfigItem) ProtoReflect() protoreflect.Message { mi := &file_agent_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -495,54 +489,68 @@ func (x *ConfigValue) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ConfigValue.ProtoReflect.Descriptor instead. -func (*ConfigValue) Descriptor() ([]byte, []int) { +// Deprecated: Use ConfigItem.ProtoReflect.Descriptor instead. +func (*ConfigItem) Descriptor() ([]byte, []int) { return file_agent_proto_rawDescGZIP(), []int{8} } -func (m *ConfigValue) GetV() isConfigValue_V { +func (x *ConfigItem) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *ConfigItem) GetPath() bool { + if x != nil && x.Path != nil { + return *x.Path + } + return false +} + +func (m *ConfigItem) GetV() isConfigItem_V { if m != nil { return m.V } return nil } -func (x *ConfigValue) GetValue() *structpb.Value { - if x, ok := x.GetV().(*ConfigValue_Value); ok { +func (x *ConfigItem) GetValue() *structpb.Value { + if x, ok := x.GetV().(*ConfigItem_Value); ok { return x.Value } return nil } -func (x *ConfigValue) GetValueFrom() *ConfigValueFrom { - if x, ok := x.GetV().(*ConfigValue_ValueFrom); ok { +func (x *ConfigItem) GetValueFrom() *ConfigValueFrom { + if x, ok := x.GetV().(*ConfigItem_ValueFrom); ok { return x.ValueFrom } return nil } -func (x *ConfigValue) GetSecret() bool { +func (x *ConfigItem) GetSecret() bool { if x != nil && x.Secret != nil { return *x.Secret } return false } -type isConfigValue_V interface { - isConfigValue_V() +type isConfigItem_V interface { + isConfigItem_V() } -type ConfigValue_Value struct { - Value *structpb.Value `protobuf:"bytes,1,opt,name=value,proto3,oneof"` +type ConfigItem_Value struct { + Value *structpb.Value `protobuf:"bytes,3,opt,name=value,proto3,oneof"` // A literal value. } -type ConfigValue_ValueFrom struct { - ValueFrom *ConfigValueFrom `protobuf:"bytes,2,opt,name=value_from,json=valueFrom,proto3,oneof"` +type ConfigItem_ValueFrom struct { + ValueFrom *ConfigValueFrom `protobuf:"bytes,4,opt,name=value_from,json=valueFrom,proto3,oneof"` // A value read from the environment or local disk. } -func (*ConfigValue_Value) isConfigValue_V() {} +func (*ConfigItem_Value) isConfigItem_V() {} -func (*ConfigValue_ValueFrom) isConfigValue_V() {} +func (*ConfigItem_ValueFrom) isConfigItem_V() {} type ConfigValueFrom struct { state protoimpl.MessageState @@ -614,11 +622,11 @@ type isConfigValueFrom_F interface { } type ConfigValueFrom_Env struct { - Env string `protobuf:"bytes,1,opt,name=env,proto3,oneof"` // the name of an environment variable to read + Env string `protobuf:"bytes,1,opt,name=env,proto3,oneof"` // The name of an environment variable to read> } type ConfigValueFrom_Path struct { - Path string `protobuf:"bytes,2,opt,name=path,proto3,oneof"` // the path to a file to read + Path string `protobuf:"bytes,2,opt,name=path,proto3,oneof"` // The path to a file to read. } func (*ConfigValueFrom_Env) isConfigValueFrom_F() {} @@ -2005,262 +2013,257 @@ var file_agent_proto_rawDesc = []byte{ 0x15, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x75, 0x72, - 0x6c, 0x22, 0xc6, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x88, - 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x6c, - 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x1a, 0x4d, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x22, 0xa3, 0x01, 0x0a, 0x0b, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, - 0x72, 0x6f, 0x6d, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x88, 0x01, 0x01, - 0x42, 0x03, 0x0a, 0x01, 0x76, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, - 0x22, 0x40, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, - 0x72, 0x6f, 0x6d, 0x12, 0x12, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x03, 0x0a, - 0x01, 0x66, 0x22, 0x14, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x10, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x0e, - 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, - 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, - 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2f, - 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x0f, 0x65, 0x78, 0x70, - 0x65, 0x63, 0x74, 0x4e, 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, - 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, - 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x7c, 0x0a, 0x0d, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, - 0x68, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, - 0x00, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, - 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, - 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, - 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, - 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x89, 0x03, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, + 0x6c, 0x22, 0x40, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x22, 0xd6, 0x01, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x74, + 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x37, 0x0a, + 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x48, 0x00, 0x52, 0x09, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x88, 0x01, 0x01, 0x42, 0x03, 0x0a, 0x01, 0x76, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x61, 0x74, + 0x68, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x40, 0x0a, 0x0f, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, + 0x12, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, + 0x65, 0x6e, 0x76, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x03, 0x0a, 0x01, 0x66, 0x22, 0x14, + 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x10, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x4e, - 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x72, - 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, - 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, - 0x32, 0x0a, 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, - 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, - 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x42, - 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, - 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x72, 0x65, 0x66, 0x72, - 0x65, 0x73, 0x68, 0x22, 0x20, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, - 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x7c, 0x0a, 0x0d, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, - 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x64, 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, 0x72, - 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0xcb, 0x03, 0x0a, 0x09, 0x55, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, - 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, - 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, - 0x02, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x4e, 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x03, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x70, 0x65, - 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x0b, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, - 0x6b, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, - 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, - 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, - 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x69, - 0x6e, 0x75, 0x65, 0x4f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, - 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, - 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, - 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, - 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x42, 0x14, - 0x0a, 0x12, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x72, 0x0a, 0x08, 0x55, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x29, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa3, 0x02, 0x0a, 0x08, 0x55, 0x70, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x64, 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, - 0x1a, 0x4e, 0x0a, 0x0c, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x3b, - 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0xb3, 0x01, 0x0a, 0x0d, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x39, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, - 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x11, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1d, - 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, - 0x03, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, - 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, - 0x69, 0x6e, 0x75, 0x65, 0x4f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1b, - 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, - 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, - 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, - 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x72, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, - 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x09, 0x0a, 0x07, - 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x7c, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x74, 0x72, - 0x6f, 0x79, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, - 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, - 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, - 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, - 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, - 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, - 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x32, 0xa5, 0x04, 0x0a, 0x11, 0x41, 0x75, 0x74, - 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, - 0x0a, 0x06, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x12, 0x19, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x18, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x74, - 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x04, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0c, - 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x12, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, - 0x3a, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x15, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2b, 0x0a, 0x02, 0x55, 0x70, 0x12, 0x10, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x0f, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, - 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, - 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, - 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x75, 0x6c, 0x75, 0x6d, 0x69, 0x2f, 0x70, 0x75, 0x6c, 0x75, 0x6d, 0x69, 0x2d, 0x6b, 0x75, 0x62, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, + 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, + 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x22, 0x7c, 0x0a, 0x0d, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0xa0, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x65, + 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x6e, 0x6b, 0x22, 0x89, 0x03, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, + 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, + 0x6c, 0x6c, 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x02, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x4e, 0x6f, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, + 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x0b, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, + 0x61, 0x63, 0x6b, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, + 0x1d, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x04, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, 0x01, 0x01, 0x42, 0x0b, + 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x42, 0x14, 0x0a, + 0x12, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, + 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x22, + 0x20, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x22, 0x7c, 0x0a, 0x0d, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xa0, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, + 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, + 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, + 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x6e, 0x6b, 0x22, 0xcb, 0x03, 0x0a, 0x09, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x88, 0x01, + 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x2f, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x5f, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x0f, 0x65, + 0x78, 0x70, 0x65, 0x63, 0x74, 0x4e, 0x6f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x88, 0x01, + 0x01, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, + 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, + 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, + 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, + 0x70, 0x61, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x0a, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x07, 0x72, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x07, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x74, + 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x4f, + 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, + 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x6f, + 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, + 0x0a, 0x08, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x72, 0x0a, 0x08, 0x55, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa3, 0x02, 0x0a, 0x08, 0x55, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, + 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, + 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, + 0x6b, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x1a, 0x4e, 0x0a, 0x0c, + 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, + 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x3b, 0x0a, 0x0b, 0x4f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0xb3, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xe3, 0x02, + 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x88, 0x01, + 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x07, 0x72, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x63, 0x6f, 0x6e, + 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, + 0x4f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x06, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x61, 0x72, 0x61, + 0x6c, 0x6c, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x65, + 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, + 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x22, 0x7c, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, + 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x64, + 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x6e, 0x6b, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x6e, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x61, + 0x6c, 0x69, 0x6e, 0x6b, 0x32, 0xa5, 0x04, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x57, 0x68, + 0x6f, 0x41, 0x6d, 0x49, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x68, 0x6f, + 0x41, 0x6d, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x57, 0x68, 0x6f, 0x41, 0x6d, 0x49, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, + 0x00, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x12, 0x19, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, + 0x74, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x41, + 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x74, + 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, + 0x00, 0x12, 0x38, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x07, 0x50, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, 0x52, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x2b, 0x0a, 0x02, 0x55, 0x70, 0x12, 0x10, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, + 0x12, 0x3a, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x15, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, + 0x6f, 0x79, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x00, 0x30, 0x01, 0x42, 0x41, 0x5a, 0x3f, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x6c, 0x75, 0x6d, + 0x69, 0x2f, 0x70, 0x75, 0x6c, 0x75, 0x6d, 0x69, 0x2d, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x65, 0x73, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x32, 0x2f, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2275,7 +2278,7 @@ func file_agent_proto_rawDescGZIP() []byte { return file_agent_proto_rawDescData } -var file_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 30) +var file_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 29) var file_agent_proto_goTypes = []any{ (*WhoAmIRequest)(nil), // 0: agent.WhoAmIRequest (*WhoAmIResult)(nil), // 1: agent.WhoAmIResult @@ -2285,7 +2288,7 @@ var file_agent_proto_goTypes = []any{ (*InfoResult)(nil), // 5: agent.InfoResult (*StackSummary)(nil), // 6: agent.StackSummary (*SetAllConfigRequest)(nil), // 7: agent.SetAllConfigRequest - (*ConfigValue)(nil), // 8: agent.ConfigValue + (*ConfigItem)(nil), // 8: agent.ConfigItem (*ConfigValueFrom)(nil), // 9: agent.ConfigValueFrom (*SetAllConfigResult)(nil), // 10: agent.SetAllConfigResult (*InstallRequest)(nil), // 11: agent.InstallRequest @@ -2305,61 +2308,59 @@ var file_agent_proto_goTypes = []any{ (*DestroyRequest)(nil), // 25: agent.DestroyRequest (*DestroyStream)(nil), // 26: agent.DestroyStream (*DestroyResult)(nil), // 27: agent.DestroyResult - nil, // 28: agent.SetAllConfigRequest.ConfigEntry - nil, // 29: agent.UpResult.OutputsEntry - (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp - (*structpb.Value)(nil), // 31: google.protobuf.Value - (*structpb.Struct)(nil), // 32: google.protobuf.Struct + nil, // 28: agent.UpResult.OutputsEntry + (*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp + (*structpb.Value)(nil), // 30: google.protobuf.Value + (*structpb.Struct)(nil), // 31: google.protobuf.Struct } var file_agent_proto_depIdxs = []int32{ 6, // 0: agent.SelectStackResult.summary:type_name -> agent.StackSummary 6, // 1: agent.InfoResult.summary:type_name -> agent.StackSummary - 30, // 2: agent.StackSummary.last_update:type_name -> google.protobuf.Timestamp - 28, // 3: agent.SetAllConfigRequest.config:type_name -> agent.SetAllConfigRequest.ConfigEntry - 31, // 4: agent.ConfigValue.value:type_name -> google.protobuf.Value - 9, // 5: agent.ConfigValue.value_from:type_name -> agent.ConfigValueFrom - 32, // 6: agent.RefreshStream.event:type_name -> google.protobuf.Struct + 29, // 2: agent.StackSummary.last_update:type_name -> google.protobuf.Timestamp + 8, // 3: agent.SetAllConfigRequest.config:type_name -> agent.ConfigItem + 30, // 4: agent.ConfigItem.value:type_name -> google.protobuf.Value + 9, // 5: agent.ConfigItem.value_from:type_name -> agent.ConfigValueFrom + 31, // 6: agent.RefreshStream.event:type_name -> google.protobuf.Struct 15, // 7: agent.RefreshStream.result:type_name -> agent.RefreshResult 24, // 8: agent.RefreshResult.summary:type_name -> agent.UpdateSummary 17, // 9: agent.PreviewRequest.policy_pack:type_name -> agent.PolicyPack - 32, // 10: agent.PreviewStream.event:type_name -> google.protobuf.Struct + 31, // 10: agent.PreviewStream.event:type_name -> google.protobuf.Struct 19, // 11: agent.PreviewStream.result:type_name -> agent.PreviewResult 24, // 12: agent.PreviewResult.summary:type_name -> agent.UpdateSummary 17, // 13: agent.UpRequest.policy_pack:type_name -> agent.PolicyPack - 32, // 14: agent.UpStream.event:type_name -> google.protobuf.Struct + 31, // 14: agent.UpStream.event:type_name -> google.protobuf.Struct 22, // 15: agent.UpStream.result:type_name -> agent.UpResult 24, // 16: agent.UpResult.summary:type_name -> agent.UpdateSummary - 29, // 17: agent.UpResult.outputs:type_name -> agent.UpResult.OutputsEntry - 30, // 18: agent.UpdateSummary.start_time:type_name -> google.protobuf.Timestamp - 30, // 19: agent.UpdateSummary.end_time:type_name -> google.protobuf.Timestamp - 32, // 20: agent.DestroyStream.event:type_name -> google.protobuf.Struct + 28, // 17: agent.UpResult.outputs:type_name -> agent.UpResult.OutputsEntry + 29, // 18: agent.UpdateSummary.start_time:type_name -> google.protobuf.Timestamp + 29, // 19: agent.UpdateSummary.end_time:type_name -> google.protobuf.Timestamp + 31, // 20: agent.DestroyStream.event:type_name -> google.protobuf.Struct 27, // 21: agent.DestroyStream.result:type_name -> agent.DestroyResult 24, // 22: agent.DestroyResult.summary:type_name -> agent.UpdateSummary - 8, // 23: agent.SetAllConfigRequest.ConfigEntry.value:type_name -> agent.ConfigValue - 23, // 24: agent.UpResult.OutputsEntry.value:type_name -> agent.OutputValue - 0, // 25: agent.AutomationService.WhoAmI:input_type -> agent.WhoAmIRequest - 2, // 26: agent.AutomationService.SelectStack:input_type -> agent.SelectStackRequest - 4, // 27: agent.AutomationService.Info:input_type -> agent.InfoRequest - 7, // 28: agent.AutomationService.SetAllConfig:input_type -> agent.SetAllConfigRequest - 11, // 29: agent.AutomationService.Install:input_type -> agent.InstallRequest - 16, // 30: agent.AutomationService.Preview:input_type -> agent.PreviewRequest - 13, // 31: agent.AutomationService.Refresh:input_type -> agent.RefreshRequest - 20, // 32: agent.AutomationService.Up:input_type -> agent.UpRequest - 25, // 33: agent.AutomationService.Destroy:input_type -> agent.DestroyRequest - 1, // 34: agent.AutomationService.WhoAmI:output_type -> agent.WhoAmIResult - 3, // 35: agent.AutomationService.SelectStack:output_type -> agent.SelectStackResult - 5, // 36: agent.AutomationService.Info:output_type -> agent.InfoResult - 10, // 37: agent.AutomationService.SetAllConfig:output_type -> agent.SetAllConfigResult - 12, // 38: agent.AutomationService.Install:output_type -> agent.InstallResult - 18, // 39: agent.AutomationService.Preview:output_type -> agent.PreviewStream - 14, // 40: agent.AutomationService.Refresh:output_type -> agent.RefreshStream - 21, // 41: agent.AutomationService.Up:output_type -> agent.UpStream - 26, // 42: agent.AutomationService.Destroy:output_type -> agent.DestroyStream - 34, // [34:43] is the sub-list for method output_type - 25, // [25:34] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 23, // 23: agent.UpResult.OutputsEntry.value:type_name -> agent.OutputValue + 0, // 24: agent.AutomationService.WhoAmI:input_type -> agent.WhoAmIRequest + 2, // 25: agent.AutomationService.SelectStack:input_type -> agent.SelectStackRequest + 4, // 26: agent.AutomationService.Info:input_type -> agent.InfoRequest + 7, // 27: agent.AutomationService.SetAllConfig:input_type -> agent.SetAllConfigRequest + 11, // 28: agent.AutomationService.Install:input_type -> agent.InstallRequest + 16, // 29: agent.AutomationService.Preview:input_type -> agent.PreviewRequest + 13, // 30: agent.AutomationService.Refresh:input_type -> agent.RefreshRequest + 20, // 31: agent.AutomationService.Up:input_type -> agent.UpRequest + 25, // 32: agent.AutomationService.Destroy:input_type -> agent.DestroyRequest + 1, // 33: agent.AutomationService.WhoAmI:output_type -> agent.WhoAmIResult + 3, // 34: agent.AutomationService.SelectStack:output_type -> agent.SelectStackResult + 5, // 35: agent.AutomationService.Info:output_type -> agent.InfoResult + 10, // 36: agent.AutomationService.SetAllConfig:output_type -> agent.SetAllConfigResult + 12, // 37: agent.AutomationService.Install:output_type -> agent.InstallResult + 18, // 38: agent.AutomationService.Preview:output_type -> agent.PreviewStream + 14, // 39: agent.AutomationService.Refresh:output_type -> agent.RefreshStream + 21, // 40: agent.AutomationService.Up:output_type -> agent.UpStream + 26, // 41: agent.AutomationService.Destroy:output_type -> agent.DestroyStream + 33, // [33:42] is the sub-list for method output_type + 24, // [24:33] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_agent_proto_init() } @@ -2465,7 +2466,7 @@ func file_agent_proto_init() { } } file_agent_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*ConfigValue); i { + switch v := v.(*ConfigItem); i { case 0: return &v.state case 1: @@ -2707,10 +2708,9 @@ func file_agent_proto_init() { } file_agent_proto_msgTypes[2].OneofWrappers = []any{} file_agent_proto_msgTypes[6].OneofWrappers = []any{} - file_agent_proto_msgTypes[7].OneofWrappers = []any{} file_agent_proto_msgTypes[8].OneofWrappers = []any{ - (*ConfigValue_Value)(nil), - (*ConfigValue_ValueFrom)(nil), + (*ConfigItem_Value)(nil), + (*ConfigItem_ValueFrom)(nil), } file_agent_proto_msgTypes[9].OneofWrappers = []any{ (*ConfigValueFrom_Env)(nil), @@ -2746,7 +2746,7 @@ func file_agent_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_agent_proto_rawDesc, NumEnums: 0, - NumMessages: 30, + NumMessages: 29, NumExtensions: 0, NumServices: 1, }, diff --git a/agent/pkg/proto/agent.proto b/agent/pkg/proto/agent.proto index c733c0dc..0f5cb793 100644 --- a/agent/pkg/proto/agent.proto +++ b/agent/pkg/proto/agent.proto @@ -91,24 +91,23 @@ message StackSummary { } message SetAllConfigRequest { - optional bool path = - 1; // Parse the keys as paths in a map or list rather than raw strings - map config = - 2; // a map of ConfigValue used by Pulumi programs + repeated ConfigItem config = 1; } -message ConfigValue { +message ConfigItem { + string key = 1; // The config's key. + optional bool path = 2; // Parse the key as a paths in a map or list rather than as a raw string. oneof v { - google.protobuf.Value value = 1; - ConfigValueFrom value_from = 2; + google.protobuf.Value value = 3; // A literal value. + ConfigValueFrom value_from = 4; // A value read from the environment or local disk. } - optional bool secret = 3; + optional bool secret = 5; // Whether the config is a secret. } message ConfigValueFrom { oneof f { - string env = 1; // the name of an environment variable to read - string path = 2; // the path to a file to read + string env = 1; // The name of an environment variable to read> + string path = 2; // The path to a file to read. } } diff --git a/agent/pkg/server/grpc_test.go b/agent/pkg/server/grpc_test.go index 263719b1..b7e847aa 100644 --- a/agent/pkg/server/grpc_test.go +++ b/agent/pkg/server/grpc_test.go @@ -13,9 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -package server_test - -// TODO: Why are we using a black box test package? +package server import ( "context" @@ -25,7 +23,6 @@ import ( "time" pb "github.com/pulumi/pulumi-kubernetes-operator/v2/agent/pkg/proto" - "github.com/pulumi/pulumi-kubernetes-operator/v2/agent/pkg/server" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -45,7 +42,7 @@ func TestGracefulShutdown(t *testing.T) { tc := newTC(ctx, t, tcOptions{ProjectDir: "./testdata/hang", Stacks: []string{"test"}}) log := zap.L().Named("test").Sugar() lis := bufconn.Listen(1024) - s := server.NewGRPC(log, tc.server, nil) + s := NewGRPC(log, tc.server, nil) go func() { // This should exit cleanly if we shut down gracefully. if err := s.Serve(ctx, lis); err != nil { diff --git a/agent/pkg/server/server.go b/agent/pkg/server/server.go index 3b60a370..07e7b90e 100644 --- a/agent/pkg/server/server.go +++ b/agent/pkg/server/server.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "os" + "strings" "sync" "sync/atomic" "time" @@ -41,6 +42,8 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/auto/optrefresh" "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" "github.com/pulumi/pulumi/sdk/v3/go/common/apitype" + "github.com/pulumi/pulumi/sdk/v3/go/common/resource/config" + "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" ) const ( @@ -242,27 +245,67 @@ func (s *Server) SetAllConfig(ctx context.Context, in *pb.SetAllConfigRequest) ( return nil, err } - config := make(map[string]auto.ConfigValue) - for k, inv := range in.GetConfig() { - if k == "" { - return nil, status.Errorf(codes.InvalidArgument, "invalid config key: %s", k) - } - v, err := unmarshalConfigValue(inv) - if err != nil { - return nil, err - } - config[k] = v + p, err := stack.Workspace().ProjectSettings(ctx) + if err != nil { + return nil, fmt.Errorf("getting project settings: %w", err) + } + + config, err := unmarshalConfigItems(p.Name.String(), in.Config) + if err != nil { + return nil, fmt.Errorf("config items: %w", err) } + s.log.Debugw("setting all config", "config", config) - err = stack.SetAllConfigWithOptions(ctx, config, &auto.ConfigOptions{ - Path: in.GetPath(), - }) + err = stack.SetAllConfigWithOptions(ctx, config, &auto.ConfigOptions{Path: true}) if err != nil { return nil, err } - return nil, nil + return &pb.SetAllConfigResult{}, nil +} + +// unmarshalConfigItems maps proto ConfigItems to an auto.ConfigMap whose +// structure is appropriate for invoking with `pulumi config set-all --path` +// for efficiency. Config items whose keys are not meant to be treated as paths +// are escaped so they are treated as verbatim property paths. +func unmarshalConfigItems(project string, items []*pb.ConfigItem) (auto.ConfigMap, error) { + out := auto.ConfigMap{} + + for _, item := range items { + v, err := unmarshalConfigItem(item) // Resolves valueFrom. + if err != nil { + return nil, fmt.Errorf("unmarshalling %q config: %w", item.Key, err) + } + + // ParseKey requires all keys to be explicitly namespaced, so scope any + // implicit keys to our project. + key := item.Key + if !strings.Contains(key, tokens.TokenDelimiter) { + key = project + ":" + key + } + k, err := config.ParseKey(key) + if err != nil { + return nil, fmt.Errorf("parsing %q key: %w", key, err) + } + + // Keys which are not meant to be interpreted as paths as escaped so + // subsequent path parsing treats them as-is. In particular "foo" + // becomes `[""]`. Items which are already escaped in this way are + // untouched. See + // https://github.com/pulumi/pulumi/blob/4424d69177c47385ea4a01d8ad1b0b825d394f63/sdk/go/common/resource/properties_path.go#L32-L64 + path := false + if item.Path != nil { + path = *item.Path + } + if !path && !(strings.HasPrefix(k.Name(), `["`) && strings.HasSuffix(k.Name(), `"]`)) { + k = config.MustMakeKey(k.Namespace(), fmt.Sprintf("[%q]", k.Name())) + } + + out[k.String()] = v + } + + return out, nil } func (s *Server) Install(ctx context.Context, in *pb.InstallRequest) (*pb.InstallResult, error) { @@ -656,15 +699,15 @@ func (s *Server) Destroy(in *pb.DestroyRequest, srv pb.AutomationService_Destroy return nil } -func unmarshalConfigValue(inv *pb.ConfigValue) (auto.ConfigValue, error) { +func unmarshalConfigItem(inv *pb.ConfigItem) (auto.ConfigValue, error) { v := auto.ConfigValue{ Secret: inv.GetSecret(), } switch vv := inv.V.(type) { - case *pb.ConfigValue_Value: + case *pb.ConfigItem_Value: // FUTURE: use JSON values v.Value = fmt.Sprintf("%v", vv.Value.AsInterface()) - case *pb.ConfigValue_ValueFrom: + case *pb.ConfigItem_ValueFrom: switch from := vv.ValueFrom.F.(type) { case *pb.ConfigValueFrom_Env: data, ok := os.LookupEnv(from.Env) diff --git a/agent/pkg/server/server_test.go b/agent/pkg/server/server_test.go index b67c238f..87ba8c26 100644 --- a/agent/pkg/server/server_test.go +++ b/agent/pkg/server/server_test.go @@ -1,4 +1,4 @@ -package server_test +package server import ( "context" @@ -13,13 +13,16 @@ import ( "github.com/onsi/gomega" "github.com/onsi/gomega/format" "github.com/onsi/gomega/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/structpb" + "k8s.io/utils/ptr" pb "github.com/pulumi/pulumi-kubernetes-operator/v2/agent/pkg/proto" - "github.com/pulumi/pulumi-kubernetes-operator/v2/agent/pkg/server" + "github.com/pulumi/pulumi/sdk/v3/go/auto" "github.com/pulumi/pulumi/sdk/v3/go/common/util/fsutil" "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" @@ -35,7 +38,7 @@ func TestNewServer(t *testing.T) { tests := []struct { name string projectDir string - opts *server.Options + opts *Options wantErr any }{ { @@ -54,7 +57,7 @@ func TestNewServer(t *testing.T) { { name: "new stack", projectDir: "./testdata/simple", - opts: &server.Options{StackName: "new"}, + opts: &Options{StackName: "new"}, }, } for _, tt := range tests { @@ -66,7 +69,7 @@ func TestNewServer(t *testing.T) { ctx := newContext(t) ws := newWorkspace(ctx, t, tt.projectDir) - _, err := server.NewServer(ctx, ws, tt.opts) + _, err := NewServer(ctx, ws, tt.opts) if tt.wantErr != nil { g.Expect(err).To(gomega.MatchError(tt.wantErr)) } else { @@ -162,7 +165,7 @@ func TestSelectStack(t *testing.T) { name: "non-existent stack with create", req: pb.SelectStackRequest{ StackName: "one", - Create: Pointer(true), + Create: ptr.To(true), }, }, } @@ -246,23 +249,24 @@ func TestSetAllConfig(t *testing.T) { tests := []struct { name string stacks []string - req pb.SetAllConfigRequest - wantErr any + req *pb.SetAllConfigRequest + wantErr error want auto.ConfigMap }{ { name: "no active stack", stacks: []string{}, - req: pb.SetAllConfigRequest{}, + req: &pb.SetAllConfigRequest{}, wantErr: status.Error(codes.FailedPrecondition, "no stack is selected"), }, { name: "literal", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ - Config: map[string]*pb.ConfigValue{ - "foo": {V: &pb.ConfigValue_Value{Value: strVal}}, - }, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{{ + Key: "foo", + V: &pb.ConfigItem_Value{Value: strVal}, + }}, }, want: auto.ConfigMap{ "simple:foo": {Value: "bar"}, @@ -271,11 +275,12 @@ func TestSetAllConfig(t *testing.T) { { name: "env", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ + req: &pb.SetAllConfigRequest{ // note that TestMain sets the FOO environment variable to a test value - Config: map[string]*pb.ConfigValue{ - "foo": {V: &pb.ConfigValue_ValueFrom{ValueFrom: &pb.ConfigValueFrom{F: &pb.ConfigValueFrom_Env{Env: "FOO"}}}}, - }, + Config: []*pb.ConfigItem{{ + Key: "foo", + V: &pb.ConfigItem_ValueFrom{ValueFrom: &pb.ConfigValueFrom{F: &pb.ConfigValueFrom_Env{Env: "FOO"}}}, + }}, }, want: auto.ConfigMap{ "simple:foo": {Value: "bar"}, @@ -284,11 +289,12 @@ func TestSetAllConfig(t *testing.T) { { name: "file", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ + req: &pb.SetAllConfigRequest{ // note that TestMain sets the FOO environment variable to a test value - Config: map[string]*pb.ConfigValue{ - "foo": {V: &pb.ConfigValue_ValueFrom{ValueFrom: &pb.ConfigValueFrom{F: &pb.ConfigValueFrom_Path{Path: "./testdata/foo.txt"}}}}, - }, + Config: []*pb.ConfigItem{{ + Key: "foo", + V: &pb.ConfigItem_ValueFrom{ValueFrom: &pb.ConfigValueFrom{F: &pb.ConfigValueFrom_Path{Path: "./testdata/foo.txt"}}}, + }}, }, want: auto.ConfigMap{ "simple:foo": {Value: "bar"}, @@ -297,10 +303,13 @@ func TestSetAllConfig(t *testing.T) { { name: "path-based", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ - Path: Pointer(true), - Config: map[string]*pb.ConfigValue{ - "a.b": {V: &pb.ConfigValue_Value{Value: strVal}}, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{ + { + Key: "a.b", + Path: ptr.To(true), + V: &pb.ConfigItem_Value{Value: strVal}, + }, }, }, want: auto.ConfigMap{ @@ -308,13 +317,75 @@ func TestSetAllConfig(t *testing.T) { }, }, { - name: "secret", + name: "path-like", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ - Config: map[string]*pb.ConfigValue{ - "foo": {V: &pb.ConfigValue_Value{Value: strVal}, Secret: Pointer(true)}, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{ + { + Key: "a.b", + Path: ptr.To(false), + V: &pb.ConfigItem_Value{Value: strVal}, + }, { + Key: `"quoted[key]"`, + Path: ptr.To(false), + V: &pb.ConfigItem_Value{Value: strVal}, + }, { + Key: `["already.escaped"]`, + Path: ptr.To(false), + V: &pb.ConfigItem_Value{Value: strVal}, + }, }, }, + want: auto.ConfigMap{ + "simple:a.b": {Value: "bar"}, + `simple:"quoted[key]"`: {Value: "bar"}, + `simple:already.escaped`: {Value: "bar"}, + }, + }, + { + name: "path-overlay", + stacks: []string{"nested"}, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{ + { + Key: "myList[0]", + Path: ptr.To(true), + V: &pb.ConfigItem_Value{Value: structpb.NewStringValue("1")}, + }, + { + Key: "myList[1]", + Path: ptr.To(true), + V: &pb.ConfigItem_Value{Value: structpb.NewStringValue("2")}, + }, + { + Key: "myList[3]", + Path: ptr.To(true), + V: &pb.ConfigItem_Value{Value: structpb.NewStringValue("four")}, + }, + { + Key: "outer.more.inner", + Path: ptr.To(true), + V: &pb.ConfigItem_Value{Value: structpb.NewStringValue("wrapped")}, + }, + }, + }, + want: auto.ConfigMap{ + "aws:region": {Value: `us-west-2`}, + "simple:foo": {Value: `aha`}, + "simple:bar": {Value: `1234`}, + "simple:myList": {Value: `[1,2,"three","four"]`}, + "simple:outer": {Value: `{"inner":"my_value","more":{"inner":"wrapped"},"other":"something_else"}`}, + }, + }, + { + name: "secret", + stacks: []string{TestStackName}, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{{ + Key: "foo", + V: &pb.ConfigItem_Value{Value: strVal}, Secret: ptr.To(true), + }}, + }, want: auto.ConfigMap{ "simple:foo": {Value: "bar", Secret: true}, }, @@ -322,10 +393,11 @@ func TestSetAllConfig(t *testing.T) { { name: "typed", stacks: []string{TestStackName}, - req: pb.SetAllConfigRequest{ - Config: map[string]*pb.ConfigValue{ - "enabled": {V: &pb.ConfigValue_Value{Value: boolVal}}, - }, + req: &pb.SetAllConfigRequest{ + Config: []*pb.ConfigItem{{ + Key: "enabled", + V: &pb.ConfigItem_Value{Value: boolVal}, + }}, }, want: auto.ConfigMap{ "simple:enabled": {Value: "true"}, @@ -333,22 +405,20 @@ func TestSetAllConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - g := gomega.NewWithT(t) ctx := newContext(t) tc := newTC(ctx, t, tcOptions{ProjectDir: "./testdata/simple", Stacks: tt.stacks}) - _, err := tc.server.SetAllConfig(ctx, &tt.req) + _, err := tc.server.SetAllConfig(ctx, tt.req) if tt.wantErr != nil { - g.Expect(err).To(gomega.MatchError(tt.wantErr)) - } else { - g.Expect(err).ToNot(gomega.HaveOccurred()) - - actual, err := tc.ws.GetAllConfig(ctx, tc.stack.Name()) - g.Expect(err).ToNot(gomega.HaveOccurred()) - g.Expect(actual).To(gomega.Equal(tt.want)) + assert.ErrorIs(t, err, tt.wantErr) + return } + require.NoError(t, err) + + actual, err := tc.ws.GetAllConfig(ctx, tc.stack.Name()) + assert.NoError(t, err) + assert.Equal(t, tt.want, actual) }) } } @@ -457,6 +527,7 @@ var _ pb.AutomationService_UpServer = (*upStream)(nil) func (m *upStream) Context() context.Context { return m.ctx } + func (m *upStream) Send(resp *pb.UpStream) error { m.mu.Lock() defer m.mu.Unlock() @@ -531,6 +602,7 @@ var _ pb.AutomationService_PreviewServer = (*previewStream)(nil) func (m *previewStream) Context() context.Context { return m.ctx } + func (m *previewStream) Send(resp *pb.PreviewStream) error { m.mu.Lock() defer m.mu.Unlock() @@ -607,6 +679,7 @@ var _ pb.AutomationService_RefreshServer = (*refreshStream)(nil) func (m *refreshStream) Context() context.Context { return m.ctx } + func (m *refreshStream) Send(resp *pb.RefreshStream) error { m.mu.Lock() defer m.mu.Unlock() @@ -683,6 +756,7 @@ var _ pb.AutomationService_DestroyServer = (*destroyStream)(nil) func (m *destroyStream) Context() context.Context { return m.ctx } + func (m *destroyStream) Send(resp *pb.DestroyStream) error { m.mu.Lock() defer m.mu.Unlock() @@ -711,7 +785,7 @@ func newWorkspace(ctx context.Context, t *testing.T, templateDir string) auto.Wo // generate a project based on the template, with a file backend tempDir := t.TempDir() if templateDir != "" { - err := os.MkdirAll(filepath.Join(tempDir, ".pulumi"), 0755) + err := os.MkdirAll(filepath.Join(tempDir, ".pulumi"), 0o755) if err != nil { t.Fatalf("failed to create state backend directory: %v", err) } @@ -741,10 +815,6 @@ func newWorkspace(ctx context.Context, t *testing.T, templateDir string) auto.Wo return ws } -func Pointer[T any](d T) *T { - return &d -} - func HasStatusCode(code codes.Code, msg types.GomegaMatcher) types.GomegaMatcher { return gomega.WithTransform(func(err error) status.Status { s, _ := status.FromError(err) @@ -758,21 +828,21 @@ func HasStatusCode(code codes.Code, msg types.GomegaMatcher) types.GomegaMatcher type testContext struct { ws auto.Workspace stack *auto.Stack - server *server.Server + server *Server } type tcOptions struct { ProjectDir string Stacks []string // pre-create some stacks; last one will be selected - ServerOpts *server.Options + ServerOpts *Options } func newTC(ctx context.Context, t *testing.T, opts tcOptions) *testContext { ws := newWorkspace(ctx, t, opts.ProjectDir) if opts.ServerOpts == nil { - opts.ServerOpts = &server.Options{} + opts.ServerOpts = &Options{} } - server, err := server.NewServer(ctx, ws, opts.ServerOpts) + server, err := NewServer(ctx, ws, opts.ServerOpts) if err != nil { t.Fatalf("failed to create server: %v", err) } diff --git a/agent/pkg/server/testdata/simple/Pulumi.nested.yaml b/agent/pkg/server/testdata/simple/Pulumi.nested.yaml new file mode 100644 index 00000000..9f008501 --- /dev/null +++ b/agent/pkg/server/testdata/simple/Pulumi.nested.yaml @@ -0,0 +1,11 @@ +config: + aws:region: us-west-2 + simple:bar: 1234 + simple:foo: aha + simple:myList: + - one + - two + - three + simple:outer: + inner: my_value + other: something_else diff --git a/operator/internal/controller/auto/utils.go b/operator/internal/controller/auto/utils.go index 4aa06f53..d29a93a5 100644 --- a/operator/internal/controller/auto/utils.go +++ b/operator/internal/controller/auto/utils.go @@ -62,15 +62,18 @@ func connect(ctx context.Context, addr string) (*grpc.ClientConn, error) { } } -func marshalConfigValue(item autov1alpha1.ConfigItem) *agentpb.ConfigValue { - v := &agentpb.ConfigValue{ +func marshalConfigItem(item autov1alpha1.ConfigItem) *agentpb.ConfigItem { + v := &agentpb.ConfigItem{ + Key: item.Key, + Path: item.Path, Secret: item.Secret, } if item.Value != nil { - v.V = &agentpb.ConfigValue_Value{ + v.V = &agentpb.ConfigItem_Value{ Value: structpb.NewStringValue(*item.Value), } - } else if item.ValueFrom != nil { + } + if item.ValueFrom != nil { f := &agentpb.ConfigValueFrom{} if item.ValueFrom.Env != "" { f.F = &agentpb.ConfigValueFrom_Env{ @@ -81,7 +84,7 @@ func marshalConfigValue(item autov1alpha1.ConfigItem) *agentpb.ConfigValue { Path: item.ValueFrom.Path, } } - v.V = &agentpb.ConfigValue_ValueFrom{ + v.V = &agentpb.ConfigItem_ValueFrom{ ValueFrom: f, } } diff --git a/operator/internal/controller/auto/workspace_controller.go b/operator/internal/controller/auto/workspace_controller.go index af9a63be..f9b0d8ea 100644 --- a/operator/internal/controller/auto/workspace_controller.go +++ b/operator/internal/controller/auto/workspace_controller.go @@ -270,19 +270,20 @@ func (r *WorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( }); err != nil { return err } + + if len(stack.Config) == 0 { + l.V(1).Info("No stack configuration to set") + return nil + } + l.V(1).Info("Setting the stack configuration") + + config := make([]*agentpb.ConfigItem, 0, len(stack.Config)) for _, item := range stack.Config { - v := marshalConfigValue(item) - if _, err = wc.SetAllConfig(ctx, &agentpb.SetAllConfigRequest{ - Path: item.Path, - Config: map[string]*agentpb.ConfigValue{ - item.Key: v, - }, - }); err != nil { - return err - } + config = append(config, marshalConfigItem(item)) } - return nil + _, err = wc.SetAllConfig(ctx, &agentpb.SetAllConfigRequest{Config: config}) + return err }() if err != nil { l.Error(err, "unable to initialize the Pulumi stack")