diff --git a/api/grpc/mpi/v1/command.pb.go b/api/grpc/mpi/v1/command.pb.go index b3cdd5cf1..b00c7d2cd 100644 --- a/api/grpc/mpi/v1/command.pb.go +++ b/api/grpc/mpi/v1/command.pb.go @@ -145,7 +145,7 @@ func (x InstanceMeta_InstanceType) Number() protoreflect.EnumNumber { // Deprecated: Use InstanceMeta_InstanceType.Descriptor instead. func (InstanceMeta_InstanceType) EnumDescriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{23, 0} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{26, 0} } // The connection request is an initial handshake to establish a connection, sending NGINX Agent instance information @@ -1290,6 +1290,9 @@ type NGINXPlusAction struct { // // *NGINXPlusAction_UpdateHttpUpstreamServers // *NGINXPlusAction_GetHttpUpstreamServers + // *NGINXPlusAction_UpdateStreamServers + // *NGINXPlusAction_GetUpstreams + // *NGINXPlusAction_GetStreamUpstreams Action isNGINXPlusAction_Action `protobuf_oneof:"action"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1350,22 +1353,67 @@ func (x *NGINXPlusAction) GetGetHttpUpstreamServers() *GetHTTPUpstreamServers { return nil } +func (x *NGINXPlusAction) GetUpdateStreamServers() *UpdateStreamServers { + if x != nil { + if x, ok := x.Action.(*NGINXPlusAction_UpdateStreamServers); ok { + return x.UpdateStreamServers + } + } + return nil +} + +func (x *NGINXPlusAction) GetGetUpstreams() *GetUpstreams { + if x != nil { + if x, ok := x.Action.(*NGINXPlusAction_GetUpstreams); ok { + return x.GetUpstreams + } + } + return nil +} + +func (x *NGINXPlusAction) GetGetStreamUpstreams() *GetStreamUpstreams { + if x != nil { + if x, ok := x.Action.(*NGINXPlusAction_GetStreamUpstreams); ok { + return x.GetStreamUpstreams + } + } + return nil +} + type isNGINXPlusAction_Action interface { isNGINXPlusAction_Action() } type NGINXPlusAction_UpdateHttpUpstreamServers struct { - UpdateHttpUpstreamServers *UpdateHTTPUpstreamServers `protobuf:"bytes,2,opt,name=update_http_upstream_servers,json=updateHttpUpstreamServers,proto3,oneof"` + UpdateHttpUpstreamServers *UpdateHTTPUpstreamServers `protobuf:"bytes,1,opt,name=update_http_upstream_servers,json=updateHttpUpstreamServers,proto3,oneof"` } type NGINXPlusAction_GetHttpUpstreamServers struct { - GetHttpUpstreamServers *GetHTTPUpstreamServers `protobuf:"bytes,3,opt,name=get_http_upstream_servers,json=getHttpUpstreamServers,proto3,oneof"` + GetHttpUpstreamServers *GetHTTPUpstreamServers `protobuf:"bytes,2,opt,name=get_http_upstream_servers,json=getHttpUpstreamServers,proto3,oneof"` +} + +type NGINXPlusAction_UpdateStreamServers struct { + UpdateStreamServers *UpdateStreamServers `protobuf:"bytes,3,opt,name=update_stream_servers,json=updateStreamServers,proto3,oneof"` +} + +type NGINXPlusAction_GetUpstreams struct { + GetUpstreams *GetUpstreams `protobuf:"bytes,4,opt,name=get_upstreams,json=getUpstreams,proto3,oneof"` +} + +type NGINXPlusAction_GetStreamUpstreams struct { + GetStreamUpstreams *GetStreamUpstreams `protobuf:"bytes,5,opt,name=get_stream_upstreams,json=getStreamUpstreams,proto3,oneof"` } func (*NGINXPlusAction_UpdateHttpUpstreamServers) isNGINXPlusAction_Action() {} func (*NGINXPlusAction_GetHttpUpstreamServers) isNGINXPlusAction_Action() {} +func (*NGINXPlusAction_UpdateStreamServers) isNGINXPlusAction_Action() {} + +func (*NGINXPlusAction_GetUpstreams) isNGINXPlusAction_Action() {} + +func (*NGINXPlusAction_GetStreamUpstreams) isNGINXPlusAction_Action() {} + // Update HTTP Upstream Servers for an instance type UpdateHTTPUpstreamServers struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1467,6 +1515,135 @@ func (x *GetHTTPUpstreamServers) GetHttpUpstreamName() string { return "" } +// Update Upstream Stream Servers for an instance +type UpdateStreamServers struct { + state protoimpl.MessageState `protogen:"open.v1"` + // the name of the upstream stream + UpstreamStreamName string `protobuf:"bytes,1,opt,name=upstream_stream_name,json=upstreamStreamName,proto3" json:"upstream_stream_name,omitempty"` + // a list of upstream stream servers + Servers []*structpb.Struct `protobuf:"bytes,2,rep,name=servers,proto3" json:"servers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStreamServers) Reset() { + *x = UpdateStreamServers{} + mi := &file_mpi_v1_command_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStreamServers) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStreamServers) ProtoMessage() {} + +func (x *UpdateStreamServers) ProtoReflect() protoreflect.Message { + mi := &file_mpi_v1_command_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStreamServers.ProtoReflect.Descriptor instead. +func (*UpdateStreamServers) Descriptor() ([]byte, []int) { + return file_mpi_v1_command_proto_rawDescGZIP(), []int{21} +} + +func (x *UpdateStreamServers) GetUpstreamStreamName() string { + if x != nil { + return x.UpstreamStreamName + } + return "" +} + +func (x *UpdateStreamServers) GetServers() []*structpb.Struct { + if x != nil { + return x.Servers + } + return nil +} + +// Get Upstreams for an instance +type GetUpstreams struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUpstreams) Reset() { + *x = GetUpstreams{} + mi := &file_mpi_v1_command_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUpstreams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUpstreams) ProtoMessage() {} + +func (x *GetUpstreams) ProtoReflect() protoreflect.Message { + mi := &file_mpi_v1_command_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUpstreams.ProtoReflect.Descriptor instead. +func (*GetUpstreams) Descriptor() ([]byte, []int) { + return file_mpi_v1_command_proto_rawDescGZIP(), []int{22} +} + +// Get Stream Upstream Servers for an instance +type GetStreamUpstreams struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetStreamUpstreams) Reset() { + *x = GetStreamUpstreams{} + mi := &file_mpi_v1_command_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetStreamUpstreams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStreamUpstreams) ProtoMessage() {} + +func (x *GetStreamUpstreams) ProtoReflect() protoreflect.Message { + mi := &file_mpi_v1_command_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStreamUpstreams.ProtoReflect.Descriptor instead. +func (*GetStreamUpstreams) Descriptor() ([]byte, []int) { + return file_mpi_v1_command_proto_rawDescGZIP(), []int{23} +} + // Request an update on a particular command type CommandStatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1476,7 +1653,7 @@ type CommandStatusRequest struct { func (x *CommandStatusRequest) Reset() { *x = CommandStatusRequest{} - mi := &file_mpi_v1_command_proto_msgTypes[21] + mi := &file_mpi_v1_command_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1488,7 +1665,7 @@ func (x *CommandStatusRequest) String() string { func (*CommandStatusRequest) ProtoMessage() {} func (x *CommandStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[21] + mi := &file_mpi_v1_command_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1501,7 +1678,7 @@ func (x *CommandStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CommandStatusRequest.ProtoReflect.Descriptor instead. func (*CommandStatusRequest) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{21} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{24} } // This represents an instance being reported on @@ -1519,7 +1696,7 @@ type Instance struct { func (x *Instance) Reset() { *x = Instance{} - mi := &file_mpi_v1_command_proto_msgTypes[22] + mi := &file_mpi_v1_command_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1531,7 +1708,7 @@ func (x *Instance) String() string { func (*Instance) ProtoMessage() {} func (x *Instance) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[22] + mi := &file_mpi_v1_command_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1544,7 +1721,7 @@ func (x *Instance) ProtoReflect() protoreflect.Message { // Deprecated: Use Instance.ProtoReflect.Descriptor instead. func (*Instance) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{22} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{25} } func (x *Instance) GetInstanceMeta() *InstanceMeta { @@ -1583,7 +1760,7 @@ type InstanceMeta struct { func (x *InstanceMeta) Reset() { *x = InstanceMeta{} - mi := &file_mpi_v1_command_proto_msgTypes[23] + mi := &file_mpi_v1_command_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1595,7 +1772,7 @@ func (x *InstanceMeta) String() string { func (*InstanceMeta) ProtoMessage() {} func (x *InstanceMeta) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[23] + mi := &file_mpi_v1_command_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1608,7 +1785,7 @@ func (x *InstanceMeta) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceMeta.ProtoReflect.Descriptor instead. func (*InstanceMeta) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{23} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{26} } func (x *InstanceMeta) GetInstanceId() string { @@ -1647,7 +1824,7 @@ type InstanceConfig struct { func (x *InstanceConfig) Reset() { *x = InstanceConfig{} - mi := &file_mpi_v1_command_proto_msgTypes[24] + mi := &file_mpi_v1_command_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1659,7 +1836,7 @@ func (x *InstanceConfig) String() string { func (*InstanceConfig) ProtoMessage() {} func (x *InstanceConfig) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[24] + mi := &file_mpi_v1_command_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1672,7 +1849,7 @@ func (x *InstanceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceConfig.ProtoReflect.Descriptor instead. func (*InstanceConfig) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{24} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{27} } func (x *InstanceConfig) GetActions() []*InstanceAction { @@ -1732,7 +1909,7 @@ type InstanceRuntime struct { func (x *InstanceRuntime) Reset() { *x = InstanceRuntime{} - mi := &file_mpi_v1_command_proto_msgTypes[25] + mi := &file_mpi_v1_command_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1744,7 +1921,7 @@ func (x *InstanceRuntime) String() string { func (*InstanceRuntime) ProtoMessage() {} func (x *InstanceRuntime) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[25] + mi := &file_mpi_v1_command_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1757,7 +1934,7 @@ func (x *InstanceRuntime) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceRuntime.ProtoReflect.Descriptor instead. func (*InstanceRuntime) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{25} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{28} } func (x *InstanceRuntime) GetProcessId() int32 { @@ -1841,7 +2018,7 @@ type InstanceChild struct { func (x *InstanceChild) Reset() { *x = InstanceChild{} - mi := &file_mpi_v1_command_proto_msgTypes[26] + mi := &file_mpi_v1_command_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1853,7 +2030,7 @@ func (x *InstanceChild) String() string { func (*InstanceChild) ProtoMessage() {} func (x *InstanceChild) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[26] + mi := &file_mpi_v1_command_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1866,7 +2043,7 @@ func (x *InstanceChild) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceChild.ProtoReflect.Descriptor instead. func (*InstanceChild) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{26} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{29} } func (x *InstanceChild) GetProcessId() int32 { @@ -1895,7 +2072,7 @@ type NGINXRuntimeInfo struct { func (x *NGINXRuntimeInfo) Reset() { *x = NGINXRuntimeInfo{} - mi := &file_mpi_v1_command_proto_msgTypes[27] + mi := &file_mpi_v1_command_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1907,7 +2084,7 @@ func (x *NGINXRuntimeInfo) String() string { func (*NGINXRuntimeInfo) ProtoMessage() {} func (x *NGINXRuntimeInfo) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[27] + mi := &file_mpi_v1_command_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1920,7 +2097,7 @@ func (x *NGINXRuntimeInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use NGINXRuntimeInfo.ProtoReflect.Descriptor instead. func (*NGINXRuntimeInfo) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{27} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{30} } func (x *NGINXRuntimeInfo) GetStubStatus() *APIDetails { @@ -1979,7 +2156,7 @@ type NGINXPlusRuntimeInfo struct { func (x *NGINXPlusRuntimeInfo) Reset() { *x = NGINXPlusRuntimeInfo{} - mi := &file_mpi_v1_command_proto_msgTypes[28] + mi := &file_mpi_v1_command_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1991,7 +2168,7 @@ func (x *NGINXPlusRuntimeInfo) String() string { func (*NGINXPlusRuntimeInfo) ProtoMessage() {} func (x *NGINXPlusRuntimeInfo) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[28] + mi := &file_mpi_v1_command_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2004,7 +2181,7 @@ func (x *NGINXPlusRuntimeInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use NGINXPlusRuntimeInfo.ProtoReflect.Descriptor instead. func (*NGINXPlusRuntimeInfo) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{28} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{31} } func (x *NGINXPlusRuntimeInfo) GetStubStatus() *APIDetails { @@ -2061,7 +2238,7 @@ type APIDetails struct { func (x *APIDetails) Reset() { *x = APIDetails{} - mi := &file_mpi_v1_command_proto_msgTypes[29] + mi := &file_mpi_v1_command_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2073,7 +2250,7 @@ func (x *APIDetails) String() string { func (*APIDetails) ProtoMessage() {} func (x *APIDetails) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[29] + mi := &file_mpi_v1_command_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2086,7 +2263,7 @@ func (x *APIDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use APIDetails.ProtoReflect.Descriptor instead. func (*APIDetails) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{29} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{32} } func (x *APIDetails) GetLocation() string { @@ -2112,7 +2289,7 @@ type InstanceAction struct { func (x *InstanceAction) Reset() { *x = InstanceAction{} - mi := &file_mpi_v1_command_proto_msgTypes[30] + mi := &file_mpi_v1_command_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2124,7 +2301,7 @@ func (x *InstanceAction) String() string { func (*InstanceAction) ProtoMessage() {} func (x *InstanceAction) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[30] + mi := &file_mpi_v1_command_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2137,7 +2314,7 @@ func (x *InstanceAction) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceAction.ProtoReflect.Descriptor instead. func (*InstanceAction) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{30} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{33} } // This contains a series of NGINX Agent configurations @@ -2161,7 +2338,7 @@ type AgentConfig struct { func (x *AgentConfig) Reset() { *x = AgentConfig{} - mi := &file_mpi_v1_command_proto_msgTypes[31] + mi := &file_mpi_v1_command_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2173,7 +2350,7 @@ func (x *AgentConfig) String() string { func (*AgentConfig) ProtoMessage() {} func (x *AgentConfig) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[31] + mi := &file_mpi_v1_command_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2186,7 +2363,7 @@ func (x *AgentConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentConfig.ProtoReflect.Descriptor instead. func (*AgentConfig) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{31} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{34} } func (x *AgentConfig) GetCommand() *CommandServer { @@ -2246,7 +2423,7 @@ type CommandServer struct { func (x *CommandServer) Reset() { *x = CommandServer{} - mi := &file_mpi_v1_command_proto_msgTypes[32] + mi := &file_mpi_v1_command_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2258,7 +2435,7 @@ func (x *CommandServer) String() string { func (*CommandServer) ProtoMessage() {} func (x *CommandServer) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[32] + mi := &file_mpi_v1_command_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2271,7 +2448,7 @@ func (x *CommandServer) ProtoReflect() protoreflect.Message { // Deprecated: Use CommandServer.ProtoReflect.Descriptor instead. func (*CommandServer) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{32} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{35} } func (x *CommandServer) GetServer() *ServerSettings { @@ -2304,7 +2481,7 @@ type MetricsServer struct { func (x *MetricsServer) Reset() { *x = MetricsServer{} - mi := &file_mpi_v1_command_proto_msgTypes[33] + mi := &file_mpi_v1_command_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2316,7 +2493,7 @@ func (x *MetricsServer) String() string { func (*MetricsServer) ProtoMessage() {} func (x *MetricsServer) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[33] + mi := &file_mpi_v1_command_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2329,7 +2506,7 @@ func (x *MetricsServer) ProtoReflect() protoreflect.Message { // Deprecated: Use MetricsServer.ProtoReflect.Descriptor instead. func (*MetricsServer) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{33} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{36} } // The file settings associated with file server for configurations @@ -2341,7 +2518,7 @@ type FileServer struct { func (x *FileServer) Reset() { *x = FileServer{} - mi := &file_mpi_v1_command_proto_msgTypes[34] + mi := &file_mpi_v1_command_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2353,7 +2530,7 @@ func (x *FileServer) String() string { func (*FileServer) ProtoMessage() {} func (x *FileServer) ProtoReflect() protoreflect.Message { - mi := &file_mpi_v1_command_proto_msgTypes[34] + mi := &file_mpi_v1_command_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2366,7 +2543,7 @@ func (x *FileServer) ProtoReflect() protoreflect.Message { // Deprecated: Use FileServer.ProtoReflect.Descriptor instead. func (*FileServer) Descriptor() ([]byte, []int) { - return file_mpi_v1_command_proto_rawDescGZIP(), []int{34} + return file_mpi_v1_command_proto_rawDescGZIP(), []int{37} } var File_mpi_v1_command_proto protoreflect.FileDescriptor @@ -2544,20 +2721,34 @@ var file_mpi_v1_command_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x50, 0x6c, 0x75, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, - 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x01, 0x0a, 0x0f, 0x4e, 0x47, 0x49, + 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xbe, 0x03, 0x0a, 0x0f, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x64, 0x0a, 0x1c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x74, 0x74, 0x70, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x5b, 0x0a, 0x19, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x54, 0x54, 0x50, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x16, 0x67, 0x65, 0x74, 0x48, 0x74, 0x74, 0x70, - 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x42, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, + 0x51, 0x0a, 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x13, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0d, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x48, + 0x00, 0x52, 0x0c, 0x67, 0x65, 0x74, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, + 0x4e, 0x0a, 0x14, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x75, 0x70, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x12, 0x67, 0x65, 0x74, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7c, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, @@ -2571,90 +2762,86 @@ var file_mpi_v1_command_proto_rawDesc = []byte{ 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x68, 0x74, 0x74, 0x70, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x16, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xca, 0x01, 0x0a, 0x08, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, - 0x3f, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x42, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x22, 0xb3, 0x02, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x29, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, - 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x46, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x95, 0x01, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x49, - 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x47, 0x49, - 0x4e, 0x58, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x5f, 0x50, 0x4c, 0x55, 0x53, - 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x10, 0x04, 0x22, 0x86, 0x01, 0x0a, 0x0e, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, - 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x38, 0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x22, 0xf6, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, - 0x72, 0x03, 0x3a, 0x01, 0x2f, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x50, 0x61, 0x74, - 0x68, 0x12, 0x29, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x3a, 0x01, 0x2f, - 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x12, - 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, - 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x48, 0x00, 0x52, 0x10, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x52, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x55, 0x0a, 0x17, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x5f, - 0x70, 0x6c, 0x75, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x14, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x50, 0x6c, - 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x42, 0x0a, - 0x11, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, - 0x65, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x52, - 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, - 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x2e, 0x0a, 0x0d, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x1d, 0x0a, - 0x0a, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x22, 0xdb, 0x01, 0x0a, - 0x10, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x33, 0x0a, 0x0b, 0x73, 0x74, 0x75, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x75, 0x62, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0f, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, - 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x6f, 0x64, - 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x79, 0x6e, 0x61, - 0x6d, 0x69, 0x63, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x8e, 0x02, 0x0a, 0x14, 0x4e, - 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, + 0x7a, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 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, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0x0e, 0x0a, 0x0c, 0x47, + 0x65, 0x74, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x47, + 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x73, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xca, 0x01, 0x0a, 0x08, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x12, 0x3f, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x42, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xb3, 0x02, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x29, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, + 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x49, 0x64, 0x12, 0x46, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6d, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x2e, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x95, 0x01, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, + 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, + 0x13, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, + 0x47, 0x49, 0x4e, 0x58, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, + 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x5f, 0x50, 0x4c, + 0x55, 0x53, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x10, 0x04, 0x22, 0x86, 0x01, 0x0a, + 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x30, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0b, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x08, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xf6, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x61, + 0x72, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, + 0x48, 0x05, 0x72, 0x03, 0x3a, 0x01, 0x2f, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x29, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x3a, + 0x01, 0x2f, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, + 0x0a, 0x12, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x10, 0x6e, 0x67, 0x69, 0x6e, 0x78, 0x52, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x55, 0x0a, 0x17, 0x6e, 0x67, 0x69, 0x6e, + 0x78, 0x5f, 0x70, 0x6c, 0x75, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x14, 0x6e, 0x67, 0x69, 0x6e, 0x78, + 0x50, 0x6c, 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x42, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x72, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, + 0x64, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, + 0x72, 0x65, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x2e, + 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x64, 0x22, 0xdb, + 0x01, 0x0a, 0x10, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x0b, 0x73, 0x74, 0x75, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x73, 0x74, @@ -2667,70 +2854,84 @@ var file_mpi_v1_command_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x08, - 0x70, 0x6c, 0x75, 0x73, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x73, 0x41, 0x70, 0x69, 0x22, 0x40, 0x0a, 0x0a, 0x41, - 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x22, 0x10, 0x0a, - 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x94, 0x02, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 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, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x04, 0x61, 0x75, - 0x74, 0x68, 0x12, 0x25, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x22, 0x0f, 0x0a, 0x0d, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x0c, 0x0a, 0x0a, 0x46, 0x69, - 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0x87, 0x03, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1f, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, - 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x2e, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x8e, 0x02, 0x0a, + 0x14, 0x4e, 0x47, 0x49, 0x4e, 0x58, 0x50, 0x6c, 0x75, 0x73, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x33, 0x0a, 0x0b, 0x73, 0x74, 0x75, 0x62, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, + 0x73, 0x74, 0x75, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x6f, + 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, + 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2d, + 0x0a, 0x08, 0x70, 0x6c, 0x75, 0x73, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x73, 0x41, 0x70, 0x69, 0x22, 0x40, 0x0a, + 0x0a, 0x41, 0x50, 0x49, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x22, + 0x10, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x94, 0x02, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 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, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x75, + 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x04, 0x61, 0x75, + 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x04, + 0x61, 0x75, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4c, 0x53, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x22, 0x0f, 0x0a, 0x0d, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x0c, 0x0a, 0x0a, + 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x32, 0x87, 0x03, 0x0a, 0x0e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, 0x0a, + 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x24, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, + 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, + 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, + 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x24, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, - 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x15, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x24, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x50, - 0x6c, 0x61, 0x6e, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x12, 0x19, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x50, - 0x6c, 0x61, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1e, 0x2e, 0x6d, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x00, 0x28, 0x01, - 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x6d, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x12, 0x19, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1e, + 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x00, + 0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x6d, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2746,7 +2947,7 @@ func file_mpi_v1_command_proto_rawDescGZIP() []byte { } var file_mpi_v1_command_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_mpi_v1_command_proto_msgTypes = make([]protoimpl.MessageInfo, 35) +var file_mpi_v1_command_proto_msgTypes = make([]protoimpl.MessageInfo, 38) var file_mpi_v1_command_proto_goTypes = []any{ (InstanceHealth_InstanceHealthStatus)(0), // 0: mpi.v1.InstanceHealth.InstanceHealthStatus (InstanceMeta_InstanceType)(0), // 1: mpi.v1.InstanceMeta.InstanceType @@ -2771,89 +2972,96 @@ var file_mpi_v1_command_proto_goTypes = []any{ (*NGINXPlusAction)(nil), // 20: mpi.v1.NGINXPlusAction (*UpdateHTTPUpstreamServers)(nil), // 21: mpi.v1.UpdateHTTPUpstreamServers (*GetHTTPUpstreamServers)(nil), // 22: mpi.v1.GetHTTPUpstreamServers - (*CommandStatusRequest)(nil), // 23: mpi.v1.CommandStatusRequest - (*Instance)(nil), // 24: mpi.v1.Instance - (*InstanceMeta)(nil), // 25: mpi.v1.InstanceMeta - (*InstanceConfig)(nil), // 26: mpi.v1.InstanceConfig - (*InstanceRuntime)(nil), // 27: mpi.v1.InstanceRuntime - (*InstanceChild)(nil), // 28: mpi.v1.InstanceChild - (*NGINXRuntimeInfo)(nil), // 29: mpi.v1.NGINXRuntimeInfo - (*NGINXPlusRuntimeInfo)(nil), // 30: mpi.v1.NGINXPlusRuntimeInfo - (*APIDetails)(nil), // 31: mpi.v1.APIDetails - (*InstanceAction)(nil), // 32: mpi.v1.InstanceAction - (*AgentConfig)(nil), // 33: mpi.v1.AgentConfig - (*CommandServer)(nil), // 34: mpi.v1.CommandServer - (*MetricsServer)(nil), // 35: mpi.v1.MetricsServer - (*FileServer)(nil), // 36: mpi.v1.FileServer - (*MessageMeta)(nil), // 37: mpi.v1.MessageMeta - (*CommandResponse)(nil), // 38: mpi.v1.CommandResponse - (*FileOverview)(nil), // 39: mpi.v1.FileOverview - (*structpb.Struct)(nil), // 40: google.protobuf.Struct - (*ServerSettings)(nil), // 41: mpi.v1.ServerSettings - (*AuthSettings)(nil), // 42: mpi.v1.AuthSettings - (*TLSSettings)(nil), // 43: mpi.v1.TLSSettings + (*UpdateStreamServers)(nil), // 23: mpi.v1.UpdateStreamServers + (*GetUpstreams)(nil), // 24: mpi.v1.GetUpstreams + (*GetStreamUpstreams)(nil), // 25: mpi.v1.GetStreamUpstreams + (*CommandStatusRequest)(nil), // 26: mpi.v1.CommandStatusRequest + (*Instance)(nil), // 27: mpi.v1.Instance + (*InstanceMeta)(nil), // 28: mpi.v1.InstanceMeta + (*InstanceConfig)(nil), // 29: mpi.v1.InstanceConfig + (*InstanceRuntime)(nil), // 30: mpi.v1.InstanceRuntime + (*InstanceChild)(nil), // 31: mpi.v1.InstanceChild + (*NGINXRuntimeInfo)(nil), // 32: mpi.v1.NGINXRuntimeInfo + (*NGINXPlusRuntimeInfo)(nil), // 33: mpi.v1.NGINXPlusRuntimeInfo + (*APIDetails)(nil), // 34: mpi.v1.APIDetails + (*InstanceAction)(nil), // 35: mpi.v1.InstanceAction + (*AgentConfig)(nil), // 36: mpi.v1.AgentConfig + (*CommandServer)(nil), // 37: mpi.v1.CommandServer + (*MetricsServer)(nil), // 38: mpi.v1.MetricsServer + (*FileServer)(nil), // 39: mpi.v1.FileServer + (*MessageMeta)(nil), // 40: mpi.v1.MessageMeta + (*CommandResponse)(nil), // 41: mpi.v1.CommandResponse + (*FileOverview)(nil), // 42: mpi.v1.FileOverview + (*structpb.Struct)(nil), // 43: google.protobuf.Struct + (*ServerSettings)(nil), // 44: mpi.v1.ServerSettings + (*AuthSettings)(nil), // 45: mpi.v1.AuthSettings + (*TLSSettings)(nil), // 46: mpi.v1.TLSSettings } var file_mpi_v1_command_proto_depIdxs = []int32{ - 37, // 0: mpi.v1.CreateConnectionRequest.message_meta:type_name -> mpi.v1.MessageMeta + 40, // 0: mpi.v1.CreateConnectionRequest.message_meta:type_name -> mpi.v1.MessageMeta 3, // 1: mpi.v1.CreateConnectionRequest.resource:type_name -> mpi.v1.Resource - 24, // 2: mpi.v1.Resource.instances:type_name -> mpi.v1.Instance + 27, // 2: mpi.v1.Resource.instances:type_name -> mpi.v1.Instance 4, // 3: mpi.v1.Resource.host_info:type_name -> mpi.v1.HostInfo 6, // 4: mpi.v1.Resource.container_info:type_name -> mpi.v1.ContainerInfo 5, // 5: mpi.v1.HostInfo.release_info:type_name -> mpi.v1.ReleaseInfo - 38, // 6: mpi.v1.CreateConnectionResponse.response:type_name -> mpi.v1.CommandResponse - 33, // 7: mpi.v1.CreateConnectionResponse.agent_config:type_name -> mpi.v1.AgentConfig - 37, // 8: mpi.v1.UpdateDataPlaneStatusRequest.message_meta:type_name -> mpi.v1.MessageMeta + 41, // 6: mpi.v1.CreateConnectionResponse.response:type_name -> mpi.v1.CommandResponse + 36, // 7: mpi.v1.CreateConnectionResponse.agent_config:type_name -> mpi.v1.AgentConfig + 40, // 8: mpi.v1.UpdateDataPlaneStatusRequest.message_meta:type_name -> mpi.v1.MessageMeta 3, // 9: mpi.v1.UpdateDataPlaneStatusRequest.resource:type_name -> mpi.v1.Resource 0, // 10: mpi.v1.InstanceHealth.instance_health_status:type_name -> mpi.v1.InstanceHealth.InstanceHealthStatus - 37, // 11: mpi.v1.UpdateDataPlaneHealthRequest.message_meta:type_name -> mpi.v1.MessageMeta + 40, // 11: mpi.v1.UpdateDataPlaneHealthRequest.message_meta:type_name -> mpi.v1.MessageMeta 10, // 12: mpi.v1.UpdateDataPlaneHealthRequest.instance_healths:type_name -> mpi.v1.InstanceHealth - 37, // 13: mpi.v1.DataPlaneResponse.message_meta:type_name -> mpi.v1.MessageMeta - 38, // 14: mpi.v1.DataPlaneResponse.command_response:type_name -> mpi.v1.CommandResponse - 37, // 15: mpi.v1.ManagementPlaneRequest.message_meta:type_name -> mpi.v1.MessageMeta + 40, // 13: mpi.v1.DataPlaneResponse.message_meta:type_name -> mpi.v1.MessageMeta + 41, // 14: mpi.v1.DataPlaneResponse.command_response:type_name -> mpi.v1.CommandResponse + 40, // 15: mpi.v1.ManagementPlaneRequest.message_meta:type_name -> mpi.v1.MessageMeta 15, // 16: mpi.v1.ManagementPlaneRequest.status_request:type_name -> mpi.v1.StatusRequest 16, // 17: mpi.v1.ManagementPlaneRequest.health_request:type_name -> mpi.v1.HealthRequest 17, // 18: mpi.v1.ManagementPlaneRequest.config_apply_request:type_name -> mpi.v1.ConfigApplyRequest 18, // 19: mpi.v1.ManagementPlaneRequest.config_upload_request:type_name -> mpi.v1.ConfigUploadRequest 19, // 20: mpi.v1.ManagementPlaneRequest.action_request:type_name -> mpi.v1.APIActionRequest - 23, // 21: mpi.v1.ManagementPlaneRequest.command_status_request:type_name -> mpi.v1.CommandStatusRequest - 39, // 22: mpi.v1.ConfigApplyRequest.overview:type_name -> mpi.v1.FileOverview - 39, // 23: mpi.v1.ConfigUploadRequest.overview:type_name -> mpi.v1.FileOverview + 26, // 21: mpi.v1.ManagementPlaneRequest.command_status_request:type_name -> mpi.v1.CommandStatusRequest + 42, // 22: mpi.v1.ConfigApplyRequest.overview:type_name -> mpi.v1.FileOverview + 42, // 23: mpi.v1.ConfigUploadRequest.overview:type_name -> mpi.v1.FileOverview 20, // 24: mpi.v1.APIActionRequest.nginx_plus_action:type_name -> mpi.v1.NGINXPlusAction 21, // 25: mpi.v1.NGINXPlusAction.update_http_upstream_servers:type_name -> mpi.v1.UpdateHTTPUpstreamServers 22, // 26: mpi.v1.NGINXPlusAction.get_http_upstream_servers:type_name -> mpi.v1.GetHTTPUpstreamServers - 40, // 27: mpi.v1.UpdateHTTPUpstreamServers.servers:type_name -> google.protobuf.Struct - 25, // 28: mpi.v1.Instance.instance_meta:type_name -> mpi.v1.InstanceMeta - 26, // 29: mpi.v1.Instance.instance_config:type_name -> mpi.v1.InstanceConfig - 27, // 30: mpi.v1.Instance.instance_runtime:type_name -> mpi.v1.InstanceRuntime - 1, // 31: mpi.v1.InstanceMeta.instance_type:type_name -> mpi.v1.InstanceMeta.InstanceType - 32, // 32: mpi.v1.InstanceConfig.actions:type_name -> mpi.v1.InstanceAction - 33, // 33: mpi.v1.InstanceConfig.agent_config:type_name -> mpi.v1.AgentConfig - 29, // 34: mpi.v1.InstanceRuntime.nginx_runtime_info:type_name -> mpi.v1.NGINXRuntimeInfo - 30, // 35: mpi.v1.InstanceRuntime.nginx_plus_runtime_info:type_name -> mpi.v1.NGINXPlusRuntimeInfo - 28, // 36: mpi.v1.InstanceRuntime.instance_children:type_name -> mpi.v1.InstanceChild - 31, // 37: mpi.v1.NGINXRuntimeInfo.stub_status:type_name -> mpi.v1.APIDetails - 31, // 38: mpi.v1.NGINXPlusRuntimeInfo.stub_status:type_name -> mpi.v1.APIDetails - 31, // 39: mpi.v1.NGINXPlusRuntimeInfo.plus_api:type_name -> mpi.v1.APIDetails - 34, // 40: mpi.v1.AgentConfig.command:type_name -> mpi.v1.CommandServer - 35, // 41: mpi.v1.AgentConfig.metrics:type_name -> mpi.v1.MetricsServer - 36, // 42: mpi.v1.AgentConfig.file:type_name -> mpi.v1.FileServer - 40, // 43: mpi.v1.AgentConfig.labels:type_name -> google.protobuf.Struct - 41, // 44: mpi.v1.CommandServer.server:type_name -> mpi.v1.ServerSettings - 42, // 45: mpi.v1.CommandServer.auth:type_name -> mpi.v1.AuthSettings - 43, // 46: mpi.v1.CommandServer.tls:type_name -> mpi.v1.TLSSettings - 2, // 47: mpi.v1.CommandService.CreateConnection:input_type -> mpi.v1.CreateConnectionRequest - 8, // 48: mpi.v1.CommandService.UpdateDataPlaneStatus:input_type -> mpi.v1.UpdateDataPlaneStatusRequest - 11, // 49: mpi.v1.CommandService.UpdateDataPlaneHealth:input_type -> mpi.v1.UpdateDataPlaneHealthRequest - 13, // 50: mpi.v1.CommandService.Subscribe:input_type -> mpi.v1.DataPlaneResponse - 7, // 51: mpi.v1.CommandService.CreateConnection:output_type -> mpi.v1.CreateConnectionResponse - 9, // 52: mpi.v1.CommandService.UpdateDataPlaneStatus:output_type -> mpi.v1.UpdateDataPlaneStatusResponse - 12, // 53: mpi.v1.CommandService.UpdateDataPlaneHealth:output_type -> mpi.v1.UpdateDataPlaneHealthResponse - 14, // 54: mpi.v1.CommandService.Subscribe:output_type -> mpi.v1.ManagementPlaneRequest - 51, // [51:55] is the sub-list for method output_type - 47, // [47:51] is the sub-list for method input_type - 47, // [47:47] is the sub-list for extension type_name - 47, // [47:47] is the sub-list for extension extendee - 0, // [0:47] is the sub-list for field type_name + 23, // 27: mpi.v1.NGINXPlusAction.update_stream_servers:type_name -> mpi.v1.UpdateStreamServers + 24, // 28: mpi.v1.NGINXPlusAction.get_upstreams:type_name -> mpi.v1.GetUpstreams + 25, // 29: mpi.v1.NGINXPlusAction.get_stream_upstreams:type_name -> mpi.v1.GetStreamUpstreams + 43, // 30: mpi.v1.UpdateHTTPUpstreamServers.servers:type_name -> google.protobuf.Struct + 43, // 31: mpi.v1.UpdateStreamServers.servers:type_name -> google.protobuf.Struct + 28, // 32: mpi.v1.Instance.instance_meta:type_name -> mpi.v1.InstanceMeta + 29, // 33: mpi.v1.Instance.instance_config:type_name -> mpi.v1.InstanceConfig + 30, // 34: mpi.v1.Instance.instance_runtime:type_name -> mpi.v1.InstanceRuntime + 1, // 35: mpi.v1.InstanceMeta.instance_type:type_name -> mpi.v1.InstanceMeta.InstanceType + 35, // 36: mpi.v1.InstanceConfig.actions:type_name -> mpi.v1.InstanceAction + 36, // 37: mpi.v1.InstanceConfig.agent_config:type_name -> mpi.v1.AgentConfig + 32, // 38: mpi.v1.InstanceRuntime.nginx_runtime_info:type_name -> mpi.v1.NGINXRuntimeInfo + 33, // 39: mpi.v1.InstanceRuntime.nginx_plus_runtime_info:type_name -> mpi.v1.NGINXPlusRuntimeInfo + 31, // 40: mpi.v1.InstanceRuntime.instance_children:type_name -> mpi.v1.InstanceChild + 34, // 41: mpi.v1.NGINXRuntimeInfo.stub_status:type_name -> mpi.v1.APIDetails + 34, // 42: mpi.v1.NGINXPlusRuntimeInfo.stub_status:type_name -> mpi.v1.APIDetails + 34, // 43: mpi.v1.NGINXPlusRuntimeInfo.plus_api:type_name -> mpi.v1.APIDetails + 37, // 44: mpi.v1.AgentConfig.command:type_name -> mpi.v1.CommandServer + 38, // 45: mpi.v1.AgentConfig.metrics:type_name -> mpi.v1.MetricsServer + 39, // 46: mpi.v1.AgentConfig.file:type_name -> mpi.v1.FileServer + 43, // 47: mpi.v1.AgentConfig.labels:type_name -> google.protobuf.Struct + 44, // 48: mpi.v1.CommandServer.server:type_name -> mpi.v1.ServerSettings + 45, // 49: mpi.v1.CommandServer.auth:type_name -> mpi.v1.AuthSettings + 46, // 50: mpi.v1.CommandServer.tls:type_name -> mpi.v1.TLSSettings + 2, // 51: mpi.v1.CommandService.CreateConnection:input_type -> mpi.v1.CreateConnectionRequest + 8, // 52: mpi.v1.CommandService.UpdateDataPlaneStatus:input_type -> mpi.v1.UpdateDataPlaneStatusRequest + 11, // 53: mpi.v1.CommandService.UpdateDataPlaneHealth:input_type -> mpi.v1.UpdateDataPlaneHealthRequest + 13, // 54: mpi.v1.CommandService.Subscribe:input_type -> mpi.v1.DataPlaneResponse + 7, // 55: mpi.v1.CommandService.CreateConnection:output_type -> mpi.v1.CreateConnectionResponse + 9, // 56: mpi.v1.CommandService.UpdateDataPlaneStatus:output_type -> mpi.v1.UpdateDataPlaneStatusResponse + 12, // 57: mpi.v1.CommandService.UpdateDataPlaneHealth:output_type -> mpi.v1.UpdateDataPlaneHealthResponse + 14, // 58: mpi.v1.CommandService.Subscribe:output_type -> mpi.v1.ManagementPlaneRequest + 55, // [55:59] is the sub-list for method output_type + 51, // [51:55] is the sub-list for method input_type + 51, // [51:51] is the sub-list for extension type_name + 51, // [51:51] is the sub-list for extension extendee + 0, // [0:51] is the sub-list for field type_name } func init() { file_mpi_v1_command_proto_init() } @@ -2881,11 +3089,14 @@ func file_mpi_v1_command_proto_init() { file_mpi_v1_command_proto_msgTypes[18].OneofWrappers = []any{ (*NGINXPlusAction_UpdateHttpUpstreamServers)(nil), (*NGINXPlusAction_GetHttpUpstreamServers)(nil), + (*NGINXPlusAction_UpdateStreamServers)(nil), + (*NGINXPlusAction_GetUpstreams)(nil), + (*NGINXPlusAction_GetStreamUpstreams)(nil), } - file_mpi_v1_command_proto_msgTypes[24].OneofWrappers = []any{ + file_mpi_v1_command_proto_msgTypes[27].OneofWrappers = []any{ (*InstanceConfig_AgentConfig)(nil), } - file_mpi_v1_command_proto_msgTypes[25].OneofWrappers = []any{ + file_mpi_v1_command_proto_msgTypes[28].OneofWrappers = []any{ (*InstanceRuntime_NginxRuntimeInfo)(nil), (*InstanceRuntime_NginxPlusRuntimeInfo)(nil), } @@ -2895,7 +3106,7 @@ func file_mpi_v1_command_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_mpi_v1_command_proto_rawDesc, NumEnums: 2, - NumMessages: 35, + NumMessages: 38, NumExtensions: 0, NumServices: 1, }, diff --git a/api/grpc/mpi/v1/command.pb.validate.go b/api/grpc/mpi/v1/command.pb.validate.go index 82fe9c2d3..22c1ca542 100644 --- a/api/grpc/mpi/v1/command.pb.validate.go +++ b/api/grpc/mpi/v1/command.pb.validate.go @@ -2820,6 +2820,129 @@ func (m *NGINXPlusAction) validate(all bool) error { } } + case *NGINXPlusAction_UpdateStreamServers: + if v == nil { + err := NGINXPlusActionValidationError{ + field: "Action", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetUpdateStreamServers()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "UpdateStreamServers", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "UpdateStreamServers", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetUpdateStreamServers()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NGINXPlusActionValidationError{ + field: "UpdateStreamServers", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *NGINXPlusAction_GetUpstreams: + if v == nil { + err := NGINXPlusActionValidationError{ + field: "Action", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetGetUpstreams()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "GetUpstreams", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "GetUpstreams", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetGetUpstreams()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NGINXPlusActionValidationError{ + field: "GetUpstreams", + reason: "embedded message failed validation", + cause: err, + } + } + } + + case *NGINXPlusAction_GetStreamUpstreams: + if v == nil { + err := NGINXPlusActionValidationError{ + field: "Action", + reason: "oneof value cannot be a typed-nil", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetGetStreamUpstreams()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "GetStreamUpstreams", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NGINXPlusActionValidationError{ + field: "GetStreamUpstreams", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetGetStreamUpstreams()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NGINXPlusActionValidationError{ + field: "GetStreamUpstreams", + reason: "embedded message failed validation", + cause: err, + } + } + } + default: _ = v // ensures v is used } @@ -3144,6 +3267,345 @@ var _ interface { ErrorName() string } = GetHTTPUpstreamServersValidationError{} +// Validate checks the field values on UpdateStreamServers with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *UpdateStreamServers) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on UpdateStreamServers with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// UpdateStreamServersMultiError, or nil if none found. +func (m *UpdateStreamServers) ValidateAll() error { + return m.validate(true) +} + +func (m *UpdateStreamServers) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for UpstreamStreamName + + for idx, item := range m.GetServers() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, UpdateStreamServersValidationError{ + field: fmt.Sprintf("Servers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, UpdateStreamServersValidationError{ + field: fmt.Sprintf("Servers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return UpdateStreamServersValidationError{ + field: fmt.Sprintf("Servers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return UpdateStreamServersMultiError(errors) + } + + return nil +} + +// UpdateStreamServersMultiError is an error wrapping multiple validation +// errors returned by UpdateStreamServers.ValidateAll() if the designated +// constraints aren't met. +type UpdateStreamServersMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m UpdateStreamServersMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m UpdateStreamServersMultiError) AllErrors() []error { return m } + +// UpdateStreamServersValidationError is the validation error returned by +// UpdateStreamServers.Validate if the designated constraints aren't met. +type UpdateStreamServersValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e UpdateStreamServersValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e UpdateStreamServersValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e UpdateStreamServersValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e UpdateStreamServersValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e UpdateStreamServersValidationError) ErrorName() string { + return "UpdateStreamServersValidationError" +} + +// Error satisfies the builtin error interface +func (e UpdateStreamServersValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sUpdateStreamServers.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = UpdateStreamServersValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = UpdateStreamServersValidationError{} + +// Validate checks the field values on GetUpstreams with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *GetUpstreams) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetUpstreams with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in GetUpstreamsMultiError, or +// nil if none found. +func (m *GetUpstreams) ValidateAll() error { + return m.validate(true) +} + +func (m *GetUpstreams) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return GetUpstreamsMultiError(errors) + } + + return nil +} + +// GetUpstreamsMultiError is an error wrapping multiple validation errors +// returned by GetUpstreams.ValidateAll() if the designated constraints aren't met. +type GetUpstreamsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetUpstreamsMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetUpstreamsMultiError) AllErrors() []error { return m } + +// GetUpstreamsValidationError is the validation error returned by +// GetUpstreams.Validate if the designated constraints aren't met. +type GetUpstreamsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetUpstreamsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetUpstreamsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetUpstreamsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetUpstreamsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetUpstreamsValidationError) ErrorName() string { return "GetUpstreamsValidationError" } + +// Error satisfies the builtin error interface +func (e GetUpstreamsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetUpstreams.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetUpstreamsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetUpstreamsValidationError{} + +// Validate checks the field values on GetStreamUpstreams with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetStreamUpstreams) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetStreamUpstreams with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GetStreamUpstreamsMultiError, or nil if none found. +func (m *GetStreamUpstreams) ValidateAll() error { + return m.validate(true) +} + +func (m *GetStreamUpstreams) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return GetStreamUpstreamsMultiError(errors) + } + + return nil +} + +// GetStreamUpstreamsMultiError is an error wrapping multiple validation errors +// returned by GetStreamUpstreams.ValidateAll() if the designated constraints +// aren't met. +type GetStreamUpstreamsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetStreamUpstreamsMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetStreamUpstreamsMultiError) AllErrors() []error { return m } + +// GetStreamUpstreamsValidationError is the validation error returned by +// GetStreamUpstreams.Validate if the designated constraints aren't met. +type GetStreamUpstreamsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetStreamUpstreamsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetStreamUpstreamsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetStreamUpstreamsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetStreamUpstreamsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetStreamUpstreamsValidationError) ErrorName() string { + return "GetStreamUpstreamsValidationError" +} + +// Error satisfies the builtin error interface +func (e GetStreamUpstreamsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetStreamUpstreams.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetStreamUpstreamsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetStreamUpstreamsValidationError{} + // Validate checks the field values on CommandStatusRequest with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. diff --git a/api/grpc/mpi/v1/command.proto b/api/grpc/mpi/v1/command.proto index ef9abc234..462b769ea 100644 --- a/api/grpc/mpi/v1/command.proto +++ b/api/grpc/mpi/v1/command.proto @@ -204,8 +204,11 @@ message APIActionRequest { message NGINXPlusAction { // types of actions possible with NGINX Plus API oneof action { - UpdateHTTPUpstreamServers update_http_upstream_servers = 2; - GetHTTPUpstreamServers get_http_upstream_servers = 3; + UpdateHTTPUpstreamServers update_http_upstream_servers = 1; + GetHTTPUpstreamServers get_http_upstream_servers = 2; + UpdateStreamServers update_stream_servers = 3; + GetUpstreams get_upstreams = 4; + GetStreamUpstreams get_stream_upstreams = 5; } } @@ -223,6 +226,22 @@ message GetHTTPUpstreamServers { string http_upstream_name = 1; } +// Update Upstream Stream Servers for an instance +message UpdateStreamServers { + // the name of the upstream stream + string upstream_stream_name = 1; + // a list of upstream stream servers + repeated google.protobuf.Struct servers = 2; +} + +// Get Upstreams for an instance +message GetUpstreams { +} + +// Get Stream Upstream Servers for an instance +message GetStreamUpstreams { +} + // Request an update on a particular command message CommandStatusRequest {} diff --git a/api/grpc/mpi/v1/files.pb.go b/api/grpc/mpi/v1/files.pb.go index 2cbfb57ec..b0bd43e2c 100644 --- a/api/grpc/mpi/v1/files.pb.go +++ b/api/grpc/mpi/v1/files.pb.go @@ -515,7 +515,9 @@ type File struct { // Meta information about the file, the name (including path) and hash FileMeta *FileMeta `protobuf:"bytes,1,opt,name=file_meta,json=fileMeta,proto3" json:"file_meta,omitempty"` // Optional action - Action *File_FileAction `protobuf:"varint,2,opt,name=action,proto3,enum=mpi.v1.File_FileAction,oneof" json:"action,omitempty"` + Action *File_FileAction `protobuf:"varint,2,opt,name=action,proto3,enum=mpi.v1.File_FileAction,oneof" json:"action,omitempty"` + // Unmanaged files will not be modified + Unmanaged bool `protobuf:"varint,3,opt,name=unmanaged,proto3" json:"unmanaged,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -564,6 +566,13 @@ func (x *File) GetAction() File_FileAction { return File_FILE_ACTION_UNSPECIFIED } +func (x *File) GetUnmanaged() bool { + if x != nil { + return x.Unmanaged + } + return false +} + // Represents the get file request type GetFileRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1388,191 +1397,192 @@ var file_mpi_v1_files_proto_rawDesc = []byte{ 0x3c, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x82, 0x02, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa0, 0x02, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, - 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x22, 0x89, 0x01, 0x0a, 0x0a, - 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, - 0x4c, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x49, 0x4c, 0x45, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x41, 0x44, 0x44, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x49, 0x4c, 0x45, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, - 0x16, 0x0a, 0x12, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x77, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x09, - 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0x43, 0x0a, 0x0f, 0x47, - 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, - 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x2a, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa2, 0x02, 0x0a, - 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x3a, 0x01, - 0x2f, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x49, 0x0a, 0x0d, 0x6d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x42, 0x08, - 0xba, 0x48, 0x05, 0xb2, 0x01, 0x02, 0x38, 0x01, 0x52, 0x0c, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xba, 0x48, 0x0d, - 0x72, 0x0b, 0x32, 0x09, 0x30, 0x5b, 0x30, 0x2d, 0x37, 0x5d, 0x7b, 0x33, 0x7d, 0x52, 0x0b, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, - 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x44, - 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x42, 0x0b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, - 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x0c, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x22, 0x43, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x69, 0x6c, - 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, - 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xf9, 0x02, 0x0a, 0x0f, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x0d, - 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x00, 0x52, 0x0c, 0x73, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x06, 0x69, 0x73, - 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x58, 0x35, 0x30, 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x69, 0x73, - 0x73, 0x75, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x58, - 0x35, 0x30, 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x33, 0x0a, 0x04, 0x73, 0x61, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, - 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, - 0x04, 0x73, 0x61, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x65, 0x73, 0x52, 0x05, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x12, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, - 0x68, 0x6d, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x22, 0x4e, 0x0a, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x74, 0x5f, - 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6e, 0x6f, - 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x41, - 0x66, 0x74, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, - 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, - 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, - 0xaa, 0x04, 0x0a, 0x08, 0x58, 0x35, 0x30, 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0e, 0xba, - 0x48, 0x0b, 0x92, 0x01, 0x08, 0x22, 0x06, 0x72, 0x04, 0x10, 0x02, 0x18, 0x02, 0x52, 0x07, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, - 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, - 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x12, 0x28, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, + 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x09, 0x75, + 0x6e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x75, 0x6e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x0a, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x4c, 0x45, + 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x01, + 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x41, 0x44, 0x44, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x16, 0x0a, + 0x12, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, + 0x45, 0x54, 0x45, 0x10, 0x04, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x77, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0b, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x69, + 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, + 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0x43, 0x0a, 0x0f, 0x47, 0x65, 0x74, + 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2a, + 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa2, 0x02, 0x0a, 0x08, 0x46, + 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x3a, 0x01, 0x2f, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x49, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x42, 0x08, 0xba, 0x48, + 0x05, 0xb2, 0x01, 0x02, 0x38, 0x01, 0x52, 0x0c, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xba, 0x48, 0x0d, 0x72, 0x0b, + 0x32, 0x09, 0x30, 0x5b, 0x30, 0x2d, 0x37, 0x5d, 0x7b, 0x33, 0x7d, 0x52, 0x0b, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x44, 0x0a, 0x10, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, + 0x00, 0x52, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x42, 0x0b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, + 0x9f, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x0c, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x22, 0x43, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xf9, 0x02, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x0d, 0x73, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x00, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x58, 0x35, 0x30, 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, + 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x58, 0x35, 0x30, + 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x33, + 0x0a, 0x04, 0x73, 0x61, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x6c, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x04, 0x73, + 0x61, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x65, 0x73, 0x52, 0x05, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1a, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x12, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x12, 0x30, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x22, 0x4e, 0x0a, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x44, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x74, 0x5f, 0x62, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x42, + 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x41, 0x66, 0x74, + 0x65, 0x72, 0x22, 0x59, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x6c, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x70, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0xaa, 0x04, + 0x0a, 0x08, 0x58, 0x35, 0x30, 0x39, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0e, 0xba, 0x48, 0x0b, + 0x92, 0x01, 0x08, 0x22, 0x06, 0x72, 0x04, 0x10, 0x02, 0x18, 0x02, 0x52, 0x07, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, + 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x0e, 0x73, - 0x74, 0x72, 0x65, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x52, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, + 0x28, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x0e, 0x73, 0x74, 0x72, + 0x65, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0d, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, + 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x0d, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x2d, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x12, - 0x2c, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x00, 0x52, - 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x28, 0x0a, - 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x0b, - 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x53, 0x0a, 0x15, - 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2a, 0x8a, 0x03, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, - 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x49, 0x47, 0x4e, - 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x44, 0x32, - 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4d, - 0x44, 0x35, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x02, 0x12, 0x11, 0x0a, - 0x0d, 0x53, 0x48, 0x41, 0x31, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x03, - 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, - 0x52, 0x53, 0x41, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x5f, - 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x48, - 0x41, 0x35, 0x31, 0x32, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x06, 0x12, - 0x11, 0x0a, 0x0d, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x31, - 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, - 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x08, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x43, 0x44, 0x53, 0x41, - 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x31, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, - 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, - 0x36, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, - 0x48, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x0b, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x43, - 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, - 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x5f, 0x57, 0x49, 0x54, 0x48, - 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x0d, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, - 0x41, 0x33, 0x38, 0x34, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, - 0x53, 0x10, 0x0e, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x5f, 0x57, 0x49, - 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x0f, 0x12, 0x10, 0x0a, 0x0c, - 0x50, 0x55, 0x52, 0x45, 0x5f, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x10, 0x10, 0x32, 0xaf, - 0x02, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, - 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x1a, 0x2e, - 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, - 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x1d, 0x2e, 0x6d, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, - 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, - 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0a, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x08, 0x5a, 0x06, 0x6d, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x01, 0x52, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, + 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x00, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0b, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x0b, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, + 0x65, 0x78, 0x74, 0x72, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x53, 0x0a, 0x15, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, + 0x8a, 0x03, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x49, 0x47, 0x4e, 0x41, 0x54, + 0x55, 0x52, 0x45, 0x5f, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x44, 0x32, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x44, 0x35, + 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, + 0x48, 0x41, 0x31, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x03, 0x12, 0x13, + 0x0a, 0x0f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, + 0x41, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x5f, 0x57, 0x49, + 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x48, 0x41, 0x35, + 0x31, 0x32, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x10, 0x06, 0x12, 0x11, 0x0a, + 0x0d, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x31, 0x10, 0x07, + 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, + 0x32, 0x35, 0x36, 0x10, 0x08, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x31, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x43, + 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, + 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, + 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x0b, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x43, 0x44, 0x53, + 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x0c, 0x12, + 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, + 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x0d, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x33, + 0x38, 0x34, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, + 0x0e, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x5f, 0x57, 0x49, 0x54, 0x48, + 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x0f, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x55, + 0x52, 0x45, 0x5f, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x10, 0x10, 0x32, 0xaf, 0x02, 0x0a, + 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x1a, 0x2e, 0x6d, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x1d, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, 0x65, 0x74, + 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6d, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x6d, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, + 0x5a, 0x06, 0x6d, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/grpc/mpi/v1/files.pb.validate.go b/api/grpc/mpi/v1/files.pb.validate.go index a912068e9..e5d0d937c 100644 --- a/api/grpc/mpi/v1/files.pb.validate.go +++ b/api/grpc/mpi/v1/files.pb.validate.go @@ -933,6 +933,8 @@ func (m *File) validate(all bool) error { } } + // no validation rules for Unmanaged + if m.Action != nil { // no validation rules for Action } diff --git a/api/grpc/mpi/v1/files.proto b/api/grpc/mpi/v1/files.proto index 86ab36f00..3bef31e82 100644 --- a/api/grpc/mpi/v1/files.proto +++ b/api/grpc/mpi/v1/files.proto @@ -92,6 +92,8 @@ message File { } // Optional action optional FileAction action = 2; + // Unmanaged files will not be modified + bool unmanaged = 3; } // Represents the get file request @@ -290,4 +292,4 @@ message AttributeTypeAndValue { // The value associated with the attribute. string value = 2 [(buf.validate.field).string.min_len = 1]; -} \ No newline at end of file +} diff --git a/api/grpc/mpi/v1/helpers.go b/api/grpc/mpi/v1/helpers.go new file mode 100644 index 000000000..02a5adb83 --- /dev/null +++ b/api/grpc/mpi/v1/helpers.go @@ -0,0 +1,47 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package v1 + +import ( + "google.golang.org/protobuf/types/known/structpb" +) + +// ConvertToStructs converts a map[string]any into a slice of *structpb.Struct. +// Each key-value pair in the input map is converted into a *structpb.Struct, +// where the key is used as the field name, and the value is added to the Struct. +// +// Parameters: +// - input: A map[string]any containing key-value pairs to be converted. +// +// Returns: +// - []*structpb.Struct: A slice of *structpb.Struct, where each map entry is converted into a struct. +// - error: An error if any value in the input map cannot be converted into a *structpb.Struct. +// +// Example: +// +// input := map[string]any{ +// "key1": "value1", +// "key2": 123, +// "key3": true, +// } +// structs, err := ConvertToStructs(input) +// // structs will contain a slice of *structpb.Struct +// // err will be nil if all conversions succeed. +func ConvertToStructs(input map[string]any) ([]*structpb.Struct, error) { + structs := []*structpb.Struct{} + for key, value := range input { + // Convert each value in the map to *structpb.Struct + structValue, err := structpb.NewStruct(map[string]any{ + key: value, + }) + if err != nil { + return structs, err + } + structs = append(structs, structValue) + } + + return structs, nil +} diff --git a/api/grpc/mpi/v1/helpers_test.go b/api/grpc/mpi/v1/helpers_test.go new file mode 100644 index 000000000..62cfb0a90 --- /dev/null +++ b/api/grpc/mpi/v1/helpers_test.go @@ -0,0 +1,72 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package v1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/structpb" +) + +func TestConvertToStructs(t *testing.T) { + tests := []struct { + name string + input map[string]any + expected []*structpb.Struct + wantErr bool + }{ + { + name: "Test 1: Valid input with simple key-value pairs", + input: map[string]any{ + "key1": "value1", + "key2": 123, + "key3": true, + }, + expected: []*structpb.Struct{ + { + Fields: map[string]*structpb.Value{ + "key1": structpb.NewStringValue("value1"), + }, + }, + { + Fields: map[string]*structpb.Value{ + "key2": structpb.NewNumberValue(123), + }, + }, + { + Fields: map[string]*structpb.Value{ + "key3": structpb.NewBoolValue(true), + }, + }, + }, + wantErr: false, + }, + { + name: "Test 2: Empty input map", + input: make(map[string]any), + expected: []*structpb.Struct{}, + wantErr: false, + }, + { + name: "Test 3: Invalid input type", + input: map[string]any{ + "key1": func() {}, // Unsupported type + }, + expected: []*structpb.Struct{}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ConvertToStructs(tt.input) + + assert.Equal(t, tt.expected, got) + assert.Equal(t, tt.wantErr, err != nil) + }) + } +} diff --git a/docs/proto/protos.md b/docs/proto/protos.md index 2f2d50e2c..5373f80bd 100644 --- a/docs/proto/protos.md +++ b/docs/proto/protos.md @@ -52,6 +52,8 @@ - [DataPlaneResponse](#mpi-v1-DataPlaneResponse) - [FileServer](#mpi-v1-FileServer) - [GetHTTPUpstreamServers](#mpi-v1-GetHTTPUpstreamServers) + - [GetStreamUpstreams](#mpi-v1-GetStreamUpstreams) + - [GetUpstreams](#mpi-v1-GetUpstreams) - [HealthRequest](#mpi-v1-HealthRequest) - [HostInfo](#mpi-v1-HostInfo) - [Instance](#mpi-v1-Instance) @@ -74,6 +76,7 @@ - [UpdateDataPlaneStatusRequest](#mpi-v1-UpdateDataPlaneStatusRequest) - [UpdateDataPlaneStatusResponse](#mpi-v1-UpdateDataPlaneStatusResponse) - [UpdateHTTPUpstreamServers](#mpi-v1-UpdateHTTPUpstreamServers) + - [UpdateStreamServers](#mpi-v1-UpdateStreamServers) - [InstanceHealth.InstanceHealthStatus](#mpi-v1-InstanceHealth-InstanceHealthStatus) - [InstanceMeta.InstanceType](#mpi-v1-InstanceMeta-InstanceType) @@ -298,6 +301,7 @@ Represents meta data about a file | ----- | ---- | ----- | ----------- | | file_meta | [FileMeta](#mpi-v1-FileMeta) | | Meta information about the file, the name (including path) and hash | | action | [File.FileAction](#mpi-v1-File-FileAction) | optional | Optional action | +| unmanaged | [bool](#bool) | | Unmanaged files will not be modified | @@ -797,6 +801,26 @@ Get HTTP Upstream Servers for an instance + + +### GetStreamUpstreams +Get Stream Upstream Servers for an instance + + + + + + + + +### GetUpstreams +Get Upstreams for an instance + + + + + + ### HealthRequest @@ -977,6 +1001,9 @@ Perform an action using the NGINX Plus API on an instance | ----- | ---- | ----- | ----------- | | update_http_upstream_servers | [UpdateHTTPUpstreamServers](#mpi-v1-UpdateHTTPUpstreamServers) | | | | get_http_upstream_servers | [GetHTTPUpstreamServers](#mpi-v1-GetHTTPUpstreamServers) | | | +| update_stream_servers | [UpdateStreamServers](#mpi-v1-UpdateStreamServers) | | | +| get_upstreams | [GetUpstreams](#mpi-v1-GetUpstreams) | | | +| get_stream_upstreams | [GetStreamUpstreams](#mpi-v1-GetStreamUpstreams) | | | @@ -1136,6 +1163,22 @@ Update HTTP Upstream Servers for an instance + + + +### UpdateStreamServers +Update Upstream Stream Servers for an instance + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| upstream_stream_name | [string](#string) | | the name of the upstream stream | +| servers | [google.protobuf.Struct](#google-protobuf-Struct) | repeated | a list of upstream stream servers | + + + + + diff --git a/internal/command/command_service.go b/internal/command/command_service.go index bb7e92bf0..1139c187b 100644 --- a/internal/command/command_service.go +++ b/internal/command/command_service.go @@ -40,9 +40,11 @@ type ( subscribeCancel context.CancelFunc subscribeChannel chan *mpi.ManagementPlaneRequest configApplyRequestQueue map[string][]*mpi.ManagementPlaneRequest // key is the instance ID + instances []*mpi.Instance subscribeMutex sync.Mutex subscribeClientMutex sync.Mutex configApplyRequestQueueMutex sync.Mutex + instancesMutex sync.Mutex } ) @@ -61,6 +63,7 @@ func NewCommandService( isConnected: isConnected, subscribeChannel: subscribeChannel, configApplyRequestQueue: make(map[string][]*mpi.ManagementPlaneRequest), + instances: []*mpi.Instance{}, } var subscribeCtx context.Context @@ -127,6 +130,10 @@ func (cs *CommandService) UpdateDataPlaneStatus( } slog.DebugContext(ctx, "UpdateDataPlaneStatus response", "response", response) + cs.instancesMutex.Lock() + defer cs.instancesMutex.Unlock() + cs.instances = resource.GetInstances() + return err } @@ -252,6 +259,10 @@ func (cs *CommandService) CreateConnection( cs.isConnected.Store(true) + cs.instancesMutex.Lock() + defer cs.instancesMutex.Unlock() + cs.instances = resource.GetInstances() + return response, nil } @@ -416,6 +427,14 @@ func (cs *CommandService) receiveCallback(ctx context.Context) func() error { return recvError } + if cs.isValidRequest(ctx, request) { + switch request.GetRequest().(type) { + case *mpi.ManagementPlaneRequest_ConfigApplyRequest: + cs.queueConfigApplyRequests(ctx, request) + default: + cs.subscribeChannel <- request + } + } switch request.GetRequest().(type) { case *mpi.ManagementPlaneRequest_ConfigApplyRequest: cs.configApplyRequestQueueMutex.Lock() @@ -440,6 +459,88 @@ func (cs *CommandService) receiveCallback(ctx context.Context) func() error { } } +func (cs *CommandService) queueConfigApplyRequests(ctx context.Context, request *mpi.ManagementPlaneRequest) { + cs.configApplyRequestQueueMutex.Lock() + defer cs.configApplyRequestQueueMutex.Unlock() + + instanceID := request.GetConfigApplyRequest().GetOverview().GetConfigVersion().GetInstanceId() + cs.configApplyRequestQueue[instanceID] = append(cs.configApplyRequestQueue[instanceID], request) + if len(cs.configApplyRequestQueue[instanceID]) == 1 { + cs.subscribeChannel <- request + } else { + slog.DebugContext( + ctx, + "Config apply request is already in progress, queuing new config apply request", + "request", request, + ) + } +} + +func (cs *CommandService) isValidRequest(ctx context.Context, request *mpi.ManagementPlaneRequest) bool { + var validRequest bool + + switch request.GetRequest().(type) { + case *mpi.ManagementPlaneRequest_ConfigApplyRequest: + requestInstanceID := request.GetConfigApplyRequest().GetOverview().GetConfigVersion().GetInstanceId() + validRequest = cs.checkIfInstanceExists(ctx, request, requestInstanceID) + case *mpi.ManagementPlaneRequest_ConfigUploadRequest: + requestInstanceID := request.GetConfigUploadRequest().GetOverview().GetConfigVersion().GetInstanceId() + validRequest = cs.checkIfInstanceExists(ctx, request, requestInstanceID) + case *mpi.ManagementPlaneRequest_ActionRequest: + requestInstanceID := request.GetActionRequest().GetInstanceId() + validRequest = cs.checkIfInstanceExists(ctx, request, requestInstanceID) + default: + validRequest = true + } + + return validRequest +} + +func (cs *CommandService) checkIfInstanceExists( + ctx context.Context, + request *mpi.ManagementPlaneRequest, + requestInstanceID string, +) bool { + instanceFound := false + + cs.instancesMutex.Lock() + for _, instance := range cs.instances { + if instance.GetInstanceMeta().GetInstanceId() == requestInstanceID { + instanceFound = true + } + } + cs.instancesMutex.Unlock() + + if !instanceFound { + slog.WarnContext( + ctx, + "Unable to handle request, instance not found", + "instance", requestInstanceID, + "request", request, + ) + + response := &mpi.DataPlaneResponse{ + MessageMeta: &mpi.MessageMeta{ + MessageId: proto.GenerateMessageID(), + CorrelationId: request.GetMessageMeta().GetCorrelationId(), + Timestamp: timestamppb.Now(), + }, + CommandResponse: &mpi.CommandResponse{ + Status: mpi.CommandResponse_COMMAND_STATUS_FAILURE, + Message: "Unable to handle request", + Error: "Instance ID not found", + }, + InstanceId: requestInstanceID, + } + err := cs.SendDataPlaneResponse(ctx, response) + if err != nil { + slog.ErrorContext(ctx, "Failed to send data plane response", "error", err) + } + } + + return instanceFound +} + // Retry callback for establishing the connection between the Management Plane and the Agent. func (cs *CommandService) connectCallback( ctx context.Context, diff --git a/internal/command/command_service_test.go b/internal/command/command_service_test.go index fc7f58139..a148bb139 100644 --- a/internal/command/command_service_test.go +++ b/internal/command/command_service_test.go @@ -56,7 +56,8 @@ func (*FakeConfigApplySubscribeClient) Send(*mpi.DataPlaneResponse) error { // nolint: nilnil func (*FakeConfigApplySubscribeClient) Recv() (*mpi.ManagementPlaneRequest, error) { - protos.CreateManagementPlaneRequest() + nginxInstance := protos.GetNginxOssInstance([]string{}) + return &mpi.ManagementPlaneRequest{ MessageMeta: &mpi.MessageMeta{ MessageId: "1", @@ -67,7 +68,7 @@ func (*FakeConfigApplySubscribeClient) Recv() (*mpi.ManagementPlaneRequest, erro ConfigApplyRequest: &mpi.ConfigApplyRequest{ Overview: &mpi.FileOverview{ ConfigVersion: &mpi.ConfigVersion{ - InstanceId: "12314", + InstanceId: nginxInstance.GetInstanceMeta().GetInstanceId(), Version: "4215432", }, }, @@ -113,6 +114,11 @@ func TestCommandService_receiveCallback_configApplyRequest(t *testing.T) { subscribeChannel, ) + nginxInstance := protos.GetNginxOssInstance([]string{}) + commandService.instancesMutex.Lock() + commandService.instances = append(commandService.instances, nginxInstance) + commandService.instancesMutex.Unlock() + defer commandService.CancelSubscription(ctx) var wg sync.WaitGroup @@ -389,3 +395,142 @@ func TestCommandService_SendDataPlaneResponse_configApplyRequest(t *testing.T) { assert.Equal(t, request3, commandService.configApplyRequestQueue["12314"][0]) wg.Wait() } + +func TestCommandService_isValidRequest(t *testing.T) { + ctx := context.Background() + commandServiceClient := &v1fakes.FakeCommandServiceClient{} + subscribeClient := &FakeSubscribeClient{} + + commandService := NewCommandService( + ctx, + commandServiceClient, + types.AgentConfig(), + make(chan *mpi.ManagementPlaneRequest), + ) + + commandService.subscribeClientMutex.Lock() + commandService.subscribeClient = subscribeClient + commandService.subscribeClientMutex.Unlock() + + nginxInstance := protos.GetNginxOssInstance([]string{}) + + commandService.instancesMutex.Lock() + commandService.instances = append(commandService.instances, nginxInstance) + commandService.instancesMutex.Unlock() + + testCases := []struct { + req *mpi.ManagementPlaneRequest + name string + result bool + }{ + { + name: "Test 1: valid health request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_HealthRequest{HealthRequest: &mpi.HealthRequest{}}, + }, + result: true, + }, + { + name: "Test 2: valid config apply request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ConfigApplyRequest{ + ConfigApplyRequest: protos.CreateConfigApplyRequest(&mpi.FileOverview{ + Files: make([]*mpi.File, 0), + ConfigVersion: &mpi.ConfigVersion{ + InstanceId: nginxInstance.GetInstanceMeta().GetInstanceId(), + Version: "e23brbei3u2bru93", + }, + }), + }, + }, + result: true, + }, + { + name: "Test 3: invalid config apply request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ConfigApplyRequest{ + ConfigApplyRequest: protos.CreateConfigApplyRequest(&mpi.FileOverview{ + Files: make([]*mpi.File, 0), + ConfigVersion: &mpi.ConfigVersion{ + InstanceId: "unknown-id", + Version: "e23brbei3u2bru93", + }, + }), + }, + }, + result: false, + }, + { + name: "Test 4: valid config upload request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ConfigUploadRequest{ + ConfigUploadRequest: &mpi.ConfigUploadRequest{ + Overview: &mpi.FileOverview{ + Files: make([]*mpi.File, 0), + ConfigVersion: &mpi.ConfigVersion{ + InstanceId: nginxInstance.GetInstanceMeta().GetInstanceId(), + Version: "e23brbei3u2bru93", + }, + }, + }, + }, + }, + result: true, + }, + { + name: "Test 5: invalid config upload request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ConfigUploadRequest{ + ConfigUploadRequest: &mpi.ConfigUploadRequest{ + Overview: &mpi.FileOverview{ + Files: make([]*mpi.File, 0), + ConfigVersion: &mpi.ConfigVersion{ + InstanceId: "unknown-id", + Version: "e23brbei3u2bru93", + }, + }, + }, + }, + }, + result: false, + }, + { + name: "Test 6: valid action request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ActionRequest{ + ActionRequest: &mpi.APIActionRequest{ + InstanceId: nginxInstance.GetInstanceMeta().GetInstanceId(), + Action: nil, + }, + }, + }, + result: true, + }, + { + name: "Test 7: invalid action request", + req: &mpi.ManagementPlaneRequest{ + MessageMeta: protos.CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ActionRequest{ + ActionRequest: &mpi.APIActionRequest{ + InstanceId: "unknown-id", + Action: nil, + }, + }, + }, + result: false, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result := commandService.isValidRequest(ctx, testCase.req) + assert.Equal(t, testCase.result, result) + }) + } +} diff --git a/internal/config/config.go b/internal/config/config.go index aa8fa0711..c1958b1a8 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,12 +7,14 @@ package config import ( "context" + "encoding/json" "errors" "fmt" "log/slog" "os" "path/filepath" "slices" + "strconv" "strings" selfsignedcerts "github.com/nginx/agent/v3/pkg/tls" @@ -26,6 +28,7 @@ const ( ConfigFileName = "nginx-agent.conf" EnvPrefix = "NGINX_AGENT" KeyDelimiter = "_" + KeyValueNumber = 2 ) var viperInstance = viper.NewWithOptions(viper.KeyDelimiter(KeyDelimiter)) @@ -102,6 +105,7 @@ func ResolveConfig() (*Config, error) { Command: resolveCommand(), Watchers: resolveWatchers(), Features: viperInstance.GetStringSlice(FeaturesKey), + Labels: resolveLabels(), } slog.Debug("Agent config", "config", config) @@ -181,6 +185,7 @@ func registerFlags() { "A comma-separated list of features enabled for the agent.", ) + registerCommonFlags(fs) registerCommandFlags(fs) registerCollectorFlags(fs) registerClientFlags(fs) @@ -198,6 +203,14 @@ func registerFlags() { }) } +func registerCommonFlags(fs *flag.FlagSet) { + fs.StringToString( + LabelsRootKey, + DefaultLabels(), + "A list of labels associated with these instances", + ) +} + func registerClientFlags(fs *flag.FlagSet) { // HTTP Flags fs.Duration( @@ -289,12 +302,6 @@ func registerCommandFlags(fs *flag.FlagSet) { DefCommandAuthTokenKey, "The token used in the authentication handshake with the command server endpoint for command and control.", ) - fs.String( - CommandAuthTokenPathKey, - DefCommandAuthTokenPathKey, - "Path to the token used in the authentication handshake with the command server endpoint "+ - "for command and control.", - ) fs.String( CommandTLSCertKey, DefCommandTLSCertKey, @@ -462,6 +469,102 @@ func resolveLog() *Log { } } +func resolveLabels() map[string]interface{} { + input := viperInstance.GetStringMapString(LabelsRootKey) + + // Parsing the environment variable for labels needs to be done differently + // by parsing the environment variable as a string. + envLabels := resolveEnvironmentVariableLabels() + + if len(envLabels) > 0 { + input = envLabels + } + + result := make(map[string]interface{}) + + for key, value := range input { + trimmedKey := strings.TrimSpace(key) + trimmedValue := strings.TrimSpace(value) + + switch { + case trimmedValue == "" || trimmedValue == "nil": // Handle empty values as nil + result[trimmedKey] = nil + + case parseInt(trimmedValue) != nil: // Integer + result[trimmedKey] = parseInt(trimmedValue) + + case parseFloat(trimmedValue) != nil: // Float + result[trimmedKey] = parseFloat(trimmedValue) + + case parseBool(trimmedValue) != nil: // Boolean + result[trimmedKey] = parseBool(trimmedValue) + + case parseJSON(trimmedValue) != nil: // JSON object/array + result[trimmedKey] = parseJSON(trimmedValue) + + default: // String + result[trimmedKey] = trimmedValue + } + } + + slog.Info("Configured labels", "labels", result) + + return result +} + +func resolveEnvironmentVariableLabels() map[string]string { + envLabels := make(map[string]string) + envInput := viperInstance.GetString(LabelsRootKey) + + labels := strings.Split(envInput, ",") + if len(labels) > 0 && labels[0] != "" { + for _, label := range labels { + splitLabel := strings.Split(label, "=") + if len(splitLabel) == KeyValueNumber { + envLabels[splitLabel[0]] = splitLabel[1] + } else { + slog.Warn("Unable to parse label: " + label) + } + } + } + + return envLabels +} + +// Parsing helper functions return the parsed value or nil if parsing fails +func parseInt(value string) interface{} { + if intValue, err := strconv.Atoi(value); err == nil { + return intValue + } + + return nil +} + +func parseFloat(value string) interface{} { + if floatValue, err := strconv.ParseFloat(value, 64); err == nil { + return floatValue + } + + return nil +} + +func parseBool(value string) interface{} { + if boolValue, err := strconv.ParseBool(value); err == nil { + return boolValue + } + + return nil +} + +func parseJSON(value string) interface{} { + var jsonValue interface{} + if err := json.Unmarshal([]byte(value), &jsonValue); err == nil { + return jsonValue + } + + return nil +} + func resolveDataPlaneConfig() *DataPlaneConfig { return &DataPlaneConfig{ Nginx: &NginxDataPlaneConfig{ @@ -719,11 +822,6 @@ func resolveCommand() *Command { } } - if viperInstance.IsSet(CommandAuthTokenPathKey) { - command.Auth = &AuthConfig{ - TokenPath: viperInstance.GetString(CommandAuthTokenPathKey), - } - } if areTLSSettingsSet() { command.TLS = &TLSConfig{ Cert: viperInstance.GetString(CommandTLSCertKey), diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 70501d76f..553401384 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -7,6 +7,7 @@ package config import ( "os" "path" + "strings" "testing" "time" @@ -146,6 +147,7 @@ func checkDefaultsClientValues(t *testing.T, viperInstance *viper.Viper) { assert.Equal(t, DefMaxMessageSize, viperInstance.GetInt(ClientGRPCMaxMessageSizeKey)) assert.Equal(t, DefMaxMessageRecieveSize, viperInstance.GetInt(ClientGRPCMaxMessageReceiveSizeKey)) assert.Equal(t, DefMaxMessageSendSize, viperInstance.GetInt(ClientGRPCMaxMessageSendSizeKey)) + assert.Equal(t, make(map[string]string), viperInstance.GetStringMapString(LabelsRootKey)) } func TestSeekFileInPaths(t *testing.T) { @@ -334,6 +336,313 @@ func TestClient(t *testing.T) { assert.Equal(t, expected, result) } +func TestResolveLabels(t *testing.T) { + // Helper to set up the viper instance + setupViper := func(input map[string]string) { + viperInstance = viper.New() // Create a new viper instance for isolation + viperInstance.Set(LabelsRootKey, input) + } + + tests := []struct { + input map[string]string + expected map[string]interface{} + name string + }{ + { + name: "Test 1: Integer values", + input: map[string]string{ + "key1": "123", + "key2": "456", + }, + expected: map[string]interface{}{ + "key1": 123, + "key2": 456, + }, + }, + { + name: "Test 2: Float values", + input: map[string]string{ + "key1": "123.45", + "key2": "678.90", + }, + expected: map[string]interface{}{ + "key1": 123.45, + "key2": 678.9, + }, + }, + { + name: "Test 3: Boolean values", + input: map[string]string{ + "key1": "true", + "key2": "false", + }, + expected: map[string]interface{}{ + "key1": true, + "key2": false, + }, + }, + { + name: "Test 4: Mixed types", + input: map[string]string{ + "key1": "true", + "key2": "123", + "key3": "45.67", + "key4": "hello", + }, + expected: map[string]interface{}{ + "key1": true, + "key2": 123, + "key3": 45.67, + "key4": "hello", + }, + }, + { + name: "Test 5: String values", + input: map[string]string{ + "key1": "hello", + "key2": "world", + }, + expected: map[string]interface{}{ + "key1": "hello", + "key2": "world", + }, + }, + { + name: "Test 6: Empty input", + input: make(map[string]string), + expected: make(map[string]interface{}), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Setup viper with test input + setupViper(tt.input) + + // Call the function + actual := resolveLabels() + + // Assert the results + assert.Equal(t, tt.expected, actual) + }) + } +} + +func TestResolveLabelsWithYAML(t *testing.T) { + tests := []struct { + expected map[string]interface{} + name string + yamlInput string + }{ + { + name: "Test 1: Integer and Float Values", + yamlInput: ` +labels: + key1: "123" + key2: "45.67" +`, + expected: map[string]interface{}{ + "key1": 123, + "key2": 45.67, + }, + }, + { + name: "Test 2: Boolean Values", + yamlInput: ` +labels: + key1: "true" + key2: "false" +`, + expected: map[string]interface{}{ + "key1": true, + "key2": false, + }, + }, + { + name: "Test 3: Nil and Empty Values", + yamlInput: ` +labels: + key1: "nil" + key2: "" +`, + expected: map[string]interface{}{ + "key1": nil, + "key2": nil, + }, + }, + { + name: "Test 4: Array Values", + yamlInput: ` +labels: + key1: "[1, 2, 3]" +`, + expected: map[string]interface{}{ + "key1": []interface{}{float64(1), float64(2), float64(3)}, + }, + }, + { + name: "Test 5: Nested JSON Object", + yamlInput: ` +labels: + key1: '{"a": 1, "b": 2}' +`, + expected: map[string]interface{}{ + "key1": map[string]interface{}{ + "a": float64(1), + "b": float64(2), + }, + }, + }, + { + name: "Test 6: Plain Strings", + yamlInput: ` +labels: + key1: "hello" + key2: "world" +`, + expected: map[string]interface{}{ + "key1": "hello", + "key2": "world", + }, + }, + { + name: "Test 7: Specific Strings Example", + yamlInput: ` +labels: + config-sync-group: "group1" +`, + expected: map[string]interface{}{ + "config-sync-group": "group1", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set up viper with YAML input + viperInstance = viper.New() // Create a new viper instance for isolation + viperInstance.SetConfigType("yaml") + + err := viperInstance.ReadConfig(strings.NewReader(tt.yamlInput)) + require.NoError(t, err, "Error reading YAML input") + + // Call the function + actual := resolveLabels() + + // Assert the results + assert.Equal(t, tt.expected, actual) + }) + } +} + +func TestParseInt(t *testing.T) { + tests := []struct { + expected interface{} + name string + input string + }{ + {name: "Test 1: Valid Integer", input: "123", expected: 123}, + {name: "Test 2: Negative Integer", input: "-456", expected: -456}, + {name: "Test 3: Zero", input: "0", expected: 0}, + {name: "Test 4: Invalid Integer", input: "abc", expected: nil}, + {name: "Test 5: Empty String", input: "", expected: nil}, + {name: "Test 6: Float String", input: "45.67", expected: nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := parseInt(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestParseFloat(t *testing.T) { + tests := []struct { + expected interface{} + name string + input string + }{ + {name: "Test 1: Valid Float", input: "45.67", expected: 45.67}, + {name: "Test 2: Negative Float", input: "-123.45", expected: -123.45}, + {name: "Test 3: Valid Integer as Float", input: "123", expected: 123.0}, + {name: "Test 4: Invalid Float", input: "abc", expected: nil}, + {name: "Test 5: Empty String", input: "", expected: nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := parseFloat(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestParseBool(t *testing.T) { + tests := []struct { + expected interface{} + name string + input string + }{ + {name: "Test 1: True (lowercase)", input: "true", expected: true}, + {name: "Test 2: False (lowercase)", input: "false", expected: false}, + {name: "Test 3: True (uppercase)", input: "TRUE", expected: true}, + {name: "Test 4: False (uppercase)", input: "FALSE", expected: false}, + {name: "Test 5: Numeric True", input: "1", expected: true}, + {name: "Test 6: Numeric False", input: "0", expected: false}, + {name: "Test 7: Invalid Boolean", input: "abc", expected: nil}, + {name: "Test 8: Empty String", input: "", expected: nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := parseBool(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestParseJSON(t *testing.T) { + tests := []struct { + expected interface{} + name string + input string + }{ + { + name: "Test 1: Valid JSON Object", + input: `{"a": 1, "b": "text"}`, + expected: map[string]interface{}{ + "a": float64(1), + "b": "text", + }, + }, + { + name: "Test 2: Valid JSON Array", + input: `[1, 2, 3]`, + expected: []interface{}{float64(1), float64(2), float64(3)}, + }, + { + name: "Test 3: Nested JSON", + input: `{"a": {"b": [1, 2, 3]}}`, + expected: map[string]interface{}{ + "a": map[string]interface{}{"b": []interface{}{float64(1), float64(2), float64(3)}}, + }, + }, + {name: "Test 4: Invalid JSON", input: `{"a": 1,`, expected: nil}, + {name: "Test 5: Empty String", input: "", expected: nil}, + {name: "Test 6: Plain String", input: `"hello"`, expected: "hello"}, + {name: "Test 7: Number as JSON", input: "123", expected: float64(123)}, + {name: "Test 8: Boolean as JSON", input: "true", expected: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := parseJSON(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + func getAgentConfig() *Config { return &Config{ UUID: "", @@ -460,5 +769,6 @@ func getAgentConfig() *Config { ServerName: "server-name", }, }, + Labels: make(map[string]any), } } diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 9cc7f822e..8d66c7146 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -93,3 +93,7 @@ func DefaultAllowedDirectories() []string { "/var/log/nginx", } } + +func DefaultLabels() map[string]string { + return make(map[string]string) +} diff --git a/internal/config/flags.go b/internal/config/flags.go index 7b4bb793d..d8b2861be 100644 --- a/internal/config/flags.go +++ b/internal/config/flags.go @@ -14,6 +14,7 @@ const ( ConfigPathKey = "path" CommandRootKey = "command" DataPlaneConfigRootKey = "data_plane_config" + LabelsRootKey = "labels" LogLevelRootKey = "log" CollectorRootKey = "collector" VersionKey = "version" diff --git a/internal/config/types.go b/internal/config/types.go index fe910bdc5..43ceb9e66 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -39,6 +39,7 @@ type ( Collector *Collector `yaml:"-" mapstructure:"collector"` File *File `yaml:"-" mapstructure:"file"` Watchers *Watchers `yaml:"-"` + Labels map[string]any `yaml:"-" mapstructure:"labels"` Version string `yaml:"-"` Path string `yaml:"-"` UUID string `yaml:"-"` diff --git a/internal/datasource/proto/message.go b/internal/datasource/proto/message.go index a2d547ca0..a665355fc 100644 --- a/internal/datasource/proto/message.go +++ b/internal/datasource/proto/message.go @@ -9,6 +9,9 @@ import ( "log/slog" "time" + mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/google/uuid" agentUuid "github.com/nginx/agent/v3/pkg/uuid" ) @@ -29,3 +32,21 @@ func GenerateMessageID() string { return uuidv7.String() } + +func CreateDataPlaneResponse(correlationID string, status mpi.CommandResponse_CommandStatus, + message, instanceID, err string, +) *mpi.DataPlaneResponse { + return &mpi.DataPlaneResponse{ + MessageMeta: &mpi.MessageMeta{ + MessageId: GenerateMessageID(), + CorrelationId: correlationID, + Timestamp: timestamppb.Now(), + }, + CommandResponse: &mpi.CommandResponse{ + Status: status, + Message: message, + Error: err, + }, + InstanceId: instanceID, + } +} diff --git a/internal/file/file_manager_service.go b/internal/file/file_manager_service.go index 6d9bb1114..466bf01be 100644 --- a/internal/file/file_manager_service.go +++ b/internal/file/file_manager_service.go @@ -473,6 +473,11 @@ func (fms *FileManagerService) DetermineFileActions(currentFiles, modifiedFiles currentFile, ok := currentFiles[file.GetFileMeta().GetName()] // default to unchanged action file.Action = &unchangedAction + + // if file is unmanaged, action is set to unchanged so file is skipped when performing actions + if file.GetUnmanaged() { + continue + } // if file doesn't exist in the current files, file has been added // set file action if !ok { diff --git a/internal/file/file_manager_service_test.go b/internal/file/file_manager_service_test.go index a90c51af4..c0da7ad99 100644 --- a/internal/file/file_manager_service_test.go +++ b/internal/file/file_manager_service_test.go @@ -462,6 +462,12 @@ func TestFileManagerService_DetermineFileActions(t *testing.T) { addTestFileName := tempDir + "/nginx_add.conf" + unmanagedFile := helpers.CreateFileWithErrorCheck(t, tempDir, "nginx_unmanaged.conf") + defer helpers.RemoveFileWithErrorCheck(t, unmanagedFile.Name()) + unmanagedFileContent := []byte("test unmanaged file") + unmanagedErr := os.WriteFile(unmanagedFile.Name(), unmanagedFileContent, 0o600) + require.NoError(t, unmanagedErr) + tests := []struct { expectedError error modifiedFiles map[string]*mpi.File @@ -479,6 +485,10 @@ func TestFileManagerService_DetermineFileActions(t *testing.T) { updateTestFile.Name(): { FileMeta: protos.FileMeta(updateTestFile.Name(), files.GenerateHash(updatedFileContent)), }, + unmanagedFile.Name(): { + FileMeta: protos.FileMeta(unmanagedFile.Name(), files.GenerateHash(unmanagedFileContent)), + Unmanaged: true, + }, }, currentFiles: map[string]*mpi.File{ deleteTestFile.Name(): { @@ -487,6 +497,10 @@ func TestFileManagerService_DetermineFileActions(t *testing.T) { updateTestFile.Name(): { FileMeta: protos.FileMeta(updateTestFile.Name(), files.GenerateHash(fileContent)), }, + unmanagedFile.Name(): { + FileMeta: protos.FileMeta(unmanagedFile.Name(), files.GenerateHash(fileContent)), + Unmanaged: true, + }, }, expectedCache: map[string]*mpi.File{ deleteTestFile.Name(): { diff --git a/internal/resource/nginx_plus_actions.go b/internal/resource/nginx_plus_actions.go new file mode 100644 index 000000000..84b34d250 --- /dev/null +++ b/internal/resource/nginx_plus_actions.go @@ -0,0 +1,149 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package resource + +import ( + "context" + "encoding/json" + "log/slog" + + mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1" + "github.com/nginx/agent/v3/internal/datasource/proto" + "github.com/nginx/agent/v3/internal/logger" +) + +const emptyResponse = "{}" + +type APIAction struct { + ResourceService resourceServiceInterface +} + +func (a *APIAction) HandleUpdateStreamServersRequest(ctx context.Context, action *mpi.NGINXPlusAction, + instance *mpi.Instance, +) *mpi.DataPlaneResponse { + correlationID := logger.GetCorrelationID(ctx) + instanceID := instance.GetInstanceMeta().GetInstanceId() + + add, update, del, err := a.ResourceService.UpdateStreamServers(ctx, instance, + action.GetUpdateStreamServers().GetUpstreamStreamName(), action.GetUpdateStreamServers().GetServers()) + if err != nil { + slog.ErrorContext(ctx, "Unable to update stream servers of upstream", "request", + action.GetUpdateHttpUpstreamServers(), "error", err) + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + "", instanceID, err.Error()) + } + + slog.DebugContext(ctx, "Successfully updated stream upstream servers", "http_upstream_name", + action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update), + "delete", len(del)) + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, + "Successfully updated stream upstream servers", instanceID, "") +} + +func (a *APIAction) HandleGetStreamUpstreamsRequest(ctx context.Context, + instance *mpi.Instance, +) *mpi.DataPlaneResponse { + correlationID := logger.GetCorrelationID(ctx) + instanceID := instance.GetInstanceMeta().GetInstanceId() + streamUpstreamsResponse := emptyResponse + + streamUpstreams, err := a.ResourceService.GetStreamUpstreams(ctx, instance) + if err != nil { + slog.ErrorContext(ctx, "Unable to get stream upstreams", "error", err) + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + "", instanceID, err.Error()) + } + + if streamUpstreams != nil { + streamUpstreamsJSON, jsonErr := json.Marshal(streamUpstreams) + if jsonErr != nil { + slog.ErrorContext(ctx, "Unable to marshal stream upstreams", "err", err) + } + streamUpstreamsResponse = string(streamUpstreamsJSON) + } + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, + streamUpstreamsResponse, instanceID, "") +} + +func (a *APIAction) HandleGetUpstreamsRequest(ctx context.Context, instance *mpi.Instance) *mpi.DataPlaneResponse { + correlationID := logger.GetCorrelationID(ctx) + instanceID := instance.GetInstanceMeta().GetInstanceId() + upstreamsResponse := emptyResponse + + upstreams, err := a.ResourceService.GetUpstreams(ctx, instance) + if err != nil { + slog.InfoContext(ctx, "Unable to get upstreams", "error", err) + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + "", instanceID, err.Error()) + } + + if upstreams != nil { + upstreamsJSON, jsonErr := json.Marshal(upstreams) + if jsonErr != nil { + slog.ErrorContext(ctx, "Unable to marshal upstreams", "err", err) + } + upstreamsResponse = string(upstreamsJSON) + } + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, + upstreamsResponse, instanceID, "") +} + +func (a *APIAction) HandleUpdateHTTPUpstreamsRequest(ctx context.Context, action *mpi.NGINXPlusAction, + instance *mpi.Instance, +) *mpi.DataPlaneResponse { + correlationID := logger.GetCorrelationID(ctx) + instanceID := instance.GetInstanceMeta().GetInstanceId() + + add, update, del, err := a.ResourceService.UpdateHTTPUpstreamServers(ctx, instance, + action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), + action.GetUpdateHttpUpstreamServers().GetServers()) + if err != nil { + slog.ErrorContext(ctx, "Unable to update HTTP servers of upstream", "request", + action.GetUpdateHttpUpstreamServers(), "error", err) + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + "", instanceID, err.Error()) + } + + slog.DebugContext(ctx, "Successfully updated http upstream servers", "http_upstream_name", + action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update), + "delete", len(del)) + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, + "Successfully updated HTTP Upstreams", instanceID, "") +} + +func (a *APIAction) HandleGetHTTPUpstreamsServersRequest(ctx context.Context, action *mpi.NGINXPlusAction, + instance *mpi.Instance, +) *mpi.DataPlaneResponse { + correlationID := logger.GetCorrelationID(ctx) + instanceID := instance.GetInstanceMeta().GetInstanceId() + upstreamsResponse := emptyResponse + + upstreams, err := a.ResourceService.GetHTTPUpstreamServers(ctx, instance, + action.GetGetHttpUpstreamServers().GetHttpUpstreamName()) + if err != nil { + slog.ErrorContext(ctx, "Unable to get HTTP servers of upstream", "error", err) + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + "", instanceID, err.Error()) + } + + if upstreams != nil { + upstreamsJSON, jsonErr := json.Marshal(upstreams) + if jsonErr != nil { + slog.ErrorContext(ctx, "Unable to marshal http upstreams", "err", err) + } + upstreamsResponse = string(upstreamsJSON) + } + + return proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, + upstreamsResponse, instanceID, "") +} diff --git a/internal/resource/resource_plugin.go b/internal/resource/resource_plugin.go index 9c1519c65..a32aa3581 100644 --- a/internal/resource/resource_plugin.go +++ b/internal/resource/resource_plugin.go @@ -7,7 +7,6 @@ package resource import ( "context" - "encoding/json" "errors" "fmt" "log/slog" @@ -17,7 +16,6 @@ import ( "github.com/nginx/agent/v3/internal/datasource/proto" "github.com/nginx/agent/v3/internal/logger" "github.com/nginx/agent/v3/internal/model" - "google.golang.org/protobuf/types/known/timestamppb" "github.com/nginx/agent/v3/internal/bus" ) @@ -34,7 +32,7 @@ type Resource struct { type errResponse struct { Status string `json:"status"` - Test string `json:"test"` + Text string `json:"test"` Code string `json:"code"` } @@ -165,9 +163,12 @@ func (r *Resource) handleAPIActionRequest(ctx context.Context, msg *bus.Message) func (r *Resource) handleNginxPlusActionRequest(ctx context.Context, action *mpi.NGINXPlusAction, instanceID string) { correlationID := logger.GetCorrelationID(ctx) instance := r.resourceService.Instance(instanceID) + apiAction := APIAction{ + ResourceService: r.resourceService, + } if instance == nil { slog.ErrorContext(ctx, "Unable to find instance with ID", "id", instanceID) - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + resp := proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, "", instanceID, fmt.Sprintf("failed to preform API "+ "action, could not find instance with ID: %s", instanceID)) @@ -178,7 +179,7 @@ func (r *Resource) handleNginxPlusActionRequest(ctx context.Context, action *mpi if instance.GetInstanceMeta().GetInstanceType() != mpi.InstanceMeta_INSTANCE_TYPE_NGINX_PLUS { slog.ErrorContext(ctx, "Failed to preform API action", "error", errors.New("instance is not NGINX Plus")) - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, + resp := proto.CreateDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, "", instanceID, "failed to preform API action, instance is not NGINX Plus") r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) @@ -188,49 +189,24 @@ func (r *Resource) handleNginxPlusActionRequest(ctx context.Context, action *mpi switch action.GetAction().(type) { case *mpi.NGINXPlusAction_UpdateHttpUpstreamServers: - slog.DebugContext(ctx, "Updating http upstream servers", - "request", action.GetUpdateHttpUpstreamServers()) - add, update, del, err := r.resourceService.UpdateHTTPUpstreams(ctx, instance, - action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), - action.GetUpdateHttpUpstreamServers().GetServers()) - if err != nil { - slog.ErrorContext(ctx, "Unable to update HTTP servers of upstream", "request", - action.GetUpdateHttpUpstreamServers(), "error", err) - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, - "", instanceID, err.Error()) - r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) - - return - } - - slog.DebugContext(ctx, "Successfully updated http upstream servers", "http_upstream_name", - action.GetUpdateHttpUpstreamServers().GetHttpUpstreamName(), "add", len(add), "update", len(update), - "delete", len(del)) - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, - "Successfully updated HTTP Upstreams", instanceID, "") - + slog.DebugContext(ctx, "Updating http upstream servers", "request", action.GetUpdateHttpUpstreamServers()) + resp := apiAction.HandleUpdateHTTPUpstreamsRequest(ctx, action, instance) r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) - case *mpi.NGINXPlusAction_GetHttpUpstreamServers: slog.DebugContext(ctx, "Getting http upstream servers", "request", action.GetGetHttpUpstreamServers()) - upstreams, err := r.resourceService.GetUpstreams(ctx, instance, - action.GetGetHttpUpstreamServers().GetHttpUpstreamName()) - if err != nil { - slog.ErrorContext(ctx, "Unable to get HTTP servers of upstream", "error", err) - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, - "", instanceID, err.Error()) - r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) - - return - } - - upstreamsJSON, err := json.Marshal(upstreams) - if err != nil { - slog.ErrorContext(ctx, "Unable to marshal http upstreams", "err", err) - } - resp := r.createDataPlaneResponse(correlationID, mpi.CommandResponse_COMMAND_STATUS_OK, - string(upstreamsJSON), instanceID, "") - + resp := apiAction.HandleGetHTTPUpstreamsServersRequest(ctx, action, instance) + r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) + case *mpi.NGINXPlusAction_UpdateStreamServers: + slog.DebugContext(ctx, "Updating stream servers", "request", action.GetUpdateStreamServers()) + resp := apiAction.HandleUpdateStreamServersRequest(ctx, action, instance) + r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) + case *mpi.NGINXPlusAction_GetStreamUpstreams: + slog.DebugContext(ctx, "Getting stream upstreams", "request", action.GetGetStreamUpstreams()) + resp := apiAction.HandleGetStreamUpstreamsRequest(ctx, instance) + r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) + case *mpi.NGINXPlusAction_GetUpstreams: + slog.DebugContext(ctx, "Getting upstreams", "request", action.GetGetUpstreams()) + resp := apiAction.HandleGetUpstreamsRequest(ctx, instance) r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: resp}) default: slog.DebugContext(ctx, "NGINX Plus action not implemented yet") @@ -248,7 +224,7 @@ func (r *Resource) handleWriteConfigSuccessful(ctx context.Context, msg *bus.Mes if err != nil { data.Error = err slog.Error("errors found during config apply, sending error status, rolling back config", "err", err) - response := r.createDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_ERROR, + response := proto.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_ERROR, "Config apply failed, rolling back config", data.InstanceID, err.Error()) r.messagePipe.Process(ctx, &bus.Message{Topic: bus.DataPlaneResponseTopic, Data: response}) @@ -257,7 +233,7 @@ func (r *Resource) handleWriteConfigSuccessful(ctx context.Context, msg *bus.Mes return } - response := r.createDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_OK, + response := proto.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_OK, "Config apply successful", data.InstanceID, "") r.messagePipe.Process( @@ -280,10 +256,10 @@ func (r *Resource) handleRollbackWrite(ctx context.Context, msg *bus.Message) { if err != nil { slog.Error("errors found during rollback, sending failure status", "err", err) - rollbackResponse := r.createDataPlaneResponse(data.CorrelationID, + rollbackResponse := proto.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_ERROR, "Rollback failed", data.InstanceID, err.Error()) - applyResponse := r.createDataPlaneResponse(data.CorrelationID, + applyResponse := proto.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, "Config apply failed, rollback failed", data.InstanceID, data.Error.Error()) @@ -293,27 +269,9 @@ func (r *Resource) handleRollbackWrite(ctx context.Context, msg *bus.Message) { return } - applyResponse := r.createDataPlaneResponse(data.CorrelationID, + applyResponse := proto.CreateDataPlaneResponse(data.CorrelationID, mpi.CommandResponse_COMMAND_STATUS_FAILURE, "Config apply failed, rollback successful", data.InstanceID, data.Error.Error()) r.messagePipe.Process(ctx, &bus.Message{Topic: bus.ConfigApplyCompleteTopic, Data: applyResponse}) } - -func (*Resource) createDataPlaneResponse(correlationID string, status mpi.CommandResponse_CommandStatus, - message, instanceID, err string, -) *mpi.DataPlaneResponse { - return &mpi.DataPlaneResponse{ - MessageMeta: &mpi.MessageMeta{ - MessageId: proto.GenerateMessageID(), - CorrelationId: correlationID, - Timestamp: timestamppb.Now(), - }, - CommandResponse: &mpi.CommandResponse{ - Status: status, - Message: message, - Error: err, - }, - InstanceId: instanceID, - } -} diff --git a/internal/resource/resource_plugin_test.go b/internal/resource/resource_plugin_test.go index 807b380f2..313b8bb98 100644 --- a/internal/resource/resource_plugin_test.go +++ b/internal/resource/resource_plugin_test.go @@ -199,7 +199,7 @@ func TestResource_createPlusAPIError(t *testing.T) { expectedErr := plusAPIErr{ Error: errResponse{ Status: "404", - Test: "upstream not found", + Text: "upstream not found", Code: "UpstreamNotFound", }, RequestID: "b534bdab5cb5e321e8b41b431828b270", @@ -213,6 +213,7 @@ func TestResource_createPlusAPIError(t *testing.T) { assert.Equal(t, errors.New(string(expectedJSON)), result) } +// nolint: dupl func TestResource_Process_APIAction_GetHTTPServers(t *testing.T) { ctx := context.Background() @@ -290,7 +291,7 @@ func TestResource_Process_APIAction_GetHTTPServers(t *testing.T) { for _, test := range tests { t.Run(test.name, func(tt *testing.T) { fakeResourceService := &resourcefakes.FakeResourceServiceInterface{} - fakeResourceService.GetUpstreamsReturns(test.upstreams, test.err) + fakeResourceService.GetHTTPUpstreamServersReturns(test.upstreams, test.err) if test.instance.GetInstanceMeta().GetInstanceId() != "e1374cb1-462d-3b6c-9f3b-f28332b5f10f" { fakeResourceService.InstanceReturns(test.instance) } @@ -323,6 +324,7 @@ func TestResource_Process_APIAction_GetHTTPServers(t *testing.T) { } } +// nolint: dupl func TestResource_Process_APIAction_UpdateHTTPUpstreams(t *testing.T) { ctx := context.Background() tests := []struct { @@ -391,9 +393,9 @@ func TestResource_Process_APIAction_UpdateHTTPUpstreams(t *testing.T) { fakeResourceService := &resourcefakes.FakeResourceServiceInterface{} fakeResourceService.InstanceReturns(test.instance) - fakeResourceService.UpdateHTTPUpstreamsReturnsOnCall(0, test.upstreams, []client.UpstreamServer{}, + fakeResourceService.UpdateHTTPUpstreamServersReturnsOnCall(0, test.upstreams, []client.UpstreamServer{}, []client.UpstreamServer{}, test.err) - fakeResourceService.UpdateHTTPUpstreamsReturnsOnCall(1, []client.UpstreamServer{}, + fakeResourceService.UpdateHTTPUpstreamServersReturnsOnCall(1, []client.UpstreamServer{}, []client.UpstreamServer{}, []client.UpstreamServer{}, test.err) messagePipe := busfakes.NewFakeMessagePipe() @@ -425,6 +427,401 @@ func TestResource_Process_APIAction_UpdateHTTPUpstreams(t *testing.T) { } } +// nolint: dupl +func TestResource_Process_APIAction_UpdateStreamServers(t *testing.T) { + ctx := context.Background() + tests := []struct { + instance *mpi.Instance + name string + expectedLog string + message *bus.Message + err error + topic []string + upstreams []client.StreamUpstreamServer + }{ + { + name: "Test 1: Success, Update Stream Servers", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusUpdateStreamServers("test_upstream", + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId(), []*structpb.Struct{ + { + Fields: map[string]*structpb.Value{ + "max_cons": structpb.NewNumberValue(8), + "max_fails": structpb.NewNumberValue(0), + "backup": structpb.NewBoolValue(true), + "service": structpb.NewStringValue("test_server"), + }, + }, + }), + }, + err: nil, + upstreams: []client.StreamUpstreamServer{ + helpers.CreateNginxPlusStreamServer(t), + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + expectedLog: "Successfully updated stream upstream", + }, + { + name: "Test 2: Fail, Update Stream Servers", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusUpdateStreamServers("test_upstream", + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId(), []*structpb.Struct{ + { + Fields: map[string]*structpb.Value{ + "max_cons": structpb.NewNumberValue(8), + "max_fails": structpb.NewNumberValue(0), + "backup": structpb.NewBoolValue(true), + "service": structpb.NewStringValue("test_server"), + }, + }, + }), + }, + err: errors.New("something went wrong"), + upstreams: []client.StreamUpstreamServer{ + helpers.CreateNginxPlusStreamServer(t), + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + expectedLog: "Unable to update stream servers of upstream", + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + logBuf := &bytes.Buffer{} + stub.StubLoggerWith(logBuf) + + fakeResourceService := &resourcefakes.FakeResourceServiceInterface{} + fakeResourceService.InstanceReturns(test.instance) + fakeResourceService.UpdateStreamServersReturnsOnCall(0, test.upstreams, []client.StreamUpstreamServer{}, + []client.StreamUpstreamServer{}, test.err) + fakeResourceService.UpdateStreamServersReturnsOnCall(0, test.upstreams, []client.StreamUpstreamServer{}, + []client.StreamUpstreamServer{}, test.err) + + messagePipe := busfakes.NewFakeMessagePipe() + + resourcePlugin := NewResource(types.AgentConfig()) + resourcePlugin.resourceService = fakeResourceService + + err := messagePipe.Register(2, []bus.Plugin{resourcePlugin}) + require.NoError(tt, err) + + resourcePlugin.messagePipe = messagePipe + + resourcePlugin.Process(ctx, test.message) + + assert.Equal(tt, test.topic[0], messagePipe.GetMessages()[0].Topic) + + response, ok := messagePipe.GetMessages()[0].Data.(*mpi.DataPlaneResponse) + assert.True(tt, ok) + + if test.err != nil { + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_FAILURE, response.GetCommandResponse().GetStatus()) + } else { + assert.Empty(tt, response.GetCommandResponse().GetError()) + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_OK, response.GetCommandResponse().GetStatus()) + } + + helpers.ValidateLog(tt, test.expectedLog, logBuf) + }) + } +} + +// nolint: dupl +func TestResource_Process_APIAction_GetStreamUpstreams(t *testing.T) { + ctx := context.Background() + + inValidInstance := protos.GetNginxPlusInstance([]string{}) + inValidInstance.InstanceMeta.InstanceId = "e1374cb1-462d-3b6c-9f3b-f28332b5f10f" + + tests := []struct { + instance *mpi.Instance + upstreams *client.StreamUpstreams + name string + message *bus.Message + err error + topic []string + }{ + { + name: "Test 1: Success, Get Stream Upstreams API Action", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusGetStreamUpstreams( + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: nil, + upstreams: &client.StreamUpstreams{ + "upstream_1": client.StreamUpstream{ + Zone: "zone_1", + Peers: []client.StreamPeer{ + { + Server: "server_1", + }, + }, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + }, + { + name: "Test 2: Fail, Get Stream Upstreams API Action", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusGetStreamUpstreams( + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to get stream upstreams servers"), + upstreams: &client.StreamUpstreams{ + "upstream_1": client.StreamUpstream{ + Zone: "zone_1", + Peers: []client.StreamPeer{ + { + Server: "server_1", + }, + }, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + }, + { + name: "Test 3: Fail, No Instance", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreatAPIActionRequestNginxPlusGetHTTPServers("test_upstream", + protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to preform API action, could not find instance with ID: " + + "e1374cb1-462d-3b6c-9f3b-f28332b5f10c"), + upstreams: &client.StreamUpstreams{ + "upstream_1": client.StreamUpstream{ + Zone: "zone_1", + Peers: []client.StreamPeer{ + { + Server: "server_1", + }, + }, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: inValidInstance, + }, + { + name: "Test 4: Fail, OSS Instance", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreatAPIActionRequestNginxPlusGetHTTPServers("test_upstream", + protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to preform API action, instance is not NGINX Plus"), + upstreams: &client.StreamUpstreams{ + "upstream_1": client.StreamUpstream{ + Zone: "zone_1", + Peers: []client.StreamPeer{ + { + Server: "server_1", + }, + }, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxOssInstance([]string{}), + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + fakeResourceService := &resourcefakes.FakeResourceServiceInterface{} + fakeResourceService.GetStreamUpstreamsReturns(test.upstreams, test.err) + if test.instance.GetInstanceMeta().GetInstanceId() != "e1374cb1-462d-3b6c-9f3b-f28332b5f10f" { + fakeResourceService.InstanceReturns(test.instance) + } + + messagePipe := busfakes.NewFakeMessagePipe() + + resourcePlugin := NewResource(types.AgentConfig()) + resourcePlugin.resourceService = fakeResourceService + + err := messagePipe.Register(2, []bus.Plugin{resourcePlugin}) + require.NoError(t, err) + + resourcePlugin.messagePipe = messagePipe + + resourcePlugin.Process(ctx, test.message) + + assert.Equal(t, test.topic[0], messagePipe.GetMessages()[0].Topic) + + response, ok := messagePipe.GetMessages()[0].Data.(*mpi.DataPlaneResponse) + assert.True(tt, ok) + + if test.err != nil { + assert.Equal(tt, test.err.Error(), response.GetCommandResponse().GetError()) + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_FAILURE, response.GetCommandResponse().GetStatus()) + } else { + assert.Empty(t, response.GetCommandResponse().GetError()) + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_OK, response.GetCommandResponse().GetStatus()) + } + }) + } +} + +// nolint: dupl +func TestResource_Process_APIAction_GetUpstreams(t *testing.T) { + ctx := context.Background() + + inValidInstance := protos.GetNginxPlusInstance([]string{}) + inValidInstance.InstanceMeta.InstanceId = "e1374cb1-462d-3b6c-9f3b-f28332b5f10f" + + tests := []struct { + instance *mpi.Instance + upstreams *client.Upstreams + name string + message *bus.Message + err error + topic []string + }{ + { + name: "Test 1: Success, Get Upstreams API Action", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusGetUpstreams( + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: nil, + upstreams: &client.Upstreams{ + "upstream_1": client.Upstream{ + Zone: "zone_1", + Peers: []client.Peer{ + { + Server: "server_1", + }, + }, + Queue: client.Queue{}, + Keepalive: 6, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + }, + { + name: "Test 2: Fail, Get Upstreams API Action", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreateAPIActionRequestNginxPlusGetUpstreams( + protos.GetNginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to get upstreams"), + upstreams: &client.Upstreams{ + "upstream_1": client.Upstream{ + Zone: "zone_1", + Peers: []client.Peer{ + { + Server: "server_1", + }, + }, + Queue: client.Queue{}, + Keepalive: 6, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxPlusInstance([]string{}), + }, + { + name: "Test 3: Fail, No Instance", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreatAPIActionRequestNginxPlusGetHTTPServers("test_upstream", + protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to preform API action, could not find instance with ID: " + + "e1374cb1-462d-3b6c-9f3b-f28332b5f10c"), + upstreams: &client.Upstreams{ + "upstream_1": client.Upstream{ + Zone: "zone_1", + Peers: []client.Peer{ + { + Server: "server_1", + }, + }, + Queue: client.Queue{}, + Keepalive: 6, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: inValidInstance, + }, + { + name: "Test 4: Fail, OSS Instance", + message: &bus.Message{ + Topic: bus.APIActionRequestTopic, + Data: protos.CreatAPIActionRequestNginxPlusGetHTTPServers("test_upstream", + protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId()), + }, + err: errors.New("failed to preform API action, instance is not NGINX Plus"), + upstreams: &client.Upstreams{ + "upstream_1": client.Upstream{ + Zone: "zone_1", + Peers: []client.Peer{ + { + Server: "server_1", + }, + }, + Queue: client.Queue{}, + Keepalive: 6, + Zombies: 0, + }, + }, + topic: []string{bus.DataPlaneResponseTopic}, + instance: protos.GetNginxOssInstance([]string{}), + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + fakeResourceService := &resourcefakes.FakeResourceServiceInterface{} + fakeResourceService.GetUpstreamsReturns(test.upstreams, test.err) + if test.instance.GetInstanceMeta().GetInstanceId() != "e1374cb1-462d-3b6c-9f3b-f28332b5f10f" { + fakeResourceService.InstanceReturns(test.instance) + } + + messagePipe := busfakes.NewFakeMessagePipe() + + resourcePlugin := NewResource(types.AgentConfig()) + resourcePlugin.resourceService = fakeResourceService + + err := messagePipe.Register(2, []bus.Plugin{resourcePlugin}) + require.NoError(t, err) + + resourcePlugin.messagePipe = messagePipe + + resourcePlugin.Process(ctx, test.message) + + assert.Equal(t, test.topic[0], messagePipe.GetMessages()[0].Topic) + + response, ok := messagePipe.GetMessages()[0].Data.(*mpi.DataPlaneResponse) + assert.True(tt, ok) + + if test.err != nil { + assert.Equal(tt, test.err.Error(), response.GetCommandResponse().GetError()) + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_FAILURE, response.GetCommandResponse().GetStatus()) + } else { + assert.Empty(t, response.GetCommandResponse().GetError()) + assert.Equal(tt, mpi.CommandResponse_COMMAND_STATUS_OK, response.GetCommandResponse().GetStatus()) + } + }) + } +} + func TestResource_Process_Rollback(t *testing.T) { ctx := context.Background() diff --git a/internal/resource/resource_service.go b/internal/resource/resource_service.go index 9325f4c2c..d74836e64 100644 --- a/internal/resource/resource_service.go +++ b/internal/resource/resource_service.go @@ -46,9 +46,14 @@ type resourceServiceInterface interface { DeleteInstances(instanceList []*mpi.Instance) *mpi.Resource ApplyConfig(ctx context.Context, instanceID string) error Instance(instanceID string) *mpi.Instance - GetUpstreams(ctx context.Context, instance *mpi.Instance, upstreams string) ([]client.UpstreamServer, error) - UpdateHTTPUpstreams(ctx context.Context, instance *mpi.Instance, upstream string, + GetHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstreams string) ([]client.UpstreamServer, + error) + UpdateHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstream string, upstreams []*structpb.Struct) (added, updated, deleted []client.UpstreamServer, err error) + GetUpstreams(ctx context.Context, instance *mpi.Instance) (*client.Upstreams, error) + GetStreamUpstreams(ctx context.Context, instance *mpi.Instance) (*client.StreamUpstreams, error) + UpdateStreamServers(ctx context.Context, instance *mpi.Instance, upstream string, + upstreams []*structpb.Struct) (added, updated, deleted []client.StreamUpstreamServer, err error) } type ( @@ -158,6 +163,10 @@ func (r *ResourceService) ApplyConfig(ctx context.Context, instanceID string) er var instance *mpi.Instance operator := r.instanceOperators[instanceID] + if operator == nil { + return fmt.Errorf("instance %s not found", instanceID) + } + for _, resourceInstance := range r.resource.GetInstances() { if resourceInstance.GetInstanceMeta().GetInstanceId() == instanceID { instance = resourceInstance @@ -177,7 +186,7 @@ func (r *ResourceService) ApplyConfig(ctx context.Context, instanceID string) er return nil } -func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instance, +func (r *ResourceService) GetHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstream string, ) ([]client.UpstreamServer, error) { plusClient, err := r.createPlusClient(instance) @@ -188,12 +197,64 @@ func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instan servers, getServersErr := plusClient.GetHTTPServers(ctx, upstream) + slog.Warn("Error returned from NGINX Plus client, GetHTTPUpstreamServers", "err", getServersErr) + return servers, createPlusAPIError(getServersErr) } +func (r *ResourceService) GetUpstreams(ctx context.Context, instance *mpi.Instance, +) (*client.Upstreams, error) { + plusClient, err := r.createPlusClient(instance) + if err != nil { + slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) + return nil, err + } + + servers, getUpstreamsErr := plusClient.GetUpstreams(ctx) + + slog.Warn("Error returned from NGINX Plus client, GetUpstreams", "err", getUpstreamsErr) + + return servers, createPlusAPIError(getUpstreamsErr) +} + +func (r *ResourceService) GetStreamUpstreams(ctx context.Context, instance *mpi.Instance, +) (*client.StreamUpstreams, error) { + plusClient, err := r.createPlusClient(instance) + if err != nil { + slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) + return nil, err + } + + streamUpstreams, getServersErr := plusClient.GetStreamUpstreams(ctx) + + slog.Warn("Error returned from NGINX Plus client, GetStreamUpstreams", "err", getServersErr) + + return streamUpstreams, createPlusAPIError(getServersErr) +} + // max number of returns from function is 3 // nolint: revive -func (r *ResourceService) UpdateHTTPUpstreams(ctx context.Context, instance *mpi.Instance, upstream string, +func (r *ResourceService) UpdateStreamServers(ctx context.Context, instance *mpi.Instance, upstream string, + upstreams []*structpb.Struct, +) (added, updated, deleted []client.StreamUpstreamServer, err error) { + plusClient, err := r.createPlusClient(instance) + if err != nil { + slog.ErrorContext(ctx, "Failed to create plus client ", "error", err) + return nil, nil, nil, err + } + + servers := convertToStreamUpstreamServer(upstreams) + + added, updated, deleted, updateError := plusClient.UpdateStreamServers(ctx, upstream, servers) + + slog.Warn("Error returned from NGINX Plus client, UpdateStreamServers", "err", updateError) + + return added, updated, deleted, createPlusAPIError(updateError) +} + +// max number of returns from function is 3 +// nolint: revive +func (r *ResourceService) UpdateHTTPUpstreamServers(ctx context.Context, instance *mpi.Instance, upstream string, upstreams []*structpb.Struct, ) (added, updated, deleted []client.UpstreamServer, err error) { plusClient, err := r.createPlusClient(instance) @@ -206,6 +267,8 @@ func (r *ResourceService) UpdateHTTPUpstreams(ctx context.Context, instance *mpi added, updated, deleted, updateError := plusClient.UpdateHTTPServers(ctx, upstream, servers) + slog.Warn("Error returned from NGINX Plus client, UpdateHTTPUpstreamServers", "err", updateError) + return added, updated, deleted, createPlusAPIError(updateError) } @@ -223,6 +286,20 @@ func convertToUpstreamServer(upstreams []*structpb.Struct) []client.UpstreamServ return servers } +func convertToStreamUpstreamServer(streamUpstreams []*structpb.Struct) []client.StreamUpstreamServer { + var servers []client.StreamUpstreamServer + res, err := json.Marshal(streamUpstreams) + if err != nil { + slog.Error("Failed to marshal stream upstream server", "error", err, "stream_upstreams", streamUpstreams) + } + err = json.Unmarshal(res, &servers) + if err != nil { + slog.Error("Failed to unmarshal stream upstream server", "error", err, "stream_upstreams", streamUpstreams) + } + + return servers +} + func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.NginxClient, error) { plusAPI := instance.GetInstanceRuntime().GetNginxPlusRuntimeInfo().GetPlusApi() var endpoint string @@ -231,6 +308,7 @@ func (r *ResourceService) createPlusClient(instance *mpi.Instance) (*client.Ngin return nil, errors.New("failed to preform API action, NGINX Plus API is not configured") } + slog.Info("location", "", plusAPI.GetListen()) if strings.HasPrefix(plusAPI.GetListen(), "unix:") { endpoint = fmt.Sprintf(unixPlusAPIFormat, plusAPI.GetLocation()) } else { @@ -288,7 +366,7 @@ func createPlusAPIError(apiErr error) error { plusErr := plusAPIErr{ Error: errResponse{ Status: errorSlice[0], - Test: errorSlice[1], + Text: errorSlice[1], Code: errorSlice[2], }, RequestID: errorSlice[3], diff --git a/internal/resource/resource_service_test.go b/internal/resource/resource_service_test.go index 312995e19..ce9ca4c85 100644 --- a/internal/resource/resource_service_test.go +++ b/internal/resource/resource_service_test.go @@ -147,6 +147,42 @@ func TestResourceService_DeleteInstance(t *testing.T) { } } +func TestResourceService_Instance(t *testing.T) { + ctx := context.Background() + + tests := []struct { + result *v1.Instance + name string + instances []*v1.Instance + }{ + { + name: "Test 1: instance found", + instances: []*v1.Instance{ + protos.GetNginxOssInstance([]string{}), + protos.GetNginxPlusInstance([]string{}), + }, + result: protos.GetNginxPlusInstance([]string{}), + }, + { + name: "Test 2: instance not found", + instances: []*v1.Instance{ + protos.GetNginxOssInstance([]string{}), + }, + result: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + resourceService := NewResourceService(ctx, types.AgentConfig()) + resourceService.resource.Instances = test.instances + instance := resourceService.Instance(protos.GetNginxPlusInstance([]string{}). + GetInstanceMeta().GetInstanceId()) + assert.Equal(tt, test.result, instance) + }) + } +} + func TestResourceService_GetResource(t *testing.T) { ctx := context.Background() @@ -200,8 +236,14 @@ func TestResourceService_GetResource(t *testing.T) { func TestResourceService_createPlusClient(t *testing.T) { instanceWithAPI := protos.GetNginxPlusInstance([]string{}) instanceWithAPI.InstanceRuntime.GetNginxPlusRuntimeInfo().PlusApi = &v1.APIDetails{ - Location: "localhost:80", - Listen: "/api", + Location: "/api", + Listen: "localhost:80", + } + + instanceWithUnixAPI := protos.GetNginxPlusInstance([]string{}) + instanceWithUnixAPI.InstanceRuntime.GetNginxPlusRuntimeInfo().PlusApi = &v1.APIDetails{ + Listen: "unix:/var/run/nginx-status.sock", + Location: "/api", } ctx := context.Background() @@ -216,7 +258,12 @@ func TestResourceService_createPlusClient(t *testing.T) { err: nil, }, { - name: "Test 2: Fail Creating Client - API not Configured", + name: "Test 2: Create Plus Client, Unix", + instance: instanceWithUnixAPI, + err: nil, + }, + { + name: "Test 3: Fail Creating Client - API not Configured", instance: protos.GetNginxPlusInstance([]string{}), err: errors.New("failed to preform API action, NGINX Plus API is not configured"), }, @@ -240,6 +287,7 @@ func TestResourceService_ApplyConfig(t *testing.T) { ctx := context.Background() tests := []struct { + instanceID string reloadErr error validateErr error expected error @@ -247,22 +295,32 @@ func TestResourceService_ApplyConfig(t *testing.T) { }{ { name: "Test 1: Successful reload", + instanceID: protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId(), reloadErr: nil, validateErr: nil, expected: nil, }, { name: "Test 2: Failed reload", + instanceID: protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId(), reloadErr: fmt.Errorf("something went wrong"), validateErr: nil, expected: fmt.Errorf("failed to reload NGINX %w", fmt.Errorf("something went wrong")), }, { name: "Test 3: Failed validate", + instanceID: protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId(), reloadErr: nil, validateErr: fmt.Errorf("something went wrong"), expected: fmt.Errorf("failed validating config %w", fmt.Errorf("something went wrong")), }, + { + name: "Test 4: Unknown instance ID", + instanceID: "unknown", + reloadErr: nil, + validateErr: nil, + expected: fmt.Errorf("instance unknown not found"), + }, } for _, test := range tests { @@ -283,13 +341,13 @@ func TestResourceService_ApplyConfig(t *testing.T) { } resourceService.resource.Instances = instances - reloadError := resourceService.ApplyConfig(ctx, - protos.GetNginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId()) + reloadError := resourceService.ApplyConfig(ctx, test.instanceID) assert.Equal(t, test.expected, reloadError) }) } } +// nolint: dupl func Test_convertToUpstreamServer(t *testing.T) { expectedMax := 2 expectedFails := 0 @@ -331,3 +389,46 @@ func Test_convertToUpstreamServer(t *testing.T) { result := convertToUpstreamServer(test) assert.Equal(t, expected, result) } + +// nolint: dupl +func Test_convertToStreamUpstreamServer(t *testing.T) { + expectedMax := 2 + expectedFails := 0 + expectedBackup := true + expected := []client.StreamUpstreamServer{ + { + MaxConns: &expectedMax, + MaxFails: &expectedFails, + Backup: &expectedBackup, + Server: "test_server", + }, + { + MaxConns: &expectedMax, + MaxFails: &expectedFails, + Backup: &expectedBackup, + Server: "test_server2", + }, + } + + test := []*structpb.Struct{ + { + Fields: map[string]*structpb.Value{ + "max_conns": structpb.NewNumberValue(2), + "max_fails": structpb.NewNumberValue(0), + "backup": structpb.NewBoolValue(expectedBackup), + "server": structpb.NewStringValue("test_server"), + }, + }, + { + Fields: map[string]*structpb.Value{ + "max_conns": structpb.NewNumberValue(2), + "max_fails": structpb.NewNumberValue(0), + "backup": structpb.NewBoolValue(expectedBackup), + "server": structpb.NewStringValue("test_server2"), + }, + }, + } + + result := convertToStreamUpstreamServer(test) + assert.Equal(t, expected, result) +} diff --git a/internal/resource/resourcefakes/fake_resource_service_interface.go b/internal/resource/resourcefakes/fake_resource_service_interface.go index 1c17dc332..a6bc3985c 100644 --- a/internal/resource/resourcefakes/fake_resource_service_interface.go +++ b/internal/resource/resourcefakes/fake_resource_service_interface.go @@ -45,19 +45,47 @@ type FakeResourceServiceInterface struct { deleteInstancesReturnsOnCall map[int]struct { result1 *v1.Resource } - GetUpstreamsStub func(context.Context, *v1.Instance, string) ([]client.UpstreamServer, error) + GetHTTPUpstreamServersStub func(context.Context, *v1.Instance, string) ([]client.UpstreamServer, error) + getHTTPUpstreamServersMutex sync.RWMutex + getHTTPUpstreamServersArgsForCall []struct { + arg1 context.Context + arg2 *v1.Instance + arg3 string + } + getHTTPUpstreamServersReturns struct { + result1 []client.UpstreamServer + result2 error + } + getHTTPUpstreamServersReturnsOnCall map[int]struct { + result1 []client.UpstreamServer + result2 error + } + GetStreamUpstreamsStub func(context.Context, *v1.Instance) (*client.StreamUpstreams, error) + getStreamUpstreamsMutex sync.RWMutex + getStreamUpstreamsArgsForCall []struct { + arg1 context.Context + arg2 *v1.Instance + } + getStreamUpstreamsReturns struct { + result1 *client.StreamUpstreams + result2 error + } + getStreamUpstreamsReturnsOnCall map[int]struct { + result1 *client.StreamUpstreams + result2 error + } + GetUpstreamsStub func(context.Context, *v1.Instance) (*client.Upstreams, error) getUpstreamsMutex sync.RWMutex getUpstreamsArgsForCall []struct { arg1 context.Context arg2 *v1.Instance - arg3 string } getUpstreamsReturns struct { - result1 []client.UpstreamServer + result1 *client.Upstreams result2 error } getUpstreamsReturnsOnCall map[int]struct { - result1 []client.UpstreamServer + result1 *client.Upstreams result2 error } InstanceStub func(string) *v1.Instance @@ -71,21 +99,21 @@ type FakeResourceServiceInterface struct { instanceReturnsOnCall map[int]struct { result1 *v1.Instance } - UpdateHTTPUpstreamsStub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error) - updateHTTPUpstreamsMutex sync.RWMutex - updateHTTPUpstreamsArgsForCall []struct { + UpdateHTTPUpstreamServersStub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error) + updateHTTPUpstreamServersMutex sync.RWMutex + updateHTTPUpstreamServersArgsForCall []struct { arg1 context.Context arg2 *v1.Instance arg3 string arg4 []*structpb.Struct } - updateHTTPUpstreamsReturns struct { + updateHTTPUpstreamServersReturns struct { result1 []client.UpstreamServer result2 []client.UpstreamServer result3 []client.UpstreamServer result4 error } - updateHTTPUpstreamsReturnsOnCall map[int]struct { + updateHTTPUpstreamServersReturnsOnCall map[int]struct { result1 []client.UpstreamServer result2 []client.UpstreamServer result3 []client.UpstreamServer @@ -102,6 +130,26 @@ type FakeResourceServiceInterface struct { updateInstancesReturnsOnCall map[int]struct { result1 *v1.Resource } + UpdateStreamServersStub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.StreamUpstreamServer, []client.StreamUpstreamServer, []client.StreamUpstreamServer, error) + updateStreamServersMutex sync.RWMutex + updateStreamServersArgsForCall []struct { + arg1 context.Context + arg2 *v1.Instance + arg3 string + arg4 []*structpb.Struct + } + updateStreamServersReturns struct { + result1 []client.StreamUpstreamServer + result2 []client.StreamUpstreamServer + result3 []client.StreamUpstreamServer + result4 error + } + updateStreamServersReturnsOnCall map[int]struct { + result1 []client.StreamUpstreamServer + result2 []client.StreamUpstreamServer + result3 []client.StreamUpstreamServer + result4 error + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -300,20 +348,150 @@ func (fake *FakeResourceServiceInterface) DeleteInstancesReturnsOnCall(i int, re }{result1} } -func (fake *FakeResourceServiceInterface) GetUpstreams(arg1 context.Context, arg2 *v1.Instance, arg3 string) ([]client.UpstreamServer, error) { +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServers(arg1 context.Context, arg2 *v1.Instance, arg3 string) ([]client.UpstreamServer, error) { + fake.getHTTPUpstreamServersMutex.Lock() + ret, specificReturn := fake.getHTTPUpstreamServersReturnsOnCall[len(fake.getHTTPUpstreamServersArgsForCall)] + fake.getHTTPUpstreamServersArgsForCall = append(fake.getHTTPUpstreamServersArgsForCall, struct { + arg1 context.Context + arg2 *v1.Instance + arg3 string + }{arg1, arg2, arg3}) + stub := fake.GetHTTPUpstreamServersStub + fakeReturns := fake.getHTTPUpstreamServersReturns + fake.recordInvocation("GetHTTPUpstreamServers", []interface{}{arg1, arg2, arg3}) + fake.getHTTPUpstreamServersMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServersCallCount() int { + fake.getHTTPUpstreamServersMutex.RLock() + defer fake.getHTTPUpstreamServersMutex.RUnlock() + return len(fake.getHTTPUpstreamServersArgsForCall) +} + +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServersCalls(stub func(context.Context, *v1.Instance, string) ([]client.UpstreamServer, error)) { + fake.getHTTPUpstreamServersMutex.Lock() + defer fake.getHTTPUpstreamServersMutex.Unlock() + fake.GetHTTPUpstreamServersStub = stub +} + +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServersArgsForCall(i int) (context.Context, *v1.Instance, string) { + fake.getHTTPUpstreamServersMutex.RLock() + defer fake.getHTTPUpstreamServersMutex.RUnlock() + argsForCall := fake.getHTTPUpstreamServersArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServersReturns(result1 []client.UpstreamServer, result2 error) { + fake.getHTTPUpstreamServersMutex.Lock() + defer fake.getHTTPUpstreamServersMutex.Unlock() + fake.GetHTTPUpstreamServersStub = nil + fake.getHTTPUpstreamServersReturns = struct { + result1 []client.UpstreamServer + result2 error + }{result1, result2} +} + +func (fake *FakeResourceServiceInterface) GetHTTPUpstreamServersReturnsOnCall(i int, result1 []client.UpstreamServer, result2 error) { + fake.getHTTPUpstreamServersMutex.Lock() + defer fake.getHTTPUpstreamServersMutex.Unlock() + fake.GetHTTPUpstreamServersStub = nil + if fake.getHTTPUpstreamServersReturnsOnCall == nil { + fake.getHTTPUpstreamServersReturnsOnCall = make(map[int]struct { + result1 []client.UpstreamServer + result2 error + }) + } + fake.getHTTPUpstreamServersReturnsOnCall[i] = struct { + result1 []client.UpstreamServer + result2 error + }{result1, result2} +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreams(arg1 context.Context, arg2 *v1.Instance) (*client.StreamUpstreams, error) { + fake.getStreamUpstreamsMutex.Lock() + ret, specificReturn := fake.getStreamUpstreamsReturnsOnCall[len(fake.getStreamUpstreamsArgsForCall)] + fake.getStreamUpstreamsArgsForCall = append(fake.getStreamUpstreamsArgsForCall, struct { + arg1 context.Context + arg2 *v1.Instance + }{arg1, arg2}) + stub := fake.GetStreamUpstreamsStub + fakeReturns := fake.getStreamUpstreamsReturns + fake.recordInvocation("GetStreamUpstreams", []interface{}{arg1, arg2}) + fake.getStreamUpstreamsMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreamsCallCount() int { + fake.getStreamUpstreamsMutex.RLock() + defer fake.getStreamUpstreamsMutex.RUnlock() + return len(fake.getStreamUpstreamsArgsForCall) +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreamsCalls(stub func(context.Context, *v1.Instance) (*client.StreamUpstreams, error)) { + fake.getStreamUpstreamsMutex.Lock() + defer fake.getStreamUpstreamsMutex.Unlock() + fake.GetStreamUpstreamsStub = stub +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreamsArgsForCall(i int) (context.Context, *v1.Instance) { + fake.getStreamUpstreamsMutex.RLock() + defer fake.getStreamUpstreamsMutex.RUnlock() + argsForCall := fake.getStreamUpstreamsArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreamsReturns(result1 *client.StreamUpstreams, result2 error) { + fake.getStreamUpstreamsMutex.Lock() + defer fake.getStreamUpstreamsMutex.Unlock() + fake.GetStreamUpstreamsStub = nil + fake.getStreamUpstreamsReturns = struct { + result1 *client.StreamUpstreams + result2 error + }{result1, result2} +} + +func (fake *FakeResourceServiceInterface) GetStreamUpstreamsReturnsOnCall(i int, result1 *client.StreamUpstreams, result2 error) { + fake.getStreamUpstreamsMutex.Lock() + defer fake.getStreamUpstreamsMutex.Unlock() + fake.GetStreamUpstreamsStub = nil + if fake.getStreamUpstreamsReturnsOnCall == nil { + fake.getStreamUpstreamsReturnsOnCall = make(map[int]struct { + result1 *client.StreamUpstreams + result2 error + }) + } + fake.getStreamUpstreamsReturnsOnCall[i] = struct { + result1 *client.StreamUpstreams + result2 error + }{result1, result2} +} + +func (fake *FakeResourceServiceInterface) GetUpstreams(arg1 context.Context, arg2 *v1.Instance) (*client.Upstreams, error) { fake.getUpstreamsMutex.Lock() ret, specificReturn := fake.getUpstreamsReturnsOnCall[len(fake.getUpstreamsArgsForCall)] fake.getUpstreamsArgsForCall = append(fake.getUpstreamsArgsForCall, struct { arg1 context.Context arg2 *v1.Instance - arg3 string - }{arg1, arg2, arg3}) + }{arg1, arg2}) stub := fake.GetUpstreamsStub fakeReturns := fake.getUpstreamsReturns - fake.recordInvocation("GetUpstreams", []interface{}{arg1, arg2, arg3}) + fake.recordInvocation("GetUpstreams", []interface{}{arg1, arg2}) fake.getUpstreamsMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3) + return stub(arg1, arg2) } if specificReturn { return ret.result1, ret.result2 @@ -327,41 +505,41 @@ func (fake *FakeResourceServiceInterface) GetUpstreamsCallCount() int { return len(fake.getUpstreamsArgsForCall) } -func (fake *FakeResourceServiceInterface) GetUpstreamsCalls(stub func(context.Context, *v1.Instance, string) ([]client.UpstreamServer, error)) { +func (fake *FakeResourceServiceInterface) GetUpstreamsCalls(stub func(context.Context, *v1.Instance) (*client.Upstreams, error)) { fake.getUpstreamsMutex.Lock() defer fake.getUpstreamsMutex.Unlock() fake.GetUpstreamsStub = stub } -func (fake *FakeResourceServiceInterface) GetUpstreamsArgsForCall(i int) (context.Context, *v1.Instance, string) { +func (fake *FakeResourceServiceInterface) GetUpstreamsArgsForCall(i int) (context.Context, *v1.Instance) { fake.getUpstreamsMutex.RLock() defer fake.getUpstreamsMutex.RUnlock() argsForCall := fake.getUpstreamsArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 + return argsForCall.arg1, argsForCall.arg2 } -func (fake *FakeResourceServiceInterface) GetUpstreamsReturns(result1 []client.UpstreamServer, result2 error) { +func (fake *FakeResourceServiceInterface) GetUpstreamsReturns(result1 *client.Upstreams, result2 error) { fake.getUpstreamsMutex.Lock() defer fake.getUpstreamsMutex.Unlock() fake.GetUpstreamsStub = nil fake.getUpstreamsReturns = struct { - result1 []client.UpstreamServer + result1 *client.Upstreams result2 error }{result1, result2} } -func (fake *FakeResourceServiceInterface) GetUpstreamsReturnsOnCall(i int, result1 []client.UpstreamServer, result2 error) { +func (fake *FakeResourceServiceInterface) GetUpstreamsReturnsOnCall(i int, result1 *client.Upstreams, result2 error) { fake.getUpstreamsMutex.Lock() defer fake.getUpstreamsMutex.Unlock() fake.GetUpstreamsStub = nil if fake.getUpstreamsReturnsOnCall == nil { fake.getUpstreamsReturnsOnCall = make(map[int]struct { - result1 []client.UpstreamServer + result1 *client.Upstreams result2 error }) } fake.getUpstreamsReturnsOnCall[i] = struct { - result1 []client.UpstreamServer + result1 *client.Upstreams result2 error }{result1, result2} } @@ -427,24 +605,24 @@ func (fake *FakeResourceServiceInterface) InstanceReturnsOnCall(i int, result1 * }{result1} } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreams(arg1 context.Context, arg2 *v1.Instance, arg3 string, arg4 []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error) { +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServers(arg1 context.Context, arg2 *v1.Instance, arg3 string, arg4 []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error) { var arg4Copy []*structpb.Struct if arg4 != nil { arg4Copy = make([]*structpb.Struct, len(arg4)) copy(arg4Copy, arg4) } - fake.updateHTTPUpstreamsMutex.Lock() - ret, specificReturn := fake.updateHTTPUpstreamsReturnsOnCall[len(fake.updateHTTPUpstreamsArgsForCall)] - fake.updateHTTPUpstreamsArgsForCall = append(fake.updateHTTPUpstreamsArgsForCall, struct { + fake.updateHTTPUpstreamServersMutex.Lock() + ret, specificReturn := fake.updateHTTPUpstreamServersReturnsOnCall[len(fake.updateHTTPUpstreamServersArgsForCall)] + fake.updateHTTPUpstreamServersArgsForCall = append(fake.updateHTTPUpstreamServersArgsForCall, struct { arg1 context.Context arg2 *v1.Instance arg3 string arg4 []*structpb.Struct }{arg1, arg2, arg3, arg4Copy}) - stub := fake.UpdateHTTPUpstreamsStub - fakeReturns := fake.updateHTTPUpstreamsReturns - fake.recordInvocation("UpdateHTTPUpstreams", []interface{}{arg1, arg2, arg3, arg4Copy}) - fake.updateHTTPUpstreamsMutex.Unlock() + stub := fake.UpdateHTTPUpstreamServersStub + fakeReturns := fake.updateHTTPUpstreamServersReturns + fake.recordInvocation("UpdateHTTPUpstreamServers", []interface{}{arg1, arg2, arg3, arg4Copy}) + fake.updateHTTPUpstreamServersMutex.Unlock() if stub != nil { return stub(arg1, arg2, arg3, arg4) } @@ -454,30 +632,30 @@ func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreams(arg1 context.Conte return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3, fakeReturns.result4 } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsCallCount() int { - fake.updateHTTPUpstreamsMutex.RLock() - defer fake.updateHTTPUpstreamsMutex.RUnlock() - return len(fake.updateHTTPUpstreamsArgsForCall) +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServersCallCount() int { + fake.updateHTTPUpstreamServersMutex.RLock() + defer fake.updateHTTPUpstreamServersMutex.RUnlock() + return len(fake.updateHTTPUpstreamServersArgsForCall) } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsCalls(stub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error)) { - fake.updateHTTPUpstreamsMutex.Lock() - defer fake.updateHTTPUpstreamsMutex.Unlock() - fake.UpdateHTTPUpstreamsStub = stub +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServersCalls(stub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.UpstreamServer, []client.UpstreamServer, []client.UpstreamServer, error)) { + fake.updateHTTPUpstreamServersMutex.Lock() + defer fake.updateHTTPUpstreamServersMutex.Unlock() + fake.UpdateHTTPUpstreamServersStub = stub } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsArgsForCall(i int) (context.Context, *v1.Instance, string, []*structpb.Struct) { - fake.updateHTTPUpstreamsMutex.RLock() - defer fake.updateHTTPUpstreamsMutex.RUnlock() - argsForCall := fake.updateHTTPUpstreamsArgsForCall[i] +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServersArgsForCall(i int) (context.Context, *v1.Instance, string, []*structpb.Struct) { + fake.updateHTTPUpstreamServersMutex.RLock() + defer fake.updateHTTPUpstreamServersMutex.RUnlock() + argsForCall := fake.updateHTTPUpstreamServersArgsForCall[i] return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsReturns(result1 []client.UpstreamServer, result2 []client.UpstreamServer, result3 []client.UpstreamServer, result4 error) { - fake.updateHTTPUpstreamsMutex.Lock() - defer fake.updateHTTPUpstreamsMutex.Unlock() - fake.UpdateHTTPUpstreamsStub = nil - fake.updateHTTPUpstreamsReturns = struct { +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServersReturns(result1 []client.UpstreamServer, result2 []client.UpstreamServer, result3 []client.UpstreamServer, result4 error) { + fake.updateHTTPUpstreamServersMutex.Lock() + defer fake.updateHTTPUpstreamServersMutex.Unlock() + fake.UpdateHTTPUpstreamServersStub = nil + fake.updateHTTPUpstreamServersReturns = struct { result1 []client.UpstreamServer result2 []client.UpstreamServer result3 []client.UpstreamServer @@ -485,19 +663,19 @@ func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsReturns(result1 []c }{result1, result2, result3, result4} } -func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamsReturnsOnCall(i int, result1 []client.UpstreamServer, result2 []client.UpstreamServer, result3 []client.UpstreamServer, result4 error) { - fake.updateHTTPUpstreamsMutex.Lock() - defer fake.updateHTTPUpstreamsMutex.Unlock() - fake.UpdateHTTPUpstreamsStub = nil - if fake.updateHTTPUpstreamsReturnsOnCall == nil { - fake.updateHTTPUpstreamsReturnsOnCall = make(map[int]struct { +func (fake *FakeResourceServiceInterface) UpdateHTTPUpstreamServersReturnsOnCall(i int, result1 []client.UpstreamServer, result2 []client.UpstreamServer, result3 []client.UpstreamServer, result4 error) { + fake.updateHTTPUpstreamServersMutex.Lock() + defer fake.updateHTTPUpstreamServersMutex.Unlock() + fake.UpdateHTTPUpstreamServersStub = nil + if fake.updateHTTPUpstreamServersReturnsOnCall == nil { + fake.updateHTTPUpstreamServersReturnsOnCall = make(map[int]struct { result1 []client.UpstreamServer result2 []client.UpstreamServer result3 []client.UpstreamServer result4 error }) } - fake.updateHTTPUpstreamsReturnsOnCall[i] = struct { + fake.updateHTTPUpstreamServersReturnsOnCall[i] = struct { result1 []client.UpstreamServer result2 []client.UpstreamServer result3 []client.UpstreamServer @@ -571,6 +749,84 @@ func (fake *FakeResourceServiceInterface) UpdateInstancesReturnsOnCall(i int, re }{result1} } +func (fake *FakeResourceServiceInterface) UpdateStreamServers(arg1 context.Context, arg2 *v1.Instance, arg3 string, arg4 []*structpb.Struct) ([]client.StreamUpstreamServer, []client.StreamUpstreamServer, []client.StreamUpstreamServer, error) { + var arg4Copy []*structpb.Struct + if arg4 != nil { + arg4Copy = make([]*structpb.Struct, len(arg4)) + copy(arg4Copy, arg4) + } + fake.updateStreamServersMutex.Lock() + ret, specificReturn := fake.updateStreamServersReturnsOnCall[len(fake.updateStreamServersArgsForCall)] + fake.updateStreamServersArgsForCall = append(fake.updateStreamServersArgsForCall, struct { + arg1 context.Context + arg2 *v1.Instance + arg3 string + arg4 []*structpb.Struct + }{arg1, arg2, arg3, arg4Copy}) + stub := fake.UpdateStreamServersStub + fakeReturns := fake.updateStreamServersReturns + fake.recordInvocation("UpdateStreamServers", []interface{}{arg1, arg2, arg3, arg4Copy}) + fake.updateStreamServersMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3, ret.result4 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3, fakeReturns.result4 +} + +func (fake *FakeResourceServiceInterface) UpdateStreamServersCallCount() int { + fake.updateStreamServersMutex.RLock() + defer fake.updateStreamServersMutex.RUnlock() + return len(fake.updateStreamServersArgsForCall) +} + +func (fake *FakeResourceServiceInterface) UpdateStreamServersCalls(stub func(context.Context, *v1.Instance, string, []*structpb.Struct) ([]client.StreamUpstreamServer, []client.StreamUpstreamServer, []client.StreamUpstreamServer, error)) { + fake.updateStreamServersMutex.Lock() + defer fake.updateStreamServersMutex.Unlock() + fake.UpdateStreamServersStub = stub +} + +func (fake *FakeResourceServiceInterface) UpdateStreamServersArgsForCall(i int) (context.Context, *v1.Instance, string, []*structpb.Struct) { + fake.updateStreamServersMutex.RLock() + defer fake.updateStreamServersMutex.RUnlock() + argsForCall := fake.updateStreamServersArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeResourceServiceInterface) UpdateStreamServersReturns(result1 []client.StreamUpstreamServer, result2 []client.StreamUpstreamServer, result3 []client.StreamUpstreamServer, result4 error) { + fake.updateStreamServersMutex.Lock() + defer fake.updateStreamServersMutex.Unlock() + fake.UpdateStreamServersStub = nil + fake.updateStreamServersReturns = struct { + result1 []client.StreamUpstreamServer + result2 []client.StreamUpstreamServer + result3 []client.StreamUpstreamServer + result4 error + }{result1, result2, result3, result4} +} + +func (fake *FakeResourceServiceInterface) UpdateStreamServersReturnsOnCall(i int, result1 []client.StreamUpstreamServer, result2 []client.StreamUpstreamServer, result3 []client.StreamUpstreamServer, result4 error) { + fake.updateStreamServersMutex.Lock() + defer fake.updateStreamServersMutex.Unlock() + fake.UpdateStreamServersStub = nil + if fake.updateStreamServersReturnsOnCall == nil { + fake.updateStreamServersReturnsOnCall = make(map[int]struct { + result1 []client.StreamUpstreamServer + result2 []client.StreamUpstreamServer + result3 []client.StreamUpstreamServer + result4 error + }) + } + fake.updateStreamServersReturnsOnCall[i] = struct { + result1 []client.StreamUpstreamServer + result2 []client.StreamUpstreamServer + result3 []client.StreamUpstreamServer + result4 error + }{result1, result2, result3, result4} +} + func (fake *FakeResourceServiceInterface) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() @@ -580,14 +836,20 @@ func (fake *FakeResourceServiceInterface) Invocations() map[string][][]interface defer fake.applyConfigMutex.RUnlock() fake.deleteInstancesMutex.RLock() defer fake.deleteInstancesMutex.RUnlock() + fake.getHTTPUpstreamServersMutex.RLock() + defer fake.getHTTPUpstreamServersMutex.RUnlock() + fake.getStreamUpstreamsMutex.RLock() + defer fake.getStreamUpstreamsMutex.RUnlock() fake.getUpstreamsMutex.RLock() defer fake.getUpstreamsMutex.RUnlock() fake.instanceMutex.RLock() defer fake.instanceMutex.RUnlock() - fake.updateHTTPUpstreamsMutex.RLock() - defer fake.updateHTTPUpstreamsMutex.RUnlock() + fake.updateHTTPUpstreamServersMutex.RLock() + defer fake.updateHTTPUpstreamServersMutex.RUnlock() fake.updateInstancesMutex.RLock() defer fake.updateInstancesMutex.RUnlock() + fake.updateStreamServersMutex.RLock() + defer fake.updateStreamServersMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/internal/watcher/instance/instance_watcher_service.go b/internal/watcher/instance/instance_watcher_service.go index fb64ecdc3..523ad704a 100644 --- a/internal/watcher/instance/instance_watcher_service.go +++ b/internal/watcher/instance/instance_watcher_service.go @@ -19,7 +19,6 @@ import ( "github.com/nginx/agent/v3/internal/logger" "github.com/nginx/agent/v3/internal/model" "github.com/nginx/agent/v3/internal/watcher/process" - "google.golang.org/protobuf/types/known/structpb" ) const defaultAgentPath = "/run/nginx-agent" @@ -285,6 +284,11 @@ func (iw *InstanceWatcherService) agentInstance(ctx context.Context) *mpi.Instan slog.WarnContext(ctx, "Unable to read process location, defaulting to /var/run/nginx-agent", "error", err) } + labels, convertErr := mpi.ConvertToStructs(iw.agentConfig.Labels) + if convertErr != nil { + slog.WarnContext(ctx, "Unable to convert config to labels structure", "error", convertErr) + } + return &mpi.Instance{ InstanceMeta: &mpi.InstanceMeta{ InstanceId: iw.agentConfig.UUID, @@ -298,7 +302,7 @@ func (iw *InstanceWatcherService) agentInstance(ctx context.Context) *mpi.Instan Command: config.ToCommandProto(iw.agentConfig.Command), Metrics: &mpi.MetricsServer{}, File: &mpi.FileServer{}, - Labels: []*structpb.Struct{}, + Labels: labels, Features: iw.agentConfig.Features, MessageBufferSize: "", }, diff --git a/test/helpers/nginx_plus.go b/test/helpers/nginx_plus.go index 0384b9b9f..62be2956e 100644 --- a/test/helpers/nginx_plus.go +++ b/test/helpers/nginx_plus.go @@ -511,3 +511,26 @@ func CreateNginxPlusUpstreamServer(t *testing.T) client.UpstreamServer { Drain: false, } } + +func CreateNginxPlusStreamServer(t *testing.T) client.StreamUpstreamServer { + t.Helper() + + maxConns := 10 + maxFails := 2 + weight := 0 + down := false + backup := true + + return client.StreamUpstreamServer{ + MaxConns: &maxConns, + MaxFails: &maxFails, + Backup: &backup, + Down: &down, + Weight: &weight, + Server: "test_server", + FailTimeout: "", + SlowStart: "", + Service: "", + ID: serverID, + } +} diff --git a/test/integration/grpc_management_plane_api_test.go b/test/integration/grpc_management_plane_api_test.go index dd4a4b19b..b2936c19e 100644 --- a/test/integration/grpc_management_plane_api_test.go +++ b/test/integration/grpc_management_plane_api_test.go @@ -207,6 +207,11 @@ func TestGrpc_ConfigUpload(t *testing.T) { nginxInstanceID := verifyConnection(t, 2) assert.False(t, t.Failed()) + responses := getManagementPlaneResponses(t, 1) + + assert.Equal(t, mpi.CommandResponse_COMMAND_STATUS_OK, responses[0].GetCommandResponse().GetStatus()) + assert.Equal(t, "Successfully updated all files", responses[0].GetCommandResponse().GetMessage()) + request := fmt.Sprintf(`{ "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", @@ -214,10 +219,16 @@ func TestGrpc_ConfigUpload(t *testing.T) { "timestamp": "2023-01-15T01:30:15.01Z" }, "config_upload_request": { - "instance_id": "%s" + "overview" : { + "config_version": { + "instance_id": "%s" + } + } } }`, nginxInstanceID) + t.Logf("Sending config upload request: %s", request) + client := resty.New() client.SetRetryCount(retryCount).SetRetryWaitTime(retryWaitTime).SetRetryMaxWaitTime(retryMaxWaitTime) @@ -227,7 +238,7 @@ func TestGrpc_ConfigUpload(t *testing.T) { require.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode()) - responses := getManagementPlaneResponses(t, 2) + responses = getManagementPlaneResponses(t, 2) assert.Equal(t, mpi.CommandResponse_COMMAND_STATUS_OK, responses[0].GetCommandResponse().GetStatus()) assert.Equal(t, "Successfully updated all files", responses[0].GetCommandResponse().GetMessage()) diff --git a/test/mock/grpc/README.md b/test/mock/grpc/README.md index d45069315..7272f5457 100644 --- a/test/mock/grpc/README.md +++ b/test/mock/grpc/README.md @@ -279,9 +279,11 @@ Example response: } ] ``` + ## POST /api/v1/requests -Used to send management plane requests over the Subscribe rpc stream to the NGINX Agent. \ -Example request body: +Used to send management plane requests over the Subscribe rpc stream to the NGINX Agent. + +Example request body to health request: ``` { "message_meta": { @@ -292,6 +294,123 @@ Example request body: "health_request": {} } ``` + +Example request body to get HTTP upstream servers example: +``` +{ + "message_meta": { + "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", + "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", + "timestamp": "2023-01-15T01:30:15.01Z" + }, + "action_request": { + "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", + "nginx_plus_action": { + "get_http_upstream_servers": { + "http_upstream_name": "nginx1" + } + } + } +} +``` + +Example request body to update HTTP upstream servers example: +``` +{ + "message_meta": { + "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", + "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", + "timestamp": "2023-01-15T01:30:15.01Z" + }, + "action_request": { + "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", + "nginx_plus_action": { + "update_http_upstream_servers": { + "http_upstream_name": "nginx1", + "servers": [ + { + "max_conns": 0, + "max_fails": 3, + "backup": false, + "down": false, + "weight": 1, + "server": "127.0.0.1:9081", + "fail_timeout": "10s", + "slow_start": "0s" + } + ] + } + } + } +} +``` + +Example request body to update upstream stream servers example: +``` +{ + "message_meta": { + "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", + "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", + "timestamp": "2023-01-15T01:30:15.01Z" + }, + "action_request": { + "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", + "nginx_plus_action": { + "update_stream_servers": { + "upstream_stream_name": "stream_backend", + "servers": [ + { + "id" : 0, + "server" : "10.0.0.1:12348", + "weight" : 1, + "max_conns" : 0, + "max_fails" : 1, + "fail_timeout" : "10s", + "slow_start" : 0, + "backup" : false, + "down" : false + } + ] + } + } + } +} +``` + +Example request body to get upstreams example: +``` +{ + "message_meta": { + "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", + "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", + "timestamp": "2023-01-15T01:30:15.01Z" + }, + "action_request": { + "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", + "nginx_plus_action": { + "get_upstreams": {} + } + } +} +``` + +Example request body to get stream upstreams example: +``` +{ + "message_meta": { + "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", + "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", + "timestamp": "2023-01-15T01:30:15.01Z" + }, + "action_request": { + "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", + "nginx_plus_action": { + "get_stream_upstreams": {} + } + } +} +``` + ## POST /api/v1/instance/\/config/apply Used to send management plane config apply request over the Subscribe rpc stream to the NGINX Agent for a particular data plane instance. diff --git a/test/mock/grpc/mock_management_command_service.go b/test/mock/grpc/mock_management_command_service.go index ce9abd24e..f6df717a6 100644 --- a/test/mock/grpc/mock_management_command_service.go +++ b/test/mock/grpc/mock_management_command_service.go @@ -334,7 +334,7 @@ func (cs *CommandService) addResponseAndRequestEndpoints() { return } - pb := protojson.UnmarshalOptions{DiscardUnknown: true} + pb := protojson.UnmarshalOptions{DiscardUnknown: true, AllowPartial: true} err = pb.Unmarshal(body, &request) if err != nil { slog.Error("Error unmarshalling request body", "err", err) diff --git a/test/mock/grpc/mock_management_file_service.go b/test/mock/grpc/mock_management_file_service.go index 4a5485a41..b7352edb2 100644 --- a/test/mock/grpc/mock_management_file_service.go +++ b/test/mock/grpc/mock_management_file_service.go @@ -82,7 +82,7 @@ func (mgs *FileService) UpdateOverview( }, Request: &v1.ManagementPlaneRequest_ConfigUploadRequest{ ConfigUploadRequest: &v1.ConfigUploadRequest{ - Overview: request.GetOverview(), + Overview: overview, }, }, } diff --git a/test/protos/management_plane_request.go b/test/protos/management_plane_request.go index 71232f8eb..d128f1010 100644 --- a/test/protos/management_plane_request.go +++ b/test/protos/management_plane_request.go @@ -42,6 +42,42 @@ func CreatAPIActionRequestNginxPlusGetHTTPServers(upstream, instanceID string) * } } +func CreateAPIActionRequestNginxPlusGetUpstreams(instanceID string) *mpi.ManagementPlaneRequest { + return &mpi.ManagementPlaneRequest{ + MessageMeta: CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ActionRequest{ + ActionRequest: &mpi.APIActionRequest{ + InstanceId: instanceID, + Action: &mpi.APIActionRequest_NginxPlusAction{ + NginxPlusAction: &mpi.NGINXPlusAction{ + Action: &mpi.NGINXPlusAction_GetUpstreams{ + GetUpstreams: &mpi.GetUpstreams{}, + }, + }, + }, + }, + }, + } +} + +func CreateAPIActionRequestNginxPlusGetStreamUpstreams(instanceID string) *mpi.ManagementPlaneRequest { + return &mpi.ManagementPlaneRequest{ + MessageMeta: CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ActionRequest{ + ActionRequest: &mpi.APIActionRequest{ + InstanceId: instanceID, + Action: &mpi.APIActionRequest_NginxPlusAction{ + NginxPlusAction: &mpi.NGINXPlusAction{ + Action: &mpi.NGINXPlusAction_GetStreamUpstreams{ + GetStreamUpstreams: &mpi.GetStreamUpstreams{}, + }, + }, + }, + }, + }, + } +} + func CreatAPIActionRequestNginxPlusUpdateHTTPServers(upstream, instanceID string, servers []*structpb.Struct, ) *mpi.ManagementPlaneRequest { @@ -64,3 +100,26 @@ func CreatAPIActionRequestNginxPlusUpdateHTTPServers(upstream, instanceID string }, } } + +func CreateAPIActionRequestNginxPlusUpdateStreamServers(upstream, instanceID string, + servers []*structpb.Struct, +) *mpi.ManagementPlaneRequest { + return &mpi.ManagementPlaneRequest{ + MessageMeta: CreateMessageMeta(), + Request: &mpi.ManagementPlaneRequest_ActionRequest{ + ActionRequest: &mpi.APIActionRequest{ + InstanceId: instanceID, + Action: &mpi.APIActionRequest_NginxPlusAction{ + NginxPlusAction: &mpi.NGINXPlusAction{ + Action: &mpi.NGINXPlusAction_UpdateStreamServers{ + UpdateStreamServers: &mpi.UpdateStreamServers{ + Servers: servers, + UpstreamStreamName: upstream, + }, + }, + }, + }, + }, + }, + } +}