diff --git a/.kres.yaml b/.kres.yaml index aaec2d2..293e59d 100644 --- a/.kres.yaml +++ b/.kres.yaml @@ -25,7 +25,7 @@ spec: baseSpecPath: /api vtProtobufEnabled: true specs: - - source: api/storage/storage.proto + - source: api/storage/discovery.proto subdirectory: storage genGateway: false --- diff --git a/Dockerfile b/Dockerfile index 7d724cf..4acc88d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. # -# Generated on 2024-05-28T00:03:10Z by kres bcb280a. +# Generated on 2024-05-30T08:00:54Z by kres f249b6c. ARG TOOLCHAIN @@ -21,7 +21,7 @@ RUN markdownlint --ignore "CHANGELOG.md" --ignore "**/node_modules/**" --ignore # collects proto specs FROM scratch AS proto-specs -ADD api/storage/storage.proto /api/storage/ +ADD api/storage/discovery.proto /api/storage/ # base toolchain image FROM --platform=${BUILDPLATFORM} ${TOOLCHAIN} AS toolchain @@ -37,6 +37,9 @@ ENV GOTOOLCHAIN ${GOTOOLCHAIN} ARG GOEXPERIMENT ENV GOEXPERIMENT ${GOEXPERIMENT} ENV GOPATH /go +ARG GOIMPORTS_VERSION +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/tools/cmd/goimports@v${GOIMPORTS_VERSION} +RUN mv /go/bin/goimports /bin ARG PROTOBUF_GO_VERSION RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOBUF_GO_VERSION} RUN mv /go/bin/protoc-gen-go /bin @@ -46,9 +49,6 @@ RUN mv /go/bin/protoc-gen-go-grpc /bin ARG GRPC_GATEWAY_VERSION RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v${GRPC_GATEWAY_VERSION} RUN mv /go/bin/protoc-gen-grpc-gateway /bin -ARG GOIMPORTS_VERSION -RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/tools/cmd/goimports@v${GOIMPORTS_VERSION} -RUN mv /go/bin/goimports /bin ARG VTPROTOBUF_VERSION RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v${VTPROTOBUF_VERSION} RUN mv /go/bin/protoc-gen-go-vtproto /bin @@ -81,8 +81,8 @@ RUN --mount=type=cache,target=/go/pkg go list -mod=readonly all >/dev/null # runs protobuf compiler FROM tools AS proto-compile COPY --from=proto-specs / / -RUN protoc -I/api --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size+equal+clone /api/storage/storage.proto -RUN rm /api/storage/storage.proto +RUN protoc -I/api --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size+equal+clone /api/storage/discovery.proto +RUN rm /api/storage/discovery.proto RUN goimports -w -local github.com/siderolabs/discovery-service /api RUN gofumpt -w /api diff --git a/api/storage/storage.pb.go b/api/storage/discovery.pb.go similarity index 62% rename from api/storage/storage.pb.go rename to api/storage/discovery.pb.go index 1d7ecce..5457c0b 100644 --- a/api/storage/storage.pb.go +++ b/api/storage/discovery.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.1 // protoc v4.24.4 -// source: storage/storage.proto +// source: storage/discovery.proto package storagepb @@ -34,7 +34,7 @@ type StateSnapshot struct { func (x *StateSnapshot) Reset() { *x = StateSnapshot{} if protoimpl.UnsafeEnabled { - mi := &file_storage_storage_proto_msgTypes[0] + mi := &file_storage_discovery_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -47,7 +47,7 @@ func (x *StateSnapshot) String() string { func (*StateSnapshot) ProtoMessage() {} func (x *StateSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_storage_storage_proto_msgTypes[0] + mi := &file_storage_discovery_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -60,7 +60,7 @@ func (x *StateSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSnapshot.ProtoReflect.Descriptor instead. func (*StateSnapshot) Descriptor() ([]byte, []int) { - return file_storage_storage_proto_rawDescGZIP(), []int{0} + return file_storage_discovery_proto_rawDescGZIP(), []int{0} } func (x *StateSnapshot) GetClusters() []*ClusterSnapshot { @@ -83,7 +83,7 @@ type ClusterSnapshot struct { func (x *ClusterSnapshot) Reset() { *x = ClusterSnapshot{} if protoimpl.UnsafeEnabled { - mi := &file_storage_storage_proto_msgTypes[1] + mi := &file_storage_discovery_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -96,7 +96,7 @@ func (x *ClusterSnapshot) String() string { func (*ClusterSnapshot) ProtoMessage() {} func (x *ClusterSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_storage_storage_proto_msgTypes[1] + mi := &file_storage_discovery_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -109,7 +109,7 @@ func (x *ClusterSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ClusterSnapshot.ProtoReflect.Descriptor instead. func (*ClusterSnapshot) Descriptor() ([]byte, []int) { - return file_storage_storage_proto_rawDescGZIP(), []int{1} + return file_storage_discovery_proto_rawDescGZIP(), []int{1} } func (x *ClusterSnapshot) GetId() string { @@ -141,7 +141,7 @@ type AffiliateSnapshot struct { func (x *AffiliateSnapshot) Reset() { *x = AffiliateSnapshot{} if protoimpl.UnsafeEnabled { - mi := &file_storage_storage_proto_msgTypes[2] + mi := &file_storage_discovery_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -154,7 +154,7 @@ func (x *AffiliateSnapshot) String() string { func (*AffiliateSnapshot) ProtoMessage() {} func (x *AffiliateSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_storage_storage_proto_msgTypes[2] + mi := &file_storage_discovery_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -167,7 +167,7 @@ func (x *AffiliateSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use AffiliateSnapshot.ProtoReflect.Descriptor instead. func (*AffiliateSnapshot) Descriptor() ([]byte, []int) { - return file_storage_storage_proto_rawDescGZIP(), []int{2} + return file_storage_discovery_proto_rawDescGZIP(), []int{2} } func (x *AffiliateSnapshot) GetId() string { @@ -211,7 +211,7 @@ type EndpointSnapshot struct { func (x *EndpointSnapshot) Reset() { *x = EndpointSnapshot{} if protoimpl.UnsafeEnabled { - mi := &file_storage_storage_proto_msgTypes[3] + mi := &file_storage_discovery_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -224,7 +224,7 @@ func (x *EndpointSnapshot) String() string { func (*EndpointSnapshot) ProtoMessage() {} func (x *EndpointSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_storage_storage_proto_msgTypes[3] + mi := &file_storage_discovery_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -237,7 +237,7 @@ func (x *EndpointSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use EndpointSnapshot.ProtoReflect.Descriptor instead. func (*EndpointSnapshot) Descriptor() ([]byte, []int) { - return file_storage_storage_proto_rawDescGZIP(), []int{3} + return file_storage_discovery_proto_rawDescGZIP(), []int{3} } func (x *EndpointSnapshot) GetExpiration() *timestamppb.Timestamp { @@ -254,72 +254,73 @@ func (x *EndpointSnapshot) GetData() []byte { return nil } -var File_storage_storage_proto protoreflect.FileDescriptor - -var file_storage_storage_proto_rawDesc = []byte{ - 0x0a, 0x15, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, 0x64, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x6e, 0x0a, 0x0f, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x4b, 0x0a, - 0x0a, 0x61, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x66, 0x66, - 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x0a, - 0x61, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x11, 0x41, +var File_storage_discovery_proto protoreflect.FileDescriptor + +var file_storage_discovery_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x6f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, + 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x6e, 0x0a, 0x0f, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x4b, 0x0a, 0x0a, 0x61, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x52, 0x0a, 0x61, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x73, 0x22, 0xbd, 0x01, 0x0a, + 0x11, 0x41, 0x66, 0x66, 0x69, 0x6c, 0x69, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x48, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x62, 0x0a, 0x10, + 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x48, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x6f, 0x2e, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, - 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x62, 0x0a, 0x10, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x3a, - 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x37, - 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, - 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, + 0x69, 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( - file_storage_storage_proto_rawDescOnce sync.Once - file_storage_storage_proto_rawDescData = file_storage_storage_proto_rawDesc + file_storage_discovery_proto_rawDescOnce sync.Once + file_storage_discovery_proto_rawDescData = file_storage_discovery_proto_rawDesc ) -func file_storage_storage_proto_rawDescGZIP() []byte { - file_storage_storage_proto_rawDescOnce.Do(func() { - file_storage_storage_proto_rawDescData = protoimpl.X.CompressGZIP(file_storage_storage_proto_rawDescData) +func file_storage_discovery_proto_rawDescGZIP() []byte { + file_storage_discovery_proto_rawDescOnce.Do(func() { + file_storage_discovery_proto_rawDescData = protoimpl.X.CompressGZIP(file_storage_discovery_proto_rawDescData) }) - return file_storage_storage_proto_rawDescData + return file_storage_discovery_proto_rawDescData } -var file_storage_storage_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_storage_storage_proto_goTypes = []interface{}{ +var file_storage_discovery_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_storage_discovery_proto_goTypes = []interface{}{ (*StateSnapshot)(nil), // 0: sidero.discovery.storage.StateSnapshot (*ClusterSnapshot)(nil), // 1: sidero.discovery.storage.ClusterSnapshot (*AffiliateSnapshot)(nil), // 2: sidero.discovery.storage.AffiliateSnapshot (*EndpointSnapshot)(nil), // 3: sidero.discovery.storage.EndpointSnapshot (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp } -var file_storage_storage_proto_depIdxs = []int32{ +var file_storage_discovery_proto_depIdxs = []int32{ 1, // 0: sidero.discovery.storage.StateSnapshot.clusters:type_name -> sidero.discovery.storage.ClusterSnapshot 2, // 1: sidero.discovery.storage.ClusterSnapshot.affiliates:type_name -> sidero.discovery.storage.AffiliateSnapshot 4, // 2: sidero.discovery.storage.AffiliateSnapshot.expiration:type_name -> google.protobuf.Timestamp @@ -332,13 +333,13 @@ var file_storage_storage_proto_depIdxs = []int32{ 0, // [0:5] is the sub-list for field type_name } -func init() { file_storage_storage_proto_init() } -func file_storage_storage_proto_init() { - if File_storage_storage_proto != nil { +func init() { file_storage_discovery_proto_init() } +func file_storage_discovery_proto_init() { + if File_storage_discovery_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_storage_storage_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_storage_discovery_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StateSnapshot); i { case 0: return &v.state @@ -350,7 +351,7 @@ func file_storage_storage_proto_init() { return nil } } - file_storage_storage_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_storage_discovery_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ClusterSnapshot); i { case 0: return &v.state @@ -362,7 +363,7 @@ func file_storage_storage_proto_init() { return nil } } - file_storage_storage_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_storage_discovery_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AffiliateSnapshot); i { case 0: return &v.state @@ -374,7 +375,7 @@ func file_storage_storage_proto_init() { return nil } } - file_storage_storage_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_storage_discovery_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EndpointSnapshot); i { case 0: return &v.state @@ -391,18 +392,18 @@ func file_storage_storage_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_storage_storage_proto_rawDesc, + RawDescriptor: file_storage_discovery_proto_rawDesc, NumEnums: 0, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_storage_storage_proto_goTypes, - DependencyIndexes: file_storage_storage_proto_depIdxs, - MessageInfos: file_storage_storage_proto_msgTypes, + GoTypes: file_storage_discovery_proto_goTypes, + DependencyIndexes: file_storage_discovery_proto_depIdxs, + MessageInfos: file_storage_discovery_proto_msgTypes, }.Build() - File_storage_storage_proto = out.File - file_storage_storage_proto_rawDesc = nil - file_storage_storage_proto_goTypes = nil - file_storage_storage_proto_depIdxs = nil + File_storage_discovery_proto = out.File + file_storage_discovery_proto_rawDesc = nil + file_storage_discovery_proto_goTypes = nil + file_storage_discovery_proto_depIdxs = nil } diff --git a/api/storage/storage.proto b/api/storage/discovery.proto similarity index 100% rename from api/storage/storage.proto rename to api/storage/discovery.proto diff --git a/api/storage/storage_vtproto.pb.go b/api/storage/discovery_vtproto.pb.go similarity index 99% rename from api/storage/storage_vtproto.pb.go rename to api/storage/discovery_vtproto.pb.go index 4ae0b8c..0ecef9f 100644 --- a/api/storage/storage_vtproto.pb.go +++ b/api/storage/discovery_vtproto.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. // protoc-gen-go-vtproto version: v0.6.0 -// source: storage/storage.proto +// source: storage/discovery.proto package storagepb diff --git a/cmd/discovery-service/main.go b/cmd/discovery-service/main.go index 58f9ac3..cb93e89 100644 --- a/cmd/discovery-service/main.go +++ b/cmd/discovery-service/main.go @@ -8,40 +8,19 @@ package main import ( "context" - "errors" "flag" - "fmt" "log" - "net" - "net/http" "os" "os/signal" "syscall" "time" - grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" - grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" - "github.com/jonboulle/clockwork" - prom "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/siderolabs/discovery-api/api/v1alpha1/server/pb" + "github.com/prometheus/client_golang/prometheus" "github.com/siderolabs/go-debug" "go.uber.org/zap" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/experimental" - "google.golang.org/grpc/keepalive" - "google.golang.org/grpc/status" - "github.com/siderolabs/discovery-service/internal/landing" - "github.com/siderolabs/discovery-service/internal/limiter" _ "github.com/siderolabs/discovery-service/internal/proto" - "github.com/siderolabs/discovery-service/internal/state" - "github.com/siderolabs/discovery-service/internal/state/storage" - "github.com/siderolabs/discovery-service/pkg/limits" - "github.com/siderolabs/discovery-service/pkg/server" + "github.com/siderolabs/discovery-service/pkg/service" ) var ( @@ -95,7 +74,28 @@ func main() { zap.ReplaceGlobals(logger) zap.RedirectStdLog(logger) - if err = signalHandler(context.Background(), logger, run); err != nil { + if err = signalHandler(context.Background(), logger, func(ctx context.Context, logger *zap.Logger) error { + return service.Run(ctx, service.Options{ + SnapshotsEnabled: snapshotsEnabled, + SnapshotPath: snapshotPath, + SnapshotInterval: snapshotInterval, + + RedirectEndpoint: redirectEndpoint, + ListenAddr: listenAddr, + GCInterval: gcInterval, + + LandingServerEnabled: true, + LandingAddr: landingAddr, + + DebugServerEnabled: true, + DebugAddr: debugAddr, + + MetricsServerEnabled: true, + MetricsAddr: metricsAddr, + + MetricsRegisterer: prometheus.DefaultRegisterer, + }, logger) + }); err != nil { logger.Error("service failed", zap.Error(err)) os.Exit(1) @@ -108,214 +108,3 @@ func signalHandler(ctx context.Context, logger *zap.Logger, f func(ctx context.C return f(ctx, logger) } - -func recoveryHandler(logger *zap.Logger) grpc_recovery.RecoveryHandlerFunc { - return func(p interface{}) error { - if logger != nil { - logger.Error("grpc panic", zap.Any("panic", p), zap.Stack("stack")) - } - - return status.Errorf(codes.Internal, "%v", p) - } -} - -func interceptorLogger(l *zap.Logger) logging.Logger { - return logging.LoggerFunc(func(_ context.Context, lvl logging.Level, msg string, fields ...any) { - f := make([]zap.Field, 0, len(fields)/2) - - for i := 0; i < len(fields); i += 2 { - key := fields[i].(string) //nolint:forcetypeassert,errcheck - value := fields[i+1] - - switch v := value.(type) { - case string: - f = append(f, zap.String(key, v)) - case int: - f = append(f, zap.Int(key, v)) - case bool: - f = append(f, zap.Bool(key, v)) - default: - f = append(f, zap.Any(key, v)) - } - } - - logger := l.WithOptions(zap.AddCallerSkip(1)).With(f...) - - switch lvl { - case logging.LevelDebug: - logger.Debug(msg) - case logging.LevelInfo: - logger.Info(msg) - case logging.LevelWarn: - logger.Warn(msg) - case logging.LevelError: - logger.Error(msg) - default: - panic(fmt.Sprintf("unknown level %v", lvl)) - } - }) -} - -func run(ctx context.Context, logger *zap.Logger) error { - logger.Info("service starting") - - defer logger.Info("service shut down") - - recoveryOpt := grpc_recovery.WithRecoveryHandler(recoveryHandler(logger)) - - limiter := limiter.NewIPRateLimiter(limits.IPRateRequestsPerSecondMax, limits.IPRateBurstSizeMax) - - metrics := grpc_prometheus.NewServerMetrics( - grpc_prometheus.WithServerHandlingTimeHistogram(grpc_prometheus.WithHistogramBuckets([]float64{0.01, 0.1, 0.25, 0.5, 1.0, 2.5})), - ) - - loggingOpts := []logging.Option{ - logging.WithLogOnEvents(logging.StartCall, logging.FinishCall), - logging.WithFieldsFromContext(logging.ExtractFields), - } - - //nolint:contextcheck - serverOptions := []grpc.ServerOption{ - grpc.ChainUnaryInterceptor( - server.AddLoggingFieldsUnaryServerInterceptor(), - logging.UnaryServerInterceptor(interceptorLogger(logger), loggingOpts...), - server.RateLimitUnaryServerInterceptor(limiter), - metrics.UnaryServerInterceptor(), - grpc_recovery.UnaryServerInterceptor(recoveryOpt), - ), - grpc.ChainStreamInterceptor( - server.AddLoggingFieldsStreamServerInterceptor(), - server.RateLimitStreamServerInterceptor(limiter), - logging.StreamServerInterceptor(interceptorLogger(logger), loggingOpts...), - metrics.StreamServerInterceptor(), - grpc_recovery.StreamServerInterceptor(recoveryOpt), - ), - grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ - MinTime: 10 * time.Second, - }), - grpc.SharedWriteBuffer(true), - experimental.RecvBufferPool(grpc.NewSharedBufferPool()), - grpc.ReadBufferSize(16 * 1024), - grpc.WriteBufferSize(16 * 1024), - } - - state := state.NewState(logger) - prom.MustRegister(state) - - var stateStorage *storage.Storage - - if snapshotsEnabled { - stateStorage = storage.New(snapshotPath, state, logger) - prom.MustRegister(stateStorage) - - if err := stateStorage.Load(); err != nil { - logger.Warn("failed to load state from storage", zap.Error(err)) - } - } else { - logger.Info("snapshots are disabled") - } - - srv := server.NewClusterServer(state, ctx.Done(), redirectEndpoint) - prom.MustRegister(srv) - - lis, err := net.Listen("tcp", listenAddr) - if err != nil { - return fmt.Errorf("failed to listen: %w", err) - } - - landingLis, err := net.Listen("tcp", landingAddr) - if err != nil { - return fmt.Errorf("failed to listen: %w", err) - } - - s := grpc.NewServer(serverOptions...) - pb.RegisterClusterServer(s, srv) - - metrics.InitializeMetrics(s) - - if err = prom.Register(metrics); err != nil { - return fmt.Errorf("failed to register metrics: %w", err) - } - - var metricsMux http.ServeMux - - metricsMux.Handle("/metrics", promhttp.Handler()) - - metricsServer := http.Server{ - Addr: metricsAddr, - Handler: &metricsMux, - } - - landingServer := http.Server{ - Handler: landing.Handler(state, logger), - } - - eg, ctx := errgroup.WithContext(ctx) - - if snapshotsEnabled { - eg.Go(func() error { - return stateStorage.Start(ctx, clockwork.NewRealClock(), snapshotInterval) - }) - } - - eg.Go(func() error { - logger.Info("gRPC server starting", zap.Stringer("address", lis.Addr())) - - if err := s.Serve(lis); err != nil { - return fmt.Errorf("failed to serve: %w", err) - } - - return nil - }) - - eg.Go(func() error { - logger.Info("landing server starting", zap.Stringer("address", landingLis.Addr())) - - if err := landingServer.Serve(landingLis); err != nil && !errors.Is(err, http.ErrServerClosed) { - return fmt.Errorf("failed to serve: %w", err) - } - - return nil - }) - - eg.Go(func() error { - logger.Info("metrics starting", zap.String("address", metricsServer.Addr)) - - if err := metricsServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - return err - } - - return nil - }) - - eg.Go(func() error { - <-ctx.Done() - - shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) - defer shutdownCancel() - - s.GracefulStop() - landingServer.Shutdown(ctx) //nolint:errcheck - metricsServer.Shutdown(shutdownCtx) //nolint:errcheck,contextcheck - - return nil - }) - - eg.Go(func() error { - state.RunGC(ctx, logger, gcInterval) - - return nil - }) - - eg.Go(func() error { - limiter.RunGC(ctx) - - return nil - }) - - eg.Go(func() error { - return debug.ListenAndServe(ctx, debugAddr, func(msg string) { logger.Info(msg) }) - }) - - return eg.Wait() -} diff --git a/pkg/service/service.go b/pkg/service/service.go new file mode 100644 index 0000000..f9f21f8 --- /dev/null +++ b/pkg/service/service.go @@ -0,0 +1,318 @@ +// Copyright (c) 2024 Sidero Labs, Inc. +// +// Use of this software is governed by the Business Source License +// included in the LICENSE file. + +// Package service implements the high-level service entry point. +package service + +import ( + "context" + "errors" + "fmt" + "net" + "net/http" + "time" + + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" + "github.com/jonboulle/clockwork" + prom "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/siderolabs/discovery-api/api/v1alpha1/server/pb" + "github.com/siderolabs/go-debug" + "go.uber.org/zap" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/experimental" + "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/status" + + "github.com/siderolabs/discovery-service/internal/landing" + "github.com/siderolabs/discovery-service/internal/limiter" + "github.com/siderolabs/discovery-service/internal/state" + "github.com/siderolabs/discovery-service/internal/state/storage" + "github.com/siderolabs/discovery-service/pkg/limits" + "github.com/siderolabs/discovery-service/pkg/server" +) + +// Options are the configuration options for the service. +type Options struct { + MetricsRegisterer prom.Registerer + + LandingAddr string + MetricsAddr string + SnapshotPath string + DebugAddr string + RedirectEndpoint string + ListenAddr string + + GCInterval time.Duration + SnapshotInterval time.Duration + + LandingServerEnabled bool + DebugServerEnabled bool + MetricsServerEnabled bool + SnapshotsEnabled bool +} + +// Run starts the service with the given options. +func Run(ctx context.Context, options Options, logger *zap.Logger) error { + logger.Info("service starting") + + defer logger.Info("service shut down") + + recoveryOpt := grpc_recovery.WithRecoveryHandler(recoveryHandler(logger)) + + limiter := limiter.NewIPRateLimiter(limits.IPRateRequestsPerSecondMax, limits.IPRateBurstSizeMax) + + metrics := grpc_prometheus.NewServerMetrics( + grpc_prometheus.WithServerHandlingTimeHistogram(grpc_prometheus.WithHistogramBuckets([]float64{0.01, 0.1, 0.25, 0.5, 1.0, 2.5})), + ) + + loggingOpts := []logging.Option{ + logging.WithLogOnEvents(logging.StartCall, logging.FinishCall), + logging.WithFieldsFromContext(logging.ExtractFields), + } + + //nolint:contextcheck + serverOptions := []grpc.ServerOption{ + grpc.ChainUnaryInterceptor( + server.AddLoggingFieldsUnaryServerInterceptor(), + logging.UnaryServerInterceptor(interceptorLogger(logger), loggingOpts...), + server.RateLimitUnaryServerInterceptor(limiter), + metrics.UnaryServerInterceptor(), + grpc_recovery.UnaryServerInterceptor(recoveryOpt), + ), + grpc.ChainStreamInterceptor( + server.AddLoggingFieldsStreamServerInterceptor(), + server.RateLimitStreamServerInterceptor(limiter), + logging.StreamServerInterceptor(interceptorLogger(logger), loggingOpts...), + metrics.StreamServerInterceptor(), + grpc_recovery.StreamServerInterceptor(recoveryOpt), + ), + grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ + MinTime: 10 * time.Second, + }), + grpc.SharedWriteBuffer(true), + experimental.RecvBufferPool(grpc.NewSharedBufferPool()), + grpc.ReadBufferSize(16 * 1024), + grpc.WriteBufferSize(16 * 1024), + } + + state := state.NewState(logger) + + var stateStorage *storage.Storage + + if options.SnapshotsEnabled { + stateStorage = storage.New(options.SnapshotPath, state, logger) + if err := stateStorage.Load(); err != nil { + logger.Warn("failed to load state from storage", zap.Error(err)) + } + } else { + logger.Info("snapshots are disabled") + } + + srv := server.NewClusterServer(state, ctx.Done(), options.RedirectEndpoint) + + lis, err := net.Listen("tcp", options.ListenAddr) + if err != nil { + return fmt.Errorf("failed to listen: %w", err) + } + + landingLis, err := net.Listen("tcp", options.LandingAddr) + if err != nil { + return fmt.Errorf("failed to listen: %w", err) + } + + s := grpc.NewServer(serverOptions...) + pb.RegisterClusterServer(s, srv) + + metrics.InitializeMetrics(s) + + var ( + metricsServer http.Server + landingServer http.Server + ) + + if options.MetricsServerEnabled { + var metricsMux http.ServeMux + + metricsMux.Handle("/metrics", promhttp.Handler()) + + metricsServer = http.Server{ + Addr: options.MetricsAddr, + Handler: &metricsMux, + } + } + + if options.LandingServerEnabled { + landingServer = http.Server{ + Handler: landing.Handler(state, logger), + } + } + + eg, ctx := errgroup.WithContext(ctx) + + if options.SnapshotsEnabled { + eg.Go(func() error { + return stateStorage.Start(ctx, clockwork.NewRealClock(), options.SnapshotInterval) + }) + } + + eg.Go(func() error { + logger.Info("gRPC server starting", zap.Stringer("address", lis.Addr())) + + if serveErr := s.Serve(lis); serveErr != nil { + return fmt.Errorf("failed to serve: %w", serveErr) + } + + return nil + }) + + if options.LandingServerEnabled { + eg.Go(func() error { + logger.Info("landing server starting", zap.Stringer("address", landingLis.Addr())) + + if serveErr := landingServer.Serve(landingLis); serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) { + return fmt.Errorf("failed to serve: %w", serveErr) + } + + return nil + }) + } + + if options.MetricsServerEnabled { + eg.Go(func() error { + logger.Info("metrics starting", zap.String("address", metricsServer.Addr)) + + if serveErr := metricsServer.ListenAndServe(); serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) { + return serveErr + } + + return nil + }) + } + + eg.Go(func() error { + <-ctx.Done() + + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer shutdownCancel() + + s.GracefulStop() + + if options.LandingServerEnabled { + landingServer.Shutdown(ctx) //nolint:errcheck + } + + if options.MetricsServerEnabled { + metricsServer.Shutdown(shutdownCtx) //nolint:errcheck,contextcheck + } + + return nil + }) + + eg.Go(func() error { + state.RunGC(ctx, logger, options.GCInterval) + + return nil + }) + + eg.Go(func() error { + limiter.RunGC(ctx) + + return nil + }) + + if options.DebugServerEnabled { + eg.Go(func() error { + return debug.ListenAndServe(ctx, options.DebugAddr, func(msg string) { logger.Info(msg) }) + }) + } + + if options.MetricsRegisterer != nil { + collectors := []prom.Collector{state, srv, metrics, stateStorage} + + defer unregisterCollectors(options.MetricsRegisterer, collectors...) + + if err = registerCollectors(options.MetricsRegisterer, collectors...); err != nil { + return fmt.Errorf("failed to register collectors: %w", err) + } + } + + return eg.Wait() +} + +func recoveryHandler(logger *zap.Logger) grpc_recovery.RecoveryHandlerFunc { + return func(p interface{}) error { + if logger != nil { + logger.Error("grpc panic", zap.Any("panic", p), zap.Stack("stack")) + } + + return status.Errorf(codes.Internal, "%v", p) + } +} + +func interceptorLogger(l *zap.Logger) logging.Logger { + return logging.LoggerFunc(func(_ context.Context, lvl logging.Level, msg string, fields ...any) { + f := make([]zap.Field, 0, len(fields)/2) + + for i := 0; i < len(fields); i += 2 { + key := fields[i].(string) //nolint:forcetypeassert,errcheck + value := fields[i+1] + + switch v := value.(type) { + case string: + f = append(f, zap.String(key, v)) + case int: + f = append(f, zap.Int(key, v)) + case bool: + f = append(f, zap.Bool(key, v)) + default: + f = append(f, zap.Any(key, v)) + } + } + + logger := l.WithOptions(zap.AddCallerSkip(1)).With(f...) + + switch lvl { + case logging.LevelDebug: + logger.Debug(msg) + case logging.LevelInfo: + logger.Info(msg) + case logging.LevelWarn: + logger.Warn(msg) + case logging.LevelError: + logger.Error(msg) + default: + panic(fmt.Sprintf("unknown level %v", lvl)) + } + }) +} + +func unregisterCollectors(registerer prom.Registerer, collectors ...prom.Collector) { + for _, collector := range collectors { + if collector == nil { + continue + } + + registerer.Unregister(collector) + } +} + +func registerCollectors(registerer prom.Registerer, collectors ...prom.Collector) (err error) { + for _, collector := range collectors { + if collector == nil { + continue + } + + if err = registerer.Register(collector); err != nil { + return fmt.Errorf("failed to register collector: %w", err) + } + } + + return nil +}