diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml index b494223a2b8104d7d37b9ba316348f815f633375..60fea0a976322b297da439ccb425fd3acebd8336 100644 --- a/.gitlab/ci/.test.yml +++ b/.gitlab/ci/.test.yml @@ -18,6 +18,7 @@ unit-test: - cd controller - make ci-unit-test after_script: + - cd controller - go tool cover -func=coverage.out <<: *test diff --git a/.golangci.yml b/.golangci.yml index b5c8fb3a790edcad9b9e73ce5baa9096fd07b0ac..ccc5f10f0bbd17944a52347b87caddd23d446eec 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,7 @@ run: issues-exit-code: 1 # directories to be ignored by linters skip-dirs: + - artifacts - controller/forks - controller/test - controller/mocks diff --git a/api/go/gosdn/core/core.pb.go b/api/go/gosdn/core/core.pb.go index 562655fc9c3001e2e5992ff509111d1a7c06ea27..fb190ee9c49be4820013ee45119c93a35e119cd5 100644 --- a/api/go/gosdn/core/core.pb.go +++ b/api/go/gosdn/core/core.pb.go @@ -71,16 +71,17 @@ func (Status) EnumDescriptor() ([]byte, []int) { return file_gosdn_core_core_proto_rawDescGZIP(), []int{0} } -type GetPndListRequest struct { +type GetPndRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Pid string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"` } -func (x *GetPndListRequest) Reset() { - *x = GetPndListRequest{} +func (x *GetPndRequest) Reset() { + *x = GetPndRequest{} if protoimpl.UnsafeEnabled { mi := &file_gosdn_core_core_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -88,13 +89,13 @@ func (x *GetPndListRequest) Reset() { } } -func (x *GetPndListRequest) String() string { +func (x *GetPndRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetPndListRequest) ProtoMessage() {} +func (*GetPndRequest) ProtoMessage() {} -func (x *GetPndListRequest) ProtoReflect() protoreflect.Message { +func (x *GetPndRequest) ProtoReflect() protoreflect.Message { mi := &file_gosdn_core_core_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -106,29 +107,36 @@ func (x *GetPndListRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetPndListRequest.ProtoReflect.Descriptor instead. -func (*GetPndListRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use GetPndRequest.ProtoReflect.Descriptor instead. +func (*GetPndRequest) Descriptor() ([]byte, []int) { return file_gosdn_core_core_proto_rawDescGZIP(), []int{0} } -func (x *GetPndListRequest) GetTimestamp() int64 { +func (x *GetPndRequest) GetTimestamp() int64 { if x != nil { return x.Timestamp } return 0 } -type GetPndRequest struct { +func (x *GetPndRequest) GetPid() string { + if x != nil { + return x.Pid + } + return "" +} + +type GetPndResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pid []string `protobuf:"bytes,3,rep,name=pid,proto3" json:"pid,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Pnd *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"` } -func (x *GetPndRequest) Reset() { - *x = GetPndRequest{} +func (x *GetPndResponse) Reset() { + *x = GetPndResponse{} if protoimpl.UnsafeEnabled { mi := &file_gosdn_core_core_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -136,13 +144,13 @@ func (x *GetPndRequest) Reset() { } } -func (x *GetPndRequest) String() string { +func (x *GetPndResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetPndRequest) ProtoMessage() {} +func (*GetPndResponse) ProtoMessage() {} -func (x *GetPndRequest) ProtoReflect() protoreflect.Message { +func (x *GetPndResponse) ProtoReflect() protoreflect.Message { mi := &file_gosdn_core_core_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -154,36 +162,35 @@ func (x *GetPndRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetPndRequest.ProtoReflect.Descriptor instead. -func (*GetPndRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use GetPndResponse.ProtoReflect.Descriptor instead. +func (*GetPndResponse) Descriptor() ([]byte, []int) { return file_gosdn_core_core_proto_rawDescGZIP(), []int{1} } -func (x *GetPndRequest) GetTimestamp() int64 { +func (x *GetPndResponse) GetTimestamp() int64 { if x != nil { return x.Timestamp } return 0 } -func (x *GetPndRequest) GetPid() []string { +func (x *GetPndResponse) GetPnd() *pnd.PrincipalNetworkDomain { if x != nil { - return x.Pid + return x.Pnd } return nil } -type GetPndListResponse struct { +type GetPndListRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pnd []*pnd.PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. } -func (x *GetPndListResponse) Reset() { - *x = GetPndListResponse{} +func (x *GetPndListRequest) Reset() { + *x = GetPndListRequest{} if protoimpl.UnsafeEnabled { mi := &file_gosdn_core_core_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -191,13 +198,13 @@ func (x *GetPndListResponse) Reset() { } } -func (x *GetPndListResponse) String() string { +func (x *GetPndListRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetPndListResponse) ProtoMessage() {} +func (*GetPndListRequest) ProtoMessage() {} -func (x *GetPndListResponse) ProtoReflect() protoreflect.Message { +func (x *GetPndListRequest) ProtoReflect() protoreflect.Message { mi := &file_gosdn_core_core_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -209,26 +216,19 @@ func (x *GetPndListResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetPndListResponse.ProtoReflect.Descriptor instead. -func (*GetPndListResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use GetPndListRequest.ProtoReflect.Descriptor instead. +func (*GetPndListRequest) Descriptor() ([]byte, []int) { return file_gosdn_core_core_proto_rawDescGZIP(), []int{2} } -func (x *GetPndListResponse) GetTimestamp() int64 { +func (x *GetPndListRequest) GetTimestamp() int64 { if x != nil { return x.Timestamp } return 0 } -func (x *GetPndListResponse) GetPnd() []*pnd.PrincipalNetworkDomain { - if x != nil { - return x.Pnd - } - return nil -} - -type GetPndResponse struct { +type GetPndListResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -237,8 +237,8 @@ type GetPndResponse struct { Pnd []*pnd.PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"` } -func (x *GetPndResponse) Reset() { - *x = GetPndResponse{} +func (x *GetPndListResponse) Reset() { + *x = GetPndListResponse{} if protoimpl.UnsafeEnabled { mi := &file_gosdn_core_core_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -246,13 +246,13 @@ func (x *GetPndResponse) Reset() { } } -func (x *GetPndResponse) String() string { +func (x *GetPndListResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetPndResponse) ProtoMessage() {} +func (*GetPndListResponse) ProtoMessage() {} -func (x *GetPndResponse) ProtoReflect() protoreflect.Message { +func (x *GetPndListResponse) ProtoReflect() protoreflect.Message { mi := &file_gosdn_core_core_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -264,19 +264,19 @@ func (x *GetPndResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetPndResponse.ProtoReflect.Descriptor instead. -func (*GetPndResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use GetPndListResponse.ProtoReflect.Descriptor instead. +func (*GetPndListResponse) Descriptor() ([]byte, []int) { return file_gosdn_core_core_proto_rawDescGZIP(), []int{3} } -func (x *GetPndResponse) GetTimestamp() int64 { +func (x *GetPndListResponse) GetTimestamp() int64 { if x != nil { return x.Timestamp } return 0 } -func (x *GetPndResponse) GetPnd() []*pnd.PrincipalNetworkDomain { +func (x *GetPndListResponse) GetPnd() []*pnd.PrincipalNetworkDomain { if x != nil { return x.Pnd } @@ -574,21 +574,21 @@ var file_gosdn_core_core_proto_rawDesc = []byte{ 0x6f, 0x72, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x2f, 0x70, 0x6e, 0x64, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3f, 0x0a, 0x0d, 0x47, 0x65, 0x74, - 0x50, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x67, 0x0a, 0x12, 0x47, 0x65, - 0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, - 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, - 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, - 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, - 0x70, 0x6e, 0x64, 0x22, 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x52, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x6e, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, + 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x6e, 0x64, 0x22, 0x31, 0x0a, 0x11, + 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, + 0x67, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, @@ -674,10 +674,10 @@ var file_gosdn_core_core_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_gosdn_core_core_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_gosdn_core_core_proto_goTypes = []interface{}{ (Status)(0), // 0: gosdn.core.Status - (*GetPndListRequest)(nil), // 1: gosdn.core.GetPndListRequest - (*GetPndRequest)(nil), // 2: gosdn.core.GetPndRequest - (*GetPndListResponse)(nil), // 3: gosdn.core.GetPndListResponse - (*GetPndResponse)(nil), // 4: gosdn.core.GetPndResponse + (*GetPndRequest)(nil), // 1: gosdn.core.GetPndRequest + (*GetPndResponse)(nil), // 2: gosdn.core.GetPndResponse + (*GetPndListRequest)(nil), // 3: gosdn.core.GetPndListRequest + (*GetPndListResponse)(nil), // 4: gosdn.core.GetPndListResponse (*CreatePndListRequest)(nil), // 5: gosdn.core.CreatePndListRequest (*PndCreateProperties)(nil), // 6: gosdn.core.PndCreateProperties (*CreatePndListResponse)(nil), // 7: gosdn.core.CreatePndListResponse @@ -686,17 +686,17 @@ var file_gosdn_core_core_proto_goTypes = []interface{}{ (*pnd.PrincipalNetworkDomain)(nil), // 10: gosdn.pnd.PrincipalNetworkDomain } var file_gosdn_core_core_proto_depIdxs = []int32{ - 10, // 0: gosdn.core.GetPndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain - 10, // 1: gosdn.core.GetPndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain + 10, // 0: gosdn.core.GetPndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain + 10, // 1: gosdn.core.GetPndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain 6, // 2: gosdn.core.CreatePndListRequest.pnd:type_name -> gosdn.core.PndCreateProperties 0, // 3: gosdn.core.CreatePndListResponse.status:type_name -> gosdn.core.Status 0, // 4: gosdn.core.DeletePndResponse.status:type_name -> gosdn.core.Status - 2, // 5: gosdn.core.CoreService.GetPnd:input_type -> gosdn.core.GetPndRequest - 1, // 6: gosdn.core.CoreService.GetPndList:input_type -> gosdn.core.GetPndListRequest + 1, // 5: gosdn.core.CoreService.GetPnd:input_type -> gosdn.core.GetPndRequest + 3, // 6: gosdn.core.CoreService.GetPndList:input_type -> gosdn.core.GetPndListRequest 5, // 7: gosdn.core.CoreService.CreatePndList:input_type -> gosdn.core.CreatePndListRequest 8, // 8: gosdn.core.CoreService.DeletePnd:input_type -> gosdn.core.DeletePndRequest - 4, // 9: gosdn.core.CoreService.GetPnd:output_type -> gosdn.core.GetPndResponse - 3, // 10: gosdn.core.CoreService.GetPndList:output_type -> gosdn.core.GetPndListResponse + 2, // 9: gosdn.core.CoreService.GetPnd:output_type -> gosdn.core.GetPndResponse + 4, // 10: gosdn.core.CoreService.GetPndList:output_type -> gosdn.core.GetPndListResponse 7, // 11: gosdn.core.CoreService.CreatePndList:output_type -> gosdn.core.CreatePndListResponse 9, // 12: gosdn.core.CoreService.DeletePnd:output_type -> gosdn.core.DeletePndResponse 9, // [9:13] is the sub-list for method output_type @@ -713,7 +713,7 @@ func file_gosdn_core_core_proto_init() { } if !protoimpl.UnsafeEnabled { file_gosdn_core_core_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPndListRequest); i { + switch v := v.(*GetPndRequest); i { case 0: return &v.state case 1: @@ -725,7 +725,7 @@ func file_gosdn_core_core_proto_init() { } } file_gosdn_core_core_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPndRequest); i { + switch v := v.(*GetPndResponse); i { case 0: return &v.state case 1: @@ -737,7 +737,7 @@ func file_gosdn_core_core_proto_init() { } } file_gosdn_core_core_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPndListResponse); i { + switch v := v.(*GetPndListRequest); i { case 0: return &v.state case 1: @@ -749,7 +749,7 @@ func file_gosdn_core_core_proto_init() { } } file_gosdn_core_core_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPndResponse); i { + switch v := v.(*GetPndListResponse); i { case 0: return &v.state case 1: diff --git a/api/go/gosdn/core/core.pb.gw.go b/api/go/gosdn/core/core.pb.gw.go index f20b6b3fcf07850e55869757651a55ebdeccda38..8c56242b632551449573f8c7e56c895e2fe3c12f 100644 --- a/api/go/gosdn/core/core.pb.gw.go +++ b/api/go/gosdn/core/core.pb.gw.go @@ -51,7 +51,7 @@ func request_CoreService_GetPnd_0(ctx context.Context, marshaler runtime.Marshal return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid") } - protoReq.Pid, err = runtime.StringSlice(val, ",") + protoReq.Pid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err) } @@ -84,7 +84,7 @@ func local_request_CoreService_GetPnd_0(ctx context.Context, marshaler runtime.M return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid") } - protoReq.Pid, err = runtime.StringSlice(val, ",") + protoReq.Pid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err) } diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go index 3738f74a09fbca7fb2ffe3c9e2116e6e3606bf44..8b52d80fe24ce2736647ae104ff754eaa8be9562 100644 --- a/api/go/gosdn/pnd/pnd.pb.go +++ b/api/go/gosdn/pnd/pnd.pb.go @@ -292,7 +292,7 @@ type GetOndListRequest struct { unknownFields protoimpl.UnknownFields Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Pid string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetOndListRequest) Reset() { @@ -346,9 +346,9 @@ type GetOndRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Did []string `protobuf:"bytes,3,rep,name=did,proto3" json:"did,omitempty"` - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Did string `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"` + Pid string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetOndRequest) Reset() { @@ -390,11 +390,11 @@ func (x *GetOndRequest) GetTimestamp() int64 { return 0 } -func (x *GetOndRequest) GetDid() []string { +func (x *GetOndRequest) GetDid() string { if x != nil { return x.Did } - return nil + return "" } func (x *GetOndRequest) GetPid() string { @@ -410,7 +410,7 @@ type GetSbiListRequest struct { unknownFields protoimpl.UnknownFields Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Pid string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetSbiListRequest) Reset() { @@ -464,9 +464,9 @@ type GetSbiRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Sid []string `protobuf:"bytes,3,rep,name=sid,proto3" json:"sid,omitempty"` - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Sid string `protobuf:"bytes,2,opt,name=sid,proto3" json:"sid,omitempty"` + Pid string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetSbiRequest) Reset() { @@ -508,11 +508,11 @@ func (x *GetSbiRequest) GetTimestamp() int64 { return 0 } -func (x *GetSbiRequest) GetSid() []string { +func (x *GetSbiRequest) GetSid() string { if x != nil { return x.Sid } - return nil + return "" } func (x *GetSbiRequest) GetPid() string { @@ -528,7 +528,7 @@ type GetChangeListRequest struct { unknownFields protoimpl.UnknownFields Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Pid string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetChangeListRequest) Reset() { @@ -582,9 +582,9 @@ type GetChangeRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Cuid string `protobuf:"bytes,3,opt,name=cuid,proto3" json:"cuid,omitempty"` - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. + Cuid []string `protobuf:"bytes,2,rep,name=cuid,proto3" json:"cuid,omitempty"` + Pid string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"` } func (x *GetChangeRequest) Reset() { @@ -626,11 +626,11 @@ func (x *GetChangeRequest) GetTimestamp() int64 { return 0 } -func (x *GetChangeRequest) GetCuid() string { +func (x *GetChangeRequest) GetCuid() []string { if x != nil { return x.Cuid } - return "" + return nil } func (x *GetChangeRequest) GetPid() string { @@ -719,8 +719,8 @@ type GetOndResponse struct { Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. // TODO: Check if this is really needed. Perhaps a reference to the PND's ID // is also sufficient. - Pnd *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"` - Ond []*OrchestratedNetworkingDevice `protobuf:"bytes,3,rep,name=ond,proto3" json:"ond,omitempty"` + Pnd *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"` + Ond *OrchestratedNetworkingDevice `protobuf:"bytes,3,opt,name=ond,proto3" json:"ond,omitempty"` } func (x *GetOndResponse) Reset() { @@ -769,7 +769,7 @@ func (x *GetOndResponse) GetPnd() *PrincipalNetworkDomain { return nil } -func (x *GetOndResponse) GetOnd() []*OrchestratedNetworkingDevice { +func (x *GetOndResponse) GetOnd() *OrchestratedNetworkingDevice { if x != nil { return x.Ond } @@ -849,8 +849,8 @@ type GetSbiResponse struct { Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. // TODO: Check if this is really needed. Perhaps a reference to the PND's ID // is also sufficient. - Pnd *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"` - Sbi []*southbound.SouthboundInterface `protobuf:"bytes,3,rep,name=sbi,proto3" json:"sbi,omitempty"` + Pnd *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"` + Sbi *southbound.SouthboundInterface `protobuf:"bytes,3,opt,name=sbi,proto3" json:"sbi,omitempty"` } func (x *GetSbiResponse) Reset() { @@ -899,7 +899,7 @@ func (x *GetSbiResponse) GetPnd() *PrincipalNetworkDomain { return nil } -func (x *GetSbiResponse) GetSbi() []*southbound.SouthboundInterface { +func (x *GetSbiResponse) GetSbi() *southbound.SouthboundInterface { if x != nil { return x.Sbi } @@ -1305,9 +1305,10 @@ type Change struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Age int64 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` - State ChangeState `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.pnd.ChangeState" json:"state,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Age int64 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` + State ChangeState `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.pnd.ChangeState" json:"state,omitempty"` + Diff *gnmi.Notification `protobuf:"bytes,4,opt,name=diff,proto3" json:"diff,omitempty"` } func (x *Change) Reset() { @@ -1363,6 +1364,13 @@ func (x *Change) GetState() ChangeState { return ChangeState_CHANGE_STATE_UNSPECIFIED } +func (x *Change) GetDiff() *gnmi.Notification { + if x != nil { + return x.Diff + } + return nil +} + type SetOndListRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1866,7 +1874,8 @@ type SetResponse struct { unknownFields protoimpl.UnknownFields Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Status Status `protobuf:"varint,2,opt,name=status,proto3,enum=gosdn.pnd.Status" json:"status,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Status Status `protobuf:"varint,3,opt,name=status,proto3,enum=gosdn.pnd.Status" json:"status,omitempty"` } func (x *SetResponse) Reset() { @@ -1908,6 +1917,13 @@ func (x *SetResponse) GetTimestamp() int64 { return 0 } +func (x *SetResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + func (x *SetResponse) GetStatus() Status { if x != nil { return x.Status @@ -2228,8 +2244,8 @@ type DeleteOndRequest struct { unknownFields protoimpl.UnknownFields Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch. - Pid string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` - Did string `protobuf:"bytes,5,opt,name=did,proto3" json:"did,omitempty"` + Pid string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"` + Did string `protobuf:"bytes,3,opt,name=did,proto3" json:"did,omitempty"` } func (x *DeleteOndRequest) Reset() { @@ -2363,31 +2379,31 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, - 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x43, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, + 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x43, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x03, 0x73, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x73, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x46, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, - 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x56, + 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x56, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x63, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, + 0x63, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x66, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, @@ -2401,7 +2417,7 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x33, 0x0a, 0x03, 0x70, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, - 0x03, 0x70, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x03, 0x70, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x4f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x03, 0x6f, 0x6e, 0x64, 0x22, @@ -2422,7 +2438,7 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x6e, 0x64, 0x12, 0x37, 0x0a, 0x03, 0x73, 0x62, - 0x69, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, + 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x22, 0xa0, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, @@ -2480,85 +2496,79 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x22, - 0x58, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, - 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74, - 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, + 0x80, 0x01, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x67, 0x6f, + 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x64, 0x69, + 0x66, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x64, 0x69, + 0x66, 0x66, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03, 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, + 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x03, 0x6f, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x11, + 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, + 0x23, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, + 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, + 0x03, 0x73, 0x62, 0x69, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x74, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03, - 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, - 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x03, 0x6f, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x70, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, - 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x10, 0x0a, 0x03, 0x70, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x74, 0x0a, - 0x14, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, - 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x70, 0x69, 0x64, 0x22, 0x85, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x7b, 0x0a, 0x0d, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x64, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x70, 0x69, 0x5f, - 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, - 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x05, 0x61, 0x70, 0x69, 0x4f, 0x70, 0x22, 0xc9, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x74, - 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, - 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, - 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, - 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, 0x06, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x2d, - 0x0a, 0x08, 0x73, 0x62, 0x69, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x62, 0x69, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a, - 0x09, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x75, 0x69, 0x64, 0x12, 0x24, - 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73, - 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x02, 0x6f, 0x70, 0x22, 0x56, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, - 0x12, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x06, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, + 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x85, 0x01, 0x0a, + 0x12, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x09, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x70, 0x12, 0x3f, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, + 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x70, 0x69, 0x64, 0x22, 0x7b, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x70, 0x69, 0x5f, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x41, 0x70, + 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x61, 0x70, 0x69, 0x4f, + 0x70, 0x22, 0xc9, 0x01, 0x0a, 0x06, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, + 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, + 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x4b, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x73, + 0x64, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, + 0x06, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x62, 0x69, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x73, 0x64, + 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x73, + 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x22, 0x45, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x63, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x70, 0x22, 0x66, 0x0a, + 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, + 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, @@ -2567,14 +2577,33 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x11, 0x53, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, - 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65, - 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, + 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, + 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, + 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, + 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, + 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, + 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, @@ -2583,162 +2612,153 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, - 0x94, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, - 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, + 0x54, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x64, 0x69, 0x64, 0x22, 0x5c, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, + 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x22, 0x5c, 0x0a, 0x11, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x9c, 0x01, 0x0a, 0x0b, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, - 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x48, 0x41, 0x4e, - 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, - 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a, - 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, - 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, - 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4e, - 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c, 0x41, 0x70, 0x69, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50, 0x49, - 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, - 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, - 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, - 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62, 0x69, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e, - 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x49, 0x53, 0x45, 0x44, 0x10, - 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, - 0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, - 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, - 0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, - 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x10, - 0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, - 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x02, 0x32, 0xfc, 0x09, 0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, - 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, - 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, - 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, - 0x6e, 0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, - 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, - 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, - 0x15, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, - 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, - 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, - 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, - 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63, - 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, - 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, - 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, - 0x62, 0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e, - 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, - 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64, - 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69, - 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, - 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, - 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, - 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, - 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, - 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, - 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, - 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e, - 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x2f, 0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d, 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, - 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, - 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, - 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47, - 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, - 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, - 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, - 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, - 0x74, 0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65, - 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, - 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, - 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, - 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, - 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, - 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, - 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e, - 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, - 0x69, 0x64, 0x7d, 0x42, 0xae, 0x02, 0x5a, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, - 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, - 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, - 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41, 0xfb, 0x01, 0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f, - 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, - 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a, - 0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, - 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a, - 0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, - 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, - 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62, - 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, - 0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, + 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x2a, 0x9c, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, + 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, + 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, + 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4e, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, + 0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, + 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, + 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, + 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, + 0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, + 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a, + 0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, + 0x49, 0x4e, 0x45, 0x52, 0x49, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42, + 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a, + 0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, + 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, + 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, + 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x10, 0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xfc, 0x09, + 0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, + 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, + 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, + 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, + 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, + 0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f, + 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, + 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, + 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12, + 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, + 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, + 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x62, + 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, + 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, + 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06, + 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, + 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, + 0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, + 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, + 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, + 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, + 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, + 0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, + 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, + 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, + 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d, + 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, + 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73, + 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, + 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, + 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61, + 0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, + 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, + 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70, + 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70, + 0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, + 0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, + 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x42, 0xae, 0x02, 0x5a, + 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, + 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41, + 0xfb, 0x01, 0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, + 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63, + 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44, + 0x4e, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a, 0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, + 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, + 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, + 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a, 0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, + 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38, + 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, + 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2816,55 +2836,56 @@ var file_gosdn_pnd_pnd_proto_depIdxs = []int32{ 39, // 14: gosdn.pnd.OrchestratedNetworkingDevice.device:type_name -> gnmi.Notification 38, // 15: gosdn.pnd.OrchestratedNetworkingDevice.sbi:type_name -> gosdn.southbound.SouthboundInterface 0, // 16: gosdn.pnd.Change.state:type_name -> gosdn.pnd.ChangeState - 27, // 17: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd - 28, // 18: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi - 29, // 19: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange - 26, // 20: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest - 1, // 21: gosdn.pnd.ChangeRequest.api_op:type_name -> gosdn.pnd.ApiOperation - 38, // 22: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface - 40, // 23: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption - 2, // 24: gosdn.pnd.SetSbi.sbi_type:type_name -> gosdn.pnd.SbiType - 3, // 25: gosdn.pnd.SetChange.op:type_name -> gosdn.pnd.Operation - 4, // 26: gosdn.pnd.SetResponse.status:type_name -> gosdn.pnd.Status - 4, // 27: gosdn.pnd.SetOndListResponse.status:type_name -> gosdn.pnd.Status - 30, // 28: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse - 4, // 29: gosdn.pnd.SetChangeListResponse.status:type_name -> gosdn.pnd.Status - 30, // 30: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse - 4, // 31: gosdn.pnd.SetChangeResponse.status:type_name -> gosdn.pnd.Status - 4, // 32: gosdn.pnd.SetSbiListResponse.status:type_name -> gosdn.pnd.Status - 30, // 33: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse - 4, // 34: gosdn.pnd.SetPathListResponse.status:type_name -> gosdn.pnd.Status - 30, // 35: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse - 4, // 36: gosdn.pnd.DeleteOndResponse.status:type_name -> gosdn.pnd.Status - 5, // 37: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest - 6, // 38: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest - 22, // 39: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest - 7, // 40: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest - 8, // 41: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest - 23, // 42: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest - 9, // 43: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest - 10, // 44: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest - 24, // 45: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest - 11, // 46: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest - 25, // 47: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest - 36, // 48: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest - 13, // 49: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse - 12, // 50: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse - 31, // 51: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse - 15, // 52: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse - 14, // 53: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse - 34, // 54: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse - 18, // 55: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse - 17, // 56: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse - 32, // 57: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse - 16, // 58: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse - 35, // 59: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse - 37, // 60: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse - 49, // [49:61] is the sub-list for method output_type - 37, // [37:49] is the sub-list for method input_type - 37, // [37:37] is the sub-list for extension type_name - 37, // [37:37] is the sub-list for extension extendee - 0, // [0:37] is the sub-list for field type_name + 39, // 17: gosdn.pnd.Change.diff:type_name -> gnmi.Notification + 27, // 18: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd + 28, // 19: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi + 29, // 20: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange + 26, // 21: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest + 1, // 22: gosdn.pnd.ChangeRequest.api_op:type_name -> gosdn.pnd.ApiOperation + 38, // 23: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface + 40, // 24: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption + 2, // 25: gosdn.pnd.SetSbi.sbi_type:type_name -> gosdn.pnd.SbiType + 3, // 26: gosdn.pnd.SetChange.op:type_name -> gosdn.pnd.Operation + 4, // 27: gosdn.pnd.SetResponse.status:type_name -> gosdn.pnd.Status + 4, // 28: gosdn.pnd.SetOndListResponse.status:type_name -> gosdn.pnd.Status + 30, // 29: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse + 4, // 30: gosdn.pnd.SetChangeListResponse.status:type_name -> gosdn.pnd.Status + 30, // 31: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse + 4, // 32: gosdn.pnd.SetChangeResponse.status:type_name -> gosdn.pnd.Status + 4, // 33: gosdn.pnd.SetSbiListResponse.status:type_name -> gosdn.pnd.Status + 30, // 34: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse + 4, // 35: gosdn.pnd.SetPathListResponse.status:type_name -> gosdn.pnd.Status + 30, // 36: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse + 4, // 37: gosdn.pnd.DeleteOndResponse.status:type_name -> gosdn.pnd.Status + 5, // 38: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest + 6, // 39: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest + 22, // 40: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest + 7, // 41: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest + 8, // 42: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest + 23, // 43: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest + 9, // 44: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest + 10, // 45: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest + 24, // 46: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest + 11, // 47: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest + 25, // 48: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest + 36, // 49: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest + 13, // 50: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse + 12, // 51: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse + 31, // 52: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse + 15, // 53: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse + 14, // 54: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse + 34, // 55: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse + 18, // 56: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse + 17, // 57: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse + 32, // 58: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse + 16, // 59: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse + 35, // 60: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse + 37, // 61: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse + 50, // [50:62] is the sub-list for method output_type + 38, // [38:50] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_gosdn_pnd_pnd_proto_init() } diff --git a/api/go/gosdn/pnd/pnd.pb.gw.go b/api/go/gosdn/pnd/pnd.pb.gw.go index 2b75200c8fad1fa6fe38831ee7293ad358a82c8b..2c59921a9a36b169854bf52d9cdbb2f9dc37c5c1 100644 --- a/api/go/gosdn/pnd/pnd.pb.gw.go +++ b/api/go/gosdn/pnd/pnd.pb.gw.go @@ -131,7 +131,7 @@ func request_PndService_GetOnd_0(ctx context.Context, marshaler runtime.Marshale return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "did") } - protoReq.Did, err = runtime.StringSlice(val, ",") + protoReq.Did, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "did", err) } @@ -174,7 +174,7 @@ func local_request_PndService_GetOnd_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "did") } - protoReq.Did, err = runtime.StringSlice(val, ",") + protoReq.Did, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "did", err) } @@ -359,7 +359,7 @@ func request_PndService_GetSbi_0(ctx context.Context, marshaler runtime.Marshale return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sid") } - protoReq.Sid, err = runtime.StringSlice(val, ",") + protoReq.Sid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sid", err) } @@ -402,7 +402,7 @@ func local_request_PndService_GetSbi_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "sid") } - protoReq.Sid, err = runtime.StringSlice(val, ",") + protoReq.Sid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "sid", err) } @@ -587,7 +587,7 @@ func request_PndService_GetChange_0(ctx context.Context, marshaler runtime.Marsh return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid") } - protoReq.Cuid, err = runtime.String(val) + protoReq.Cuid, err = runtime.StringSlice(val, ",") if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err) } @@ -630,7 +630,7 @@ func local_request_PndService_GetChange_0(ctx context.Context, marshaler runtime return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid") } - protoReq.Cuid, err = runtime.String(val) + protoReq.Cuid, err = runtime.StringSlice(val, ",") if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err) } diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json index 4a016bc2c27b39a0706fa3505d0640987c8a9acc..7752e8aa07811f91ea044176236fd0e4dcf505a3 100644 --- a/api/openapiv2/gosdn_northbound.swagger.json +++ b/api/openapiv2/gosdn_northbound.swagger.json @@ -146,12 +146,7 @@ "name": "pid", "in": "path", "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "minItems": 1 + "type": "string" }, { "name": "timestamp", @@ -383,7 +378,12 @@ "name": "cuid", "in": "path", "required": true, - "type": "string" + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "minItems": 1 }, { "name": "timestamp", @@ -427,12 +427,7 @@ "name": "did", "in": "path", "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "minItems": 1 + "type": "string" }, { "name": "timestamp", @@ -795,12 +790,7 @@ "name": "sid", "in": "path", "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "minItems": 1 + "type": "string" }, { "name": "timestamp", @@ -1314,10 +1304,7 @@ "format": "int64" }, "pnd": { - "type": "array", - "items": { - "$ref": "#/definitions/pndPrincipalNetworkDomain" - } + "$ref": "#/definitions/pndPrincipalNetworkDomain" } } }, @@ -2479,6 +2466,9 @@ "type": "string", "format": "int64" }, + "id": { + "type": "string" + }, "status": { "$ref": "#/definitions/gosdnpndStatus" } @@ -2564,6 +2554,9 @@ }, "state": { "$ref": "#/definitions/pndChangeState" + }, + "diff": { + "$ref": "#/definitions/gnmiNotification" } } }, @@ -2677,10 +2670,7 @@ "description": "TODO: Check if this is really needed. Perhaps a reference to the PND's ID\nis also sufficient." }, "ond": { - "type": "array", - "items": { - "$ref": "#/definitions/pndOrchestratedNetworkingDevice" - } + "$ref": "#/definitions/pndOrchestratedNetworkingDevice" } } }, @@ -2734,10 +2724,7 @@ "description": "TODO: Check if this is really needed. Perhaps a reference to the PND's ID\nis also sufficient." }, "sbi": { - "type": "array", - "items": { - "$ref": "#/definitions/southboundSouthboundInterface" - } + "$ref": "#/definitions/southboundSouthboundInterface" } } }, diff --git a/api/proto/buf.lock b/api/proto/buf.lock index 60d8de11dc18ebb85fc6bab0acf9be9c0d7d0b24..87b5db40a38f740a05fd512626def460cf8ce415 100644 --- a/api/proto/buf.lock +++ b/api/proto/buf.lock @@ -4,7 +4,7 @@ deps: - remote: buf.build owner: googleapis repository: googleapis - commit: f3590c56d388417ebbedefae77ac12bf + commit: 8ab0a452adb64b36ac7a40ae95bd59b2 - remote: buf.build owner: grpc-ecosystem repository: grpc-gateway diff --git a/api/proto/gosdn/core/core.proto b/api/proto/gosdn/core/core.proto index a55a8dd17293a84a0353569cb49aa55762ef46bc..d2476f3897755c07298973f159a11ca888ae96e6 100644 --- a/api/proto/gosdn/core/core.proto +++ b/api/proto/gosdn/core/core.proto @@ -35,25 +35,26 @@ service CoreService { } } -message GetPndListRequest { - int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. -} message GetPndRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - repeated string pid = 3; + string pid = 2; } -message GetPndListResponse { +message GetPndResponse { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2; + .gosdn.pnd.PrincipalNetworkDomain pnd = 2; } -message GetPndResponse { - int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2; +message GetPndListRequest { + int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. } +message GetPndListResponse { + int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. + repeated .gosdn.pnd.PrincipalNetworkDomain pnd = 2; + } + message CreatePndListRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. repeated PndCreateProperties pnd = 2; diff --git a/api/proto/gosdn/pnd/pnd.proto b/api/proto/gosdn/pnd/pnd.proto index 11bed8ef564785395463955b363ba372fcff4da8..d68ef4940e68f6987808b4482fe8137136a9393f 100644 --- a/api/proto/gosdn/pnd/pnd.proto +++ b/api/proto/gosdn/pnd/pnd.proto @@ -118,34 +118,35 @@ service PndService { message GetOndListRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - string pid = 4; + string pid = 2; } message GetOndRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - repeated string did = 3; - string pid = 4; + string did = 2; + string pid = 3; } message GetSbiListRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - string pid = 4; + string pid = 2; } + message GetSbiRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - repeated string sid = 3; - string pid = 4; + string sid = 2; + string pid = 3; } message GetChangeListRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - string pid = 4; + string pid = 2; } message GetChangeRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - string cuid = 3; - string pid = 4; + repeated string cuid = 2; + string pid = 3; } message GetPathRequest { @@ -160,7 +161,7 @@ message GetOndResponse { // TODO: Check if this is really needed. Perhaps a reference to the PND's ID // is also sufficient. PrincipalNetworkDomain pnd = 2; - repeated OrchestratedNetworkingDevice ond = 3; + OrchestratedNetworkingDevice ond = 3; } message GetOndListResponse { @@ -176,7 +177,7 @@ message GetSbiResponse { // TODO: Check if this is really needed. Perhaps a reference to the PND's ID // is also sufficient. PrincipalNetworkDomain pnd = 2; - repeated .gosdn.southbound.SouthboundInterface sbi = 3; + .gosdn.southbound.SouthboundInterface sbi = 3; } message GetSbiListResponse { @@ -235,8 +236,8 @@ enum ChangeState { message Change { string id = 1; int64 age = 2; - ChangeState state = 3; + gnmi.Notification diff = 4; } message SetOndListRequest { @@ -310,7 +311,8 @@ message SetChange { message SetResponse{ int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - Status status = 2; + string id = 2; + Status status = 3; } message SetOndListResponse{ @@ -344,8 +346,8 @@ message SetPathListResponse{ message DeleteOndRequest { int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - string pid = 4; - string did = 5; + string pid = 2; + string did = 3; } message DeleteOndResponse { diff --git a/cli/adapter/OndAdapter.go b/cli/adapter/OndAdapter.go deleted file mode 100644 index b8e8da3083fa3680ab0724d21c4b05795f409d26..0000000000000000000000000000000000000000 --- a/cli/adapter/OndAdapter.go +++ /dev/null @@ -1 +0,0 @@ -package adapter diff --git a/cli/adapter/PndAdapter.go b/cli/adapter/PndAdapter.go index a03b5480bb0bb6bda6defd5aabacd862fb9a46d2..a02ac56ea36adfc4f457dd03484b76fbf1d8e8fa 100644 --- a/cli/adapter/PndAdapter.go +++ b/cli/adapter/PndAdapter.go @@ -5,15 +5,12 @@ import ( "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core" ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" - spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" "code.fbi.h-da.de/danet/gosdn/controller/api" - "code.fbi.h-da.de/danet/gosdn/controller/interfaces/change" "code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound" "code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors" "github.com/google/uuid" "github.com/openconfig/goyang/pkg/yang" - log "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" "google.golang.org/protobuf/proto" ) @@ -69,22 +66,22 @@ func (p *PndAdapter) GetSbiSchemaTree(ctx context.Context, sid uuid.UUID) (map[s // GetDevice requests one or multiple devices belonging to a given // PrincipalNetworkDomain from the controller. -func (p *PndAdapter) GetDevice(ctx context.Context, identifier ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { - resp, err := api.GetDevice(ctx, p.endpoint, p.id.String(), identifier...) +func (p *PndAdapter) GetDevice(ctx context.Context, identifier string) (*ppb.GetOndResponse, error) { + resp, err := api.GetDevice(ctx, p.endpoint, p.id.String(), identifier) if err != nil { return nil, err } - return resp.Ond, nil + return resp, nil } // GetDevices requests all devices belonging to the PrincipalNetworkDomain // attached to this adapter. -func (p *PndAdapter) GetDevices(ctx context.Context) ([]*ppb.OrchestratedNetworkingDevice, error) { +func (p *PndAdapter) GetDevices(ctx context.Context) (*ppb.GetOndListResponse, error) { resp, err := api.GetDevices(ctx, p.endpoint, p.id.String()) if err != nil { return nil, err } - return resp.Ond, nil + return resp, nil } // RemoveDevice removes a device from the controller @@ -108,22 +105,21 @@ func (p *PndAdapter) RemovePnd(ctx context.Context, pid uuid.UUID) (*core.Delete // ChangeOND sends an API call to the controller requesting the creation of // a change from the provided Operation, path and value. The Change is marked // as Pending and times out after the specified timeout period -func (p *PndAdapter) ChangeOND(ctx context.Context, duid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) (uuid.UUID, error) { +func (p *PndAdapter) ChangeOND(ctx context.Context, duid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) (*ppb.SetPathListResponse, error) { var v string if len(value) != 0 { v = value[0] } resp, err := api.ChangeRequest(ctx, p.endpoint, duid.String(), p.id.String(), path, v, operation) if err != nil { - return uuid.Nil, err + return nil, err } - log.Info(resp) - return uuid.Nil, err + return resp, err } // Request sends an API call to the controller requesting the specified path // for the specified device -func (p *PndAdapter) Request(ctx context.Context, did uuid.UUID, path string) (proto.Message, error) { +func (p *PndAdapter) Request(ctx context.Context, did uuid.UUID, path string) (*ppb.GetPathResponse, error) { resp, err := api.GetPath(ctx, p.endpoint, p.id.String(), did.String(), path) if err != nil { return nil, err @@ -169,22 +165,22 @@ func (p *PndAdapter) ContainsDevice(uuid.UUID) bool { // GetSbi sends an API call to the controller requesting the // registered SBI with the provided ID. -func (p *PndAdapter) GetSbi(ctx context.Context, sid ...string) ([]*spb.SouthboundInterface, error) { - resp, err := api.GetSbi(ctx, p.endpoint, p.id.String(), sid...) +func (p *PndAdapter) GetSbi(ctx context.Context, sid string) (*ppb.GetSbiResponse, error) { + resp, err := api.GetSbi(ctx, p.endpoint, p.id.String(), sid) if err != nil { return nil, err } - return resp.Sbi, nil + return resp, nil } // GetSBIs sends an API call to the controller requesting the // registered SBIs. Not implemented, always returns nil -func (p *PndAdapter) GetSBIs(ctx context.Context) ([]*spb.SouthboundInterface, error) { +func (p *PndAdapter) GetSBIs(ctx context.Context) (*ppb.GetSbiListResponse, error) { resp, err := api.GetSBIs(ctx, p.endpoint, p.id.String()) if err != nil { return nil, err } - return resp.Sbi, nil + return resp, nil } // ID returns the PND Adapter's UUID @@ -199,57 +195,67 @@ func (p *PndAdapter) Endpoint() string { // PendingChanges sends an API call to the controller requesting // the UUIDs of all pending changes -func (p *PndAdapter) PendingChanges(ctx context.Context) []uuid.UUID { +func (p *PndAdapter) PendingChanges(ctx context.Context) ([]*ppb.Change, error) { resp, err := api.GetChanges(ctx, p.endpoint, p.id.String()) if err != nil { - log.Error(err) - return nil + return nil, err } - return filterChanges(ppb.ChangeState_CHANGE_STATE_PENDING, resp) + return filterChanges(ppb.ChangeState_CHANGE_STATE_PENDING, resp), nil } // CommittedChanges sends an API call to the controller requesting // the UUIDs of all committed changes -func (p *PndAdapter) CommittedChanges(ctx context.Context) []uuid.UUID { +func (p *PndAdapter) CommittedChanges(ctx context.Context) ([]*ppb.Change, error) { resp, err := api.GetChanges(ctx, p.endpoint, p.id.String()) if err != nil { - log.Error(err) - return nil + return nil, err } - return filterChanges(ppb.ChangeState_CHANGE_STATE_COMMITTED, resp) + return filterChanges(ppb.ChangeState_CHANGE_STATE_COMMITTED, resp), nil } -// GetChange sends an API call to the controller requesting the specified change -func (p *PndAdapter) GetChange(uuid.UUID) (change.Change, error) { - return nil, &errors.ErrNotYetImplemented{} +// ConfirmedChanges sends an API call to the controller requesting +// the UUIDs of all confirmed changes +func (p *PndAdapter) ConfirmedChanges(ctx context.Context) ([]*ppb.Change, error) { + resp, err := api.GetChanges(ctx, p.endpoint, p.id.String()) + if err != nil { + return nil, err + } + return filterChanges(ppb.ChangeState_CHANGE_STATE_CONFIRMED, resp), nil +} + +// GetChange sends an API call to the controller requesting one or more changes +// for the specific PND +func (p *PndAdapter) GetChange(ctx context.Context, identifier ...string) (*ppb.GetChangeResponse, error) { + resp, err := api.GetChange(ctx, p.endpoint, p.id.String(), identifier...) + if err != nil { + return nil, err + } + return resp, nil } // Commit sends an API call to the controller committing the specified change -func (p *PndAdapter) Commit(ctx context.Context, cuid uuid.UUID) error { +func (p *PndAdapter) Commit(ctx context.Context, cuid uuid.UUID) (*ppb.SetChangeListResponse, error) { resp, err := api.Commit(ctx, p.endpoint, p.id.String(), cuid.String()) if err != nil { - return err + return nil, err } - log.Info(resp) - return nil + return resp, nil } // Confirm sends an API call to the controller confirming the specified change -func (p *PndAdapter) Confirm(ctx context.Context, cuid uuid.UUID) error { +func (p *PndAdapter) Confirm(ctx context.Context, cuid uuid.UUID) (*ppb.SetChangeListResponse, error) { resp, err := api.Confirm(ctx, p.endpoint, p.id.String(), cuid.String()) if err != nil { - return err + return nil, err } - log.Info(resp) - return nil + return resp, nil } -func filterChanges(state ppb.ChangeState, resp *ppb.GetChangeListResponse) []uuid.UUID { - changes := make([]uuid.UUID, 0) +func filterChanges(state ppb.ChangeState, resp *ppb.GetChangeListResponse) []*ppb.Change { + changes := make([]*ppb.Change, 0) for _, ch := range resp.Change { if ch.State == state { - id, _ := uuid.Parse(ch.Id) - changes = append(changes, id) + changes = append(changes, ch) } } return changes diff --git a/cli/adapter/PndAdapter_test.go b/cli/adapter/PndAdapter_test.go index 2f5b1612abd5b6345387b47cfd8ecf4e2dd7c141..2c49e7804c452cab296fbd9ff5405042213deff0 100644 --- a/cli/adapter/PndAdapter_test.go +++ b/cli/adapter/PndAdapter_test.go @@ -385,7 +385,7 @@ func TestPndAdapter_PendingChanges(t *testing.T) { id: tt.fields.id, endpoint: tt.fields.endpoint, } - if got := p.PendingChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) { + if got, _ := p.PendingChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) { t.Errorf("PndAdapter.PendingChanges() = %v, want %v", got, tt.want) } }) @@ -410,7 +410,7 @@ func TestPndAdapter_CommittedChanges(t *testing.T) { id: tt.fields.id, endpoint: tt.fields.endpoint, } - if got := p.CommittedChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) { + if got, _ := p.CommittedChanges(context.TODO()); !reflect.DeepEqual(got, tt.want) { t.Errorf("PndAdapter.CommittedChanges() = %v, want %v", got, tt.want) } }) @@ -423,7 +423,7 @@ func TestPndAdapter_GetChange(t *testing.T) { endpoint string } type args struct { - in uuid.UUID + in []string } tests := []struct { name string @@ -440,7 +440,7 @@ func TestPndAdapter_GetChange(t *testing.T) { id: tt.fields.id, endpoint: tt.fields.endpoint, } - got, err := p.GetChange(tt.args.in) + got, err := p.GetChange(context.TODO(), tt.args.in...) if (err != nil) != tt.wantErr { t.Errorf("PndAdapter.GetChange() error = %v, wantErr %v", err, tt.wantErr) return @@ -474,7 +474,7 @@ func TestPndAdapter_Commit(t *testing.T) { id: tt.fields.id, endpoint: tt.fields.endpoint, } - if err := p.Commit(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr { + if _, err := p.Commit(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr { t.Errorf("PndAdapter.Commit() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -503,7 +503,7 @@ func TestPndAdapter_Confirm(t *testing.T) { id: tt.fields.id, endpoint: tt.fields.endpoint, } - if err := p.Confirm(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr { + if _, err := p.Confirm(context.TODO(), tt.args.cuid); (err != nil) != tt.wantErr { t.Errorf("PndAdapter.Confirm() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/cli/cmd/changeCommit.go b/cli/cmd/changeCommit.go index 8bdc0ea4190d9acf8a47492bcb975566becda5f9..0994ee2f6e302db03c9ee5634a59e7782f255368 100644 --- a/cli/cmd/changeCommit.go +++ b/cli/cmd/changeCommit.go @@ -33,7 +33,7 @@ package cmd import ( "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -48,10 +48,14 @@ Change UUID must be specified as positional argument.`, Run: func(cmd *cobra.Command, args []string) { cuid, err := uuid.Parse(args[0]) if err != nil { - log.Fatal(err) + pterm.Error.Println(err) } - if err := pndAdapter.Commit(createContextWithAuthorization(), cuid); err != nil { - log.Fatal(err) + resp, err := pndAdapter.Commit(createContextWithAuthorization(), cuid) + if err != nil { + pterm.Error.Println(err) + } + for _, r := range resp.GetResponses() { + pterm.Info.Println(r.String()) } }, } diff --git a/cli/cmd/changeConfirm.go b/cli/cmd/changeConfirm.go index 4fa511580fcd55858702c74fb1bf2e0389498b07..20a49e536a6cb4509d28e1446d17f258b022bab8 100644 --- a/cli/cmd/changeConfirm.go +++ b/cli/cmd/changeConfirm.go @@ -33,7 +33,7 @@ package cmd import ( "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -48,10 +48,15 @@ Change UUID must be specified as positional argument`, Run: func(cmd *cobra.Command, args []string) { cuid, err := uuid.Parse(args[0]) if err != nil { - log.Fatal(err) + pterm.Error.Println(err) } - if err := pndAdapter.Confirm(createContextWithAuthorization(), cuid); err != nil { - log.Fatal(err) + + resp, err := pndAdapter.Confirm(createContextWithAuthorization(), cuid) + if err != nil { + pterm.Error.Println(err) + } + for _, r := range resp.GetResponses() { + pterm.Info.Println(r.String()) } }, } diff --git a/cli/cmd/init.go b/cli/cmd/changeGet.go similarity index 57% rename from cli/cmd/init.go rename to cli/cmd/changeGet.go index f2d809e8744a915d4c8c674c3a4abcc199fbf5c6..6495b1e3f85ba5e4c3dae7913878031f2b8ae373 100644 --- a/cli/cmd/init.go +++ b/cli/cmd/changeGet.go @@ -32,44 +32,41 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - "fmt" - "os" - - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" - "github.com/spf13/viper" + "google.golang.org/protobuf/encoding/protojson" ) -var controllerAPIEndpoint string +// confirmCmd represents the confirm command +var getCmd = &cobra.Command{ + Use: "get [uuid]", + Args: cobra.ExactArgs(1), + Short: "returns information about the requested change", + Long: `Returns detailed information about a specific change. The + changes UUID has to be specified via a positional argument.`, -// initCmd represents the init command -var initCmd = &cobra.Command{ - Use: "init", - Short: "initialise controller", - Long: `Initialise PND and SBI and saves values to config file on controller. -The --controller flag is required to change the controller address`, + Run: func(cmd *cobra.Command, args []string) { + changes, err := pndAdapter.GetChange(createContextWithAuthorization(), args[0]) + if err != nil { + pterm.Error.Println(err) + } + for _, c := range changes.GetChange() { + title := pterm.Sprintf("Change with ID: %s", c.GetId()) + panel1 := pterm.DefaultBox.WithTitle("Age:").Sprint(c.GetAge()) + panel2 := pterm.DefaultBox.WithTitle("State:").Sprint(c.GetState()) + panel3 := pterm.DefaultBox.WithTitle("Diff:").Sprint(protojson.Format(c.GetDiff())) - RunE: func(cmd *cobra.Command, args []string) error { - log.Infof("New controller address: %v", viper.GetString("controllerAPIEndpoint")) + panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{ + {{Data: panel1}}, + {{Data: panel2}}, + {{Data: panel3}}, + }).Srender() - if err := viper.WriteConfig(); err != nil { - fmt.Fprintln(os.Stderr, "Could not write config:", err) + pterm.DefaultBox.WithTitle(title).WithTitleTopCenter().WithRightPadding(0).WithBottomPadding(0).Println(panels) } - return nil }, } func init() { - rootCmd.AddCommand(initCmd) - - initCmd.Flags().StringVar(&controllerAPIEndpoint, "controller", "gosdn-develop.apps.ocp.fbi.h-da.de:55055", "address of the controller") - err := viper.BindPFlag("controllerAPIEndpoint", initCmd.Flags().Lookup("controller")) - if err != nil { - fmt.Fprintln(os.Stderr, "Could not bind controllerAPIEndpoint:", err) - } - - // Set controller flag as required (possibly not?) - //if err := initCmd.MarkFlagRequired("controller"); err != nil { - // fmt.Fprintln(os.Stderr, "Could not mark controller flag as required:", err) - //} + changeCmd.AddCommand(getCmd) } diff --git a/cli/cmd/changeList.go b/cli/cmd/changeList.go index dcd3dc4f4e37a3e480a1a8d7feeacdb673a17802..af52241337c28aacfcbb372493fb9fba9953beb2 100644 --- a/cli/cmd/changeList.go +++ b/cli/cmd/changeList.go @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -43,17 +43,33 @@ var changeListCmd = &cobra.Command{ Short: "list all changes", Long: `Lists all configuration changes with their UUIDs.`, - Run: func(cmd *cobra.Command, args []string) { - committed := pndAdapter.CommittedChanges(createContextWithAuthorization()) - log.Info("committed changes:") - for i, ch := range committed { - log.Infof(" Change %v: %v", i+1, ch.String()) + RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Process change list request") + committed, err := pndAdapter.CommittedChanges(createContextWithAuthorization()) + if err != nil { + spinner.Fail(err) + return err } - pending := pndAdapter.PendingChanges(createContextWithAuthorization()) - log.Info("pending changes:") - for i, ch := range pending { - log.Infof(" Change %v: %v", i+1, ch.String()) + pending, err := pndAdapter.PendingChanges(createContextWithAuthorization()) + if err != nil { + spinner.Fail(err) + return err } + + // TODO: maybe we want to return more information about changes? E.g., + // the diff of the change (probably only for a single get of a change). + // This would require us to change pndAdapter methods. + data := pterm.TableData{[]string{"UUID", "Status"}} + for _, ch := range pending { + data = append(data, []string{ch.String(), "pending"}) + } + for _, ch := range committed { + data = append(data, []string{ch.String(), "commited"}) + } + + spinner.Success() + pterm.DefaultTable.WithHasHeader().WithData(data).Render() + return nil }, } diff --git a/cli/cmd/deviceCreate.go b/cli/cmd/deviceCreate.go index 56781bf23682bf5c68c2078216d8f04c1d91d60d..efd182a0dfcb0516684fb79a0bd3d74e7aec7048 100644 --- a/cli/cmd/deviceCreate.go +++ b/cli/cmd/deviceCreate.go @@ -33,9 +33,8 @@ package cmd import ( "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" - "google.golang.org/protobuf/encoding/protojson" spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" @@ -50,8 +49,10 @@ Device address must be provided with IP and port,e.g., 192.168.1.1:6030. User cr if they diverge from the default credentials (user:'admin' and pw:'arista').`, RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Creating new device") err := checkIPPort(address) if err != nil { + spinner.Fail(err) return err } @@ -73,16 +74,19 @@ if they diverge from the default credentials (user:'admin' and pw:'arista').`, } sid, err := uuid.Parse(cliSbi) if err != nil { + spinner.Fail(err) return err } resp, err := pndAdapter.AddDevice(createContextWithAuthorization(), deviceName, opt, sid) if err != nil { + spinner.Fail(err) return err } - log.Info(protojson.Format(resp)) - + for _, r := range resp.GetResponses() { + spinner.Success("Device has been created with ID: ", r.GetId()) + } return nil }, } diff --git a/cli/cmd/deviceDelete.go b/cli/cmd/deviceDelete.go index 82769ea903f055eed956ee4ab75f73f58b249e3b..c354ccc2c5a335df172704914c7d8e976539eaf9 100644 --- a/cli/cmd/deviceDelete.go +++ b/cli/cmd/deviceDelete.go @@ -34,7 +34,7 @@ package cmd import ( ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -46,17 +46,27 @@ var deviceDeleteCmd = &cobra.Command{ Long: `Delete a path for a given orchestrated network device. The device UUID and request path must be specified as a positional arguments.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Create a path deletion request.") did, err := uuid.Parse(args[0]) if err != nil { - log.Fatal(err) + spinner.Fail(err) + return err } - log.Info(pndAdapter.ChangeOND( + resp, err := pndAdapter.ChangeOND( createContextWithAuthorization(), did, ppb.ApiOperation_API_OPERATION_DELETE, args[1], - )) + ) + for _, r := range resp.Responses { + if r.Status == ppb.Status_STATUS_OK { + spinner.Success("A change for path deletion for Device: ", did.String(), "has been created -> Change ID: ", r.GetId()) + } else { + spinner.Fail("An error occured while creating a path deletion request for Device with ID: ", r.GetId(), r.GetStatus()) + } + } + return nil }, } diff --git a/cli/cmd/deviceGet.go b/cli/cmd/deviceGet.go index 0bbaaff0b4f9a0435fd4329028ff3bed9cd34bca..271eeca4a3043c63afa7a0f4b02a70f39ab6f364 100644 --- a/cli/cmd/deviceGet.go +++ b/cli/cmd/deviceGet.go @@ -33,7 +33,7 @@ package cmd import ( "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" ) @@ -46,22 +46,37 @@ var deviceGetCmd = &cobra.Command{ Long: `Requests a path from a specified orchestrated network device on the controller. The device UUID and request path must be specified as a positional arguments.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { did, err := uuid.Parse(args[0]) if err != nil { - log.Fatal(err) + pterm.Error.Println(err) + return err } - message, err := pndAdapter.Request( + res, err := pndAdapter.Request( createContextWithAuthorization(), did, args[1], ) if err != nil { - log.Error(err) + pterm.Error.Println(err) + return err } - log.Info(protojson.Format(message)) + for _, n := range res.Device { + panel1 := pterm.DefaultBox.WithTitle("Timestamp:").Sprint(n.GetTimestamp()) + panel2 := pterm.DefaultBox.WithTitle("Requested Path:").Sprint(args[1]) + panel3 := pterm.DefaultBox.WithTitle("Update:").Sprint(protojson.Format(n.Update[0])) + + panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{ + {{Data: panel1}}, + {{Data: panel2}}, + {{Data: panel3}}, + }).Srender() + + pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels) + } + return nil }, } diff --git a/cli/cmd/deviceList.go b/cli/cmd/deviceList.go index 3e0d7408fd8067b9351eb4166eb6e6d3485ca25c..c74939942fd69fa3411cde5301189b4d9d1afde7 100644 --- a/cli/cmd/deviceList.go +++ b/cli/cmd/deviceList.go @@ -32,8 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -46,23 +45,22 @@ var deviceListCmd = &cobra.Command{ Long: "List all orchestrated network devices within the current PND.", RunE: func(cmd *cobra.Command, args []string) error { - respONDs, err := pndAdapter.GetDevices(createContextWithAuthorization()) + spinner, _ := pterm.DefaultSpinner.Start("Fetching data from controller") + + resp, err := pndAdapter.GetDevices(createContextWithAuthorization()) if err != nil { + spinner.Fail(err) return err } - for i, dev := range respONDs { - log.Infof("OND %v: name: %v, uuid: %v", i+1, dev.Name, dev.Id) - sid, err := uuid.Parse(dev.GetSbi().GetId()) - if err != nil { - return err - } - tree, err := pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid) - if err != nil { - return err - } - log.Infof(" SchemaTree: %v", tree) + data := pterm.TableData{[]string{"UUID", "Name", "SBI-UUID", "SBI-Type"}} + for _, dev := range resp.GetOnd() { + data = append(data, []string{dev.GetId(), dev.GetName(), dev.GetSbi().GetId(), dev.GetSbi().GetType().String()}) } + + spinner.Success() + + pterm.DefaultTable.WithHasHeader().WithData(data).Render() return nil }, } diff --git a/cli/cmd/deviceRemove.go b/cli/cmd/deviceRemove.go index 37170c2de6127f7fe7cbc97705a87525dec29dfb..6cbdf8125fb4750ce1d2c3b6f893ed539e86604c 100644 --- a/cli/cmd/deviceRemove.go +++ b/cli/cmd/deviceRemove.go @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/google/uuid" "github.com/spf13/cobra" @@ -48,15 +48,18 @@ var deviceRemoveCmd = &cobra.Command{ The device UUID must be specified as a positional argument.`, RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Removing device with ID: ", args[0]) did, err := uuid.Parse(args[0]) if err != nil { + spinner.Fail(err) return err } - resp, err := pndAdapter.RemoveDevice(createContextWithAuthorization(), did) + _, err = pndAdapter.RemoveDevice(createContextWithAuthorization(), did) if err != nil { + spinner.Fail(err) return err } - log.Infof("Deletion of OND with ID %v: %s", did, resp.GetStatus().String()) + spinner.Success("PND has been deleted, ID: ", did.String()) return nil }, } diff --git a/cli/cmd/deviceSet.go b/cli/cmd/deviceSet.go index a8088d34a9e67c18a23d96e971b26198eaa64d55..8cd63cb2ad629f880b981f0f451ac86f0a16eb63 100644 --- a/cli/cmd/deviceSet.go +++ b/cli/cmd/deviceSet.go @@ -34,7 +34,7 @@ package cmd import ( ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -52,25 +52,38 @@ The device UUID, request path and value must be specified as positional argument To enable replacing behaviour (destructive!), set the --replace flag."`, Run: func(cmd *cobra.Command, args []string) { + spinner, _ := pterm.DefaultSpinner.Start("Create a path set request.") did, err := uuid.Parse(args[0]) if err != nil { - log.Fatal(err) + spinner.Fail(err) } var operation ppb.ApiOperation if replace { operation = ppb.ApiOperation_API_OPERATION_REPLACE - log.Info("Replace") + spinner.UpdateText("Replace generated and sent") } else { operation = ppb.ApiOperation_API_OPERATION_UPDATE - log.Info("Update") + spinner.UpdateText("Update generated and sent") } - log.Info(pndAdapter.ChangeOND( + + resp, err := pndAdapter.ChangeOND( createContextWithAuthorization(), did, operation, args[1], args[2], - )) + ) + if err != nil { + spinner.Fail(err) + } + + for _, r := range resp.GetResponses() { + if r.Status == ppb.Status_STATUS_OK { + spinner.Success("A change for Device: ", did.String(), "has been created -> Change ID: ", r.GetId()) + } else { + spinner.Fail("An error occured while creating a path set request for Device with ID: ", r.GetId(), r.GetStatus()) + } + } }, } diff --git a/cli/cmd/deviceShow.go b/cli/cmd/deviceShow.go index 7fb4198839ae0d72ce2995221af22efa315e5ef6..12b08b7269fbb435d4e83556122789a16d4a222a 100644 --- a/cli/cmd/deviceShow.go +++ b/cli/cmd/deviceShow.go @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -46,8 +46,30 @@ Device UUID or name must be specified as a positional argument. The device information returned is the information as currently stored in the controller. The actual device is not queried directly.`, - Run: func(cmd *cobra.Command, args []string) { - log.Info(pndAdapter.GetDevice(createContextWithAuthorization(), args[0])) + RunE: func(cmd *cobra.Command, args []string) error { + resp, err := pndAdapter.GetDevice(createContextWithAuthorization(), args[0]) + if err != nil { + pterm.Error.Println(err) + return err + } + + dev := resp.GetOnd() + + panel1 := pterm.DefaultBox.WithTitle("UUID:").Sprint(dev.Id) + panel2 := pterm.DefaultBox.WithTitle("Name:").Sprint(dev.Name) + panel3 := pterm.DefaultBox.WithTitle("SBI-UUID:").Sprint(dev.Sbi.Id) + panel4 := pterm.DefaultBox.WithTitle("SBI-Type:").Sprint(dev.Sbi.Type.String()) + + panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{ + {{Data: panel1}}, + {{Data: panel2}}, + {{Data: panel3}}, + {{Data: panel4}}, + }).Srender() + + pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels) + + return nil }, } diff --git a/cli/cmd/login.go b/cli/cmd/login.go index 3d9aba572e887642340628b92979cffec0662dcf..e1c8fdeb49fea104d263dbcc81dfe07f81eb63a7 100644 --- a/cli/cmd/login.go +++ b/cli/cmd/login.go @@ -35,7 +35,7 @@ import ( "context" "code.fbi.h-da.de/danet/gosdn/controller/api" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -48,25 +48,26 @@ var loginCmd = &cobra.Command{ User credentials need to be provided in the body`, RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Login attempt for user: ", nbUserName) + + if controllerAPIEndpoint != "" { + if err := viper.WriteConfig(); err != nil { + pterm.Error.Println("Could not write config:", err) + } + pterm.Info.Println("New controller address: ", viper.GetString("controllerAPIEndpoint")) + } + // TODO: maybe add credentials in context instead of context.TODO() resp, err := api.Login(context.TODO(), viper.GetString("controllerAPIEndpoint"), nbUserName, nbUserPwd) if err != nil { + spinner.Fail("Login failed: ", err) return err } - userToken = resp.Token - - if err := api.Init(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint")); err != nil { - return err - } + spinner.Success("Authentication for ", nbUserName, " was successful.") - sbiResp, err := api.GetSBIs(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), viper.GetString("CLI_PND")) - if err != nil { - return err - } - sid := sbiResp.Sbi[0].GetId() - viper.Set("CLI_SBI", sid) - log.Infof("SBI: %v", sid) + userToken = resp.Token + pterm.Info.Println("Authentication-User-Token:", userToken) return nil }, @@ -74,10 +75,17 @@ var loginCmd = &cobra.Command{ var nbUserName string var nbUserPwd string +var controllerAPIEndpoint string func init() { rootCmd.AddCommand(loginCmd) loginCmd.Flags().StringVar(&nbUserName, "u", "", "username for login") loginCmd.Flags().StringVar(&nbUserPwd, "p", "", "pwd for login") + loginCmd.Flags().StringVar(&controllerAPIEndpoint, "controller", viper.GetString("controllerAPIEndpoint"), "address of the controller") + + err := viper.BindPFlag("controllerAPIEndpoint", loginCmd.Flags().Lookup("controller")) + if err != nil { + pterm.Error.Println("Could not bind controllerAPIEndpoint:", err) + } } diff --git a/cli/cmd/pndCreate.go b/cli/cmd/pndCreate.go index f08d429d2685139006200e9ed21949baf79d9d7f..a2859604d68fe38b34a252aa1d56b5b9354346a2 100644 --- a/cli/cmd/pndCreate.go +++ b/cli/cmd/pndCreate.go @@ -32,18 +32,17 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( + "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core" "code.fbi.h-da.de/danet/gosdn/controller/api" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" - "google.golang.org/protobuf/encoding/protojson" - - log "github.com/sirupsen/logrus" ) // pndCreateCmd represents the create command var pndCreateCmd = &cobra.Command{ Use: "create [description]", - Args: cobra.ExactArgs(1), + Args: cobra.ExactArgs(0), Short: "creates a new principal network domain to the controller", Long: `A principal network domain is a main networking entity. This can be a campus building or site. @@ -52,21 +51,31 @@ A description must be passed as positional argument. A name and default SBI can passed using parameters.`, RunE: func(cmd *cobra.Command, args []string) error { - resp, err := api.AddPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), pndName, args[0], pndDefaultSbi) + spinner, _ := pterm.DefaultSpinner.Start("Creating new PND") + resp, err := api.AddPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), pndName, pndDescription, pndDefaultSbi) if err != nil { + spinner.Fail(err) return err } - log.Info(protojson.Format(resp)) + + if resp.Status == core.Status_STATUS_OK { + spinner.Success("PND has been created with name: ", pndName) + } else { + spinner.Fail("Failed creating the PND with name: ", pndName) + } + return nil }, } var pndName string var pndDefaultSbi string +var pndDescription string func init() { pndCmd.AddCommand(pndCreateCmd) pndCreateCmd.Flags().StringVar(&pndName, "name", "", "the name of the pnd") + pndCreateCmd.Flags().StringVar(&pndDescription, "description", "", "description of the pnd") pndCreateCmd.Flags().StringVar(&pndDefaultSbi, "sbi", "openconfig", "the default SBI of the pnd") } diff --git a/cli/cmd/pndGet.go b/cli/cmd/pndGet.go index ef5e36a32d68e9f149ca293ab10a6b51dfce03d8..735018a6f0077c51b07a5ba0c305d08d9b1c2954 100644 --- a/cli/cmd/pndGet.go +++ b/cli/cmd/pndGet.go @@ -32,7 +32,7 @@ package cmd import ( "code.fbi.h-da.de/danet/gosdn/controller/api" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -40,17 +40,31 @@ import ( // pndGetCmd represents the get command var pndGetCmd = &cobra.Command{ Use: "get", - Short: "get one or multiple PNDs by uuid or name and print them to stdout", - Long: `Get one or multiple PNDs by uuid or name and print them to stdout.`, + Args: cobra.ExactArgs(1), + Short: "Request a PND by uuid.", + Long: `Request a PND specified by uuid. The PND's UUID, Name and Description are returned.`, RunE: func(cmd *cobra.Command, args []string) error { - resp, err := api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), args...) + spinner, _ := pterm.DefaultSpinner.Start("Fetching requested PNDs from controller.") + resp, err := api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerApiEndpoint"), args[0]) if err != nil { + spinner.Fail(err) return err } - for i, pnd := range resp.Pnd { - log.Infof("PND %v: %v\n\tuuid: %v", i+1, pnd.Name, pnd.Id) - } + + pnd := resp.Pnd + panel1 := pterm.DefaultBox.WithTitle("UUID:").Sprint(pnd.Id) + panel2 := pterm.DefaultBox.WithTitle("Name:").Sprint(pnd.Name) + panel3 := pterm.DefaultBox.WithTitle("Description:").Sprint(pnd.Description) + + panels, _ := pterm.DefaultPanel.WithPanels(pterm.Panels{ + {{Data: panel1}}, + {{Data: panel2}}, + {{Data: panel3}}, + }).Srender() + + spinner.Success() + pterm.DefaultBox.WithRightPadding(0).WithBottomPadding(0).Println(panels) return nil }, } diff --git a/cli/cmd/pndList.go b/cli/cmd/pndList.go index 2f44d74b661e3df3ab5593eb7d2d93d05dcb6868..65006b0c7705f8896abd7c81900420a23be2bee4 100644 --- a/cli/cmd/pndList.go +++ b/cli/cmd/pndList.go @@ -33,7 +33,7 @@ package cmd import ( "code.fbi.h-da.de/danet/gosdn/controller/api" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) @@ -46,14 +46,21 @@ var pndListCmd = &cobra.Command{ Long: `List all information about the current PND.`, RunE: func(cmd *cobra.Command, args []string) error { - - resp, err := api.GetPnd(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String()) + spinner, _ := pterm.DefaultSpinner.Start("Fetching PND list from controller") + resp, err := api.GetPnds(createContextWithAuthorization(), pndAdapter.Endpoint()) if err != nil { + spinner.Fail(err) return err } - for i, pnd := range resp.Pnd { - log.Infof("PND %v: name: %v, uuid: %v", i+1, pnd.Name, pnd.Id) + + data := pterm.TableData{[]string{"UUID", "Name", "Description"}} + for _, pnd := range resp.Pnd { + data = append(data, []string{pnd.GetId(), pnd.GetName(), pnd.GetDescription()}) } + + spinner.Success() + + pterm.DefaultTable.WithHasHeader().WithData(data).Render() return nil }, } diff --git a/cli/cmd/pndRemove.go b/cli/cmd/pndRemove.go index ed4890a7581d014c938eef65a7c5db2f4cd3b03d..98fb573ee900a245d8e39e6312876a9e01d25d06 100644 --- a/cli/cmd/pndRemove.go +++ b/cli/cmd/pndRemove.go @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. package cmd import ( - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/google/uuid" "github.com/spf13/cobra" @@ -42,19 +42,22 @@ import ( var pndRemoveCmd = &cobra.Command{ Use: "remove", Aliases: []string{"rm"}, - Short: "TODO - not yet implemented", - Long: `TODO - not yet implemented`, + Short: "Removes the PND with the provided ID", + Long: "Removes the PND with the provided ID", RunE: func(cmd *cobra.Command, args []string) error { + spinner, _ := pterm.DefaultSpinner.Start("Removing PND with ID: ", args[0]) pid, err := uuid.Parse(args[0]) if err != nil { + spinner.Fail(err) return err } - resp, err := pndAdapter.RemovePnd(createContextWithAuthorization(), pid) + _, err = pndAdapter.RemovePnd(createContextWithAuthorization(), pid) if err != nil { + spinner.Fail(err) return err } - log.Infof("Deletion of PND with ID %v: %s", pid, resp.GetStatus().String()) + spinner.Success("PND has been deleted, ID: ", pid.String()) return nil }, } diff --git a/cli/cmd/pndUse.go b/cli/cmd/pndUse.go index 22be64cab7dfa2a0402b4c1b828a36c1f307e4ac..f3f77d7970d321bda990c5f658e19093ad4fc6ba 100644 --- a/cli/cmd/pndUse.go +++ b/cli/cmd/pndUse.go @@ -34,7 +34,7 @@ package cmd import ( "code.fbi.h-da.de/danet/gosdn/cli/adapter" "code.fbi.h-da.de/danet/gosdn/controller/api" - log "github.com/sirupsen/logrus" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -51,25 +51,32 @@ var pndUseCmd = &cobra.Command{ newPndAdapter, err := adapter.NewPndAdapter(newPND, viper.GetString("controllerAPIEndpoint")) if err != nil { - log.Fatal(err) + pterm.Error.Println(err) return err } _, err = api.GetPnd(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), newPND) if err != nil { - log.Fatal(err) + pterm.Error.Println(err) + return err + } + + sbi, err := api.GetSBIs(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint"), newPND) + if err != nil { + pterm.Error.Println(err) return err } viper.Set("CLI_PND", newPND) + viper.Set("CLI_SBI", sbi.GetSbi()[0].GetId()) err = viper.WriteConfig() if err != nil { - log.Fatal(err) + pterm.Error.Println(err) return err } pndAdapter = newPndAdapter - log.Infof("PND with ID: %s set for usage", pndAdapter.ID().String()) + pterm.Info.Printf("PND with ID: %s has been set for usage.\n", pndAdapter.ID().String()) return nil }, } diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go index e9704be94b631c7c17c75e8fa744f8c0ef8ae7f8..20be885d3f62c66c944dbf81f5492af868a640b4 100644 --- a/cli/cmd/prompt.go +++ b/cli/cmd/prompt.go @@ -36,21 +36,23 @@ import ( "os" "strings" - "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" "code.fbi.h-da.de/danet/gosdn/cli/completer" + "code.fbi.h-da.de/danet/gosdn/controller/api" "github.com/c-bata/go-prompt" "github.com/google/uuid" + "github.com/openconfig/goyang/pkg/yang" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/spf13/viper" ) -var suggestions []prompt.Suggest - // PromptCompleter provides completion for a device type PromptCompleter struct { - //NOTE: not too sure about this but for now it should be sufficient - deviceID uuid.UUID yangSchemaCompleterMap map[uuid.UUID]*completer.YangSchemaCompleter + currentSuggestions []prompt.Suggest + document *prompt.Document + history []string } // NewPromptCompleter returns a new promptCompleter @@ -62,25 +64,35 @@ func NewPromptCompleter() *PromptCompleter { // Run starts the interactive completion func (pc *PromptCompleter) Run() { - fmt.Println("Welcome to the interactive mode of gosdnc.") - defer fmt.Println("Bye!") + title, _ := pterm.DefaultBigText.WithLetters( + pterm.NewLettersFromString("go"), + pterm.NewLettersFromStringWithStyle("SDN", pterm.NewStyle(pterm.FgCyan)), + pterm.NewLettersFromString("c"), + ).Srender() + description := pterm.DefaultBasicText.Sprint("Control your goSDN controller like you've never done it before!") + pterm.DefaultCenter.Println(title) + pterm.DefaultCenter.Println(description) p := prompt.New( executeFunc, pc.cstmCompleter, prompt.OptionTitle("gosdnc-prompt: interactive gosdn CLI"), prompt.OptionPrefix(">>> "), + prompt.OptionPrefixTextColor(prompt.Cyan), prompt.OptionCompletionWordSeparator(completer.YangSchemaCompletionSeperator), prompt.OptionShowCompletionAtStart(), - prompt.OptionSuggestionBGColor(prompt.DarkBlue), - prompt.OptionSuggestionTextColor(prompt.DarkGray), - prompt.OptionDescriptionTextColor(prompt.White), - prompt.OptionDescriptionBGColor(prompt.DarkGray), - prompt.OptionSelectedSuggestionBGColor(prompt.DarkRed), + prompt.OptionCompletionOnDown(), + prompt.OptionHistory(pc.history), + prompt.OptionSuggestionBGColor(prompt.DarkGray), + prompt.OptionSuggestionTextColor(prompt.LightGray), + prompt.OptionDescriptionTextColor(prompt.DarkGray), + prompt.OptionDescriptionBGColor(prompt.LightGray), + prompt.OptionSelectedSuggestionBGColor(prompt.Cyan), prompt.OptionSelectedSuggestionTextColor(prompt.DarkGray), - prompt.OptionSelectedDescriptionBGColor(prompt.DarkGray), - prompt.OptionSelectedDescriptionTextColor(prompt.White), + prompt.OptionSelectedDescriptionBGColor(prompt.LightGray), + prompt.OptionSelectedDescriptionTextColor(prompt.DarkGray), ) + p.Run() } @@ -96,106 +108,231 @@ func executeFunc(s string) { } } -func flagVisitor(f *pflag.Flag) { - if !f.Hidden { - suggestions = append(suggestions, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage}) - } -} - func (pc *PromptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest { // Start with the cobra 'rootCmd' and walk through it // Reference: https://github.com/stromland/cobra-prompt currCmd := rootCmd - inputSplit := removeFlagsFromInputSlice(strings.Fields(d.CurrentLine())) - if c, _, err := currCmd.Find(inputSplit); err == nil { + inputSplit := strings.Fields(d.CurrentLine()) + inputSplitFiltered, inputFlags := filterFlagSlice(inputSplit) + if c, _, err := currCmd.Find(inputSplitFiltered); err == nil { currCmd = c } - return completionBasedOnCmd(pc, currCmd, inputSplit, d) + return completionBasedOnCmd(pc, currCmd, inputSplitFiltered, inputFlags, d) } -func removeFlagsFromInputSlice(input []string) []string { - r := []string{} +func filterFlagSlice(input []string) (commandSlice []string, flagSlice []string) { for _, in := range input { if !strings.HasPrefix(in, "--") { - r = append(r, in) + commandSlice = append(commandSlice, in) + } else { + flagSlice = append(flagSlice, strings.Split(in, "=")[0]) } } - return r + return commandSlice, flagSlice } func deviceGetCompletion(c *PromptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest { - inputLen := len(inputSplit) - if inputLen == 2 || inputLen == 3 { - if id, err := uuid.Parse(inputSplit[inputLen-1]); err == nil { - if c, ok := c.yangSchemaCompleterMap[id]; ok { - return c.Complete(d) - } - dev, err := pndAdapter.GetDevice(createContextWithAuthorization(), id.String()) - if err != nil { - return []prompt.Suggest{} - } - sid, err := uuid.Parse(dev[0].GetSbi().GetId()) - if err != nil { - return []prompt.Suggest{} - } - schemaTree, err := pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid) - if err != nil { - return []prompt.Suggest{} - } - c.yangSchemaCompleterMap[id] = completer.NewYangSchemaCompleter(schemaTree["Device"], true) - if yc, ok := c.yangSchemaCompleterMap[id]; ok { - c.deviceID = id - return yc.Complete(d) - } - + switch inputLen := len(inputSplit); inputLen { + case 2: + return c.updateSuggestionsThroughFunc(d, getDevices) + case 3: + id, err := uuid.Parse(inputSplit[inputLen-1]) + if err != nil { + return c.updateSuggestionsThroughFunc(d, getDevices) + } + if c, ok := c.yangSchemaCompleterMap[id]; ok { + return c.Complete(d) + } + schemaTree, err := getSchemaTreeForDeviceID(id.String()) + if err != nil { return []prompt.Suggest{} } - if inputLen == 2 || (inputLen == 3 && !(d.GetWordBeforeCursor() == "")) { - return prompt.FilterHasPrefix(getDevices(), d.GetWordBeforeCursor(), true) + c.yangSchemaCompleterMap[id] = completer.NewYangSchemaCompleter(schemaTree["Device"], true) + if yc, ok := c.yangSchemaCompleterMap[id]; ok { + return yc.Complete(d) + } + case 4: + if d.GetWordBeforeCursor() == "" || d.GetWordAfterCursor() != "" { + return []prompt.Suggest{} + } + id, err := uuid.Parse(inputSplit[inputLen-2]) + if err != nil { + return c.updateSuggestionsThroughFunc(d, getDevices) } - } else { - if yc, ok := c.yangSchemaCompleterMap[c.deviceID]; ok { + if yc, ok := c.yangSchemaCompleterMap[id]; ok { return yc.Complete(d) } + default: return []prompt.Suggest{} } return []prompt.Suggest{} } -func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, loaded []prompt.Suggest) []prompt.Suggest { - suggestions = []prompt.Suggest{} - if len(loaded) > 0 { - suggestions = append(suggestions, loaded...) +func (pc *PromptCompleter) updateSuggestionsThroughFunc(d prompt.Document, fn func() ([]prompt.Suggest, error)) []prompt.Suggest { + if pc.currentSuggestions == nil { + var err error + pc.currentSuggestions, err = fn() + if err != nil { + return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true) + } } + return prompt.FilterHasPrefix(pc.currentSuggestions, d.GetWordBeforeCursor(), true) +} + +func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, inputFlags []string, loaded []prompt.Suggest) []prompt.Suggest { if currCmd.HasAvailableFlags() { - // it would be possible to always show the inherited flags, but i think - // this is currently not necessary. - // currCmd.InheritedFlags().VisitAll(flagVisitor) - currCmd.LocalFlags().VisitAll(flagVisitor) + currCmd.LocalFlags().VisitAll( + func(f *pflag.Flag) { + if !f.Hidden && !sliceContains(inputFlags, "--"+f.Name) { + loaded = append(loaded, prompt.Suggest{Text: "--" + f.Name, Description: f.Usage}) + } + }, + ) } for _, cmd := range currCmd.Commands() { - suggestions = append(suggestions, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short}) + loaded = append(loaded, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short}) } - return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true) + + return prompt.FilterHasPrefix(loaded, d.GetWordBeforeCursor(), true) } -func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, d prompt.Document) []prompt.Suggest { +//nolint +func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, inputFlags []string, d prompt.Document) []prompt.Suggest { switch cmd { - case pndUseCmd, pndGetCmd: - return cobraCommandCompletion(cmd, d, getPnds()) + case pndUseCmd, pndGetCmd, pndRemoveCmd: + if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") { + suggestions := c.updateSuggestionsThroughFunc(d, getPnds) + return cobraCommandCompletion(cmd, d, inputFlags, suggestions) + } case commitCmd: - return getChangesByType(pnd.ChangeState_CHANGE_STATE_PENDING) + if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") { + return c.updateSuggestionsThroughFunc(d, getCommitedChanges) + } case confirmCmd: - return getChangesByType(pnd.ChangeState_CHANGE_STATE_COMMITTED) + if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") { + return c.updateSuggestionsThroughFunc(d, getConfirmedChanges) + } + case deviceRemoveCmd: + if len(inputSplit) < 3 || (len(inputSplit) == 3 && d.GetWordBeforeCursor() != "") { + return c.updateSuggestionsThroughFunc(d, getDevices) + } case deviceGetCmd, deviceSetCmd: return deviceGetCompletion(c, d, inputSplit) case deviceShowCmd: - return getDevices() + devices, err := getDevices() + if err != nil { + return []prompt.Suggest{} + } + return devices + case deviceCmd, pndCmd, changeCmd: + c.currentSuggestions = nil + return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{}) default: - return cobraCommandCompletion(cmd, d, []prompt.Suggest{}) + return cobraCommandCompletion(cmd, d, inputFlags, []prompt.Suggest{}) + } + + return []prompt.Suggest{} +} + +// getDevices is a helper function which requests devices from the controller +// and gives feedback about the current pulling status with the help of pterm +// the result is converted into a prompt.Suggest slice. +func getDevices() ([]prompt.Suggest, error) { + spinner, _ := pterm.DefaultSpinner.Start("Fetching devices from controller.") + resp, err := pndAdapter.GetDevices(createContextWithAuthorization()) + if err != nil { + spinner.Fail(err) + return []prompt.Suggest{}, err + } + + s := []prompt.Suggest{} + for _, ond := range resp.Ond { + s = append(s, prompt.Suggest{Text: ond.GetId(), Description: ond.GetName()}) + } + spinner.Success() + return completer.SortSuggestionByText(s), nil +} + +// getSchemaTreeForDeviceID is a helper function which requests the SBI's +// schema tree of a specific device. The function gives feedback about the +// current pulling status with the help of pterm. +func getSchemaTreeForDeviceID(id string) (map[string]*yang.Entry, error) { + spinner, _ := pterm.DefaultSpinner.Start("Fetching schema tree for Device with ID: ", id) + dev, err := pndAdapter.GetDevice(createContextWithAuthorization(), id) + if err != nil { + spinner.Fail(err) + return nil, err + } + sid, err := uuid.Parse(dev.GetOnd().GetSbi().GetId()) + if err != nil { + spinner.Fail(err) + return nil, err + } + spinner.Success() + return pndAdapter.GetSbiSchemaTree(createContextWithAuthorization(), sid) +} + +// getPnds is a helper function which requests pnds from the controller and +// gives feedback about the current pulling status with the help of pterm the +// result is converted into a prompt.Suggest slice. +func getPnds() ([]prompt.Suggest, error) { + spinner, _ := pterm.DefaultSpinner.Start("Fetching PNDs from controller.") + resp, err := api.GetIds(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint")) + if err != nil { + spinner.Fail(err) + return []prompt.Suggest{}, err + } + + s := []prompt.Suggest{} + for _, pnd := range resp { + s = append(s, prompt.Suggest{Text: pnd.GetId(), Description: pnd.GetDescription()}) + } + spinner.Success() + return completer.SortSuggestionByText(s), nil +} + +// getCommitedChanges is a helper function which requests all the commited +// changes from the controller and gives feedback about the current pulling +// status with the help of pterm the result is converted into a prompt.Suggest +// slice. +func getCommitedChanges() ([]prompt.Suggest, error) { + spinner, _ := pterm.DefaultSpinner.Start("Fetching commited changes.") + + resp, err := pndAdapter.CommittedChanges(createContextWithAuthorization()) + if err != nil { + spinner.Fail(err) + return []prompt.Suggest{}, err + } + + s := []prompt.Suggest{} + for _, change := range resp { + s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()}) + } + spinner.Success() + return completer.SortSuggestionByText(s), nil +} + +// getConfirmedChanges is a helper function which requests all the confirmed +// changes from the controller and gives feedback about the current pulling +// status with the help of pterm the result is converted into a prompt.Suggest +// slice. +func getConfirmedChanges() ([]prompt.Suggest, error) { + spinner, _ := pterm.DefaultSpinner.Start("Fetching confirmed changes.") + + resp, err := pndAdapter.ConfirmedChanges(createContextWithAuthorization()) + if err != nil { + spinner.Fail(err) + return []prompt.Suggest{}, err + } + + s := []prompt.Suggest{} + for _, change := range resp { + s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()}) } + spinner.Success() + return completer.SortSuggestionByText(s), nil } var exitCmd = &cobra.Command{ diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 3fdfffe2095ed8c681896c51683fdde555236579..bf5c804082d791d811db3f991fb88f40ed0ba1ce 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -67,7 +67,8 @@ The login command must be called for authorization. // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - cobra.CheckErr(rootCmd.Execute()) + rootCmd.Execute() + //cobra.CheckErr(rootCmd.Execute()) } func init() { diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go index cf6a0378032e6d3305564603ffb893089c2541d0..0e5df4a663be835a9701806ff9bff5e1d6b07a02 100644 --- a/cli/cmd/utils.go +++ b/cli/cmd/utils.go @@ -36,11 +36,6 @@ import ( "errors" "net" - "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" - "code.fbi.h-da.de/danet/gosdn/cli/completer" - "code.fbi.h-da.de/danet/gosdn/controller/api" - "github.com/c-bata/go-prompt" - "github.com/spf13/viper" "google.golang.org/grpc/metadata" ) @@ -60,45 +55,14 @@ func checkIPPort(string) error { return nil } -func getDevices() []prompt.Suggest { - resp, err := api.GetDevices(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String()) - if err != nil { - return []prompt.Suggest{} - } - - s := []prompt.Suggest{} - for _, ond := range resp.Ond { - s = append(s, prompt.Suggest{Text: ond.GetId(), Description: ond.GetName()}) - } - return completer.SortSuggestionByText(s) -} - -func getPnds() []prompt.Suggest { - resp, err := api.GetIds(createContextWithAuthorization(), viper.GetString("controllerAPIEndpoint")) - if err != nil { - return []prompt.Suggest{} - } - - s := []prompt.Suggest{} - for _, pnd := range resp { - s = append(s, prompt.Suggest{Text: pnd.GetId(), Description: pnd.GetDescription()}) - } - return completer.SortSuggestionByText(s) -} - -func getChangesByType(cType pnd.ChangeState) []prompt.Suggest { - resp, err := api.GetChanges(createContextWithAuthorization(), pndAdapter.Endpoint(), pndAdapter.ID().String()) - if err != nil { - return []prompt.Suggest{} - } - - s := []prompt.Suggest{} - for _, change := range resp.GetChange() { - if change.GetState() == cType { - s = append(s, prompt.Suggest{Text: change.GetId(), Description: change.State.String()}) +// sliceContains checks if a slice contains the given item +func sliceContains[T comparable](slice []T, toCompare T) bool { + for _, sliceEntry := range slice { + if sliceEntry == toCompare { + return true } } - return completer.SortSuggestionByText(s) + return false } func createContextWithAuthorization() context.Context { diff --git a/controller/Makefile b/controller/Makefile index 1ca977f2b730d2b27c1feb07c955291e66a52dd5..fdedd2e7b5ae2d83ed942cd18fe1573a2348c160 100644 --- a/controller/Makefile +++ b/controller/Makefile @@ -53,7 +53,7 @@ ci-unit-test: ci-install-tools ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -short -race $$( go list ./... | grep -v /forks/ | grep -v /mocks ) -v -coverprofile=coverage.out ci-controller-test: ci-install-tools - ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun + ENVIRONMENT=testing gotestsum --junitfile report.xml --format testname -- -race -v -run TestRun -coverprofile=coverage.out integration-test-nucleus: ENVIRONMENT=testing &&\ diff --git a/controller/api/apiIntegration_test.go b/controller/api/apiIntegration_test.go index 8a288847339ff1ff24aa6388d0cad891b469de3c..a97a54820db061d3e85f91105982bb903c2547cb 100644 --- a/controller/api/apiIntegration_test.go +++ b/controller/api/apiIntegration_test.go @@ -86,7 +86,6 @@ func TestApiIntegration(t *testing.T) { context.TODO(), testAPIEndpoint, cliPnd, - "", did, ) if (err != nil) != tt.wantErr { @@ -109,7 +108,7 @@ func TestApiIntegration(t *testing.T) { return } - resp, err := GetDevice(context.TODO(), testAddress, testUsername, testPassword, testPath) + resp, err := GetDevice(context.TODO(), testAddress, testUsername, testPassword) if err != nil { if !tt.wantErr { t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) @@ -118,7 +117,7 @@ func TestApiIntegration(t *testing.T) { } var got string if resp != nil { - got = resp.Ond[0].Name + got = resp.Ond.Name } else { t.Errorf("integration test failed got cannot be nil") } diff --git a/controller/api/api_test.go b/controller/api/api_test.go index 0f4f904af2aa7dedc1a393879e137cccf037145e..a789e65b18d39981c98b18b2c2b60219849ff011 100644 --- a/controller/api/api_test.go +++ b/controller/api/api_test.go @@ -47,7 +47,7 @@ func Test_GetPnd(t *testing.T) { t.Error(err) return } - got := resp.Pnd[0].Id + got := resp.Pnd.Id if got != pndID { t.Errorf("PND ID is %v, expected %v", got, pndID) } @@ -101,7 +101,7 @@ func Test_GetDevice(t *testing.T) { t.Error(err) return } - got := resp.Ond[0].Id + got := resp.Ond.Id if got != ondID { t.Errorf("PND ID is %v, expected %v", got, ondID) } diff --git a/controller/api/change.go b/controller/api/change.go index e469db6c1f584bd139d9f6127b70af7aa74abd39..57b82608554a78c6dd892557b300df9cdd6ee4c1 100644 --- a/controller/api/change.go +++ b/controller/api/change.go @@ -2,6 +2,7 @@ package api import ( "context" + "errors" "time" ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" @@ -21,6 +22,23 @@ func GetChanges(ctx context.Context, addr, pnd string) (*ppb.GetChangeListRespon return client.GetChangeList(ctx, req) } +// GetChange requests one or more changes from the controller +func GetChange(ctx context.Context, addr string, pnd string, args ...string) (*ppb.GetChangeResponse, error) { + client, err := nbi.PndClient(addr, dialOptions...) + if err != nil { + return nil, err + } + if len(args) <= 0 { + return nil, errors.New("not enough arguments") + } + req := &ppb.GetChangeRequest{ + Timestamp: time.Now().UnixNano(), + Pid: pnd, + Cuid: args, + } + return client.GetChange(ctx, req) +} + // Commit sends a Commit request for one or multiple changes to the // controller. func Commit(ctx context.Context, addr, pnd string, cuids ...string) (*ppb.SetChangeListResponse, error) { @@ -61,9 +79,10 @@ func CommitConfirm(ctx context.Context, addr, pnd string, changes []*ppb.SetChan return client.SetChangeList(ctx, req) } -// ChangeRequest change creates a ChangeRequest for the specified OND. ApiOperations are -// used to specify the type of the change (update, replace, delete as specified -// in https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state) +// ChangeRequest creates a ChangeRequest for the specified OND. ApiOperations +// are used to specify the type of the change (update, replace, delete as +// specified in +// https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state) // For delete operations the value field needs to contain an empty string. func ChangeRequest(ctx context.Context, addr, did, pid, path, value string, op ppb.ApiOperation) (*ppb.SetPathListResponse, error) { req := &ppb.ChangeRequest{ diff --git a/controller/api/device.go b/controller/api/device.go index b8c6a00141d54df49b6db447e549f18fa782e8b2..9ac80f41bf95713d42959155e1dc51c7d161ab58 100644 --- a/controller/api/device.go +++ b/controller/api/device.go @@ -52,7 +52,7 @@ func AddDevice(ctx context.Context, addr, deviceName string, opt *tpb.TransportO // GetDevice requests one device belonging to a given // PrincipalNetworkDomain from the controller. If no device identifier // is provided, an error is thrown. -func GetDevice(ctx context.Context, addr, pid string, did ...string) (*ppb.GetOndResponse, error) { +func GetDevice(ctx context.Context, addr, pid string, did string) (*ppb.GetOndResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err diff --git a/controller/api/initialise_test.go b/controller/api/initialise_test.go index 5a8e97231f32e8a287b79ae266424364e93c60b1..bdd70085037ef49cedd18f19aa2ba437871e6405 100644 --- a/controller/api/initialise_test.go +++ b/controller/api/initialise_test.go @@ -85,9 +85,26 @@ func bootstrapUnitTest() { userService = rbacImpl.NewUserService(rbacImpl.NewMemoryUserStore()) roleService = rbacImpl.NewRoleService(rbacImpl.NewMemoryRoleStore()) + previousHostname := "previousHostname" + intendedHostname := "intendedHostname" + mockChange := &mocks.Change{} mockChange.On("Age").Return(time.Hour) mockChange.On("State").Return(ppb.ChangeState_CHANGE_STATE_INCONSISTENT) + mockChange.On("PreviousState").Return(&openconfig.Device{ + System: &openconfig.OpenconfigSystem_System{ + Config: &openconfig.OpenconfigSystem_System_Config{ + Hostname: &previousHostname, + }, + }, + }) + mockChange.On("IntendedState").Return(&openconfig.Device{ + System: &openconfig.OpenconfigSystem_System{ + Config: &openconfig.OpenconfigSystem_System_Config{ + Hostname: &intendedHostname, + }, + }, + }) mockPnd := mocks.NetworkDomain{} mockPnd.On("ID").Return(pndUUID) @@ -96,7 +113,7 @@ func bootstrapUnitTest() { mockPnd.On("PendingChanges").Return([]uuid.UUID{changeUUID}) mockPnd.On("CommittedChanges").Return([]uuid.UUID{changeUUID}) mockPnd.On("GetChange", mock.Anything).Return(mockChange, nil) - mockPnd.On("AddDevice", mock.Anything, mock.Anything, mock.Anything).Return(nil) + mockPnd.On("AddDevice", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mockPnd.On("GetDevice", mock.Anything).Return(&nucleus.CommonDevice{ UUID: deviceUUID, Model: &openconfig.Device{}, diff --git a/controller/api/pnd.go b/controller/api/pnd.go index 791ebefc6d425580547364ff7ee28509100938d2..a6c9eb0ac0e9c3eb57d88db980c702fd9ebf7b9e 100644 --- a/controller/api/pnd.go +++ b/controller/api/pnd.go @@ -33,7 +33,7 @@ func AddPnd(ctx context.Context, addr, name, description, sbi string) (*pb.Creat // GetPnd requests one PrincipalNetworkDomain from the // controller. -func GetPnd(ctx context.Context, addr string, args ...string) (*pb.GetPndResponse, error) { +func GetPnd(ctx context.Context, addr string, args string) (*pb.GetPndResponse, error) { coreClient, err := nbi.CoreClient(addr, dialOptions...) if err != nil { return nil, err @@ -56,9 +56,6 @@ func GetPnds(ctx context.Context, addr string, args ...string) (*pb.GetPndListRe if err != nil { return nil, err } - if len(args) <= 0 { - return nil, errors.New("not enough arguments") - } req := &pb.GetPndListRequest{ Timestamp: time.Now().UnixNano(), diff --git a/controller/api/sbi.go b/controller/api/sbi.go index 30de02ab087ea5c0698a80d96eaeb76505d26b6f..e34ec6a9d4c61fdbc52dc3876770a7515b7501e2 100644 --- a/controller/api/sbi.go +++ b/controller/api/sbi.go @@ -10,7 +10,7 @@ import ( // GetSbi requests one or more to the provided PND belonging SBIs from the // controller. -func GetSbi(ctx context.Context, addr string, pid string, sid ...string) (*ppb.GetSbiResponse, error) { +func GetSbi(ctx context.Context, addr string, pid string, sid string) (*ppb.GetSbiResponse, error) { client, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err diff --git a/controller/interfaces/change/change.go b/controller/interfaces/change/change.go index ba8075db9dd3b7c4f85b872b947a084c8a19f076..40e8cc90ecbba6985a92989ecfeb81f09f265597 100644 --- a/controller/interfaces/change/change.go +++ b/controller/interfaces/change/change.go @@ -18,6 +18,8 @@ type Change interface { Confirm() error State() ppb.ChangeState Age() time.Duration + PreviousState() ygot.GoStruct + IntendedState() ygot.GoStruct } // Payload contains two ygot.GoStructs, the first represents the original state diff --git a/controller/interfaces/networkdomain/pnd.go b/controller/interfaces/networkdomain/pnd.go index 2c86f6260acc4da3d2eba8b84688fe659592c68e..fc9dec411c54ec8a1877445401bb801f37aec274 100644 --- a/controller/interfaces/networkdomain/pnd.go +++ b/controller/interfaces/networkdomain/pnd.go @@ -16,7 +16,7 @@ type NetworkDomain interface { Destroy() error AddSbi(s southbound.SouthboundInterface) error RemoveSbi(uuid.UUID) error - AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) error + AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error) GetDevice(identifier string) (device.Device, error) RemoveDevice(uuid.UUID) error Devices() []device.Device diff --git a/controller/mocks/Change.go b/controller/mocks/Change.go index 9c3e9b9f26cddfe94a04c0e0d1a68b8f248dfa3a..fb370384e3fbc8e3ee90bc09e28fbe39cad807e2 100644 --- a/controller/mocks/Change.go +++ b/controller/mocks/Change.go @@ -1,14 +1,18 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks import ( - time "time" + testing "testing" pnd "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" mock "github.com/stretchr/testify/mock" + time "time" + uuid "github.com/google/uuid" + + ygot "github.com/openconfig/ygot/ygot" ) // Change is an autogenerated mock type for the Change type @@ -74,6 +78,38 @@ func (_m *Change) ID() uuid.UUID { return r0 } +// IntendedState provides a mock function with given fields: +func (_m *Change) IntendedState() ygot.GoStruct { + ret := _m.Called() + + var r0 ygot.GoStruct + if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ygot.GoStruct) + } + } + + return r0 +} + +// PreviousState provides a mock function with given fields: +func (_m *Change) PreviousState() ygot.GoStruct { + ret := _m.Called() + + var r0 ygot.GoStruct + if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ygot.GoStruct) + } + } + + return r0 +} + // State provides a mock function with given fields: func (_m *Change) State() pnd.ChangeState { ret := _m.Called() @@ -87,3 +123,12 @@ func (_m *Change) State() pnd.ChangeState { return r0 } + +// NewChange creates a new instance of Change. It also registers a cleanup function to assert the mocks expectations. +func NewChange(t testing.TB) *Change { + mock := &Change{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/Device.go b/controller/mocks/Device.go index 5004309d1d439424d96d31b581b3e5f915d7f3bb..4b42cddd742c8809f09c16d2911ddc6d05f80cd2 100644 --- a/controller/mocks/Device.go +++ b/controller/mocks/Device.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks @@ -7,6 +7,8 @@ import ( mock "github.com/stretchr/testify/mock" protoreflect "google.golang.org/protobuf/reflect/protoreflect" + testing "testing" + transport "code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport" uuid "github.com/google/uuid" @@ -19,32 +21,32 @@ type Device struct { mock.Mock } -// ID provides a mock function with given fields: -func (_m *Device) ID() uuid.UUID { +// GetModel provides a mock function with given fields: +func (_m *Device) GetModel() ygot.ValidatedGoStruct { ret := _m.Called() - var r0 uuid.UUID - if rf, ok := ret.Get(0).(func() uuid.UUID); ok { + var r0 ygot.ValidatedGoStruct + if rf, ok := ret.Get(0).(func() ygot.ValidatedGoStruct); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(uuid.UUID) + r0 = ret.Get(0).(ygot.ValidatedGoStruct) } } return r0 } -// Model provides a mock function with given fields: -func (_m *Device) Model() ygot.GoStruct { +// ID provides a mock function with given fields: +func (_m *Device) ID() uuid.UUID { ret := _m.Called() - var r0 ygot.GoStruct - if rf, ok := ret.Get(0).(func() ygot.GoStruct); ok { + var r0 uuid.UUID + if rf, ok := ret.Get(0).(func() uuid.UUID); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(ygot.GoStruct) + r0 = ret.Get(0).(uuid.UUID) } } @@ -110,3 +112,12 @@ func (_m *Device) Transport() transport.Transport { return r0 } + +// NewDevice creates a new instance of Device. It also registers a cleanup function to assert the mocks expectations. +func NewDevice(t testing.TB) *Device { + mock := &Device{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/NetworkDomain.go b/controller/mocks/NetworkDomain.go index 607db2834b1e53331278f1cc1ddcb153790f67a8..22e6e7bfc2f65a0316466d46598827dc31eb621c 100644 --- a/controller/mocks/NetworkDomain.go +++ b/controller/mocks/NetworkDomain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks @@ -14,6 +14,8 @@ import ( southbound "code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound" + testing "testing" + transport "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" uuid "github.com/google/uuid" @@ -25,17 +27,26 @@ type NetworkDomain struct { } // AddDevice provides a mock function with given fields: name, opts, sid -func (_m *NetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) error { +func (_m *NetworkDomain) AddDevice(name string, opts *transport.TransportOption, sid uuid.UUID) (uuid.UUID, error) { ret := _m.Called(name, opts, sid) - var r0 error - if rf, ok := ret.Get(0).(func(string, *transport.TransportOption, uuid.UUID) error); ok { + var r0 uuid.UUID + if rf, ok := ret.Get(0).(func(string, *transport.TransportOption, uuid.UUID) uuid.UUID); ok { r0 = rf(name, opts, sid) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(uuid.UUID) + } } - return r0 + var r1 error + if rf, ok := ret.Get(1).(func(string, *transport.TransportOption, uuid.UUID) error); ok { + r1 = rf(name, opts, sid) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // AddSbi provides a mock function with given fields: s @@ -393,3 +404,12 @@ func (_m *NetworkDomain) RequestAll(_a0 string) error { return r0 } + +// NewNetworkDomain creates a new instance of NetworkDomain. It also registers a cleanup function to assert the mocks expectations. +func NewNetworkDomain(t testing.TB) *NetworkDomain { + mock := &NetworkDomain{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/Plugin.go b/controller/mocks/Plugin.go index f69729e0c9536a06314fca0e65d3f9b56157af3c..b6d86b9165866a110766c87bbd51b7d8934f3108 100644 --- a/controller/mocks/Plugin.go +++ b/controller/mocks/Plugin.go @@ -1,11 +1,14 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks import ( + testing "testing" + plugin "code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin" - uuid "github.com/google/uuid" mock "github.com/stretchr/testify/mock" + + uuid "github.com/google/uuid" ) // Plugin is an autogenerated mock type for the Plugin type @@ -86,3 +89,12 @@ func (_m *Plugin) Update() error { return r0 } + +// NewPlugin creates a new instance of Plugin. It also registers a cleanup function to assert the mocks expectations. +func NewPlugin(t testing.TB) *Plugin { + mock := &Plugin{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/SouthboundInterface.go b/controller/mocks/SouthboundInterface.go index abf903d86ecce202e3a6c11b27e4098220e0afc5..ca8fa0a15e5db5baad513f82c4b2398c26eb120c 100644 --- a/controller/mocks/SouthboundInterface.go +++ b/controller/mocks/SouthboundInterface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks @@ -7,6 +7,8 @@ import ( gnmi "github.com/openconfig/gnmi/proto/gnmi" mock "github.com/stretchr/testify/mock" + testing "testing" + uuid "github.com/google/uuid" yang "github.com/openconfig/goyang/pkg/yang" @@ -143,3 +145,12 @@ func (_m *SouthboundInterface) Unmarshal(_a0 []byte, _a1 *gnmi.Path, _a2 ygot.Va return r0 } + +// NewSouthboundInterface creates a new instance of SouthboundInterface. It also registers a cleanup function to assert the mocks expectations. +func NewSouthboundInterface(t testing.TB) *SouthboundInterface { + mock := &SouthboundInterface{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/Storable.go b/controller/mocks/Storable.go index 2f37e9dc922e617f2b42e0a89903d1001c1042c8..9219bcfc00e0276434dcc8cb53dbaa8a0cfddb18 100644 --- a/controller/mocks/Storable.go +++ b/controller/mocks/Storable.go @@ -1,10 +1,12 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks import ( mock "github.com/stretchr/testify/mock" + testing "testing" + uuid "github.com/google/uuid" ) @@ -28,3 +30,12 @@ func (_m *Storable) ID() uuid.UUID { return r0 } + +// NewStorable creates a new instance of Storable. It also registers a cleanup function to assert the mocks expectations. +func NewStorable(t testing.TB) *Storable { + mock := &Storable{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/mocks/Transport.go b/controller/mocks/Transport.go index b2c7aa34f6b2b4235d36f407c9ed7c24f1ffd940..ae80536a4f465db7af6e5d47ec8beebd7ee027c4 100644 --- a/controller/mocks/Transport.go +++ b/controller/mocks/Transport.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.11.0. DO NOT EDIT. package mocks @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + ytypes "github.com/openconfig/ygot/ytypes" ) @@ -109,3 +111,12 @@ func (_m *Transport) Type() string { return r0 } + +// NewTransport creates a new instance of Transport. It also registers a cleanup function to assert the mocks expectations. +func NewTransport(t testing.TB) *Transport { + mock := &Transport{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/controller/northbound/server/auth_test.go b/controller/northbound/server/auth_test.go index ba6487644fe11d68577783a293b11016ae4a325b..8681ca7cb016d73c9ffcb9859a36be747655229d 100644 --- a/controller/northbound/server/auth_test.go +++ b/controller/northbound/server/auth_test.go @@ -620,6 +620,7 @@ func TestAuth_UpdateRoles(t *testing.T) { } func TestAuth_DeletePermissionsForRole(t *testing.T) { + clearAndCreateAuthTestSetup() type args struct { ctx context.Context request *apb.DeletePermissionsForRoleRequest diff --git a/controller/northbound/server/core.go b/controller/northbound/server/core.go index d002ded24df4cc088af9d432aeffb0095d1ce0ad..13a7304c5975738d97f543a7f02f6452c25da171 100644 --- a/controller/northbound/server/core.go +++ b/controller/northbound/server/core.go @@ -22,27 +22,25 @@ func (s core) GetPnd(ctx context.Context, request *pb.GetPndRequest) (*pb.GetPnd start := metrics.StartHook(labels, grpcRequestsTotal) defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) - pndList, err := stringToUUID(request.Pid) + pndID, err := uuid.Parse(request.Pid) if err != nil { return nil, handleRPCError(labels, err) } - pnds := make([]*ppb.PrincipalNetworkDomain, len(pndList)) - for i, id := range pndList { - pnd, err := pndc.Get(store.Query{ID: id}) - if err != nil { - return nil, err - } + storedPnd, err := pndc.Get(store.Query{ID: pndID}) + if err != nil { + return nil, err + } - pnds[i] = &ppb.PrincipalNetworkDomain{ - Id: pnd.ID().String(), - Name: pnd.GetName(), - Description: pnd.GetDescription(), - } + pnd := &ppb.PrincipalNetworkDomain{ + Id: storedPnd.ID().String(), + Name: storedPnd.GetName(), + Description: storedPnd.GetDescription(), } + return &pb.GetPndResponse{ Timestamp: time.Now().UnixNano(), - Pnd: pnds, + Pnd: pnd, }, nil } diff --git a/controller/northbound/server/core_test.go b/controller/northbound/server/core_test.go index 86a36afc739716c1bbac9f1306edb60e368debdc..ba01c8c4c930d12f0a80fc71e3ee89f568205aff 100644 --- a/controller/northbound/server/core_test.go +++ b/controller/northbound/server/core_test.go @@ -66,7 +66,6 @@ func Test_core_GetPnd(t *testing.T) { name string args args want []string - length int wantErr bool }{ { @@ -74,12 +73,9 @@ func Test_core_GetPnd(t *testing.T) { args: args{ ctx: context.Background(), request: &pb.GetPndRequest{ - Pid: []string{ - pndID, - }, + Pid: pndID, }, }, - length: 1, want: []string{ pndID, "test", @@ -87,6 +83,7 @@ func Test_core_GetPnd(t *testing.T) { }, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := core{ @@ -100,18 +97,14 @@ func Test_core_GetPnd(t *testing.T) { if tt.name == "default" { got := []string{ - resp.Pnd[0].Id, - resp.Pnd[0].Name, - resp.Pnd[0].Description, + resp.Pnd.Id, + resp.Pnd.Name, + resp.Pnd.Description, } if !reflect.DeepEqual(got, tt.want) { t.Errorf("core.GetPnd() = %v, want %v", got, tt.want) } } - length := len(resp.Pnd) - if tt.length != length { - t.Errorf("core.GetPnd() = %v, want %v", length, tt.length) - } }) } } diff --git a/controller/northbound/server/pnd.go b/controller/northbound/server/pnd.go index 6d53008450b78c502f81a6bf5ace70a8c367d0c4..fbd7e730879d7e3a5b55229729a9ef49dee45f9a 100644 --- a/controller/northbound/server/pnd.go +++ b/controller/northbound/server/pnd.go @@ -42,7 +42,7 @@ func (p pndServer) GetOnd(ctx context.Context, request *ppb.GetOndRequest) (*ppb log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - onds, err := fillOnds(pnd, false, request.Did...) + onds, err := fillOnd(pnd, request.Did) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -72,7 +72,7 @@ func (p pndServer) GetOndList(ctx context.Context, request *ppb.GetOndListReques log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - onds, err := fillOnds(pnd, true) + onds, err := fillOnds(pnd) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -88,58 +88,50 @@ func (p pndServer) GetOndList(ctx context.Context, request *ppb.GetOndListReques }, nil } -func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { - var ondList []device.Device - var onds []*ppb.OrchestratedNetworkingDevice +func fillOnd(pnd networkdomain.NetworkDomain, did string) (*ppb.OrchestratedNetworkingDevice, error) { + d, err := pnd.GetDevice(did) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + cfg := ygot.GNMINotificationsConfig{} + dev, err := ygot.TogNMINotifications(d.GetModel(), time.Now().UnixNano(), cfg) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } - // all indicates if a client wants all devices or only a single one - switch all { - case true: - ondList = pnd.Devices() - onds = make([]*ppb.OrchestratedNetworkingDevice, len(ondList)) - for _, dev := range ondList { - did = append(did, dev.ID().String()) - } + sbi := spb.SouthboundInterface{} + if d.SBI() != nil { + sbi.Id = d.SBI().ID().String() + sbi.Type = d.SBI().Type() + } - default: - if len(did) == 0 { - err := &errors.ErrInvalidParameters{ - Func: fillOnds, - Param: "length of 'did' cannot be '0' when 'all' is set to 'false'", - } - log.Error(err) + return &ppb.OrchestratedNetworkingDevice{ + Id: did, + Name: d.Name(), + Device: dev, + Sbi: &sbi, + }, nil +} - return nil, err - } +func fillOnds(pnd networkdomain.NetworkDomain) ([]*ppb.OrchestratedNetworkingDevice, error) { + var ondList []device.Device + var onds []*ppb.OrchestratedNetworkingDevice + + ondList = pnd.Devices() + var did []string - onds = make([]*ppb.OrchestratedNetworkingDevice, 1) + for _, dev := range ondList { + did = append(did, dev.ID().String()) } - for i, id := range did { - d, err := pnd.GetDevice(id) + for _, id := range did { + ond, err := fillOnd(pnd, id) if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - cfg := ygot.GNMINotificationsConfig{} - dev, err := ygot.TogNMINotifications(d.GetModel(), time.Now().UnixNano(), cfg) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - - sbi := spb.SouthboundInterface{} - if d.SBI() != nil { - sbi.Id = d.SBI().ID().String() - sbi.Type = d.SBI().Type() - } - - onds[i] = &ppb.OrchestratedNetworkingDevice{ - Id: id, - Name: d.Name(), - Device: dev, - Sbi: &sbi, + return nil, err } + onds = append(onds, ond) } return onds, nil @@ -253,7 +245,13 @@ func (p pndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - sbis, err := fillSbis(pnd, false, request.Sid...) + + sbiID, err := uuid.Parse(request.Sid) + if err != nil { + return nil, err + } + + sbi, err := pnd.GetSBI(sbiID) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -265,7 +263,10 @@ func (p pndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb Name: pnd.GetName(), Description: pnd.GetDescription(), }, - Sbi: sbis, + Sbi: &spb.SouthboundInterface{ + Id: sbiID.String(), + Type: sbi.Type(), + }, }, nil } @@ -283,7 +284,7 @@ func (p pndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListReques log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - sbis, err := fillSbis(pnd, true, "") + sbis, err := fillSbis(pnd) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -299,7 +300,7 @@ func (p pndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListReques }, nil } -func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) { +func fillSbis(pnd networkdomain.NetworkDomain) ([]*spb.SouthboundInterface, error) { sbis, err := pnd.GetSBIs() if err != nil { return nil, err @@ -320,7 +321,7 @@ func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb. return sbisToReturn, nil } -func stringToUUID(sid []string) ([]uuid.UUID, error) { +func stringArrayToUUIDs(sid []string) ([]uuid.UUID, error) { UUIDs := make([]uuid.UUID, len(sid)) for i, id := range sid { parsed, err := uuid.Parse(id) @@ -393,7 +394,7 @@ func (p pndServer) GetChange(ctx context.Context, request *ppb.GetChangeRequest) log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - changes, err := fillChanges(pnd, false, request.Cuid) + changes, err := fillChanges(pnd, false, request.Cuid...) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -454,7 +455,7 @@ func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]* Param: "length of 'did' cannot be '0' when 'all' is set to 'false'", } } - changeList, err = stringToUUID(cuid) + changeList, err = stringArrayToUUIDs(cuid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -469,10 +470,17 @@ func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]* return nil, status.Errorf(codes.Aborted, "%v", err) } + diff, err := ygot.Diff(c.PreviousState(), c.IntendedState()) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + changes[i] = &ppb.Change{ Id: ch.String(), Age: c.Age().Microseconds(), State: c.State(), + Diff: diff, } } return changes, nil @@ -492,25 +500,30 @@ func (p pndServer) SetOndList(ctx context.Context, request *ppb.SetOndListReques return nil, handleRPCError(labels, err) } + deviceIDs := make([]uuid.UUID, 0, len(request.Ond)) for _, r := range request.Ond { sid, err := uuid.Parse(r.Sbi.Id) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - if err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid); err != nil { + did, err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid) + if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } + deviceIDs = append(deviceIDs, did) } + + r := make([]*ppb.SetResponse, len(deviceIDs)) + for i, did := range deviceIDs { + r[i] = &ppb.SetResponse{Id: did.String(), Status: ppb.Status_STATUS_OK} + } + return &ppb.SetOndListResponse{ Timestamp: time.Now().UnixNano(), Status: ppb.Status_STATUS_OK, - Responses: []*ppb.SetResponse{ - { - Status: ppb.Status_STATUS_OK, - }, - }, + Responses: r, }, nil } diff --git a/controller/northbound/server/pnd_test.go b/controller/northbound/server/pnd_test.go index ca3ac203213824532d41742be4cd061228756883..be7622913b8ff9d8ae57dd99443cade4be8fd56b 100644 --- a/controller/northbound/server/pnd_test.go +++ b/controller/northbound/server/pnd_test.go @@ -180,19 +180,18 @@ func Test_pnd_Get(t *testing.T) { args: args{ ctx: context.Background(), request: &pb.GetPndRequest{ - Pid: []string{ - pndID}, + Pid: pndID, }, }, want: &pb.GetPndResponse{ - Pnd: []*ppb.PrincipalNetworkDomain{ - {Id: pndID, - Name: "test", - Description: "test"}, - }, + Pnd: &ppb.PrincipalNetworkDomain{ + Id: pndID, + Name: "test", + Description: "test"}, }, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p := core{ diff --git a/controller/nucleus/change.go b/controller/nucleus/change.go index 6da303875849d7a9f6e27f3f4f8904f3f043845d..935360ca57c77ff157f40168cff8c0c44dfc78da 100644 --- a/controller/nucleus/change.go +++ b/controller/nucleus/change.go @@ -116,6 +116,18 @@ func (c *Change) State() ppb.ChangeState { return state } +// PreviousState returns the previous state of the devices config as +// ygot.GoStruct. +func (c *Change) PreviousState() ygot.GoStruct { + return c.previousState +} + +// IntendedState returns the intended state of the devices config as +// ygot.GoStruct. +func (c *Change) IntendedState() ygot.GoStruct { + return c.intendedState +} + func stateManager(ctx context.Context, ch *Change, timeout time.Duration) (chan<- ppb.ChangeState, <-chan ppb.ChangeState, <-chan error) { stateIn := make(chan ppb.ChangeState) stateOut := make(chan ppb.ChangeState) diff --git a/controller/nucleus/memoryDeviceStore.go b/controller/nucleus/memoryDeviceStore.go index 536bb6ea4502e5de931b31e3ae95a25c514dda62..9a04d7a5c1c3fa06648e1eddefe7c2156ce35dcd 100644 --- a/controller/nucleus/memoryDeviceStore.go +++ b/controller/nucleus/memoryDeviceStore.go @@ -49,8 +49,8 @@ func (t *MemoryDeviceStore) Add(item device.Device) error { // Update updates a existing device. func (t *MemoryDeviceStore) Update(item device.Device) error { _, ok := t.Store[item.ID().String()] - if ok { - return nil + if !ok { + return errors.ErrCouldNotFind{StoreName: deviceStoreName} } var device device.LoadedDevice diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go index 69795871e51da7d81d867d1a817dc6aca8413963..b3499a8d8a5bf09c35f9d6093f73be3b386a0a8b 100644 --- a/controller/nucleus/principalNetworkDomain.go +++ b/controller/nucleus/principalNetworkDomain.go @@ -215,32 +215,31 @@ func (pnd *pndImplementation) RemoveSbi(sid uuid.UUID) error { } // AddDevice adds a new device to the PND -func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, sid uuid.UUID) error { +func (pnd *pndImplementation) AddDevice(name string, opt *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error) { labels := prometheus.Labels{"type": opt.Type.String()} start := metrics.StartHook(labels, deviceCreationsTotal) defer metrics.FinishHook(labels, start, deviceCreationDurationSecondsTotal, deviceCreationDurationSeconds) var sbi southbound.SouthboundInterface + var err error switch t := opt.Type; t { case spb.Type_TYPE_CONTAINERISED: return pnd.handleCsbiEnrolment(name, opt) case spb.Type_TYPE_PLUGIN: - var err error sbi, err = pnd.requestPlugin(name, opt) if err != nil { - return err + return uuid.Nil, err } default: - var err error sbi, err = pnd.sbic.Get(store.Query{ID: sid}) if err != nil { - return err + return uuid.Nil, err } } d, err := NewDevice(name, uuid.Nil, opt, sbi) if err != nil { - return err + return uuid.Nil, err } return pnd.addDevice(d) } @@ -302,13 +301,13 @@ func (pnd *pndImplementation) removeSbi(id uuid.UUID) error { } // addDevice adds a device to the PND's device store. -func (pnd *pndImplementation) addDevice(device device.Device) error { +func (pnd *pndImplementation) addDevice(device device.Device) (uuid.UUID, error) { err := pnd.devices.Add(device) if err != nil { - return err + return uuid.Nil, err } - return nil + return device.ID(), nil } func (pnd *pndImplementation) removeDevice(id uuid.UUID) error { @@ -492,7 +491,7 @@ func (pnd *pndImplementation) handleCsbiDeletion(id uuid.UUID) error { return nil } -func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.TransportOption) error { +func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.TransportOption) (uuid.UUID, error) { g := new(errgroup.Group) ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5) defer cancel() @@ -502,20 +501,26 @@ func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.Transpor } resp, err := pnd.csbiClient.Create(ctx, req) if err != nil { - return err + return uuid.Nil, err } + // the slice only contains one deployment + var devID uuid.UUID for _, d := range resp.Deployments { dCopy := d g.Go(func() error { - return pnd.createCsbiDevice(ctx, name, dCopy, opt) + devID, err = pnd.createCsbiDevice(ctx, name, dCopy, opt) + if err != nil { + return err + } + return nil }) } err = g.Wait() if err != nil { - return err + return uuid.Nil, err } - return nil + return devID, nil } // createCsbiDevice is a helper method for cSBI device creation. The method @@ -526,10 +531,10 @@ func (pnd *pndImplementation) createCsbiDevice( name string, d *cpb.Deployment, opt *tpb.TransportOption, -) error { +) (uuid.UUID, error) { id, err := uuid.Parse(d.Id) if err != nil { - return err + return uuid.Nil, err } ch := make(chan device.Details, 1) pnd.callback(id, ch) @@ -547,7 +552,7 @@ func (pnd *pndImplementation) createCsbiDevice( log.Infof("syn from csbi %v", deviceDetails.ID) id, err := uuid.Parse(deviceDetails.ID) if err != nil { - return err + return uuid.Nil, err } csbiTransportOptions := &tpb.TransportOption{ Address: deviceDetails.Address, @@ -568,41 +573,42 @@ func (pnd *pndImplementation) createCsbiDevice( // here and in csbi. gClient, err := pnd.csbiClient.GetGoStruct(ctx, req) if err != nil { - return err + return uuid.Nil, err } csbiID, err := saveGenericClientStreamToFile(gClient, "gostructs.go", uuid.New()) if err != nil { - return err + return uuid.Nil, err } // TODO: this is currently just a workaround needs major adjustments // here and in csbi. mClient, err := pnd.csbiClient.GetManifest(ctx, req) if err != nil { - return err + return uuid.Nil, err } _, err = saveGenericClientStreamToFile(mClient, "plugin.yml", csbiID) if err != nil { - return err + return uuid.Nil, err } csbi, err := NewSBI(spb.Type_TYPE_CONTAINERISED, csbiID) if err != nil { - return err + return uuid.Nil, err } err = pnd.sbic.Add(csbi) if err != nil { - return err + return uuid.Nil, err } d, err := NewDevice(name, uuid.Nil, csbiTransportOptions, csbi) if err != nil { - return err + return uuid.Nil, err } d.(*CsbiDevice).UUID = id ch <- device.Details{TransportOption: opt} if err := pnd.devices.Add(d); err != nil { - return err + return uuid.Nil, err } + return id, nil } - return nil + return uuid.Nil, nil } // requestPlugin is a feature for cSBIs and sends a plugin request to the cSBI diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go index f06f7cfc791de08f35133317a23ef43a750312bf..a70b61252633e51e37cd6e6c249ff01fef733e9b 100644 --- a/controller/nucleus/principalNetworkDomain_test.go +++ b/controller/nucleus/principalNetworkDomain_test.go @@ -115,7 +115,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) { t.Error(err) } - err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID) + _, err := pnd.AddDevice(tt.args.name, tt.args.opts, defaultSbiID) if (err != nil) != tt.wantErr { t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr) } @@ -290,7 +290,8 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) { sbi: sbi, transport: nil, } - if err := pnd.addDevice(d); err != nil { + _, err = pnd.addDevice(d) + if err != nil { t.Error(err) } got, err := pnd.MarshalDevice(tt.args.uuid.String()) @@ -339,7 +340,8 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) { sbi: sbi, transport: nil, } - if err := pnd.addDevice(d); err != nil { + _, err = pnd.addDevice(d) + if err != nil { t.Error(err) } if err := pnd.RemoveDevice(tt.args.uuid); (err != nil) != tt.wantErr { @@ -454,10 +456,12 @@ func Test_pndImplementation_RemoveSbiWithAssociatedDevices(t *testing.T) { if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { t.Error(err) } - if err := pnd.AddDevice("associatedDevice", opts, tt.args.id); err != nil { + _, err = pnd.AddDevice("associatedDevice", opts, tt.args.id) + if err != nil { t.Error(err) } - if err := pnd.AddDevice("associatedDevice2", opts, tt.args.id); err != nil { + _, err = pnd.AddDevice("associatedDevice2", opts, tt.args.id) + if err != nil { t.Error(err) } if tt.name == "exclusively remove associated devices" { @@ -465,7 +469,8 @@ func Test_pndImplementation_RemoveSbiWithAssociatedDevices(t *testing.T) { if err := pnd.addSbi(&OpenConfig{id: newID}); err != nil { t.Error(err) } - if err := pnd.AddDevice("associatedDevice2", opts, newID); err != nil { + _, err := pnd.AddDevice("associatedDevice2", opts, newID) + if err != nil { t.Error(err) } } @@ -560,7 +565,7 @@ func Test_pndImplementation_Request(t *testing.T) { transport: &transport, } - _ = pnd.addDevice(deviceWithMockTransport) + _, _ = pnd.addDevice(deviceWithMockTransport) _, err = pnd.Request(tt.args.uuid, tt.args.path) if (err != nil) != tt.wantErr { @@ -644,7 +649,7 @@ func Test_pndImplementation_RequestAll(t *testing.T) { transport: &transport, } - _ = pnd.addDevice(deviceWithMockTransport) + _, _ = pnd.addDevice(deviceWithMockTransport) device, _ := pnd.devices.Get(store.Query{ID: mdid}) if device == nil { @@ -756,7 +761,8 @@ func Test_pndImplementation_ChangeOND(t *testing.T) { if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { t.Error(err) } - if err := pnd.AddDevice("testdevice", opts, defaultSbiID); err != nil { + _, err := pnd.AddDevice("testdevice", opts, defaultSbiID) + if err != nil { t.Error(err) return } @@ -799,7 +805,8 @@ func Test_pndImplementation_GetDevice(t *testing.T) { t.Error(err) return } - if err = pnd.addDevice(d); err != nil { + _, err = pnd.addDevice(d) + if err != nil { t.Error(err) return } @@ -859,7 +866,8 @@ func Test_pndImplementation_GetDeviceByName(t *testing.T) { t.Error(err) return } - if err = pnd.addDevice(d); err != nil { + _, err = pnd.addDevice(d) + if err != nil { t.Error(err) return } @@ -933,11 +941,12 @@ func Test_pndImplementation_Confirm(t *testing.T) { d := mockDevice() tr := d.Transport().(*mocks.Transport) tr.On("Set", mockContext, mock.Anything, mock.Anything).Return(nil) - if err := pnd.addDevice(d); err != nil { + _, err := pnd.addDevice(d) + if err != nil { t.Error(err) return } - _, err := pnd.ChangeOND(d.ID(), ppb.ApiOperation_API_OPERATION_UPDATE, "system/config/hostname", "ceos3000") + _, err = pnd.ChangeOND(d.ID(), ppb.ApiOperation_API_OPERATION_UPDATE, "system/config/hostname", "ceos3000") if err != nil { t.Error(err) return diff --git a/controller/rbac/memoryRoleStore.go b/controller/rbac/memoryRoleStore.go index e40dc60b79afde6cecb0a69e9586f140fe74fbd9..da0e023eb7ffb6c14bb1ec1a4211603aadde82d6 100644 --- a/controller/rbac/memoryRoleStore.go +++ b/controller/rbac/memoryRoleStore.go @@ -55,8 +55,8 @@ func (s *MemoryRoleStore) Delete(item rbac.Role) error { // Update updates an existing role. func (s *MemoryRoleStore) Update(item rbac.Role) error { _, ok := s.Store[item.ID().String()] - if ok { - return nil + if !ok { + return errors.ErrCouldNotFind{StoreName: roleStoreName} } var role rbac.LoadedRole diff --git a/controller/rbac/memoryUserStore.go b/controller/rbac/memoryUserStore.go index 338f56180fe137187b9c12a95530bf5a1caf5d46..c97439278b59716ee188f635c178e94eb8d6efd2 100644 --- a/controller/rbac/memoryUserStore.go +++ b/controller/rbac/memoryUserStore.go @@ -55,8 +55,8 @@ func (s *MemoryUserStore) Delete(item rbac.User) error { // Update updates an existing user. func (s *MemoryUserStore) Update(item rbac.User) error { _, ok := s.Store[item.ID().String()] - if ok { - return nil + if !ok { + return errors.ErrCouldNotFind{StoreName: userStoreName} } var user rbac.LoadedUser diff --git a/controller/test/integration/nucleusIntegration_test.go b/controller/test/integration/nucleusIntegration_test.go index 04899ccee07a31faf95e180cee1ffaf9df8ca386..333efb1778f6acf0a22cc9f54f9ed57e82d150bc 100644 --- a/controller/test/integration/nucleusIntegration_test.go +++ b/controller/test/integration/nucleusIntegration_test.go @@ -177,7 +177,8 @@ func TestGnmi_SetValidIntegration(t *testing.T) { t.Error(err) return } - if err := pnd.AddDevice("test", opt, sbi.ID()); err != nil { + _, err = pnd.AddDevice("test", opt, sbi.ID()) + if err != nil { t.Error(err) return } diff --git a/go.mod b/go.mod index b35ed07e1023f269be5f4b6b0771ac6c8cfe66b6..ae34105ad3b70e38c2fdcf51fed055822ce50d07 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( require ( github.com/c-bata/go-prompt v0.2.6 github.com/mitchellh/go-homedir v1.1.0 + github.com/pterm/pterm v0.12.41 github.com/spf13/pflag v1.0.5 go.mongodb.org/mongo-driver v1.8.4 google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 @@ -37,6 +38,14 @@ require ( require github.com/gorilla/mux v1.8.0 // indirect +require ( + github.com/atomicgo/cursor v0.0.1 // indirect + github.com/gookit/color v1.5.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect +) + require ( github.com/Microsoft/go-winio v0.5.1 // indirect github.com/Microsoft/hcsshim v0.9.2 // indirect @@ -63,7 +72,7 @@ require ( github.com/magiconair/properties v1.8.5 // indirect github.com/mattn/go-colorable v0.1.7 // indirect github.com/mattn/go-isatty v0.0.12 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mitchellh/mapstructure v1.4.2 // indirect diff --git a/go.sum b/go.sum index 269d78c6602a33845743b3e80481a478e9d9014a..6871178105715d93874ff49bc76dc8e93cd07bc3 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,14 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.3.5 h1:g9krITRRlIsF1eO9sUKXtiTw670gZIIk6T08Keeo1nM= +github.com/MarvinJWendt/testza v0.3.5/go.mod h1:ExbTpWmA1z2E9HSskvrNcwApoX4F9bID692s10nuHRY= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -118,6 +126,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -509,6 +519,9 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -599,6 +612,10 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -640,8 +657,9 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= @@ -827,6 +845,17 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= +github.com/pterm/pterm v0.12.41 h1:e2BRfFo1H9nL8GY0S3ImbZqfZ/YimOk9XtkhoobKJVs= +github.com/pterm/pterm v0.12.41/go.mod h1:LW/G4J2A42XlTaPTAGRPvbBfF4UXvHWhC6SN7ueU4jU= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -841,6 +870,8 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -936,6 +967,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= @@ -1250,15 +1283,19 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=