diff --git a/cmd/protoc-gen-go-gins/gins.go b/cmd/protoc-gen-go-gins/gins.go index 54ae56a..33f0b00 100644 --- a/cmd/protoc-gen-go-gins/gins.go +++ b/cmd/protoc-gen-go-gins/gins.go @@ -16,11 +16,11 @@ import ( ) const ( - contextPackage = protogen.GoImportPath("context") - ginPackage = protogen.GoImportPath("github.com/gin-gonic/gin") - ginsPackage = protogen.GoImportPath("github.com/origadmin/toolkits/runtime/kratos/transport/gins") - transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http") - bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding") + contextPackage = protogen.GoImportPath("context") + ginPackage = protogen.GoImportPath("github.com/gin-gonic/gin") + ginsPackage = protogen.GoImportPath("github.com/origadmin/toolkits/runtime/transport/gins") + bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding") + //transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http") ) var methodSets = make(map[string]int) diff --git a/dorm/transaction.go b/dorm/transaction.go index ff8a58f..eb6266e 100644 --- a/dorm/transaction.go +++ b/dorm/transaction.go @@ -5,12 +5,12 @@ import ( ) // ExecFunc is a function that can be executed within a transaction -type ExecFunc func(context.Context) error +type ExecFunc = func(context.Context) error // Trans is a transaction wrapper type Trans interface { - Tx(ctx context.Context, fn func(tx Tx) error) error - TxExec(ctx context.Context, fn ExecFunc) error + Tx(ctx context.Context, fn func(context.Context) error) error + InTx(ctx context.Context, fn func(tx Tx) error) error } type Tx interface { diff --git a/errors/string.go b/errors/string.go index 99a61eb..861710a 100644 --- a/errors/string.go +++ b/errors/string.go @@ -35,6 +35,13 @@ func (obj String) Is(err error) bool { } // ErrString creates a new error from a string +// +// Deprecated: use errors.NewString instead func ErrString(err string) String { return String(err) } + +// NewString creates a new error from a string +func NewString(message string) String { + return String(message) +} diff --git a/examples/buf.lock b/examples/buf.lock index 077deea..b2af281 100644 --- a/examples/buf.lock +++ b/examples/buf.lock @@ -1,6 +1,12 @@ # Generated by buf. DO NOT EDIT. version: v2 deps: + - name: buf.build/bufbuild/protovalidate + commit: 5a7b106cbb87462d9a8c9ffecdbd2e38 + digest: b5:0f2dc6c9453e9cc9e9f36807aaa5f94022e837d91fef4dcaeed79a35c0843cc64eba28ff077aab24da3b2cb12639ad256246f9f9a36c033b99d5754b19996b7e - name: buf.build/googleapis/googleapis - commit: f52d4f76a8434cc5966798b1d3b4f110 - digest: b5:5e634ff0ee118aea188b3e9c13ad7d285a192ef6c591bc20ff5a3360438d6ca310cfe9d663b20d60e1daa21789add35b919eac84e8e94a4d576e83a50dd2d62c + commit: 553fd4b4b3a640be9b69a3fa0c17b383 + digest: b5:9e7cb39758f3487f0751765227dc0b9f0ef7a401ab37fa2e97c363446810f4bd0dca1f46dbb793a12d98c019f4028e48d0831b5cb3f09190f068ec1866c69c1d + - name: buf.build/origadmin/runtime + commit: 157d05fd7b25402aa7aa58ed28f7a3b6 + digest: b5:333b207fe1af60e28ba0db9aac8526638fcec6baab132dd9e3ce1603078836f245946d544dca965cb839864172024db3dbfa4d013d0b10e26361df36a2e2803f diff --git a/examples/buf.yaml b/examples/buf.yaml index 471dfd9..87db757 100644 --- a/examples/buf.yaml +++ b/examples/buf.yaml @@ -13,4 +13,5 @@ breaking: - FILE deps: - buf.build/googleapis/googleapis + - buf.build/origadmin/runtime # - buf.build/envoyproxy/protoc-gen-validate diff --git a/examples/proto/helloworld/v1/helloworld.proto b/examples/proto/helloworld/v1/helloworld.proto index 4af3213..b61a067 100644 --- a/examples/proto/helloworld/v1/helloworld.proto +++ b/examples/proto/helloworld/v1/helloworld.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package helloworld.v1; +import "config/v1/cors.proto"; import "google/api/annotations.proto"; option go_package = "github.com/origadmin/toolkits/examples/services/helloworld/v1;helloworld"; @@ -29,3 +30,7 @@ message SayHelloRequest { message SayHelloResponse { string message = 1; } + +message ExampleCors { + config.v1.CorsConfig cors = 1; +} \ No newline at end of file diff --git a/examples/services/helloworld/v1/helloworld.pb.go b/examples/services/helloworld/v1/helloworld.pb.go index 907c5cf..73fccd3 100644 --- a/examples/services/helloworld/v1/helloworld.pb.go +++ b/examples/services/helloworld/v1/helloworld.pb.go @@ -7,6 +7,7 @@ package helloworld import ( + config "github.com/origadmin/toolkits/runtime/config" _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -113,20 +114,70 @@ func (x *SayHelloResponse) GetMessage() string { return "" } +type ExampleCors struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cors *config.CorsConfig `protobuf:"bytes,1,opt,name=cors,proto3" json:"cors,omitempty"` +} + +func (x *ExampleCors) Reset() { + *x = ExampleCors{} + mi := &file_helloworld_v1_helloworld_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExampleCors) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExampleCors) ProtoMessage() {} + +func (x *ExampleCors) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_v1_helloworld_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 ExampleCors.ProtoReflect.Descriptor instead. +func (*ExampleCors) Descriptor() ([]byte, []int) { + return file_helloworld_v1_helloworld_proto_rawDescGZIP(), []int{2} +} + +func (x *ExampleCors) GetCors() *config.CorsConfig { + if x != nil { + return x.Cors + } + return nil +} + var File_helloworld_v1_helloworld_proto protoreflect.FileDescriptor var file_helloworld_v1_helloworld_proto_rawDesc = []byte{ 0x0a, 0x1e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x1a, - 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x25, 0x0a, - 0x0f, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x10, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x32, 0x8a, 0x01, 0x0a, 0x0e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x53, 0x65, + 0x14, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x72, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x25, 0x0a, 0x0f, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x10, 0x53, 0x61, + 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x38, 0x0a, 0x0b, 0x45, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x72, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x04, 0x63, 0x6f, + 0x72, 0x73, 0x32, 0x8a, 0x01, 0x0a, 0x0e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x78, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, @@ -162,19 +213,22 @@ func file_helloworld_v1_helloworld_proto_rawDescGZIP() []byte { return file_helloworld_v1_helloworld_proto_rawDescData } -var file_helloworld_v1_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_v1_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_helloworld_v1_helloworld_proto_goTypes = []any{ - (*SayHelloRequest)(nil), // 0: helloworld.v1.SayHelloRequest - (*SayHelloResponse)(nil), // 1: helloworld.v1.SayHelloResponse + (*SayHelloRequest)(nil), // 0: helloworld.v1.SayHelloRequest + (*SayHelloResponse)(nil), // 1: helloworld.v1.SayHelloResponse + (*ExampleCors)(nil), // 2: helloworld.v1.ExampleCors + (*config.CorsConfig)(nil), // 3: config.v1.CorsConfig } var file_helloworld_v1_helloworld_proto_depIdxs = []int32{ - 0, // 0: helloworld.v1.GreeterService.SayHello:input_type -> helloworld.v1.SayHelloRequest - 1, // 1: helloworld.v1.GreeterService.SayHello:output_type -> helloworld.v1.SayHelloResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 3, // 0: helloworld.v1.ExampleCors.cors:type_name -> config.v1.CorsConfig + 0, // 1: helloworld.v1.GreeterService.SayHello:input_type -> helloworld.v1.SayHelloRequest + 1, // 2: helloworld.v1.GreeterService.SayHello:output_type -> helloworld.v1.SayHelloResponse + 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_helloworld_v1_helloworld_proto_init() } @@ -188,7 +242,7 @@ func file_helloworld_v1_helloworld_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_helloworld_v1_helloworld_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 3, NumExtensions: 0, NumServices: 1, }, diff --git a/examples/services/helloworld/v1/helloworld.pb.validate.go b/examples/services/helloworld/v1/helloworld.pb.validate.go index 6b52a49..95c94c6 100644 --- a/examples/services/helloworld/v1/helloworld.pb.validate.go +++ b/examples/services/helloworld/v1/helloworld.pb.validate.go @@ -238,3 +238,131 @@ var _ interface { Cause() error ErrorName() string } = SayHelloResponseValidationError{} + +// Validate checks the field values on ExampleCors with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ExampleCors) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ExampleCors with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ExampleCorsMultiError, or +// nil if none found. +func (m *ExampleCors) ValidateAll() error { + return m.validate(true) +} + +func (m *ExampleCors) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetCors()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ExampleCorsValidationError{ + field: "Cors", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ExampleCorsValidationError{ + field: "Cors", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetCors()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ExampleCorsValidationError{ + field: "Cors", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return ExampleCorsMultiError(errors) + } + + return nil +} + +// ExampleCorsMultiError is an error wrapping multiple validation errors +// returned by ExampleCors.ValidateAll() if the designated constraints aren't met. +type ExampleCorsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ExampleCorsMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ExampleCorsMultiError) AllErrors() []error { return m } + +// ExampleCorsValidationError is the validation error returned by +// ExampleCors.Validate if the designated constraints aren't met. +type ExampleCorsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ExampleCorsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ExampleCorsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ExampleCorsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ExampleCorsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ExampleCorsValidationError) ErrorName() string { return "ExampleCorsValidationError" } + +// Error satisfies the builtin error interface +func (e ExampleCorsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sExampleCors.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ExampleCorsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ExampleCorsValidationError{} diff --git a/examples/services/helloworld/v1/helloworld_gins.pb.go b/examples/services/helloworld/v1/helloworld_gins.pb.go index 6c80603..afa7e12 100644 --- a/examples/services/helloworld/v1/helloworld_gins.pb.go +++ b/examples/services/helloworld/v1/helloworld_gins.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-gins. DO NOT EDIT. // versions: -// - protoc-gen-go-gins v1.0.0 +// - protoc-gen-go-gins 0.0.84 // - protoc (unknown) // source: helloworld/v1/helloworld.proto @@ -10,7 +10,7 @@ import ( context "context" gin "github.com/gin-gonic/gin" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - gins "github.com/origadmin/toolkits/runtime/kratos/transport/gins" + gins "github.com/origadmin/toolkits/runtime/transport/gins" ) // This is a compile-time assertion to ensure that this generated file @@ -23,17 +23,17 @@ const _ = gins.SupportPackageIsVersion1 const GreeterService_SayHello_OperationName = "/helloworld.v1.GreeterService/SayHello" -type GreeterServiceGINServer interface { +type GreeterServiceGINSServer interface { // SayHello Sends a greeting SayHello(context.Context, *SayHelloRequest) (*SayHelloResponse, error) } -func RegisterGreeterServiceGINServer(router gin.IRouter, srv GreeterServiceGINServer) { +func RegisterGreeterServiceGINSServer(router gin.IRouter, srv GreeterServiceGINSServer) { router.POST("/say_hello", _GreeterService_SayHello0_GIN_Handler(srv)) router.GET("/helloworld/:name", _GreeterService_SayHello1_GIN_Handler(srv)) } -func _GreeterService_SayHello0_GIN_Handler(srv GreeterServiceGINServer) func(ctx *gin.Context) { +func _GreeterService_SayHello0_GIN_Handler(srv GreeterServiceGINSServer) func(ctx *gin.Context) { return func(ctx *gin.Context) { var in SayHelloRequest if err := gins.BindBody(ctx, &in); err != nil { @@ -56,7 +56,7 @@ func _GreeterService_SayHello0_GIN_Handler(srv GreeterServiceGINServer) func(ctx } } -func _GreeterService_SayHello1_GIN_Handler(srv GreeterServiceGINServer) func(ctx *gin.Context) { +func _GreeterService_SayHello1_GIN_Handler(srv GreeterServiceGINSServer) func(ctx *gin.Context) { return func(ctx *gin.Context) { var in SayHelloRequest if err := gins.BindQuery(ctx, &in); err != nil { @@ -79,19 +79,19 @@ func _GreeterService_SayHello1_GIN_Handler(srv GreeterServiceGINServer) func(ctx } } -type GreeterServiceGINClient interface { +type GreeterServiceGINSClient interface { SayHello(ctx context.Context, req *SayHelloRequest, opts ...gins.CallOption) (rsp *SayHelloResponse, err error) } -type GreeterServiceGINClientImpl struct { +type GreeterServiceGINSClientImpl struct { cc *gins.Client } -func NewGreeterServiceGINClient(client *gins.Client) GreeterServiceGINClient { - return &GreeterServiceGINClientImpl{client} +func NewGreeterServiceGINSClient(client *gins.Client) GreeterServiceGINSClient { + return &GreeterServiceGINSClientImpl{client} } -func (c *GreeterServiceGINClientImpl) SayHello(ctx context.Context, in *SayHelloRequest, opts ...gins.CallOption) (*SayHelloResponse, error) { +func (c *GreeterServiceGINSClientImpl) SayHello(ctx context.Context, in *SayHelloRequest, opts ...gins.CallOption) (*SayHelloResponse, error) { var out SayHelloResponse pattern := "/helloworld/{name}" path := binding.EncodeURL(pattern, in, true) diff --git a/runtime/bootstrap/bootstrap.go b/runtime/bootstrap/bootstrap.go index c85ce7c..b49466c 100644 --- a/runtime/bootstrap/bootstrap.go +++ b/runtime/bootstrap/bootstrap.go @@ -1,26 +1,105 @@ package bootstrap +import ( + "path/filepath" + "time" +) + +// Constants for default paths and environment +const ( + DefaultConfigPath = "configs/config.toml" + DefaultEnv = "dev" + DefaultWorkDir = "." +) + +// Bootstrap struct to hold bootstrap information type Bootstrap struct { + Flags Flags WorkDir string ConfigPath string Env string Daemon bool } -func DefaultBootstrap() Bootstrap { - return Bootstrap{ - WorkDir: ".", - ConfigPath: "configs/config.toml", - Env: "dev", +// SetFlags sets the flags for the bootstrap +func (b *Bootstrap) SetFlags(name, version string) { + b.Flags.Version = version + b.Flags.ServiceName = name +} + +// ServiceID returns the service ID +func (b *Bootstrap) ServiceID() string { + return b.Flags.ServiceID() +} + +// ID returns the ID +func (b *Bootstrap) ID() string { + return b.Flags.ID +} + +// Version returns the version +func (b *Bootstrap) Version() string { + return b.Flags.Version +} + +// ServiceName returns the service name +func (b *Bootstrap) ServiceName() string { + return b.Flags.ServiceName +} + +// StartTime returns the start time +func (b *Bootstrap) StartTime() time.Time { + return b.Flags.StartTime +} + +// Metadata returns the metadata +func (b *Bootstrap) Metadata() map[string]string { + return b.Flags.Metadata +} + +// WorkPath returns the work path +func (b *Bootstrap) WorkPath() string { + // set workdir to current directory if not set + if b.WorkDir == "" { + b.WorkDir = DefaultWorkDir + } + // if the workdir is not absolute path, make it absolute + b.WorkDir, _ = filepath.Abs(b.WorkDir) + + // return the workdir, if the config path is empty + if b.ConfigPath == "" { + return b.WorkDir + } + + // if the config path is absolute path, return it + if filepath.IsAbs(b.ConfigPath) { + return b.ConfigPath + } + + // point the path to the `workdir path/config path`, and make it absolute + path := filepath.Join(b.WorkDir, b.ConfigPath) + path, _ = filepath.Abs(path) + return path +} + +// DefaultBootstrap returns a default bootstrap +func DefaultBootstrap() *Bootstrap { + return &Bootstrap{ + WorkDir: DefaultWorkDir, + ConfigPath: DefaultConfigPath, + Env: DefaultEnv, Daemon: false, + Flags: DefaultFlags(), } } -func NewBootstrap(dir, path string) Bootstrap { - return Bootstrap{ +// New returns a new bootstrap +func New(dir, path string) *Bootstrap { + return &Bootstrap{ WorkDir: dir, ConfigPath: path, - Env: "dev", + Env: DefaultEnv, Daemon: false, + Flags: DefaultFlags(), } } diff --git a/runtime/bootstrap/flags.go b/runtime/bootstrap/flags.go index 66d9509..97fa38b 100644 --- a/runtime/bootstrap/flags.go +++ b/runtime/bootstrap/flags.go @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2024 OrigAdmin. All rights reserved. + */ + package bootstrap import ( @@ -5,6 +9,7 @@ import ( "time" ) +// Flags is a struct that holds the flags for the service type Flags struct { ID string Version string @@ -13,10 +18,12 @@ type Flags struct { Metadata map[string]string } +// ServiceID returns the ID of the service func (f Flags) ServiceID() string { return f.ID + "." + f.ServiceName } +// DefaultFlags returns the default flags for the service func DefaultFlags() Flags { id, _ := os.Hostname() return Flags{ @@ -25,6 +32,7 @@ func DefaultFlags() Flags { } } +// NewFlags returns a new set of flags for the service func NewFlags(name string, version string) Flags { f := DefaultFlags() f.Version = version diff --git a/runtime/bootstrap/load.go b/runtime/bootstrap/load.go index a03b71a..f7f010c 100644 --- a/runtime/bootstrap/load.go +++ b/runtime/bootstrap/load.go @@ -1,18 +1,86 @@ package bootstrap import ( + "os" + "path/filepath" + "github.com/origadmin/toolkits/codec" "github.com/origadmin/toolkits/errors" "github.com/origadmin/toolkits/runtime/config" ) -func LoadSourceConfig(boot *Bootstrap) (*config.SourceConfig, error) { +// loadSource loads the config file from the given path +func loadSource(si os.FileInfo, path string) (*config.SourceConfig, error) { + // Check if the file or directory exists + if si == nil { + return nil, errors.New("load config file target is not exist") + } + // Check if the path is a directory + if si.IsDir() { + return loadSourceDir(path) + } + // Get the file type from the extension + typo := codec.TypeFromExt(filepath.Ext(path)) + // Check if the file type is unknown + if typo == codec.UNKNOWN { + return nil, errors.New("unknown file type: " + path) + } + // Load the config file + return loadSourceFile(path) +} + +// loadSourceFile loads the config file from the given path +func loadSourceFile(path string) (*config.SourceConfig, error) { var cfg config.SourceConfig - err := codec.DecodeFromFile(boot.ConfigPath, &cfg) - if err != nil { - return nil, errors.Wrap(err, "LoadConfig") + // Decode the file into the config struct + if err := codec.DecodeFromFile(path, &cfg); err != nil { + return nil, errors.Wrapf(err, "failed to parse config file %s", path) } + return &cfg, nil +} +// loadSourceDir loads the config file from the given directory +func loadSourceDir(path string) (*config.SourceConfig, error) { + var cfg config.SourceConfig + // Walk through the directory and load each file + err := filepath.WalkDir(path, func(walkpath string, d os.DirEntry, err error) error { + if err != nil { + return errors.Wrapf(err, "failed to get config file %s", walkpath) + } + // Check if the path is a directory + if d.IsDir() { + return nil + } + // Get the file type from the extension + typo := codec.TypeFromExt(filepath.Ext(walkpath)) + // Check if the file type is unknown + if typo == codec.UNKNOWN { + return nil + } + + // Decode the file into the config struct + if err := codec.DecodeFromFile(walkpath, &cfg); err != nil { + return errors.Wrapf(err, "failed to parse config file %s", walkpath) + } + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "load config error") + } return &cfg, nil } + +// LoadSourceConfig loads the config file from the given path +func LoadSourceConfig(bootstrap *Bootstrap) (*config.SourceConfig, error) { + // Get the path from the bootstrap + path := bootstrap.WorkPath() + + // Get the file info from the path + stat, err := os.Stat(path) + if err != nil { + return nil, errors.Wrap(err, "load config stat error") + } + // Load the config file + return loadSource(stat, path) +} diff --git a/runtime/buf.gen.yaml b/runtime/buf.gen.yaml index fcadeaa..a7a8a62 100644 --- a/runtime/buf.gen.yaml +++ b/runtime/buf.gen.yaml @@ -5,8 +5,12 @@ managed: # override: # - file_option: go_package_prefix # value: github.com/origadmin/toolkits/runtime -# inputs: -# - directory: protos + # override: + # - file_option: go_package + # value: internal/config/v1;config + # inputs: + # - directory: protos + # plugins: - local: protoc-gen-go out: internal diff --git a/runtime/buf.yaml b/runtime/buf.yaml index ed374d4..645eaf9 100644 --- a/runtime/buf.yaml +++ b/runtime/buf.yaml @@ -10,6 +10,17 @@ modules: breaking: use: - FILE +# - path: database/ent/proto +# name: buf.build/origadmin/entgen +# lint: +# use: +# - STANDARD +# except: +# - PACKAGE_VERSION_SUFFIX +# - PACKAGE_DIRECTORY_MATCH +# breaking: +# use: +# - FILE deps: # - buf.build/envoyproxy/protoc-gen-validate - buf.build/bufbuild/protovalidate diff --git a/runtime/build.go b/runtime/build.go new file mode 100644 index 0000000..9e10108 --- /dev/null +++ b/runtime/build.go @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 OrigAdmin. All rights reserved. + */ + +// Package runtime implements the functions, types, and interfaces for the module. +package runtime + +import ( + "sync" + + "github.com/origadmin/toolkits/runtime/config" + "github.com/origadmin/toolkits/runtime/registry" +) + +// builder is a struct that holds a map of ConfigBuilders and a map of RegistryBuilders. +type builder struct { + configs map[string]ConfigBuilder + configMux sync.RWMutex + registries map[string]RegistryBuilder + registryMux sync.RWMutex +} + +// NewConfig creates a new Config object based on the given SourceConfig and options. +func (b *builder) NewConfig(cfg *config.SourceConfig, opts ...config.Option) (config.Config, error) { + b.configMux.RLock() + defer b.configMux.RUnlock() + configBuilder, ok := build.configs[cfg.Type] + if !ok { + return nil, ErrNotFound + } + return configBuilder.NewConfig(cfg, opts...) +} + +// NewRegistrar creates a new Registrar object based on the given RegistryConfig. +func (b *builder) NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) { + b.registryMux.RLock() + defer b.registryMux.RUnlock() + registryBuilder, ok := build.registries[cfg.Type] + if !ok { + return nil, ErrNotFound + } + return registryBuilder.NewRegistrar(cfg) +} + +// NewDiscovery creates a new Discovery object based on the given RegistryConfig. +func (b *builder) NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) { + b.registryMux.RLock() + defer b.registryMux.RUnlock() + registryBuilder, ok := build.registries[cfg.Type] + if !ok { + return nil, ErrNotFound + } + return registryBuilder.NewDiscovery(cfg) +} + +// RegisterConfig registers a new ConfigBuilder with the given name. +func (b *builder) RegisterConfig(name string, configBuilder ConfigBuilder) { + b.configMux.Lock() + defer b.configMux.Unlock() + build.configs[name] = configBuilder +} + +// RegisterConfigFunc registers a new ConfigBuilder with the given name and function. +func (b *builder) RegisterConfigFunc(name string, configBuilder ConfigBuildFunc) { + b.RegisterConfig(name, configBuilder) +} + +// RegisterRegistry registers a new RegistryBuilder with the given name. +func (b *builder) RegisterRegistry(name string, registryBuilder RegistryBuilder) { + b.registryMux.Lock() + defer b.registryMux.Unlock() + build.registries[name] = registryBuilder +} + +// RegisterRegistryFunc registers a new RegistryBuilder with the given name and functions. +func (b *builder) RegisterRegistryFunc(name string, registryBuilder RegistrarBuildFunc, discoveryBuilder DiscoveryBuildFunc) { + b.RegisterRegistry(name, ®istryWrap{ + RegistrarBuildFunc: registryBuilder, + DiscoveryBuildFunc: discoveryBuilder, + }) +} diff --git a/runtime/build_config.go b/runtime/build_config.go new file mode 100644 index 0000000..7d86689 --- /dev/null +++ b/runtime/build_config.go @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 OrigAdmin. All rights reserved. + */ + +// Package runtime implements the functions, types, and interfaces for the module. +package runtime + +import ( + "github.com/origadmin/toolkits/runtime/config" +) + +// configBuildRegistry is an interface that defines a method for registering a config builder. +type configBuildRegistry interface { + // RegisterConfig registers a config builder with the given name. + RegisterConfig(name string, configBuilder ConfigBuilder) +} + +// ConfigBuilder is an interface that defines a method for creating a new config. +type ConfigBuilder interface { + // NewConfig creates a new config using the given SourceConfig and a list of Options. + NewConfig(cfg *config.SourceConfig, opts ...config.Option) (config.Config, error) +} + +// ConfigBuildFunc is a function type that takes a SourceConfig and a list of Options and returns a Config and an error. +type ConfigBuildFunc func(*config.SourceConfig, ...config.Option) (config.Config, error) + +// NewConfig is a method that implements the ConfigBuilder interface for ConfigBuildFunc. +func (fn ConfigBuildFunc) NewConfig(cfg *config.SourceConfig, opts ...config.Option) (config.Config, error) { + // Call the function with the given SourceConfig and a list of Options. + return fn(cfg, opts...) +} diff --git a/runtime/build_registry.go b/runtime/build_registry.go new file mode 100644 index 0000000..d4749f1 --- /dev/null +++ b/runtime/build_registry.go @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 OrigAdmin. All rights reserved. + */ + +// Package runtime implements the functions, types, and interfaces for the module. +package runtime + +import ( + "github.com/origadmin/toolkits/runtime/config" + "github.com/origadmin/toolkits/runtime/registry" +) + +// registryBuildRegistry is an interface that defines a method for registering a RegistryBuilder. +type registryBuildRegistry interface { + RegisterRegistry(name string, registryBuilder RegistryBuilder) +} + +// RegistryBuilder is an interface that defines methods for creating a Discovery and a Registrar. +type RegistryBuilder interface { + NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) + NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) +} + +// RegistrarBuildFunc is a function type that takes a *config.RegistryConfig and returns a registry.Registrar and an error. +type RegistrarBuildFunc func(cfg *config.RegistryConfig) (registry.Registrar, error) + +// NewRegistrar is a method that calls the RegistrarBuildFunc with the given config. +func (fn RegistrarBuildFunc) NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) { + return fn(cfg) +} + +// DiscoveryBuildFunc is a function type that takes a *config.RegistryConfig and returns a registry.Discovery and an error. +type DiscoveryBuildFunc func(cfg *config.RegistryConfig) (registry.Discovery, error) + +// NewDiscovery is a method that calls the DiscoveryBuildFunc with the given config. +func (fn DiscoveryBuildFunc) NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) { + return fn(cfg) +} + +// registryWrap is a struct that embeds RegistrarBuildFunc and DiscoveryBuildFunc. +type registryWrap struct { + RegistrarBuildFunc + DiscoveryBuildFunc +} + +// _ is a blank identifier that is used to satisfy the interface requirement for RegistryBuilder. +var _ RegistryBuilder = ®istryWrap{} diff --git a/runtime/config/config.go b/runtime/config/config.go index ba0509b..f0a26cd 100644 --- a/runtime/config/config.go +++ b/runtime/config/config.go @@ -116,6 +116,9 @@ type ( SourceConfig_ETCD = config.SourceConfig_ETCD SourceConfig_ETCDMultiError = config.SourceConfig_ETCDMultiError SourceConfig_ETCDValidationError = config.SourceConfig_ETCDValidationError + SourceConfig_Custom = config.SourceConfig_Custom + SourceConfig_CustomMultiError = config.SourceConfig_CustomMultiError + SourceConfig_CustomValidationError = config.SourceConfig_CustomValidationError SourceConfig_File = config.SourceConfig_File SourceConfig_FileMultiError = config.SourceConfig_FileMultiError SourceConfig_FileValidationError = config.SourceConfig_FileValidationError diff --git a/runtime/internal/config/v1/source.pb.go b/runtime/internal/config/v1/source.pb.go index 4823eda..2b27fcb 100644 --- a/runtime/internal/config/v1/source.pb.go +++ b/runtime/internal/config/v1/source.pb.go @@ -10,6 +10,7 @@ import ( _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" reflect "reflect" sync "sync" ) @@ -293,6 +294,51 @@ func (x *SourceConfig_ETCD) GetEndpoints() []string { return nil } +type SourceConfig_Custom struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *anypb.Any `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +} + +func (x *SourceConfig_Custom) Reset() { + *x = SourceConfig_Custom{} + mi := &file_config_v1_source_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SourceConfig_Custom) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SourceConfig_Custom) ProtoMessage() {} + +func (x *SourceConfig_Custom) ProtoReflect() protoreflect.Message { + mi := &file_config_v1_source_proto_msgTypes[4] + 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 SourceConfig_Custom.ProtoReflect.Descriptor instead. +func (*SourceConfig_Custom) Descriptor() ([]byte, []int) { + return file_config_v1_source_proto_rawDescGZIP(), []int{0, 3} +} + +func (x *SourceConfig_Custom) GetConfig() *anypb.Any { + if x != nil { + return x.Config + } + return nil +} + var File_config_v1_source_proto protoreflect.FileDescriptor var file_config_v1_source_proto_rawDesc = []byte{ @@ -300,60 +346,66 @@ var file_config_v1_source_proto_rawDesc = []byte{ 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0xb9, 0x05, 0x0a, 0x0c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x51, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x3d, 0xba, 0x48, 0x3a, 0x72, 0x38, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x52, 0x06, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x52, 0x04, 0x65, 0x74, 0x63, 0x64, 0x52, 0x05, 0x6e, 0x61, 0x63, 0x6f, - 0x73, 0x52, 0x06, 0x61, 0x70, 0x6f, 0x6c, 0x6c, 0x6f, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x65, 0x73, 0x52, 0x07, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x69, 0x73, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, - 0x3b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x48, - 0x01, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x04, - 0x65, 0x74, 0x63, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2e, 0x45, 0x54, 0x43, 0x44, 0x48, 0x02, 0x52, 0x04, 0x65, 0x74, 0x63, 0x64, - 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x22, 0x0a, - 0x0c, 0x65, 0x6e, 0x76, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x08, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, - 0x73, 0x12, 0x40, 0x0a, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x6e, 0x76, - 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x61, - 0x72, 0x67, 0x73, 0x1a, 0x32, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, - 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, 0x64, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x1a, 0x24, 0x0a, - 0x04, 0x45, 0x54, 0x43, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, - 0x07, 0x0a, 0x05, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x74, 0x63, 0x64, 0x42, 0x96, 0x01, 0x0a, - 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x0b, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x69, 0x67, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x2f, 0x74, 0x6f, 0x6f, 0x6c, 0x6b, 0x69, 0x74, 0x73, 0x2f, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3b, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, - 0xe2, 0x02, 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xff, 0x05, 0x0a, 0x0c, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0xba, 0x48, 0x48, 0x72, + 0x46, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x06, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x52, 0x04, 0x65, 0x74, 0x63, 0x64, 0x52, 0x05, 0x6e, 0x61, 0x63, + 0x6f, 0x73, 0x52, 0x06, 0x61, 0x70, 0x6f, 0x6c, 0x6c, 0x6f, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x52, 0x07, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x69, 0x73, 0x52, + 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x35, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x48, 0x00, 0x52, + 0x04, 0x66, 0x69, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x3b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x48, 0x01, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x65, 0x74, 0x63, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x54, 0x43, + 0x44, 0x48, 0x02, 0x52, 0x04, 0x65, 0x74, 0x63, 0x64, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x5f, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, + 0x76, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x08, 0x65, 0x6e, + 0x76, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x45, 0x6e, 0x76, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x1a, 0x32, 0x0a, 0x04, + 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x1a, 0x64, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x1a, 0x24, 0x0a, 0x04, 0x45, 0x54, 0x43, 0x44, 0x12, 0x1c, + 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x36, 0x0a, 0x06, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x41, 0x72, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x74, 0x63, 0x64, 0x42, 0x96, 0x01, + 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x42, + 0x0b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x72, 0x69, 0x67, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x2f, 0x74, 0x6f, 0x6f, 0x6c, 0x6b, 0x69, 0x74, 0x73, 0x2f, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3b, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -368,24 +420,27 @@ func file_config_v1_source_proto_rawDescGZIP() []byte { return file_config_v1_source_proto_rawDescData } -var file_config_v1_source_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_config_v1_source_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_config_v1_source_proto_goTypes = []any{ (*SourceConfig)(nil), // 0: config.v1.SourceConfig (*SourceConfig_File)(nil), // 1: config.v1.SourceConfig.File (*SourceConfig_Consul)(nil), // 2: config.v1.SourceConfig.Consul (*SourceConfig_ETCD)(nil), // 3: config.v1.SourceConfig.ETCD - nil, // 4: config.v1.SourceConfig.EnvArgsEntry + (*SourceConfig_Custom)(nil), // 4: config.v1.SourceConfig.Custom + nil, // 5: config.v1.SourceConfig.EnvArgsEntry + (*anypb.Any)(nil), // 6: google.protobuf.Any } var file_config_v1_source_proto_depIdxs = []int32{ 1, // 0: config.v1.SourceConfig.file:type_name -> config.v1.SourceConfig.File 2, // 1: config.v1.SourceConfig.consul:type_name -> config.v1.SourceConfig.Consul 3, // 2: config.v1.SourceConfig.etcd:type_name -> config.v1.SourceConfig.ETCD - 4, // 3: config.v1.SourceConfig.env_args:type_name -> config.v1.SourceConfig.EnvArgsEntry - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 5, // 3: config.v1.SourceConfig.env_args:type_name -> config.v1.SourceConfig.EnvArgsEntry + 6, // 4: config.v1.SourceConfig.Custom.config:type_name -> google.protobuf.Any + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_config_v1_source_proto_init() } @@ -400,7 +455,7 @@ func file_config_v1_source_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_config_v1_source_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/runtime/internal/config/v1/source.pb.validate.go b/runtime/internal/config/v1/source.pb.validate.go index ce72ac0..e624923 100644 --- a/runtime/internal/config/v1/source.pb.validate.go +++ b/runtime/internal/config/v1/source.pb.validate.go @@ -556,3 +556,134 @@ var _ interface { Cause() error ErrorName() string } = SourceConfig_ETCDValidationError{} + +// Validate checks the field values on SourceConfig_Custom with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *SourceConfig_Custom) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SourceConfig_Custom with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// SourceConfig_CustomMultiError, or nil if none found. +func (m *SourceConfig_Custom) ValidateAll() error { + return m.validate(true) +} + +func (m *SourceConfig_Custom) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetConfig()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SourceConfig_CustomValidationError{ + field: "Config", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SourceConfig_CustomValidationError{ + field: "Config", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetConfig()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SourceConfig_CustomValidationError{ + field: "Config", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return SourceConfig_CustomMultiError(errors) + } + + return nil +} + +// SourceConfig_CustomMultiError is an error wrapping multiple validation +// errors returned by SourceConfig_Custom.ValidateAll() if the designated +// constraints aren't met. +type SourceConfig_CustomMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SourceConfig_CustomMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SourceConfig_CustomMultiError) AllErrors() []error { return m } + +// SourceConfig_CustomValidationError is the validation error returned by +// SourceConfig_Custom.Validate if the designated constraints aren't met. +type SourceConfig_CustomValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SourceConfig_CustomValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SourceConfig_CustomValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SourceConfig_CustomValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SourceConfig_CustomValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SourceConfig_CustomValidationError) ErrorName() string { + return "SourceConfig_CustomValidationError" +} + +// Error satisfies the builtin error interface +func (e SourceConfig_CustomValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSourceConfig_Custom.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SourceConfig_CustomValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SourceConfig_CustomValidationError{} diff --git a/runtime/kratos/builder.go b/runtime/kratos/builder.go deleted file mode 100644 index 4113daa..0000000 --- a/runtime/kratos/builder.go +++ /dev/null @@ -1,83 +0,0 @@ -package kratos - -import ( - "sync" - - "github.com/go-kratos/kratos/v2/registry" - - "github.com/origadmin/toolkits/errors" - "github.com/origadmin/toolkits/runtime/config" -) - -type ConfigBuilder func(*config.SourceConfig, ...config.Option) (config.Config, error) - -type RegistryBuilder interface { - NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) - NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) -} - -type builder struct { - mutex sync.RWMutex - configs map[string]ConfigBuilder - registries map[string]RegistryBuilder -} - -var ( - once = &sync.Once{} - build = &builder{} -) - -var ErrNotFound = errors.String("not found") - -func init() { - build.init() -} - -func (b *builder) init() { - once.Do(func() { - b.configs = make(map[string]ConfigBuilder) - b.registries = make(map[string]RegistryBuilder) - }) -} - -func RegistryConfig(name string, configBuilder ConfigBuilder) { - build.mutex.Lock() - defer build.mutex.Unlock() - build.configs[name] = configBuilder -} - -func NewConfig(cfg *config.SourceConfig, opts ...config.Option) (config.Config, error) { - build.mutex.RLock() - defer build.mutex.RUnlock() - configBuilder, ok := build.configs[cfg.Type] - if !ok { - return nil, ErrNotFound - } - return configBuilder(cfg, opts...) -} - -func RegistryRegistry(name string, registryBuilder RegistryBuilder) { - build.mutex.Lock() - defer build.mutex.Unlock() - build.registries[name] = registryBuilder -} - -func NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) { - build.mutex.RLock() - defer build.mutex.RUnlock() - discoveryBuilder, ok := build.registries[cfg.Type] - if !ok { - return nil, ErrNotFound - } - return discoveryBuilder.NewDiscovery(cfg) -} - -func NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) { - build.mutex.RLock() - defer build.mutex.RUnlock() - discoveryBuilder, ok := build.registries[cfg.Type] - if !ok { - return nil, ErrNotFound - } - return discoveryBuilder.NewRegistrar(cfg) -} diff --git a/runtime/kratos/middlewares/logger/logger.go b/runtime/middlewares/logger/logger.go similarity index 100% rename from runtime/kratos/middlewares/logger/logger.go rename to runtime/middlewares/logger/logger.go diff --git a/runtime/kratos/middlewares/security/security.go b/runtime/middlewares/security/security.go similarity index 100% rename from runtime/kratos/middlewares/security/security.go rename to runtime/middlewares/security/security.go diff --git a/runtime/proto/config/v1/cors.proto b/runtime/proto/config/v1/cors.proto index cc8fed8..5a4ee80 100644 --- a/runtime/proto/config/v1/cors.proto +++ b/runtime/proto/config/v1/cors.proto @@ -8,33 +8,33 @@ option go_package = "github.com/origadmin/toolkits/runtime/config;config"; // cors config. message CorsConfig { - // AllowCredentials indicates whether the request can include user credentials like - // cookies, HTTP authentication or client side SSL certificates. - bool allow_credentials = 2 [json_name = "allow_credentials"]; - // AllowOrigins is a list of origins a cross-domain request can be executed from. - // If the special "*" value is present in the list, all origins will be allowed. - // Default value is [*] - repeated string allow_origins = 3 [json_name = "allow_origins"]; - // AllowMethods is a list of methods the client is allowed to use with - // cross-domain requests. Default value is simple methods (GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS) - repeated string allow_methods = 4 [json_name = "allow_methods"]; - // AllowHeaders is list of non simple headers the client is allowed to use with - // cross-domain requests. - repeated string allow_headers = 5 [json_name = "allow_headers"]; - // ExposeHeaders indicates which headers are safe to expose to the API of a CORS - // API specification - repeated string expose_headers = 6 [json_name = "expose_headers"]; - // MaxAge indicates how long (with second-precision) the results of a preflight request - // can be cached - google.protobuf.Duration max_age = 7 [json_name = "max_age"]; - // Allows to add origins like http://some-domain/*, https://api.* or http://some.*.subdomain.com - bool allow_wildcard = 8 [json_name = "allow_wildcard"]; - // Allows usage of popular browser extensions schemas - bool allow_browser_extensions = 9 [json_name = "allow_browser_extensions"]; - // Allows usage of WebSocket protocol - bool allow_web_sockets = 10 [json_name = "allow_web_sockets"]; - // Allows usage of private network addresses (127.0.0.1, [::1], localhost) - bool allow_private_network = 11 [json_name = "allow_private_network"]; - // Allows usage of file:// schema (dangerous!) use it only when you 100% sure it's needed - bool allow_files = 12 [json_name = "allow_files"]; + // AllowCredentials indicates whether the request can include user credentials like + // cookies, HTTP authentication or client side SSL certificates. + bool allow_credentials = 2 [json_name = "allow_credentials"]; + // AllowOrigins is a list of origins a cross-domain request can be executed from. + // If the special "*" value is present in the list, all origins will be allowed. + // Default value is [*] + repeated string allow_origins = 3 [json_name = "allow_origins"]; + // AllowMethods is a list of methods the client is allowed to use with + // cross-domain requests. Default value is simple methods (GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS) + repeated string allow_methods = 4 [json_name = "allow_methods"]; + // AllowHeaders is list of non simple headers the client is allowed to use with + // cross-domain requests. + repeated string allow_headers = 5 [json_name = "allow_headers"]; + // ExposeHeaders indicates which headers are safe to expose to the API of a CORS + // API specification + repeated string expose_headers = 6 [json_name = "expose_headers"]; + // MaxAge indicates how long (with second-precision) the results of a preflight request + // can be cached + google.protobuf.Duration max_age = 7 [json_name = "max_age"]; + // Allows to add origins like http://some-domain/*, https://api.* or http://some.*.subdomain.com + bool allow_wildcard = 8 [json_name = "allow_wildcard"]; + // Allows usage of popular browser extensions schemas + bool allow_browser_extensions = 9 [json_name = "allow_browser_extensions"]; + // Allows usage of WebSocket protocol + bool allow_web_sockets = 10 [json_name = "allow_web_sockets"]; + // Allows usage of private network addresses (127.0.0.1, [::1], localhost) + bool allow_private_network = 11 [json_name = "allow_private_network"]; + // Allows usage of file:// schema (dangerous!) use it only when you 100% sure it's needed + bool allow_files = 12 [json_name = "allow_files"]; } \ No newline at end of file diff --git a/runtime/proto/config/v1/data.proto b/runtime/proto/config/v1/data.proto index 8d6bb8e..c62850f 100644 --- a/runtime/proto/config/v1/data.proto +++ b/runtime/proto/config/v1/data.proto @@ -7,20 +7,20 @@ import "google/protobuf/duration.proto"; option go_package = "github.com/origadmin/toolkits/runtime/config;config"; message DataConfig { - // Database - message Database { - bool debug = 1; // Debugging + // Database + message Database { + bool debug = 1; // Debugging - string driver = 2; // Driver name: mysql, postgresql, mongodb, sqlite...... - string source = 3; // Data source (DSN string) + string driver = 2; // Driver name: mysql, postgresql, mongodb, sqlite...... + string source = 3; // Data source (DSN string) - bool migrate = 10; // Data migration switch + bool migrate = 10; // Data migration switch - bool enable_trace = 12; // Link tracking switch - bool enable_metrics = 13; // Performance analysis switch + bool enable_trace = 12; // Link tracking switch + bool enable_metrics = 13; // Performance analysis switch - int32 max_idle_connections = 20; // Maximum number of free connections in the connection pool - int32 max_open_connections = 21; // Maximum number of open connections in the connection pool - google.protobuf.Duration connection_max_lifetime = 22; // Maximum length of time that the connection can be reused - } + int32 max_idle_connections = 20; // Maximum number of free connections in the connection pool + int32 max_open_connections = 21; // Maximum number of open connections in the connection pool + google.protobuf.Duration connection_max_lifetime = 22; // Maximum length of time that the connection can be reused + } } \ No newline at end of file diff --git a/runtime/proto/config/v1/logger.proto b/runtime/proto/config/v1/logger.proto index b37b0ec..909a690 100644 --- a/runtime/proto/config/v1/logger.proto +++ b/runtime/proto/config/v1/logger.proto @@ -6,15 +6,15 @@ option go_package = "github.com/origadmin/toolkits/runtime/config;config"; // logger config. message LoggerConfig { - enum Level { - LEVEL_UNSPECIFIED = 0; - LEVEL_DEBUG = 1; - LEVEL_INFO = 2; - LEVEL_WARN = 3; - LEVEL_ERROR = 4; - LEVEL_FATAL = 5; - } + enum Level { + LEVEL_UNSPECIFIED = 0; + LEVEL_DEBUG = 1; + LEVEL_INFO = 2; + LEVEL_WARN = 3; + LEVEL_ERROR = 4; + LEVEL_FATAL = 5; + } - string name = 2 [json_name = "name"]; - Level level = 3 [json_name = "level"]; + string name = 2 [json_name = "name"]; + Level level = 3 [json_name = "level"]; } \ No newline at end of file diff --git a/runtime/proto/config/v1/metrics.proto b/runtime/proto/config/v1/metrics.proto index 9f013d8..c3585ff 100644 --- a/runtime/proto/config/v1/metrics.proto +++ b/runtime/proto/config/v1/metrics.proto @@ -7,7 +7,7 @@ option go_package = "github.com/origadmin/toolkits/runtime/config;config"; // metric config. message MetricConfig { - repeated string includes = 2 [json_name = "includes"]; - string name = 3 [json_name = "name"]; - string address = 4 [json_name = "address"]; + repeated string includes = 2 [json_name = "includes"]; + string name = 3 [json_name = "name"]; + string address = 4 [json_name = "address"]; } \ No newline at end of file diff --git a/runtime/proto/config/v1/middleware.proto b/runtime/proto/config/v1/middleware.proto index bd72047..97ea321 100644 --- a/runtime/proto/config/v1/middleware.proto +++ b/runtime/proto/config/v1/middleware.proto @@ -11,10 +11,10 @@ import "google/protobuf/duration.proto"; option go_package = "github.com/origadmin/toolkits/runtime/config;config"; message MiddlewareConfig { - CorsConfig cors = 1 [json_name = "cors"]; - MetricConfig metric = 2 [json_name = "metric"]; - LoggerConfig logger = 3 [json_name = "logger"]; - SecurityConfig security = 4 [json_name = "security"]; + CorsConfig cors = 1 [json_name = "cors"]; + MetricConfig metric = 2 [json_name = "metric"]; + LoggerConfig logger = 3 [json_name = "logger"]; + SecurityConfig security = 4 [json_name = "security"]; - google.protobuf.Duration timeout = 5 [json_name = "timeout"]; + google.protobuf.Duration timeout = 5 [json_name = "timeout"]; } \ No newline at end of file diff --git a/runtime/proto/config/v1/security.proto b/runtime/proto/config/v1/security.proto index 712841f..ce564ba 100644 --- a/runtime/proto/config/v1/security.proto +++ b/runtime/proto/config/v1/security.proto @@ -8,24 +8,24 @@ option go_package = "github.com/origadmin/toolkits/runtime/config;config"; // Authorization middleware config message AuthorizationConfig { - repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths - string signing_method = 3 [json_name = "signing_method"]; // Signing method - string signing_key = 4 [json_name = "signing_key"]; // Signing key - string old_signing_key = 5 [json_name = "old_signing_key"]; // Old signing key - google.protobuf.Duration expired_time = 6 [json_name = "expired_time"]; // Expired time + repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths + string signing_method = 3 [json_name = "signing_method"]; // Signing method + string signing_key = 4 [json_name = "signing_key"]; // Signing key + string old_signing_key = 5 [json_name = "old_signing_key"]; // Old signing key + google.protobuf.Duration expired_time = 6 [json_name = "expired_time"]; // Expired time } // Casbin middleware config message CasbinConfig { - repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths - string policy_file = 3 [json_name = "policy_file"]; // Policy file - string model_file = 4 [json_name = "model_file"]; // Model file + repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths + string policy_file = 3 [json_name = "policy_file"]; // Policy file + string model_file = 4 [json_name = "model_file"]; // Model file } // Security middleware config. message SecurityConfig { - repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths - AuthorizationConfig authorization = 5 [json_name = "authorization"]; // AuthorizationConfig - CasbinConfig casbin = 6 [json_name = "casbin"]; // CasbinConfig + repeated string allowed_method_paths = 2 [json_name = "allowed_method_paths"]; // Direct release method paths + AuthorizationConfig authorization = 5 [json_name = "authorization"]; // AuthorizationConfig + CasbinConfig casbin = 6 [json_name = "casbin"]; // CasbinConfig } \ No newline at end of file diff --git a/runtime/proto/config/v1/source.proto b/runtime/proto/config/v1/source.proto index 51581de..d53f41a 100644 --- a/runtime/proto/config/v1/source.proto +++ b/runtime/proto/config/v1/source.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package config.v1; import "buf/validate/validate.proto"; +import "google/protobuf/any.proto"; option go_package = "github.com/origadmin/toolkits/runtime/config;config"; @@ -30,7 +31,12 @@ message SourceConfig { message ETCD { repeated string endpoints = 1 [json_name = "endpoints"]; } - string type = 1 [(buf.validate.field).string = {in: ["none", "consul", "etcd", "nacos", "apollo", "kubernetes", "polaris"]}]; // Type + + message Custom { + google.protobuf.Any config = 1 [json_name = "config"]; + } + + string type = 1 [(buf.validate.field).string = {in: ["none", "file", "consul", "etcd", "nacos", "apollo", "kubernetes", "polaris", "custom"]}]; // Type string name = 2 [json_name = "name"]; // Name optional File file = 3 [json_name = "file"]; optional Consul consul = 4 [json_name = "consul"]; // Consul diff --git a/runtime/proto/config/v1/tracer.proto b/runtime/proto/config/v1/tracer.proto index 04d3ea0..6fa4e6f 100644 --- a/runtime/proto/config/v1/tracer.proto +++ b/runtime/proto/config/v1/tracer.proto @@ -6,6 +6,6 @@ option go_package = "github.com/origadmin/toolkits/runtime/config;config"; // Trace config. message TraceConfig { - string name = 2 [json_name = "name"]; - string endpoint = 3 [json_name = "endpoint"]; + string name = 2 [json_name = "name"]; + string endpoint = 3 [json_name = "endpoint"]; } \ No newline at end of file diff --git a/runtime/kratos/registry/registry.go b/runtime/registry/registry.go similarity index 85% rename from runtime/kratos/registry/registry.go rename to runtime/registry/registry.go index 7c2bbf1..13153e8 100644 --- a/runtime/kratos/registry/registry.go +++ b/runtime/registry/registry.go @@ -4,6 +4,7 @@ import ( "github.com/go-kratos/kratos/v2/registry" ) +// This is only alias type for registry type ( Watcher = registry.Watcher ServiceInstance = registry.ServiceInstance diff --git a/runtime/runtime.go b/runtime/runtime.go new file mode 100644 index 0000000..3c46d28 --- /dev/null +++ b/runtime/runtime.go @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 OrigAdmin. All rights reserved. + */ + +// Package runtime provides functions for loading configurations and registering services. +package runtime + +import ( + "sync" + + "github.com/origadmin/toolkits/errors" + "github.com/origadmin/toolkits/runtime/config" + "github.com/origadmin/toolkits/runtime/registry" +) + +type Builder interface { + ConfigBuilder + RegistryBuilder + + configBuildRegistry + registryBuildRegistry +} + +// build is a global variable that holds an instance of the builder struct. +var ( + once = &sync.Once{} + build = &builder{} +) + +// ErrNotFound is an error that is returned when a ConfigBuilder or RegistryBuilder is not found. +var ErrNotFound = errors.String("not found") + +// init initializes the builder struct. +func init() { + once.Do(func() { + build.init() + }) +} + +// init initializes the builder struct. +func (b *builder) init() { + b.configs = make(map[string]ConfigBuilder) + b.registries = make(map[string]RegistryBuilder) +} + +// RegisterConfig registers a ConfigBuilder with the builder. +func RegisterConfig(name string, configBuilder ConfigBuilder) { + build.RegisterConfig(name, configBuilder) +} + +// NewConfig creates a new Config using the registered ConfigBuilder. +func NewConfig(cfg *config.SourceConfig, opts ...config.Option) (config.Config, error) { + return build.NewConfig(cfg, opts...) +} + +// RegisterRegistry registers a RegistryBuilder with the builder. +func RegisterRegistry(name string, registryBuilder RegistryBuilder) { + build.RegisterRegistry(name, registryBuilder) +} + +// NewDiscovery creates a new Discovery using the registered RegistryBuilder. +func NewDiscovery(cfg *config.RegistryConfig) (registry.Discovery, error) { + return build.NewDiscovery(cfg) +} + +// NewRegistrar creates a new Registrar using the registered RegistryBuilder. +func NewRegistrar(cfg *config.RegistryConfig) (registry.Registrar, error) { + return build.NewRegistrar(cfg) +} + +// New creates a new Builder. +func New() Builder { + b := &builder{} + b.init() + return b +} diff --git a/runtime/kratos/transport/gins/README.md b/runtime/transport/gins/README.md similarity index 100% rename from runtime/kratos/transport/gins/README.md rename to runtime/transport/gins/README.md diff --git a/runtime/kratos/transport/gins/binding.go b/runtime/transport/gins/binding.go similarity index 100% rename from runtime/kratos/transport/gins/binding.go rename to runtime/transport/gins/binding.go diff --git a/runtime/kratos/transport/gins/codec.go b/runtime/transport/gins/codec.go similarity index 100% rename from runtime/kratos/transport/gins/codec.go rename to runtime/transport/gins/codec.go diff --git a/runtime/kratos/transport/gins/codec_go1.20.go b/runtime/transport/gins/codec_go1.20.go similarity index 100% rename from runtime/kratos/transport/gins/codec_go1.20.go rename to runtime/transport/gins/codec_go1.20.go diff --git a/runtime/kratos/transport/gins/context.go b/runtime/transport/gins/context.go similarity index 100% rename from runtime/kratos/transport/gins/context.go rename to runtime/transport/gins/context.go diff --git a/runtime/kratos/transport/gins/endpoint.go b/runtime/transport/gins/endpoint.go similarity index 100% rename from runtime/kratos/transport/gins/endpoint.go rename to runtime/transport/gins/endpoint.go diff --git a/runtime/kratos/transport/gins/host.go b/runtime/transport/gins/host.go similarity index 100% rename from runtime/kratos/transport/gins/host.go rename to runtime/transport/gins/host.go diff --git a/runtime/kratos/transport/gins/logger.go b/runtime/transport/gins/logger.go similarity index 100% rename from runtime/kratos/transport/gins/logger.go rename to runtime/transport/gins/logger.go diff --git a/runtime/kratos/transport/gins/middleware.go b/runtime/transport/gins/middleware.go similarity index 91% rename from runtime/kratos/transport/gins/middleware.go rename to runtime/transport/gins/middleware.go index 23e6762..a055327 100644 --- a/runtime/kratos/transport/gins/middleware.go +++ b/runtime/transport/gins/middleware.go @@ -24,7 +24,13 @@ func Logger(logger log.Logger) HandlerFunc { path := c.Request.URL.Path query := c.Request.URL.RawQuery c.Next() - + //"status": c.Writer.Status(), + // "method": c.Request.Method, + // "path": path, + // "ip": c.ClientIP(), + // "latency": latency, + // "user-agent": c.Request.UserAgent(), + // "time": end.Format(timeFormat), cost := time.Since(start) _ = logger.Log(log.LevelInfo, "status", c.Writer.Status(), diff --git a/runtime/kratos/transport/gins/options.go b/runtime/transport/gins/options.go similarity index 100% rename from runtime/kratos/transport/gins/options.go rename to runtime/transport/gins/options.go diff --git a/runtime/kratos/transport/gins/server.go b/runtime/transport/gins/server.go similarity index 100% rename from runtime/kratos/transport/gins/server.go rename to runtime/transport/gins/server.go diff --git a/runtime/kratos/transport/gins/server_test.go b/runtime/transport/gins/server_test.go similarity index 100% rename from runtime/kratos/transport/gins/server_test.go rename to runtime/transport/gins/server_test.go diff --git a/runtime/kratos/transport/gins/transport.go b/runtime/transport/gins/transport.go similarity index 100% rename from runtime/kratos/transport/gins/transport.go rename to runtime/transport/gins/transport.go diff --git a/runtime/kratos/transport/gins/transport_http.go b/runtime/transport/gins/transport_http.go similarity index 100% rename from runtime/kratos/transport/gins/transport_http.go rename to runtime/transport/gins/transport_http.go diff --git a/runtime/kratos/transport/gins/transport_test.go b/runtime/transport/gins/transport_test.go similarity index 100% rename from runtime/kratos/transport/gins/transport_test.go rename to runtime/transport/gins/transport_test.go