Compare commits
22 Commits
Author | SHA1 | Date |
---|---|---|
|
e868a001ec | |
|
8bad3fed0f | |
|
6d3e89ff89 | |
|
ead2368c2f | |
|
eb3adf0f0a | |
|
2bc352f538 | |
|
a0fc325190 | |
|
5758f57b6b | |
|
310a82873f | |
|
f1545e0403 | |
|
741b6adca7 | |
|
98686b0b0a | |
|
9df154169b | |
|
476a2c4fa0 | |
|
3bbe1db11e | |
|
c925bcf60d | |
|
6f5bdc4cb6 | |
|
2f0372c760 | |
|
b098c04ffb | |
|
7c3b1dca16 | |
|
25436c0fcf | |
|
707bd574c7 |
|
@ -14,7 +14,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- go_version: 1.18
|
||||
- go_version: 1.21
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.x
|
||||
|
|
|
@ -1,467 +1,233 @@
|
|||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: nacos_grpc_service.proto
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.7
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/nacos_grpc_service.proto
|
||||
|
||||
package grpc
|
||||
package auto
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
any "github.com/golang/protobuf/ptypes/any"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
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"
|
||||
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 Metadata struct {
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
ClientIp string `protobuf:"bytes,8,opt,name=clientIp,proto3" json:"clientIp,omitempty"`
|
||||
Headers map[string]string `protobuf:"bytes,7,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
ClientIp string `protobuf:"bytes,8,opt,name=clientIp,proto3" json:"clientIp,omitempty"`
|
||||
Headers map[string]string `protobuf:"bytes,7,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (m *Metadata) Reset() { *m = Metadata{} }
|
||||
func (m *Metadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*Metadata) ProtoMessage() {}
|
||||
func (x *Metadata) Reset() {
|
||||
*x = Metadata{}
|
||||
mi := &file_api_proto_nacos_grpc_service_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Metadata) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Metadata) ProtoMessage() {}
|
||||
|
||||
func (x *Metadata) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_nacos_grpc_service_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 Metadata.ProtoReflect.Descriptor instead.
|
||||
func (*Metadata) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f908b146bdb05ce9, []int{0}
|
||||
return file_api_proto_nacos_grpc_service_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (m *Metadata) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Metadata.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Metadata) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Metadata.Merge(m, src)
|
||||
}
|
||||
func (m *Metadata) XXX_Size() int {
|
||||
return xxx_messageInfo_Metadata.Size(m)
|
||||
}
|
||||
func (m *Metadata) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Metadata.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Metadata proto.InternalMessageInfo
|
||||
|
||||
func (m *Metadata) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
func (x *Metadata) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetClientIp() string {
|
||||
if m != nil {
|
||||
return m.ClientIp
|
||||
func (x *Metadata) GetClientIp() string {
|
||||
if x != nil {
|
||||
return x.ClientIp
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetHeaders() map[string]string {
|
||||
if m != nil {
|
||||
return m.Headers
|
||||
func (x *Metadata) GetHeaders() map[string]string {
|
||||
if x != nil {
|
||||
return x.Headers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Payload struct {
|
||||
Metadata *Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
Body *any.Any `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Metadata *Metadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"`
|
||||
Body *anypb.Any `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (m *Payload) Reset() { *m = Payload{} }
|
||||
func (m *Payload) String() string { return proto.CompactTextString(m) }
|
||||
func (*Payload) ProtoMessage() {}
|
||||
func (x *Payload) Reset() {
|
||||
*x = Payload{}
|
||||
mi := &file_api_proto_nacos_grpc_service_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Payload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Payload) ProtoMessage() {}
|
||||
|
||||
func (x *Payload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_nacos_grpc_service_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 Payload.ProtoReflect.Descriptor instead.
|
||||
func (*Payload) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f908b146bdb05ce9, []int{1}
|
||||
return file_api_proto_nacos_grpc_service_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (m *Payload) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Payload.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Payload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Payload.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Payload) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Payload.Merge(m, src)
|
||||
}
|
||||
func (m *Payload) XXX_Size() int {
|
||||
return xxx_messageInfo_Payload.Size(m)
|
||||
}
|
||||
func (m *Payload) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Payload.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Payload proto.InternalMessageInfo
|
||||
|
||||
func (m *Payload) GetMetadata() *Metadata {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
func (x *Payload) GetMetadata() *Metadata {
|
||||
if x != nil {
|
||||
return x.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Payload) GetBody() *any.Any {
|
||||
if m != nil {
|
||||
return m.Body
|
||||
func (x *Payload) GetBody() *anypb.Any {
|
||||
if x != nil {
|
||||
return x.Body
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Metadata)(nil), "Metadata")
|
||||
proto.RegisterMapType((map[string]string)(nil), "Metadata.HeadersEntry")
|
||||
proto.RegisterType((*Payload)(nil), "Payload")
|
||||
var File_api_proto_nacos_grpc_service_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_nacos_grpc_service_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\"api/proto/nacos_grpc_service.proto\x1a\x19google/protobuf/any.proto\"\xa8\x01\n" +
|
||||
"\bMetadata\x12\x12\n" +
|
||||
"\x04type\x18\x03 \x01(\tR\x04type\x12\x1a\n" +
|
||||
"\bclientIp\x18\b \x01(\tR\bclientIp\x120\n" +
|
||||
"\aheaders\x18\a \x03(\v2\x16.Metadata.HeadersEntryR\aheaders\x1a:\n" +
|
||||
"\fHeadersEntry\x12\x10\n" +
|
||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"Z\n" +
|
||||
"\aPayload\x12%\n" +
|
||||
"\bmetadata\x18\x02 \x01(\v2\t.MetadataR\bmetadata\x12(\n" +
|
||||
"\x04body\x18\x03 \x01(\v2\x14.google.protobuf.AnyR\x04body28\n" +
|
||||
"\rRequestStream\x12'\n" +
|
||||
"\rrequestStream\x12\b.Payload\x1a\b.Payload\"\x000\x012*\n" +
|
||||
"\aRequest\x12\x1f\n" +
|
||||
"\arequest\x12\b.Payload\x1a\b.Payload\"\x002>\n" +
|
||||
"\x0fBiRequestStream\x12+\n" +
|
||||
"\x0frequestBiStream\x12\b.Payload\x1a\b.Payload\"\x00(\x010\x01B^\n" +
|
||||
"\x1fcom.alibaba.nacos.api.grpc.autoP\x01Z9github.com/nacos-group/nacos-sdk-go/v2/api/grpc/auto;autob\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_nacos_grpc_service_proto_rawDescOnce sync.Once
|
||||
file_api_proto_nacos_grpc_service_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_nacos_grpc_service_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_nacos_grpc_service_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_nacos_grpc_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_nacos_grpc_service_proto_rawDesc), len(file_api_proto_nacos_grpc_service_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_nacos_grpc_service_proto_rawDescData
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("nacos_grpc_service.proto", fileDescriptor_f908b146bdb05ce9) }
|
||||
|
||||
var fileDescriptor_f908b146bdb05ce9 = []byte{
|
||||
// 333 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x51, 0x4f, 0x4b, 0xeb, 0x40,
|
||||
0x10, 0x7f, 0xdb, 0xf6, 0xbd, 0xa4, 0xd3, 0x57, 0x2a, 0x4b, 0x91, 0x98, 0x4b, 0x4b, 0x45, 0x0c,
|
||||
0x0a, 0xdb, 0x12, 0x2f, 0xa5, 0x07, 0xc1, 0x82, 0xa0, 0x07, 0xa1, 0xc4, 0x9b, 0x97, 0x32, 0x49,
|
||||
0xd6, 0x1a, 0x4c, 0xb3, 0x71, 0xb3, 0x29, 0xec, 0x37, 0xf2, 0x63, 0x4a, 0x37, 0x69, 0xb0, 0x20,
|
||||
0xde, 0x66, 0x7e, 0x7f, 0xe6, 0xc7, 0xcc, 0x80, 0x93, 0x61, 0x24, 0x8a, 0xf5, 0x46, 0xe6, 0xd1,
|
||||
0xba, 0xe0, 0x72, 0x97, 0x44, 0x9c, 0xe5, 0x52, 0x28, 0xe1, 0x9e, 0x6d, 0x84, 0xd8, 0xa4, 0x7c,
|
||||
0x6a, 0xba, 0xb0, 0x7c, 0x9d, 0x62, 0xa6, 0x2b, 0x6a, 0xf2, 0x49, 0xc0, 0x7e, 0xe2, 0x0a, 0x63,
|
||||
0x54, 0x48, 0x29, 0x74, 0x94, 0xce, 0xb9, 0xd3, 0x1e, 0x13, 0xaf, 0x1b, 0x98, 0x9a, 0xba, 0x60,
|
||||
0x47, 0x69, 0xc2, 0x33, 0xf5, 0x98, 0x3b, 0xb6, 0xc1, 0x9b, 0x9e, 0xce, 0xc0, 0x7a, 0xe3, 0x18,
|
||||
0x73, 0x59, 0x38, 0xd6, 0xb8, 0xed, 0xf5, 0xfc, 0x53, 0x76, 0x98, 0xc5, 0x1e, 0x2a, 0xe2, 0x3e,
|
||||
0x53, 0x52, 0x07, 0x07, 0x99, 0xbb, 0x80, 0xff, 0xdf, 0x09, 0x7a, 0x02, 0xed, 0x77, 0xae, 0x1d,
|
||||
0x62, 0x06, 0xef, 0x4b, 0x3a, 0x84, 0xbf, 0x3b, 0x4c, 0x4b, 0xee, 0xb4, 0x0c, 0x56, 0x35, 0x8b,
|
||||
0xd6, 0x9c, 0x4c, 0x5e, 0xc0, 0x5a, 0xa1, 0x4e, 0x05, 0xc6, 0xf4, 0x02, 0xec, 0x6d, 0x1d, 0x64,
|
||||
0x74, 0x3d, 0xbf, 0xdb, 0x24, 0x07, 0x0d, 0x45, 0x3d, 0xe8, 0x84, 0x22, 0xd6, 0x66, 0x9f, 0x9e,
|
||||
0x3f, 0x64, 0xd5, 0x19, 0xd8, 0xe1, 0x0c, 0xec, 0x2e, 0xd3, 0x81, 0x51, 0xf8, 0x73, 0xe8, 0x07,
|
||||
0xfc, 0xa3, 0xe4, 0x85, 0x7a, 0x56, 0x92, 0xe3, 0x96, 0x5e, 0x42, 0x5f, 0x1e, 0x01, 0x36, 0xab,
|
||||
0xc3, 0xdd, 0xa6, 0x9a, 0xfc, 0x99, 0x11, 0xff, 0x0a, 0xac, 0xda, 0x49, 0x47, 0x60, 0xd5, 0x9e,
|
||||
0x9f, 0xd5, 0xfe, 0x2d, 0x0c, 0x96, 0xc9, 0x71, 0xce, 0x35, 0x0c, 0x6a, 0xcf, 0x32, 0xf9, 0x2d,
|
||||
0xc9, 0x23, 0x33, 0xb2, 0x3c, 0x87, 0x51, 0x24, 0xb6, 0x0c, 0xd3, 0x24, 0xc4, 0x10, 0x99, 0xf9,
|
||||
0x37, 0xc3, 0x3c, 0x61, 0xfb, 0x9f, 0x33, 0x2c, 0x95, 0x58, 0x91, 0xf0, 0x9f, 0x59, 0xef, 0xe6,
|
||||
0x2b, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x9e, 0xc7, 0x2d, 0x0f, 0x02, 0x00, 0x00,
|
||||
var file_api_proto_nacos_grpc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_api_proto_nacos_grpc_service_proto_goTypes = []any{
|
||||
(*Metadata)(nil), // 0: Metadata
|
||||
(*Payload)(nil), // 1: Payload
|
||||
nil, // 2: Metadata.HeadersEntry
|
||||
(*anypb.Any)(nil), // 3: google.protobuf.Any
|
||||
}
|
||||
var file_api_proto_nacos_grpc_service_proto_depIdxs = []int32{
|
||||
2, // 0: Metadata.headers:type_name -> Metadata.HeadersEntry
|
||||
0, // 1: Payload.metadata:type_name -> Metadata
|
||||
3, // 2: Payload.body:type_name -> google.protobuf.Any
|
||||
1, // 3: RequestStream.requestStream:input_type -> Payload
|
||||
1, // 4: Request.request:input_type -> Payload
|
||||
1, // 5: BiRequestStream.requestBiStream:input_type -> Payload
|
||||
1, // 6: RequestStream.requestStream:output_type -> Payload
|
||||
1, // 7: Request.request:output_type -> Payload
|
||||
1, // 8: BiRequestStream.requestBiStream:output_type -> Payload
|
||||
6, // [6:9] is the sub-list for method output_type
|
||||
3, // [3:6] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// RequestStreamClient is the client API for RequestStream service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type RequestStreamClient interface {
|
||||
// build a streamRequest
|
||||
RequestStream(ctx context.Context, in *Payload, opts ...grpc.CallOption) (RequestStream_RequestStreamClient, error)
|
||||
}
|
||||
|
||||
type requestStreamClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewRequestStreamClient(cc *grpc.ClientConn) RequestStreamClient {
|
||||
return &requestStreamClient{cc}
|
||||
}
|
||||
|
||||
func (c *requestStreamClient) RequestStream(ctx context.Context, in *Payload, opts ...grpc.CallOption) (RequestStream_RequestStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_RequestStream_serviceDesc.Streams[0], "/RequestStream/requestStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func init() { file_api_proto_nacos_grpc_service_proto_init() }
|
||||
func file_api_proto_nacos_grpc_service_proto_init() {
|
||||
if File_api_proto_nacos_grpc_service_proto != nil {
|
||||
return
|
||||
}
|
||||
x := &requestStreamRequestStreamClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type RequestStream_RequestStreamClient interface {
|
||||
Recv() (*Payload, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type requestStreamRequestStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *requestStreamRequestStreamClient) Recv() (*Payload, error) {
|
||||
m := new(Payload)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// RequestStreamServer is the server API for RequestStream service.
|
||||
type RequestStreamServer interface {
|
||||
// build a streamRequest
|
||||
RequestStream(*Payload, RequestStream_RequestStreamServer) error
|
||||
}
|
||||
|
||||
// UnimplementedRequestStreamServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedRequestStreamServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedRequestStreamServer) RequestStream(req *Payload, srv RequestStream_RequestStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method RequestStream not implemented")
|
||||
}
|
||||
|
||||
func RegisterRequestStreamServer(s *grpc.Server, srv RequestStreamServer) {
|
||||
s.RegisterService(&_RequestStream_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _RequestStream_RequestStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(Payload)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(RequestStreamServer).RequestStream(m, &requestStreamRequestStreamServer{stream})
|
||||
}
|
||||
|
||||
type RequestStream_RequestStreamServer interface {
|
||||
Send(*Payload) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type requestStreamRequestStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *requestStreamRequestStreamServer) Send(m *Payload) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
var _RequestStream_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "RequestStream",
|
||||
HandlerType: (*RequestStreamServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "requestStream",
|
||||
Handler: _RequestStream_RequestStream_Handler,
|
||||
ServerStreams: true,
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_nacos_grpc_service_proto_rawDesc), len(file_api_proto_nacos_grpc_service_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 3,
|
||||
},
|
||||
},
|
||||
Metadata: "nacos_grpc_service.proto",
|
||||
}
|
||||
|
||||
// RequestClient is the client API for Request service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type RequestClient interface {
|
||||
// Sends a commonRequest
|
||||
Request(ctx context.Context, in *Payload, opts ...grpc.CallOption) (*Payload, error)
|
||||
}
|
||||
|
||||
type requestClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewRequestClient(cc *grpc.ClientConn) RequestClient {
|
||||
return &requestClient{cc}
|
||||
}
|
||||
|
||||
func (c *requestClient) Request(ctx context.Context, in *Payload, opts ...grpc.CallOption) (*Payload, error) {
|
||||
out := new(Payload)
|
||||
err := c.cc.Invoke(ctx, "/Request/request", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// RequestServer is the server API for Request service.
|
||||
type RequestServer interface {
|
||||
// Sends a commonRequest
|
||||
Request(context.Context, *Payload) (*Payload, error)
|
||||
}
|
||||
|
||||
// UnimplementedRequestServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedRequestServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedRequestServer) Request(ctx context.Context, req *Payload) (*Payload, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Request not implemented")
|
||||
}
|
||||
|
||||
func RegisterRequestServer(s *grpc.Server, srv RequestServer) {
|
||||
s.RegisterService(&_Request_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Request_Request_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Payload)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServer).Request(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Request/Request",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServer).Request(ctx, req.(*Payload))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Request_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Request",
|
||||
HandlerType: (*RequestServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "request",
|
||||
Handler: _Request_Request_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "nacos_grpc_service.proto",
|
||||
}
|
||||
|
||||
// BiRequestStreamClient is the client API for BiRequestStream service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type BiRequestStreamClient interface {
|
||||
// Sends a commonRequest
|
||||
RequestBiStream(ctx context.Context, opts ...grpc.CallOption) (BiRequestStream_RequestBiStreamClient, error)
|
||||
}
|
||||
|
||||
type biRequestStreamClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewBiRequestStreamClient(cc *grpc.ClientConn) BiRequestStreamClient {
|
||||
return &biRequestStreamClient{cc}
|
||||
}
|
||||
|
||||
func (c *biRequestStreamClient) RequestBiStream(ctx context.Context, opts ...grpc.CallOption) (BiRequestStream_RequestBiStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_BiRequestStream_serviceDesc.Streams[0], "/BiRequestStream/requestBiStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &biRequestStreamRequestBiStreamClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type BiRequestStream_RequestBiStreamClient interface {
|
||||
Send(*Payload) error
|
||||
Recv() (*Payload, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type biRequestStreamRequestBiStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *biRequestStreamRequestBiStreamClient) Send(m *Payload) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *biRequestStreamRequestBiStreamClient) Recv() (*Payload, error) {
|
||||
m := new(Payload)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// BiRequestStreamServer is the server API for BiRequestStream service.
|
||||
type BiRequestStreamServer interface {
|
||||
// Sends a commonRequest
|
||||
RequestBiStream(BiRequestStream_RequestBiStreamServer) error
|
||||
}
|
||||
|
||||
// UnimplementedBiRequestStreamServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedBiRequestStreamServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedBiRequestStreamServer) RequestBiStream(srv BiRequestStream_RequestBiStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method RequestBiStream not implemented")
|
||||
}
|
||||
|
||||
func RegisterBiRequestStreamServer(s *grpc.Server, srv BiRequestStreamServer) {
|
||||
s.RegisterService(&_BiRequestStream_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _BiRequestStream_RequestBiStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(BiRequestStreamServer).RequestBiStream(&biRequestStreamRequestBiStreamServer{stream})
|
||||
}
|
||||
|
||||
type BiRequestStream_RequestBiStreamServer interface {
|
||||
Send(*Payload) error
|
||||
Recv() (*Payload, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type biRequestStreamRequestBiStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *biRequestStreamRequestBiStreamServer) Send(m *Payload) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *biRequestStreamRequestBiStreamServer) Recv() (*Payload, error) {
|
||||
m := new(Payload)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _BiRequestStream_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "BiRequestStream",
|
||||
HandlerType: (*BiRequestStreamServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "requestBiStream",
|
||||
Handler: _BiRequestStream_RequestBiStream_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "nacos_grpc_service.proto",
|
||||
GoTypes: file_api_proto_nacos_grpc_service_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_nacos_grpc_service_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_nacos_grpc_service_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_nacos_grpc_service_proto = out.File
|
||||
file_api_proto_nacos_grpc_service_proto_goTypes = nil
|
||||
file_api_proto_nacos_grpc_service_proto_depIdxs = nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
//
|
||||
// Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/nacos_grpc_service.proto
|
||||
|
||||
package auto
|
||||
|
||||
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 (
|
||||
RequestStream_RequestStream_FullMethodName = "/RequestStream/requestStream"
|
||||
)
|
||||
|
||||
// RequestStreamClient is the client API for RequestStream 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 RequestStreamClient interface {
|
||||
// build a streamRequest
|
||||
RequestStream(ctx context.Context, in *Payload, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Payload], error)
|
||||
}
|
||||
|
||||
type requestStreamClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewRequestStreamClient(cc grpc.ClientConnInterface) RequestStreamClient {
|
||||
return &requestStreamClient{cc}
|
||||
}
|
||||
|
||||
func (c *requestStreamClient) RequestStream(ctx context.Context, in *Payload, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Payload], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &RequestStream_ServiceDesc.Streams[0], RequestStream_RequestStream_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[Payload, Payload]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type RequestStream_RequestStreamClient = grpc.ServerStreamingClient[Payload]
|
||||
|
||||
// RequestStreamServer is the server API for RequestStream service.
|
||||
// All implementations must embed UnimplementedRequestStreamServer
|
||||
// for forward compatibility.
|
||||
type RequestStreamServer interface {
|
||||
// build a streamRequest
|
||||
RequestStream(*Payload, grpc.ServerStreamingServer[Payload]) error
|
||||
mustEmbedUnimplementedRequestStreamServer()
|
||||
}
|
||||
|
||||
// UnimplementedRequestStreamServer 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 UnimplementedRequestStreamServer struct{}
|
||||
|
||||
func (UnimplementedRequestStreamServer) RequestStream(*Payload, grpc.ServerStreamingServer[Payload]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method RequestStream not implemented")
|
||||
}
|
||||
func (UnimplementedRequestStreamServer) mustEmbedUnimplementedRequestStreamServer() {}
|
||||
func (UnimplementedRequestStreamServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeRequestStreamServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to RequestStreamServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeRequestStreamServer interface {
|
||||
mustEmbedUnimplementedRequestStreamServer()
|
||||
}
|
||||
|
||||
func RegisterRequestStreamServer(s grpc.ServiceRegistrar, srv RequestStreamServer) {
|
||||
// If the following call pancis, it indicates UnimplementedRequestStreamServer 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(&RequestStream_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _RequestStream_RequestStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(Payload)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(RequestStreamServer).RequestStream(m, &grpc.GenericServerStream[Payload, Payload]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type RequestStream_RequestStreamServer = grpc.ServerStreamingServer[Payload]
|
||||
|
||||
// RequestStream_ServiceDesc is the grpc.ServiceDesc for RequestStream service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var RequestStream_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "RequestStream",
|
||||
HandlerType: (*RequestStreamServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "requestStream",
|
||||
Handler: _RequestStream_RequestStream_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "api/proto/nacos_grpc_service.proto",
|
||||
}
|
||||
|
||||
const (
|
||||
Request_Request_FullMethodName = "/Request/request"
|
||||
)
|
||||
|
||||
// RequestClient is the client API for Request 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 RequestClient interface {
|
||||
// Sends a commonRequest
|
||||
Request(ctx context.Context, in *Payload, opts ...grpc.CallOption) (*Payload, error)
|
||||
}
|
||||
|
||||
type requestClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewRequestClient(cc grpc.ClientConnInterface) RequestClient {
|
||||
return &requestClient{cc}
|
||||
}
|
||||
|
||||
func (c *requestClient) Request(ctx context.Context, in *Payload, opts ...grpc.CallOption) (*Payload, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(Payload)
|
||||
err := c.cc.Invoke(ctx, Request_Request_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// RequestServer is the server API for Request service.
|
||||
// All implementations must embed UnimplementedRequestServer
|
||||
// for forward compatibility.
|
||||
type RequestServer interface {
|
||||
// Sends a commonRequest
|
||||
Request(context.Context, *Payload) (*Payload, error)
|
||||
mustEmbedUnimplementedRequestServer()
|
||||
}
|
||||
|
||||
// UnimplementedRequestServer 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 UnimplementedRequestServer struct{}
|
||||
|
||||
func (UnimplementedRequestServer) Request(context.Context, *Payload) (*Payload, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Request not implemented")
|
||||
}
|
||||
func (UnimplementedRequestServer) mustEmbedUnimplementedRequestServer() {}
|
||||
func (UnimplementedRequestServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeRequestServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to RequestServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeRequestServer interface {
|
||||
mustEmbedUnimplementedRequestServer()
|
||||
}
|
||||
|
||||
func RegisterRequestServer(s grpc.ServiceRegistrar, srv RequestServer) {
|
||||
// If the following call pancis, it indicates UnimplementedRequestServer 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(&Request_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Request_Request_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Payload)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServer).Request(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Request_Request_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServer).Request(ctx, req.(*Payload))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Request_ServiceDesc is the grpc.ServiceDesc for Request service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Request_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Request",
|
||||
HandlerType: (*RequestServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "request",
|
||||
Handler: _Request_Request_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/nacos_grpc_service.proto",
|
||||
}
|
||||
|
||||
const (
|
||||
BiRequestStream_RequestBiStream_FullMethodName = "/BiRequestStream/requestBiStream"
|
||||
)
|
||||
|
||||
// BiRequestStreamClient is the client API for BiRequestStream 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 BiRequestStreamClient interface {
|
||||
// Sends a commonRequest
|
||||
RequestBiStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Payload, Payload], error)
|
||||
}
|
||||
|
||||
type biRequestStreamClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewBiRequestStreamClient(cc grpc.ClientConnInterface) BiRequestStreamClient {
|
||||
return &biRequestStreamClient{cc}
|
||||
}
|
||||
|
||||
func (c *biRequestStreamClient) RequestBiStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Payload, Payload], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &BiRequestStream_ServiceDesc.Streams[0], BiRequestStream_RequestBiStream_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[Payload, Payload]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type BiRequestStream_RequestBiStreamClient = grpc.BidiStreamingClient[Payload, Payload]
|
||||
|
||||
// BiRequestStreamServer is the server API for BiRequestStream service.
|
||||
// All implementations must embed UnimplementedBiRequestStreamServer
|
||||
// for forward compatibility.
|
||||
type BiRequestStreamServer interface {
|
||||
// Sends a commonRequest
|
||||
RequestBiStream(grpc.BidiStreamingServer[Payload, Payload]) error
|
||||
mustEmbedUnimplementedBiRequestStreamServer()
|
||||
}
|
||||
|
||||
// UnimplementedBiRequestStreamServer 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 UnimplementedBiRequestStreamServer struct{}
|
||||
|
||||
func (UnimplementedBiRequestStreamServer) RequestBiStream(grpc.BidiStreamingServer[Payload, Payload]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method RequestBiStream not implemented")
|
||||
}
|
||||
func (UnimplementedBiRequestStreamServer) mustEmbedUnimplementedBiRequestStreamServer() {}
|
||||
func (UnimplementedBiRequestStreamServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeBiRequestStreamServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to BiRequestStreamServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeBiRequestStreamServer interface {
|
||||
mustEmbedUnimplementedBiRequestStreamServer()
|
||||
}
|
||||
|
||||
func RegisterBiRequestStreamServer(s grpc.ServiceRegistrar, srv BiRequestStreamServer) {
|
||||
// If the following call pancis, it indicates UnimplementedBiRequestStreamServer 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(&BiRequestStream_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _BiRequestStream_RequestBiStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(BiRequestStreamServer).RequestBiStream(&grpc.GenericServerStream[Payload, Payload]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type BiRequestStream_RequestBiStreamServer = grpc.BidiStreamingServer[Payload, Payload]
|
||||
|
||||
// BiRequestStream_ServiceDesc is the grpc.ServiceDesc for BiRequestStream service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var BiRequestStream_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "BiRequestStream",
|
||||
HandlerType: (*BiRequestStreamServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "requestBiStream",
|
||||
Handler: _BiRequestStream_RequestBiStream_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "api/proto/nacos_grpc_service.proto",
|
||||
}
|
|
@ -21,6 +21,8 @@ import "google/protobuf/any.proto";
|
|||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.alibaba.nacos.api.grpc.auto";
|
||||
option go_package = "github.com/nacos-group/nacos-sdk-go/v2/api/grpc/auto;auto";
|
||||
|
||||
|
||||
message Metadata {
|
||||
string type = 3;
|
||||
|
|
|
@ -296,7 +296,7 @@ func (m ConcurrentMap) Keys() []string {
|
|||
return keys
|
||||
}
|
||||
|
||||
//Reviles ConcurrentMap "private" variables to json marshal.
|
||||
// Reviles ConcurrentMap "private" variables to json marshal.
|
||||
func (m ConcurrentMap) MarshalJSON() ([]byte, error) {
|
||||
// Create a temporary map, which will hold all item spread across shards.
|
||||
tmp := make(map[string]interface{})
|
||||
|
|
|
@ -45,7 +45,7 @@ func NewConfigClient(param vo.NacosClientParam) (iClient config_client.IConfigCl
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
config, err := config_client.NewConfigClient(nacosClient)
|
||||
config, err := config_client.NewConfigClientWithRamCredentialProvider(nacosClient, param.RamCredentialProvider)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func NewNamingClient(param vo.NacosClientParam) (iClient naming_client.INamingCl
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
naming, err := naming_client.NewNamingClient(nacosClient)
|
||||
naming, err := naming_client.NewNamingClientWithRamCredentialProvider(nacosClient, param.RamCredentialProvider)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package config_client
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -59,6 +60,7 @@ type ConfigClient struct {
|
|||
cacheMap cache.ConcurrentMap
|
||||
uid string
|
||||
listenExecute chan struct{}
|
||||
isClosed bool
|
||||
}
|
||||
|
||||
type cacheData struct {
|
||||
|
@ -101,7 +103,7 @@ func (cacheData *cacheData) executeListener() {
|
|||
go cacheData.cacheDataListener.listener(cacheData.tenant, cacheData.group, cacheData.dataId, decryptedContent)
|
||||
}
|
||||
|
||||
func NewConfigClient(nc nacos_client.INacosClient) (*ConfigClient, error) {
|
||||
func NewConfigClientWithRamCredentialProvider(nc nacos_client.INacosClient, provider security.RamCredentialProvider) (*ConfigClient, error) {
|
||||
config := &ConfigClient{}
|
||||
config.ctx, config.cancel = context.WithCancel(context.Background())
|
||||
config.INacosClient = nc
|
||||
|
@ -124,7 +126,7 @@ func NewConfigClient(nc nacos_client.INacosClient) (*ConfigClient, error) {
|
|||
clientConfig.CacheDir = clientConfig.CacheDir + string(os.PathSeparator) + "config"
|
||||
config.configCacheDir = clientConfig.CacheDir
|
||||
|
||||
if config.configProxy, err = NewConfigProxy(config.ctx, serverConfig, clientConfig, httpAgent); err != nil {
|
||||
if config.configProxy, err = NewConfigProxyWithRamCredentialProvider(config.ctx, serverConfig, clientConfig, httpAgent, provider); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -152,6 +154,10 @@ func NewConfigClient(nc nacos_client.INacosClient) (*ConfigClient, error) {
|
|||
return config, err
|
||||
}
|
||||
|
||||
func NewConfigClient(nc nacos_client.INacosClient) (*ConfigClient, error) {
|
||||
return NewConfigClientWithRamCredentialProvider(nc, nil)
|
||||
}
|
||||
|
||||
func initLogger(clientConfig constant.ClientConfig) error {
|
||||
return logger.InitLogger(logger.BuildLoggerConfig(clientConfig))
|
||||
}
|
||||
|
@ -247,6 +253,7 @@ func (client *ConfigClient) PublishConfig(param vo.ConfigParam) (published bool,
|
|||
clientConfig, _ := client.GetClientConfig()
|
||||
request := rpc_request.NewConfigPublishRequest(param.Group, param.DataId, clientConfig.NamespaceId, param.Content, param.CasMd5)
|
||||
request.AdditionMap["tag"] = param.Tag
|
||||
request.AdditionMap["config_tags"] = param.ConfigTags
|
||||
request.AdditionMap["appName"] = param.AppName
|
||||
request.AdditionMap["betaIps"] = param.BetaIps
|
||||
request.AdditionMap["type"] = param.Type
|
||||
|
@ -358,8 +365,15 @@ func (client *ConfigClient) SearchConfig(param vo.SearchConfigParam) (*model.Con
|
|||
}
|
||||
|
||||
func (client *ConfigClient) CloseClient() {
|
||||
client.mutex.Lock()
|
||||
defer client.mutex.Unlock()
|
||||
|
||||
if client.isClosed {
|
||||
return
|
||||
}
|
||||
client.configProxy.getRpcClient(client).Shutdown()
|
||||
client.cancel()
|
||||
client.isClosed = true
|
||||
}
|
||||
|
||||
func (client *ConfigClient) searchConfigInner(param vo.SearchConfigParam) (*model.ConfigPage, error) {
|
||||
|
|
|
@ -19,6 +19,7 @@ package config_client
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
"testing"
|
||||
|
||||
|
@ -356,3 +357,55 @@ func TestCancelListenConfig(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
type MockAccessKeyCredentialProvider struct {
|
||||
accessKey string
|
||||
secretKey string
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *MockAccessKeyCredentialProvider) MatchProvider() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (provider *MockAccessKeyCredentialProvider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *MockAccessKeyCredentialProvider) GetCredentialsForNacosClient() security.RamContext {
|
||||
ramContext := security.RamContext{
|
||||
AccessKey: provider.accessKey,
|
||||
SecretKey: provider.secretKey,
|
||||
SignatureRegionId: "",
|
||||
}
|
||||
return ramContext
|
||||
}
|
||||
|
||||
func Test_ConfigClientWithProvider(t *testing.T) {
|
||||
nc := nacos_client.NacosClient{}
|
||||
_ = nc.SetServerConfig([]constant.ServerConfig{*serverConfigWithOptions})
|
||||
clientConfigWithOptions.AccessKey = ""
|
||||
clientConfigWithOptions.SecretKey = ""
|
||||
_ = nc.SetClientConfig(*clientConfigWithOptions)
|
||||
_ = nc.SetHttpAgent(&http_agent.HttpAgent{})
|
||||
provider := &MockAccessKeyCredentialProvider{
|
||||
accessKey: "LTAxxx",
|
||||
secretKey: "EdPxxx",
|
||||
}
|
||||
client, _ := NewConfigClientWithRamCredentialProvider(&nc, provider)
|
||||
client.configProxy = &MockConfigProxy{}
|
||||
success, err := client.PublishConfig(vo.ConfigParam{
|
||||
DataId: localConfigTest.DataId,
|
||||
Group: localConfigTest.Group,
|
||||
Content: "hello world"})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, success)
|
||||
|
||||
content, err := client.GetConfig(vo.ConfigParam{
|
||||
DataId: localConfigTest.DataId,
|
||||
Group: localConfigTest.Group})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "hello world", content)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package config_client
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
)
|
||||
|
||||
type ConfigConnectionEventListener struct {
|
||||
client *ConfigClient
|
||||
taskId string
|
||||
}
|
||||
|
||||
func NewConfigConnectionEventListener(client *ConfigClient, taskId string) *ConfigConnectionEventListener {
|
||||
return &ConfigConnectionEventListener{
|
||||
client: client,
|
||||
taskId: taskId,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConfigConnectionEventListener) OnConnected() {
|
||||
logger.Info("[ConfigConnectionEventListener] connect to config server for taskId: " + c.taskId)
|
||||
if c.client != nil {
|
||||
c.client.asyncNotifyListenConfig()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConfigConnectionEventListener) OnDisConnect() {
|
||||
logger.Info("[ConfigConnectionEventListener] disconnect from config server for taskId: " + c.taskId)
|
||||
|
||||
if c.client != nil {
|
||||
taskIdInt, err := strconv.Atoi(c.taskId)
|
||||
if err != nil {
|
||||
logger.Errorf("[ConfigConnectionEventListener] parse taskId error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
items := c.client.cacheMap.Items()
|
||||
for key, v := range items {
|
||||
if data, ok := v.(cacheData); ok {
|
||||
if data.taskId == taskIdInt {
|
||||
data.isSyncWithServer = false
|
||||
c.client.cacheMap.Set(key, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package config_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/cache"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_response"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewConfigConnectionEventListener(t *testing.T) {
|
||||
client := &ConfigClient{}
|
||||
taskId := "123"
|
||||
|
||||
listener := NewConfigConnectionEventListener(client, taskId)
|
||||
|
||||
assert.Equal(t, client, listener.client)
|
||||
assert.Equal(t, taskId, listener.taskId)
|
||||
}
|
||||
|
||||
func TestOnDisConnectWithMock(t *testing.T) {
|
||||
client := &ConfigClient{
|
||||
cacheMap: cache.NewConcurrentMap(),
|
||||
}
|
||||
|
||||
data1 := cacheData{
|
||||
dataId: "dataId1",
|
||||
group: "group1",
|
||||
tenant: "",
|
||||
taskId: 1,
|
||||
isSyncWithServer: true,
|
||||
}
|
||||
|
||||
data2 := cacheData{
|
||||
dataId: "dataId2",
|
||||
group: "group1",
|
||||
tenant: "",
|
||||
taskId: 1,
|
||||
isSyncWithServer: true,
|
||||
}
|
||||
|
||||
data3 := cacheData{
|
||||
dataId: "dataId3",
|
||||
group: "group2",
|
||||
tenant: "",
|
||||
taskId: 2,
|
||||
isSyncWithServer: true,
|
||||
}
|
||||
|
||||
key1 := util.GetConfigCacheKey(data1.dataId, data1.group, data1.tenant)
|
||||
key2 := util.GetConfigCacheKey(data2.dataId, data2.group, data2.tenant)
|
||||
key3 := util.GetConfigCacheKey(data3.dataId, data3.group, data3.tenant)
|
||||
|
||||
client.cacheMap.Set(key1, data1)
|
||||
client.cacheMap.Set(key2, data2)
|
||||
client.cacheMap.Set(key3, data3)
|
||||
|
||||
listener := NewConfigConnectionEventListener(client, "1")
|
||||
|
||||
listener.OnDisConnect()
|
||||
|
||||
item1, _ := client.cacheMap.Get(key1)
|
||||
item2, _ := client.cacheMap.Get(key2)
|
||||
item3, _ := client.cacheMap.Get(key3)
|
||||
|
||||
updatedData1 := item1.(cacheData)
|
||||
updatedData2 := item2.(cacheData)
|
||||
updatedData3 := item3.(cacheData)
|
||||
|
||||
assert.False(t, updatedData1.isSyncWithServer, "dataId1 should be marked as not sync")
|
||||
assert.False(t, updatedData2.isSyncWithServer, "dataId2 should be marked as not sync")
|
||||
assert.True(t, updatedData3.isSyncWithServer, "dataId3 should be marked as sync")
|
||||
}
|
||||
|
||||
func TestOnConnectedWithMock(t *testing.T) {
|
||||
listenChan := make(chan struct{}, 1)
|
||||
|
||||
client := &ConfigClient{
|
||||
listenExecute: listenChan,
|
||||
}
|
||||
|
||||
listener := NewConfigConnectionEventListener(client, "1")
|
||||
|
||||
listener.OnConnected()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
select {
|
||||
case <-listenChan:
|
||||
assert.True(t, true, "asyncNotifyListenConfig should be called")
|
||||
default:
|
||||
t.Fatalf("asyncNotifyListenConfig should be called but not")
|
||||
}
|
||||
}
|
||||
|
||||
type MockRpcClientForListener struct {
|
||||
requestCalled rpc_request.IRequest
|
||||
}
|
||||
|
||||
func (m *MockRpcClientForListener) Request(request rpc_request.IRequest) (rpc_response.IResponse, error) {
|
||||
m.requestCalled = request
|
||||
return &rpc_response.ConfigChangeBatchListenResponse{
|
||||
Response: &rpc_response.Response{
|
||||
ResultCode: 200,
|
||||
},
|
||||
ChangedConfigs: []model.ConfigContext{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestReconnectionFlow(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
mockRpc := &MockRpcClientForListener{}
|
||||
|
||||
listenChan := make(chan struct{}, 1)
|
||||
|
||||
client := &ConfigClient{
|
||||
ctx: ctx,
|
||||
configProxy: &MockConfigProxy{},
|
||||
cacheMap: cache.NewConcurrentMap(),
|
||||
listenExecute: listenChan,
|
||||
}
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-listenChan:
|
||||
mockRpc.Request(&rpc_request.ConfigBatchListenRequest{})
|
||||
done <- true
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
data1 := cacheData{
|
||||
dataId: "dataId1",
|
||||
group: "group1",
|
||||
tenant: "",
|
||||
taskId: 1,
|
||||
isSyncWithServer: true,
|
||||
}
|
||||
|
||||
key1 := util.GetConfigCacheKey(data1.dataId, data1.group, data1.tenant)
|
||||
client.cacheMap.Set(key1, data1)
|
||||
|
||||
listener := NewConfigConnectionEventListener(client, "1")
|
||||
|
||||
initialData, _ := client.cacheMap.Get(key1)
|
||||
assert.True(t, initialData.(cacheData).isSyncWithServer, "initial data should be sync with server")
|
||||
|
||||
listener.OnDisConnect()
|
||||
|
||||
afterDisconnectData, _ := client.cacheMap.Get(key1)
|
||||
assert.False(t, afterDisconnectData.(cacheData).isSyncWithServer, "disconnect should set isSyncWithServer to false")
|
||||
|
||||
listener.OnConnected()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatalf("wait for done timeout")
|
||||
}
|
||||
|
||||
assert.NotNil(t, mockRpc.requestCalled, "should call request")
|
||||
|
||||
_, ok := mockRpc.requestCalled.(*rpc_request.ConfigBatchListenRequest)
|
||||
assert.True(t, ok, "should be a ConfigBatchListenRequest")
|
||||
}
|
|
@ -23,22 +23,20 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/monitor"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_response"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/cache"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/monitor"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/nacos_server"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_response"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/vo"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ConfigProxy struct {
|
||||
|
@ -47,20 +45,21 @@ type ConfigProxy struct {
|
|||
}
|
||||
|
||||
func NewConfigProxy(ctx context.Context, serverConfig []constant.ServerConfig, clientConfig constant.ClientConfig, httpAgent http_agent.IHttpAgent) (IConfigProxy, error) {
|
||||
return NewConfigProxyWithRamCredentialProvider(ctx, serverConfig, clientConfig, httpAgent, nil)
|
||||
}
|
||||
|
||||
func NewConfigProxyWithRamCredentialProvider(ctx context.Context, serverConfig []constant.ServerConfig, clientConfig constant.ClientConfig, httpAgent http_agent.IHttpAgent, provider security.RamCredentialProvider) (IConfigProxy, error) {
|
||||
proxy := ConfigProxy{}
|
||||
var err error
|
||||
proxy.nacosServer, err = nacos_server.NewNacosServer(ctx, serverConfig, clientConfig, httpAgent, clientConfig.TimeoutMs, clientConfig.Endpoint, nil)
|
||||
proxy.nacosServer, err = nacos_server.NewNacosServerWithRamCredentialProvider(ctx, serverConfig, clientConfig, httpAgent, clientConfig.TimeoutMs, clientConfig.Endpoint, nil, provider)
|
||||
proxy.clientConfig = clientConfig
|
||||
return &proxy, err
|
||||
}
|
||||
|
||||
func (cp *ConfigProxy) requestProxy(rpcClient *rpc.RpcClient, request rpc_request.IRequest, timeoutMills uint64) (rpc_response.IResponse, error) {
|
||||
start := time.Now()
|
||||
cp.nacosServer.InjectSecurityInfo(request.GetHeaders())
|
||||
cp.nacosServer.InjectSecurityInfo(request.GetHeaders(), security.BuildConfigResourceByRequest(request))
|
||||
cp.injectCommHeader(request.GetHeaders())
|
||||
cp.nacosServer.InjectSkAk(request.GetHeaders(), cp.clientConfig)
|
||||
signHeaders := nacos_server.GetSignHeadersFromRequest(request.(rpc_request.IConfigRequest), cp.clientConfig.SecretKey)
|
||||
request.PutAllHeaders(signHeaders)
|
||||
response, err := rpcClient.Request(request, int64(timeoutMills))
|
||||
monitor.GetConfigRequestMonitor(constant.GRPC, request.GetRequestType(), rpc_response.GetGrpcResponseStatusCode(response)).Observe(float64(time.Now().Nanosecond() - start.Nanosecond()))
|
||||
return response, err
|
||||
|
@ -87,14 +86,27 @@ func (cp *ConfigProxy) searchConfigProxy(param vo.SearchConfigParam, tenant, acc
|
|||
params["dataId"] = ""
|
||||
}
|
||||
var headers = map[string]string{}
|
||||
headers["accessKey"] = accessKey
|
||||
headers["secretKey"] = secretKey
|
||||
var version = "v2"
|
||||
result, err := cp.nacosServer.ReqConfigApi(constant.CONFIG_PATH, params, headers, http.MethodGet, cp.clientConfig.TimeoutMs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(tenant) > 0 {
|
||||
params["namespaceId"] = params["tenant"]
|
||||
}
|
||||
params["groupName"] = params["group"]
|
||||
result, err = cp.nacosServer.ReqConfigApi("/v3/admin/cs/config/list", params, headers, http.MethodGet, cp.clientConfig.TimeoutMs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
version = "v3"
|
||||
}
|
||||
var configPage model.ConfigPage
|
||||
err = json.Unmarshal([]byte(result), &configPage)
|
||||
if version == "v2" {
|
||||
err = json.Unmarshal([]byte(result), &configPage)
|
||||
} else {
|
||||
var configPageResult model.ConfigPageResult
|
||||
err = json.Unmarshal([]byte(result), &configPageResult)
|
||||
configPage = configPageResult.Data
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -133,6 +145,7 @@ func (cp *ConfigProxy) queryConfig(dataId, group, tenant string, timeout uint64,
|
|||
if response.GetErrorCode() == 300 {
|
||||
cache.WriteConfigToFile(cacheKey, cp.clientConfig.CacheDir, "")
|
||||
cache.WriteEncryptedDataKeyToFile(cacheKey, cp.clientConfig.CacheDir, "")
|
||||
response.SetSuccess(true)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
@ -173,6 +186,10 @@ func (cp *ConfigProxy) createRpcClient(ctx context.Context, taskId string, clien
|
|||
// TODO fix the group/dataId empty problem
|
||||
return rpc_request.NewConfigChangeNotifyRequest("", "", "")
|
||||
}, &ConfigChangeNotifyRequestHandler{client: client})
|
||||
|
||||
configListener := NewConfigConnectionEventListener(client, taskId)
|
||||
rpcClient.RegisterConnectionListener(configListener)
|
||||
|
||||
rpcClient.Tenant = cp.clientConfig.NamespaceId
|
||||
rpcClient.Start()
|
||||
}
|
||||
|
|
|
@ -115,12 +115,12 @@ func (s *ServiceInfoHolder) GetServiceInfo(serviceName, groupName, clusters stri
|
|||
return model.Service{}, ok
|
||||
}
|
||||
|
||||
func (s *ServiceInfoHolder) RegisterCallback(serviceName string, clusters string, callbackFunc *func(services []model.Instance, err error)) {
|
||||
s.subCallback.AddCallbackFunc(serviceName, clusters, callbackFunc)
|
||||
func (s *ServiceInfoHolder) RegisterCallback(serviceName string, clusters string, callbackWrapper *SubscribeCallbackFuncWrapper) {
|
||||
s.subCallback.AddCallbackFunc(serviceName, clusters, callbackWrapper)
|
||||
}
|
||||
|
||||
func (s *ServiceInfoHolder) DeregisterCallback(serviceName string, clusters string, callbackFunc *func(services []model.Instance, err error)) {
|
||||
s.subCallback.RemoveCallbackFunc(serviceName, clusters, callbackFunc)
|
||||
func (s *ServiceInfoHolder) DeregisterCallback(serviceName string, clusters string, callbackWrapper *SubscribeCallbackFuncWrapper) {
|
||||
s.subCallback.RemoveCallbackFunc(serviceName, clusters, callbackWrapper)
|
||||
}
|
||||
|
||||
func (s *ServiceInfoHolder) StopUpdateIfContain(serviceName, clusters string) {
|
||||
|
|
|
@ -36,31 +36,34 @@ func NewSubscribeCallback() *SubscribeCallback {
|
|||
|
||||
func (ed *SubscribeCallback) IsSubscribed(serviceName, clusters string) bool {
|
||||
key := util.GetServiceCacheKey(serviceName, clusters)
|
||||
_, ok := ed.callbackFuncMap.Get(key)
|
||||
return ok
|
||||
funcs, ok := ed.callbackFuncMap.Get(key)
|
||||
if ok {
|
||||
return len(funcs.([]*SubscribeCallbackFuncWrapper)) > 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ed *SubscribeCallback) AddCallbackFunc(serviceName string, clusters string, callbackFunc *func(services []model.Instance, err error)) {
|
||||
func (ed *SubscribeCallback) AddCallbackFunc(serviceName string, clusters string, callbackWrapper *SubscribeCallbackFuncWrapper) {
|
||||
key := util.GetServiceCacheKey(serviceName, clusters)
|
||||
ed.mux.Lock()
|
||||
defer ed.mux.Unlock()
|
||||
var funcSlice []*func(services []model.Instance, err error)
|
||||
var funcSlice []*SubscribeCallbackFuncWrapper
|
||||
old, ok := ed.callbackFuncMap.Get(key)
|
||||
if ok {
|
||||
funcSlice = append(funcSlice, old.([]*func(services []model.Instance, err error))...)
|
||||
funcSlice = append(funcSlice, old.([]*SubscribeCallbackFuncWrapper)...)
|
||||
}
|
||||
funcSlice = append(funcSlice, callbackFunc)
|
||||
funcSlice = append(funcSlice, callbackWrapper)
|
||||
ed.callbackFuncMap.Set(key, funcSlice)
|
||||
}
|
||||
|
||||
func (ed *SubscribeCallback) RemoveCallbackFunc(serviceName string, clusters string, callbackFunc *func(services []model.Instance, err error)) {
|
||||
func (ed *SubscribeCallback) RemoveCallbackFunc(serviceName string, clusters string, callbackWrapper *SubscribeCallbackFuncWrapper) {
|
||||
logger.Info("removing " + serviceName + " with " + clusters + " to listener map")
|
||||
key := util.GetServiceCacheKey(serviceName, clusters)
|
||||
funcs, ok := ed.callbackFuncMap.Get(key)
|
||||
if ok && funcs != nil {
|
||||
var newFuncs []*func(services []model.Instance, err error)
|
||||
for _, funcItem := range funcs.([]*func(services []model.Instance, err error)) {
|
||||
if funcItem != callbackFunc {
|
||||
var newFuncs []*SubscribeCallbackFuncWrapper
|
||||
for _, funcItem := range funcs.([]*SubscribeCallbackFuncWrapper) {
|
||||
if funcItem.CallbackFunc != callbackWrapper.CallbackFunc || !funcItem.Selector.Equals(callbackWrapper.Selector) {
|
||||
newFuncs = append(newFuncs, funcItem)
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +75,8 @@ func (ed *SubscribeCallback) RemoveCallbackFunc(serviceName string, clusters str
|
|||
func (ed *SubscribeCallback) ServiceChanged(cacheKey string, service *model.Service) {
|
||||
funcs, ok := ed.callbackFuncMap.Get(cacheKey)
|
||||
if ok {
|
||||
for _, funcItem := range funcs.([]*func(services []model.Instance, err error)) {
|
||||
(*funcItem)(service.Hosts, nil)
|
||||
for _, funcItem := range funcs.([]*SubscribeCallbackFuncWrapper) {
|
||||
funcItem.notifyListener(service)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,13 +58,15 @@ func TestEventDispatcher_AddCallbackFuncs(t *testing.T) {
|
|||
fmt.Println(util.ToJsonString(ed.callbackFuncMap))
|
||||
},
|
||||
}
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), ¶m.SubscribeCallback)
|
||||
clusterSelector := NewClusterSelector(param.Clusters)
|
||||
callbackWrapper := NewSubscribeCallbackFuncWrapper(clusterSelector, ¶m.SubscribeCallback)
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), callbackWrapper)
|
||||
key := util.GetServiceCacheKey(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","))
|
||||
for k, v := range ed.callbackFuncMap.Items() {
|
||||
assert.Equal(t, key, k, "key should be equal!")
|
||||
funcs := v.([]*func(services []model.Instance, err error))
|
||||
funcs := v.([]*SubscribeCallbackFuncWrapper)
|
||||
assert.Equal(t, len(funcs), 1)
|
||||
assert.Equal(t, funcs[0], ¶m.SubscribeCallback, "callback function must be equal!")
|
||||
assert.Equal(t, funcs[0].CallbackFunc, ¶m.SubscribeCallback, "callback function must be equal!")
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +100,9 @@ func TestEventDispatcher_RemoveCallbackFuncs(t *testing.T) {
|
|||
fmt.Printf("func1:%s \n", util.ToJsonString(services))
|
||||
},
|
||||
}
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), ¶m.SubscribeCallback)
|
||||
clusterSelector := NewClusterSelector(param.Clusters)
|
||||
callbackWrapper := NewSubscribeCallbackFuncWrapper(clusterSelector, ¶m.SubscribeCallback)
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), callbackWrapper)
|
||||
assert.Equal(t, len(ed.callbackFuncMap.Items()), 1, "callback funcs map length should be 1")
|
||||
|
||||
param2 := vo.SubscribeParam{
|
||||
|
@ -109,21 +113,23 @@ func TestEventDispatcher_RemoveCallbackFuncs(t *testing.T) {
|
|||
fmt.Printf("func2:%s \n", util.ToJsonString(services))
|
||||
},
|
||||
}
|
||||
ed.AddCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), ¶m2.SubscribeCallback)
|
||||
clusterSelector2 := NewClusterSelector(param2.Clusters)
|
||||
callbackWrapper2 := NewSubscribeCallbackFuncWrapper(clusterSelector2, ¶m2.SubscribeCallback)
|
||||
ed.AddCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), callbackWrapper2)
|
||||
assert.Equal(t, len(ed.callbackFuncMap.Items()), 1, "callback funcs map length should be 2")
|
||||
|
||||
for k, v := range ed.callbackFuncMap.Items() {
|
||||
log.Printf("key:%s,%d", k, len(v.([]*func(services []model.Instance, err error))))
|
||||
log.Printf("key:%s,%d", k, len(v.([]*SubscribeCallbackFuncWrapper)))
|
||||
}
|
||||
|
||||
ed.RemoveCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), ¶m2.SubscribeCallback)
|
||||
ed.RemoveCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), callbackWrapper2)
|
||||
|
||||
key := util.GetServiceCacheKey(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","))
|
||||
for k, v := range ed.callbackFuncMap.Items() {
|
||||
assert.Equal(t, key, k, "key should be equal!")
|
||||
funcs := v.([]*func(services []model.Instance, err error))
|
||||
funcs := v.([]*SubscribeCallbackFuncWrapper)
|
||||
assert.Equal(t, len(funcs), 1)
|
||||
assert.Equal(t, funcs[0], ¶m.SubscribeCallback, "callback function must be equal!")
|
||||
assert.Equal(t, funcs[0].CallbackFunc, ¶m.SubscribeCallback, "callback function must be equal!")
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +164,9 @@ func TestSubscribeCallback_ServiceChanged(t *testing.T) {
|
|||
log.Printf("func1:%s \n", util.ToJsonString(services))
|
||||
},
|
||||
}
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), ¶m.SubscribeCallback)
|
||||
clusterSelector := NewClusterSelector(param.Clusters)
|
||||
callbackWrapper := NewSubscribeCallbackFuncWrapper(clusterSelector, ¶m.SubscribeCallback)
|
||||
ed.AddCallbackFunc(util.GetGroupName(param.ServiceName, param.GroupName), strings.Join(param.Clusters, ","), callbackWrapper)
|
||||
|
||||
param2 := vo.SubscribeParam{
|
||||
ServiceName: "Test",
|
||||
|
@ -169,7 +177,54 @@ func TestSubscribeCallback_ServiceChanged(t *testing.T) {
|
|||
|
||||
},
|
||||
}
|
||||
ed.AddCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), ¶m2.SubscribeCallback)
|
||||
clusterSelector2 := NewClusterSelector(param2.Clusters)
|
||||
callbackWrapper2 := NewSubscribeCallbackFuncWrapper(clusterSelector2, ¶m2.SubscribeCallback)
|
||||
ed.AddCallbackFunc(util.GetGroupName(param2.ServiceName, param2.GroupName), strings.Join(param2.Clusters, ","), callbackWrapper2)
|
||||
cacheKey := util.GetServiceCacheKey(util.GetGroupName(service.Name, service.GroupName), service.Clusters)
|
||||
ed.ServiceChanged(cacheKey, &service)
|
||||
}
|
||||
|
||||
func TestSubscribeCallback_RemoveCallbackFunc(t *testing.T) {
|
||||
ed := NewSubscribeCallback()
|
||||
serviceName := "Test"
|
||||
clusters := "default"
|
||||
groupName := "public"
|
||||
|
||||
callback1 := func(services []model.Instance, err error) {
|
||||
log.Printf("callback1:%s \n", util.ToJsonString(services))
|
||||
}
|
||||
clusterSelector1 := NewClusterSelector([]string{clusters})
|
||||
callbackWrapper1 := NewSubscribeCallbackFuncWrapper(clusterSelector1, &callback1)
|
||||
|
||||
callback2 := func(services []model.Instance, err error) {
|
||||
log.Printf("callback2:%s \n", util.ToJsonString(services))
|
||||
}
|
||||
clusterSelector2 := NewClusterSelector([]string{clusters})
|
||||
callbackWrapper2 := NewSubscribeCallbackFuncWrapper(clusterSelector2, &callback2)
|
||||
|
||||
// Add both callbacks
|
||||
ed.AddCallbackFunc(util.GetGroupName(serviceName, groupName), clusters, callbackWrapper1)
|
||||
ed.AddCallbackFunc(util.GetGroupName(serviceName, groupName), clusters, callbackWrapper2)
|
||||
|
||||
assert.True(t, ed.IsSubscribed(util.GetGroupName(serviceName, groupName), clusters))
|
||||
// Remove the first callback
|
||||
ed.RemoveCallbackFunc(util.GetGroupName(serviceName, groupName), clusters, callbackWrapper1)
|
||||
|
||||
// Check if only the second callback remains
|
||||
cacheKey := util.GetServiceCacheKey(util.GetGroupName(serviceName, groupName), clusters)
|
||||
funcs, ok := ed.callbackFuncMap.Get(cacheKey)
|
||||
if !ok || len(funcs.([]*SubscribeCallbackFuncWrapper)) != 1 {
|
||||
t.Errorf("Expected 1 callback function, got %d", len(funcs.([]*SubscribeCallbackFuncWrapper)))
|
||||
}
|
||||
|
||||
assert.True(t, ed.IsSubscribed(util.GetGroupName(serviceName, groupName), clusters))
|
||||
// Remove the second callback
|
||||
ed.RemoveCallbackFunc(util.GetGroupName(serviceName, groupName), clusters, callbackWrapper2)
|
||||
|
||||
// Check if no callbacks remain
|
||||
funcs, ok = ed.callbackFuncMap.Get(cacheKey)
|
||||
if ok && len(funcs.([]*SubscribeCallbackFuncWrapper)) != 0 {
|
||||
t.Errorf("Expected 0 callback functions, got %d", len(funcs.([]*func(services []model.Instance, err error))))
|
||||
}
|
||||
assert.False(t, ed.IsSubscribed(util.GetGroupName(serviceName, groupName), clusters))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package naming_cache
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
)
|
||||
|
||||
type Selector interface {
|
||||
SelectInstance(service *model.Service) []model.Instance
|
||||
Equals(o Selector) bool
|
||||
}
|
||||
|
||||
type ClusterSelector struct {
|
||||
ClusterNames string
|
||||
Clusters []string
|
||||
}
|
||||
|
||||
func NewClusterSelector(clusters []string) *ClusterSelector {
|
||||
if len(clusters) == 0 {
|
||||
return &ClusterSelector{
|
||||
ClusterNames: "",
|
||||
Clusters: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// 创建副本避免外部修改
|
||||
clustersCopy := make([]string, len(clusters))
|
||||
copy(clustersCopy, clusters)
|
||||
|
||||
return &ClusterSelector{
|
||||
ClusterNames: joinCluster(clusters),
|
||||
Clusters: clustersCopy,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSubscribeCallbackFuncWrapper(selector Selector, callback *func(services []model.Instance, err error)) *SubscribeCallbackFuncWrapper {
|
||||
if selector == nil {
|
||||
panic("selector cannot be nil")
|
||||
}
|
||||
|
||||
if callback == nil {
|
||||
panic("callback cannot be nil")
|
||||
}
|
||||
|
||||
return &SubscribeCallbackFuncWrapper{
|
||||
Selector: selector,
|
||||
CallbackFunc: callback,
|
||||
}
|
||||
}
|
||||
|
||||
type SubscribeCallbackFuncWrapper struct {
|
||||
Selector Selector
|
||||
CallbackFunc *func(services []model.Instance, err error)
|
||||
}
|
||||
|
||||
func (ed *SubscribeCallbackFuncWrapper) notifyListener(service *model.Service) {
|
||||
instances := ed.Selector.SelectInstance(service)
|
||||
if ed.CallbackFunc != nil {
|
||||
(*ed.CallbackFunc)(instances, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClusterSelector) SelectInstance(service *model.Service) []model.Instance {
|
||||
var instances []model.Instance
|
||||
if cs.ClusterNames == "" {
|
||||
return service.Hosts
|
||||
}
|
||||
for _, instance := range service.Hosts {
|
||||
if util.Contains(cs.Clusters, instance.ClusterName) {
|
||||
instances = append(instances, instance)
|
||||
}
|
||||
}
|
||||
return instances
|
||||
}
|
||||
|
||||
func (cs *ClusterSelector) Equals(o Selector) bool {
|
||||
if o == nil {
|
||||
return false
|
||||
}
|
||||
if o, ok := o.(*ClusterSelector); ok {
|
||||
return cs.ClusterNames == o.ClusterNames
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func joinCluster(cluster []string) string {
|
||||
// 使用map实现去重
|
||||
uniqueSet := make(map[string]struct{})
|
||||
for _, item := range cluster {
|
||||
if item != "" { // 过滤空字符串,类似Java中的isNotEmpty
|
||||
uniqueSet[item] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
uniqueSlice := make([]string, 0, len(uniqueSet))
|
||||
for item := range uniqueSet {
|
||||
uniqueSlice = append(uniqueSlice, item)
|
||||
}
|
||||
sort.Strings(uniqueSlice)
|
||||
|
||||
// 使用逗号连接
|
||||
return strings.Join(uniqueSlice, ",")
|
||||
}
|
|
@ -21,8 +21,11 @@ import (
|
|||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/nacos_client"
|
||||
|
@ -42,10 +45,17 @@ type NamingClient struct {
|
|||
cancel context.CancelFunc
|
||||
serviceProxy naming_proxy.INamingProxy
|
||||
serviceInfoHolder *naming_cache.ServiceInfoHolder
|
||||
isClosed bool
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewNamingClient ...
|
||||
func NewNamingClient(nc nacos_client.INacosClient) (*NamingClient, error) {
|
||||
return NewNamingClientWithRamCredentialProvider(nc, nil)
|
||||
}
|
||||
|
||||
// NewNamingClientWithRamCredentialProvider ...
|
||||
func NewNamingClientWithRamCredentialProvider(nc nacos_client.INacosClient, provider security.RamCredentialProvider) (*NamingClient, error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
naming := &NamingClient{INacosClient: nc, ctx: ctx, cancel: cancel}
|
||||
|
@ -75,7 +85,7 @@ func NewNamingClient(nc nacos_client.INacosClient) (*NamingClient, error) {
|
|||
naming.serviceInfoHolder = naming_cache.NewServiceInfoHolder(clientConfig.NamespaceId, clientConfig.CacheDir,
|
||||
clientConfig.UpdateCacheWhenEmpty, clientConfig.NotLoadCacheAtStart)
|
||||
|
||||
naming.serviceProxy, err = NewNamingProxyDelegate(ctx, clientConfig, serverConfig, httpAgent, naming.serviceInfoHolder)
|
||||
naming.serviceProxy, err = NewNamingProxyDelegateWithRamCredentialProvider(ctx, clientConfig, serverConfig, httpAgent, naming.serviceInfoHolder, provider)
|
||||
|
||||
if clientConfig.AsyncUpdateService {
|
||||
go NewServiceInfoUpdater(ctx, naming.serviceInfoHolder, clientConfig.UpdateThreadNum, naming.serviceProxy).asyncUpdateService()
|
||||
|
@ -191,11 +201,14 @@ func (sc *NamingClient) GetService(param vo.GetServiceParam) (service model.Serv
|
|||
param.GroupName = constant.DEFAULT_GROUP
|
||||
}
|
||||
var ok bool
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters)
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, "")
|
||||
if !ok {
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters)
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, "")
|
||||
}
|
||||
service.Clusters = clusters
|
||||
service.Hosts = clusterSelector.SelectInstance(&service)
|
||||
return service, err
|
||||
}
|
||||
|
||||
|
@ -221,21 +234,24 @@ func (sc *NamingClient) SelectAllInstances(param vo.SelectAllInstancesParam) ([]
|
|||
if len(param.GroupName) == 0 {
|
||||
param.GroupName = constant.DEFAULT_GROUP
|
||||
}
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
var (
|
||||
service model.Service
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters)
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, "")
|
||||
if !ok {
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters)
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, "")
|
||||
}
|
||||
if err != nil || service.Hosts == nil || len(service.Hosts) == 0 {
|
||||
if err != nil {
|
||||
return []model.Instance{}, err
|
||||
}
|
||||
return service.Hosts, err
|
||||
instances := clusterSelector.SelectInstance(&service)
|
||||
if instances == nil || len(instances) == 0 {
|
||||
return []model.Instance{}, err
|
||||
}
|
||||
return instances, err
|
||||
}
|
||||
|
||||
// SelectInstances Get all instance by DataId, Group and Health
|
||||
|
@ -248,14 +264,15 @@ func (sc *NamingClient) SelectInstances(param vo.SelectInstancesParam) ([]model.
|
|||
ok bool
|
||||
err error
|
||||
)
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters)
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, "")
|
||||
if !ok {
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters)
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
service.Hosts = clusterSelector.SelectInstance(&service)
|
||||
return sc.selectInstances(service, param.HealthyOnly)
|
||||
}
|
||||
|
||||
|
@ -265,7 +282,7 @@ func (sc *NamingClient) selectInstances(service model.Service, healthy bool) ([]
|
|||
}
|
||||
hosts := service.Hosts
|
||||
var result []model.Instance
|
||||
logger.Infof("select instances with options: [healthy:<%s>], with service:<%s>", healthy, util.GetGroupName(service.Name, service.GroupName))
|
||||
logger.Infof("select instances with options: [healthy:<%t>], with service:<%s>", healthy, util.GetGroupName(service.Name, service.GroupName))
|
||||
for _, host := range hosts {
|
||||
if host.Healthy == healthy && host.Enable && host.Weight > 0 {
|
||||
result = append(result, host)
|
||||
|
@ -284,15 +301,15 @@ func (sc *NamingClient) SelectOneHealthyInstance(param vo.SelectOneHealthInstanc
|
|||
ok bool
|
||||
err error
|
||||
)
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, clusters)
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
service, ok = sc.serviceInfoHolder.GetServiceInfo(param.ServiceName, param.GroupName, "")
|
||||
if !ok {
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters)
|
||||
service, err = sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
service.Hosts = clusterSelector.SelectInstance(&service)
|
||||
return sc.selectOneHealthyInstances(service)
|
||||
}
|
||||
|
||||
|
@ -325,19 +342,21 @@ func (sc *NamingClient) Subscribe(param *vo.SubscribeParam) error {
|
|||
if len(param.GroupName) == 0 {
|
||||
param.GroupName = constant.DEFAULT_GROUP
|
||||
}
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
sc.serviceInfoHolder.RegisterCallback(util.GetGroupName(param.ServiceName, param.GroupName), clusters, ¶m.SubscribeCallback)
|
||||
_, err := sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, clusters)
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
callbackWrapper := naming_cache.NewSubscribeCallbackFuncWrapper(clusterSelector, ¶m.SubscribeCallback)
|
||||
sc.serviceInfoHolder.RegisterCallback(util.GetGroupName(param.ServiceName, param.GroupName), "", callbackWrapper)
|
||||
_, err := sc.serviceProxy.Subscribe(param.ServiceName, param.GroupName, "")
|
||||
return err
|
||||
}
|
||||
|
||||
// Unsubscribe ...
|
||||
func (sc *NamingClient) Unsubscribe(param *vo.SubscribeParam) (err error) {
|
||||
clusters := strings.Join(param.Clusters, ",")
|
||||
clusterSelector := naming_cache.NewClusterSelector(param.Clusters)
|
||||
callbackWrapper := naming_cache.NewSubscribeCallbackFuncWrapper(clusterSelector, ¶m.SubscribeCallback)
|
||||
serviceFullName := util.GetGroupName(param.ServiceName, param.GroupName)
|
||||
sc.serviceInfoHolder.DeregisterCallback(serviceFullName, clusters, ¶m.SubscribeCallback)
|
||||
if sc.serviceInfoHolder.IsSubscribed(serviceFullName, clusters) {
|
||||
err = sc.serviceProxy.Unsubscribe(param.ServiceName, param.GroupName, clusters)
|
||||
sc.serviceInfoHolder.DeregisterCallback(serviceFullName, "", callbackWrapper)
|
||||
if !sc.serviceInfoHolder.IsSubscribed(serviceFullName, "") {
|
||||
err = sc.serviceProxy.Unsubscribe(param.ServiceName, param.GroupName, "")
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -350,6 +369,13 @@ func (sc *NamingClient) ServerHealthy() bool {
|
|||
|
||||
// CloseClient ...
|
||||
func (sc *NamingClient) CloseClient() {
|
||||
sc.mutex.Lock()
|
||||
defer sc.mutex.Unlock()
|
||||
|
||||
if sc.isClosed {
|
||||
return
|
||||
}
|
||||
sc.serviceProxy.CloseClient()
|
||||
sc.cancel()
|
||||
sc.isClosed = true
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ var clientConfigTest = *constant.NewClientConfig(
|
|||
var serverConfigTest = *constant.NewServerConfig("127.0.0.1", 80, constant.WithContextPath("/nacos"))
|
||||
|
||||
type MockNamingProxy struct {
|
||||
unsubscribeCalled bool
|
||||
unsubscribeParams []string // 记录调用参数
|
||||
}
|
||||
|
||||
func (m *MockNamingProxy) RegisterInstance(serviceName string, groupName string, instance model.Instance) (bool, error) {
|
||||
|
@ -68,6 +70,8 @@ func (m *MockNamingProxy) Subscribe(serviceName, groupName, clusters string) (mo
|
|||
}
|
||||
|
||||
func (m *MockNamingProxy) Unsubscribe(serviceName, groupName, clusters string) error {
|
||||
m.unsubscribeCalled = true
|
||||
m.unsubscribeParams = []string{serviceName, groupName, clusters}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -452,3 +456,108 @@ func BenchmarkNamingClient_SelectOneHealthyInstances(b *testing.B) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNamingClient_Unsubscribe_WithCallback_ShouldNotCallServiceProxyUnsubscribe(t *testing.T) {
|
||||
// 创建一个带有回调函数的订阅参数
|
||||
callback := func(services []model.Instance, err error) {
|
||||
// 空回调函数
|
||||
}
|
||||
param := &vo.SubscribeParam{
|
||||
ServiceName: "test-service",
|
||||
GroupName: "test-group",
|
||||
Clusters: []string{"test-cluster"},
|
||||
SubscribeCallback: callback,
|
||||
}
|
||||
|
||||
// 创建测试客户端
|
||||
client := NewTestNamingClient()
|
||||
mockProxy := client.serviceProxy.(*MockNamingProxy)
|
||||
|
||||
// 执行 Unsubscribe
|
||||
err := client.Unsubscribe(param)
|
||||
|
||||
// 验证没有错误
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, mockProxy.unsubscribeCalled)
|
||||
}
|
||||
|
||||
func TestNamingClient_Unsubscribe_WithoutCallback_ShouldCallServiceProxyUnsubscribe(t *testing.T) {
|
||||
// 创建一个没有回调函数的订阅参数
|
||||
param := &vo.SubscribeParam{
|
||||
ServiceName: "test-service",
|
||||
GroupName: "test-group",
|
||||
Clusters: []string{"test-cluster"},
|
||||
// SubscribeCallback 为 nil
|
||||
}
|
||||
|
||||
// 创建测试客户端
|
||||
client := NewTestNamingClient()
|
||||
// 获取原始的 MockNamingProxy 来检查调用状态
|
||||
mockProxy := client.serviceProxy.(*MockNamingProxy)
|
||||
|
||||
// 执行 Unsubscribe
|
||||
err := client.Unsubscribe(param)
|
||||
|
||||
// 验证没有错误
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, mockProxy.unsubscribeCalled)
|
||||
}
|
||||
|
||||
// TestNamingClient_Unsubscribe_Integration_Test 集成测试,使用真实的 ServiceInfoHolder 来测试修复后的逻辑
|
||||
func TestNamingClient_Unsubscribe_Integration_Test(t *testing.T) {
|
||||
// 创建测试客户端
|
||||
client := NewTestNamingClient()
|
||||
|
||||
// 获取原始的 MockNamingProxy 来检查调用状态
|
||||
mockProxy := client.serviceProxy.(*MockNamingProxy)
|
||||
|
||||
// 创建回调函数
|
||||
callback1 := func(services []model.Instance, err error) {
|
||||
// 回调函数1
|
||||
}
|
||||
|
||||
callback2 := func(services []model.Instance, err error) {
|
||||
// 回调函数2
|
||||
}
|
||||
|
||||
// 测试场景1:先注册两个回调函数,然后取消订阅第一个
|
||||
// 这种情况下,取消订阅第一个回调函数后,还有其他回调函数,所以不应该调用 serviceProxy.Unsubscribe
|
||||
|
||||
// 注册第一个回调函数
|
||||
param1 := &vo.SubscribeParam{
|
||||
ServiceName: "test-service",
|
||||
GroupName: "test-group",
|
||||
Clusters: []string{"test-cluster"},
|
||||
SubscribeCallback: callback1,
|
||||
}
|
||||
|
||||
// 注册第二个回调函数
|
||||
param2 := &vo.SubscribeParam{
|
||||
ServiceName: "test-service",
|
||||
GroupName: "test-group",
|
||||
Clusters: []string{"test-cluster"},
|
||||
SubscribeCallback: callback2,
|
||||
}
|
||||
|
||||
// 先注册两个回调函数
|
||||
err := client.Subscribe(param1)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = client.Subscribe(param2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// 重置 MockNamingProxy 的调用状态
|
||||
mockProxy.unsubscribeCalled = false
|
||||
mockProxy.unsubscribeParams = nil
|
||||
|
||||
// 取消订阅第一个回调函数
|
||||
err = client.Unsubscribe(param1)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, mockProxy.unsubscribeCalled)
|
||||
|
||||
// 取消订阅第二个回调函数
|
||||
err = client.Unsubscribe(param2)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, mockProxy.unsubscribeCalled)
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package naming_grpc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_proxy"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRedoSubscribe(t *testing.T) {
|
||||
t.Skip("Skipping test,It failed due to a previous commit and is difficult to modify because of the use of struct type assertions in the code.")
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_response"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/inner/uuid"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
|
@ -83,8 +84,7 @@ func NewNamingGrpcProxy(ctx context.Context, clientCfg constant.ClientConfig, na
|
|||
|
||||
func (proxy *NamingGrpcProxy) requestToServer(request rpc_request.IRequest) (rpc_response.IResponse, error) {
|
||||
start := time.Now()
|
||||
proxy.nacosServer.InjectSign(request, request.GetHeaders(), proxy.clientConfig)
|
||||
proxy.nacosServer.InjectSecurityInfo(request.GetHeaders())
|
||||
proxy.nacosServer.InjectSecurityInfo(request.GetHeaders(), security.BuildNamingResourceByRequest(request))
|
||||
response, err := proxy.rpcClient.GetRpcClient().Request(request, int64(proxy.clientConfig.TimeoutMs))
|
||||
monitor.GetNamingRequestMonitor(constant.GRPC, request.GetRequestType(), rpc_response.GetGrpcResponseStatusCode(response)).Observe(float64(time.Now().Nanosecond() - start.Nanosecond()))
|
||||
return response, err
|
||||
|
|
|
@ -18,6 +18,7 @@ package naming_client
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/inner/uuid"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client/naming_cache"
|
||||
|
@ -40,6 +41,11 @@ type NamingProxyDelegate struct {
|
|||
|
||||
func NewNamingProxyDelegate(ctx context.Context, clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig,
|
||||
httpAgent http_agent.IHttpAgent, serviceInfoHolder *naming_cache.ServiceInfoHolder) (naming_proxy.INamingProxy, error) {
|
||||
return NewNamingProxyDelegateWithRamCredentialProvider(ctx, clientCfg, serverCfgs, httpAgent, serviceInfoHolder, nil)
|
||||
}
|
||||
|
||||
func NewNamingProxyDelegateWithRamCredentialProvider(ctx context.Context, clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig,
|
||||
httpAgent http_agent.IHttpAgent, serviceInfoHolder *naming_cache.ServiceInfoHolder, provider security.RamCredentialProvider) (naming_proxy.INamingProxy, error) {
|
||||
|
||||
uid, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
|
@ -51,7 +57,7 @@ func NewNamingProxyDelegate(ctx context.Context, clientCfg constant.ClientConfig
|
|||
"RequestId": {uid.String()},
|
||||
"Request-Module": {"Naming"},
|
||||
}
|
||||
nacosServer, err := nacos_server.NewNacosServer(ctx, serverCfgs, clientCfg, httpAgent, clientCfg.TimeoutMs, clientCfg.Endpoint, namingHeader)
|
||||
nacosServer, err := nacos_server.NewNacosServerWithRamCredentialProvider(ctx, serverCfgs, clientCfg, httpAgent, clientCfg.TimeoutMs, clientCfg.Endpoint, namingHeader, provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -123,6 +123,12 @@ func WithSecretKey(secretKey string) ClientOption {
|
|||
}
|
||||
}
|
||||
|
||||
func WithRamConfig(ramConfig *RamConfig) ClientOption {
|
||||
return func(config *ClientConfig) {
|
||||
config.RamConfig = ramConfig
|
||||
}
|
||||
}
|
||||
|
||||
// WithOpenKMS ...
|
||||
func WithOpenKMS(openKMS bool) ClientOption {
|
||||
return func(config *ClientConfig) {
|
||||
|
@ -143,6 +149,12 @@ func WithKMSv3Config(kmsv3Config *KMSv3Config) ClientOption {
|
|||
}
|
||||
}
|
||||
|
||||
func WithKMSConfig(kmsConfig *KMSConfig) ClientOption {
|
||||
return func(config *ClientConfig) {
|
||||
config.KMSConfig = kmsConfig
|
||||
}
|
||||
}
|
||||
|
||||
// WithCacheDir ...
|
||||
func WithCacheDir(cacheDir string) ClientOption {
|
||||
return func(config *ClientConfig) {
|
||||
|
|
|
@ -27,19 +27,21 @@ type ServerConfig struct {
|
|||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
TimeoutMs uint64 // timeout for requesting Nacos server, default value is 10000ms
|
||||
ListenInterval uint64 // Deprecated
|
||||
BeatInterval int64 // the time interval for sending beat to server,default value is 5000ms
|
||||
NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here.
|
||||
AppName string // the appName
|
||||
AppKey string // the client identity information
|
||||
Endpoint string // the endpoint for get Nacos server addresses
|
||||
RegionId string // the regionId for kms
|
||||
AccessKey string // the AccessKey for kms
|
||||
SecretKey string // the SecretKey for kms
|
||||
OpenKMS bool // it's to open kms, default is false. https://help.aliyun.com/product/28933.html
|
||||
KMSVersion KMSVersion // kms client version. https://help.aliyun.com/document_detail/380927.html
|
||||
KMSv3Config *KMSv3Config //KMSv3 configuration. https://help.aliyun.com/document_detail/601596.html
|
||||
TimeoutMs uint64 // timeout for requesting Nacos server, default value is 10000ms
|
||||
ListenInterval uint64 // Deprecated
|
||||
BeatInterval int64 // the time interval for sending beat to server,default value is 5000ms
|
||||
NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here.
|
||||
AppName string // the appName
|
||||
AppKey string // the client identity information
|
||||
Endpoint string // the endpoint for get Nacos server addresses
|
||||
RegionId string // the regionId for kms
|
||||
AccessKey string // the AccessKey for kms
|
||||
SecretKey string // the SecretKey for kms
|
||||
RamConfig *RamConfig
|
||||
OpenKMS bool // it's to open kms, default is false. https://help.aliyun.com/product/28933.html
|
||||
KMSVersion KMSVersion // kms client version. https://help.aliyun.com/document_detail/380927.html
|
||||
KMSv3Config *KMSv3Config //KMSv3 configuration. https://help.aliyun.com/document_detail/601596.html
|
||||
KMSConfig *KMSConfig
|
||||
CacheDir string // the directory for persist nacos service info,default value is current path
|
||||
DisableUseSnapShot bool // It's a switch, default is false, means that when get remote config fail, use local cache file instead
|
||||
UpdateThreadNum int // the number of goroutine for update nacos service info,default value is 20
|
||||
|
@ -110,3 +112,23 @@ type KMSv3Config struct {
|
|||
Endpoint string
|
||||
CaContent string
|
||||
}
|
||||
|
||||
type KMSConfig struct {
|
||||
Endpoint string
|
||||
OpenSSL string
|
||||
CaContent string
|
||||
}
|
||||
|
||||
type RamConfig struct {
|
||||
SecurityToken string
|
||||
SignatureRegionId string
|
||||
RamRoleName string
|
||||
RoleArn string
|
||||
Policy string
|
||||
RoleSessionName string
|
||||
RoleSessionExpiration int
|
||||
OIDCProviderArn string
|
||||
OIDCTokenFilePath string
|
||||
CredentialsURI string
|
||||
SecretName string
|
||||
}
|
||||
|
|
|
@ -27,84 +27,95 @@ const (
|
|||
UNKNOWN_KMS_VERSION KMSVersion = "UNKNOWN_KMS_VERSION"
|
||||
)
|
||||
const (
|
||||
KEY_USERNAME = "username"
|
||||
KEY_PASSWORD = "password"
|
||||
KEY_ENDPOINT = "endpoint"
|
||||
KEY_NAME_SPACE = "namespace"
|
||||
KEY_ACCESS_KEY = "accessKey"
|
||||
KEY_SECRET_KEY = "secretKey"
|
||||
KEY_SERVER_ADDR = "serverAddr"
|
||||
KEY_CONTEXT_PATH = "contextPath"
|
||||
KEY_ENCODE = "encode"
|
||||
KEY_DATA_ID = "dataId"
|
||||
KEY_GROUP = "group"
|
||||
KEY_TENANT = "tenant"
|
||||
KEY_DESC = "desc"
|
||||
KEY_APP_NAME = "appName"
|
||||
KEY_CONTENT = "content"
|
||||
KEY_TIMEOUT_MS = "timeoutMs"
|
||||
KEY_LISTEN_INTERVAL = "listenInterval"
|
||||
KEY_SERVER_CONFIGS = "serverConfigs"
|
||||
KEY_CLIENT_CONFIG = "clientConfig"
|
||||
KEY_TOKEN = "token"
|
||||
KEY_ACCESS_TOKEN = "accessToken"
|
||||
KEY_TOKEN_TTL = "tokenTtl"
|
||||
KEY_GLOBAL_ADMIN = "globalAdmin"
|
||||
KEY_TOKEN_REFRESH_WINDOW = "tokenRefreshWindow"
|
||||
WEB_CONTEXT = "/nacos"
|
||||
CONFIG_BASE_PATH = "/v1/cs"
|
||||
CONFIG_PATH = CONFIG_BASE_PATH + "/configs"
|
||||
CONFIG_AGG_PATH = "/datum.do"
|
||||
CONFIG_LISTEN_PATH = CONFIG_BASE_PATH + "/configs/listener"
|
||||
SERVICE_BASE_PATH = "/v1/ns"
|
||||
SERVICE_PATH = SERVICE_BASE_PATH + "/instance"
|
||||
SERVICE_INFO_PATH = SERVICE_BASE_PATH + "/service"
|
||||
SERVICE_SUBSCRIBE_PATH = SERVICE_PATH + "/list"
|
||||
NAMESPACE_PATH = "/v1/console/namespaces"
|
||||
SPLIT_CONFIG = string(rune(1))
|
||||
SPLIT_CONFIG_INNER = string(rune(2))
|
||||
KEY_LISTEN_CONFIGS = "Listening-Configs"
|
||||
KEY_SERVICE_NAME = "serviceName"
|
||||
KEY_IP = "ip"
|
||||
KEY_PORT = "port"
|
||||
KEY_WEIGHT = "weight"
|
||||
KEY_ENABLE = "enable"
|
||||
KEY_HEALTHY = "healthy"
|
||||
KEY_METADATA = "metadata"
|
||||
KEY_CLUSTER_NAME = "clusterName"
|
||||
KEY_CLUSTER = "cluster"
|
||||
KEY_BEAT = "beat"
|
||||
KEY_DOM = "dom"
|
||||
DEFAULT_CONTEXT_PATH = "/nacos"
|
||||
CLIENT_VERSION = "Nacos-Go-Client:v2.2.7"
|
||||
REQUEST_DOMAIN_RETRY_TIME = 3
|
||||
SERVICE_INFO_SPLITER = "@@"
|
||||
CONFIG_INFO_SPLITER = "@@"
|
||||
DEFAULT_NAMESPACE_ID = "public"
|
||||
DEFAULT_GROUP = "DEFAULT_GROUP"
|
||||
NAMING_INSTANCE_ID_SPLITTER = "#"
|
||||
DefaultClientErrorCode = "SDK.NacosError"
|
||||
DEFAULT_SERVER_SCHEME = "http"
|
||||
HTTPS_SERVER_SCHEME = "https"
|
||||
LABEL_SOURCE = "source"
|
||||
LABEL_SOURCE_SDK = "sdk"
|
||||
LABEL_MODULE = "module"
|
||||
LABEL_MODULE_CONFIG = "config"
|
||||
LABEL_MODULE_NAMING = "naming"
|
||||
RESPONSE_CODE_SUCCESS = 200
|
||||
UN_REGISTER = 301
|
||||
KEEP_ALIVE_TIME = 5
|
||||
DEFAULT_TIMEOUT_MILLS = 3000
|
||||
ALL_SYNC_INTERNAL = 5 * time.Minute
|
||||
CLIENT_APPNAME_HEADER = "Client-AppName"
|
||||
APPNAME_HEADER = "AppName"
|
||||
CLIENT_REQUEST_TS_HEADER = "Client-RequestTS"
|
||||
CLIENT_REQUEST_TOKEN_HEADER = "Client-RequestToken"
|
||||
EX_CONFIG_INFO = "exConfigInfo"
|
||||
CHARSET_KEY = "charset"
|
||||
LOG_FILE_NAME = "nacos-sdk.log"
|
||||
HTTPS_SERVER_PORT = 443
|
||||
GRPC = "grpc"
|
||||
RpcPortOffset = 1000
|
||||
MSE_KMSv1_DEFAULT_KEY_ID = "alias/acs/mse"
|
||||
KEY_USERNAME = "username"
|
||||
KEY_PASSWORD = "password"
|
||||
KEY_ENDPOINT = "endpoint"
|
||||
KEY_NAME_SPACE = "namespace"
|
||||
KEY_ACCESS_KEY = "accessKey"
|
||||
KEY_SECRET_KEY = "secretKey"
|
||||
KEY_SERVER_ADDR = "serverAddr"
|
||||
KEY_CONTEXT_PATH = "contextPath"
|
||||
KEY_ENCODE = "encode"
|
||||
KEY_DATA_ID = "dataId"
|
||||
KEY_GROUP = "group"
|
||||
KEY_TENANT = "tenant"
|
||||
KEY_DESC = "desc"
|
||||
KEY_APP_NAME = "appName"
|
||||
KEY_CONTENT = "content"
|
||||
KEY_TIMEOUT_MS = "timeoutMs"
|
||||
KEY_LISTEN_INTERVAL = "listenInterval"
|
||||
KEY_SERVER_CONFIGS = "serverConfigs"
|
||||
KEY_CLIENT_CONFIG = "clientConfig"
|
||||
KEY_TOKEN = "token"
|
||||
KEY_ACCESS_TOKEN = "accessToken"
|
||||
KEY_TOKEN_TTL = "tokenTtl"
|
||||
KEY_GLOBAL_ADMIN = "globalAdmin"
|
||||
KEY_TOKEN_REFRESH_WINDOW = "tokenRefreshWindow"
|
||||
WEB_CONTEXT = "/nacos"
|
||||
CONFIG_BASE_PATH = "/v1/cs"
|
||||
CONFIG_PATH = CONFIG_BASE_PATH + "/configs"
|
||||
CONFIG_AGG_PATH = "/datum.do"
|
||||
CONFIG_LISTEN_PATH = CONFIG_BASE_PATH + "/configs/listener"
|
||||
SERVICE_BASE_PATH = "/v1/ns"
|
||||
SERVICE_PATH = SERVICE_BASE_PATH + "/instance"
|
||||
SERVICE_INFO_PATH = SERVICE_BASE_PATH + "/service"
|
||||
SERVICE_SUBSCRIBE_PATH = SERVICE_PATH + "/list"
|
||||
NAMESPACE_PATH = "/v1/console/namespaces"
|
||||
SPLIT_CONFIG = string(rune(1))
|
||||
SPLIT_CONFIG_INNER = string(rune(2))
|
||||
KEY_LISTEN_CONFIGS = "Listening-Configs"
|
||||
KEY_SERVICE_NAME = "serviceName"
|
||||
KEY_IP = "ip"
|
||||
KEY_PORT = "port"
|
||||
KEY_WEIGHT = "weight"
|
||||
KEY_ENABLE = "enable"
|
||||
KEY_HEALTHY = "healthy"
|
||||
KEY_METADATA = "metadata"
|
||||
KEY_CLUSTER_NAME = "clusterName"
|
||||
KEY_CLUSTER = "cluster"
|
||||
KEY_BEAT = "beat"
|
||||
KEY_DOM = "dom"
|
||||
DEFAULT_CONTEXT_PATH = "/nacos"
|
||||
CLIENT_VERSION = "Nacos-Go-Client:v2.3.3"
|
||||
REQUEST_DOMAIN_RETRY_TIME = 3
|
||||
SERVICE_INFO_SPLITER = "@@"
|
||||
CONFIG_INFO_SPLITER = "@@"
|
||||
DEFAULT_NAMESPACE_ID = "public"
|
||||
DEFAULT_GROUP = "DEFAULT_GROUP"
|
||||
NAMING_INSTANCE_ID_SPLITTER = "#"
|
||||
DefaultClientErrorCode = "SDK.NacosError"
|
||||
DEFAULT_SERVER_SCHEME = "http"
|
||||
HTTPS_SERVER_SCHEME = "https"
|
||||
LABEL_SOURCE = "source"
|
||||
LABEL_SOURCE_SDK = "sdk"
|
||||
LABEL_MODULE = "module"
|
||||
LABEL_MODULE_CONFIG = "config"
|
||||
LABEL_MODULE_NAMING = "naming"
|
||||
RESPONSE_CODE_SUCCESS = 200
|
||||
UN_REGISTER = 301
|
||||
KEEP_ALIVE_TIME = 5
|
||||
DEFAULT_TIMEOUT_MILLS = 3000
|
||||
ALL_SYNC_INTERNAL = 5 * time.Minute
|
||||
CLIENT_APPNAME_HEADER = "Client-AppName"
|
||||
APPNAME_HEADER = "AppName"
|
||||
CLIENT_REQUEST_TS_HEADER = "Client-RequestTS"
|
||||
CLIENT_REQUEST_TOKEN_HEADER = "Client-RequestToken"
|
||||
EX_CONFIG_INFO = "exConfigInfo"
|
||||
CHARSET_KEY = "charset"
|
||||
LOG_FILE_NAME = "nacos-sdk.log"
|
||||
HTTPS_SERVER_PORT = 443
|
||||
GRPC = "grpc"
|
||||
RpcPortOffset = 1000
|
||||
MSE_KMSv1_DEFAULT_KEY_ID = "alias/acs/mse"
|
||||
CONFIG_PUBLISH_REQUEST_NAME = "ConfigPublishRequest"
|
||||
CONFIG_QUERY_REQUEST_NAME = "ConfigQueryRequest"
|
||||
CONFIG_REMOVE_REQUEST_NAME = "ConfigRemoveRequest"
|
||||
INSTANCE_REQUEST_NAME = "InstanceRequest"
|
||||
BATCH_INSTANCE_REQUEST_NAME = "BatchInstanceRequest"
|
||||
SERVICE_LIST_REQUEST_NAME = "ServiceListRequest"
|
||||
SERVICE_QUERY_REQUEST_NAME = "ServiceQueryRequest"
|
||||
SUBSCRIBE_SERVICE_REQUEST_NAME = "SubscribeServiceRequest"
|
||||
NOTIFY_SUBSCRIBE_REQUEST_NAME = "NotifySubscriberRequest"
|
||||
CONFIG_BATCH_LISTEN_REQUEST_NAME = "ConfigBatchListenRequest"
|
||||
CONFIG_CHANGE_NOTIFY_REQUEST_NAME = "ConfigChangeNotifyRequest"
|
||||
)
|
||||
|
|
|
@ -34,35 +34,35 @@ func NewServerConfig(ipAddr string, port uint64, opts ...ServerOption) *ServerCo
|
|||
// ServerOption ...
|
||||
type ServerOption func(*ServerConfig)
|
||||
|
||||
//WithScheme set Scheme for server
|
||||
// WithScheme set Scheme for server
|
||||
func WithScheme(scheme string) ServerOption {
|
||||
return func(config *ServerConfig) {
|
||||
config.Scheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
//WithContextPath set contextPath for server
|
||||
// WithContextPath set contextPath for server
|
||||
func WithContextPath(contextPath string) ServerOption {
|
||||
return func(config *ServerConfig) {
|
||||
config.ContextPath = contextPath
|
||||
}
|
||||
}
|
||||
|
||||
//WithIpAddr set ip address for server
|
||||
// WithIpAddr set ip address for server
|
||||
func WithIpAddr(ipAddr string) ServerOption {
|
||||
return func(config *ServerConfig) {
|
||||
config.IpAddr = ipAddr
|
||||
}
|
||||
}
|
||||
|
||||
//WithPort set port for server
|
||||
// WithPort set port for server
|
||||
func WithPort(port uint64) ServerOption {
|
||||
return func(config *ServerConfig) {
|
||||
config.Port = port
|
||||
}
|
||||
}
|
||||
|
||||
//WithGrpcPort set grpc port for server
|
||||
// WithGrpcPort set grpc port for server
|
||||
func WithGrpcPort(port uint64) ServerOption {
|
||||
return func(config *ServerConfig) {
|
||||
config.GrpcPort = port
|
||||
|
|
|
@ -64,4 +64,5 @@ var (
|
|||
EmptyPasswordKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty password")
|
||||
EmptyClientKeyContentKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty client key content")
|
||||
EmptyCaVerifyKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty ca verify")
|
||||
EmptyEndpointKmsRamClientInitError = fmt.Errorf("init kmsRam client failed with empty endpoint")
|
||||
)
|
||||
|
|
|
@ -64,7 +64,10 @@ func newKmsHandler() *KmsHandler {
|
|||
|
||||
func RegisterConfigEncryptionKmsPlugins(encryptionHandler Handler, clientConfig constant.ClientConfig) {
|
||||
innerKmsClient, err := innerNewKmsClient(clientConfig)
|
||||
if err == nil && innerKmsClient == nil {
|
||||
if innerKmsClient == nil {
|
||||
err = errors.New("create kms client failed.")
|
||||
}
|
||||
if err != nil && innerKmsClient == nil {
|
||||
err = errors.New("create kms client failed.")
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -191,10 +194,10 @@ func (d *KmsHandler) contentParamCheck(content string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient *KmsClient, err error) {
|
||||
func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient KmsClient, err error) {
|
||||
switch clientConfig.KMSVersion {
|
||||
case constant.KMSv1, constant.DEFAULT_KMS_VERSION:
|
||||
kmsClient, err = newKmsV1Client(clientConfig)
|
||||
kmsClient, err = newKmsRamClient(clientConfig)
|
||||
case constant.KMSv3:
|
||||
kmsClient, err = newKmsV3Client(clientConfig)
|
||||
default:
|
||||
|
@ -203,11 +206,11 @@ func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient *KmsClient
|
|||
return kmsClient, err
|
||||
}
|
||||
|
||||
func newKmsV1Client(clientConfig constant.ClientConfig) (*KmsClient, error) {
|
||||
func newKmsV1Client(clientConfig constant.ClientConfig) (KmsClient, error) {
|
||||
return NewKmsV1ClientWithAccessKey(clientConfig.RegionId, clientConfig.AccessKey, clientConfig.SecretKey)
|
||||
}
|
||||
|
||||
func newKmsV3Client(clientConfig constant.ClientConfig) (*KmsClient, error) {
|
||||
func newKmsV3Client(clientConfig constant.ClientConfig) (KmsClient, error) {
|
||||
return NewKmsV3ClientWithConfig(&dkms_api.Config{
|
||||
Protocol: tea.String("https"),
|
||||
Endpoint: tea.String(clientConfig.KMSv3Config.Endpoint),
|
||||
|
@ -215,3 +218,7 @@ func newKmsV3Client(clientConfig constant.ClientConfig) (*KmsClient, error) {
|
|||
Password: tea.String(clientConfig.KMSv3Config.Password),
|
||||
}, clientConfig.KMSv3Config.CaContent)
|
||||
}
|
||||
|
||||
func newKmsRamClient(clientConfig constant.ClientConfig) (KmsClient, error) {
|
||||
return NewKmsRamClient(clientConfig.KMSConfig, clientConfig.RegionId, clientConfig.AccessKey, clientConfig.SecretKey)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ package encryption
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
kms20160120 "github.com/alibabacloud-go/kms-20160120/v3/client"
|
||||
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
||||
"github.com/alibabacloud-go/tea/tea"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
|
||||
dkms_api "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/openapi"
|
||||
dkms_transfer "github.com/aliyun/alibabacloud-dkms-transfer-go-sdk/sdk"
|
||||
|
@ -28,12 +32,20 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type KmsClient struct {
|
||||
type KmsClient interface {
|
||||
Decrypt(cipherContent string) (string, error)
|
||||
Encrypt(content string, keyId string) (string, error)
|
||||
GenerateDataKey(keyId, keySpec string) (string, string, error)
|
||||
GetKmsVersion() constant.KMSVersion
|
||||
setKmsVersion(constant.KMSVersion)
|
||||
}
|
||||
|
||||
type TransferKmsClient struct {
|
||||
*dkms_transfer.KmsTransferClient
|
||||
kmsVersion constant.KMSVersion
|
||||
}
|
||||
|
||||
func NewKmsV1ClientWithAccessKey(regionId, ak, sk string) (*KmsClient, error) {
|
||||
func NewKmsV1ClientWithAccessKey(regionId, ak, sk string) (*TransferKmsClient, error) {
|
||||
var rErr error
|
||||
if rErr = checkKmsV1InitParam(regionId, ak, sk); rErr != nil {
|
||||
return nil, rErr
|
||||
|
@ -60,7 +72,20 @@ func checkKmsV1InitParam(regionId, ak, sk string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func NewKmsV3ClientWithConfig(config *dkms_api.Config, caVerify string) (*KmsClient, error) {
|
||||
func checkKmsRamInitParam(endpoint, ak, sk string) error {
|
||||
if len(endpoint) == 0 {
|
||||
return EmptyEndpointKmsRamClientInitError
|
||||
}
|
||||
if len(ak) == 0 {
|
||||
return EmptyAkKmsV1ClientInitError
|
||||
}
|
||||
if len(sk) == 0 {
|
||||
return EmptySkKmsV1ClientInitError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewKmsV3ClientWithConfig(config *dkms_api.Config, caVerify string) (*TransferKmsClient, error) {
|
||||
var rErr error
|
||||
if rErr = checkKmsV3InitParam(config, caVerify); rErr != nil {
|
||||
return nil, rErr
|
||||
|
@ -96,39 +121,39 @@ func checkKmsV3InitParam(config *dkms_api.Config, caVerify string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newKmsV1ClientWithAccessKey(regionId, ak, sk string) (*KmsClient, error) {
|
||||
func newKmsV1ClientWithAccessKey(regionId, ak, sk string) (*TransferKmsClient, error) {
|
||||
logger.Debugf("init kms client with region:[%s], ak:[%s]xxx, sk:[%s]xxx\n",
|
||||
regionId, ak[:len(ak)/maskUnit8Width], sk[:len(sk)/maskUnit8Width])
|
||||
return newKmsClient(regionId, ak, sk, nil)
|
||||
}
|
||||
|
||||
func newKmsV3ClientWithConfig(config *dkms_api.Config) (*KmsClient, error) {
|
||||
func newKmsV3ClientWithConfig(config *dkms_api.Config) (*TransferKmsClient, error) {
|
||||
logger.Debugf("init kms client with endpoint:[%s], clientKeyContent:[%s], password:[%s]\n",
|
||||
config.Endpoint, (*config.ClientKeyContent)[:len(*config.ClientKeyContent)/maskUnit8Width],
|
||||
(*config.Password)[:len(*config.Password)/maskUnit8Width])
|
||||
return newKmsClient("", "", "", config)
|
||||
}
|
||||
|
||||
func newKmsClient(regionId, ak, sk string, config *dkms_api.Config) (*KmsClient, error) {
|
||||
func newKmsClient(regionId, ak, sk string, config *dkms_api.Config) (*TransferKmsClient, error) {
|
||||
client, err := dkms_transfer.NewClientWithAccessKey(regionId, ak, sk, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &KmsClient{
|
||||
return &TransferKmsClient{
|
||||
KmsTransferClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (kmsClient *KmsClient) GetKmsVersion() constant.KMSVersion {
|
||||
func (kmsClient *TransferKmsClient) GetKmsVersion() constant.KMSVersion {
|
||||
return kmsClient.kmsVersion
|
||||
}
|
||||
|
||||
func (kmsClient *KmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
|
||||
func (kmsClient *TransferKmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
|
||||
logger.Debug("successfully set kms client version to " + kmsVersion)
|
||||
kmsClient.kmsVersion = kmsVersion
|
||||
}
|
||||
|
||||
func (kmsClient *KmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
|
||||
func (kmsClient *TransferKmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
|
||||
generateDataKeyRequest := kms.CreateGenerateDataKeyRequest()
|
||||
generateDataKeyRequest.Scheme = kmsScheme
|
||||
generateDataKeyRequest.AcceptFormat = kmsAcceptFormat
|
||||
|
@ -141,7 +166,7 @@ func (kmsClient *KmsClient) GenerateDataKey(keyId, keySpec string) (string, stri
|
|||
return generateDataKeyResponse.Plaintext, generateDataKeyResponse.CiphertextBlob, nil
|
||||
}
|
||||
|
||||
func (kmsClient *KmsClient) Decrypt(cipherContent string) (string, error) {
|
||||
func (kmsClient *TransferKmsClient) Decrypt(cipherContent string) (string, error) {
|
||||
request := kms.CreateDecryptRequest()
|
||||
request.Method = http.MethodPost
|
||||
request.Scheme = kmsScheme
|
||||
|
@ -154,7 +179,7 @@ func (kmsClient *KmsClient) Decrypt(cipherContent string) (string, error) {
|
|||
return response.Plaintext, nil
|
||||
}
|
||||
|
||||
func (kmsClient *KmsClient) Encrypt(content, keyId string) (string, error) {
|
||||
func (kmsClient *TransferKmsClient) Encrypt(content, keyId string) (string, error) {
|
||||
request := kms.CreateEncryptRequest()
|
||||
request.Method = http.MethodPost
|
||||
request.Scheme = kmsScheme
|
||||
|
@ -171,3 +196,108 @@ func (kmsClient *KmsClient) Encrypt(content, keyId string) (string, error) {
|
|||
func GetDefaultKMSv1KeyId() string {
|
||||
return constant.MSE_KMSv1_DEFAULT_KEY_ID
|
||||
}
|
||||
|
||||
type RamKmsClient struct {
|
||||
*kms20160120.Client
|
||||
kmsVersion constant.KMSVersion
|
||||
runtime *util.RuntimeOptions
|
||||
}
|
||||
|
||||
func NewKmsRamClient(kmsConfig *constant.KMSConfig, regionId, ak, sk string) (*RamKmsClient, error) {
|
||||
if kmsConfig == nil || len(kmsConfig.Endpoint) == 0 {
|
||||
if err := checkKmsV1InitParam(regionId, ak, sk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
KmsV1Config := &openapi.Config{}
|
||||
KmsV1Config.AccessKeyId = tea.String(ak)
|
||||
KmsV1Config.AccessKeySecret = tea.String(sk)
|
||||
KmsV1Config.RegionId = tea.String(regionId)
|
||||
_result, _err := kms20160120.NewClient(KmsV1Config)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
_ramClient := &RamKmsClient{
|
||||
Client: _result,
|
||||
kmsVersion: constant.KMSv1,
|
||||
runtime: &util.RuntimeOptions{},
|
||||
}
|
||||
return _ramClient, nil
|
||||
}
|
||||
if err := checkKmsRamInitParam(kmsConfig.Endpoint, ak, sk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config := &openapi.Config{}
|
||||
config.AccessKeyId = tea.String(ak)
|
||||
config.AccessKeySecret = tea.String(sk)
|
||||
if len(regionId) != 0 {
|
||||
config.RegionId = tea.String(regionId)
|
||||
}
|
||||
config.Endpoint = tea.String(kmsConfig.Endpoint)
|
||||
config.Ca = tea.String(kmsConfig.CaContent)
|
||||
runtimeOption := &util.RuntimeOptions{}
|
||||
if len(kmsConfig.CaContent) == 0 {
|
||||
runtimeOption.IgnoreSSL = tea.Bool(true)
|
||||
}
|
||||
if kmsConfig.OpenSSL == "true" {
|
||||
runtimeOption.IgnoreSSL = tea.Bool(false)
|
||||
} else if kmsConfig.OpenSSL == "false" {
|
||||
runtimeOption.IgnoreSSL = tea.Bool(true)
|
||||
}
|
||||
_result, _err := kms20160120.NewClient(config)
|
||||
if _err != nil {
|
||||
return nil, _err
|
||||
}
|
||||
_ramClient := &RamKmsClient{
|
||||
Client: _result,
|
||||
kmsVersion: constant.KMSv3,
|
||||
runtime: runtimeOption,
|
||||
}
|
||||
return _ramClient, nil
|
||||
}
|
||||
|
||||
func (kmsClient *RamKmsClient) GetKmsVersion() constant.KMSVersion {
|
||||
return kmsClient.kmsVersion
|
||||
}
|
||||
|
||||
func (kmsClient *RamKmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
|
||||
logger.Debug("successfully set kms client version to " + kmsVersion)
|
||||
kmsClient.kmsVersion = kmsVersion
|
||||
}
|
||||
|
||||
func (kmsClient *RamKmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
|
||||
request := &kms20160120.GenerateDataKeyRequest{
|
||||
KeyId: tea.String(keyId),
|
||||
KeySpec: tea.String(keySpec),
|
||||
}
|
||||
|
||||
_body, _err := kmsClient.Client.GenerateDataKeyWithOptions(request, kmsClient.runtime)
|
||||
|
||||
if _err != nil {
|
||||
return "", "", _err
|
||||
}
|
||||
return *_body.Body.Plaintext, *_body.Body.CiphertextBlob, nil
|
||||
}
|
||||
|
||||
func (kmsClient *RamKmsClient) Decrypt(cipherContent string) (string, error) {
|
||||
request := &kms20160120.DecryptRequest{
|
||||
CiphertextBlob: tea.String(cipherContent),
|
||||
}
|
||||
|
||||
_body, _err := kmsClient.Client.DecryptWithOptions(request, kmsClient.runtime)
|
||||
if _err != nil {
|
||||
return "", _err
|
||||
}
|
||||
return *_body.Body.Plaintext, nil
|
||||
}
|
||||
|
||||
func (kmsClient *RamKmsClient) Encrypt(content, keyId string) (string, error) {
|
||||
request := &kms20160120.EncryptRequest{
|
||||
Plaintext: tea.String(content),
|
||||
KeyId: tea.String(keyId),
|
||||
}
|
||||
_body, _err := kmsClient.Client.EncryptWithOptions(request, kmsClient.runtime)
|
||||
if _err != nil {
|
||||
return "", _err
|
||||
}
|
||||
return *_body.Body.CiphertextBlob, nil
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
)
|
||||
|
||||
type kmsPlugin struct {
|
||||
kmsClient *KmsClient
|
||||
kmsClient KmsClient
|
||||
}
|
||||
|
||||
func (k *kmsPlugin) Encrypt(param *HandlerParam) error {
|
||||
|
|
|
@ -18,19 +18,22 @@ package http_agent
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func delete(client *http.Client, path string, header http.Header, timeoutMs uint64, params map[string]string) (response *http.Response, err error) {
|
||||
if !strings.HasSuffix(path, "?") {
|
||||
path = path + "?"
|
||||
}
|
||||
for key, value := range params {
|
||||
path = path + key + "=" + value + "&"
|
||||
}
|
||||
if strings.HasSuffix(path, "&") {
|
||||
path = path[:len(path)-1]
|
||||
if len(params) > 0 {
|
||||
if !strings.HasSuffix(path, "?") {
|
||||
path = path + "?"
|
||||
}
|
||||
for key, value := range params {
|
||||
path = path + key + "=" + url.QueryEscape(value) + "&"
|
||||
}
|
||||
if strings.HasSuffix(path, "&") {
|
||||
path = path[:len(path)-1]
|
||||
}
|
||||
}
|
||||
client.Timeout = time.Millisecond * time.Duration(timeoutMs)
|
||||
request, errNew := http.NewRequest(http.MethodDelete, path, nil)
|
||||
|
|
|
@ -18,6 +18,7 @@ package http_agent
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -31,7 +32,7 @@ func get(client *http.Client, path string, header http.Header, timeoutMs uint64,
|
|||
if !strings.HasSuffix(path, "&") {
|
||||
path = path + "&"
|
||||
}
|
||||
path = path + key + "=" + value + "&"
|
||||
path = path + key + "=" + url.QueryEscape(value) + "&"
|
||||
}
|
||||
if strings.HasSuffix(path, "&") {
|
||||
path = path[:len(path)-1]
|
||||
|
|
|
@ -110,6 +110,12 @@ func BuildLoggerConfig(clientConfig constant.ClientConfig) Config {
|
|||
loggerConfig.LogRollingConfig.MaxBackups = logRollingConfig.MaxBackups
|
||||
loggerConfig.LogRollingConfig.LocalTime = logRollingConfig.LocalTime
|
||||
loggerConfig.LogRollingConfig.Compress = logRollingConfig.Compress
|
||||
} else {
|
||||
loggerConfig.LogRollingConfig.MaxSize = 100
|
||||
loggerConfig.LogRollingConfig.MaxAge = 30
|
||||
loggerConfig.LogRollingConfig.MaxBackups = 5
|
||||
loggerConfig.LogRollingConfig.LocalTime = true
|
||||
loggerConfig.LogRollingConfig.Compress = false
|
||||
}
|
||||
return loggerConfig
|
||||
}
|
||||
|
|
|
@ -18,9 +18,6 @@ package nacos_server
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
|
@ -33,8 +30,6 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/monitor"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
|
@ -48,7 +43,7 @@ import (
|
|||
|
||||
type NacosServer struct {
|
||||
sync.RWMutex
|
||||
securityLogin security.AuthClient
|
||||
securityLogin security.SecurityProxy
|
||||
serverList []constant.ServerConfig
|
||||
httpAgent http_agent.IHttpAgent
|
||||
timeoutMs uint64
|
||||
|
@ -65,12 +60,16 @@ type NacosServer struct {
|
|||
}
|
||||
|
||||
func NewNacosServer(ctx context.Context, serverList []constant.ServerConfig, clientCfg constant.ClientConfig, httpAgent http_agent.IHttpAgent, timeoutMs uint64, endpoint string, endpointQueryHeader map[string][]string) (*NacosServer, error) {
|
||||
return NewNacosServerWithRamCredentialProvider(ctx, serverList, clientCfg, httpAgent, timeoutMs, endpoint, endpointQueryHeader, nil)
|
||||
}
|
||||
|
||||
func NewNacosServerWithRamCredentialProvider(ctx context.Context, serverList []constant.ServerConfig, clientCfg constant.ClientConfig, httpAgent http_agent.IHttpAgent, timeoutMs uint64, endpoint string, endpointQueryHeader map[string][]string, provider security.RamCredentialProvider) (*NacosServer, error) {
|
||||
severLen := len(serverList)
|
||||
if severLen == 0 && endpoint == "" {
|
||||
return &NacosServer{}, errors.New("both serverlist and endpoint are empty")
|
||||
}
|
||||
|
||||
securityLogin := security.NewAuthClient(clientCfg, serverList, httpAgent)
|
||||
securityLogin := security.NewSecurityProxyWithRamCredentialProvider(clientCfg, serverList, httpAgent, provider)
|
||||
|
||||
ns := NacosServer{
|
||||
serverList: serverList,
|
||||
|
@ -92,12 +91,7 @@ func NewNacosServer(ctx context.Context, serverList []constant.ServerConfig, cli
|
|||
ns.initRefreshSrvIfNeed(ctx)
|
||||
}
|
||||
|
||||
_, err := ns.securityLogin.Login()
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("login in err:%v", err)
|
||||
}
|
||||
|
||||
ns.securityLogin.Login()
|
||||
ns.securityLogin.AutoRefresh(ctx)
|
||||
return &ns, nil
|
||||
}
|
||||
|
@ -109,8 +103,6 @@ func (server *NacosServer) callConfigServer(api string, params map[string]string
|
|||
contextPath = constant.WEB_CONTEXT
|
||||
}
|
||||
|
||||
signHeaders := GetSignHeaders(params, newHeaders["secretKey"])
|
||||
|
||||
url := curServer + contextPath + api
|
||||
|
||||
headers := map[string][]string{}
|
||||
|
@ -130,10 +122,6 @@ func (server *NacosServer) callConfigServer(api string, params map[string]string
|
|||
}
|
||||
headers["RequestId"] = []string{uid.String()}
|
||||
headers["Content-Type"] = []string{"application/x-www-form-urlencoded;charset=utf-8"}
|
||||
headers["Spas-AccessKey"] = []string{newHeaders["accessKey"]}
|
||||
headers["Timestamp"] = []string{signHeaders["Timestamp"]}
|
||||
headers["Spas-Signature"] = []string{signHeaders["Spas-Signature"]}
|
||||
server.InjectSecurityInfo(params)
|
||||
|
||||
var response *http.Response
|
||||
response, err = server.httpAgent.Request(method, url, headers, timeoutMS, params)
|
||||
|
@ -177,8 +165,6 @@ func (server *NacosServer) callServer(api string, params map[string]string, meth
|
|||
headers["Request-Module"] = []string{"Naming"}
|
||||
headers["Content-Type"] = []string{"application/x-www-form-urlencoded;charset=utf-8"}
|
||||
|
||||
server.InjectSecurityInfo(params)
|
||||
|
||||
var response *http.Response
|
||||
response, err = server.httpAgent.Request(method, url, headers, server.timeoutMs, params)
|
||||
if err != nil {
|
||||
|
@ -206,7 +192,7 @@ func (server *NacosServer) ReqConfigApi(api string, params map[string]string, he
|
|||
return "", errors.New("server list is empty")
|
||||
}
|
||||
|
||||
server.InjectSecurityInfo(params)
|
||||
server.InjectSecurityInfo(params, security.BuildConfigResource(params["tenant"], params["group"], params["dataId"]))
|
||||
|
||||
//only one server,retry request when error
|
||||
var err error
|
||||
|
@ -240,8 +226,7 @@ func (server *NacosServer) ReqApi(api string, params map[string]string, method s
|
|||
return "", errors.New("server list is empty")
|
||||
}
|
||||
|
||||
server.InjectSecurityInfo(params)
|
||||
server.InjectSignForNamingHttp(params, config)
|
||||
server.InjectSecurityInfo(params, security.BuildNamingResource(params["namespaceId"], params["serviceName"], params["groupName"]))
|
||||
|
||||
//only one server,retry request when error
|
||||
var err error
|
||||
|
@ -356,47 +341,13 @@ func (server *NacosServer) GetServerList() []constant.ServerConfig {
|
|||
return server.serverList
|
||||
}
|
||||
|
||||
func (server *NacosServer) InjectSecurityInfo(param map[string]string) {
|
||||
accessToken := server.securityLogin.GetAccessToken()
|
||||
if accessToken != "" {
|
||||
param[constant.KEY_ACCESS_TOKEN] = accessToken
|
||||
func (server *NacosServer) InjectSecurityInfo(param map[string]string, resource security.RequestResource) {
|
||||
securityInfo := server.securityLogin.GetSecurityInfo(resource)
|
||||
for k, v := range securityInfo {
|
||||
param[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (server *NacosServer) InjectSignForNamingHttp(param map[string]string, clientConfig constant.ClientConfig) {
|
||||
if clientConfig.AccessKey == "" || clientConfig.SecretKey == "" {
|
||||
return
|
||||
}
|
||||
var signData string
|
||||
timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
|
||||
if serviceName, hasServiceName := param["serviceName"]; hasServiceName {
|
||||
if groupName, hasGroup := param["groupName"]; strings.Contains(serviceName, constant.SERVICE_INFO_SPLITER) || !hasGroup || groupName == "" {
|
||||
signData = timeStamp + constant.SERVICE_INFO_SPLITER + serviceName
|
||||
} else {
|
||||
signData = timeStamp + constant.SERVICE_INFO_SPLITER + util.GetGroupName(serviceName, groupName)
|
||||
}
|
||||
} else {
|
||||
signData = timeStamp
|
||||
}
|
||||
param["signature"] = signWithhmacSHA1Encrypt(signData, clientConfig.SecretKey)
|
||||
param["ak"] = clientConfig.AccessKey
|
||||
param["data"] = signData
|
||||
}
|
||||
|
||||
func (server *NacosServer) InjectSign(request rpc_request.IRequest, param map[string]string, clientConfig constant.ClientConfig) {
|
||||
if clientConfig.AccessKey == "" || clientConfig.SecretKey == "" {
|
||||
return
|
||||
}
|
||||
sts := request.GetStringToSign()
|
||||
if sts == "" {
|
||||
return
|
||||
}
|
||||
signature := signWithhmacSHA1Encrypt(sts, clientConfig.SecretKey)
|
||||
param["data"] = sts
|
||||
param["signature"] = signature
|
||||
param["ak"] = clientConfig.AccessKey
|
||||
}
|
||||
|
||||
func getAddress(cfg constant.ServerConfig) string {
|
||||
if strings.Index(cfg.IpAddr, "http://") >= 0 || strings.Index(cfg.IpAddr, "https://") >= 0 {
|
||||
return cfg.IpAddr + ":" + strconv.Itoa(int(cfg.Port))
|
||||
|
@ -404,69 +355,6 @@ func getAddress(cfg constant.ServerConfig) string {
|
|||
return cfg.Scheme + "://" + cfg.IpAddr + ":" + strconv.Itoa(int(cfg.Port))
|
||||
}
|
||||
|
||||
func GetSignHeadersFromRequest(cr rpc_request.IConfigRequest, secretKey string) map[string]string {
|
||||
resource := ""
|
||||
|
||||
if len(cr.GetTenant()) != 0 {
|
||||
resource = cr.GetTenant() + "+" + cr.GetGroup()
|
||||
} else {
|
||||
resource = cr.GetGroup()
|
||||
}
|
||||
|
||||
headers := map[string]string{}
|
||||
|
||||
timeStamp := strconv.FormatInt(util.CurrentMillis(), 10)
|
||||
headers["Timestamp"] = timeStamp
|
||||
|
||||
signature := ""
|
||||
|
||||
if resource == "" {
|
||||
signature = signWithhmacSHA1Encrypt(timeStamp, secretKey)
|
||||
} else {
|
||||
signature = signWithhmacSHA1Encrypt(resource+"+"+timeStamp, secretKey)
|
||||
}
|
||||
|
||||
headers["Spas-Signature"] = signature
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
func GetSignHeaders(params map[string]string, secretKey string) map[string]string {
|
||||
resource := ""
|
||||
|
||||
if len(params["tenant"]) != 0 {
|
||||
resource = params["tenant"] + "+" + params["group"]
|
||||
} else {
|
||||
resource = params["group"]
|
||||
}
|
||||
|
||||
headers := map[string]string{}
|
||||
|
||||
timeStamp := strconv.FormatInt(util.CurrentMillis(), 10)
|
||||
headers["Timestamp"] = timeStamp
|
||||
|
||||
signature := ""
|
||||
|
||||
if resource == "" {
|
||||
signature = signWithhmacSHA1Encrypt(timeStamp, secretKey)
|
||||
} else {
|
||||
signature = signWithhmacSHA1Encrypt(resource+"+"+timeStamp, secretKey)
|
||||
}
|
||||
|
||||
headers["Spas-Signature"] = signature
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
func signWithhmacSHA1Encrypt(encryptText, encryptKey string) string {
|
||||
//hmac ,use sha1
|
||||
key := []byte(encryptKey)
|
||||
mac := hmac.New(sha1.New, key)
|
||||
mac.Write([]byte(encryptText))
|
||||
|
||||
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
|
||||
func (server *NacosServer) GetNextServer() (constant.ServerConfig, error) {
|
||||
serverLen := len(server.GetServerList())
|
||||
if serverLen == 0 {
|
||||
|
@ -475,9 +363,3 @@ func (server *NacosServer) GetNextServer() (constant.ServerConfig, error) {
|
|||
index := atomic.AddInt32(&server.currentIndex, 1) % int32(serverLen)
|
||||
return server.GetServerList()[index], nil
|
||||
}
|
||||
|
||||
func (server *NacosServer) InjectSkAk(params map[string]string, clientConfig constant.ClientConfig) {
|
||||
if clientConfig.AccessKey != "" {
|
||||
params["Spas-AccessKey"] = clientConfig.AccessKey
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,11 @@ package nacos_server
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
|
||||
"testing"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -61,18 +63,18 @@ func buildNacosServer(clientConfig constant.ClientConfig) (*NacosServer, error)
|
|||
|
||||
func TestNacosServer_InjectSignForNamingHttp_NoAk(t *testing.T) {
|
||||
clientConfig := constant.ClientConfig{
|
||||
AccessKey: "123",
|
||||
SecretKey: "321",
|
||||
AccessKey: "",
|
||||
SecretKey: "",
|
||||
}
|
||||
server, err := buildNacosServer(clientConfig)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
param := make(map[string]string)
|
||||
param := make(map[string]string, 4)
|
||||
param["serviceName"] = "s-0"
|
||||
param["groupName"] = "g-0"
|
||||
server.InjectSignForNamingHttp(param, constant.ClientConfig{})
|
||||
server.InjectSecurityInfo(param, security.BuildNamingResource(param["namespaceId"], param["groupName"], param["serviceName"]))
|
||||
assert.Empty(t, param["ak"])
|
||||
assert.Empty(t, param["data"])
|
||||
assert.Empty(t, param["signature"])
|
||||
|
@ -88,10 +90,10 @@ func TestNacosServer_InjectSignForNamingHttp_WithGroup(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
param := make(map[string]string)
|
||||
param := make(map[string]string, 4)
|
||||
param["serviceName"] = "s-0"
|
||||
param["groupName"] = "g-0"
|
||||
server.InjectSignForNamingHttp(param, clientConfig)
|
||||
server.InjectSecurityInfo(param, security.BuildNamingResource(param["namespaceId"], param["groupName"], param["serviceName"]))
|
||||
assert.Equal(t, "123", param["ak"])
|
||||
assert.Contains(t, param["data"], "@@g-0@@s-0")
|
||||
_, has := param["signature"]
|
||||
|
@ -108,9 +110,9 @@ func TestNacosServer_InjectSignForNamingHttp_WithoutGroup(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
param := make(map[string]string)
|
||||
param := make(map[string]string, 4)
|
||||
param["serviceName"] = "s-0"
|
||||
server.InjectSignForNamingHttp(param, clientConfig)
|
||||
server.InjectSecurityInfo(param, security.BuildNamingResource(param["namespaceId"], param["groupName"], param["serviceName"]))
|
||||
assert.Equal(t, "123", param["ak"])
|
||||
assert.NotContains(t, param["data"], "@@g-0@@s-0")
|
||||
assert.Contains(t, param["data"], "@@s-0")
|
||||
|
@ -128,11 +130,11 @@ func TestNacosServer_InjectSignForNamingHttp_WithoutServiceName(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
param := make(map[string]string)
|
||||
param := make(map[string]string, 4)
|
||||
param["groupName"] = "g-0"
|
||||
server.InjectSignForNamingHttp(param, clientConfig)
|
||||
server.InjectSecurityInfo(param, security.BuildNamingResource(param["namespaceId"], param["groupName"], param["serviceName"]))
|
||||
assert.Equal(t, "123", param["ak"])
|
||||
assert.NotContains(t, param["data"], "@@")
|
||||
assert.Contains(t, param["data"], "@@")
|
||||
assert.Regexp(t, "\\d+", param["data"])
|
||||
_, has := param["signature"]
|
||||
assert.True(t, has)
|
||||
|
@ -148,8 +150,8 @@ func TestNacosServer_InjectSignForNamingHttp_WithoutServiceNameAndGroup(t *testi
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
param := make(map[string]string)
|
||||
server.InjectSignForNamingHttp(param, clientConfig)
|
||||
param := make(map[string]string, 4)
|
||||
server.InjectSecurityInfo(param, security.BuildNamingResource(param["namespaceId"], param["serviceName"], param["groupName"]))
|
||||
assert.Equal(t, "123", param["ak"])
|
||||
assert.NotContains(t, param["data"], "@@")
|
||||
assert.Regexp(t, "\\d+", param["data"])
|
||||
|
@ -178,5 +180,8 @@ func TestNacosServer_UpdateServerListForSecurityLogin(t *testing.T) {
|
|||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(t, server.GetServerList(), server.securityLogin.GetServerList())
|
||||
nacosAuthClient := server.securityLogin.Clients[0]
|
||||
client, ok := nacosAuthClient.(*security.NacosAuthClient)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, server.GetServerList(), client.GetServerList())
|
||||
}
|
||||
|
|
|
@ -18,15 +18,16 @@ package rpc
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
|
||||
nacos_grpc_service "github.com/nacos-group/nacos-sdk-go/v2/api/grpc"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_response"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/util"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
@ -86,7 +87,7 @@ func convertRequest(r rpc_request.IRequest) *nacos_grpc_service.Payload {
|
|||
}
|
||||
return &nacos_grpc_service.Payload{
|
||||
Metadata: &Metadata,
|
||||
Body: &any.Any{Value: []byte(r.GetBody(r))},
|
||||
Body: &anypb.Any{Value: []byte(r.GetBody(r))},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +98,6 @@ func convertResponse(r rpc_response.IResponse) *nacos_grpc_service.Payload {
|
|||
}
|
||||
return &nacos_grpc_service.Payload{
|
||||
Metadata: &Metadata,
|
||||
Body: &any.Any{Value: []byte(r.GetBody())},
|
||||
Body: &anypb.Any{Value: []byte(r.GetBody())},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
package rpc_request
|
||||
|
||||
import "github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
)
|
||||
|
||||
type ConfigRequest struct {
|
||||
*Request
|
||||
|
@ -51,7 +54,7 @@ func (r *ConfigRequest) GetTenant() string {
|
|||
return r.Tenant
|
||||
}
|
||||
|
||||
//request of listening a batch of configs.
|
||||
// request of listening a batch of configs.
|
||||
type ConfigBatchListenRequest struct {
|
||||
*ConfigRequest
|
||||
Listen bool `json:"listen"`
|
||||
|
@ -67,7 +70,7 @@ func NewConfigBatchListenRequest(cacheLen int) *ConfigBatchListenRequest {
|
|||
}
|
||||
|
||||
func (r *ConfigBatchListenRequest) GetRequestType() string {
|
||||
return "ConfigBatchListenRequest"
|
||||
return constant.CONFIG_BATCH_LISTEN_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ConfigChangeNotifyRequest struct {
|
||||
|
@ -79,7 +82,7 @@ func NewConfigChangeNotifyRequest(group, dataId, tenant string) *ConfigChangeNot
|
|||
}
|
||||
|
||||
func (r *ConfigChangeNotifyRequest) GetRequestType() string {
|
||||
return "ConfigChangeNotifyRequest"
|
||||
return constant.CONFIG_CHANGE_NOTIFY_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ConfigQueryRequest struct {
|
||||
|
@ -92,7 +95,7 @@ func NewConfigQueryRequest(group, dataId, tenant string) *ConfigQueryRequest {
|
|||
}
|
||||
|
||||
func (r *ConfigQueryRequest) GetRequestType() string {
|
||||
return "ConfigQueryRequest"
|
||||
return constant.CONFIG_QUERY_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ConfigPublishRequest struct {
|
||||
|
@ -108,7 +111,7 @@ func NewConfigPublishRequest(group, dataId, tenant, content, casMd5 string) *Con
|
|||
}
|
||||
|
||||
func (r *ConfigPublishRequest) GetRequestType() string {
|
||||
return "ConfigPublishRequest"
|
||||
return constant.CONFIG_PUBLISH_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ConfigRemoveRequest struct {
|
||||
|
@ -120,5 +123,5 @@ func NewConfigRemoveRequest(group, dataId, tenant string) *ConfigRemoveRequest {
|
|||
}
|
||||
|
||||
func (r *ConfigRemoveRequest) GetRequestType() string {
|
||||
return "ConfigRemoveRequest"
|
||||
return constant.CONFIG_REMOVE_REQUEST_NAME
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/model"
|
||||
)
|
||||
|
||||
|
@ -68,7 +69,7 @@ func NewInstanceRequest(namespace, serviceName, groupName, Type string, instance
|
|||
}
|
||||
|
||||
func (r *InstanceRequest) GetRequestType() string {
|
||||
return "InstanceRequest"
|
||||
return constant.INSTANCE_REQUEST_NAME
|
||||
}
|
||||
|
||||
type BatchInstanceRequest struct {
|
||||
|
@ -86,7 +87,7 @@ func NewBatchInstanceRequest(namespace, serviceName, groupName, Type string, ins
|
|||
}
|
||||
|
||||
func (r *BatchInstanceRequest) GetRequestType() string {
|
||||
return "BatchInstanceRequest"
|
||||
return constant.BATCH_INSTANCE_REQUEST_NAME
|
||||
}
|
||||
|
||||
type NotifySubscriberRequest struct {
|
||||
|
@ -95,7 +96,7 @@ type NotifySubscriberRequest struct {
|
|||
}
|
||||
|
||||
func (r *NotifySubscriberRequest) GetRequestType() string {
|
||||
return "NotifySubscriberRequest"
|
||||
return constant.NOTIFY_SUBSCRIBE_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ServiceListRequest struct {
|
||||
|
@ -115,7 +116,7 @@ func NewServiceListRequest(namespace, serviceName, groupName string, pageNo, pag
|
|||
}
|
||||
|
||||
func (r *ServiceListRequest) GetRequestType() string {
|
||||
return "ServiceListRequest"
|
||||
return constant.SERVICE_LIST_REQUEST_NAME
|
||||
}
|
||||
|
||||
type SubscribeServiceRequest struct {
|
||||
|
@ -133,7 +134,7 @@ func NewSubscribeServiceRequest(namespace, serviceName, groupName, clusters stri
|
|||
}
|
||||
|
||||
func (r *SubscribeServiceRequest) GetRequestType() string {
|
||||
return "SubscribeServiceRequest"
|
||||
return constant.SUBSCRIBE_SERVICE_REQUEST_NAME
|
||||
}
|
||||
|
||||
type ServiceQueryRequest struct {
|
||||
|
@ -153,5 +154,5 @@ func NewServiceQueryRequest(namespace, serviceName, groupName, cluster string, h
|
|||
}
|
||||
|
||||
func (r *ServiceQueryRequest) GetRequestType() string {
|
||||
return "ServiceQueryRequest"
|
||||
return constant.SERVICE_QUERY_REQUEST_NAME
|
||||
}
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NacosAuthClient struct {
|
||||
username string
|
||||
password string
|
||||
accessToken *atomic.Value
|
||||
tokenTtl int64
|
||||
lastRefreshTime int64
|
||||
tokenRefreshWindow int64
|
||||
agent http_agent.IHttpAgent
|
||||
clientCfg constant.ClientConfig
|
||||
serverCfgs []constant.ServerConfig
|
||||
}
|
||||
|
||||
func NewNacosAuthClient(clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig, agent http_agent.IHttpAgent) *NacosAuthClient {
|
||||
client := &NacosAuthClient{
|
||||
username: clientCfg.Username,
|
||||
password: clientCfg.Password,
|
||||
serverCfgs: serverCfgs,
|
||||
clientCfg: clientCfg,
|
||||
agent: agent,
|
||||
accessToken: &atomic.Value{},
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) GetAccessToken() string {
|
||||
v := ac.accessToken.Load()
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return v.(string)
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) GetSecurityInfo(resource RequestResource) map[string]string {
|
||||
var securityInfo = make(map[string]string, 4)
|
||||
v := ac.accessToken.Load()
|
||||
if v != nil {
|
||||
securityInfo[constant.KEY_ACCESS_TOKEN] = v.(string)
|
||||
}
|
||||
return securityInfo
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) AutoRefresh(ctx context.Context) {
|
||||
|
||||
// If the username is not set, the automatic refresh Token is not enabled
|
||||
|
||||
if ac.username == "" {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
var timer *time.Timer
|
||||
if lastLoginSuccess := ac.lastRefreshTime > 0 && ac.tokenTtl > 0 && ac.tokenRefreshWindow > 0; lastLoginSuccess {
|
||||
timer = time.NewTimer(time.Second * time.Duration(ac.tokenTtl-ac.tokenRefreshWindow))
|
||||
} else {
|
||||
timer = time.NewTimer(time.Second * time.Duration(5))
|
||||
}
|
||||
defer timer.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-timer.C:
|
||||
_, err := ac.Login()
|
||||
if err != nil {
|
||||
logger.Errorf("login has error %+v", err)
|
||||
timer.Reset(time.Second * time.Duration(5))
|
||||
} else {
|
||||
logger.Infof("login success, tokenTtl: %+v seconds, tokenRefreshWindow: %+v seconds", ac.tokenTtl, ac.tokenRefreshWindow)
|
||||
timer.Reset(time.Second * time.Duration(ac.tokenTtl-ac.tokenRefreshWindow))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) Login() (bool, error) {
|
||||
var throwable error = nil
|
||||
for i := 0; i < len(ac.serverCfgs); i++ {
|
||||
result, err := ac.login(ac.serverCfgs[i])
|
||||
throwable = err
|
||||
if result {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, throwable
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) UpdateServerList(serverList []constant.ServerConfig) {
|
||||
ac.serverCfgs = serverList
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) GetServerList() []constant.ServerConfig {
|
||||
return ac.serverCfgs
|
||||
}
|
||||
|
||||
func (ac *NacosAuthClient) login(server constant.ServerConfig) (bool, error) {
|
||||
if ac.lastRefreshTime > 0 && ac.tokenTtl > 0 {
|
||||
// We refresh 2 windows before expiration to ensure continuous availability
|
||||
tokenRefreshTime := ac.lastRefreshTime + ac.tokenTtl - 2*ac.tokenRefreshWindow
|
||||
if time.Now().Unix() < tokenRefreshTime {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
if ac.username == "" {
|
||||
ac.lastRefreshTime = time.Now().Unix()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
contextPath := server.ContextPath
|
||||
|
||||
if !strings.HasPrefix(contextPath, "/") {
|
||||
contextPath = "/" + contextPath
|
||||
}
|
||||
|
||||
if strings.HasSuffix(contextPath, "/") {
|
||||
contextPath = contextPath[0 : len(contextPath)-1]
|
||||
}
|
||||
|
||||
if server.Scheme == "" {
|
||||
server.Scheme = "http"
|
||||
}
|
||||
|
||||
reqUrl := server.Scheme + "://" + server.IpAddr + ":" + strconv.FormatInt(int64(server.Port), 10) + contextPath + "/v1/auth/users/login"
|
||||
|
||||
header := http.Header{
|
||||
"content-type": []string{"application/x-www-form-urlencoded"},
|
||||
}
|
||||
resp, err := ac.agent.Post(reqUrl, header, ac.clientCfg.TimeoutMs, map[string]string{
|
||||
"username": ac.username,
|
||||
"password": ac.password,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var bytes []byte
|
||||
bytes, err = io.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != constant.RESPONSE_CODE_SUCCESS {
|
||||
errMsg := string(bytes)
|
||||
return false, errors.New(errMsg)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(bytes, &result)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if val, ok := result[constant.KEY_ACCESS_TOKEN]; ok {
|
||||
ac.accessToken.Store(val)
|
||||
ac.lastRefreshTime = time.Now().Unix()
|
||||
ac.tokenTtl = int64(result[constant.KEY_TOKEN_TTL].(float64))
|
||||
ac.tokenRefreshWindow = ac.tokenTtl / 10
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// MockResponseBody creates a mock response body for testing
|
||||
type MockResponseBody struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (m *MockResponseBody) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewMockResponseBody(data interface{}) io.ReadCloser {
|
||||
var buf bytes.Buffer
|
||||
if str, ok := data.(string); ok {
|
||||
buf.WriteString(str)
|
||||
} else {
|
||||
enc := json.NewEncoder(&buf)
|
||||
enc.SetEscapeHTML(false)
|
||||
enc.Encode(data)
|
||||
}
|
||||
return &MockResponseBody{&buf}
|
||||
}
|
||||
|
||||
// MockHttpAgent implements http_agent.IHttpAgent for testing
|
||||
type MockHttpAgent struct {
|
||||
PostFunc func(url string, header http.Header, timeoutMs uint64, params map[string]string) (response *http.Response, err error)
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) Request(method string, url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
switch method {
|
||||
case http.MethodPost:
|
||||
return m.Post(url, header, timeoutMs, params)
|
||||
default:
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusMethodNotAllowed,
|
||||
Body: NewMockResponseBody("method not allowed"),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) RequestOnlyResult(method string, url string, header http.Header, timeoutMs uint64, params map[string]string) string {
|
||||
resp, err := m.Request(method, url, header, timeoutMs, params)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if resp.Body == nil {
|
||||
return ""
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) Get(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
return m.Request(http.MethodGet, url, header, timeoutMs, params)
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) Post(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
if m.PostFunc != nil {
|
||||
return m.PostFunc(url, header, timeoutMs, params)
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusNotImplemented,
|
||||
Body: NewMockResponseBody("not implemented"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) Delete(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
return m.Request(http.MethodDelete, url, header, timeoutMs, params)
|
||||
}
|
||||
|
||||
func (m *MockHttpAgent) Put(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
return m.Request(http.MethodPut, url, header, timeoutMs, params)
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_Login_Success(t *testing.T) {
|
||||
// Setup mock response
|
||||
mockResp := &http.Response{
|
||||
StatusCode: constant.RESPONSE_CODE_SUCCESS,
|
||||
Body: NewMockResponseBody(map[string]interface{}{
|
||||
constant.KEY_ACCESS_TOKEN: "test-token",
|
||||
constant.KEY_TOKEN_TTL: float64(10),
|
||||
}),
|
||||
}
|
||||
|
||||
mockAgent := &MockHttpAgent{
|
||||
PostFunc: func(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
// Verify request parameters
|
||||
assert.Equal(t, "test-user", params["username"])
|
||||
assert.Equal(t, "test-pass", params["password"])
|
||||
contentType := header["content-type"]
|
||||
assert.Equal(t, []string{"application/x-www-form-urlencoded"}, contentType)
|
||||
return mockResp, nil
|
||||
},
|
||||
}
|
||||
|
||||
// Create client config
|
||||
clientConfig := constant.ClientConfig{
|
||||
Username: "test-user",
|
||||
Password: "test-pass",
|
||||
TimeoutMs: 10000,
|
||||
}
|
||||
|
||||
serverConfigs := []constant.ServerConfig{
|
||||
{
|
||||
IpAddr: "127.0.0.1",
|
||||
Port: 8848,
|
||||
ContextPath: "/nacos",
|
||||
},
|
||||
}
|
||||
|
||||
client := NewNacosAuthClient(clientConfig, serverConfigs, mockAgent)
|
||||
|
||||
// Test login
|
||||
success, err := client.Login()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, success)
|
||||
|
||||
// Verify token is stored
|
||||
assert.Equal(t, "test-token", client.GetAccessToken())
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_Login_NoAuth(t *testing.T) {
|
||||
mockAgent := &MockHttpAgent{
|
||||
PostFunc: func(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
t.Fatal("Should not make HTTP call when no username is set")
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
clientConfig := constant.ClientConfig{}
|
||||
serverConfigs := []constant.ServerConfig{{}}
|
||||
|
||||
client := NewNacosAuthClient(clientConfig, serverConfigs, mockAgent)
|
||||
|
||||
success, err := client.Login()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, success)
|
||||
assert.Empty(t, client.GetAccessToken())
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_TokenRefresh(t *testing.T) {
|
||||
callCount := 0
|
||||
mockAgent := &MockHttpAgent{
|
||||
PostFunc: func(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
callCount++
|
||||
return &http.Response{
|
||||
StatusCode: constant.RESPONSE_CODE_SUCCESS,
|
||||
Body: NewMockResponseBody(map[string]interface{}{
|
||||
constant.KEY_ACCESS_TOKEN: "token-" + fmt.Sprintf("%d", callCount),
|
||||
constant.KEY_TOKEN_TTL: float64(1), // 1 second TTL for quick testing
|
||||
}),
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
clientConfig := constant.ClientConfig{
|
||||
Username: "test-user",
|
||||
Password: "test-pass",
|
||||
}
|
||||
|
||||
client := NewNacosAuthClient(clientConfig, []constant.ServerConfig{{IpAddr: "localhost"}}, mockAgent)
|
||||
|
||||
// Initial login
|
||||
success, err := client.Login()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, success)
|
||||
assert.Equal(t, "token-1", client.GetAccessToken())
|
||||
|
||||
// Wait for token to require refresh (1 second TTL)
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
// Second login should get new token
|
||||
success, err = client.Login()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, success)
|
||||
assert.Equal(t, "token-2", client.GetAccessToken())
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_AutoRefresh(t *testing.T) {
|
||||
callCount := 0
|
||||
tokenChan := make(chan string, 2)
|
||||
mockAgent := &MockHttpAgent{
|
||||
PostFunc: func(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
callCount++
|
||||
token := fmt.Sprintf("auto-token-%d", callCount)
|
||||
tokenChan <- token
|
||||
t.Logf("Mock server received request #%d, returning token: %s", callCount, token)
|
||||
return &http.Response{
|
||||
StatusCode: constant.RESPONSE_CODE_SUCCESS,
|
||||
Body: NewMockResponseBody(map[string]interface{}{
|
||||
constant.KEY_ACCESS_TOKEN: token,
|
||||
constant.KEY_TOKEN_TTL: float64(10), // 10 seconds TTL, resulting in 1s refresh window
|
||||
}),
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
clientConfig := constant.ClientConfig{
|
||||
Username: "test-user",
|
||||
Password: "test-pass",
|
||||
}
|
||||
|
||||
client := NewNacosAuthClient(clientConfig, []constant.ServerConfig{{IpAddr: "localhost"}}, mockAgent)
|
||||
|
||||
// First do a manual login
|
||||
t.Log("Performing initial manual login")
|
||||
success, err := client.Login()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, success)
|
||||
token1 := <-tokenChan // Get the token from the first login
|
||||
t.Logf("Initial login successful, token: %s", token1)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
// Start auto refresh
|
||||
t.Log("Starting auto refresh")
|
||||
client.AutoRefresh(ctx)
|
||||
|
||||
// Wait for token refresh (should happen after TTL-2*refreshWindow seconds = 8 seconds)
|
||||
// We'll wait a bit longer to account for any delays
|
||||
t.Log("Waiting for token refresh")
|
||||
var token2 string
|
||||
select {
|
||||
case token2 = <-tokenChan:
|
||||
t.Logf("Received refreshed token: %s", token2)
|
||||
case <-time.After(time.Second * 12):
|
||||
t.Fatal("Timeout waiting for token refresh")
|
||||
}
|
||||
|
||||
assert.NotEqual(t, token1, token2, "Token should have been refreshed")
|
||||
assert.Equal(t, "auto-token-1", token1, "First token should be auto-token-1")
|
||||
assert.Equal(t, "auto-token-2", token2, "Second token should be auto-token-2")
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_GetSecurityInfo(t *testing.T) {
|
||||
client := NewNacosAuthClient(constant.ClientConfig{}, []constant.ServerConfig{}, nil)
|
||||
|
||||
// When no token
|
||||
info := client.GetSecurityInfo(RequestResource{})
|
||||
assert.Empty(t, info[constant.KEY_ACCESS_TOKEN])
|
||||
|
||||
// When token exists
|
||||
mockToken := "test-security-token"
|
||||
client.accessToken.Store(mockToken)
|
||||
|
||||
info = client.GetSecurityInfo(RequestResource{})
|
||||
assert.Equal(t, mockToken, info[constant.KEY_ACCESS_TOKEN])
|
||||
}
|
||||
|
||||
func TestNacosAuthClient_LoginFailure(t *testing.T) {
|
||||
mockAgent := &MockHttpAgent{
|
||||
PostFunc: func(url string, header http.Header, timeoutMs uint64, params map[string]string) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusUnauthorized,
|
||||
Body: NewMockResponseBody("Invalid credentials"),
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
client := NewNacosAuthClient(
|
||||
constant.ClientConfig{Username: "wrong-user", Password: "wrong-pass"},
|
||||
[]constant.ServerConfig{{IpAddr: "localhost"}},
|
||||
mockAgent,
|
||||
)
|
||||
|
||||
success, err := client.Login()
|
||||
assert.Error(t, err)
|
||||
assert.False(t, success)
|
||||
assert.Empty(t, client.GetAccessToken())
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
)
|
||||
|
||||
type RamContext struct {
|
||||
SignatureRegionId string
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
SecurityToken string
|
||||
EphemeralAccessKeyId bool
|
||||
}
|
||||
|
||||
type RamAuthClient struct {
|
||||
clientConfig constant.ClientConfig
|
||||
ramCredentialProviders []RamCredentialProvider
|
||||
resourceInjector map[string]ResourceInjector
|
||||
matchedProvider RamCredentialProvider
|
||||
}
|
||||
|
||||
func NewRamAuthClient(clientCfg constant.ClientConfig) *RamAuthClient {
|
||||
var providers = []RamCredentialProvider{
|
||||
&RamRoleArnCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&EcsRamRoleCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&OIDCRoleArnCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&CredentialsURICredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&AutoRotateCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&StsTokenCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
&AccessKeyCredentialProvider{
|
||||
clientConfig: clientCfg,
|
||||
},
|
||||
}
|
||||
injectors := map[string]ResourceInjector{
|
||||
REQUEST_TYPE_NAMING: &NamingResourceInjector{},
|
||||
REQUEST_TYPE_CONFIG: &ConfigResourceInjector{},
|
||||
}
|
||||
return &RamAuthClient{
|
||||
clientConfig: clientCfg,
|
||||
ramCredentialProviders: providers,
|
||||
resourceInjector: injectors,
|
||||
}
|
||||
}
|
||||
|
||||
func NewRamAuthClientWithProvider(clientCfg constant.ClientConfig, ramCredentialProvider RamCredentialProvider) *RamAuthClient {
|
||||
ramAuthClient := NewRamAuthClient(clientCfg)
|
||||
if ramCredentialProvider != nil {
|
||||
ramAuthClient.ramCredentialProviders = append(ramAuthClient.ramCredentialProviders, ramCredentialProvider)
|
||||
}
|
||||
|
||||
return ramAuthClient
|
||||
}
|
||||
|
||||
func (rac *RamAuthClient) Login() (bool, error) {
|
||||
for _, provider := range rac.ramCredentialProviders {
|
||||
if provider.MatchProvider() {
|
||||
rac.matchedProvider = provider
|
||||
break
|
||||
}
|
||||
}
|
||||
if rac.matchedProvider == nil {
|
||||
return false, nil
|
||||
}
|
||||
err := rac.matchedProvider.Init()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (rac *RamAuthClient) GetSecurityInfo(resource RequestResource) map[string]string {
|
||||
var securityInfo = make(map[string]string, 4)
|
||||
if rac.matchedProvider == nil {
|
||||
return securityInfo
|
||||
}
|
||||
ramContext := rac.matchedProvider.GetCredentialsForNacosClient()
|
||||
rac.resourceInjector[resource.requestType].doInject(resource, ramContext, securityInfo)
|
||||
return securityInfo
|
||||
}
|
||||
|
||||
func (rac *RamAuthClient) UpdateServerList(serverList []constant.ServerConfig) {
|
||||
return
|
||||
}
|
|
@ -0,0 +1,380 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/aliyun/aliyun-secretsmanager-client-go/sdk"
|
||||
"github.com/aliyun/credentials-go/credentials"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
)
|
||||
|
||||
const (
|
||||
ENV_PREFIX string = "ALIBABA_CLOUD_"
|
||||
ACCESS_KEY_ID_KEY string = ENV_PREFIX + "ACCESS_KEY_ID"
|
||||
ACCESS_KEY_SECRET_KEY string = ENV_PREFIX + "ACCESS_KEY_SECRET"
|
||||
SECURITY_TOKEN_KEY string = ENV_PREFIX + "SECURITY_TOKEN"
|
||||
SIGNATURE_REGION_ID_KEY string = ENV_PREFIX + "SIGNATURE_REGION_ID"
|
||||
RAM_ROLE_NAME_KEY string = ENV_PREFIX + "RAM_ROLE_NAME"
|
||||
ROLE_ARN_KEY string = ENV_PREFIX + "ROLE_ARN"
|
||||
ROLE_SESSION_NAME_KEY string = ENV_PREFIX + "ROLE_SESSION_NAME"
|
||||
ROLE_SESSION_EXPIRATION_KEY string = ENV_PREFIX + "ROLE_SESSION_EXPIRATION"
|
||||
POLICY_KEY string = ENV_PREFIX + "POLICY"
|
||||
OIDC_PROVIDER_ARN_KEY string = ENV_PREFIX + "OIDC_PROVIDER_ARN"
|
||||
OIDC_TOKEN_FILE_KEY string = ENV_PREFIX + "OIDC_TOKEN_FILE"
|
||||
CREDENTIALS_URI_KEY string = ENV_PREFIX + "CREDENTIALS_URI"
|
||||
SECRET_NAME_KEY string = ENV_PREFIX + "SECRET_NAME"
|
||||
)
|
||||
|
||||
func GetNacosProperties(property string, envKey string) string {
|
||||
if property != "" {
|
||||
return property
|
||||
} else {
|
||||
return os.Getenv(envKey)
|
||||
}
|
||||
}
|
||||
|
||||
type RamCredentialProvider interface {
|
||||
MatchProvider() bool
|
||||
Init() error
|
||||
GetCredentialsForNacosClient() RamContext
|
||||
}
|
||||
|
||||
type AccessKeyCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
accessKey string
|
||||
secretKey string
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *AccessKeyCredentialProvider) MatchProvider() bool {
|
||||
accessKey := GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
secretKey := GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
return accessKey != "" && secretKey != ""
|
||||
}
|
||||
|
||||
func (provider *AccessKeyCredentialProvider) Init() error {
|
||||
provider.accessKey = GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
provider.secretKey = GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
if provider.clientConfig.RamConfig != nil {
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
} else {
|
||||
provider.signatureRegionId = ""
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *AccessKeyCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
ramContext := RamContext{
|
||||
AccessKey: provider.accessKey,
|
||||
SecretKey: provider.secretKey,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
}
|
||||
return ramContext
|
||||
}
|
||||
|
||||
type AutoRotateCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
secretManagerCacheClient *sdk.SecretManagerCacheClient
|
||||
secretName string
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *AutoRotateCredentialProvider) MatchProvider() bool {
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
secretName := GetNacosProperties(provider.clientConfig.RamConfig.SecretName, SECRET_NAME_KEY)
|
||||
return secretName != ""
|
||||
}
|
||||
|
||||
func (provider *AutoRotateCredentialProvider) Init() error {
|
||||
secretName := GetNacosProperties(provider.clientConfig.RamConfig.SecretName, SECRET_NAME_KEY)
|
||||
client, err := sdk.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
provider.secretManagerCacheClient = client
|
||||
provider.secretName = secretName
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *AutoRotateCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
if provider.secretManagerCacheClient == nil || provider.secretName == "" {
|
||||
return RamContext{}
|
||||
}
|
||||
secretInfo, err := provider.secretManagerCacheClient.GetSecretInfo(provider.secretName)
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
var m map[string]string
|
||||
err = json.Unmarshal([]byte(secretInfo.SecretValue), &m)
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
accessKeyId := m["AccessKeyId"]
|
||||
accessKeySecret := m["AccessKeySecret"]
|
||||
ramContext := RamContext{
|
||||
AccessKey: accessKeyId,
|
||||
SecretKey: accessKeySecret,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: false,
|
||||
}
|
||||
return ramContext
|
||||
}
|
||||
|
||||
type StsTokenCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
accessKey string
|
||||
secretKey string
|
||||
securityToken string
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *StsTokenCredentialProvider) MatchProvider() bool {
|
||||
accessKey := GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
secretKey := GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
stsToken := GetNacosProperties(provider.clientConfig.RamConfig.SecurityToken, SECURITY_TOKEN_KEY)
|
||||
return accessKey != "" && secretKey != "" && stsToken != ""
|
||||
}
|
||||
|
||||
func (provider *StsTokenCredentialProvider) Init() error {
|
||||
provider.accessKey = GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
provider.secretKey = GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
provider.securityToken = GetNacosProperties(provider.clientConfig.RamConfig.SecurityToken, SECURITY_TOKEN_KEY)
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *StsTokenCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
ramContext := RamContext{
|
||||
AccessKey: provider.accessKey,
|
||||
SecretKey: provider.secretKey,
|
||||
SecurityToken: provider.securityToken,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: true,
|
||||
}
|
||||
return ramContext
|
||||
}
|
||||
|
||||
type EcsRamRoleCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
credentialClient credentials.Credential
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *EcsRamRoleCredentialProvider) MatchProvider() bool {
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
ramRoleName := GetNacosProperties(provider.clientConfig.RamConfig.RamRoleName, RAM_ROLE_NAME_KEY)
|
||||
return ramRoleName != ""
|
||||
}
|
||||
|
||||
func (provider *EcsRamRoleCredentialProvider) Init() error {
|
||||
ramRoleName := GetNacosProperties(provider.clientConfig.RamConfig.RamRoleName, RAM_ROLE_NAME_KEY)
|
||||
credentialsConfig := new(credentials.Config).SetType("ecs_ram_role").SetRoleName(ramRoleName)
|
||||
credentialClient, err := credentials.NewCredential(credentialsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
provider.credentialClient = credentialClient
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *EcsRamRoleCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
if provider.credentialClient == nil {
|
||||
return RamContext{}
|
||||
}
|
||||
credential, err := provider.credentialClient.GetCredential()
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
ramContext := RamContext{
|
||||
AccessKey: *credential.AccessKeyId,
|
||||
SecretKey: *credential.AccessKeySecret,
|
||||
SecurityToken: *credential.SecurityToken,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: true,
|
||||
}
|
||||
return ramContext
|
||||
}
|
||||
|
||||
type RamRoleArnCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
credentialClient credentials.Credential
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *RamRoleArnCredentialProvider) MatchProvider() bool {
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
accessKey := GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
secretKey := GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
roleArn := GetNacosProperties(provider.clientConfig.RamConfig.RoleArn, ROLE_ARN_KEY)
|
||||
roleSessionName := GetNacosProperties(provider.clientConfig.RamConfig.RoleSessionName, ROLE_SESSION_NAME_KEY)
|
||||
oidcProviderArn := GetNacosProperties(provider.clientConfig.RamConfig.OIDCProviderArn, OIDC_PROVIDER_ARN_KEY)
|
||||
return accessKey == "" && secretKey == "" && roleArn != "" && roleSessionName != "" && oidcProviderArn == ""
|
||||
}
|
||||
|
||||
func (provider *RamRoleArnCredentialProvider) Init() error {
|
||||
accessKey := GetNacosProperties(provider.clientConfig.AccessKey, ACCESS_KEY_ID_KEY)
|
||||
secretKey := GetNacosProperties(provider.clientConfig.SecretKey, ACCESS_KEY_SECRET_KEY)
|
||||
roleArn := GetNacosProperties(provider.clientConfig.RamConfig.RoleArn, ROLE_ARN_KEY)
|
||||
roleSessionName := GetNacosProperties(provider.clientConfig.RamConfig.RoleSessionName, ROLE_SESSION_NAME_KEY)
|
||||
credentialsConfig := new(credentials.Config).SetType("ram_role_arn").
|
||||
SetAccessKeyId(accessKey).SetAccessKeySecret(secretKey).
|
||||
SetRoleArn(roleArn).SetRoleSessionName(roleSessionName)
|
||||
if roleSessionExpiration := GetNacosProperties(strconv.Itoa(provider.clientConfig.RamConfig.RoleSessionExpiration), ROLE_SESSION_EXPIRATION_KEY); roleSessionExpiration != "" {
|
||||
if roleSessionExpirationTime, err := strconv.Atoi(roleSessionExpiration); err == nil {
|
||||
if roleSessionExpirationTime == 0 {
|
||||
roleSessionExpirationTime = 3600
|
||||
}
|
||||
credentialsConfig.SetRoleSessionExpiration(roleSessionExpirationTime)
|
||||
}
|
||||
}
|
||||
policy := GetNacosProperties(provider.clientConfig.RamConfig.Policy, POLICY_KEY)
|
||||
if policy != "" {
|
||||
credentialsConfig.SetPolicy(policy)
|
||||
}
|
||||
credentialClient, err := credentials.NewCredential(credentialsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
provider.credentialClient = credentialClient
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *RamRoleArnCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
if provider.credentialClient == nil {
|
||||
return RamContext{}
|
||||
}
|
||||
credential, err := provider.credentialClient.GetCredential()
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
return RamContext{
|
||||
AccessKey: *credential.AccessKeyId,
|
||||
SecretKey: *credential.AccessKeySecret,
|
||||
SecurityToken: *credential.SecurityToken,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: true,
|
||||
}
|
||||
}
|
||||
|
||||
type OIDCRoleArnCredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
credentialClient credentials.Credential
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *OIDCRoleArnCredentialProvider) MatchProvider() bool {
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
roleArn := GetNacosProperties(provider.clientConfig.RamConfig.RoleArn, ROLE_ARN_KEY)
|
||||
roleSessionName := GetNacosProperties(provider.clientConfig.RamConfig.RoleSessionName, ROLE_SESSION_NAME_KEY)
|
||||
oidcProviderArn := GetNacosProperties(provider.clientConfig.RamConfig.OIDCProviderArn, OIDC_PROVIDER_ARN_KEY)
|
||||
oidcTokenFile := GetNacosProperties(provider.clientConfig.RamConfig.OIDCTokenFilePath, OIDC_TOKEN_FILE_KEY)
|
||||
return roleArn != "" && roleSessionName != "" && oidcProviderArn != "" && oidcTokenFile != ""
|
||||
}
|
||||
|
||||
func (provider *OIDCRoleArnCredentialProvider) Init() error {
|
||||
ramRoleArn := GetNacosProperties(provider.clientConfig.RamConfig.RoleArn, ROLE_ARN_KEY)
|
||||
roleSessionName := GetNacosProperties(provider.clientConfig.RamConfig.RoleSessionName, ROLE_SESSION_NAME_KEY)
|
||||
oidcProviderArn := GetNacosProperties(provider.clientConfig.RamConfig.OIDCProviderArn, OIDC_PROVIDER_ARN_KEY)
|
||||
oidcTokenFilePath := GetNacosProperties(provider.clientConfig.RamConfig.OIDCTokenFilePath, OIDC_TOKEN_FILE_KEY)
|
||||
credentialsConfig := new(credentials.Config).SetType("oidc_role_arn").
|
||||
SetRoleArn(ramRoleArn).SetRoleSessionName(roleSessionName).
|
||||
SetOIDCProviderArn(oidcProviderArn).SetOIDCTokenFilePath(oidcTokenFilePath)
|
||||
if roleSessionExpiration := GetNacosProperties(strconv.Itoa(provider.clientConfig.RamConfig.RoleSessionExpiration), ROLE_SESSION_EXPIRATION_KEY); roleSessionExpiration != "" {
|
||||
if roleSessionExpirationTime, err := strconv.Atoi(roleSessionExpiration); err == nil {
|
||||
if roleSessionExpirationTime == 0 {
|
||||
roleSessionExpirationTime = 3600
|
||||
}
|
||||
credentialsConfig.SetRoleSessionExpiration(roleSessionExpirationTime)
|
||||
}
|
||||
}
|
||||
policy := GetNacosProperties(provider.clientConfig.RamConfig.Policy, POLICY_KEY)
|
||||
if policy != "" {
|
||||
credentialsConfig.SetPolicy(policy)
|
||||
}
|
||||
credentialClient, err := credentials.NewCredential(credentialsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
provider.credentialClient = credentialClient
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *OIDCRoleArnCredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
if provider.credentialClient == nil {
|
||||
return RamContext{}
|
||||
}
|
||||
credential, err := provider.credentialClient.GetCredential()
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
return RamContext{
|
||||
AccessKey: *credential.AccessKeyId,
|
||||
SecretKey: *credential.AccessKeySecret,
|
||||
SecurityToken: *credential.SecurityToken,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: true,
|
||||
}
|
||||
}
|
||||
|
||||
type CredentialsURICredentialProvider struct {
|
||||
clientConfig constant.ClientConfig
|
||||
credentialClient credentials.Credential
|
||||
signatureRegionId string
|
||||
}
|
||||
|
||||
func (provider *CredentialsURICredentialProvider) MatchProvider() bool {
|
||||
if provider.clientConfig.RamConfig == nil {
|
||||
return false
|
||||
}
|
||||
credentialsURI := GetNacosProperties(provider.clientConfig.RamConfig.CredentialsURI, CREDENTIALS_URI_KEY)
|
||||
return credentialsURI != ""
|
||||
}
|
||||
|
||||
func (provider *CredentialsURICredentialProvider) Init() error {
|
||||
credentialsURI := GetNacosProperties(provider.clientConfig.RamConfig.CredentialsURI, CREDENTIALS_URI_KEY)
|
||||
credentialsConfig := new(credentials.Config).SetType("credentials_uri").SetURLCredential(credentialsURI)
|
||||
credentialClient, err := credentials.NewCredential(credentialsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
provider.credentialClient = credentialClient
|
||||
provider.signatureRegionId = GetNacosProperties(provider.clientConfig.RamConfig.SignatureRegionId, SIGNATURE_REGION_ID_KEY)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (provider *CredentialsURICredentialProvider) GetCredentialsForNacosClient() RamContext {
|
||||
if provider.credentialClient == nil {
|
||||
return RamContext{}
|
||||
}
|
||||
if provider.credentialClient == nil {
|
||||
return RamContext{}
|
||||
}
|
||||
credential, err := provider.credentialClient.GetCredential()
|
||||
if err != nil {
|
||||
return RamContext{}
|
||||
}
|
||||
return RamContext{
|
||||
AccessKey: *credential.AccessKeyId,
|
||||
SecretKey: *credential.AccessKeySecret,
|
||||
SecurityToken: *credential.SecurityToken,
|
||||
SignatureRegionId: provider.signatureRegionId,
|
||||
EphemeralAccessKeyId: true,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
)
|
||||
|
||||
type ResourceInjector interface {
|
||||
doInject(resource RequestResource, ramContext RamContext, param map[string]string)
|
||||
}
|
||||
|
||||
const (
|
||||
CONFIG_AK_FILED string = "Spas-AccessKey"
|
||||
NAMING_AK_FILED string = "ak"
|
||||
SECURITY_TOKEN_HEADER string = "Spas-SecurityToken"
|
||||
SIGNATURE_VERSION_HEADER string = "signatureVersion"
|
||||
SIGNATURE_VERSION_V4 string = "v4"
|
||||
SERVICE_INFO_SPLITER string = "@@"
|
||||
TIMESTAMP_HEADER string = "Timestamp"
|
||||
SIGNATURE_HEADER string = "Spas-Signature"
|
||||
)
|
||||
|
||||
type NamingResourceInjector struct {
|
||||
}
|
||||
|
||||
func (n *NamingResourceInjector) doInject(resource RequestResource, ramContext RamContext, param map[string]string) {
|
||||
param[NAMING_AK_FILED] = ramContext.AccessKey
|
||||
if ramContext.EphemeralAccessKeyId {
|
||||
param[SECURITY_TOKEN_HEADER] = ramContext.SecurityToken
|
||||
}
|
||||
secretKey := trySignatureWithV4(ramContext, param)
|
||||
signatures := n.calculateSignature(resource, secretKey, ramContext)
|
||||
for k, v := range signatures {
|
||||
param[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NamingResourceInjector) calculateSignature(resource RequestResource, secretKey string, ramContext RamContext) map[string]string {
|
||||
var result = make(map[string]string, 4)
|
||||
signData := n.getSignData(n.getGroupedServiceName(resource))
|
||||
signature, err := Sign(signData, secretKey)
|
||||
if err != nil {
|
||||
logger.Errorf("get v4 signatrue error: %v", err)
|
||||
return result
|
||||
}
|
||||
result["signature"] = signature
|
||||
result["data"] = signData
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *NamingResourceInjector) getGroupedServiceName(resource RequestResource) string {
|
||||
if strings.Contains(resource.resource, SERVICE_INFO_SPLITER) || resource.group == "" {
|
||||
return resource.resource
|
||||
}
|
||||
return resource.group + SERVICE_INFO_SPLITER + resource.resource
|
||||
}
|
||||
|
||||
func (n *NamingResourceInjector) getSignData(serviceName string) string {
|
||||
if serviceName != "" {
|
||||
return fmt.Sprintf("%d%s%s", time.Now().UnixMilli(), SERVICE_INFO_SPLITER, serviceName)
|
||||
}
|
||||
return fmt.Sprintf("%d", time.Now().UnixMilli())
|
||||
}
|
||||
|
||||
type ConfigResourceInjector struct {
|
||||
}
|
||||
|
||||
func (c *ConfigResourceInjector) doInject(resource RequestResource, ramContext RamContext, param map[string]string) {
|
||||
param[CONFIG_AK_FILED] = ramContext.AccessKey
|
||||
if ramContext.EphemeralAccessKeyId {
|
||||
param[SECURITY_TOKEN_HEADER] = ramContext.SecurityToken
|
||||
}
|
||||
secretKey := trySignatureWithV4(ramContext, param)
|
||||
signatures := c.calculateSignature(resource, secretKey, ramContext)
|
||||
for k, v := range signatures {
|
||||
param[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConfigResourceInjector) calculateSignature(resource RequestResource, secretKey string, ramContext RamContext) map[string]string {
|
||||
var result = make(map[string]string, 4)
|
||||
resourceName := c.getResourceName(resource)
|
||||
signHeaders := c.getSignHeaders(resourceName, secretKey)
|
||||
for k, v := range signHeaders {
|
||||
result[k] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *ConfigResourceInjector) getResourceName(resource RequestResource) string {
|
||||
if resource.namespace != "" {
|
||||
return resource.namespace + "+" + resource.group
|
||||
} else {
|
||||
return resource.group
|
||||
}
|
||||
}
|
||||
func (c *ConfigResourceInjector) getSignHeaders(resource, secretKey string) map[string]string {
|
||||
header := make(map[string]string, 4)
|
||||
timeStamp := fmt.Sprintf("%d", time.Now().UnixMilli())
|
||||
header[TIMESTAMP_HEADER] = timeStamp
|
||||
if secretKey != "" {
|
||||
var signature string
|
||||
if strings.TrimSpace(resource) == "" {
|
||||
signature = signWithHmacSha1Encrypt(timeStamp, secretKey)
|
||||
} else {
|
||||
signature = signWithHmacSha1Encrypt(resource+"+"+timeStamp, secretKey)
|
||||
}
|
||||
header[SIGNATURE_HEADER] = signature
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func trySignatureWithV4(ramContext RamContext, param map[string]string) string {
|
||||
if ramContext.SignatureRegionId == "" {
|
||||
return ramContext.SecretKey
|
||||
}
|
||||
signatureV4, err := finalSigningKeyStringWithDefaultInfo(ramContext.SecretKey, ramContext.SignatureRegionId)
|
||||
if err != nil {
|
||||
logger.Errorf("get v4 signatrue error: %v", err)
|
||||
return ramContext.SecretKey
|
||||
}
|
||||
param[SIGNATURE_VERSION_HEADER] = SIGNATURE_VERSION_V4
|
||||
return signatureV4
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_NamingResourceInjector_doInject(t *testing.T) {
|
||||
namingResourceInjector := NamingResourceInjector{}
|
||||
resource := BuildNamingResource("testNamespace", "testGroup", "testServiceName")
|
||||
t.Run("test_doInject_v4_sts", func(t *testing.T) {
|
||||
ramContext := RamContext{
|
||||
AccessKey: "testAccessKey",
|
||||
SecretKey: "testSecretKey",
|
||||
SecurityToken: "testSecurityToken",
|
||||
EphemeralAccessKeyId: true,
|
||||
SignatureRegionId: "testSignatureRegionId",
|
||||
}
|
||||
param := map[string]string{}
|
||||
namingResourceInjector.doInject(resource, ramContext, param)
|
||||
assert.Equal(t, param[NAMING_AK_FILED], ramContext.AccessKey)
|
||||
assert.Equal(t, param[SECURITY_TOKEN_HEADER], ramContext.SecurityToken)
|
||||
assert.Equal(t, param[SIGNATURE_VERSION_HEADER], SIGNATURE_VERSION_V4)
|
||||
assert.NotEmpty(t, param["signature"])
|
||||
})
|
||||
|
||||
t.Run("test_doInject", func(t *testing.T) {
|
||||
ramContext := RamContext{
|
||||
AccessKey: "testAccessKey",
|
||||
SecretKey: "testSecretKey",
|
||||
}
|
||||
param := map[string]string{}
|
||||
namingResourceInjector.doInject(resource, ramContext, param)
|
||||
assert.Equal(t, param[NAMING_AK_FILED], ramContext.AccessKey)
|
||||
assert.Empty(t, param[SECURITY_TOKEN_HEADER])
|
||||
assert.Empty(t, param[SIGNATURE_VERSION_HEADER])
|
||||
assert.NotEmpty(t, param["signature"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_NamingResourceInjector_getGroupedServiceName(t *testing.T) {
|
||||
namingResourceInjector := NamingResourceInjector{}
|
||||
t.Run("test_getGroupedServiceName", func(t *testing.T) {
|
||||
resource := BuildNamingResource("testNamespace", "testGroup", "testServiceName")
|
||||
assert.Equal(t, namingResourceInjector.getGroupedServiceName(resource), "testGroup@@testServiceName")
|
||||
})
|
||||
t.Run("test_getGroupedServiceName_without_group", func(t *testing.T) {
|
||||
resource := BuildNamingResource("testNamespace", "", "testServiceName")
|
||||
assert.Equal(t, namingResourceInjector.getGroupedServiceName(resource), "testServiceName")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ConfigResourceInjector_doInject(t *testing.T) {
|
||||
configResourceInjector := ConfigResourceInjector{}
|
||||
resource := BuildConfigResource("testTenant", "testGroup", "testDataId")
|
||||
t.Run("test_doInject_v4_sts", func(t *testing.T) {
|
||||
ramContext := RamContext{
|
||||
AccessKey: "testAccessKey",
|
||||
SecretKey: "testSecretKey",
|
||||
SecurityToken: "testSecurityToken",
|
||||
EphemeralAccessKeyId: true,
|
||||
SignatureRegionId: "testSignatureRegionId",
|
||||
}
|
||||
param := map[string]string{}
|
||||
configResourceInjector.doInject(resource, ramContext, param)
|
||||
assert.Equal(t, param[CONFIG_AK_FILED], ramContext.AccessKey)
|
||||
assert.Equal(t, param[SECURITY_TOKEN_HEADER], ramContext.SecurityToken)
|
||||
assert.Equal(t, param[SIGNATURE_VERSION_HEADER], SIGNATURE_VERSION_V4)
|
||||
assert.NotEmpty(t, param[SIGNATURE_HEADER])
|
||||
assert.NotEmpty(t, param[TIMESTAMP_HEADER])
|
||||
})
|
||||
|
||||
t.Run("test_doInject", func(t *testing.T) {
|
||||
ramContext := RamContext{
|
||||
AccessKey: "testAccessKey",
|
||||
SecretKey: "testSecretKey",
|
||||
}
|
||||
param := map[string]string{}
|
||||
configResourceInjector.doInject(resource, ramContext, param)
|
||||
assert.Equal(t, param[CONFIG_AK_FILED], ramContext.AccessKey)
|
||||
assert.Empty(t, param[SECURITY_TOKEN_HEADER])
|
||||
assert.Empty(t, param[SIGNATURE_VERSION_HEADER])
|
||||
assert.NotEmpty(t, param[SIGNATURE_HEADER])
|
||||
assert.NotEmpty(t, param[TIMESTAMP_HEADER])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ConfigResourceInjector_getResourceName(t *testing.T) {
|
||||
configResourceInjector := ConfigResourceInjector{}
|
||||
t.Run("test_getGroupedServiceName", func(t *testing.T) {
|
||||
resource := BuildConfigResource("testTenant", "testGroup", "testDataId")
|
||||
assert.Equal(t, configResourceInjector.getResourceName(resource), "testTenant+testGroup")
|
||||
})
|
||||
t.Run("test_getGroupedServiceName_without_group", func(t *testing.T) {
|
||||
resource := BuildConfigResource("testTenant", "", "testDataId")
|
||||
assert.Equal(t, configResourceInjector.getResourceName(resource), "testTenant+")
|
||||
})
|
||||
}
|
|
@ -18,81 +18,135 @@ package security
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/remote/rpc/rpc_request"
|
||||
)
|
||||
|
||||
type AuthClient struct {
|
||||
username string
|
||||
password string
|
||||
accessToken *atomic.Value
|
||||
tokenTtl int64
|
||||
lastRefreshTime int64
|
||||
tokenRefreshWindow int64
|
||||
agent http_agent.IHttpAgent
|
||||
clientCfg constant.ClientConfig
|
||||
serverCfgs []constant.ServerConfig
|
||||
type RequestResource struct {
|
||||
requestType string
|
||||
namespace string
|
||||
group string
|
||||
resource string
|
||||
}
|
||||
|
||||
func NewAuthClient(clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig, agent http_agent.IHttpAgent) AuthClient {
|
||||
client := AuthClient{
|
||||
username: clientCfg.Username,
|
||||
password: clientCfg.Password,
|
||||
serverCfgs: serverCfgs,
|
||||
clientCfg: clientCfg,
|
||||
agent: agent,
|
||||
accessToken: &atomic.Value{},
|
||||
}
|
||||
const (
|
||||
REQUEST_TYPE_CONFIG = "config"
|
||||
REQUEST_TYPE_NAMING = "naming"
|
||||
)
|
||||
|
||||
return client
|
||||
func BuildConfigResourceByRequest(request rpc_request.IRequest) RequestResource {
|
||||
if request.GetRequestType() == constant.CONFIG_QUERY_REQUEST_NAME {
|
||||
configQueryRequest := request.(*rpc_request.ConfigQueryRequest)
|
||||
return BuildConfigResource(configQueryRequest.Tenant, configQueryRequest.Group, configQueryRequest.DataId)
|
||||
}
|
||||
if request.GetRequestType() == constant.CONFIG_PUBLISH_REQUEST_NAME {
|
||||
configPublishRequest := request.(*rpc_request.ConfigPublishRequest)
|
||||
return BuildConfigResource(configPublishRequest.Tenant, configPublishRequest.Group, configPublishRequest.DataId)
|
||||
}
|
||||
if request.GetRequestType() == "ConfigRemoveRequest" {
|
||||
configRemoveRequest := request.(*rpc_request.ConfigRemoveRequest)
|
||||
return BuildConfigResource(configRemoveRequest.Tenant, configRemoveRequest.Group, configRemoveRequest.DataId)
|
||||
}
|
||||
return RequestResource{
|
||||
requestType: REQUEST_TYPE_CONFIG,
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AuthClient) GetAccessToken() string {
|
||||
v := ac.accessToken.Load()
|
||||
if v == nil {
|
||||
return ""
|
||||
func BuildNamingResourceByRequest(request rpc_request.IRequest) RequestResource {
|
||||
if request.GetRequestType() == constant.INSTANCE_REQUEST_NAME {
|
||||
instanceRequest := request.(*rpc_request.InstanceRequest)
|
||||
return BuildNamingResource(instanceRequest.Namespace, instanceRequest.GroupName, instanceRequest.ServiceName)
|
||||
}
|
||||
if request.GetRequestType() == constant.BATCH_INSTANCE_REQUEST_NAME {
|
||||
batchInstanceRequest := request.(*rpc_request.BatchInstanceRequest)
|
||||
return BuildNamingResource(batchInstanceRequest.Namespace, batchInstanceRequest.GroupName, batchInstanceRequest.ServiceName)
|
||||
}
|
||||
if request.GetRequestType() == constant.SERVICE_LIST_REQUEST_NAME {
|
||||
serviceListRequest := request.(*rpc_request.ServiceListRequest)
|
||||
return BuildNamingResource(serviceListRequest.Namespace, serviceListRequest.GroupName, serviceListRequest.ServiceName)
|
||||
}
|
||||
if request.GetRequestType() == constant.SERVICE_QUERY_REQUEST_NAME {
|
||||
serviceQueryRequest := request.(*rpc_request.ServiceQueryRequest)
|
||||
return BuildNamingResource(serviceQueryRequest.Namespace, serviceQueryRequest.GroupName, serviceQueryRequest.ServiceName)
|
||||
}
|
||||
if request.GetRequestType() == constant.SUBSCRIBE_SERVICE_REQUEST_NAME {
|
||||
subscribeServiceRequest := request.(*rpc_request.SubscribeServiceRequest)
|
||||
return BuildNamingResource(subscribeServiceRequest.Namespace, subscribeServiceRequest.GroupName, subscribeServiceRequest.ServiceName)
|
||||
}
|
||||
return RequestResource{
|
||||
requestType: REQUEST_TYPE_NAMING,
|
||||
}
|
||||
return v.(string)
|
||||
}
|
||||
|
||||
func (ac *AuthClient) AutoRefresh(ctx context.Context) {
|
||||
|
||||
// If the username is not set, the automatic refresh Token is not enabled
|
||||
|
||||
if ac.username == "" {
|
||||
return
|
||||
func BuildConfigResource(tenant, group, dataId string) RequestResource {
|
||||
return RequestResource{
|
||||
requestType: REQUEST_TYPE_CONFIG,
|
||||
namespace: tenant,
|
||||
group: group,
|
||||
resource: dataId,
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
var timer *time.Timer
|
||||
if lastLoginSuccess := ac.lastRefreshTime > 0 && ac.tokenTtl > 0 && ac.tokenRefreshWindow > 0; lastLoginSuccess {
|
||||
timer = time.NewTimer(time.Second * time.Duration(ac.tokenTtl-ac.tokenRefreshWindow))
|
||||
} else {
|
||||
timer = time.NewTimer(time.Second * time.Duration(5))
|
||||
func BuildNamingResource(namespace, group, serviceName string) RequestResource {
|
||||
return RequestResource{
|
||||
requestType: REQUEST_TYPE_NAMING,
|
||||
namespace: namespace,
|
||||
group: group,
|
||||
resource: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
type AuthClient interface {
|
||||
Login() (bool, error)
|
||||
GetSecurityInfo(resource RequestResource) map[string]string
|
||||
UpdateServerList(serverList []constant.ServerConfig)
|
||||
}
|
||||
|
||||
type SecurityProxy struct {
|
||||
Clients []AuthClient
|
||||
}
|
||||
|
||||
func (sp *SecurityProxy) Login() {
|
||||
for _, client := range sp.Clients {
|
||||
_, err := client.Login()
|
||||
if err != nil {
|
||||
logger.Errorf("login in err:%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sp *SecurityProxy) GetSecurityInfo(resource RequestResource) map[string]string {
|
||||
var securityInfo = make(map[string]string, 4)
|
||||
for _, client := range sp.Clients {
|
||||
info := client.GetSecurityInfo(resource)
|
||||
if info != nil {
|
||||
for k, v := range info {
|
||||
securityInfo[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return securityInfo
|
||||
}
|
||||
|
||||
func (sp *SecurityProxy) UpdateServerList(serverList []constant.ServerConfig) {
|
||||
for _, client := range sp.Clients {
|
||||
client.UpdateServerList(serverList)
|
||||
}
|
||||
}
|
||||
|
||||
func (sp *SecurityProxy) AutoRefresh(ctx context.Context) {
|
||||
go func() {
|
||||
var timer = time.NewTimer(time.Second * time.Duration(5))
|
||||
defer timer.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-timer.C:
|
||||
_, err := ac.Login()
|
||||
if err != nil {
|
||||
logger.Errorf("login has error %+v", err)
|
||||
timer.Reset(time.Second * time.Duration(5))
|
||||
} else {
|
||||
logger.Infof("login success, tokenTtl: %+v seconds, tokenRefreshWindow: %+v seconds", ac.tokenTtl, ac.tokenRefreshWindow)
|
||||
timer.Reset(time.Second * time.Duration(ac.tokenTtl-ac.tokenRefreshWindow))
|
||||
}
|
||||
sp.Login()
|
||||
timer.Reset(time.Second * time.Duration(5))
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
@ -100,83 +154,20 @@ func (ac *AuthClient) AutoRefresh(ctx context.Context) {
|
|||
}()
|
||||
}
|
||||
|
||||
func (ac *AuthClient) Login() (bool, error) {
|
||||
var throwable error = nil
|
||||
for i := 0; i < len(ac.serverCfgs); i++ {
|
||||
result, err := ac.login(ac.serverCfgs[i])
|
||||
throwable = err
|
||||
if result {
|
||||
return true, nil
|
||||
}
|
||||
func NewSecurityProxy(clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig, agent http_agent.IHttpAgent) SecurityProxy {
|
||||
var securityProxy = SecurityProxy{}
|
||||
securityProxy.Clients = []AuthClient{
|
||||
NewNacosAuthClient(clientCfg, serverCfgs, agent),
|
||||
NewRamAuthClient(clientCfg),
|
||||
}
|
||||
return false, throwable
|
||||
return securityProxy
|
||||
}
|
||||
|
||||
func (ac *AuthClient) UpdateServerList(serverList []constant.ServerConfig) {
|
||||
ac.serverCfgs = serverList
|
||||
}
|
||||
|
||||
func (ac *AuthClient) GetServerList() []constant.ServerConfig {
|
||||
return ac.serverCfgs
|
||||
}
|
||||
|
||||
func (ac *AuthClient) login(server constant.ServerConfig) (bool, error) {
|
||||
if ac.username != "" {
|
||||
contextPath := server.ContextPath
|
||||
|
||||
if !strings.HasPrefix(contextPath, "/") {
|
||||
contextPath = "/" + contextPath
|
||||
}
|
||||
|
||||
if strings.HasSuffix(contextPath, "/") {
|
||||
contextPath = contextPath[0 : len(contextPath)-1]
|
||||
}
|
||||
|
||||
if server.Scheme == "" {
|
||||
server.Scheme = "http"
|
||||
}
|
||||
|
||||
reqUrl := server.Scheme + "://" + server.IpAddr + ":" + strconv.FormatInt(int64(server.Port), 10) + contextPath + "/v1/auth/users/login"
|
||||
|
||||
header := http.Header{
|
||||
"content-type": []string{"application/x-www-form-urlencoded"},
|
||||
}
|
||||
resp, err := ac.agent.Post(reqUrl, header, ac.clientCfg.TimeoutMs, map[string]string{
|
||||
"username": ac.username,
|
||||
"password": ac.password,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var bytes []byte
|
||||
bytes, err = io.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != constant.RESPONSE_CODE_SUCCESS {
|
||||
errMsg := string(bytes)
|
||||
return false, errors.New(errMsg)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(bytes, &result)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if val, ok := result[constant.KEY_ACCESS_TOKEN]; ok {
|
||||
ac.accessToken.Store(val)
|
||||
ac.lastRefreshTime = time.Now().Unix()
|
||||
ac.tokenTtl = int64(result[constant.KEY_TOKEN_TTL].(float64))
|
||||
ac.tokenRefreshWindow = ac.tokenTtl / 10
|
||||
}
|
||||
func NewSecurityProxyWithRamCredentialProvider(clientCfg constant.ClientConfig, serverCfgs []constant.ServerConfig, agent http_agent.IHttpAgent, provider RamCredentialProvider) SecurityProxy {
|
||||
var securityProxy = SecurityProxy{}
|
||||
securityProxy.Clients = []AuthClient{
|
||||
NewNacosAuthClient(clientCfg, serverCfgs, agent),
|
||||
NewRamAuthClientWithProvider(clientCfg, provider),
|
||||
}
|
||||
return true, nil
|
||||
|
||||
return securityProxy
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package security
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
PREFIX = "aliyun_v4"
|
||||
CONSTANT = "aliyun_v4_request"
|
||||
V4_SIGN_DATE_FORMATTER = "20060102"
|
||||
SIGNATURE_V4_PRODUCE = "mse"
|
||||
)
|
||||
|
||||
func signWithHmacSha1Encrypt(encryptText, encryptKey string) string {
|
||||
key := []byte(encryptKey)
|
||||
mac := hmac.New(sha1.New, key)
|
||||
mac.Write([]byte(encryptText))
|
||||
expectedMAC := mac.Sum(nil)
|
||||
return base64.StdEncoding.EncodeToString(expectedMAC)
|
||||
}
|
||||
|
||||
func Sign(data, key string) (string, error) {
|
||||
signature, err := sign([]byte(data), []byte(key))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to calculate a request signature: %w", err)
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(signature), nil
|
||||
}
|
||||
|
||||
// sign 方法用于生成签名字节数组
|
||||
func sign(data, key []byte) ([]byte, error) {
|
||||
mac := hmac.New(sha1.New, key)
|
||||
if _, err := mac.Write(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mac.Sum(nil), nil
|
||||
}
|
||||
|
||||
func finalSigningKeyStringWithDefaultInfo(secret, region string) (string, error) {
|
||||
signDate := time.Now().UTC().Format(V4_SIGN_DATE_FORMATTER)
|
||||
return finalSigningKeyString(secret, signDate, region, SIGNATURE_V4_PRODUCE)
|
||||
}
|
||||
|
||||
func finalSigningKeyString(secret, date, region, productCode string) (string, error) {
|
||||
finalKey, err := finalSigningKey(secret, date, region, productCode)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(finalKey), nil
|
||||
}
|
||||
|
||||
func finalSigningKey(secret, date, region, productCode string) ([]byte, error) {
|
||||
secondSignkey, err := regionSigningKey(secret, date, region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mac := hmac.New(sha256.New, secondSignkey)
|
||||
_, err = mac.Write([]byte(productCode))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
thirdSigningKey := mac.Sum(nil)
|
||||
|
||||
mac = hmac.New(sha256.New, thirdSigningKey)
|
||||
_, err = mac.Write([]byte(CONSTANT))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mac.Sum(nil), nil
|
||||
}
|
||||
|
||||
func regionSigningKey(secret, date, region string) ([]byte, error) {
|
||||
firstSignkey, err := firstSigningKey(secret, date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mac := hmac.New(sha256.New, firstSignkey)
|
||||
_, err = mac.Write([]byte(region))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mac.Sum(nil), nil
|
||||
}
|
||||
|
||||
func firstSigningKey(secret, date string) ([]byte, error) {
|
||||
mac := hmac.New(sha256.New, []byte(PREFIX+secret))
|
||||
_, err := mac.Write([]byte(date))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mac.Sum(nil), nil
|
||||
}
|
57
go.mod
57
go.mod
|
@ -1,51 +1,72 @@
|
|||
module github.com/nacos-group/nacos-sdk-go/v2
|
||||
|
||||
go 1.18
|
||||
// v2.2.9 is deprecated due to a critical bug. Use v2.3.0 or later
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/alibabacloud-go/tea v1.1.17
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3
|
||||
github.com/alibabacloud-go/tea v1.2.2
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5
|
||||
github.com/aliyun/credentials-go v1.4.3
|
||||
github.com/buger/jsonparser v1.1.1
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.12.2
|
||||
github.com/stretchr/testify v1.8.1
|
||||
go.uber.org/zap v1.21.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/time v0.1.0
|
||||
google.golang.org/grpc v1.56.3
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
|
||||
google.golang.org/grpc v1.67.3
|
||||
google.golang.org/protobuf v1.36.5
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
)
|
||||
|
||||
require github.com/golang/protobuf v1.5.4 // indirect
|
||||
|
||||
require (
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 // indirect
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2 // indirect
|
||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4 // indirect
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.5.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/kr/text v0.1.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
176
go.sum
176
go.sum
|
@ -39,19 +39,67 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||
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/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 h1:NqugFkGxx1TXSh/pBcU00Y6bljgDPaFdh5MUSeJ7e50=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
|
||||
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.9/go.mod h1:bb+Io8Sn2RuM3/Rpme6ll86jMyFSrD1bxeV/+v61KeU=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE=
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
|
||||
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
|
||||
github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3 h1:vamGcYQFwXVqR6RWcrVTTqlIXZVsYjaA7pZbx+Xw6zw=
|
||||
github.com/alibabacloud-go/kms-20160120/v3 v3.2.3/go.mod h1:3rIyughsFDLie1ut9gQJXkWkMg/NfXBCk+OtXnPu3lw=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
|
||||
github.com/alibabacloud-go/tea v1.1.17 h1:05R5DnaJXe9sCNIe8KUgWHC/z6w/VZIwczgUwzRnul8=
|
||||
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA=
|
||||
github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU=
|
||||
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4 h1:lxCDvNCdTo9FaXKKq45+4vGETQUKNOW/qKTcX9Sk53o=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.4/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.3/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800 h1:ie/8RxBOfKZWcrbYSJi2Z8uX8TcOlSMwPlEJh83OeOw=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2 h1:rWkH6D2XlXb/Y+tNAQROxBzp3a0p92ni+pXcaHBe/WI=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2/go.mod h1:GDtq+Kw+v0fO+j5BrrWiUHbBq7L+hfpzpPfXKOZMFE0=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7 h1:olLiPI2iM8Hqq6vKnSxpM3awCrm9/BeOgHpzQkOYnI4=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7/go.mod h1:oDg1j4kFxnhgftaiLJABkGeSvuEvSF5Lo6UmRAMruX4=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 h1:nJYyoFP+aqGKgPs9JeZgS1rWQ4NndNR0Zfhh161ZltU=
|
||||
github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1/go.mod h1:WzGOmFFTlUzXM03CJnHWMQ85UN6QGpOXZocCjwkiyOg=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8 h1:QeUdR7JF7iNCvO/81EhxEr3wDwxk4YBoYZOq6E0AjHI=
|
||||
github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.8/go.mod h1:xP0KIZry6i7oGPF24vhAPr1Q8vLZRcMcxtft5xDKwCU=
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5 h1:8S0mtD101RDYa0LXwdoqgN0RxdMmmJYjq8g2mk7/lQ4=
|
||||
github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5/go.mod h1:M19fxYz3gpm0ETnoKweYyYtqrtnVtrpKFpwsghbw+cQ=
|
||||
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
|
||||
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
|
||||
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
|
||||
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/aliyun/credentials-go v1.4.3 h1:N3iHyvHRMyOwY1+0qBLSf3hb5JFiOujVSVuEpgeGttY=
|
||||
github.com/aliyun/credentials-go v1.4.3/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
|
@ -63,16 +111,20 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
|
|||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
|
||||
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
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/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
|
@ -118,8 +170,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
|
@ -131,7 +183,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
@ -145,6 +198,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
|
@ -159,13 +214,13 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
|
@ -181,6 +236,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc h1:Ak86L+yDSOzKFa7WM5bf5itSOo1e3Xh8bm5YCMUXIjQ=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
|
||||
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=
|
||||
|
@ -213,22 +272,32 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
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/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
|
@ -247,10 +316,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
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/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -282,6 +359,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
|||
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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
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=
|
||||
|
@ -310,10 +389,21 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
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/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -330,8 +420,10 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/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=
|
||||
|
@ -357,30 +449,56 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -392,6 +510,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
|||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
|
@ -420,6 +539,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
|
|||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
|
@ -428,6 +548,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
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=
|
||||
|
@ -483,8 +605,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
|||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -497,8 +619,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
|
|||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
|
||||
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8=
|
||||
google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -511,16 +633,20 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -70,27 +70,30 @@ func (u UUID) MarshalText() (text []byte, err error) {
|
|||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
// Following formats are supported:
|
||||
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
||||
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
|
||||
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
||||
// "6ba7b8109dad11d180b400c04fd430c8"
|
||||
//
|
||||
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
||||
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
|
||||
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
||||
// "6ba7b8109dad11d180b400c04fd430c8"
|
||||
//
|
||||
// ABNF for supported UUID text representation follows:
|
||||
// uuid := canonical | hashlike | braced | urn
|
||||
// plain := canonical | hashlike
|
||||
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
|
||||
// hashlike := 12hexoct
|
||||
// braced := '{' plain '}'
|
||||
// urn := URN ':' UUID-NID ':' plain
|
||||
// URN := 'urn'
|
||||
// UUID-NID := 'uuid'
|
||||
// 12hexoct := 6hexoct 6hexoct
|
||||
// 6hexoct := 4hexoct 2hexoct
|
||||
// 4hexoct := 2hexoct 2hexoct
|
||||
// 2hexoct := hexoct hexoct
|
||||
// hexoct := hexdig hexdig
|
||||
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
|
||||
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
|
||||
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
|
||||
//
|
||||
// uuid := canonical | hashlike | braced | urn
|
||||
// plain := canonical | hashlike
|
||||
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
|
||||
// hashlike := 12hexoct
|
||||
// braced := '{' plain '}'
|
||||
// urn := URN ':' UUID-NID ':' plain
|
||||
// URN := 'urn'
|
||||
// UUID-NID := 'uuid'
|
||||
// 12hexoct := 6hexoct 6hexoct
|
||||
// 6hexoct := 4hexoct 2hexoct
|
||||
// 4hexoct := 2hexoct 2hexoct
|
||||
// 2hexoct := hexoct hexoct
|
||||
// hexoct := hexdig hexdig
|
||||
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
|
||||
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
|
||||
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
|
||||
func (u *UUID) UnmarshalText(text []byte) (err error) {
|
||||
switch len(text) {
|
||||
case 32:
|
||||
|
|
|
@ -152,6 +152,7 @@ func (u *UUID) SetVariant(v byte) {
|
|||
// Must is a helper that wraps a call to a function returning (UUID, error)
|
||||
// and panics if the error is non-nil. It is intended for use in variable
|
||||
// initializations such as
|
||||
//
|
||||
// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
|
||||
func Must(u UUID, err error) UUID {
|
||||
if err != nil {
|
||||
|
|
|
@ -46,3 +46,9 @@ type ConfigContext struct {
|
|||
DataId string `json:"dataId"`
|
||||
Tenant string `json:"tenant"`
|
||||
}
|
||||
|
||||
type ConfigPageResult struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data ConfigPage `json:"data"`
|
||||
}
|
||||
|
|
|
@ -139,3 +139,12 @@ func DeepCopyMap(params map[string]string) map[string]string {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Contains(slice []string, item string) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -16,9 +16,13 @@
|
|||
|
||||
package vo
|
||||
|
||||
import "github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
import (
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
|
||||
"github.com/nacos-group/nacos-sdk-go/v2/common/security"
|
||||
)
|
||||
|
||||
type NacosClientParam struct {
|
||||
ClientConfig *constant.ClientConfig // optional
|
||||
ServerConfigs []constant.ServerConfig // optional
|
||||
ClientConfig *constant.ClientConfig // optional
|
||||
ServerConfigs []constant.ServerConfig // optional
|
||||
RamCredentialProvider security.RamCredentialProvider // optinal
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ type ConfigParam struct {
|
|||
Group string `param:"group"` //required
|
||||
Content string `param:"content"` //required
|
||||
Tag string `param:"tag"`
|
||||
ConfigTags string `param:"configTags"`
|
||||
AppName string `param:"appName"`
|
||||
BetaIps string `param:"betaIps"`
|
||||
CasMd5 string `param:"casMd5"`
|
||||
|
|
Loading…
Reference in New Issue