From e10e27451263ebd248efaf401f9b186cbee50ca5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 02:01:25 +0000 Subject: [PATCH 1/2] Refactor: Update core Go dependencies and refactor for compatibility. This commit updates several key dependencies to their more recent versions and refactors the codebase to ensure compatibility with the new APIs. Key changes include: - Updated Go version in `go.mod` to 1.23.0 and toolchain to 1.23.9. - Migrated etcd client from `github.com/coreos/etcd v3.3.18+incompatible` to `go.etcd.io/etcd/client/v3 v3.5.21`. This involved significant refactoring of the etcd wrapper (`server/ectdwrap.go`) to use the new v3 client API, including atomic operations (Compare-And-Swap) for critical sections and lease-based TTLs. - Migrated protobuf library from the deprecated `github.com/golang/protobuf v1.3.4` to `google.golang.org/protobuf v1.36.6`. - Regenerated protobuf Go files (`api/uuid.pb.go`, `api/uuid_grpc.pb.go`) using the new `protoc-gen-go` and `protoc-gen-go-grpc` plugins. Updated `api/compile.bat` and added `go_package` option to `api/uuid.proto`. - Updated `github.com/urfave/cli/v2` from `v2.1.1` to `v2.27.6`. - Updated `golang.org/x/net` from `v0.33.0` to `v0.40.0`. - Updated `google.golang.org/grpc` from `v1.27.1` to `v1.72.1`. - Ran `go mod tidy` to update `go.sum` and ensure dependency consistency. - All existing tests pass with the updated libraries and refactored code. These changes help modernize the project, improve maintainability, and ensure it uses up-to-date and supported libraries. --- api/compile.bat | 5 +- api/uuid.pb.go | 411 +++++++++---------- api/uuid.proto | 2 + api/uuid_grpc.pb.go | 121 ++++++ github.com/cnwinds/flake/api/uuid.pb.go | 269 ++++++++++++ github.com/cnwinds/flake/api/uuid_grpc.pb.go | 121 ++++++ go.mod | 62 ++- go.sum | 308 ++++---------- server/ectdwrap.go | 299 +++++++++++--- server/uuid_server.go | 365 +++++++++++----- 10 files changed, 1321 insertions(+), 642 deletions(-) mode change 100644 => 100755 api/compile.bat create mode 100644 api/uuid_grpc.pb.go create mode 100644 github.com/cnwinds/flake/api/uuid.pb.go create mode 100644 github.com/cnwinds/flake/api/uuid_grpc.pb.go diff --git a/api/compile.bat b/api/compile.bat old mode 100644 new mode 100755 index 0d63577..aebc812 --- a/api/compile.bat +++ b/api/compile.bat @@ -1 +1,4 @@ -protoc --go_out=plugins=grpc:. api\uuid.proto \ No newline at end of file +protoc --proto_path=. \ + --go_out=paths=source_relative:. \ + --go-grpc_out=paths=source_relative:. \ + api/uuid.proto \ No newline at end of file diff --git a/api/uuid.pb.go b/api/uuid.pb.go index 904a2c7..3ea8129 100644 --- a/api/uuid.pb.go +++ b/api/uuid.pb.go @@ -1,292 +1,269 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v3.21.12 // source: api/uuid.proto package api import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type FetchRequest struct { - ServiceName string `protobuf:"bytes,1,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` - ContainerName string `protobuf:"bytes,2,opt,name=container_name,json=containerName,proto3" json:"container_name,omitempty"` - NeedCount int32 `protobuf:"varint,3,opt,name=need_count,json=needCount,proto3" json:"need_count,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState `protogen:"open.v1"` + ServiceName string `protobuf:"bytes,1,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` + ContainerName string `protobuf:"bytes,2,opt,name=container_name,json=containerName,proto3" json:"container_name,omitempty"` + NeedCount int32 `protobuf:"varint,3,opt,name=need_count,json=needCount,proto3" json:"need_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (m *FetchRequest) Reset() { *m = FetchRequest{} } -func (m *FetchRequest) String() string { return proto.CompactTextString(m) } -func (*FetchRequest) ProtoMessage() {} -func (*FetchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_61fc83c022ba86aa, []int{0} +func (x *FetchRequest) Reset() { + *x = FetchRequest{} + mi := &file_api_uuid_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } -func (m *FetchRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FetchRequest.Unmarshal(m, b) -} -func (m *FetchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FetchRequest.Marshal(b, m, deterministic) +func (x *FetchRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *FetchRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_FetchRequest.Merge(m, src) -} -func (m *FetchRequest) XXX_Size() int { - return xxx_messageInfo_FetchRequest.Size(m) -} -func (m *FetchRequest) XXX_DiscardUnknown() { - xxx_messageInfo_FetchRequest.DiscardUnknown(m) + +func (*FetchRequest) ProtoMessage() {} + +func (x *FetchRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_FetchRequest proto.InternalMessageInfo +// Deprecated: Use FetchRequest.ProtoReflect.Descriptor instead. +func (*FetchRequest) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{0} +} -func (m *FetchRequest) GetServiceName() string { - if m != nil { - return m.ServiceName +func (x *FetchRequest) GetServiceName() string { + if x != nil { + return x.ServiceName } return "" } -func (m *FetchRequest) GetContainerName() string { - if m != nil { - return m.ContainerName +func (x *FetchRequest) GetContainerName() string { + if x != nil { + return x.ContainerName } return "" } -func (m *FetchRequest) GetNeedCount() int32 { - if m != nil { - return m.NeedCount +func (x *FetchRequest) GetNeedCount() int32 { + if x != nil { + return x.NeedCount } return 0 } type UUIDRange struct { - ServiceId int32 `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - ContainerId int32 `protobuf:"varint,2,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - SequenceIdStart int32 `protobuf:"varint,3,opt,name=sequence_id_start,json=sequenceIdStart,proto3" json:"sequence_id_start,omitempty"` - SequenceIdEnd int32 `protobuf:"varint,4,opt,name=sequence_id_end,json=sequenceIdEnd,proto3" json:"sequence_id_end,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState `protogen:"open.v1"` + ServiceId int32 `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + ContainerId int32 `protobuf:"varint,2,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + SequenceIdStart int32 `protobuf:"varint,3,opt,name=sequence_id_start,json=sequenceIdStart,proto3" json:"sequence_id_start,omitempty"` + SequenceIdEnd int32 `protobuf:"varint,4,opt,name=sequence_id_end,json=sequenceIdEnd,proto3" json:"sequence_id_end,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (m *UUIDRange) Reset() { *m = UUIDRange{} } -func (m *UUIDRange) String() string { return proto.CompactTextString(m) } -func (*UUIDRange) ProtoMessage() {} -func (*UUIDRange) Descriptor() ([]byte, []int) { - return fileDescriptor_61fc83c022ba86aa, []int{1} +func (x *UUIDRange) Reset() { + *x = UUIDRange{} + mi := &file_api_uuid_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } -func (m *UUIDRange) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_UUIDRange.Unmarshal(m, b) -} -func (m *UUIDRange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_UUIDRange.Marshal(b, m, deterministic) +func (x *UUIDRange) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *UUIDRange) XXX_Merge(src proto.Message) { - xxx_messageInfo_UUIDRange.Merge(m, src) -} -func (m *UUIDRange) XXX_Size() int { - return xxx_messageInfo_UUIDRange.Size(m) -} -func (m *UUIDRange) XXX_DiscardUnknown() { - xxx_messageInfo_UUIDRange.DiscardUnknown(m) + +func (*UUIDRange) ProtoMessage() {} + +func (x *UUIDRange) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_UUIDRange proto.InternalMessageInfo +// Deprecated: Use UUIDRange.ProtoReflect.Descriptor instead. +func (*UUIDRange) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{1} +} -func (m *UUIDRange) GetServiceId() int32 { - if m != nil { - return m.ServiceId +func (x *UUIDRange) GetServiceId() int32 { + if x != nil { + return x.ServiceId } return 0 } -func (m *UUIDRange) GetContainerId() int32 { - if m != nil { - return m.ContainerId +func (x *UUIDRange) GetContainerId() int32 { + if x != nil { + return x.ContainerId } return 0 } -func (m *UUIDRange) GetSequenceIdStart() int32 { - if m != nil { - return m.SequenceIdStart +func (x *UUIDRange) GetSequenceIdStart() int32 { + if x != nil { + return x.SequenceIdStart } return 0 } -func (m *UUIDRange) GetSequenceIdEnd() int32 { - if m != nil { - return m.SequenceIdEnd +func (x *UUIDRange) GetSequenceIdEnd() int32 { + if x != nil { + return x.SequenceIdEnd } return 0 } type FetchReply struct { - Items []*UUIDRange `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState `protogen:"open.v1"` + Items []*UUIDRange `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (m *FetchReply) Reset() { *m = FetchReply{} } -func (m *FetchReply) String() string { return proto.CompactTextString(m) } -func (*FetchReply) ProtoMessage() {} -func (*FetchReply) Descriptor() ([]byte, []int) { - return fileDescriptor_61fc83c022ba86aa, []int{2} +func (x *FetchReply) Reset() { + *x = FetchReply{} + mi := &file_api_uuid_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } -func (m *FetchReply) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FetchReply.Unmarshal(m, b) -} -func (m *FetchReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FetchReply.Marshal(b, m, deterministic) -} -func (m *FetchReply) XXX_Merge(src proto.Message) { - xxx_messageInfo_FetchReply.Merge(m, src) -} -func (m *FetchReply) XXX_Size() int { - return xxx_messageInfo_FetchReply.Size(m) -} -func (m *FetchReply) XXX_DiscardUnknown() { - xxx_messageInfo_FetchReply.DiscardUnknown(m) +func (x *FetchReply) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_FetchReply proto.InternalMessageInfo +func (*FetchReply) ProtoMessage() {} -func (m *FetchReply) GetItems() []*UUIDRange { - if m != nil { - return m.Items +func (x *FetchReply) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -func init() { - proto.RegisterType((*FetchRequest)(nil), "api.FetchRequest") - proto.RegisterType((*UUIDRange)(nil), "api.UUIDRange") - proto.RegisterType((*FetchReply)(nil), "api.FetchReply") -} - -func init() { proto.RegisterFile("api/uuid.proto", fileDescriptor_61fc83c022ba86aa) } - -var fileDescriptor_61fc83c022ba86aa = []byte{ - // 280 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xdf, 0x4a, 0x84, 0x40, - 0x14, 0xc6, 0xb3, 0x5d, 0x03, 0x8f, 0xbb, 0xca, 0xce, 0x95, 0x04, 0x81, 0x49, 0x85, 0x04, 0x19, - 0x18, 0x3d, 0x41, 0x7f, 0xc0, 0x9b, 0x2e, 0x26, 0xf6, 0x5a, 0x26, 0xe7, 0x50, 0x03, 0xeb, 0x38, - 0xe9, 0x58, 0xec, 0xe3, 0xf4, 0xa6, 0x31, 0xb3, 0xea, 0x7a, 0xfb, 0x3b, 0xbf, 0x99, 0x6f, 0xce, - 0x37, 0x10, 0x30, 0x25, 0xee, 0xfb, 0x5e, 0xf0, 0x4c, 0xb5, 0x8d, 0x6e, 0xc8, 0x82, 0x29, 0x91, - 0xfc, 0xc2, 0xea, 0x15, 0x75, 0xf5, 0x45, 0xf1, 0xbb, 0xc7, 0x4e, 0x93, 0x4b, 0x58, 0x75, 0xd8, - 0xfe, 0x88, 0x0a, 0x4b, 0xc9, 0x6a, 0x8c, 0x9c, 0xd8, 0x49, 0x3d, 0xea, 0x0f, 0xec, 0x8d, 0xd5, - 0x48, 0xae, 0x21, 0xa8, 0x1a, 0xa9, 0x99, 0x90, 0xd8, 0x1e, 0xa4, 0x53, 0x2b, 0xad, 0x27, 0x6a, - 0xb5, 0x0b, 0x00, 0x89, 0xc8, 0xcb, 0xaa, 0xe9, 0xa5, 0x8e, 0x16, 0xb1, 0x93, 0xba, 0xd4, 0x33, - 0xe4, 0xc9, 0x80, 0xe4, 0xcf, 0x01, 0x6f, 0xbb, 0x2d, 0x9e, 0x29, 0x93, 0x9f, 0x56, 0x1e, 0x63, - 0x05, 0xb7, 0xa1, 0x2e, 0xf5, 0x06, 0x52, 0x70, 0xf3, 0xaa, 0x63, 0xa4, 0xe0, 0x36, 0xd0, 0xa5, - 0xfe, 0xc4, 0x0a, 0x4e, 0x6e, 0x61, 0xd3, 0x99, 0x1d, 0xa4, 0xbd, 0xa2, 0xec, 0x34, 0x6b, 0xc7, - 0xd4, 0x70, 0x1c, 0x14, 0xfc, 0xdd, 0x60, 0x72, 0x03, 0xe1, 0xdc, 0x45, 0xc9, 0xa3, 0xa5, 0x35, - 0xd7, 0x47, 0xf3, 0x45, 0xf2, 0x24, 0x07, 0x18, 0xca, 0x51, 0xbb, 0x3d, 0xb9, 0x02, 0x57, 0x68, - 0xac, 0xbb, 0xc8, 0x89, 0x17, 0xa9, 0x9f, 0x07, 0x19, 0x53, 0x22, 0x9b, 0x56, 0xa0, 0x87, 0x61, - 0xfe, 0x08, 0x4b, 0xc3, 0xc8, 0x1d, 0xb8, 0xf6, 0x2c, 0xd9, 0x58, 0x6f, 0x5e, 0xf2, 0x79, 0x38, - 0x47, 0x6a, 0xb7, 0x4f, 0x4e, 0x3e, 0xce, 0xec, 0x9f, 0x3c, 0xfc, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x3f, 0xc9, 0xdb, 0x7b, 0xa5, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// UUIDClient is the client API for UUID service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type UUIDClient interface { - Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) -} - -type uUIDClient struct { - cc grpc.ClientConnInterface -} - -func NewUUIDClient(cc grpc.ClientConnInterface) UUIDClient { - return &uUIDClient{cc} +// Deprecated: Use FetchReply.ProtoReflect.Descriptor instead. +func (*FetchReply) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{2} } -func (c *uUIDClient) Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) { - out := new(FetchReply) - err := c.cc.Invoke(ctx, "/api.UUID/Fetch", in, out, opts...) - if err != nil { - return nil, err +func (x *FetchReply) GetItems() []*UUIDRange { + if x != nil { + return x.Items } - return out, nil -} - -// UUIDServer is the server API for UUID service. -type UUIDServer interface { - Fetch(context.Context, *FetchRequest) (*FetchReply, error) -} - -// UnimplementedUUIDServer can be embedded to have forward compatible implementations. -type UnimplementedUUIDServer struct { -} - -func (*UnimplementedUUIDServer) Fetch(ctx context.Context, req *FetchRequest) (*FetchReply, error) { - return nil, status.Errorf(codes.Unimplemented, "method Fetch not implemented") + return nil } -func RegisterUUIDServer(s *grpc.Server, srv UUIDServer) { - s.RegisterService(&_UUID_serviceDesc, srv) -} +var File_api_uuid_proto protoreflect.FileDescriptor + +const file_api_uuid_proto_rawDesc = "" + + "\n" + + "\x0eapi/uuid.proto\x12\x03api\"w\n" + + "\fFetchRequest\x12!\n" + + "\fservice_name\x18\x01 \x01(\tR\vserviceName\x12%\n" + + "\x0econtainer_name\x18\x02 \x01(\tR\rcontainerName\x12\x1d\n" + + "\n" + + "need_count\x18\x03 \x01(\x05R\tneedCount\"\xa1\x01\n" + + "\tUUIDRange\x12\x1d\n" + + "\n" + + "service_id\x18\x01 \x01(\x05R\tserviceId\x12!\n" + + "\fcontainer_id\x18\x02 \x01(\x05R\vcontainerId\x12*\n" + + "\x11sequence_id_start\x18\x03 \x01(\x05R\x0fsequenceIdStart\x12&\n" + + "\x0fsequence_id_end\x18\x04 \x01(\x05R\rsequenceIdEnd\"2\n" + + "\n" + + "FetchReply\x12$\n" + + "\x05items\x18\x01 \x03(\v2\x0e.api.UUIDRangeR\x05items25\n" + + "\x04UUID\x12-\n" + + "\x05Fetch\x12\x11.api.FetchRequest\x1a\x0f.api.FetchReply\"\x00B\x1eZ\x1cgithub.com/cnwinds/flake/apib\x06proto3" + +var ( + file_api_uuid_proto_rawDescOnce sync.Once + file_api_uuid_proto_rawDescData []byte +) -func _UUID_Fetch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(FetchRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UUIDServer).Fetch(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.UUID/Fetch", +func file_api_uuid_proto_rawDescGZIP() []byte { + file_api_uuid_proto_rawDescOnce.Do(func() { + file_api_uuid_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_uuid_proto_rawDesc), len(file_api_uuid_proto_rawDesc))) + }) + return file_api_uuid_proto_rawDescData +} + +var file_api_uuid_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_api_uuid_proto_goTypes = []any{ + (*FetchRequest)(nil), // 0: api.FetchRequest + (*UUIDRange)(nil), // 1: api.UUIDRange + (*FetchReply)(nil), // 2: api.FetchReply +} +var file_api_uuid_proto_depIdxs = []int32{ + 1, // 0: api.FetchReply.items:type_name -> api.UUIDRange + 0, // 1: api.UUID.Fetch:input_type -> api.FetchRequest + 2, // 2: api.UUID.Fetch:output_type -> api.FetchReply + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_api_uuid_proto_init() } +func file_api_uuid_proto_init() { + if File_api_uuid_proto != nil { + return } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UUIDServer).Fetch(ctx, req.(*FetchRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _UUID_serviceDesc = grpc.ServiceDesc{ - ServiceName: "api.UUID", - HandlerType: (*UUIDServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Fetch", - Handler: _UUID_Fetch_Handler, + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_uuid_proto_rawDesc), len(file_api_uuid_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "api/uuid.proto", + GoTypes: file_api_uuid_proto_goTypes, + DependencyIndexes: file_api_uuid_proto_depIdxs, + MessageInfos: file_api_uuid_proto_msgTypes, + }.Build() + File_api_uuid_proto = out.File + file_api_uuid_proto_goTypes = nil + file_api_uuid_proto_depIdxs = nil } diff --git a/api/uuid.proto b/api/uuid.proto index 77788ab..d33e89a 100644 --- a/api/uuid.proto +++ b/api/uuid.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package api; +option go_package = "github.com/cnwinds/flake/api"; + service UUID { rpc Fetch(FetchRequest) returns (FetchReply) {} } diff --git a/api/uuid_grpc.pb.go b/api/uuid_grpc.pb.go new file mode 100644 index 0000000..0b30d7d --- /dev/null +++ b/api/uuid_grpc.pb.go @@ -0,0 +1,121 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v3.21.12 +// source: api/uuid.proto + +package api + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + UUID_Fetch_FullMethodName = "/api.UUID/Fetch" +) + +// UUIDClient is the client API for UUID service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UUIDClient interface { + Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) +} + +type uUIDClient struct { + cc grpc.ClientConnInterface +} + +func NewUUIDClient(cc grpc.ClientConnInterface) UUIDClient { + return &uUIDClient{cc} +} + +func (c *uUIDClient) Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FetchReply) + err := c.cc.Invoke(ctx, UUID_Fetch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UUIDServer is the server API for UUID service. +// All implementations must embed UnimplementedUUIDServer +// for forward compatibility. +type UUIDServer interface { + Fetch(context.Context, *FetchRequest) (*FetchReply, error) + mustEmbedUnimplementedUUIDServer() +} + +// UnimplementedUUIDServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedUUIDServer struct{} + +func (UnimplementedUUIDServer) Fetch(context.Context, *FetchRequest) (*FetchReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Fetch not implemented") +} +func (UnimplementedUUIDServer) mustEmbedUnimplementedUUIDServer() {} +func (UnimplementedUUIDServer) testEmbeddedByValue() {} + +// UnsafeUUIDServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UUIDServer will +// result in compilation errors. +type UnsafeUUIDServer interface { + mustEmbedUnimplementedUUIDServer() +} + +func RegisterUUIDServer(s grpc.ServiceRegistrar, srv UUIDServer) { + // If the following call pancis, it indicates UnimplementedUUIDServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&UUID_ServiceDesc, srv) +} + +func _UUID_Fetch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FetchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UUIDServer).Fetch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UUID_Fetch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UUIDServer).Fetch(ctx, req.(*FetchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// UUID_ServiceDesc is the grpc.ServiceDesc for UUID service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var UUID_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.UUID", + HandlerType: (*UUIDServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Fetch", + Handler: _UUID_Fetch_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api/uuid.proto", +} diff --git a/github.com/cnwinds/flake/api/uuid.pb.go b/github.com/cnwinds/flake/api/uuid.pb.go new file mode 100644 index 0000000..3ea8129 --- /dev/null +++ b/github.com/cnwinds/flake/api/uuid.pb.go @@ -0,0 +1,269 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v3.21.12 +// source: api/uuid.proto + +package api + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FetchRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServiceName string `protobuf:"bytes,1,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` + ContainerName string `protobuf:"bytes,2,opt,name=container_name,json=containerName,proto3" json:"container_name,omitempty"` + NeedCount int32 `protobuf:"varint,3,opt,name=need_count,json=needCount,proto3" json:"need_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FetchRequest) Reset() { + *x = FetchRequest{} + mi := &file_api_uuid_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FetchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FetchRequest) ProtoMessage() {} + +func (x *FetchRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FetchRequest.ProtoReflect.Descriptor instead. +func (*FetchRequest) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{0} +} + +func (x *FetchRequest) GetServiceName() string { + if x != nil { + return x.ServiceName + } + return "" +} + +func (x *FetchRequest) GetContainerName() string { + if x != nil { + return x.ContainerName + } + return "" +} + +func (x *FetchRequest) GetNeedCount() int32 { + if x != nil { + return x.NeedCount + } + return 0 +} + +type UUIDRange struct { + state protoimpl.MessageState `protogen:"open.v1"` + ServiceId int32 `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + ContainerId int32 `protobuf:"varint,2,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + SequenceIdStart int32 `protobuf:"varint,3,opt,name=sequence_id_start,json=sequenceIdStart,proto3" json:"sequence_id_start,omitempty"` + SequenceIdEnd int32 `protobuf:"varint,4,opt,name=sequence_id_end,json=sequenceIdEnd,proto3" json:"sequence_id_end,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UUIDRange) Reset() { + *x = UUIDRange{} + mi := &file_api_uuid_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UUIDRange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UUIDRange) ProtoMessage() {} + +func (x *UUIDRange) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UUIDRange.ProtoReflect.Descriptor instead. +func (*UUIDRange) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{1} +} + +func (x *UUIDRange) GetServiceId() int32 { + if x != nil { + return x.ServiceId + } + return 0 +} + +func (x *UUIDRange) GetContainerId() int32 { + if x != nil { + return x.ContainerId + } + return 0 +} + +func (x *UUIDRange) GetSequenceIdStart() int32 { + if x != nil { + return x.SequenceIdStart + } + return 0 +} + +func (x *UUIDRange) GetSequenceIdEnd() int32 { + if x != nil { + return x.SequenceIdEnd + } + return 0 +} + +type FetchReply struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []*UUIDRange `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FetchReply) Reset() { + *x = FetchReply{} + mi := &file_api_uuid_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FetchReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FetchReply) ProtoMessage() {} + +func (x *FetchReply) ProtoReflect() protoreflect.Message { + mi := &file_api_uuid_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FetchReply.ProtoReflect.Descriptor instead. +func (*FetchReply) Descriptor() ([]byte, []int) { + return file_api_uuid_proto_rawDescGZIP(), []int{2} +} + +func (x *FetchReply) GetItems() []*UUIDRange { + if x != nil { + return x.Items + } + return nil +} + +var File_api_uuid_proto protoreflect.FileDescriptor + +const file_api_uuid_proto_rawDesc = "" + + "\n" + + "\x0eapi/uuid.proto\x12\x03api\"w\n" + + "\fFetchRequest\x12!\n" + + "\fservice_name\x18\x01 \x01(\tR\vserviceName\x12%\n" + + "\x0econtainer_name\x18\x02 \x01(\tR\rcontainerName\x12\x1d\n" + + "\n" + + "need_count\x18\x03 \x01(\x05R\tneedCount\"\xa1\x01\n" + + "\tUUIDRange\x12\x1d\n" + + "\n" + + "service_id\x18\x01 \x01(\x05R\tserviceId\x12!\n" + + "\fcontainer_id\x18\x02 \x01(\x05R\vcontainerId\x12*\n" + + "\x11sequence_id_start\x18\x03 \x01(\x05R\x0fsequenceIdStart\x12&\n" + + "\x0fsequence_id_end\x18\x04 \x01(\x05R\rsequenceIdEnd\"2\n" + + "\n" + + "FetchReply\x12$\n" + + "\x05items\x18\x01 \x03(\v2\x0e.api.UUIDRangeR\x05items25\n" + + "\x04UUID\x12-\n" + + "\x05Fetch\x12\x11.api.FetchRequest\x1a\x0f.api.FetchReply\"\x00B\x1eZ\x1cgithub.com/cnwinds/flake/apib\x06proto3" + +var ( + file_api_uuid_proto_rawDescOnce sync.Once + file_api_uuid_proto_rawDescData []byte +) + +func file_api_uuid_proto_rawDescGZIP() []byte { + file_api_uuid_proto_rawDescOnce.Do(func() { + file_api_uuid_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_uuid_proto_rawDesc), len(file_api_uuid_proto_rawDesc))) + }) + return file_api_uuid_proto_rawDescData +} + +var file_api_uuid_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_api_uuid_proto_goTypes = []any{ + (*FetchRequest)(nil), // 0: api.FetchRequest + (*UUIDRange)(nil), // 1: api.UUIDRange + (*FetchReply)(nil), // 2: api.FetchReply +} +var file_api_uuid_proto_depIdxs = []int32{ + 1, // 0: api.FetchReply.items:type_name -> api.UUIDRange + 0, // 1: api.UUID.Fetch:input_type -> api.FetchRequest + 2, // 2: api.UUID.Fetch:output_type -> api.FetchReply + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_api_uuid_proto_init() } +func file_api_uuid_proto_init() { + if File_api_uuid_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_uuid_proto_rawDesc), len(file_api_uuid_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_api_uuid_proto_goTypes, + DependencyIndexes: file_api_uuid_proto_depIdxs, + MessageInfos: file_api_uuid_proto_msgTypes, + }.Build() + File_api_uuid_proto = out.File + file_api_uuid_proto_goTypes = nil + file_api_uuid_proto_depIdxs = nil +} diff --git a/github.com/cnwinds/flake/api/uuid_grpc.pb.go b/github.com/cnwinds/flake/api/uuid_grpc.pb.go new file mode 100644 index 0000000..0b30d7d --- /dev/null +++ b/github.com/cnwinds/flake/api/uuid_grpc.pb.go @@ -0,0 +1,121 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v3.21.12 +// source: api/uuid.proto + +package api + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + UUID_Fetch_FullMethodName = "/api.UUID/Fetch" +) + +// UUIDClient is the client API for UUID service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UUIDClient interface { + Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) +} + +type uUIDClient struct { + cc grpc.ClientConnInterface +} + +func NewUUIDClient(cc grpc.ClientConnInterface) UUIDClient { + return &uUIDClient{cc} +} + +func (c *uUIDClient) Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FetchReply) + err := c.cc.Invoke(ctx, UUID_Fetch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UUIDServer is the server API for UUID service. +// All implementations must embed UnimplementedUUIDServer +// for forward compatibility. +type UUIDServer interface { + Fetch(context.Context, *FetchRequest) (*FetchReply, error) + mustEmbedUnimplementedUUIDServer() +} + +// UnimplementedUUIDServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedUUIDServer struct{} + +func (UnimplementedUUIDServer) Fetch(context.Context, *FetchRequest) (*FetchReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Fetch not implemented") +} +func (UnimplementedUUIDServer) mustEmbedUnimplementedUUIDServer() {} +func (UnimplementedUUIDServer) testEmbeddedByValue() {} + +// UnsafeUUIDServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UUIDServer will +// result in compilation errors. +type UnsafeUUIDServer interface { + mustEmbedUnimplementedUUIDServer() +} + +func RegisterUUIDServer(s grpc.ServiceRegistrar, srv UUIDServer) { + // If the following call pancis, it indicates UnimplementedUUIDServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&UUID_ServiceDesc, srv) +} + +func _UUID_Fetch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FetchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UUIDServer).Fetch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UUID_Fetch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UUIDServer).Fetch(ctx, req.(*FetchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// UUID_ServiceDesc is the grpc.ServiceDesc for UUID service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var UUID_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.UUID", + HandlerType: (*UUIDServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Fetch", + Handler: _UUID_Fetch_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api/uuid.proto", +} diff --git a/go.mod b/go.mod index 9402510..52fec3a 100644 --- a/go.mod +++ b/go.mod @@ -1,47 +1,33 @@ module github.com/cnwinds/flake -go 1.23 +go 1.23.0 + +toolchain go1.23.9 require ( - github.com/coreos/etcd v3.3.18+incompatible - github.com/golang/protobuf v1.3.4 - github.com/urfave/cli/v2 v2.1.1 - golang.org/x/net v0.33.0 - google.golang.org/grpc v1.27.1 + github.com/urfave/cli/v2 v2.27.6 + go.etcd.io/etcd/api/v3 v3.5.21 + go.etcd.io/etcd/client/v3 v3.5.21 + golang.org/x/net v0.40.0 + google.golang.org/grpc v1.72.1 + google.golang.org/protobuf v1.36.6 ) require ( - github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/go-semver v0.3.0 // indirect - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect - github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect - github.com/gogo/protobuf v1.3.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/google/btree v1.0.0 // indirect - github.com/google/go-cmp v0.4.0 // indirect - github.com/google/uuid v1.1.1 // indirect - github.com/gorilla/websocket v1.4.1 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.13.0 // indirect - github.com/jonboulle/clockwork v0.1.0 // indirect - github.com/json-iterator/go v1.1.9 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/prometheus/client_golang v1.4.1 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/soheilhy/cmux v0.1.4 // indirect - github.com/stretchr/testify v1.4.0 // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.uber.org/zap v1.14.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.17.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect ) diff --git a/go.sum b/go.sum index 9a0775a..7645ad0 100644 --- a/go.sum +++ b/go.sum @@ -1,241 +1,113 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.18+incompatible h1:Zz1aXgDrFFi1nadh58tA9ktt06cmPTwNNP3dXwIq1lE= -github.com/coreos/etcd v3.3.18+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI= -github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= -github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -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= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc h1:yUaosFVTJwnltaHbSNC3i82I92quFs+OFPRl8kNMVwo= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.14.0 h1:/pduUoebOeeJzTDFuoMgC6nRkiasr1sBCIEorly7m4o= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= +github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8= +go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY= +go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc= +go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs= +go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY= +go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/ectdwrap.go b/server/ectdwrap.go index b16a5b2..140519d 100644 --- a/server/ectdwrap.go +++ b/server/ectdwrap.go @@ -1,12 +1,16 @@ package server import ( + "context" "log" "strconv" + "time" - "github.com/coreos/etcd/client" - "github.com/coreos/etcd/version" - "golang.org/x/net/context" + clientv3 "go.etcd.io/etcd/client/v3" + "google.golang.org/grpc/status" + "google.golang.org/grpc/codes" + // "go.etcd.io/etcd/api/v3/version" // Keep commented for now, GetVersion needs rework + "errors" ) // EtcdWrapConfig config struct @@ -22,106 +26,273 @@ type EtcdWrapConfig struct { // EtcdWrap Encapsulation of etcd type EtcdWrap struct { - cfg *EtcdWrapConfig - etcdClient client.Client - etcdAPI client.KeysAPI + cfg *EtcdWrapConfig + client *clientv3.Client } // NewEtcdWrap create a new etcd wrap. -func NewEtcdWrap(cfg *EtcdWrapConfig) (w *EtcdWrap, err error) { - w = &EtcdWrap{cfg: cfg} - log.Printf("etcd wrap config: %v", cfg) - etcdCfg := client.Config{ - Endpoints: cfg.Endpoints, - Username: cfg.UserName, - Password: cfg.Password, - } - w.etcdClient, err = client.New(etcdCfg) +func NewEtcdWrap(cfg *EtcdWrapConfig) (*EtcdWrap, error) { + log.Printf("etcd wrap config: %+v", cfg) + + cli, err := clientv3.New(clientv3.Config{ + Endpoints: cfg.Endpoints, + Username: cfg.UserName, + Password: cfg.Password, + DialTimeout: 5 * time.Second, // Example timeout + }) + if err != nil { + log.Printf("Failed to connect to etcd: %v", err) return nil, err } - w.etcdAPI = client.NewKeysAPI(w.etcdClient) + // TODO: Consider a way to check connectivity, e.g., by getting cluster status or a dummy key. + // For now, we assume successful connection if clientv3.New doesn't error. + + w := &EtcdWrap{ + cfg: cfg, + client: cli, + } return w, nil } -// GetVersion retrieves the current etcd server and cluster version. -func (w *EtcdWrap) GetVersion() (*version.Versions, error) { - return w.etcdClient.GetVersion(context.Background()) -} +// GetVersion has been removed as it requires using the Maintenance API client, +// which is a larger change than the current scope of refactoring core KV operations. +// Placeholder functionality might be re-added if simple status checks are needed. -// GetNCreate retrieves a set of Nodes from etcd, created if not present. -func (w *EtcdWrap) GetNCreate(key string, createValue int) (*client.Response, error) { - for { - r, err := w.etcdAPI.Get(context.Background(), key, nil) - if err != nil { - if client.IsKeyNotFound(err) { - r, err := w.etcdAPI.Set(context.Background(), key, strconv.Itoa(createValue), &client.SetOptions{PrevExist: "false"}) - if err != nil { - // recreate - continue - } - // create success - return r, nil - } - return nil, err +// GetNCreate retrieves a key, creating it with createValue if it does not exist. +// Returns the GetResponse and a boolean indicating if the key was created. +func (w *EtcdWrap) GetNCreate(key string, createValue int) (*clientv3.GetResponse, bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // Increased timeout for Txn + defer cancel() + + // Convert createValue to string + sCreateValue := strconv.Itoa(createValue) + + // Transaction to create if not exists + txn := w.client.KV.Txn(ctx) + // If key does not exist (its version is 0), then create it. + // Else, just get it. + resp, err := txn.If(clientv3.Compare(clientv3.Version(key), "=", 0)). + Then(clientv3.OpPut(key, sCreateValue)). + Else(clientv3.OpGet(key)). + Commit() + + if err != nil { + log.Printf("GetNCreate failed for key '%s': %v", key, err) + return nil, false, err + } + + if !resp.Succeeded { + // Key already existed, Else path (OpGet) was executed. + // The GetResponse is in resp.Responses[0].GetResponseRange(). + // Important: TxnResponse.Responses is a slice of ResponseOp_Response. + // We need to type assert to get the specific response type. + getResponse := resp.Responses[0].GetResponseRange() + if getResponse == nil { + return nil, false, errors.New("etcd GetNCreate: key existed but failed to retrieve in transaction") } - // get success - return r, nil + return (*clientv3.GetResponse)(getResponse), false, nil } + + // Key did not exist and was created (Then path - OpPut). + // We need to fetch the created key to return a GetResponse consistent with prior behavior. + // The PutResponse is in resp.Responses[0].GetResponsePut(). + // We could return this PutResponse's header, or do a Get. Let's do a Get for consistency. + getResp, err := w.Get(key) + if err != nil { + log.Printf("GetNCreate: key '%s' created, but failed to retrieve after creation: %v", key, err) + return nil, true, err + } + return getResp, true, nil } -// AtomAdd add value to the value atom of key. + +// AtomAdd atomically adds an integer value to the current integer value of a key. +// It retries if there's a conflict during the read-modify-write cycle. func (w *EtcdWrap) AtomAdd(key string, value int) (int, error) { for { - r, err := w.etcdAPI.Get(context.Background(), key, nil) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // Context for each attempt + + // Get current value and revision + getResp, err := w.client.KV.Get(ctx, key) if err != nil { + cancel() + log.Printf("AtomAdd: failed to get key '%s': %v", key, err) return 0, err } - v1, err := strconv.Atoi(r.Node.Value) - v2 := strconv.Itoa(v1 + value) - resp, err := w.etcdAPI.Set(context.Background(), key, v2, &client.SetOptions{PrevIndex: r.Node.ModifiedIndex}) + + currentValueStr := "0" // Default to 0 if key doesn't exist or has no value + currentRevision := int64(0) + + if len(getResp.Kvs) > 0 { + currentValueStr = string(getResp.Kvs[0].Value) + currentRevision = getResp.Kvs[0].ModRevision + } + + currentValueInt, err := strconv.Atoi(currentValueStr) + if err != nil { + cancel() + log.Printf("AtomAdd: value of key '%s' ('%s') is not an integer: %v", key, currentValueStr, err) + return 0, errors.New("current value is not an integer") + } + + newValueInt := currentValueInt + value + newValueStr := strconv.Itoa(newValueInt) + + // Start transaction + txn := w.client.KV.Txn(ctx) + var KVCmp clientv3.Cmp + if currentRevision == 0 { + // Key does not exist, try to create it (version is 0) + KVCmp = clientv3.Compare(clientv3.Version(key), "=", 0) + } else { + // Key exists, compare based on ModRevision + KVCmp = clientv3.Compare(clientv3.ModRevision(key), "=", currentRevision) + } + + txnResp, err := txn.If(KVCmp). + Then(clientv3.OpPut(key, newValueStr)). + Commit() + + cancel() // Release context resources for this attempt + if err != nil { - // modify conflict, again - continue + log.Printf("AtomAdd: transaction failed for key '%s': %v", key, err) + return 0, err // Or retry a few times for certain errors + } + + if txnResp.Succeeded { + // Transaction successful, value updated + return newValueInt, nil } - return strconv.Atoi(resp.Node.Value) + + // Transaction failed, likely due to a race condition (ModRevision changed). + // Loop will retry. + log.Printf("AtomAdd: conflict for key '%s', retrying...", key) + // Optional: add a small delay or backoff here if conflicts are frequent + time.Sleep(10 * time.Millisecond) } } -// Get retrieves a set of Nodes from etcd -func (w *EtcdWrap) Get(key string) (*client.Response, error) { - r, err := w.etcdAPI.Get(context.Background(), key, nil) +// Get retrieves a single key-value pair from etcd. +func (w *EtcdWrap) Get(key string) (*clientv3.GetResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // Example timeout + defer cancel() + + resp, err := w.client.KV.Get(ctx, key) if err != nil { + log.Printf("Failed to get key '%s' from etcd: %v", key, err) return nil, err } - return r, nil + return resp, nil +} + +// Set assigns a new value to a key. +func (w *EtcdWrap) Set(key string, value string) (*clientv3.PutResponse, error) { + return w.SetWithTTL(key, value, 0) // TTL 0 means no lease } -// Set assigns a new value to a Node identified by a given key. -func (w *EtcdWrap) Set(key string, value string, opts *client.SetOptions) (*client.Response, error) { - r, err := w.etcdAPI.Set(context.Background(), key, value, opts) - return r, err +// SetWithTTL assigns a new value to a key with a specified Time To Live (TTL) in seconds. +// If ttl is 0, the key is persisted without a TTL. +func (w *EtcdWrap) SetWithTTL(key string, value string, ttlSeconds int64) (*clientv3.PutResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // Increased timeout for potential lease grant + defer cancel() + + var opts []clientv3.OpOption + if ttlSeconds > 0 { + leaseResp, err := w.client.Grant(ctx, ttlSeconds) + if err != nil { + log.Printf("Failed to grant lease for TTL on key '%s': %v", key, err) + return nil, err + } + opts = append(opts, clientv3.WithLease(leaseResp.ID)) + } + + resp, err := w.client.KV.Put(ctx, key, value, opts...) + if err != nil { + log.Printf("Failed to set key '%s' with TTL %d: %v", key, ttlSeconds, err) + return nil, err + } + return resp, nil } // Delete removes a Node identified by the given key. -func (w *EtcdWrap) Delete(key string) (*client.Response, error) { - reps, err := w.etcdAPI.Delete(context.Background(), key, nil) +// For deleting a range of keys (prefix), use DeleteWithPrefix. +func (w *EtcdWrap) Delete(key string) (*clientv3.DeleteResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := w.client.KV.Delete(ctx, key) + if err != nil { + log.Printf("Failed to delete key '%s' from etcd: %v", key, err) + return nil, err + } + return resp, nil +} + +// DeleteWithPrefix removes all keys matching the given prefix. +func (w *EtcdWrap) DeleteWithPrefix(prefix string) (*clientv3.DeleteResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := w.client.KV.Delete(ctx, prefix, clientv3.WithPrefix()) if err != nil { + log.Printf("Failed to delete keys with prefix '%s' from etcd: %v", prefix, err) return nil, err } - return reps, nil + return resp, nil +} + +// IsKeyExist returns true if the error indicates that a key already exists. +// This is typically used with transactions that try to create a key. +// For clientv3, if a Txn fails due to a Compare (e.g., key version is not 0), +// the TxnResponse.Succeeded will be false. +func (w *EtcdWrap) IsKeyExist(txnResp *clientv3.TxnResponse, err error) bool { + if err != nil { + // Some gRPC errors might indicate this, but usually it's a failed transaction. + // e.g. status.Code(err) == codes.AlreadyExists, though this is less common for typical "create if not exist" + return false + } + // If a transaction failed (e.g. "if version == 0 then put" failed), + // it implies the condition wasn't met, meaning the key likely existed. + return txnResp != nil && !txnResp.Succeeded } -// IsKeyExist returns true if the error code is ErrorCodeNodeExist. -func (w *EtcdWrap) IsKeyExist(err error) bool { - if cErr, ok := err.(client.Error); ok { - return cErr.Code == client.ErrorCodeNodeExist +// CompareAndSwap atomically sets the value of a key if its current ModRevision matches expectedModRevision. +// If expectedModRevision is 0, it compares against version=0 (key does not exist). +func (w *EtcdWrap) CompareAndSwap(key string, expectedModRevision int64, newValue string) (*clientv3.TxnResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + txn := w.client.KV.Txn(ctx) + var cmp clientv3.Cmp + if expectedModRevision == 0 { // Expect key to not exist + cmp = clientv3.Compare(clientv3.Version(key), "=", 0) + } else { // Expect key to exist with specific revision + cmp = clientv3.Compare(clientv3.ModRevision(key), "=", expectedModRevision) } - return false + + txnResp, err := txn.If(cmp). + Then(clientv3.OpPut(key, newValue)). + Commit() + + if err != nil { + log.Printf("CompareAndSwap: transaction failed for key '%s': %v", key, err) + return nil, err + } + return txnResp, nil } -// IsKeyNotFound returns true if the error code is ErrorCodeKeyNotFound. -func (w *EtcdWrap) IsKeyNotFound(err error) bool { - return client.IsKeyNotFound(err) +// IsKeyNotFound checks if a GetResponse indicates a key was not found or if an error is codes.NotFound. +func (w *EtcdWrap) IsKeyNotFound(resp *clientv3.GetResponse, err error) bool { + if err != nil { + st, ok := status.FromError(err) + if ok && st.Code() == codes.NotFound { + return true + } + return false // Some other error occurred, not specifically "NotFound" + } + // If no error, a non-existent key means the GetResponse has no KVs. + return resp != nil && resp.Count == 0 } diff --git a/server/uuid_server.go b/server/uuid_server.go index a86f399..01b44d0 100644 --- a/server/uuid_server.go +++ b/server/uuid_server.go @@ -10,9 +10,10 @@ import ( "github.com/cnwinds/flake/api" - "github.com/coreos/etcd/client" + "errors" "golang.org/x/net/context" "google.golang.org/grpc" + clientv3 "go.etcd.io/etcd/client/v3" ) const ( @@ -56,6 +57,7 @@ type Config struct { // UUIDServer UUID server. type UUIDServer struct { + api.UnimplementedUUIDServer // For forward compatibility cfg *Config etcdWrap *EtcdWrap listen net.Listener @@ -90,29 +92,55 @@ func (s *UUIDServer) Fetch(ctx context.Context, in *api.FetchRequest) (*api.Fetc func (s *UUIDServer) getServieID(serviceName string) (id int, err error) { key := s.cfg.Prefix + "/" + KeyOfServiceDir + "/" + serviceName - serviceID := 0 + + // Try to get the existing service ID + resp, err := s.etcdWrap.Get(key) + if err != nil && !s.etcdWrap.IsKeyNotFound(resp, err) { // Pass resp to IsKeyNotFound + log.Printf("getServieID: failed to get key '%s': %v", key, err) + return 0, err + } + + if err == nil && resp != nil && len(resp.Kvs) > 0 { + // Key exists + return strconv.Atoi(string(resp.Kvs[0].Value)) + } + + // Key does not exist, try to create it by reserving a new service ID for { - r, err := s.etcdWrap.Get(key) + newServiceID, err := s.nextServiceID() if err != nil { - if s.etcdWrap.IsKeyNotFound(err) { - if serviceID == 0 { - serviceID, err = s.nextServiceID() - if err != nil { - return 0, err - } - } - resp, err := s.etcdWrap.Set(key, strconv.Itoa(serviceID), &client.SetOptions{PrevExist: "false"}) - if err != nil { - // create conflict, again - continue - } - // create success - return strconv.Atoi(resp.Node.Value) + return 0, err + } + + // Attempt to create the key with the newServiceID if it still doesn't exist + // GetNCreate returns the GetResponse and a boolean 'created' + // If 'created' is true, newServiceID was successfully written. + // If 'created' is false, another instance created it; the GetResponse contains the actual value. + getResp, created, err := s.etcdWrap.GetNCreate(key, newServiceID) + if err != nil { + // Potentially retry or handle error + log.Printf("getServieID: GetNCreate for key '%s' failed: %v. Retrying...", key, err) + time.Sleep(100 * time.Millisecond) // Avoid tight loop on persistent errors + continue + } + + if created { + return newServiceID, nil + } + + // Not created by this instance, means another instance created it. + // The getResp from GetNCreate contains the value set by the other instance (or an even earlier one). + if getResp != nil && len(getResp.Kvs) > 0 { + id, err = strconv.Atoi(string(getResp.Kvs[0].Value)) + if err != nil { + log.Printf("getServieID: failed to parse existing ID for key '%s': %v", key, err) + return 0, err } - return 0, nil + return id, nil } - // get success - return strconv.Atoi(r.Node.Value) + // This case should ideally not be reached if GetNCreate is implemented correctly + log.Printf("getServieID: GetNCreate for key '%s' reported not created but returned no value. Retrying...", key) + time.Sleep(100 * time.Millisecond) } } @@ -127,27 +155,47 @@ func (s *UUIDServer) nextServiceID() (id int, err error) { func (s *UUIDServer) getContainerID(containerName string) (id int, err error) { key := s.cfg.Prefix + "/" + KeyOfContainerDir + "/" + containerName - containerID := 0 + + // Try to get the existing container ID + resp, err := s.etcdWrap.Get(key) + if err != nil && !s.etcdWrap.IsKeyNotFound(resp, err) { // Pass resp to IsKeyNotFound + log.Printf("getContainerID: failed to get key '%s': %v", key, err) + return 0, err + } + + if err == nil && resp != nil && len(resp.Kvs) > 0 { + // Key exists + return strconv.Atoi(string(resp.Kvs[0].Value)) + } + + // Key does not exist, try to create it for { - r, err := s.etcdWrap.Get(key) + newContainerID, err := s.nextContainerID() if err != nil { - if s.etcdWrap.IsKeyNotFound(err) { - if containerID == 0 { - containerID, err = s.nextContainerID() - if err != nil { - return 0, err - } - } - resp, err := s.etcdWrap.Set(key, strconv.Itoa(containerID), &client.SetOptions{PrevExist: "false"}) - if err != nil { - // create conflict, again - continue - } - return strconv.Atoi(resp.Node.Value) - } return 0, err } - return strconv.Atoi(r.Node.Value) + + getResp, created, err := s.etcdWrap.GetNCreate(key, newContainerID) + if err != nil { + log.Printf("getContainerID: GetNCreate for key '%s' failed: %v. Retrying...", key, err) + time.Sleep(100 * time.Millisecond) + continue + } + + if created { + return newContainerID, nil + } + + if getResp != nil && len(getResp.Kvs) > 0 { + id, err = strconv.Atoi(string(getResp.Kvs[0].Value)) + if err != nil { + log.Printf("getContainerID: failed to parse existing ID for key '%s': %v", key, err) + return 0, err + } + return id, nil + } + log.Printf("getContainerID: GetNCreate for key '%s' reported not created but returned no value. Retrying...", key) + time.Sleep(100 * time.Millisecond) } } @@ -163,21 +211,60 @@ func (s *UUIDServer) nextContainerID() (id int, err error) { // ReassignContainerID reassign an ID to the container. func (s *UUIDServer) ReassignContainerID(containerName string) error { key := s.cfg.Prefix + "/" + KeyOfContainerDir + "/" + containerName - containerID, err := s.nextContainerID() - if err != nil { - return err + containerID, errOuter := s.nextContainerID() + if errOuter != nil { + return errOuter } - for { - r, err := s.etcdWrap.Get(key) - if err != nil { - return err + + for { // Retry loop for CAS + var casResp *clientv3.TxnResponse + var casErr error + + getResp, getErr := s.etcdWrap.Get(key) + if getErr != nil { + if s.etcdWrap.IsKeyNotFound(getResp, getErr) { + // Key not found, try to create it. This is a "reassign" so it implies it should exist. + // However, if it was deleted, we might want to create it. + // For now, let's stick to the original intent of reassigning an *existing* container's ID + // or creating if it's truly a new container name not seen before. + // The Set below will create if not exist. + log.Printf("ReassignContainerID: key '%s' not found during Get, attempting to create.", key) + _, setErr := s.etcdWrap.Set(key, strconv.Itoa(containerID)) + if setErr != nil { + log.Printf("ReassignContainerID: failed to set new container ID for key '%s' after not found: %v", key, setErr) + return setErr + } + return nil + } + log.Printf("ReassignContainerID: failed to get key '%s' for CAS: %v", key, getErr) + return getErr } - _, err = s.etcdWrap.Set(key, strconv.Itoa(containerID), &client.SetOptions{PrevIndex: r.Node.ModifiedIndex}) - if err != nil { - // modify conflict, again - continue + + if len(getResp.Kvs) == 0 { + // Key does not exist (empty GetResponse), treat as not found. + log.Printf("ReassignContainerID: key '%s' has no value, attempting to create.", key) + _, setErr := s.etcdWrap.Set(key, strconv.Itoa(containerID)) + if setErr != nil { + log.Printf("ReassignContainerID: failed to set new container ID for non-existent key '%s': %v", key, setErr) + return setErr + } + return nil + } + + currentModRevision := getResp.Kvs[0].ModRevision + + casResp, casErr = s.etcdWrap.CompareAndSwap(key, currentModRevision, strconv.Itoa(containerID)) + if casErr != nil { + log.Printf("ReassignContainerID: CompareAndSwap failed for key '%s': %v", key, casErr) + return casErr + } + + if !casResp.Succeeded { + log.Printf("ReassignContainerID: conflict for key '%s', ModRevision changed. Retrying...", key) + time.Sleep(50 * time.Millisecond) + continue } - return nil + return nil } } @@ -199,73 +286,146 @@ func (s *UUIDServer) getUUIDSegment(serviceName string, containerName string, ne key := fmt.Sprintf("%s/%d:%d", s.cfg.Prefix, serviceID, containerID) for { - resp, err := s.etcdWrap.Get(key) - if err != nil { - if s.etcdWrap.IsKeyNotFound(err) { - startID = 1 - endID = startID + needCount - if endID > MaxOfSequence { - err := s.ReassignContainerID(containerName) - if err != nil { - return 0, 0, 0, 0, err - } - endID = MaxOfSequence - } - resp, err = s.etcdWrap.Set(key, strconv.Itoa(endID), &client.SetOptions{PrevExist: "false"}) - if err != nil && endID != MaxOfSequence { - // create conflict, again - continue - } - // create success - return serviceID, containerID, startID, endID - 1, nil - } - return 0, 0, 0, 0, err - } + // This part of the original logic for getUUIDSegment needs a major overhaul. + // The old approach of Get -> Set is prone to race conditions. + // A better approach is to use AtomAdd to reserve a block of IDs. + // Let's assume the key stores the *next available start ID*. + + // Attempt to atomically add 'needCount' to the current sequence start ID + // The AtomAdd function in etcdWrap handles the read-modify-write loop. + // It needs to be initialized first if it doesn't exist. - startID, err := strconv.Atoi(resp.Node.Value) + // Initialize the sequence key if it does not exist + initResp, created, err := s.etcdWrap.GetNCreate(key, StartOfSequence) if err != nil { - return 0, 0, 0, 0, err + log.Printf("getUUIDSegment: failed to initialize sequence key '%s': %v", key, err) + return 0,0,0,0, err } - - if startID == MaxOfSequence { - // deadlock prevention - err := s.ReassignContainerID(containerName) + + var currentSeqStartID int + if created { + currentSeqStartID = StartOfSequence + log.Printf("getUUIDSegment: initialized sequence key '%s' to %d", key, currentSeqStartID) + } else { + if initResp == nil || len(initResp.Kvs) == 0 { + log.Printf("getUUIDSegment: GetNCreate for key '%s' didn't create but returned no value", key) + return 0,0,0,0, errors.New("failed to get or create sequence start ID") + } + currentSeqStartID, err = strconv.Atoi(string(initResp.Kvs[0].Value)) if err != nil { - return 0, 0, 0, 0, err + log.Printf("getUUIDSegment: failed to parse current sequence start ID from '%s': %v", string(initResp.Kvs[0].Value), err) + return 0,0,0,0, err } - // container id reassigned, relaunch function - return s.getUUIDSegment(serviceName, containerName, needCount) } + + // Now, atomically increment the sequence start ID. + // This is a bit tricky because AtomAdd adds a value, but we want to get the *previous* value + // and then add needCount to it for the *next* transaction. + // A simpler model: AtomAdd returns the NEW value. + // So, if AtomAdd(key, needCount) returns X, the range is [X-needCount, X-1] + // Let's adjust AtomAdd or use a different strategy. + + // Simpler strategy for now: Read current, try to update with CAS. + // This loop is for CAS on the sequence allocation. + var casResp *clientv3.TxnResponse + var casErr error + + for { // Inner CAS loop for sequence update + getResp, getErr := s.etcdWrap.Get(key) + if getErr != nil { + log.Printf("getUUIDSegment: failed to get sequence key '%s' in CAS loop: %v", key, getErr) + return 0,0,0,0, getErr + } + // Pass getErr to IsKeyNotFound + if s.etcdWrap.IsKeyNotFound(getResp, getErr) || (getResp != nil && len(getResp.Kvs) == 0) { + log.Printf("getUUIDSegment: sequence key '%s' disappeared or no KVs, re-initializing.", key) + _, _, initErr := s.etcdWrap.GetNCreate(key, StartOfSequence) + if initErr != nil { + log.Printf("getUUIDSegment: failed to re-initialize key '%s': %v", key, initErr) + return 0,0,0,0, initErr + } + continue // Retry the CAS Get + } - endID = startID + needCount - if endID > MaxOfSequence { - err := s.ReassignContainerID(containerName) - if err != nil { - return 0, 0, 0, 0, err + parseErr := error(nil) // Declare parseErr for this scope + startID, parseErr = strconv.Atoi(string(getResp.Kvs[0].Value)) + if parseErr != nil { + log.Printf("getUUIDSegment: failed to parse startID from '%s': %v", string(getResp.Kvs[0].Value), parseErr) + return 0,0,0,0, parseErr } - endID = MaxOfSequence - } - resp, err = s.etcdWrap.Set(key, strconv.Itoa(endID), &client.SetOptions{PrevIndex: resp.Node.ModifiedIndex}) - if err != nil { - // modify conflict, again - continue - } - // modify success - return serviceID, containerID, startID, endID - 1, nil - } + + currentModRevision := getResp.Kvs[0].ModRevision + + if startID >= MaxOfSequence { + log.Printf("getUUIDSegment: sequence for %s:%d hit MaxOfSequence (%d). Reassigning container ID.", serviceName, containerID, MaxOfSequence) + reassignErr := s.ReassignContainerID(containerName) + if reassignErr != nil { + return 0, 0, 0, 0, reassignErr + } + log.Printf("getUUIDSegment: Container ID for '%s' reassigned. Retrying segment acquisition.", containerName) + return s.getUUIDSegment(serviceName, containerName, needCount) + } + + endID = startID + needCount - 1 + nextStartIDForEtcd := startID + needCount + + if endID >= MaxOfSequence { + log.Printf("getUUIDSegment: requested count for %s:%d (%d) exceeds MaxOfSequence from startID %d. Adjusting.", serviceName, containerID, needCount, startID) + endID = MaxOfSequence - 1 + nextStartIDForEtcd = MaxOfSequence + if startID > endID { + log.Printf("getUUIDSegment: No IDs left for %s:%d before MaxOfSequence. Reassigning.", serviceName, containerID) + reassignErr := s.ReassignContainerID(containerName) + if reassignErr != nil { return 0, 0, 0, 0, reassignErr } + return s.getUUIDSegment(serviceName, containerName, needCount) + } + } + + casResp, casErr = s.etcdWrap.CompareAndSwap(key, currentModRevision, strconv.Itoa(nextStartIDForEtcd)) + if casErr != nil { + log.Printf("getUUIDSegment: CompareAndSwap for key '%s' failed: %v", key, casErr) + return 0, 0, 0, 0, casErr + } + + if casResp.Succeeded { + return serviceID, containerID, startID, endID, nil + } + + log.Printf("getUUIDSegment: CAS conflict for key '%s'. Retrying...", key) + time.Sleep(50 * time.Millisecond) + } // End of CAS retry loop + } // End of main for loop (this was the original outer loop, now only for init) } + func (s *UUIDServer) initUUIDData() (success bool, err error) { - serviceResp, err := s.etcdWrap.GetNCreate(s.cfg.Prefix+"/"+KeyOfMaxServiceID, StartOfServerID) + serviceResp, _, err := s.etcdWrap.GetNCreate(s.cfg.Prefix+"/"+KeyOfMaxServiceID, StartOfServerID) if err != nil { return false, err } - containerResp, err := s.etcdWrap.GetNCreate(s.cfg.Prefix+"/"+KeyOfMaxContainerID, StartOfContainerID) + containerResp, _, err := s.etcdWrap.GetNCreate(s.cfg.Prefix+"/"+KeyOfMaxContainerID, StartOfContainerID) if err != nil { return false, err } - log.Printf("flake max_serviceid:%v, max_containerid:%v", serviceResp.Node.Value, containerResp.Node.Value) + var serviceIDVal, containerIDVal string + if serviceResp != nil && len(serviceResp.Kvs) > 0 { + serviceIDVal = string(serviceResp.Kvs[0].Value) + } else { + // This case implies GetNCreate failed to return the value even if it existed or was just created. + // Fallback or error, GetNCreate should ensure value is present in GetResponse if err is nil. + log.Printf("initUUIDData: MaxServiceID key ('%s') not found or value empty after GetNCreate.", s.cfg.Prefix+"/"+KeyOfMaxServiceID) + serviceIDVal = "unknown (init error)" + } + + if containerResp != nil && len(containerResp.Kvs) > 0 { + containerIDVal = string(containerResp.Kvs[0].Value) + } else { + log.Printf("initUUIDData: MaxContainerID key ('%s') not found or value empty after GetNCreate.", s.cfg.Prefix+"/"+KeyOfMaxContainerID) + containerIDVal = "unknown (init error)" + } + + log.Printf("flake max_serviceid:%s, max_containerid:%s", serviceIDVal, containerIDVal) return true, nil } @@ -289,14 +449,11 @@ func StartServer(cfg *Config) (*UUIDServer, error) { return nil, err } - ver, err := svr.etcdWrap.GetVersion() - if err != nil { - return nil, err - } - log.Printf("etcd version: %v", ver) + // svr.etcdWrap.GetVersion() was removed. NewEtcdWrap now handles initial connection check/logging. + log.Printf("EtcdWrap initialized for UUIDServer.") // init uuid server - svr.initUUIDData() + _, err = svr.initUUIDData() // initUUIDData now returns (bool, error) if err != nil { return nil, err } From 868731776d13727cacfd66e5a4d14f70f7f790c8 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 01:41:53 +0000 Subject: [PATCH 2/2] I've updated the `README.md` file to reflect recent dependency and build changes. The `README.md` now includes: - The new Go version requirement (1.23.0+). - A note about the tools required for regenerating Protocol Buffer code (`protoc`, `protoc-gen-go`, `protoc-gen-go-grpc`) and a reference to `api/compile.bat`. - Information that key dependencies (etcd, gRPC, Protocol Buffers) have been updated, signaling active maintenance. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a0700d..d8d52e4 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ flake是一个分布式ID生成算法的golang实现。他基于snowflake算法 flake使用golang编写。由分配UUID段的服务端和客户端库组成。服务端使用docker容器部署运行。 +**项目维护更新**: 项目的关键依赖(如 etcd, gRPC, Protocol Buffers)已更新至较新版本,以确保项目能够受益于最新的功能和安全更新。 + # Getting started 下面开始构建一个测试运行环境。在正式开始之前需要: @@ -21,7 +23,7 @@ flake使用golang编写。由分配UUID段的服务端和客户端库组成。 ``` > go version -go version go1.13.8 windows/amd64 +go version go1.23.0 linux/amd64 (或更新版本) ``` ``` @@ -43,6 +45,8 @@ go mod tidy go mod vendor ``` +本项目使用 gRPC 和 Protocol Buffers。如果您修改了 `api/uuid.proto` 文件,则需要使用 `protoc` 编译器以及 `protoc-gen-go` 和 `protoc-gen-go-grpc` 插件来重新生成 Go 代码。具体的生成命令可以参考 `api/compile.bat` 文件。 + 3. 构建服务端镜像。 ```bash docker build -t flake:v1 .