mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update kubernetes to v1.23.0
updating go dependency to latest kubernetes released version i.e v1.23.0 Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
42403e2ba7
commit
5762da3e91
2
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
generated
vendored
2
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
generated
vendored
@ -210,7 +210,7 @@ func (t *grpcTunnel) DialContext(ctx context.Context, protocol, address string)
|
||||
|
||||
klog.V(5).Infoln("DIAL_REQ sent to proxy server")
|
||||
|
||||
c := &conn{stream: t.stream}
|
||||
c := &conn{stream: t.stream, random: random}
|
||||
|
||||
select {
|
||||
case res := <-resCh:
|
||||
|
26
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
generated
vendored
26
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
generated
vendored
@ -35,6 +35,7 @@ const CloseTimeout = 10 * time.Second
|
||||
type conn struct {
|
||||
stream client.ProxyService_ProxyClient
|
||||
connID int64
|
||||
random int64
|
||||
readCh chan []byte
|
||||
closeCh chan string
|
||||
rdata []byte
|
||||
@ -113,13 +114,26 @@ func (c *conn) SetWriteDeadline(t time.Time) error {
|
||||
// proxy service to notify remote to drop the connection.
|
||||
func (c *conn) Close() error {
|
||||
klog.V(4).Infoln("closing connection")
|
||||
req := &client.Packet{
|
||||
Type: client.PacketType_CLOSE_REQ,
|
||||
Payload: &client.Packet_CloseRequest{
|
||||
CloseRequest: &client.CloseRequest{
|
||||
ConnectID: c.connID,
|
||||
var req *client.Packet
|
||||
if c.connID != 0 {
|
||||
req = &client.Packet{
|
||||
Type: client.PacketType_CLOSE_REQ,
|
||||
Payload: &client.Packet_CloseRequest{
|
||||
CloseRequest: &client.CloseRequest{
|
||||
ConnectID: c.connID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// Never received a DIAL response so no connection ID.
|
||||
req = &client.Packet{
|
||||
Type: client.PacketType_DIAL_CLS,
|
||||
Payload: &client.Packet_CloseDial{
|
||||
CloseDial: &client.CloseDial{
|
||||
Random: c.random,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
klog.V(5).InfoS("[tracing] send req", "type", req.Type)
|
||||
|
125
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client.pb.go
generated
vendored
125
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client.pb.go
generated
vendored
@ -47,6 +47,7 @@ const (
|
||||
PacketType_CLOSE_REQ PacketType = 2
|
||||
PacketType_CLOSE_RSP PacketType = 3
|
||||
PacketType_DATA PacketType = 4
|
||||
PacketType_DIAL_CLS PacketType = 5
|
||||
)
|
||||
|
||||
var PacketType_name = map[int32]string{
|
||||
@ -55,6 +56,7 @@ var PacketType_name = map[int32]string{
|
||||
2: "CLOSE_REQ",
|
||||
3: "CLOSE_RSP",
|
||||
4: "DATA",
|
||||
5: "DIAL_CLS",
|
||||
}
|
||||
|
||||
var PacketType_value = map[string]int32{
|
||||
@ -63,6 +65,7 @@ var PacketType_value = map[string]int32{
|
||||
"CLOSE_REQ": 2,
|
||||
"CLOSE_RSP": 3,
|
||||
"DATA": 4,
|
||||
"DIAL_CLS": 5,
|
||||
}
|
||||
|
||||
func (x PacketType) String() string {
|
||||
@ -103,6 +106,7 @@ type Packet struct {
|
||||
// *Packet_Data
|
||||
// *Packet_CloseRequest
|
||||
// *Packet_CloseResponse
|
||||
// *Packet_CloseDial
|
||||
Payload isPacket_Payload `protobuf_oneof:"payload"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@ -165,6 +169,10 @@ type Packet_CloseResponse struct {
|
||||
CloseResponse *CloseResponse `protobuf:"bytes,6,opt,name=closeResponse,proto3,oneof"`
|
||||
}
|
||||
|
||||
type Packet_CloseDial struct {
|
||||
CloseDial *CloseDial `protobuf:"bytes,7,opt,name=closeDial,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*Packet_DialRequest) isPacket_Payload() {}
|
||||
|
||||
func (*Packet_DialResponse) isPacket_Payload() {}
|
||||
@ -175,6 +183,8 @@ func (*Packet_CloseRequest) isPacket_Payload() {}
|
||||
|
||||
func (*Packet_CloseResponse) isPacket_Payload() {}
|
||||
|
||||
func (*Packet_CloseDial) isPacket_Payload() {}
|
||||
|
||||
func (m *Packet) GetPayload() isPacket_Payload {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
@ -217,6 +227,13 @@ func (m *Packet) GetCloseResponse() *CloseResponse {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Packet) GetCloseDial() *CloseDial {
|
||||
if x, ok := m.GetPayload().(*Packet_CloseDial); ok {
|
||||
return x.CloseDial
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// XXX_OneofWrappers is for the internal use of the proto package.
|
||||
func (*Packet) XXX_OneofWrappers() []interface{} {
|
||||
return []interface{}{
|
||||
@ -225,6 +242,7 @@ func (*Packet) XXX_OneofWrappers() []interface{} {
|
||||
(*Packet_Data)(nil),
|
||||
(*Packet_CloseRequest)(nil),
|
||||
(*Packet_CloseResponse)(nil),
|
||||
(*Packet_CloseDial)(nil),
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,6 +451,46 @@ func (m *CloseResponse) GetConnectID() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type CloseDial struct {
|
||||
// random id of the DialRequest
|
||||
Random int64 `protobuf:"varint,1,opt,name=random,proto3" json:"random,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CloseDial) Reset() { *m = CloseDial{} }
|
||||
func (m *CloseDial) String() string { return proto.CompactTextString(m) }
|
||||
func (*CloseDial) ProtoMessage() {}
|
||||
func (*CloseDial) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_fec4258d9ecd175d, []int{5}
|
||||
}
|
||||
|
||||
func (m *CloseDial) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CloseDial.Unmarshal(m, b)
|
||||
}
|
||||
func (m *CloseDial) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_CloseDial.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *CloseDial) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CloseDial.Merge(m, src)
|
||||
}
|
||||
func (m *CloseDial) XXX_Size() int {
|
||||
return xxx_messageInfo_CloseDial.Size(m)
|
||||
}
|
||||
func (m *CloseDial) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CloseDial.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CloseDial proto.InternalMessageInfo
|
||||
|
||||
func (m *CloseDial) GetRandom() int64 {
|
||||
if m != nil {
|
||||
return m.Random
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
// connectID to connect to
|
||||
ConnectID int64 `protobuf:"varint,1,opt,name=connectID,proto3" json:"connectID,omitempty"`
|
||||
@ -449,7 +507,7 @@ func (m *Data) Reset() { *m = Data{} }
|
||||
func (m *Data) String() string { return proto.CompactTextString(m) }
|
||||
func (*Data) ProtoMessage() {}
|
||||
func (*Data) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_fec4258d9ecd175d, []int{5}
|
||||
return fileDescriptor_fec4258d9ecd175d, []int{6}
|
||||
}
|
||||
|
||||
func (m *Data) XXX_Unmarshal(b []byte) error {
|
||||
@ -499,6 +557,7 @@ func init() {
|
||||
proto.RegisterType((*DialResponse)(nil), "DialResponse")
|
||||
proto.RegisterType((*CloseRequest)(nil), "CloseRequest")
|
||||
proto.RegisterType((*CloseResponse)(nil), "CloseResponse")
|
||||
proto.RegisterType((*CloseDial)(nil), "CloseDial")
|
||||
proto.RegisterType((*Data)(nil), "Data")
|
||||
}
|
||||
|
||||
@ -507,37 +566,39 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_fec4258d9ecd175d = []byte{
|
||||
// 472 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xd1, 0x6e, 0x9b, 0x30,
|
||||
0x14, 0x85, 0x00, 0x49, 0xb8, 0x21, 0x15, 0xb2, 0xa6, 0x09, 0x75, 0x93, 0x5a, 0xf1, 0x14, 0x55,
|
||||
0x0b, 0x54, 0xa9, 0x34, 0xed, 0x35, 0x0d, 0xa9, 0x52, 0xa9, 0x5a, 0x99, 0xd3, 0xa7, 0xee, 0x61,
|
||||
0xf2, 0xc0, 0x9a, 0x50, 0x18, 0x66, 0xb6, 0x97, 0x8d, 0x0f, 0xda, 0x7f, 0x4e, 0x18, 0x52, 0xc8,
|
||||
0xa4, 0x6d, 0x52, 0x9f, 0xe0, 0x1c, 0xdf, 0x73, 0x7c, 0x7d, 0xae, 0x0d, 0xf3, 0x1d, 0x2b, 0x0a,
|
||||
0x9a, 0xc8, 0x6c, 0x9f, 0xc9, 0x6a, 0x9e, 0xe4, 0x19, 0x2d, 0x64, 0x58, 0x72, 0x26, 0x59, 0xd8,
|
||||
0x82, 0xe6, 0x13, 0x28, 0xce, 0xff, 0x35, 0x80, 0x61, 0x4c, 0x92, 0x1d, 0x95, 0xe8, 0x0c, 0x4c,
|
||||
0x59, 0x95, 0xd4, 0xd3, 0xcf, 0xf5, 0xd9, 0xc9, 0x62, 0x12, 0x34, 0xf4, 0x43, 0x55, 0x52, 0xac,
|
||||
0x16, 0xd0, 0x25, 0x4c, 0xd2, 0x8c, 0xe4, 0x98, 0x7e, 0xfb, 0x4e, 0x85, 0xf4, 0x06, 0xe7, 0xfa,
|
||||
0x6c, 0xb2, 0x70, 0x82, 0xa8, 0xe3, 0x36, 0x1a, 0xee, 0x97, 0xa0, 0x2b, 0x70, 0x1a, 0x28, 0x4a,
|
||||
0x56, 0x08, 0xea, 0x19, 0x4a, 0x32, 0x6d, 0x25, 0x0d, 0xb9, 0xd1, 0xf0, 0x51, 0x11, 0x7a, 0x05,
|
||||
0x66, 0x4a, 0x24, 0xf1, 0x4c, 0x55, 0x6c, 0x05, 0x11, 0x91, 0x64, 0xa3, 0x61, 0x45, 0xd6, 0x8e,
|
||||
0x49, 0xce, 0x04, 0x3d, 0x34, 0x61, 0xb5, 0x8e, 0xab, 0x1e, 0x59, 0x3b, 0xf6, 0x8b, 0xd0, 0x5b,
|
||||
0x98, 0xb6, 0xb8, 0xed, 0x63, 0xa8, 0x54, 0x27, 0x07, 0xd5, 0x53, 0x23, 0xc7, 0x65, 0xd7, 0x36,
|
||||
0x8c, 0x4a, 0x52, 0xe5, 0x8c, 0xa4, 0xfe, 0x47, 0x98, 0xf4, 0xce, 0x89, 0x4e, 0x61, 0xac, 0xf2,
|
||||
0x4b, 0x58, 0xae, 0xf2, 0xb2, 0xf1, 0x13, 0x46, 0x1e, 0x8c, 0x48, 0x9a, 0x72, 0x2a, 0x84, 0x8a,
|
||||
0xc8, 0xc6, 0x07, 0x88, 0x5e, 0xc2, 0x90, 0x93, 0x22, 0x65, 0x5f, 0x55, 0x10, 0x06, 0x6e, 0x91,
|
||||
0xff, 0x08, 0x4e, 0x3f, 0x11, 0xf4, 0x02, 0x2c, 0xca, 0x39, 0xe3, 0xad, 0x75, 0x03, 0xd0, 0x6b,
|
||||
0xb0, 0x93, 0x66, 0xb6, 0xb7, 0x91, 0x72, 0x36, 0x70, 0x47, 0xfc, 0xd5, 0xfb, 0x0d, 0x38, 0xfd,
|
||||
0x6c, 0x8e, 0x5d, 0xf4, 0x3f, 0x5c, 0xfc, 0x15, 0x4c, 0x8f, 0x32, 0x79, 0x4e, 0x2b, 0xfe, 0x7b,
|
||||
0x30, 0xeb, 0x99, 0xfd, 0x7b, 0xab, 0xce, 0x79, 0xd0, 0x77, 0x46, 0xed, 0xf0, 0xeb, 0x43, 0x38,
|
||||
0xcd, 0xcc, 0x2f, 0x62, 0x80, 0xee, 0x2e, 0x22, 0x07, 0xc6, 0xd1, 0xed, 0xf2, 0xee, 0x13, 0x5e,
|
||||
0x7f, 0x70, 0xb5, 0x0e, 0x6d, 0x63, 0x57, 0x47, 0x53, 0xb0, 0x57, 0x77, 0xf7, 0xdb, 0xb5, 0x5a,
|
||||
0x1c, 0xf4, 0xe0, 0x36, 0x76, 0x0d, 0x34, 0x06, 0x33, 0x5a, 0x3e, 0x2c, 0x5d, 0xf3, 0xc2, 0x05,
|
||||
0x6b, 0xad, 0xb6, 0x1b, 0x81, 0xb1, 0xbe, 0xbf, 0x71, 0xb5, 0x45, 0x08, 0x4e, 0xcc, 0xd9, 0xcf,
|
||||
0x6a, 0x4b, 0xf9, 0x3e, 0x4b, 0x28, 0x3a, 0x03, 0x4b, 0x61, 0x34, 0x6a, 0xdf, 0xc1, 0xe9, 0xe1,
|
||||
0xc7, 0xd7, 0x66, 0xfa, 0xa5, 0x7e, 0x7d, 0xf3, 0x18, 0x89, 0xec, 0x8b, 0x08, 0x76, 0xef, 0x44,
|
||||
0x90, 0xb1, 0x90, 0x94, 0x99, 0xa0, 0x7c, 0x4f, 0xf9, 0xbc, 0xa0, 0xf2, 0x07, 0xe3, 0xbb, 0x79,
|
||||
0x59, 0xcb, 0xc3, 0xff, 0xbd, 0xc6, 0xcf, 0x43, 0x85, 0xae, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff,
|
||||
0x64, 0xe0, 0x62, 0xbe, 0xb8, 0x03, 0x00, 0x00,
|
||||
// 505 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x51, 0x8b, 0xd3, 0x40,
|
||||
0x18, 0x4c, 0xda, 0xa4, 0x6d, 0xbe, 0xa6, 0x47, 0x58, 0x44, 0xc2, 0x29, 0xdc, 0x11, 0x5f, 0x4a,
|
||||
0xb1, 0xe9, 0xd1, 0x03, 0xf1, 0xb5, 0xd7, 0xf4, 0xe8, 0x41, 0xf1, 0xea, 0xf6, 0x9e, 0x4e, 0x50,
|
||||
0xd6, 0x64, 0x91, 0xd0, 0x98, 0x8d, 0xbb, 0x6b, 0x35, 0x3f, 0xd3, 0x7f, 0x24, 0xd9, 0xa4, 0x4d,
|
||||
0x22, 0xa8, 0x70, 0x4f, 0xed, 0xcc, 0x7e, 0x33, 0x3b, 0x19, 0xbe, 0x85, 0xe9, 0x9e, 0xa5, 0x29,
|
||||
0x0d, 0x65, 0x7c, 0x88, 0x65, 0x3e, 0x0d, 0x93, 0x98, 0xa6, 0x72, 0x96, 0x71, 0x26, 0xd9, 0xac,
|
||||
0x02, 0xe5, 0x8f, 0xaf, 0x38, 0xef, 0x57, 0x07, 0x7a, 0x5b, 0x12, 0xee, 0xa9, 0x44, 0x17, 0x60,
|
||||
0xc8, 0x3c, 0xa3, 0xae, 0x7e, 0xa9, 0x8f, 0xcf, 0xe6, 0x43, 0xbf, 0xa4, 0x1f, 0xf2, 0x8c, 0x62,
|
||||
0x75, 0x80, 0xae, 0x60, 0x18, 0xc5, 0x24, 0xc1, 0xf4, 0xdb, 0x77, 0x2a, 0xa4, 0xdb, 0xb9, 0xd4,
|
||||
0xc7, 0xc3, 0xb9, 0xed, 0x07, 0x35, 0xb7, 0xd6, 0x70, 0x73, 0x04, 0x5d, 0x83, 0x5d, 0x42, 0x91,
|
||||
0xb1, 0x54, 0x50, 0xb7, 0xab, 0x24, 0xa3, 0x4a, 0x52, 0x92, 0x6b, 0x0d, 0xb7, 0x86, 0xd0, 0x0b,
|
||||
0x30, 0x22, 0x22, 0x89, 0x6b, 0xa8, 0x61, 0xd3, 0x0f, 0x88, 0x24, 0x6b, 0x0d, 0x2b, 0xb2, 0x70,
|
||||
0x0c, 0x13, 0x26, 0xe8, 0x31, 0x84, 0x59, 0x39, 0x2e, 0x1b, 0x64, 0xe1, 0xd8, 0x1c, 0x42, 0x6f,
|
||||
0x60, 0x54, 0xe1, 0x2a, 0x47, 0x4f, 0xa9, 0xce, 0x8e, 0xaa, 0x53, 0x90, 0xf6, 0x18, 0x9a, 0x80,
|
||||
0xa5, 0x88, 0x22, 0xae, 0xdb, 0x57, 0x1a, 0x28, 0x35, 0x05, 0xb3, 0xd6, 0x70, 0x7d, 0x7c, 0x63,
|
||||
0x41, 0x3f, 0x23, 0x79, 0xc2, 0x48, 0xe4, 0x7d, 0x80, 0x61, 0xa3, 0x13, 0x74, 0x0e, 0x03, 0xd5,
|
||||
0x75, 0xc8, 0x12, 0xd5, 0xad, 0x85, 0x4f, 0x18, 0xb9, 0xd0, 0x27, 0x51, 0xc4, 0xa9, 0x10, 0xaa,
|
||||
0x4e, 0x0b, 0x1f, 0x21, 0x7a, 0x0e, 0x3d, 0x4e, 0xd2, 0x88, 0x7d, 0x55, 0xa5, 0x75, 0x71, 0x85,
|
||||
0xbc, 0x47, 0xb0, 0x9b, 0xed, 0xa1, 0x67, 0x60, 0x52, 0xce, 0x19, 0xaf, 0xac, 0x4b, 0x80, 0x5e,
|
||||
0x82, 0x15, 0x96, 0x7b, 0x70, 0x17, 0x28, 0xe7, 0x2e, 0xae, 0x89, 0xbf, 0x7a, 0xbf, 0x06, 0xbb,
|
||||
0xd9, 0x63, 0xdb, 0x45, 0xff, 0xc3, 0xc5, 0x5b, 0xc2, 0xa8, 0xd5, 0xdf, 0x53, 0xa2, 0x78, 0xaf,
|
||||
0xc0, 0x3a, 0x15, 0xda, 0xc8, 0xa5, 0xb7, 0x72, 0xbd, 0x03, 0xa3, 0x58, 0x82, 0x7f, 0xe7, 0xa9,
|
||||
0xaf, 0xef, 0x34, 0xaf, 0x47, 0xd5, 0x36, 0x15, 0x5f, 0x6a, 0x97, 0x4b, 0x34, 0xf9, 0x08, 0x50,
|
||||
0x2f, 0x37, 0xb2, 0x61, 0x10, 0xdc, 0x2d, 0x36, 0x9f, 0xf0, 0xea, 0xbd, 0xa3, 0xd5, 0x68, 0xb7,
|
||||
0x75, 0x74, 0x34, 0x02, 0x6b, 0xb9, 0xb9, 0xdf, 0xad, 0xd4, 0x61, 0xa7, 0x01, 0x77, 0x5b, 0xa7,
|
||||
0x8b, 0x06, 0x60, 0x04, 0x8b, 0x87, 0x85, 0x63, 0x9c, 0x54, 0xcb, 0xcd, 0xce, 0x31, 0x27, 0x0e,
|
||||
0x98, 0x2b, 0x75, 0x79, 0x1f, 0xba, 0xab, 0xfb, 0x5b, 0x47, 0x9b, 0xcf, 0xc0, 0xde, 0x72, 0xf6,
|
||||
0x33, 0xdf, 0x51, 0x7e, 0x88, 0x43, 0x8a, 0x2e, 0xc0, 0x54, 0x18, 0xf5, 0xab, 0x67, 0x76, 0x7e,
|
||||
0xfc, 0xe3, 0x69, 0x63, 0xfd, 0x4a, 0xbf, 0xb9, 0x7d, 0x0c, 0x44, 0xfc, 0x45, 0xf8, 0xfb, 0xb7,
|
||||
0xc2, 0x8f, 0xd9, 0x8c, 0x64, 0xb1, 0xa0, 0xfc, 0x40, 0xf9, 0x34, 0xa5, 0xf2, 0x07, 0xe3, 0xfb,
|
||||
0x69, 0x56, 0xc8, 0x67, 0xff, 0x7b, 0xec, 0x9f, 0x7b, 0x0a, 0x5d, 0xff, 0x0e, 0x00, 0x00, 0xff,
|
||||
0xff, 0x38, 0x1b, 0xf6, 0x4f, 0x17, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
@ -29,6 +29,7 @@ enum PacketType {
|
||||
CLOSE_REQ = 2;
|
||||
CLOSE_RSP = 3;
|
||||
DATA = 4;
|
||||
DIAL_CLS = 5;
|
||||
}
|
||||
|
||||
enum Error {
|
||||
@ -45,6 +46,7 @@ message Packet {
|
||||
Data data = 4;
|
||||
CloseRequest closeRequest = 5;
|
||||
CloseResponse closeResponse = 6;
|
||||
CloseDial closeDial = 7;
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +85,11 @@ message CloseResponse {
|
||||
int64 connectID = 2;
|
||||
}
|
||||
|
||||
message CloseDial {
|
||||
// random id of the DialRequest
|
||||
int64 random = 1;
|
||||
}
|
||||
|
||||
message Data {
|
||||
// connectID to connect to
|
||||
int64 connectID = 1;
|
||||
|
40
vendor/sigs.k8s.io/controller-runtime/pkg/cache/cache.go
generated
vendored
40
vendor/sigs.k8s.io/controller-runtime/pkg/cache/cache.go
generated
vendored
@ -86,8 +86,13 @@ type Informer interface {
|
||||
HasSynced() bool
|
||||
}
|
||||
|
||||
// ObjectSelector is an alias name of internal.Selector.
|
||||
type ObjectSelector internal.Selector
|
||||
|
||||
// SelectorsByObject associate a client.Object's GVK to a field/label selector.
|
||||
type SelectorsByObject map[client.Object]internal.Selector
|
||||
// There is also `DefaultSelector` to set a global default (which will be overridden by
|
||||
// a more specific setting here, if any).
|
||||
type SelectorsByObject map[client.Object]ObjectSelector
|
||||
|
||||
// Options are the optional arguments for creating a new InformersMap object.
|
||||
type Options struct {
|
||||
@ -114,6 +119,10 @@ type Options struct {
|
||||
// [2] https://pkg.go.dev/k8s.io/apimachinery/pkg/fields#Set
|
||||
SelectorsByObject SelectorsByObject
|
||||
|
||||
// DefaultSelector will be used as selectors for all object types
|
||||
// that do not have a selector in SelectorsByObject defined.
|
||||
DefaultSelector ObjectSelector
|
||||
|
||||
// UnsafeDisableDeepCopyByObject indicates not to deep copy objects during get or
|
||||
// list objects per GVK at the specified object.
|
||||
// Be very careful with this, when enabled you must DeepCopy any object before mutating it,
|
||||
@ -129,7 +138,7 @@ func New(config *rest.Config, opts Options) (Cache, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selectorsByGVK, err := convertToSelectorsByGVK(opts.SelectorsByObject, opts.Scheme)
|
||||
selectorsByGVK, err := convertToSelectorsByGVK(opts.SelectorsByObject, opts.DefaultSelector, opts.Scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -150,21 +159,23 @@ func New(config *rest.Config, opts Options) (Cache, error) {
|
||||
// returned from cache get/list before mutating it.
|
||||
func BuilderWithOptions(options Options) NewCacheFunc {
|
||||
return func(config *rest.Config, opts Options) (Cache, error) {
|
||||
if opts.Scheme == nil {
|
||||
opts.Scheme = options.Scheme
|
||||
if options.Scheme == nil {
|
||||
options.Scheme = opts.Scheme
|
||||
}
|
||||
if opts.Mapper == nil {
|
||||
opts.Mapper = options.Mapper
|
||||
if options.Mapper == nil {
|
||||
options.Mapper = opts.Mapper
|
||||
}
|
||||
if options.Resync == nil {
|
||||
options.Resync = opts.Resync
|
||||
}
|
||||
if options.Namespace == "" {
|
||||
options.Namespace = opts.Namespace
|
||||
}
|
||||
if opts.Resync == nil {
|
||||
opts.Resync = options.Resync
|
||||
}
|
||||
if opts.Namespace == "" {
|
||||
opts.Namespace = options.Namespace
|
||||
}
|
||||
opts.SelectorsByObject = options.SelectorsByObject
|
||||
opts.UnsafeDisableDeepCopyByObject = options.UnsafeDisableDeepCopyByObject
|
||||
return New(config, opts)
|
||||
|
||||
return New(config, options)
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,15 +202,16 @@ func defaultOpts(config *rest.Config, opts Options) (Options, error) {
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func convertToSelectorsByGVK(selectorsByObject SelectorsByObject, scheme *runtime.Scheme) (internal.SelectorsByGVK, error) {
|
||||
func convertToSelectorsByGVK(selectorsByObject SelectorsByObject, defaultSelector ObjectSelector, scheme *runtime.Scheme) (internal.SelectorsByGVK, error) {
|
||||
selectorsByGVK := internal.SelectorsByGVK{}
|
||||
for object, selector := range selectorsByObject {
|
||||
gvk, err := apiutil.GVKForObject(object, scheme)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selectorsByGVK[gvk] = selector
|
||||
selectorsByGVK[gvk] = internal.Selector(selector)
|
||||
}
|
||||
selectorsByGVK[schema.GroupVersionKind{}] = internal.Selector(defaultSelector)
|
||||
return selectorsByGVK, nil
|
||||
}
|
||||
|
||||
|
28
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go
generated
vendored
28
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go
generated
vendored
@ -66,7 +66,7 @@ func newSpecificInformersMap(config *rest.Config,
|
||||
startWait: make(chan struct{}),
|
||||
createListWatcher: createListWatcher,
|
||||
namespace: namespace,
|
||||
selectors: selectors,
|
||||
selectors: selectors.forGVK,
|
||||
disableDeepCopy: disableDeepCopy,
|
||||
}
|
||||
return ip
|
||||
@ -131,7 +131,7 @@ type specificInformersMap struct {
|
||||
|
||||
// selectors are the label or field selectors that will be added to the
|
||||
// ListWatch ListOptions.
|
||||
selectors SelectorsByGVK
|
||||
selectors func(gvk schema.GroupVersionKind) Selector
|
||||
|
||||
// disableDeepCopy indicates not to deep copy objects during get or list objects.
|
||||
disableDeepCopy DisableDeepCopyByGVK
|
||||
@ -277,19 +277,19 @@ func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformer
|
||||
// Create a new ListWatch for the obj
|
||||
return &cache.ListWatch{
|
||||
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
res := listObj.DeepCopyObject()
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
isNamespaceScoped := namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot
|
||||
err := client.Get().NamespaceIfScoped(namespace, isNamespaceScoped).Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Do(ctx).Into(res)
|
||||
return res, err
|
||||
},
|
||||
// Setup the watch function
|
||||
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
// Watch needs to be set to true separately
|
||||
opts.Watch = true
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
isNamespaceScoped := namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot
|
||||
return client.Get().NamespaceIfScoped(namespace, isNamespaceScoped).Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec).Watch(ctx)
|
||||
},
|
||||
@ -319,8 +319,8 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
|
||||
// Create a new ListWatch for the obj
|
||||
return &cache.ListWatch{
|
||||
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
if namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot {
|
||||
return dynamicClient.Resource(mapping.Resource).Namespace(namespace).List(ctx, opts)
|
||||
}
|
||||
@ -328,10 +328,10 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
|
||||
},
|
||||
// Setup the watch function
|
||||
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
// Watch needs to be set to true separately
|
||||
opts.Watch = true
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
if namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot {
|
||||
return dynamicClient.Resource(mapping.Resource).Namespace(namespace).Watch(ctx, opts)
|
||||
}
|
||||
@ -366,13 +366,13 @@ func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersM
|
||||
// create the relevant listwatch
|
||||
return &cache.ListWatch{
|
||||
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
|
||||
var (
|
||||
list *metav1.PartialObjectMetadataList
|
||||
err error
|
||||
)
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
if namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot {
|
||||
list, err = client.Resource(mapping.Resource).Namespace(namespace).List(ctx, opts)
|
||||
} else {
|
||||
@ -387,7 +387,7 @@ func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersM
|
||||
},
|
||||
// Setup the watch function
|
||||
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
ip.selectors[gvk].ApplyToList(&opts)
|
||||
ip.selectors(gvk).ApplyToList(&opts)
|
||||
// Watch needs to be set to true separately
|
||||
opts.Watch = true
|
||||
|
||||
@ -395,7 +395,7 @@ func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersM
|
||||
watcher watch.Interface
|
||||
err error
|
||||
)
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors[gvk])
|
||||
namespace := restrictNamespaceBySelector(ip.namespace, ip.selectors(gvk))
|
||||
if namespace != "" && mapping.Scope.Name() != meta.RESTScopeNameRoot {
|
||||
watcher, err = client.Resource(mapping.Resource).Namespace(namespace).Watch(ctx, opts)
|
||||
} else {
|
||||
|
11
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/selector.go
generated
vendored
11
vendor/sigs.k8s.io/controller-runtime/pkg/cache/internal/selector.go
generated
vendored
@ -26,6 +26,17 @@ import (
|
||||
// SelectorsByGVK associate a GroupVersionKind to a field/label selector.
|
||||
type SelectorsByGVK map[schema.GroupVersionKind]Selector
|
||||
|
||||
func (s SelectorsByGVK) forGVK(gvk schema.GroupVersionKind) Selector {
|
||||
if specific, found := s[gvk]; found {
|
||||
return specific
|
||||
}
|
||||
if defaultSelector, found := s[schema.GroupVersionKind{}]; found {
|
||||
return defaultSelector
|
||||
}
|
||||
|
||||
return Selector{}
|
||||
}
|
||||
|
||||
// Selector specify the label/field selector to fill in ListOptions.
|
||||
type Selector struct {
|
||||
Label labels.Selector
|
||||
|
4
vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go
generated
vendored
4
vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
@ -125,7 +125,7 @@ func loadConfig(context string) (*rest.Config, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get current user: %v", err)
|
||||
}
|
||||
loadingRules.Precedence = append(loadingRules.Precedence, path.Join(u.HomeDir, clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName))
|
||||
loadingRules.Precedence = append(loadingRules.Precedence, filepath.Join(u.HomeDir, clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName))
|
||||
}
|
||||
|
||||
return loadConfigWithContext("", loadingRules, context)
|
||||
|
2
vendor/sigs.k8s.io/controller-runtime/pkg/cluster/cluster.go
generated
vendored
2
vendor/sigs.k8s.io/controller-runtime/pkg/cluster/cluster.go
generated
vendored
@ -245,7 +245,7 @@ func setOptionsDefaults(options Options) Options {
|
||||
}
|
||||
}
|
||||
|
||||
if options.Logger == nil {
|
||||
if options.Logger.GetSink() == nil {
|
||||
options.Logger = logf.RuntimeLog.WithName("cluster")
|
||||
}
|
||||
|
||||
|
1
vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/zz_generated.deepcopy.go
generated
vendored
1
vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/zz_generated.deepcopy.go
generated
vendored
@ -1,3 +1,4 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
2
vendor/sigs.k8s.io/controller-runtime/pkg/controller/controller.go
generated
vendored
2
vendor/sigs.k8s.io/controller-runtime/pkg/controller/controller.go
generated
vendored
@ -104,7 +104,7 @@ func NewUnmanaged(name string, mgr manager.Manager, options Options) (Controller
|
||||
return nil, fmt.Errorf("must specify Name for Controller")
|
||||
}
|
||||
|
||||
if options.Log == nil {
|
||||
if options.Log.GetSink() == nil {
|
||||
options.Log = mgr.GetLogger()
|
||||
}
|
||||
|
||||
|
16
vendor/sigs.k8s.io/controller-runtime/pkg/internal/httpserver/server.go
generated
vendored
Normal file
16
vendor/sigs.k8s.io/controller-runtime/pkg/internal/httpserver/server.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
package httpserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// New returns a new server with sane defaults.
|
||||
func New(handler http.Handler) *http.Server {
|
||||
return &http.Server{
|
||||
Handler: handler,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout
|
||||
ReadHeaderTimeout: 32 * time.Second,
|
||||
}
|
||||
}
|
98
vendor/sigs.k8s.io/controller-runtime/pkg/log/deleg.go
generated
vendored
98
vendor/sigs.k8s.io/controller-runtime/pkg/log/deleg.go
generated
vendored
@ -25,16 +25,15 @@ import (
|
||||
// loggerPromise knows how to populate a concrete logr.Logger
|
||||
// with options, given an actual base logger later on down the line.
|
||||
type loggerPromise struct {
|
||||
logger *DelegatingLogger
|
||||
logger *DelegatingLogSink
|
||||
childPromises []*loggerPromise
|
||||
promisesLock sync.Mutex
|
||||
|
||||
name *string
|
||||
tags []interface{}
|
||||
level int
|
||||
name *string
|
||||
tags []interface{}
|
||||
}
|
||||
|
||||
func (p *loggerPromise) WithName(l *DelegatingLogger, name string) *loggerPromise {
|
||||
func (p *loggerPromise) WithName(l *DelegatingLogSink, name string) *loggerPromise {
|
||||
res := &loggerPromise{
|
||||
logger: l,
|
||||
name: &name,
|
||||
@ -48,7 +47,7 @@ func (p *loggerPromise) WithName(l *DelegatingLogger, name string) *loggerPromis
|
||||
}
|
||||
|
||||
// WithValues provides a new Logger with the tags appended.
|
||||
func (p *loggerPromise) WithValues(l *DelegatingLogger, tags ...interface{}) *loggerPromise {
|
||||
func (p *loggerPromise) WithValues(l *DelegatingLogSink, tags ...interface{}) *loggerPromise {
|
||||
res := &loggerPromise{
|
||||
logger: l,
|
||||
tags: tags,
|
||||
@ -61,61 +60,53 @@ func (p *loggerPromise) WithValues(l *DelegatingLogger, tags ...interface{}) *lo
|
||||
return res
|
||||
}
|
||||
|
||||
func (p *loggerPromise) V(l *DelegatingLogger, level int) *loggerPromise {
|
||||
res := &loggerPromise{
|
||||
logger: l,
|
||||
level: level,
|
||||
promisesLock: sync.Mutex{},
|
||||
}
|
||||
|
||||
p.promisesLock.Lock()
|
||||
defer p.promisesLock.Unlock()
|
||||
p.childPromises = append(p.childPromises, res)
|
||||
return res
|
||||
}
|
||||
|
||||
// Fulfill instantiates the Logger with the provided logger.
|
||||
func (p *loggerPromise) Fulfill(parentLogger logr.Logger) {
|
||||
logger := logr.WithCallDepth(parentLogger, 1)
|
||||
func (p *loggerPromise) Fulfill(parentLogSink logr.LogSink) {
|
||||
sink := parentLogSink
|
||||
if p.name != nil {
|
||||
logger = logger.WithName(*p.name)
|
||||
sink = sink.WithName(*p.name)
|
||||
}
|
||||
|
||||
if p.tags != nil {
|
||||
logger = logger.WithValues(p.tags...)
|
||||
}
|
||||
if p.level != 0 {
|
||||
logger = logger.V(p.level)
|
||||
sink = sink.WithValues(p.tags...)
|
||||
}
|
||||
|
||||
p.logger.lock.Lock()
|
||||
p.logger.logger = logger
|
||||
p.logger.logger = sink
|
||||
p.logger.promise = nil
|
||||
p.logger.lock.Unlock()
|
||||
|
||||
for _, childPromise := range p.childPromises {
|
||||
childPromise.Fulfill(logger)
|
||||
childPromise.Fulfill(sink)
|
||||
}
|
||||
}
|
||||
|
||||
// DelegatingLogger is a logr.Logger that delegates to another logr.Logger.
|
||||
// DelegatingLogSink is a logsink that delegates to another logr.LogSink.
|
||||
// If the underlying promise is not nil, it registers calls to sub-loggers with
|
||||
// the logging factory to be populated later, and returns a new delegating
|
||||
// logger. It expects to have *some* logr.Logger set at all times (generally
|
||||
// a no-op logger before the promises are fulfilled).
|
||||
type DelegatingLogger struct {
|
||||
type DelegatingLogSink struct {
|
||||
lock sync.RWMutex
|
||||
logger logr.Logger
|
||||
logger logr.LogSink
|
||||
promise *loggerPromise
|
||||
info logr.RuntimeInfo
|
||||
}
|
||||
|
||||
// Init implements logr.LogSink.
|
||||
func (l *DelegatingLogSink) Init(info logr.RuntimeInfo) {
|
||||
l.lock.Lock()
|
||||
defer l.lock.Unlock()
|
||||
l.info = info
|
||||
}
|
||||
|
||||
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||
// flags might be used to set the logging verbosity and disable some info
|
||||
// logs.
|
||||
func (l *DelegatingLogger) Enabled() bool {
|
||||
func (l *DelegatingLogSink) Enabled(level int) bool {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
return l.logger.Enabled()
|
||||
return l.logger.Enabled(level)
|
||||
}
|
||||
|
||||
// Info logs a non-error message with the given key/value pairs as context.
|
||||
@ -124,10 +115,10 @@ func (l *DelegatingLogger) Enabled() bool {
|
||||
// the log line. The key/value pairs can then be used to add additional
|
||||
// variable information. The key/value pairs should alternate string
|
||||
// keys and arbitrary values.
|
||||
func (l *DelegatingLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
func (l *DelegatingLogSink) Info(level int, msg string, keysAndValues ...interface{}) {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
l.logger.Info(msg, keysAndValues...)
|
||||
l.logger.Info(level, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// Error logs an error, with the given message and key/value pairs as context.
|
||||
@ -138,33 +129,14 @@ func (l *DelegatingLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
// The msg field should be used to add context to any underlying error,
|
||||
// while the err field should be used to attach the actual error that
|
||||
// triggered this log line, if present.
|
||||
func (l *DelegatingLogger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
func (l *DelegatingLogSink) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
l.logger.Error(err, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// V returns an Logger value for a specific verbosity level, relative to
|
||||
// this Logger. In other words, V values are additive. V higher verbosity
|
||||
// level means a log message is less important. It's illegal to pass a log
|
||||
// level less than zero.
|
||||
func (l *DelegatingLogger) V(level int) logr.Logger {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
|
||||
if l.promise == nil {
|
||||
return l.logger.V(level)
|
||||
}
|
||||
|
||||
res := &DelegatingLogger{logger: l.logger}
|
||||
promise := l.promise.V(res, level)
|
||||
res.promise = promise
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// WithName provides a new Logger with the name appended.
|
||||
func (l *DelegatingLogger) WithName(name string) logr.Logger {
|
||||
func (l *DelegatingLogSink) WithName(name string) logr.LogSink {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
|
||||
@ -172,7 +144,7 @@ func (l *DelegatingLogger) WithName(name string) logr.Logger {
|
||||
return l.logger.WithName(name)
|
||||
}
|
||||
|
||||
res := &DelegatingLogger{logger: l.logger}
|
||||
res := &DelegatingLogSink{logger: l.logger}
|
||||
promise := l.promise.WithName(res, name)
|
||||
res.promise = promise
|
||||
|
||||
@ -180,7 +152,7 @@ func (l *DelegatingLogger) WithName(name string) logr.Logger {
|
||||
}
|
||||
|
||||
// WithValues provides a new Logger with the tags appended.
|
||||
func (l *DelegatingLogger) WithValues(tags ...interface{}) logr.Logger {
|
||||
func (l *DelegatingLogSink) WithValues(tags ...interface{}) logr.LogSink {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
|
||||
@ -188,7 +160,7 @@ func (l *DelegatingLogger) WithValues(tags ...interface{}) logr.Logger {
|
||||
return l.logger.WithValues(tags...)
|
||||
}
|
||||
|
||||
res := &DelegatingLogger{logger: l.logger}
|
||||
res := &DelegatingLogSink{logger: l.logger}
|
||||
promise := l.promise.WithValues(res, tags...)
|
||||
res.promise = promise
|
||||
|
||||
@ -198,16 +170,16 @@ func (l *DelegatingLogger) WithValues(tags ...interface{}) logr.Logger {
|
||||
// Fulfill switches the logger over to use the actual logger
|
||||
// provided, instead of the temporary initial one, if this method
|
||||
// has not been previously called.
|
||||
func (l *DelegatingLogger) Fulfill(actual logr.Logger) {
|
||||
func (l *DelegatingLogSink) Fulfill(actual logr.LogSink) {
|
||||
if l.promise != nil {
|
||||
l.promise.Fulfill(actual)
|
||||
}
|
||||
}
|
||||
|
||||
// NewDelegatingLogger constructs a new DelegatingLogger which uses
|
||||
// NewDelegatingLogSink constructs a new DelegatingLogSink which uses
|
||||
// the given logger before it's promise is fulfilled.
|
||||
func NewDelegatingLogger(initial logr.Logger) *DelegatingLogger {
|
||||
l := &DelegatingLogger{
|
||||
func NewDelegatingLogSink(initial logr.LogSink) *DelegatingLogSink {
|
||||
l := &DelegatingLogSink{
|
||||
logger: initial,
|
||||
promise: &loggerPromise{promisesLock: sync.Mutex{}},
|
||||
}
|
||||
|
21
vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go
generated
vendored
21
vendor/sigs.k8s.io/controller-runtime/pkg/log/log.go
generated
vendored
@ -47,14 +47,14 @@ func SetLogger(l logr.Logger) {
|
||||
defer loggerWasSetLock.Unlock()
|
||||
|
||||
loggerWasSet = true
|
||||
Log.Fulfill(l)
|
||||
dlog.Fulfill(l.GetSink())
|
||||
}
|
||||
|
||||
// It is safe to assume that if this wasn't set within the first 30 seconds of a binaries
|
||||
// lifetime, it will never get set. The DelegatingLogger causes a high number of memory
|
||||
// allocations when not given an actual Logger, so we set a NullLogger to avoid that.
|
||||
// lifetime, it will never get set. The DelegatingLogSink causes a high number of memory
|
||||
// allocations when not given an actual Logger, so we set a NullLogSink to avoid that.
|
||||
//
|
||||
// We need to keep the DelegatingLogger because we have various inits() that get a logger from
|
||||
// We need to keep the DelegatingLogSink because we have various inits() that get a logger from
|
||||
// here. They will always get executed before any code that imports controller-runtime
|
||||
// has a chance to run and hence to set an actual logger.
|
||||
func init() {
|
||||
@ -64,7 +64,7 @@ func init() {
|
||||
loggerWasSetLock.Lock()
|
||||
defer loggerWasSetLock.Unlock()
|
||||
if !loggerWasSet {
|
||||
Log.Fulfill(NullLogger{})
|
||||
dlog.Fulfill(NullLogSink{})
|
||||
}
|
||||
}()
|
||||
}
|
||||
@ -78,14 +78,17 @@ var (
|
||||
// to another logr.Logger. You *must* call SetLogger to
|
||||
// get any actual logging. If SetLogger is not called within
|
||||
// the first 30 seconds of a binaries lifetime, it will get
|
||||
// set to a NullLogger.
|
||||
var Log = NewDelegatingLogger(NullLogger{})
|
||||
// set to a NullLogSink.
|
||||
var (
|
||||
dlog = NewDelegatingLogSink(NullLogSink{})
|
||||
Log = logr.New(dlog)
|
||||
)
|
||||
|
||||
// FromContext returns a logger with predefined values from a context.Context.
|
||||
func FromContext(ctx context.Context, keysAndValues ...interface{}) logr.Logger {
|
||||
var log logr.Logger = Log
|
||||
log := Log
|
||||
if ctx != nil {
|
||||
if logger := logr.FromContext(ctx); logger != nil {
|
||||
if logger, err := logr.FromContext(ctx); err == nil {
|
||||
log = logger
|
||||
}
|
||||
}
|
||||
|
25
vendor/sigs.k8s.io/controller-runtime/pkg/log/null.go
generated
vendored
25
vendor/sigs.k8s.io/controller-runtime/pkg/log/null.go
generated
vendored
@ -24,37 +24,36 @@ import (
|
||||
// but avoids accidentally adding the testing flags to
|
||||
// all binaries.
|
||||
|
||||
// NullLogger is a logr.Logger that does nothing.
|
||||
type NullLogger struct{}
|
||||
// NullLogSink is a logr.Logger that does nothing.
|
||||
type NullLogSink struct{}
|
||||
|
||||
var _ logr.Logger = NullLogger{}
|
||||
var _ logr.LogSink = NullLogSink{}
|
||||
|
||||
// Init implements logr.LogSink.
|
||||
func (log NullLogSink) Init(logr.RuntimeInfo) {
|
||||
}
|
||||
|
||||
// Info implements logr.InfoLogger.
|
||||
func (NullLogger) Info(_ string, _ ...interface{}) {
|
||||
func (NullLogSink) Info(_ int, _ string, _ ...interface{}) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// Enabled implements logr.InfoLogger.
|
||||
func (NullLogger) Enabled() bool {
|
||||
func (NullLogSink) Enabled(level int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Error implements logr.Logger.
|
||||
func (NullLogger) Error(_ error, _ string, _ ...interface{}) {
|
||||
func (NullLogSink) Error(_ error, _ string, _ ...interface{}) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// V implements logr.Logger.
|
||||
func (log NullLogger) V(_ int) logr.Logger {
|
||||
return log
|
||||
}
|
||||
|
||||
// WithName implements logr.Logger.
|
||||
func (log NullLogger) WithName(_ string) logr.Logger {
|
||||
func (log NullLogSink) WithName(_ string) logr.LogSink {
|
||||
return log
|
||||
}
|
||||
|
||||
// WithValues implements logr.Logger.
|
||||
func (log NullLogger) WithValues(_ ...interface{}) logr.Logger {
|
||||
func (log NullLogSink) WithValues(_ ...interface{}) logr.LogSink {
|
||||
return log
|
||||
}
|
||||
|
492
vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go
generated
vendored
492
vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
@ -30,6 +31,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
@ -40,6 +42,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/cluster"
|
||||
"sigs.k8s.io/controller-runtime/pkg/config/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/internal/httpserver"
|
||||
intrec "sigs.k8s.io/controller-runtime/pkg/internal/recorder"
|
||||
"sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
|
||||
@ -61,17 +64,16 @@ const (
|
||||
var _ Runnable = &controllerManager{}
|
||||
|
||||
type controllerManager struct {
|
||||
sync.Mutex
|
||||
started bool
|
||||
|
||||
stopProcedureEngaged *int64
|
||||
errChan chan error
|
||||
runnables *runnables
|
||||
|
||||
// cluster holds a variety of methods to interact with a cluster. Required.
|
||||
cluster cluster.Cluster
|
||||
|
||||
// leaderElectionRunnables is the set of Controllers that the controllerManager injects deps into and Starts.
|
||||
// These Runnables are managed by lead election.
|
||||
leaderElectionRunnables []Runnable
|
||||
|
||||
// nonLeaderElectionRunnables is the set of webhook servers that the controllerManager injects deps into and Starts.
|
||||
// These Runnables will not be blocked by lead election.
|
||||
nonLeaderElectionRunnables []Runnable
|
||||
|
||||
// recorderProvider is used to generate event recorders that will be injected into Controllers
|
||||
// (and EventHandlers, Sources and Predicates).
|
||||
recorderProvider *intrec.Provider
|
||||
@ -104,12 +106,6 @@ type controllerManager struct {
|
||||
// Healthz probe handler
|
||||
healthzHandler *healthz.Handler
|
||||
|
||||
mu sync.Mutex
|
||||
started bool
|
||||
startedLeader bool
|
||||
healthzStarted bool
|
||||
errChan chan error
|
||||
|
||||
// controllerOptions are the global controller options.
|
||||
controllerOptions v1alpha1.ControllerConfigurationSpec
|
||||
|
||||
@ -117,25 +113,20 @@ type controllerManager struct {
|
||||
// If none is set, it defaults to log.Log global logger.
|
||||
logger logr.Logger
|
||||
|
||||
// leaderElectionStopped is an internal channel used to signal the stopping procedure that the
|
||||
// LeaderElection.Run(...) function has returned and the shutdown can proceed.
|
||||
leaderElectionStopped chan struct{}
|
||||
|
||||
// leaderElectionCancel is used to cancel the leader election. It is distinct from internalStopper,
|
||||
// because for safety reasons we need to os.Exit() when we lose the leader election, meaning that
|
||||
// it must be deferred until after gracefulShutdown is done.
|
||||
leaderElectionCancel context.CancelFunc
|
||||
|
||||
// leaderElectionStopped is an internal channel used to signal the stopping procedure that the
|
||||
// LeaderElection.Run(...) function has returned and the shutdown can proceed.
|
||||
leaderElectionStopped chan struct{}
|
||||
|
||||
// stop procedure engaged. In other words, we should not add anything else to the manager
|
||||
stopProcedureEngaged bool
|
||||
|
||||
// elected is closed when this manager becomes the leader of a group of
|
||||
// managers, either because it won a leader election or because no leader
|
||||
// election was configured.
|
||||
elected chan struct{}
|
||||
|
||||
caches []hasCache
|
||||
|
||||
// port is the port that the webhook server serves at.
|
||||
port int
|
||||
// host is the hostname that the webhook server binds to.
|
||||
@ -160,10 +151,6 @@ type controllerManager struct {
|
||||
// between tries of actions.
|
||||
retryPeriod time.Duration
|
||||
|
||||
// waitForRunnable is holding the number of runnables currently running so that
|
||||
// we can wait for them to exit before quitting the manager
|
||||
waitForRunnable sync.WaitGroup
|
||||
|
||||
// gracefulShutdownTimeout is the duration given to runnable to stop
|
||||
// before the manager actually returns on stop.
|
||||
gracefulShutdownTimeout time.Duration
|
||||
@ -192,36 +179,17 @@ type hasCache interface {
|
||||
|
||||
// Add sets dependencies on i, and adds it to the list of Runnables to start.
|
||||
func (cm *controllerManager) Add(r Runnable) error {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
if cm.stopProcedureEngaged {
|
||||
return errors.New("can't accept new runnable as stop procedure is already engaged")
|
||||
}
|
||||
cm.Lock()
|
||||
defer cm.Unlock()
|
||||
return cm.add(r)
|
||||
}
|
||||
|
||||
func (cm *controllerManager) add(r Runnable) error {
|
||||
// Set dependencies on the object
|
||||
if err := cm.SetFields(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var shouldStart bool
|
||||
|
||||
// Add the runnable to the leader election or the non-leaderelection list
|
||||
if leRunnable, ok := r.(LeaderElectionRunnable); ok && !leRunnable.NeedLeaderElection() {
|
||||
shouldStart = cm.started
|
||||
cm.nonLeaderElectionRunnables = append(cm.nonLeaderElectionRunnables, r)
|
||||
} else if hasCache, ok := r.(hasCache); ok {
|
||||
cm.caches = append(cm.caches, hasCache)
|
||||
} else {
|
||||
shouldStart = cm.startedLeader
|
||||
cm.leaderElectionRunnables = append(cm.leaderElectionRunnables, r)
|
||||
}
|
||||
|
||||
if shouldStart {
|
||||
// If already started, start the controller
|
||||
cm.startRunnable(r)
|
||||
}
|
||||
|
||||
return nil
|
||||
return cm.runnables.Add(r)
|
||||
}
|
||||
|
||||
// Deprecated: use the equivalent Options field to set a field. This method will be removed in v0.10.
|
||||
@ -244,13 +212,17 @@ func (cm *controllerManager) SetFields(i interface{}) error {
|
||||
|
||||
// AddMetricsExtraHandler adds extra handler served on path to the http server that serves metrics.
|
||||
func (cm *controllerManager) AddMetricsExtraHandler(path string, handler http.Handler) error {
|
||||
cm.Lock()
|
||||
defer cm.Unlock()
|
||||
|
||||
if cm.started {
|
||||
return fmt.Errorf("unable to add new metrics handler because metrics endpoint has already been created")
|
||||
}
|
||||
|
||||
if path == defaultMetricsEndpoint {
|
||||
return fmt.Errorf("overriding builtin %s endpoint is not allowed", defaultMetricsEndpoint)
|
||||
}
|
||||
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
|
||||
if _, found := cm.metricsExtraHandlers[path]; found {
|
||||
return fmt.Errorf("can't register extra handler by duplicate path %q on metrics http server", path)
|
||||
}
|
||||
@ -262,14 +234,10 @@ func (cm *controllerManager) AddMetricsExtraHandler(path string, handler http.Ha
|
||||
|
||||
// AddHealthzCheck allows you to add Healthz checker.
|
||||
func (cm *controllerManager) AddHealthzCheck(name string, check healthz.Checker) error {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
cm.Lock()
|
||||
defer cm.Unlock()
|
||||
|
||||
if cm.stopProcedureEngaged {
|
||||
return errors.New("can't accept new healthCheck as stop procedure is already engaged")
|
||||
}
|
||||
|
||||
if cm.healthzStarted {
|
||||
if cm.started {
|
||||
return fmt.Errorf("unable to add new checker because healthz endpoint has already been created")
|
||||
}
|
||||
|
||||
@ -283,15 +251,11 @@ func (cm *controllerManager) AddHealthzCheck(name string, check healthz.Checker)
|
||||
|
||||
// AddReadyzCheck allows you to add Readyz checker.
|
||||
func (cm *controllerManager) AddReadyzCheck(name string, check healthz.Checker) error {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
cm.Lock()
|
||||
defer cm.Unlock()
|
||||
|
||||
if cm.stopProcedureEngaged {
|
||||
return errors.New("can't accept new ready check as stop procedure is already engaged")
|
||||
}
|
||||
|
||||
if cm.healthzStarted {
|
||||
return fmt.Errorf("unable to add new checker because readyz endpoint has already been created")
|
||||
if cm.started {
|
||||
return fmt.Errorf("unable to add new checker because healthz endpoint has already been created")
|
||||
}
|
||||
|
||||
if cm.readyzHandler == nil {
|
||||
@ -344,7 +308,7 @@ func (cm *controllerManager) GetWebhookServer() *webhook.Server {
|
||||
}
|
||||
}
|
||||
if err := cm.Add(cm.webhookServer); err != nil {
|
||||
panic("unable to add webhook server to the controller manager")
|
||||
panic(fmt.Sprintf("unable to add webhook server to the controller manager: %s", err))
|
||||
}
|
||||
})
|
||||
return cm.webhookServer
|
||||
@ -365,79 +329,89 @@ func (cm *controllerManager) serveMetrics() {
|
||||
// TODO(JoelSpeed): Use existing Kubernetes machinery for serving metrics
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(defaultMetricsEndpoint, handler)
|
||||
|
||||
func() {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
|
||||
for path, extraHandler := range cm.metricsExtraHandlers {
|
||||
mux.Handle(path, extraHandler)
|
||||
}
|
||||
}()
|
||||
|
||||
server := http.Server{
|
||||
Handler: mux,
|
||||
for path, extraHandler := range cm.metricsExtraHandlers {
|
||||
mux.Handle(path, extraHandler)
|
||||
}
|
||||
// Run the server
|
||||
cm.startRunnable(RunnableFunc(func(_ context.Context) error {
|
||||
cm.logger.Info("Starting metrics server", "path", defaultMetricsEndpoint)
|
||||
if err := server.Serve(cm.metricsListener); err != nil && err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
// Shutdown the server when stop is closed
|
||||
<-cm.internalProceduresStop
|
||||
if err := server.Shutdown(cm.shutdownCtx); err != nil {
|
||||
cm.errChan <- err
|
||||
}
|
||||
server := httpserver.New(mux)
|
||||
go cm.httpServe("metrics", cm.logger.WithValues("path", defaultMetricsEndpoint), server, cm.metricsListener)
|
||||
}
|
||||
|
||||
func (cm *controllerManager) serveHealthProbes() {
|
||||
mux := http.NewServeMux()
|
||||
server := http.Server{
|
||||
Handler: mux,
|
||||
server := httpserver.New(mux)
|
||||
|
||||
if cm.readyzHandler != nil {
|
||||
mux.Handle(cm.readinessEndpointName, http.StripPrefix(cm.readinessEndpointName, cm.readyzHandler))
|
||||
// Append '/' suffix to handle subpaths
|
||||
mux.Handle(cm.readinessEndpointName+"/", http.StripPrefix(cm.readinessEndpointName, cm.readyzHandler))
|
||||
}
|
||||
if cm.healthzHandler != nil {
|
||||
mux.Handle(cm.livenessEndpointName, http.StripPrefix(cm.livenessEndpointName, cm.healthzHandler))
|
||||
// Append '/' suffix to handle subpaths
|
||||
mux.Handle(cm.livenessEndpointName+"/", http.StripPrefix(cm.livenessEndpointName, cm.healthzHandler))
|
||||
}
|
||||
|
||||
func() {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
go cm.httpServe("health probe", cm.logger, server, cm.healthProbeListener)
|
||||
}
|
||||
|
||||
if cm.readyzHandler != nil {
|
||||
mux.Handle(cm.readinessEndpointName, http.StripPrefix(cm.readinessEndpointName, cm.readyzHandler))
|
||||
// Append '/' suffix to handle subpaths
|
||||
mux.Handle(cm.readinessEndpointName+"/", http.StripPrefix(cm.readinessEndpointName, cm.readyzHandler))
|
||||
}
|
||||
if cm.healthzHandler != nil {
|
||||
mux.Handle(cm.livenessEndpointName, http.StripPrefix(cm.livenessEndpointName, cm.healthzHandler))
|
||||
// Append '/' suffix to handle subpaths
|
||||
mux.Handle(cm.livenessEndpointName+"/", http.StripPrefix(cm.livenessEndpointName, cm.healthzHandler))
|
||||
}
|
||||
|
||||
// Run server
|
||||
cm.startRunnable(RunnableFunc(func(_ context.Context) error {
|
||||
if err := server.Serve(cm.healthProbeListener); err != nil && err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
cm.healthzStarted = true
|
||||
}()
|
||||
func (cm *controllerManager) httpServe(kind string, log logr.Logger, server *http.Server, ln net.Listener) {
|
||||
log = log.WithValues("kind", kind, "addr", ln.Addr())
|
||||
|
||||
go func() {
|
||||
// Shutdown the server when stop is closed
|
||||
<-cm.internalProceduresStop
|
||||
if err := server.Shutdown(cm.shutdownCtx); err != nil {
|
||||
log.Info("Starting server")
|
||||
if err := server.Serve(ln); err != nil {
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
return
|
||||
}
|
||||
if atomic.LoadInt64(cm.stopProcedureEngaged) > 0 {
|
||||
// There might be cases where connections are still open and we try to shutdown
|
||||
// but not having enough time to close the connection causes an error in Serve
|
||||
//
|
||||
// In that case we want to avoid returning an error to the main error channel.
|
||||
log.Error(err, "error on Serve after stop has been engaged")
|
||||
return
|
||||
}
|
||||
cm.errChan <- err
|
||||
}
|
||||
}()
|
||||
|
||||
// Shutdown the server when stop is closed.
|
||||
<-cm.internalProceduresStop
|
||||
if err := server.Shutdown(cm.shutdownCtx); err != nil {
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
// Avoid logging context related errors.
|
||||
return
|
||||
}
|
||||
if atomic.LoadInt64(cm.stopProcedureEngaged) > 0 {
|
||||
cm.logger.Error(err, "error on Shutdown after stop has been engaged")
|
||||
return
|
||||
}
|
||||
cm.errChan <- err
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the manager and waits indefinitely.
|
||||
// There is only two ways to have start return:
|
||||
// An error has occurred during in one of the internal operations,
|
||||
// such as leader election, cache start, webhooks, and so on.
|
||||
// Or, the context is cancelled.
|
||||
func (cm *controllerManager) Start(ctx context.Context) (err error) {
|
||||
if err := cm.Add(cm.cluster); err != nil {
|
||||
return fmt.Errorf("failed to add cluster to runnables: %w", err)
|
||||
cm.Lock()
|
||||
if cm.started {
|
||||
cm.Unlock()
|
||||
return errors.New("manager already started")
|
||||
}
|
||||
var ready bool
|
||||
defer func() {
|
||||
// Only unlock the manager if we haven't reached
|
||||
// the internal readiness condition.
|
||||
if !ready {
|
||||
cm.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
// Initialize the internal context.
|
||||
cm.internalCtx, cm.internalCancel = context.WithCancel(ctx)
|
||||
|
||||
// This chan indicates that stop is complete, in other words all runnables have returned or timeout on stop request
|
||||
@ -459,45 +433,70 @@ func (cm *controllerManager) Start(ctx context.Context) (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
// initialize this here so that we reset the signal channel state on every start
|
||||
// Everything that might write into this channel must be started in a new goroutine,
|
||||
// because otherwise we might block this routine trying to write into the full channel
|
||||
// and will not be able to enter the deferred cm.engageStopProcedure() which drains
|
||||
// it.
|
||||
cm.errChan = make(chan error)
|
||||
// Add the cluster runnable.
|
||||
if err := cm.add(cm.cluster); err != nil {
|
||||
return fmt.Errorf("failed to add cluster to runnables: %w", err)
|
||||
}
|
||||
|
||||
// Metrics should be served whether the controller is leader or not.
|
||||
// (If we don't serve metrics for non-leaders, prometheus will still scrape
|
||||
// the pod but will get a connection refused)
|
||||
// the pod but will get a connection refused).
|
||||
if cm.metricsListener != nil {
|
||||
go cm.serveMetrics()
|
||||
cm.serveMetrics()
|
||||
}
|
||||
|
||||
// Serve health probes
|
||||
// Serve health probes.
|
||||
if cm.healthProbeListener != nil {
|
||||
cm.serveHealthProbes()
|
||||
}
|
||||
|
||||
// Webhooks MUST start before any cache is populated, otherwise there is a race condition
|
||||
// First start any webhook servers, which includes conversion, validation, and defaulting
|
||||
// webhooks that are registered.
|
||||
//
|
||||
// WARNING: Webhooks MUST start before any cache is populated, otherwise there is a race condition
|
||||
// between conversion webhooks and the cache sync (usually initial list) which causes the webhooks
|
||||
// to never start because no cache can be populated.
|
||||
cm.startWebhookRunnables()
|
||||
|
||||
go cm.startNonLeaderElectionRunnables()
|
||||
|
||||
go func() {
|
||||
if cm.resourceLock != nil {
|
||||
err := cm.startLeaderElection()
|
||||
if err != nil {
|
||||
cm.errChan <- err
|
||||
}
|
||||
} else {
|
||||
// Treat not having leader election enabled the same as being elected.
|
||||
cm.startLeaderElectionRunnables()
|
||||
close(cm.elected)
|
||||
if err := cm.runnables.Webhooks.Start(cm.internalCtx); err != nil {
|
||||
if err != wait.ErrWaitTimeout {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Start and wait for caches.
|
||||
if err := cm.runnables.Caches.Start(cm.internalCtx); err != nil {
|
||||
if err != wait.ErrWaitTimeout {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Start the non-leaderelection Runnables after the cache has synced.
|
||||
if err := cm.runnables.Others.Start(cm.internalCtx); err != nil {
|
||||
if err != wait.ErrWaitTimeout {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Start the leader election and all required runnables.
|
||||
{
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cm.leaderElectionCancel = cancel
|
||||
go func() {
|
||||
if cm.resourceLock != nil {
|
||||
if err := cm.startLeaderElection(ctx); err != nil {
|
||||
cm.errChan <- err
|
||||
}
|
||||
} else {
|
||||
// Treat not having leader election enabled the same as being elected.
|
||||
if err := cm.startLeaderElectionRunnables(); err != nil {
|
||||
cm.errChan <- err
|
||||
}
|
||||
close(cm.elected)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
ready = true
|
||||
cm.Unlock()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// We are done
|
||||
@ -511,24 +510,31 @@ func (cm *controllerManager) Start(ctx context.Context) (err error) {
|
||||
// engageStopProcedure signals all runnables to stop, reads potential errors
|
||||
// from the errChan and waits for them to end. It must not be called more than once.
|
||||
func (cm *controllerManager) engageStopProcedure(stopComplete <-chan struct{}) error {
|
||||
// Populate the shutdown context.
|
||||
var shutdownCancel context.CancelFunc
|
||||
if cm.gracefulShutdownTimeout > 0 {
|
||||
cm.shutdownCtx, shutdownCancel = context.WithTimeout(context.Background(), cm.gracefulShutdownTimeout)
|
||||
} else {
|
||||
cm.shutdownCtx, shutdownCancel = context.WithCancel(context.Background())
|
||||
if !atomic.CompareAndSwapInt64(cm.stopProcedureEngaged, 0, 1) {
|
||||
return errors.New("stop procedure already engaged")
|
||||
}
|
||||
defer shutdownCancel()
|
||||
|
||||
// Cancel the internal stop channel and wait for the procedures to stop and complete.
|
||||
close(cm.internalProceduresStop)
|
||||
cm.internalCancel()
|
||||
// Populate the shutdown context, this operation MUST be done before
|
||||
// closing the internalProceduresStop channel.
|
||||
//
|
||||
// The shutdown context immediately expires if the gracefulShutdownTimeout is not set.
|
||||
var shutdownCancel context.CancelFunc
|
||||
cm.shutdownCtx, shutdownCancel = context.WithTimeout(context.Background(), cm.gracefulShutdownTimeout)
|
||||
defer shutdownCancel()
|
||||
|
||||
// Start draining the errors before acquiring the lock to make sure we don't deadlock
|
||||
// if something that has the lock is blocked on trying to write into the unbuffered
|
||||
// channel after something else already wrote into it.
|
||||
var closeOnce sync.Once
|
||||
go func() {
|
||||
for {
|
||||
// Closing in the for loop is required to avoid race conditions between
|
||||
// the closure of all internal procedures and making sure to have a reader off the error channel.
|
||||
closeOnce.Do(func() {
|
||||
// Cancel the internal stop channel and wait for the procedures to stop and complete.
|
||||
close(cm.internalProceduresStop)
|
||||
cm.internalCancel()
|
||||
})
|
||||
select {
|
||||
case err, ok := <-cm.errChan:
|
||||
if ok {
|
||||
@ -539,26 +545,14 @@ func (cm *controllerManager) engageStopProcedure(stopComplete <-chan struct{}) e
|
||||
}
|
||||
}
|
||||
}()
|
||||
if cm.gracefulShutdownTimeout == 0 {
|
||||
return nil
|
||||
}
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
cm.stopProcedureEngaged = true
|
||||
|
||||
// we want to close this after the other runnables stop, because we don't
|
||||
// We want to close this after the other runnables stop, because we don't
|
||||
// want things like leader election to try and emit events on a closed
|
||||
// channel
|
||||
defer cm.recorderProvider.Stop(cm.shutdownCtx)
|
||||
return cm.waitForRunnableToEnd(shutdownCancel)
|
||||
}
|
||||
|
||||
// waitForRunnableToEnd blocks until all runnables ended or the
|
||||
// tearDownTimeout was reached. In the latter case, an error is returned.
|
||||
func (cm *controllerManager) waitForRunnableToEnd(shutdownCancel context.CancelFunc) (retErr error) {
|
||||
// Cancel leader election only after we waited. It will os.Exit() the app for safety.
|
||||
defer func() {
|
||||
if retErr == nil && cm.leaderElectionCancel != nil {
|
||||
// Cancel leader election only after we waited. It will os.Exit() the app for safety.
|
||||
if cm.resourceLock != nil {
|
||||
// After asking the context to be cancelled, make sure
|
||||
// we wait for the leader stopped channel to be closed, otherwise
|
||||
// we might encounter race conditions between this code
|
||||
@ -569,104 +563,48 @@ func (cm *controllerManager) waitForRunnableToEnd(shutdownCancel context.CancelF
|
||||
}()
|
||||
|
||||
go func() {
|
||||
cm.waitForRunnable.Wait()
|
||||
// First stop the non-leader election runnables.
|
||||
cm.logger.Info("Stopping and waiting for non leader election runnables")
|
||||
cm.runnables.Others.StopAndWait(cm.shutdownCtx)
|
||||
|
||||
// Stop all the leader election runnables, which includes reconcilers.
|
||||
cm.logger.Info("Stopping and waiting for leader election runnables")
|
||||
cm.runnables.LeaderElection.StopAndWait(cm.shutdownCtx)
|
||||
|
||||
// Stop the caches before the leader election runnables, this is an important
|
||||
// step to make sure that we don't race with the reconcilers by receiving more events
|
||||
// from the API servers and enqueueing them.
|
||||
cm.logger.Info("Stopping and waiting for caches")
|
||||
cm.runnables.Caches.StopAndWait(cm.shutdownCtx)
|
||||
|
||||
// Webhooks should come last, as they might be still serving some requests.
|
||||
cm.logger.Info("Stopping and waiting for webhooks")
|
||||
cm.runnables.Webhooks.StopAndWait(cm.shutdownCtx)
|
||||
|
||||
// Proceed to close the manager and overall shutdown context.
|
||||
cm.logger.Info("Wait completed, proceeding to shutdown the manager")
|
||||
shutdownCancel()
|
||||
}()
|
||||
|
||||
<-cm.shutdownCtx.Done()
|
||||
if err := cm.shutdownCtx.Err(); err != nil && err != context.Canceled {
|
||||
return fmt.Errorf("failed waiting for all runnables to end within grace period of %s: %w", cm.gracefulShutdownTimeout, err)
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
if cm.gracefulShutdownTimeout > 0 {
|
||||
return fmt.Errorf("failed waiting for all runnables to end within grace period of %s: %w", cm.gracefulShutdownTimeout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// For any other error, return the error.
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cm *controllerManager) startWebhookRunnables() {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
|
||||
// WARNING: Webhooks MUST start before any cache is populated, otherwise there is a race condition
|
||||
// between conversion webhooks and the cache sync (usually initial list) which causes the webhooks
|
||||
// to never start because no cache can be populated.
|
||||
for _, c := range cm.nonLeaderElectionRunnables {
|
||||
if _, ok := c.(*webhook.Server); ok {
|
||||
cm.startRunnable(c)
|
||||
}
|
||||
}
|
||||
func (cm *controllerManager) startLeaderElectionRunnables() error {
|
||||
return cm.runnables.LeaderElection.Start(cm.internalCtx)
|
||||
}
|
||||
|
||||
func (cm *controllerManager) startNonLeaderElectionRunnables() {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
|
||||
// Start and wait for caches.
|
||||
cm.waitForCache(cm.internalCtx)
|
||||
|
||||
// Start the non-leaderelection Runnables after the cache has synced
|
||||
for _, c := range cm.nonLeaderElectionRunnables {
|
||||
if _, ok := c.(*webhook.Server); ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Controllers block, but we want to return an error if any have an error starting.
|
||||
// Write any Start errors to a channel so we can return them
|
||||
cm.startRunnable(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *controllerManager) startLeaderElectionRunnables() {
|
||||
cm.mu.Lock()
|
||||
defer cm.mu.Unlock()
|
||||
|
||||
cm.waitForCache(cm.internalCtx)
|
||||
|
||||
// Start the leader election Runnables after the cache has synced
|
||||
for _, c := range cm.leaderElectionRunnables {
|
||||
// Controllers block, but we want to return an error if any have an error starting.
|
||||
// Write any Start errors to a channel so we can return them
|
||||
cm.startRunnable(c)
|
||||
}
|
||||
|
||||
cm.startedLeader = true
|
||||
}
|
||||
|
||||
func (cm *controllerManager) waitForCache(ctx context.Context) {
|
||||
if cm.started {
|
||||
return
|
||||
}
|
||||
|
||||
for _, cache := range cm.caches {
|
||||
cm.startRunnable(cache)
|
||||
}
|
||||
|
||||
// Wait for the caches to sync.
|
||||
// TODO(community): Check the return value and write a test
|
||||
for _, cache := range cm.caches {
|
||||
cache.GetCache().WaitForCacheSync(ctx)
|
||||
}
|
||||
// TODO: This should be the return value of cm.cache.WaitForCacheSync but we abuse
|
||||
// cm.started as check if we already started the cache so it must always become true.
|
||||
// Making sure that the cache doesn't get started twice is needed to not get a "close
|
||||
// of closed channel" panic
|
||||
cm.started = true
|
||||
}
|
||||
|
||||
func (cm *controllerManager) startLeaderElection() (err error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cm.mu.Lock()
|
||||
cm.leaderElectionCancel = cancel
|
||||
cm.mu.Unlock()
|
||||
|
||||
if cm.onStoppedLeading == nil {
|
||||
cm.onStoppedLeading = func() {
|
||||
// Make sure graceful shutdown is skipped if we lost the leader lock without
|
||||
// intending to.
|
||||
cm.gracefulShutdownTimeout = time.Duration(0)
|
||||
// Most implementations of leader election log.Fatal() here.
|
||||
// Since Start is wrapped in log.Fatal when called, we can just return
|
||||
// an error here which will cause the program to exit.
|
||||
cm.errChan <- errors.New("leader election lost")
|
||||
}
|
||||
}
|
||||
func (cm *controllerManager) startLeaderElection(ctx context.Context) (err error) {
|
||||
l, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
|
||||
Lock: cm.resourceLock,
|
||||
LeaseDuration: cm.leaseDuration,
|
||||
@ -674,10 +612,24 @@ func (cm *controllerManager) startLeaderElection() (err error) {
|
||||
RetryPeriod: cm.retryPeriod,
|
||||
Callbacks: leaderelection.LeaderCallbacks{
|
||||
OnStartedLeading: func(_ context.Context) {
|
||||
cm.startLeaderElectionRunnables()
|
||||
if err := cm.startLeaderElectionRunnables(); err != nil {
|
||||
cm.errChan <- err
|
||||
return
|
||||
}
|
||||
close(cm.elected)
|
||||
},
|
||||
OnStoppedLeading: cm.onStoppedLeading,
|
||||
OnStoppedLeading: func() {
|
||||
if cm.onStoppedLeading != nil {
|
||||
cm.onStoppedLeading()
|
||||
}
|
||||
// Make sure graceful shutdown is skipped if we lost the leader lock without
|
||||
// intending to.
|
||||
cm.gracefulShutdownTimeout = time.Duration(0)
|
||||
// Most implementations of leader election log.Fatal() here.
|
||||
// Since Start is wrapped in log.Fatal when called, we can just return
|
||||
// an error here which will cause the program to exit.
|
||||
cm.errChan <- errors.New("leader election lost")
|
||||
},
|
||||
},
|
||||
ReleaseOnCancel: cm.leaderElectionReleaseOnCancel,
|
||||
})
|
||||
@ -697,13 +649,3 @@ func (cm *controllerManager) startLeaderElection() (err error) {
|
||||
func (cm *controllerManager) Elected() <-chan struct{} {
|
||||
return cm.elected
|
||||
}
|
||||
|
||||
func (cm *controllerManager) startRunnable(r Runnable) {
|
||||
cm.waitForRunnable.Add(1)
|
||||
go func() {
|
||||
defer cm.waitForRunnable.Done()
|
||||
if err := r.Start(cm.internalCtx); err != nil {
|
||||
cm.errChan <- err
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
9
vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go
generated
vendored
9
vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go
generated
vendored
@ -31,6 +31,7 @@ import (
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cluster"
|
||||
@ -365,8 +366,14 @@ func New(config *rest.Config, options Options) (Manager, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errChan := make(chan error)
|
||||
runnables := newRunnables(errChan)
|
||||
|
||||
return &controllerManager{
|
||||
stopProcedureEngaged: pointer.Int64(0),
|
||||
cluster: cluster,
|
||||
runnables: runnables,
|
||||
errChan: errChan,
|
||||
recorderProvider: recorderProvider,
|
||||
resourceLock: resourceLock,
|
||||
metricsListener: metricsListener,
|
||||
@ -571,7 +578,7 @@ func setOptionsDefaults(options Options) Options {
|
||||
options.GracefulShutdownTimeout = &gracefulShutdownTimeout
|
||||
}
|
||||
|
||||
if options.Logger == nil {
|
||||
if options.Logger.GetSink() == nil {
|
||||
options.Logger = log.Log
|
||||
}
|
||||
|
||||
|
296
vendor/sigs.k8s.io/controller-runtime/pkg/manager/runnable_group.go
generated
vendored
Normal file
296
vendor/sigs.k8s.io/controller-runtime/pkg/manager/runnable_group.go
generated
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
)
|
||||
|
||||
var (
|
||||
errRunnableGroupStopped = errors.New("can't accept new runnable as stop procedure is already engaged")
|
||||
)
|
||||
|
||||
// readyRunnable encapsulates a runnable with
|
||||
// a ready check.
|
||||
type readyRunnable struct {
|
||||
Runnable
|
||||
Check runnableCheck
|
||||
signalReady bool
|
||||
}
|
||||
|
||||
// runnableCheck can be passed to Add() to let the runnable group determine that a
|
||||
// runnable is ready. A runnable check should block until a runnable is ready,
|
||||
// if the returned result is false, the runnable is considered not ready and failed.
|
||||
type runnableCheck func(ctx context.Context) bool
|
||||
|
||||
// runnables handles all the runnables for a manager by grouping them accordingly to their
|
||||
// type (webhooks, caches etc.).
|
||||
type runnables struct {
|
||||
Webhooks *runnableGroup
|
||||
Caches *runnableGroup
|
||||
LeaderElection *runnableGroup
|
||||
Others *runnableGroup
|
||||
}
|
||||
|
||||
// newRunnables creates a new runnables object.
|
||||
func newRunnables(errChan chan error) *runnables {
|
||||
return &runnables{
|
||||
Webhooks: newRunnableGroup(errChan),
|
||||
Caches: newRunnableGroup(errChan),
|
||||
LeaderElection: newRunnableGroup(errChan),
|
||||
Others: newRunnableGroup(errChan),
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a runnable to closest group of runnable that they belong to.
|
||||
//
|
||||
// Add should be able to be called before and after Start, but not after StopAndWait.
|
||||
// Add should return an error when called during StopAndWait.
|
||||
// The runnables added before Start are started when Start is called.
|
||||
// The runnables added after Start are started directly.
|
||||
func (r *runnables) Add(fn Runnable) error {
|
||||
switch runnable := fn.(type) {
|
||||
case hasCache:
|
||||
return r.Caches.Add(fn, func(ctx context.Context) bool {
|
||||
return runnable.GetCache().WaitForCacheSync(ctx)
|
||||
})
|
||||
case *webhook.Server:
|
||||
return r.Webhooks.Add(fn, nil)
|
||||
case LeaderElectionRunnable:
|
||||
if !runnable.NeedLeaderElection() {
|
||||
return r.Others.Add(fn, nil)
|
||||
}
|
||||
return r.LeaderElection.Add(fn, nil)
|
||||
default:
|
||||
return r.LeaderElection.Add(fn, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// runnableGroup manages a group of runnables that are
|
||||
// meant to be running together until StopAndWait is called.
|
||||
//
|
||||
// Runnables can be added to a group after the group has started
|
||||
// but not after it's stopped or while shutting down.
|
||||
type runnableGroup struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
||||
start sync.Mutex
|
||||
startOnce sync.Once
|
||||
started bool
|
||||
startQueue []*readyRunnable
|
||||
startReadyCh chan *readyRunnable
|
||||
|
||||
stop sync.RWMutex
|
||||
stopOnce sync.Once
|
||||
stopped bool
|
||||
|
||||
// errChan is the error channel passed by the caller
|
||||
// when the group is created.
|
||||
// All errors are forwarded to this channel once they occur.
|
||||
errChan chan error
|
||||
|
||||
// ch is the internal channel where the runnables are read off from.
|
||||
ch chan *readyRunnable
|
||||
|
||||
// wg is an internal sync.WaitGroup that allows us to properly stop
|
||||
// and wait for all the runnables to finish before returning.
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
func newRunnableGroup(errChan chan error) *runnableGroup {
|
||||
r := &runnableGroup{
|
||||
startReadyCh: make(chan *readyRunnable),
|
||||
errChan: errChan,
|
||||
ch: make(chan *readyRunnable),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
r.ctx, r.cancel = context.WithCancel(context.Background())
|
||||
return r
|
||||
}
|
||||
|
||||
// Started returns true if the group has started.
|
||||
func (r *runnableGroup) Started() bool {
|
||||
r.start.Lock()
|
||||
defer r.start.Unlock()
|
||||
return r.started
|
||||
}
|
||||
|
||||
// Start starts the group and waits for all
|
||||
// initially registered runnables to start.
|
||||
// It can only be called once, subsequent calls have no effect.
|
||||
func (r *runnableGroup) Start(ctx context.Context) error {
|
||||
var retErr error
|
||||
|
||||
r.startOnce.Do(func() {
|
||||
defer close(r.startReadyCh)
|
||||
|
||||
// Start the internal reconciler.
|
||||
go r.reconcile()
|
||||
|
||||
// Start the group and queue up all
|
||||
// the runnables that were added prior.
|
||||
r.start.Lock()
|
||||
r.started = true
|
||||
for _, rn := range r.startQueue {
|
||||
rn.signalReady = true
|
||||
r.ch <- rn
|
||||
}
|
||||
r.start.Unlock()
|
||||
|
||||
// If we don't have any queue, return.
|
||||
if len(r.startQueue) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Wait for all runnables to signal.
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if err := ctx.Err(); !errors.Is(err, context.Canceled) {
|
||||
retErr = err
|
||||
}
|
||||
case rn := <-r.startReadyCh:
|
||||
for i, existing := range r.startQueue {
|
||||
if existing == rn {
|
||||
// Remove the item from the start queue.
|
||||
r.startQueue = append(r.startQueue[:i], r.startQueue[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
// We're done waiting if the queue is empty, return.
|
||||
if len(r.startQueue) == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return retErr
|
||||
}
|
||||
|
||||
// reconcile is our main entrypoint for every runnable added
|
||||
// to this group. Its primary job is to read off the internal channel
|
||||
// and schedule runnables while tracking their state.
|
||||
func (r *runnableGroup) reconcile() {
|
||||
for runnable := range r.ch {
|
||||
// Handle stop.
|
||||
// If the shutdown has been called we want to avoid
|
||||
// adding new goroutines to the WaitGroup because Wait()
|
||||
// panics if Add() is called after it.
|
||||
{
|
||||
r.stop.RLock()
|
||||
if r.stopped {
|
||||
// Drop any runnables if we're stopped.
|
||||
r.errChan <- errRunnableGroupStopped
|
||||
r.stop.RUnlock()
|
||||
continue
|
||||
}
|
||||
|
||||
// Why is this here?
|
||||
// When StopAndWait is called, if a runnable is in the process
|
||||
// of being added, we could end up in a situation where
|
||||
// the WaitGroup is incremented while StopAndWait has called Wait(),
|
||||
// which would result in a panic.
|
||||
r.wg.Add(1)
|
||||
r.stop.RUnlock()
|
||||
}
|
||||
|
||||
// Start the runnable.
|
||||
go func(rn *readyRunnable) {
|
||||
go func() {
|
||||
if rn.Check(r.ctx) {
|
||||
if rn.signalReady {
|
||||
r.startReadyCh <- rn
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// If we return, the runnable ended cleanly
|
||||
// or returned an error to the channel.
|
||||
//
|
||||
// We should always decrement the WaitGroup here.
|
||||
defer r.wg.Done()
|
||||
|
||||
// Start the runnable.
|
||||
if err := rn.Start(r.ctx); err != nil {
|
||||
r.errChan <- err
|
||||
}
|
||||
}(runnable)
|
||||
}
|
||||
}
|
||||
|
||||
// Add should be able to be called before and after Start, but not after StopAndWait.
|
||||
// Add should return an error when called during StopAndWait.
|
||||
func (r *runnableGroup) Add(rn Runnable, ready runnableCheck) error {
|
||||
r.stop.RLock()
|
||||
if r.stopped {
|
||||
r.stop.RUnlock()
|
||||
return errRunnableGroupStopped
|
||||
}
|
||||
r.stop.RUnlock()
|
||||
|
||||
if ready == nil {
|
||||
ready = func(_ context.Context) bool { return true }
|
||||
}
|
||||
|
||||
readyRunnable := &readyRunnable{
|
||||
Runnable: rn,
|
||||
Check: ready,
|
||||
}
|
||||
|
||||
// Handle start.
|
||||
// If the overall runnable group isn't started yet
|
||||
// we want to buffer the runnables and let Start()
|
||||
// queue them up again later.
|
||||
{
|
||||
r.start.Lock()
|
||||
|
||||
// Check if we're already started.
|
||||
if !r.started {
|
||||
// Store the runnable in the internal if not.
|
||||
r.startQueue = append(r.startQueue, readyRunnable)
|
||||
r.start.Unlock()
|
||||
return nil
|
||||
}
|
||||
r.start.Unlock()
|
||||
}
|
||||
|
||||
// Enqueue the runnable.
|
||||
r.ch <- readyRunnable
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopAndWait waits for all the runnables to finish before returning.
|
||||
func (r *runnableGroup) StopAndWait(ctx context.Context) {
|
||||
r.stopOnce.Do(func() {
|
||||
// Close the reconciler channel once we're done.
|
||||
defer close(r.ch)
|
||||
|
||||
_ = r.Start(ctx)
|
||||
r.stop.Lock()
|
||||
// Store the stopped variable so we don't accept any new
|
||||
// runnables for the time being.
|
||||
r.stopped = true
|
||||
r.stop.Unlock()
|
||||
|
||||
// Cancel the internal channel.
|
||||
r.cancel()
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
// Wait for all the runnables to finish.
|
||||
r.wg.Wait()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
// We're done, exit.
|
||||
case <-ctx.Done():
|
||||
// Calling context has expired, exit.
|
||||
}
|
||||
})
|
||||
}
|
4
vendor/sigs.k8s.io/controller-runtime/pkg/manager/signals/signal.go
generated
vendored
4
vendor/sigs.k8s.io/controller-runtime/pkg/manager/signals/signal.go
generated
vendored
@ -24,8 +24,8 @@ import (
|
||||
|
||||
var onlyOneSignalHandler = make(chan struct{})
|
||||
|
||||
// SetupSignalHandler registers for SIGTERM and SIGINT. A stop channel is returned
|
||||
// which is closed on one of these signals. If a second signal is caught, the program
|
||||
// SetupSignalHandler registers for SIGTERM and SIGINT. A context is returned
|
||||
// which is canceled on one of these signals. If a second signal is caught, the program
|
||||
// is terminated with exit code 1.
|
||||
func SetupSignalHandler() context.Context {
|
||||
close(onlyOneSignalHandler) // panics when called twice
|
||||
|
2
vendor/sigs.k8s.io/controller-runtime/pkg/reconcile/reconcile.go
generated
vendored
2
vendor/sigs.k8s.io/controller-runtime/pkg/reconcile/reconcile.go
generated
vendored
@ -87,7 +87,7 @@ For example if responding to a Pod Delete Event, the Request won't contain that
|
||||
instead the reconcile function observes this when reading the cluster state and seeing the Pod as missing.
|
||||
*/
|
||||
type Reconciler interface {
|
||||
// Reconciler performs a full reconciliation for the object referred to by the Request.
|
||||
// Reconcile performs a full reconciliation for the object referred to by the Request.
|
||||
// The Controller will requeue the Request to be processed again if an error is non-nil or
|
||||
// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
|
||||
Reconcile(context.Context, Request) (Result, error)
|
||||
|
2
vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go
generated
vendored
2
vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go
generated
vendored
@ -243,7 +243,7 @@ func StandaloneWebhook(hook *Webhook, opts StandaloneOptions) (http.Handler, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.Logger == nil {
|
||||
if opts.Logger.GetSink() == nil {
|
||||
opts.Logger = logf.RuntimeLog.WithName("webhook")
|
||||
}
|
||||
hook.log = opts.Logger
|
||||
|
5
vendor/sigs.k8s.io/controller-runtime/pkg/webhook/server.go
generated
vendored
5
vendor/sigs.k8s.io/controller-runtime/pkg/webhook/server.go
generated
vendored
@ -34,6 +34,7 @@ import (
|
||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/internal/httpserver"
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics"
|
||||
)
|
||||
@ -261,9 +262,7 @@ func (s *Server) Start(ctx context.Context) error {
|
||||
|
||||
log.Info("Serving webhook server", "host", s.Host, "port", s.Port)
|
||||
|
||||
srv := &http.Server{
|
||||
Handler: s.WebhookMux,
|
||||
}
|
||||
srv := httpserver.New(s.WebhookMux)
|
||||
|
||||
idleConnsClosed := make(chan struct{})
|
||||
go func() {
|
||||
|
42
vendor/sigs.k8s.io/json/CONTRIBUTING.md
generated
vendored
Normal file
42
vendor/sigs.k8s.io/json/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://git.k8s.io/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt:
|
||||
|
||||
_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._
|
||||
|
||||
## Criteria for adding code here
|
||||
|
||||
This library adapts the stdlib `encoding/json` decoder to be compatible with
|
||||
Kubernetes JSON decoding, and is not expected to actively add new features.
|
||||
|
||||
It may be updated with changes from the stdlib `encoding/json` decoder.
|
||||
|
||||
Any code that is added must:
|
||||
* Have full unit test and benchmark coverage
|
||||
* Be backward compatible with the existing exposed go API
|
||||
* Have zero external dependencies
|
||||
* Preserve existing benchmark performance
|
||||
* Preserve compatibility with existing decoding behavior of `UnmarshalCaseSensitivePreserveInts()` or `UnmarshalStrict()`
|
||||
* Avoid use of `unsafe`
|
||||
|
||||
## Getting Started
|
||||
|
||||
We have full documentation on how to get started contributing here:
|
||||
|
||||
<!---
|
||||
If your repo has certain guidelines for contribution, put them here ahead of the general k8s resources
|
||||
-->
|
||||
|
||||
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
|
||||
- [Kubernetes Contributor Guide](https://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](https://git.k8s.io/community/contributors/guide#contributing)
|
||||
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet) - Common resources for existing developers
|
||||
|
||||
## Community, discussion, contribution, and support
|
||||
|
||||
You can reach the maintainers of this project via the
|
||||
[sig-api-machinery mailing list / channels](https://github.com/kubernetes/community/tree/master/sig-api-machinery#contact).
|
||||
|
||||
## Mentorship
|
||||
|
||||
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
||||
|
238
vendor/sigs.k8s.io/json/LICENSE
generated
vendored
Normal file
238
vendor/sigs.k8s.io/json/LICENSE
generated
vendored
Normal file
@ -0,0 +1,238 @@
|
||||
Files other than internal/golang/* licensed under:
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
------------------
|
||||
|
||||
internal/golang/* files licensed under:
|
||||
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
35
vendor/sigs.k8s.io/json/Makefile
generated
vendored
Normal file
35
vendor/sigs.k8s.io/json/Makefile
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
.PHONY: default build test benchmark fmt vet
|
||||
|
||||
default: build
|
||||
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
test:
|
||||
go test sigs.k8s.io/json/...
|
||||
|
||||
benchmark:
|
||||
go test sigs.k8s.io/json -bench . -benchmem
|
||||
|
||||
fmt:
|
||||
go mod tidy
|
||||
gofmt -s -w *.go
|
||||
|
||||
vet:
|
||||
go vet sigs.k8s.io/json
|
||||
|
||||
@echo "checking for external dependencies"
|
||||
@deps=$$(go mod graph); \
|
||||
if [ -n "$${deps}" ]; then \
|
||||
echo "only stdlib dependencies allowed, found:"; \
|
||||
echo "$${deps}"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo "checking for unsafe use"
|
||||
@unsafe=$$(go list -f '{{.ImportPath}} depends on {{.Imports}}' sigs.k8s.io/json/... | grep unsafe || true); \
|
||||
if [ -n "$${unsafe}" ]; then \
|
||||
echo "no dependencies on unsafe allowed, found:"; \
|
||||
echo "$${unsafe}"; \
|
||||
exit 1; \
|
||||
fi
|
6
vendor/sigs.k8s.io/json/OWNERS
generated
vendored
Normal file
6
vendor/sigs.k8s.io/json/OWNERS
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- deads2k
|
||||
- lavalamp
|
||||
- liggitt
|
40
vendor/sigs.k8s.io/json/README.md
generated
vendored
Normal file
40
vendor/sigs.k8s.io/json/README.md
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# sigs.k8s.io/json
|
||||
|
||||
[](https://pkg.go.dev/sigs.k8s.io/json)
|
||||
|
||||
## Introduction
|
||||
|
||||
This library is a subproject of [sig-api-machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery#json).
|
||||
It provides case-sensitive, integer-preserving JSON unmarshaling functions based on `encoding/json` `Unmarshal()`.
|
||||
|
||||
## Compatibility
|
||||
|
||||
The `UnmarshalCaseSensitivePreserveInts()` function behaves like `encoding/json#Unmarshal()` with the following differences:
|
||||
|
||||
- JSON object keys are treated case-sensitively.
|
||||
Object keys must exactly match json tag names (for tagged struct fields)
|
||||
or struct field names (for untagged struct fields).
|
||||
- JSON integers are unmarshaled into `interface{}` fields as an `int64` instead of a
|
||||
`float64` when possible, falling back to `float64` on any parse or overflow error.
|
||||
- Syntax errors do not return an `encoding/json` `*SyntaxError` error.
|
||||
Instead, they return an error which can be passed to `SyntaxErrorOffset()` to obtain an offset.
|
||||
|
||||
## Additional capabilities
|
||||
|
||||
The `UnmarshalStrict()` function decodes identically to `UnmarshalCaseSensitivePreserveInts()`,
|
||||
and also returns non-fatal strict errors encountered while decoding:
|
||||
|
||||
- Duplicate fields encountered
|
||||
- Unknown fields encountered
|
||||
|
||||
### Community, discussion, contribution, and support
|
||||
|
||||
You can reach the maintainers of this project via the
|
||||
[sig-api-machinery mailing list / channels](https://github.com/kubernetes/community/tree/master/sig-api-machinery#contact).
|
||||
|
||||
### Code of conduct
|
||||
|
||||
Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).
|
||||
|
||||
[owners]: https://git.k8s.io/community/contributors/guide/owners.md
|
||||
[Creative Commons 4.0]: https://git.k8s.io/website/LICENSE
|
22
vendor/sigs.k8s.io/json/SECURITY.md
generated
vendored
Normal file
22
vendor/sigs.k8s.io/json/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Security Policy
|
||||
|
||||
## Security Announcements
|
||||
|
||||
Join the [kubernetes-security-announce] group for security and vulnerability announcements.
|
||||
|
||||
You can also subscribe to an RSS feed of the above using [this link][kubernetes-security-announce-rss].
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Instructions for reporting a vulnerability can be found on the
|
||||
[Kubernetes Security and Disclosure Information] page.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Information about supported Kubernetes versions can be found on the
|
||||
[Kubernetes version and version skew support policy] page on the Kubernetes website.
|
||||
|
||||
[kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce
|
||||
[kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50
|
||||
[Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions
|
||||
[Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability
|
15
vendor/sigs.k8s.io/json/SECURITY_CONTACTS
generated
vendored
Normal file
15
vendor/sigs.k8s.io/json/SECURITY_CONTACTS
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Defined below are the security contacts for this repo.
|
||||
#
|
||||
# They are the contact point for the Product Security Committee to reach out
|
||||
# to for triaging and handling of incoming issues.
|
||||
#
|
||||
# The below names agree to abide by the
|
||||
# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy)
|
||||
# and will be removed and replaced if they violate that agreement.
|
||||
#
|
||||
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||
|
||||
deads2k
|
||||
lavalamp
|
||||
liggitt
|
3
vendor/sigs.k8s.io/json/code-of-conduct.md
generated
vendored
Normal file
3
vendor/sigs.k8s.io/json/code-of-conduct.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Kubernetes Community Code of Conduct
|
||||
|
||||
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
17
vendor/sigs.k8s.io/json/doc.go
generated
vendored
Normal file
17
vendor/sigs.k8s.io/json/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright 2021 The Kubernetes Authors.
|
||||
|
||||
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 json // import "sigs.k8s.io/json"
|
3
vendor/sigs.k8s.io/json/go.mod
generated
vendored
Normal file
3
vendor/sigs.k8s.io/json/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module sigs.k8s.io/json
|
||||
|
||||
go 1.16
|
1402
vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
generated
vendored
Normal file
1402
vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1419
vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
generated
vendored
Normal file
1419
vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
143
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fold.go
generated
vendored
Normal file
143
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fold.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
|
||||
kelvin = '\u212a'
|
||||
smallLongEss = '\u017f'
|
||||
)
|
||||
|
||||
// foldFunc returns one of four different case folding equivalence
|
||||
// functions, from most general (and slow) to fastest:
|
||||
//
|
||||
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
|
||||
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
|
||||
// 3) asciiEqualFold, no special, but includes non-letters (including _)
|
||||
// 4) simpleLetterEqualFold, no specials, no non-letters.
|
||||
//
|
||||
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||
// See https://play.golang.org/p/tTxjOc0OGo
|
||||
//
|
||||
// The returned function is specialized for matching against s and
|
||||
// should only be given s. It's not curried for performance reasons.
|
||||
func foldFunc(s []byte) func(s, t []byte) bool {
|
||||
nonLetter := false
|
||||
special := false // special letter
|
||||
for _, b := range s {
|
||||
if b >= utf8.RuneSelf {
|
||||
return bytes.EqualFold
|
||||
}
|
||||
upper := b & caseMask
|
||||
if upper < 'A' || upper > 'Z' {
|
||||
nonLetter = true
|
||||
} else if upper == 'K' || upper == 'S' {
|
||||
// See above for why these letters are special.
|
||||
special = true
|
||||
}
|
||||
}
|
||||
if special {
|
||||
return equalFoldRight
|
||||
}
|
||||
if nonLetter {
|
||||
return asciiEqualFold
|
||||
}
|
||||
return simpleLetterEqualFold
|
||||
}
|
||||
|
||||
// equalFoldRight is a specialization of bytes.EqualFold when s is
|
||||
// known to be all ASCII (including punctuation), but contains an 's',
|
||||
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
|
||||
// See comments on foldFunc.
|
||||
func equalFoldRight(s, t []byte) bool {
|
||||
for _, sb := range s {
|
||||
if len(t) == 0 {
|
||||
return false
|
||||
}
|
||||
tb := t[0]
|
||||
if tb < utf8.RuneSelf {
|
||||
if sb != tb {
|
||||
sbUpper := sb & caseMask
|
||||
if 'A' <= sbUpper && sbUpper <= 'Z' {
|
||||
if sbUpper != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
t = t[1:]
|
||||
continue
|
||||
}
|
||||
// sb is ASCII and t is not. t must be either kelvin
|
||||
// sign or long s; sb must be s, S, k, or K.
|
||||
tr, size := utf8.DecodeRune(t)
|
||||
switch sb {
|
||||
case 's', 'S':
|
||||
if tr != smallLongEss {
|
||||
return false
|
||||
}
|
||||
case 'k', 'K':
|
||||
if tr != kelvin {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
t = t[size:]
|
||||
|
||||
}
|
||||
if len(t) > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// asciiEqualFold is a specialization of bytes.EqualFold for use when
|
||||
// s is all ASCII (but may contain non-letters) and contains no
|
||||
// special-folding letters.
|
||||
// See comments on foldFunc.
|
||||
func asciiEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, sb := range s {
|
||||
tb := t[i]
|
||||
if sb == tb {
|
||||
continue
|
||||
}
|
||||
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
|
||||
if sb&caseMask != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
|
||||
// use when s is all ASCII letters (no underscores, etc) and also
|
||||
// doesn't contain 'k', 'K', 's', or 'S'.
|
||||
// See comments on foldFunc.
|
||||
func simpleLetterEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, b := range s {
|
||||
if b&caseMask != t[i]&caseMask {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
43
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fuzz.go
generated
vendored
Normal file
43
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fuzz.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) (score int) {
|
||||
for _, ctor := range []func() interface{}{
|
||||
func() interface{} { return new(interface{}) },
|
||||
func() interface{} { return new(map[string]interface{}) },
|
||||
func() interface{} { return new([]interface{}) },
|
||||
} {
|
||||
v := ctor()
|
||||
err := Unmarshal(data, v)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
score = 1
|
||||
|
||||
m, err := Marshal(v)
|
||||
if err != nil {
|
||||
fmt.Printf("v=%#v\n", v)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
u := ctor()
|
||||
err = Unmarshal(m, u)
|
||||
if err != nil {
|
||||
fmt.Printf("v=%#v\n", v)
|
||||
fmt.Printf("m=%s\n", m)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
143
vendor/sigs.k8s.io/json/internal/golang/encoding/json/indent.go
generated
vendored
Normal file
143
vendor/sigs.k8s.io/json/internal/golang/encoding/json/indent.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// Compact appends to dst the JSON-encoded src with
|
||||
// insignificant space characters elided.
|
||||
func Compact(dst *bytes.Buffer, src []byte) error {
|
||||
return compact(dst, src, false)
|
||||
}
|
||||
|
||||
func compact(dst *bytes.Buffer, src []byte, escape bool) error {
|
||||
origLen := dst.Len()
|
||||
scan := newScanner()
|
||||
defer freeScanner(scan)
|
||||
start := 0
|
||||
for i, c := range src {
|
||||
if escape && (c == '<' || c == '>' || c == '&') {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u00`)
|
||||
dst.WriteByte(hex[c>>4])
|
||||
dst.WriteByte(hex[c&0xF])
|
||||
start = i + 1
|
||||
}
|
||||
// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
|
||||
if escape && c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u202`)
|
||||
dst.WriteByte(hex[src[i+2]&0xF])
|
||||
start = i + 3
|
||||
}
|
||||
v := scan.step(scan, c)
|
||||
if v >= scanSkipSpace {
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
if start < len(src) {
|
||||
dst.Write(src[start:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
|
||||
dst.WriteByte('\n')
|
||||
dst.WriteString(prefix)
|
||||
for i := 0; i < depth; i++ {
|
||||
dst.WriteString(indent)
|
||||
}
|
||||
}
|
||||
|
||||
// Indent appends to dst an indented form of the JSON-encoded src.
|
||||
// Each element in a JSON object or array begins on a new,
|
||||
// indented line beginning with prefix followed by one or more
|
||||
// copies of indent according to the indentation nesting.
|
||||
// The data appended to dst does not begin with the prefix nor
|
||||
// any indentation, to make it easier to embed inside other formatted JSON data.
|
||||
// Although leading space characters (space, tab, carriage return, newline)
|
||||
// at the beginning of src are dropped, trailing space characters
|
||||
// at the end of src are preserved and copied to dst.
|
||||
// For example, if src has no trailing spaces, neither will dst;
|
||||
// if src ends in a trailing newline, so will dst.
|
||||
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
||||
origLen := dst.Len()
|
||||
scan := newScanner()
|
||||
defer freeScanner(scan)
|
||||
needIndent := false
|
||||
depth := 0
|
||||
for _, c := range src {
|
||||
scan.bytes++
|
||||
v := scan.step(scan, c)
|
||||
if v == scanSkipSpace {
|
||||
continue
|
||||
}
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if needIndent && v != scanEndObject && v != scanEndArray {
|
||||
needIndent = false
|
||||
depth++
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
|
||||
// Emit semantically uninteresting bytes
|
||||
// (in particular, punctuation in strings) unmodified.
|
||||
if v == scanContinue {
|
||||
dst.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
|
||||
// Add spacing around real punctuation.
|
||||
switch c {
|
||||
case '{', '[':
|
||||
// delay indent so that empty object and array are formatted as {} and [].
|
||||
needIndent = true
|
||||
dst.WriteByte(c)
|
||||
|
||||
case ',':
|
||||
dst.WriteByte(c)
|
||||
newline(dst, prefix, indent, depth)
|
||||
|
||||
case ':':
|
||||
dst.WriteByte(c)
|
||||
dst.WriteByte(' ')
|
||||
|
||||
case '}', ']':
|
||||
if needIndent {
|
||||
// suppress indent in empty object/array
|
||||
needIndent = false
|
||||
} else {
|
||||
depth--
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
dst.WriteByte(c)
|
||||
|
||||
default:
|
||||
dst.WriteByte(c)
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
109
vendor/sigs.k8s.io/json/internal/golang/encoding/json/kubernetes_patch.go
generated
vendored
Normal file
109
vendor/sigs.k8s.io/json/internal/golang/encoding/json/kubernetes_patch.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 2021 The Kubernetes Authors.
|
||||
|
||||
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 json
|
||||
|
||||
import (
|
||||
gojson "encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Type-alias error and data types returned from decoding
|
||||
|
||||
type UnmarshalTypeError = gojson.UnmarshalTypeError
|
||||
type UnmarshalFieldError = gojson.UnmarshalFieldError
|
||||
type InvalidUnmarshalError = gojson.InvalidUnmarshalError
|
||||
type Number = gojson.Number
|
||||
type RawMessage = gojson.RawMessage
|
||||
type Token = gojson.Token
|
||||
type Delim = gojson.Delim
|
||||
|
||||
type UnmarshalOpt func(*decodeState)
|
||||
|
||||
func UseNumber(d *decodeState) {
|
||||
d.useNumber = true
|
||||
}
|
||||
func DisallowUnknownFields(d *decodeState) {
|
||||
d.disallowUnknownFields = true
|
||||
}
|
||||
|
||||
// CaseSensitive requires json keys to exactly match specified json tags (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or be treated as an unknown field.
|
||||
func CaseSensitive(d *decodeState) {
|
||||
d.caseSensitive = true
|
||||
}
|
||||
func (d *Decoder) CaseSensitive() {
|
||||
d.d.caseSensitive = true
|
||||
}
|
||||
|
||||
// PreserveInts decodes numbers as int64 when decoding to untyped fields,
|
||||
// if the JSON data does not contain a "." character, parses as an integer successfully,
|
||||
// and does not overflow int64. Otherwise, it falls back to default float64 decoding behavior.
|
||||
//
|
||||
// If UseNumber is also set, it takes precedence over PreserveInts.
|
||||
func PreserveInts(d *decodeState) {
|
||||
d.preserveInts = true
|
||||
}
|
||||
func (d *Decoder) PreserveInts() {
|
||||
d.d.preserveInts = true
|
||||
}
|
||||
|
||||
// DisallowDuplicateFields treats duplicate fields encountered while decoding as an error.
|
||||
func DisallowDuplicateFields(d *decodeState) {
|
||||
d.disallowDuplicateFields = true
|
||||
}
|
||||
func (d *Decoder) DisallowDuplicateFields() {
|
||||
d.d.disallowDuplicateFields = true
|
||||
}
|
||||
|
||||
// saveStrictError saves a strict decoding error,
|
||||
// for reporting at the end of the unmarshal if no other errors occurred.
|
||||
func (d *decodeState) saveStrictError(err error) {
|
||||
// prevent excessive numbers of accumulated errors
|
||||
if len(d.savedStrictErrors) >= 100 {
|
||||
return
|
||||
}
|
||||
// dedupe accumulated strict errors
|
||||
if d.seenStrictErrors == nil {
|
||||
d.seenStrictErrors = map[string]struct{}{}
|
||||
}
|
||||
msg := err.Error()
|
||||
if _, seen := d.seenStrictErrors[msg]; seen {
|
||||
return
|
||||
}
|
||||
|
||||
// accumulate the error
|
||||
d.seenStrictErrors[msg] = struct{}{}
|
||||
d.savedStrictErrors = append(d.savedStrictErrors, err)
|
||||
}
|
||||
|
||||
// UnmarshalStrictError holds errors resulting from use of strict disallow___ decoder directives.
|
||||
// If this is returned from Unmarshal(), it means the decoding was successful in all other respects.
|
||||
type UnmarshalStrictError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
func (e *UnmarshalStrictError) Error() string {
|
||||
var b strings.Builder
|
||||
b.WriteString("json: ")
|
||||
for i, err := range e.Errors {
|
||||
if i > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
b.WriteString(err.Error())
|
||||
}
|
||||
return b.String()
|
||||
}
|
608
vendor/sigs.k8s.io/json/internal/golang/encoding/json/scanner.go
generated
vendored
Normal file
608
vendor/sigs.k8s.io/json/internal/golang/encoding/json/scanner.go
generated
vendored
Normal file
@ -0,0 +1,608 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
// JSON value parser state machine.
|
||||
// Just about at the limit of what is reasonable to write by hand.
|
||||
// Some parts are a bit tedious, but overall it nicely factors out the
|
||||
// otherwise common code from the multiple scanning functions
|
||||
// in this package (Compact, Indent, checkValid, etc).
|
||||
//
|
||||
// This file starts with two simple examples using the scanner
|
||||
// before diving into the scanner itself.
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Valid reports whether data is a valid JSON encoding.
|
||||
func Valid(data []byte) bool {
|
||||
scan := newScanner()
|
||||
defer freeScanner(scan)
|
||||
return checkValid(data, scan) == nil
|
||||
}
|
||||
|
||||
// checkValid verifies that data is valid JSON-encoded data.
|
||||
// scan is passed in for use by checkValid to avoid an allocation.
|
||||
func checkValid(data []byte, scan *scanner) error {
|
||||
scan.reset()
|
||||
for _, c := range data {
|
||||
scan.bytes++
|
||||
if scan.step(scan, c) == scanError {
|
||||
return scan.err
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A SyntaxError is a description of a JSON syntax error.
|
||||
type SyntaxError struct {
|
||||
msg string // description of error
|
||||
Offset int64 // error occurred after reading Offset bytes
|
||||
}
|
||||
|
||||
func (e *SyntaxError) Error() string { return e.msg }
|
||||
|
||||
// A scanner is a JSON scanning state machine.
|
||||
// Callers call scan.reset and then pass bytes in one at a time
|
||||
// by calling scan.step(&scan, c) for each byte.
|
||||
// The return value, referred to as an opcode, tells the
|
||||
// caller about significant parsing events like beginning
|
||||
// and ending literals, objects, and arrays, so that the
|
||||
// caller can follow along if it wishes.
|
||||
// The return value scanEnd indicates that a single top-level
|
||||
// JSON value has been completed, *before* the byte that
|
||||
// just got passed in. (The indication must be delayed in order
|
||||
// to recognize the end of numbers: is 123 a whole value or
|
||||
// the beginning of 12345e+6?).
|
||||
type scanner struct {
|
||||
// The step is a func to be called to execute the next transition.
|
||||
// Also tried using an integer constant and a single func
|
||||
// with a switch, but using the func directly was 10% faster
|
||||
// on a 64-bit Mac Mini, and it's nicer to read.
|
||||
step func(*scanner, byte) int
|
||||
|
||||
// Reached end of top-level value.
|
||||
endTop bool
|
||||
|
||||
// Stack of what we're in the middle of - array values, object keys, object values.
|
||||
parseState []int
|
||||
|
||||
// Error that happened, if any.
|
||||
err error
|
||||
|
||||
// total bytes consumed, updated by decoder.Decode (and deliberately
|
||||
// not set to zero by scan.reset)
|
||||
bytes int64
|
||||
}
|
||||
|
||||
var scannerPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &scanner{}
|
||||
},
|
||||
}
|
||||
|
||||
func newScanner() *scanner {
|
||||
scan := scannerPool.Get().(*scanner)
|
||||
// scan.reset by design doesn't set bytes to zero
|
||||
scan.bytes = 0
|
||||
scan.reset()
|
||||
return scan
|
||||
}
|
||||
|
||||
func freeScanner(scan *scanner) {
|
||||
// Avoid hanging on to too much memory in extreme cases.
|
||||
if len(scan.parseState) > 1024 {
|
||||
scan.parseState = nil
|
||||
}
|
||||
scannerPool.Put(scan)
|
||||
}
|
||||
|
||||
// These values are returned by the state transition functions
|
||||
// assigned to scanner.state and the method scanner.eof.
|
||||
// They give details about the current state of the scan that
|
||||
// callers might be interested to know about.
|
||||
// It is okay to ignore the return value of any particular
|
||||
// call to scanner.state: if one call returns scanError,
|
||||
// every subsequent call will return scanError too.
|
||||
const (
|
||||
// Continue.
|
||||
scanContinue = iota // uninteresting byte
|
||||
scanBeginLiteral // end implied by next result != scanContinue
|
||||
scanBeginObject // begin object
|
||||
scanObjectKey // just finished object key (string)
|
||||
scanObjectValue // just finished non-last object value
|
||||
scanEndObject // end object (implies scanObjectValue if possible)
|
||||
scanBeginArray // begin array
|
||||
scanArrayValue // just finished array value
|
||||
scanEndArray // end array (implies scanArrayValue if possible)
|
||||
scanSkipSpace // space byte; can skip; known to be last "continue" result
|
||||
|
||||
// Stop.
|
||||
scanEnd // top-level value ended *before* this byte; known to be first "stop" result
|
||||
scanError // hit an error, scanner.err.
|
||||
)
|
||||
|
||||
// These values are stored in the parseState stack.
|
||||
// They give the current state of a composite value
|
||||
// being scanned. If the parser is inside a nested value
|
||||
// the parseState describes the nested state, outermost at entry 0.
|
||||
const (
|
||||
parseObjectKey = iota // parsing object key (before colon)
|
||||
parseObjectValue // parsing object value (after colon)
|
||||
parseArrayValue // parsing array value
|
||||
)
|
||||
|
||||
// This limits the max nesting depth to prevent stack overflow.
|
||||
// This is permitted by https://tools.ietf.org/html/rfc7159#section-9
|
||||
const maxNestingDepth = 10000
|
||||
|
||||
// reset prepares the scanner for use.
|
||||
// It must be called before calling s.step.
|
||||
func (s *scanner) reset() {
|
||||
s.step = stateBeginValue
|
||||
s.parseState = s.parseState[0:0]
|
||||
s.err = nil
|
||||
s.endTop = false
|
||||
}
|
||||
|
||||
// eof tells the scanner that the end of input has been reached.
|
||||
// It returns a scan status just as s.step does.
|
||||
func (s *scanner) eof() int {
|
||||
if s.err != nil {
|
||||
return scanError
|
||||
}
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
s.step(s, ' ')
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
if s.err == nil {
|
||||
s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
|
||||
}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// pushParseState pushes a new parse state p onto the parse stack.
|
||||
// an error state is returned if maxNestingDepth was exceeded, otherwise successState is returned.
|
||||
func (s *scanner) pushParseState(c byte, newParseState int, successState int) int {
|
||||
s.parseState = append(s.parseState, newParseState)
|
||||
if len(s.parseState) <= maxNestingDepth {
|
||||
return successState
|
||||
}
|
||||
return s.error(c, "exceeded max depth")
|
||||
}
|
||||
|
||||
// popParseState pops a parse state (already obtained) off the stack
|
||||
// and updates s.step accordingly.
|
||||
func (s *scanner) popParseState() {
|
||||
n := len(s.parseState) - 1
|
||||
s.parseState = s.parseState[0:n]
|
||||
if n == 0 {
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
} else {
|
||||
s.step = stateEndValue
|
||||
}
|
||||
}
|
||||
|
||||
func isSpace(c byte) bool {
|
||||
return c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n')
|
||||
}
|
||||
|
||||
// stateBeginValueOrEmpty is the state after reading `[`.
|
||||
func stateBeginValueOrEmpty(s *scanner, c byte) int {
|
||||
if isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == ']' {
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginValue(s, c)
|
||||
}
|
||||
|
||||
// stateBeginValue is the state at the beginning of the input.
|
||||
func stateBeginValue(s *scanner, c byte) int {
|
||||
if isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
switch c {
|
||||
case '{':
|
||||
s.step = stateBeginStringOrEmpty
|
||||
return s.pushParseState(c, parseObjectKey, scanBeginObject)
|
||||
case '[':
|
||||
s.step = stateBeginValueOrEmpty
|
||||
return s.pushParseState(c, parseArrayValue, scanBeginArray)
|
||||
case '"':
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
case '-':
|
||||
s.step = stateNeg
|
||||
return scanBeginLiteral
|
||||
case '0': // beginning of 0.123
|
||||
s.step = state0
|
||||
return scanBeginLiteral
|
||||
case 't': // beginning of true
|
||||
s.step = stateT
|
||||
return scanBeginLiteral
|
||||
case 'f': // beginning of false
|
||||
s.step = stateF
|
||||
return scanBeginLiteral
|
||||
case 'n': // beginning of null
|
||||
s.step = stateN
|
||||
return scanBeginLiteral
|
||||
}
|
||||
if '1' <= c && c <= '9' { // beginning of 1234.5
|
||||
s.step = state1
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of value")
|
||||
}
|
||||
|
||||
// stateBeginStringOrEmpty is the state after reading `{`.
|
||||
func stateBeginStringOrEmpty(s *scanner, c byte) int {
|
||||
if isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '}' {
|
||||
n := len(s.parseState)
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginString(s, c)
|
||||
}
|
||||
|
||||
// stateBeginString is the state after reading `{"key": value,`.
|
||||
func stateBeginString(s *scanner, c byte) int {
|
||||
if isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '"' {
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of object key string")
|
||||
}
|
||||
|
||||
// stateEndValue is the state after completing a value,
|
||||
// such as after reading `{}` or `true` or `["x"`.
|
||||
func stateEndValue(s *scanner, c byte) int {
|
||||
n := len(s.parseState)
|
||||
if n == 0 {
|
||||
// Completed top-level before the current byte.
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
return stateEndTop(s, c)
|
||||
}
|
||||
if isSpace(c) {
|
||||
s.step = stateEndValue
|
||||
return scanSkipSpace
|
||||
}
|
||||
ps := s.parseState[n-1]
|
||||
switch ps {
|
||||
case parseObjectKey:
|
||||
if c == ':' {
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
s.step = stateBeginValue
|
||||
return scanObjectKey
|
||||
}
|
||||
return s.error(c, "after object key")
|
||||
case parseObjectValue:
|
||||
if c == ',' {
|
||||
s.parseState[n-1] = parseObjectKey
|
||||
s.step = stateBeginString
|
||||
return scanObjectValue
|
||||
}
|
||||
if c == '}' {
|
||||
s.popParseState()
|
||||
return scanEndObject
|
||||
}
|
||||
return s.error(c, "after object key:value pair")
|
||||
case parseArrayValue:
|
||||
if c == ',' {
|
||||
s.step = stateBeginValue
|
||||
return scanArrayValue
|
||||
}
|
||||
if c == ']' {
|
||||
s.popParseState()
|
||||
return scanEndArray
|
||||
}
|
||||
return s.error(c, "after array element")
|
||||
}
|
||||
return s.error(c, "")
|
||||
}
|
||||
|
||||
// stateEndTop is the state after finishing the top-level value,
|
||||
// such as after reading `{}` or `[1,2,3]`.
|
||||
// Only space characters should be seen now.
|
||||
func stateEndTop(s *scanner, c byte) int {
|
||||
if !isSpace(c) {
|
||||
// Complain about non-space byte on next call.
|
||||
s.error(c, "after top-level value")
|
||||
}
|
||||
return scanEnd
|
||||
}
|
||||
|
||||
// stateInString is the state after reading `"`.
|
||||
func stateInString(s *scanner, c byte) int {
|
||||
if c == '"' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
if c == '\\' {
|
||||
s.step = stateInStringEsc
|
||||
return scanContinue
|
||||
}
|
||||
if c < 0x20 {
|
||||
return s.error(c, "in string literal")
|
||||
}
|
||||
return scanContinue
|
||||
}
|
||||
|
||||
// stateInStringEsc is the state after reading `"\` during a quoted string.
|
||||
func stateInStringEsc(s *scanner, c byte) int {
|
||||
switch c {
|
||||
case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
case 'u':
|
||||
s.step = stateInStringEscU
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in string escape code")
|
||||
}
|
||||
|
||||
// stateInStringEscU is the state after reading `"\u` during a quoted string.
|
||||
func stateInStringEscU(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU1
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
|
||||
func stateInStringEscU1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU12
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
|
||||
func stateInStringEscU12(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU123
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
|
||||
func stateInStringEscU123(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateNeg is the state after reading `-` during a number.
|
||||
func stateNeg(s *scanner, c byte) int {
|
||||
if c == '0' {
|
||||
s.step = state0
|
||||
return scanContinue
|
||||
}
|
||||
if '1' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in numeric literal")
|
||||
}
|
||||
|
||||
// state1 is the state after reading a non-zero integer during a number,
|
||||
// such as after reading `1` or `100` but not `0`.
|
||||
func state1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return state0(s, c)
|
||||
}
|
||||
|
||||
// state0 is the state after reading `0` during a number.
|
||||
func state0(s *scanner, c byte) int {
|
||||
if c == '.' {
|
||||
s.step = stateDot
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateDot is the state after reading the integer and decimal point in a number,
|
||||
// such as after reading `1.`.
|
||||
func stateDot(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateDot0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "after decimal point in numeric literal")
|
||||
}
|
||||
|
||||
// stateDot0 is the state after reading the integer, decimal point, and subsequent
|
||||
// digits of a number, such as after reading `3.14`.
|
||||
func stateDot0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateE is the state after reading the mantissa and e in a number,
|
||||
// such as after reading `314e` or `0.314e`.
|
||||
func stateE(s *scanner, c byte) int {
|
||||
if c == '+' || c == '-' {
|
||||
s.step = stateESign
|
||||
return scanContinue
|
||||
}
|
||||
return stateESign(s, c)
|
||||
}
|
||||
|
||||
// stateESign is the state after reading the mantissa, e, and sign in a number,
|
||||
// such as after reading `314e-` or `0.314e+`.
|
||||
func stateESign(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateE0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in exponent of numeric literal")
|
||||
}
|
||||
|
||||
// stateE0 is the state after reading the mantissa, e, optional sign,
|
||||
// and at least one digit of the exponent in a number,
|
||||
// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
|
||||
func stateE0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateT is the state after reading `t`.
|
||||
func stateT(s *scanner, c byte) int {
|
||||
if c == 'r' {
|
||||
s.step = stateTr
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'r')")
|
||||
}
|
||||
|
||||
// stateTr is the state after reading `tr`.
|
||||
func stateTr(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateTru
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateTru is the state after reading `tru`.
|
||||
func stateTru(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateF is the state after reading `f`.
|
||||
func stateF(s *scanner, c byte) int {
|
||||
if c == 'a' {
|
||||
s.step = stateFa
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'a')")
|
||||
}
|
||||
|
||||
// stateFa is the state after reading `fa`.
|
||||
func stateFa(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateFal
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateFal is the state after reading `fal`.
|
||||
func stateFal(s *scanner, c byte) int {
|
||||
if c == 's' {
|
||||
s.step = stateFals
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 's')")
|
||||
}
|
||||
|
||||
// stateFals is the state after reading `fals`.
|
||||
func stateFals(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateN is the state after reading `n`.
|
||||
func stateN(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateNu
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateNu is the state after reading `nu`.
|
||||
func stateNu(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateNul
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateNul is the state after reading `nul`.
|
||||
func stateNul(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateError is the state after reaching a syntax error,
|
||||
// such as after reading `[1}` or `5.1.2`.
|
||||
func stateError(s *scanner, c byte) int {
|
||||
return scanError
|
||||
}
|
||||
|
||||
// error records an error and switches to the error state.
|
||||
func (s *scanner) error(c byte, context string) int {
|
||||
s.step = stateError
|
||||
s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// quoteChar formats c as a quoted character literal
|
||||
func quoteChar(c byte) string {
|
||||
// special cases - different from quoted strings
|
||||
if c == '\'' {
|
||||
return `'\''`
|
||||
}
|
||||
if c == '"' {
|
||||
return `'"'`
|
||||
}
|
||||
|
||||
// use quoted string with different quotation marks
|
||||
s := strconv.Quote(string(c))
|
||||
return "'" + s[1:len(s)-1] + "'"
|
||||
}
|
519
vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
generated
vendored
Normal file
519
vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
generated
vendored
Normal file
@ -0,0 +1,519 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// A Decoder reads and decodes JSON values from an input stream.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
buf []byte
|
||||
d decodeState
|
||||
scanp int // start of unread data in buf
|
||||
scanned int64 // amount of data already scanned
|
||||
scan scanner
|
||||
err error
|
||||
|
||||
tokenState int
|
||||
tokenStack []int
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number instead of as a float64.
|
||||
func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
|
||||
|
||||
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
||||
// is a struct and the input contains object keys which do not match any
|
||||
// non-ignored, exported fields in the destination.
|
||||
func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true }
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v.
|
||||
//
|
||||
// See the documentation for Unmarshal for details about
|
||||
// the conversion of JSON into a Go value.
|
||||
func (dec *Decoder) Decode(v interface{}) error {
|
||||
if dec.err != nil {
|
||||
return dec.err
|
||||
}
|
||||
|
||||
if err := dec.tokenPrepareForDecode(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !dec.tokenValueAllowed() {
|
||||
return &SyntaxError{msg: "not at beginning of value", Offset: dec.InputOffset()}
|
||||
}
|
||||
|
||||
// Read whole value into buffer.
|
||||
n, err := dec.readValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
|
||||
dec.scanp += n
|
||||
|
||||
// Don't save err from unmarshal into dec.err:
|
||||
// the connection is still usable since we read a complete JSON
|
||||
// object from it before the error happened.
|
||||
err = dec.d.unmarshal(v)
|
||||
|
||||
// fixup token streaming state
|
||||
dec.tokenValueEnd()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Buffered returns a reader of the data remaining in the Decoder's
|
||||
// buffer. The reader is valid until the next call to Decode.
|
||||
func (dec *Decoder) Buffered() io.Reader {
|
||||
return bytes.NewReader(dec.buf[dec.scanp:])
|
||||
}
|
||||
|
||||
// readValue reads a JSON value into dec.buf.
|
||||
// It returns the length of the encoding.
|
||||
func (dec *Decoder) readValue() (int, error) {
|
||||
dec.scan.reset()
|
||||
|
||||
scanp := dec.scanp
|
||||
var err error
|
||||
Input:
|
||||
// help the compiler see that scanp is never negative, so it can remove
|
||||
// some bounds checks below.
|
||||
for scanp >= 0 {
|
||||
|
||||
// Look in the buffer for a new value.
|
||||
for ; scanp < len(dec.buf); scanp++ {
|
||||
c := dec.buf[scanp]
|
||||
dec.scan.bytes++
|
||||
switch dec.scan.step(&dec.scan, c) {
|
||||
case scanEnd:
|
||||
// scanEnd is delayed one byte so we decrement
|
||||
// the scanner bytes count by 1 to ensure that
|
||||
// this value is correct in the next call of Decode.
|
||||
dec.scan.bytes--
|
||||
break Input
|
||||
case scanEndObject, scanEndArray:
|
||||
// scanEnd is delayed one byte.
|
||||
// We might block trying to get that byte from src,
|
||||
// so instead invent a space byte.
|
||||
if stateEndValue(&dec.scan, ' ') == scanEnd {
|
||||
scanp++
|
||||
break Input
|
||||
}
|
||||
case scanError:
|
||||
dec.err = dec.scan.err
|
||||
return 0, dec.scan.err
|
||||
}
|
||||
}
|
||||
|
||||
// Did the last read have an error?
|
||||
// Delayed until now to allow buffer scan.
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if dec.scan.step(&dec.scan, ' ') == scanEnd {
|
||||
break Input
|
||||
}
|
||||
if nonSpace(dec.buf) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
dec.err = err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n := scanp - dec.scanp
|
||||
err = dec.refill()
|
||||
scanp = dec.scanp + n
|
||||
}
|
||||
return scanp - dec.scanp, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) refill() error {
|
||||
// Make room to read more into the buffer.
|
||||
// First slide down data already consumed.
|
||||
if dec.scanp > 0 {
|
||||
dec.scanned += int64(dec.scanp)
|
||||
n := copy(dec.buf, dec.buf[dec.scanp:])
|
||||
dec.buf = dec.buf[:n]
|
||||
dec.scanp = 0
|
||||
}
|
||||
|
||||
// Grow buffer if not large enough.
|
||||
const minRead = 512
|
||||
if cap(dec.buf)-len(dec.buf) < minRead {
|
||||
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
|
||||
copy(newBuf, dec.buf)
|
||||
dec.buf = newBuf
|
||||
}
|
||||
|
||||
// Read. Delay error for next iteration (after scan).
|
||||
n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
|
||||
dec.buf = dec.buf[0 : len(dec.buf)+n]
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func nonSpace(b []byte) bool {
|
||||
for _, c := range b {
|
||||
if !isSpace(c) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// An Encoder writes JSON values to an output stream.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
err error
|
||||
escapeHTML bool
|
||||
|
||||
indentBuf *bytes.Buffer
|
||||
indentPrefix string
|
||||
indentValue string
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w, escapeHTML: true}
|
||||
}
|
||||
|
||||
// Encode writes the JSON encoding of v to the stream,
|
||||
// followed by a newline character.
|
||||
//
|
||||
// See the documentation for Marshal for details about the
|
||||
// conversion of Go values to JSON.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
if enc.err != nil {
|
||||
return enc.err
|
||||
}
|
||||
e := newEncodeState()
|
||||
err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Terminate each value with a newline.
|
||||
// This makes the output look a little nicer
|
||||
// when debugging, and some kind of space
|
||||
// is required if the encoded value was a number,
|
||||
// so that the reader knows there aren't more
|
||||
// digits coming.
|
||||
e.WriteByte('\n')
|
||||
|
||||
b := e.Bytes()
|
||||
if enc.indentPrefix != "" || enc.indentValue != "" {
|
||||
if enc.indentBuf == nil {
|
||||
enc.indentBuf = new(bytes.Buffer)
|
||||
}
|
||||
enc.indentBuf.Reset()
|
||||
err = Indent(enc.indentBuf, b, enc.indentPrefix, enc.indentValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b = enc.indentBuf.Bytes()
|
||||
}
|
||||
if _, err = enc.w.Write(b); err != nil {
|
||||
enc.err = err
|
||||
}
|
||||
encodeStatePool.Put(e)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetIndent instructs the encoder to format each subsequent encoded
|
||||
// value as if indented by the package-level function Indent(dst, src, prefix, indent).
|
||||
// Calling SetIndent("", "") disables indentation.
|
||||
func (enc *Encoder) SetIndent(prefix, indent string) {
|
||||
enc.indentPrefix = prefix
|
||||
enc.indentValue = indent
|
||||
}
|
||||
|
||||
// SetEscapeHTML specifies whether problematic HTML characters
|
||||
// should be escaped inside JSON quoted strings.
|
||||
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
|
||||
// to avoid certain safety problems that can arise when embedding JSON in HTML.
|
||||
//
|
||||
// In non-HTML settings where the escaping interferes with the readability
|
||||
// of the output, SetEscapeHTML(false) disables this behavior.
|
||||
func (enc *Encoder) SetEscapeHTML(on bool) {
|
||||
enc.escapeHTML = on
|
||||
}
|
||||
|
||||
/*
|
||||
// RawMessage is a raw encoded JSON value.
|
||||
// It implements Marshaler and Unmarshaler and can
|
||||
// be used to delay JSON decoding or precompute a JSON encoding.
|
||||
type RawMessage []byte
|
||||
|
||||
// MarshalJSON returns m as the JSON encoding of m.
|
||||
func (m RawMessage) MarshalJSON() ([]byte, error) {
|
||||
if m == nil {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets *m to a copy of data.
|
||||
func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||
if m == nil {
|
||||
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
|
||||
}
|
||||
*m = append((*m)[0:0], data...)
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
var _ Marshaler = (*RawMessage)(nil)
|
||||
var _ Unmarshaler = (*RawMessage)(nil)
|
||||
|
||||
/*
|
||||
// A Token holds a value of one of these types:
|
||||
//
|
||||
// Delim, for the four JSON delimiters [ ] { }
|
||||
// bool, for JSON booleans
|
||||
// float64, for JSON numbers
|
||||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token interface{}
|
||||
*/
|
||||
|
||||
const (
|
||||
tokenTopValue = iota
|
||||
tokenArrayStart
|
||||
tokenArrayValue
|
||||
tokenArrayComma
|
||||
tokenObjectStart
|
||||
tokenObjectKey
|
||||
tokenObjectColon
|
||||
tokenObjectValue
|
||||
tokenObjectComma
|
||||
)
|
||||
|
||||
// advance tokenstate from a separator state to a value state
|
||||
func (dec *Decoder) tokenPrepareForDecode() error {
|
||||
// Note: Not calling peek before switch, to avoid
|
||||
// putting peek into the standard Decode path.
|
||||
// peek is only called when using the Token API.
|
||||
switch dec.tokenState {
|
||||
case tokenArrayComma:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ',' {
|
||||
return &SyntaxError{"expected comma after array element", dec.InputOffset()}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
case tokenObjectColon:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ':' {
|
||||
return &SyntaxError{"expected colon after object key", dec.InputOffset()}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueAllowed() bool {
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueEnd() {
|
||||
switch dec.tokenState {
|
||||
case tokenArrayStart, tokenArrayValue:
|
||||
dec.tokenState = tokenArrayComma
|
||||
case tokenObjectValue:
|
||||
dec.tokenState = tokenObjectComma
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
|
||||
type Delim rune
|
||||
|
||||
func (d Delim) String() string {
|
||||
return string(d)
|
||||
}
|
||||
*/
|
||||
|
||||
// Token returns the next JSON token in the input stream.
|
||||
// At the end of the input stream, Token returns nil, io.EOF.
|
||||
//
|
||||
// Token guarantees that the delimiters [ ] { } it returns are
|
||||
// properly nested and matched: if Token encounters an unexpected
|
||||
// delimiter in the input, it will return an error.
|
||||
//
|
||||
// The input stream consists of basic JSON values—bool, string,
|
||||
// number, and null—along with delimiters [ ] { } of type Delim
|
||||
// to mark the start and end of arrays and objects.
|
||||
// Commas and colons are elided.
|
||||
func (dec *Decoder) Token() (Token, error) {
|
||||
for {
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch c {
|
||||
case '[':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenArrayStart
|
||||
return Delim('['), nil
|
||||
|
||||
case ']':
|
||||
if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim(']'), nil
|
||||
|
||||
case '{':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenObjectStart
|
||||
return Delim('{'), nil
|
||||
|
||||
case '}':
|
||||
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim('}'), nil
|
||||
|
||||
case ':':
|
||||
if dec.tokenState != tokenObjectColon {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
continue
|
||||
|
||||
case ',':
|
||||
if dec.tokenState == tokenArrayComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
continue
|
||||
}
|
||||
if dec.tokenState == tokenObjectComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectKey
|
||||
continue
|
||||
}
|
||||
return dec.tokenError(c)
|
||||
|
||||
case '"':
|
||||
if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
|
||||
var x string
|
||||
old := dec.tokenState
|
||||
dec.tokenState = tokenTopValue
|
||||
err := dec.Decode(&x)
|
||||
dec.tokenState = old
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec.tokenState = tokenObjectColon
|
||||
return x, nil
|
||||
}
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
var x interface{}
|
||||
if err := dec.Decode(&x); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenError(c byte) (Token, error) {
|
||||
var context string
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayComma:
|
||||
context = " after array element"
|
||||
case tokenObjectKey:
|
||||
context = " looking for beginning of object key string"
|
||||
case tokenObjectColon:
|
||||
context = " after object key"
|
||||
case tokenObjectComma:
|
||||
context = " after object key:value pair"
|
||||
}
|
||||
return nil, &SyntaxError{"invalid character " + quoteChar(c) + context, dec.InputOffset()}
|
||||
}
|
||||
|
||||
// More reports whether there is another element in the
|
||||
// current array or object being parsed.
|
||||
func (dec *Decoder) More() bool {
|
||||
c, err := dec.peek()
|
||||
return err == nil && c != ']' && c != '}'
|
||||
}
|
||||
|
||||
func (dec *Decoder) peek() (byte, error) {
|
||||
var err error
|
||||
for {
|
||||
for i := dec.scanp; i < len(dec.buf); i++ {
|
||||
c := dec.buf[i]
|
||||
if isSpace(c) {
|
||||
continue
|
||||
}
|
||||
dec.scanp = i
|
||||
return c, nil
|
||||
}
|
||||
// buffer has been scanned, now report any error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = dec.refill()
|
||||
}
|
||||
}
|
||||
|
||||
// InputOffset returns the input stream byte offset of the current decoder position.
|
||||
// The offset gives the location of the end of the most recently returned token
|
||||
// and the beginning of the next token.
|
||||
func (dec *Decoder) InputOffset() int64 {
|
||||
return dec.scanned + int64(dec.scanp)
|
||||
}
|
218
vendor/sigs.k8s.io/json/internal/golang/encoding/json/tables.go
generated
vendored
Normal file
218
vendor/sigs.k8s.io/json/internal/golang/encoding/json/tables.go
generated
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
// safeSet holds the value true if the ASCII character with the given array
|
||||
// position can be represented inside a JSON string without any further
|
||||
// escaping.
|
||||
//
|
||||
// All values are true except for the ASCII control characters (0-31), the
|
||||
// double quote ("), and the backslash character ("\").
|
||||
var safeSet = [utf8.RuneSelf]bool{
|
||||
' ': true,
|
||||
'!': true,
|
||||
'"': false,
|
||||
'#': true,
|
||||
'$': true,
|
||||
'%': true,
|
||||
'&': true,
|
||||
'\'': true,
|
||||
'(': true,
|
||||
')': true,
|
||||
'*': true,
|
||||
'+': true,
|
||||
',': true,
|
||||
'-': true,
|
||||
'.': true,
|
||||
'/': true,
|
||||
'0': true,
|
||||
'1': true,
|
||||
'2': true,
|
||||
'3': true,
|
||||
'4': true,
|
||||
'5': true,
|
||||
'6': true,
|
||||
'7': true,
|
||||
'8': true,
|
||||
'9': true,
|
||||
':': true,
|
||||
';': true,
|
||||
'<': true,
|
||||
'=': true,
|
||||
'>': true,
|
||||
'?': true,
|
||||
'@': true,
|
||||
'A': true,
|
||||
'B': true,
|
||||
'C': true,
|
||||
'D': true,
|
||||
'E': true,
|
||||
'F': true,
|
||||
'G': true,
|
||||
'H': true,
|
||||
'I': true,
|
||||
'J': true,
|
||||
'K': true,
|
||||
'L': true,
|
||||
'M': true,
|
||||
'N': true,
|
||||
'O': true,
|
||||
'P': true,
|
||||
'Q': true,
|
||||
'R': true,
|
||||
'S': true,
|
||||
'T': true,
|
||||
'U': true,
|
||||
'V': true,
|
||||
'W': true,
|
||||
'X': true,
|
||||
'Y': true,
|
||||
'Z': true,
|
||||
'[': true,
|
||||
'\\': false,
|
||||
']': true,
|
||||
'^': true,
|
||||
'_': true,
|
||||
'`': true,
|
||||
'a': true,
|
||||
'b': true,
|
||||
'c': true,
|
||||
'd': true,
|
||||
'e': true,
|
||||
'f': true,
|
||||
'g': true,
|
||||
'h': true,
|
||||
'i': true,
|
||||
'j': true,
|
||||
'k': true,
|
||||
'l': true,
|
||||
'm': true,
|
||||
'n': true,
|
||||
'o': true,
|
||||
'p': true,
|
||||
'q': true,
|
||||
'r': true,
|
||||
's': true,
|
||||
't': true,
|
||||
'u': true,
|
||||
'v': true,
|
||||
'w': true,
|
||||
'x': true,
|
||||
'y': true,
|
||||
'z': true,
|
||||
'{': true,
|
||||
'|': true,
|
||||
'}': true,
|
||||
'~': true,
|
||||
'\u007f': true,
|
||||
}
|
||||
|
||||
// htmlSafeSet holds the value true if the ASCII character with the given
|
||||
// array position can be safely represented inside a JSON string, embedded
|
||||
// inside of HTML <script> tags, without any additional escaping.
|
||||
//
|
||||
// All values are true except for the ASCII control characters (0-31), the
|
||||
// double quote ("), the backslash character ("\"), HTML opening and closing
|
||||
// tags ("<" and ">"), and the ampersand ("&").
|
||||
var htmlSafeSet = [utf8.RuneSelf]bool{
|
||||
' ': true,
|
||||
'!': true,
|
||||
'"': false,
|
||||
'#': true,
|
||||
'$': true,
|
||||
'%': true,
|
||||
'&': false,
|
||||
'\'': true,
|
||||
'(': true,
|
||||
')': true,
|
||||
'*': true,
|
||||
'+': true,
|
||||
',': true,
|
||||
'-': true,
|
||||
'.': true,
|
||||
'/': true,
|
||||
'0': true,
|
||||
'1': true,
|
||||
'2': true,
|
||||
'3': true,
|
||||
'4': true,
|
||||
'5': true,
|
||||
'6': true,
|
||||
'7': true,
|
||||
'8': true,
|
||||
'9': true,
|
||||
':': true,
|
||||
';': true,
|
||||
'<': false,
|
||||
'=': true,
|
||||
'>': false,
|
||||
'?': true,
|
||||
'@': true,
|
||||
'A': true,
|
||||
'B': true,
|
||||
'C': true,
|
||||
'D': true,
|
||||
'E': true,
|
||||
'F': true,
|
||||
'G': true,
|
||||
'H': true,
|
||||
'I': true,
|
||||
'J': true,
|
||||
'K': true,
|
||||
'L': true,
|
||||
'M': true,
|
||||
'N': true,
|
||||
'O': true,
|
||||
'P': true,
|
||||
'Q': true,
|
||||
'R': true,
|
||||
'S': true,
|
||||
'T': true,
|
||||
'U': true,
|
||||
'V': true,
|
||||
'W': true,
|
||||
'X': true,
|
||||
'Y': true,
|
||||
'Z': true,
|
||||
'[': true,
|
||||
'\\': false,
|
||||
']': true,
|
||||
'^': true,
|
||||
'_': true,
|
||||
'`': true,
|
||||
'a': true,
|
||||
'b': true,
|
||||
'c': true,
|
||||
'd': true,
|
||||
'e': true,
|
||||
'f': true,
|
||||
'g': true,
|
||||
'h': true,
|
||||
'i': true,
|
||||
'j': true,
|
||||
'k': true,
|
||||
'l': true,
|
||||
'm': true,
|
||||
'n': true,
|
||||
'o': true,
|
||||
'p': true,
|
||||
'q': true,
|
||||
'r': true,
|
||||
's': true,
|
||||
't': true,
|
||||
'u': true,
|
||||
'v': true,
|
||||
'w': true,
|
||||
'x': true,
|
||||
'y': true,
|
||||
'z': true,
|
||||
'{': true,
|
||||
'|': true,
|
||||
'}': true,
|
||||
'~': true,
|
||||
'\u007f': true,
|
||||
}
|
44
vendor/sigs.k8s.io/json/internal/golang/encoding/json/tags.go
generated
vendored
Normal file
44
vendor/sigs.k8s.io/json/internal/golang/encoding/json/tags.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
139
vendor/sigs.k8s.io/json/json.go
generated
vendored
Normal file
139
vendor/sigs.k8s.io/json/json.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2021 The Kubernetes Authors.
|
||||
|
||||
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 json
|
||||
|
||||
import (
|
||||
gojson "encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
internaljson "sigs.k8s.io/json/internal/golang/encoding/json"
|
||||
)
|
||||
|
||||
// Decoder describes the decoding API exposed by `encoding/json#Decoder`
|
||||
type Decoder interface {
|
||||
Decode(v interface{}) error
|
||||
Buffered() io.Reader
|
||||
Token() (gojson.Token, error)
|
||||
More() bool
|
||||
InputOffset() int64
|
||||
}
|
||||
|
||||
// NewDecoderCaseSensitivePreserveInts returns a decoder that matches the behavior of encoding/json#NewDecoder, with the following changes:
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
func NewDecoderCaseSensitivePreserveInts(r io.Reader) Decoder {
|
||||
d := internaljson.NewDecoder(r)
|
||||
d.CaseSensitive()
|
||||
d.PreserveInts()
|
||||
return d
|
||||
}
|
||||
|
||||
// UnmarshalCaseSensitivePreserveInts parses the JSON-encoded data and stores the result in the value pointed to by v.
|
||||
//
|
||||
// UnmarshalCaseSensitivePreserveInts matches the behavior of encoding/json#Unmarshal, with the following changes:
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
func UnmarshalCaseSensitivePreserveInts(data []byte, v interface{}) error {
|
||||
return internaljson.Unmarshal(
|
||||
data,
|
||||
v,
|
||||
internaljson.CaseSensitive,
|
||||
internaljson.PreserveInts,
|
||||
)
|
||||
}
|
||||
|
||||
type StrictOption int
|
||||
|
||||
const (
|
||||
// DisallowDuplicateFields returns strict errors if data contains duplicate fields
|
||||
DisallowDuplicateFields StrictOption = 1
|
||||
|
||||
// DisallowUnknownFields returns strict errors if data contains unknown fields when decoding into typed structs
|
||||
DisallowUnknownFields StrictOption = 2
|
||||
)
|
||||
|
||||
// UnmarshalStrict parses the JSON-encoded data and stores the result in the value pointed to by v.
|
||||
// Unmarshaling is performed identically to UnmarshalCaseSensitivePreserveInts(), returning an error on failure.
|
||||
//
|
||||
// If parsing succeeds, additional strict checks as selected by `strictOptions` are performed
|
||||
// and a list of the strict failures (if any) are returned. If no `strictOptions` are selected,
|
||||
// all supported strict checks are performed.
|
||||
//
|
||||
// Currently supported strict checks are:
|
||||
// - DisallowDuplicateFields: ensure the data contains no duplicate fields
|
||||
// - DisallowUnknownFields: ensure the data contains no unknown fields (when decoding into typed structs)
|
||||
//
|
||||
// Additional strict checks may be added in the future.
|
||||
//
|
||||
// Note that the strict checks do not change what is stored in v.
|
||||
// For example, if duplicate fields are present, they will be parsed and stored in v,
|
||||
// and errors about the duplicate fields will be returned in the strict error list.
|
||||
func UnmarshalStrict(data []byte, v interface{}, strictOptions ...StrictOption) (strictErrors []error, err error) {
|
||||
if len(strictOptions) == 0 {
|
||||
err = internaljson.Unmarshal(data, v,
|
||||
// options matching UnmarshalCaseSensitivePreserveInts
|
||||
internaljson.CaseSensitive,
|
||||
internaljson.PreserveInts,
|
||||
// all strict options
|
||||
internaljson.DisallowDuplicateFields,
|
||||
internaljson.DisallowUnknownFields,
|
||||
)
|
||||
} else {
|
||||
opts := make([]internaljson.UnmarshalOpt, 0, 2+len(strictOptions))
|
||||
// options matching UnmarshalCaseSensitivePreserveInts
|
||||
opts = append(opts, internaljson.CaseSensitive, internaljson.PreserveInts)
|
||||
for _, strictOpt := range strictOptions {
|
||||
switch strictOpt {
|
||||
case DisallowDuplicateFields:
|
||||
opts = append(opts, internaljson.DisallowDuplicateFields)
|
||||
case DisallowUnknownFields:
|
||||
opts = append(opts, internaljson.DisallowUnknownFields)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown strict option %d", strictOpt)
|
||||
}
|
||||
}
|
||||
err = internaljson.Unmarshal(data, v, opts...)
|
||||
}
|
||||
|
||||
if strictErr, ok := err.(*internaljson.UnmarshalStrictError); ok {
|
||||
return strictErr.Errors, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// SyntaxErrorOffset returns if the specified error is a syntax error produced by encoding/json or this package.
|
||||
func SyntaxErrorOffset(err error) (isSyntaxError bool, offset int64) {
|
||||
switch err := err.(type) {
|
||||
case *gojson.SyntaxError:
|
||||
return true, err.Offset
|
||||
case *internaljson.SyntaxError:
|
||||
return true, err.Offset
|
||||
default:
|
||||
return false, 0
|
||||
}
|
||||
}
|
70
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/merge.go
generated
vendored
70
vendor/sigs.k8s.io/structured-merge-diff/v4/typed/merge.go
generated
vendored
@ -172,35 +172,10 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
||||
}
|
||||
out := make([]interface{}, 0, int(math.Max(float64(rLen), float64(lLen))))
|
||||
|
||||
// TODO: ordering is totally wrong.
|
||||
// TODO: might as well make the map order work the same way.
|
||||
lhsOrder := make([]fieldpath.PathElement, 0, lLen)
|
||||
|
||||
// This is a cheap hack to at least make the output order stable.
|
||||
rhsOrder := make([]fieldpath.PathElement, 0, rLen)
|
||||
|
||||
// First, collect all RHS children.
|
||||
observedRHS := fieldpath.MakePathElementValueMap(rLen)
|
||||
if rhs != nil {
|
||||
for i := 0; i < rhs.Length(); i++ {
|
||||
child := rhs.At(i)
|
||||
pe, err := listItemToPathElement(w.allocator, w.schema, t, i, child)
|
||||
if err != nil {
|
||||
errs = append(errs, errorf("rhs: element %v: %v", i, err.Error())...)
|
||||
// If we can't construct the path element, we can't
|
||||
// even report errors deeper in the schema, so bail on
|
||||
// this element.
|
||||
continue
|
||||
}
|
||||
if _, ok := observedRHS.Get(pe); ok {
|
||||
errs = append(errs, errorf("rhs: duplicate entries for key %v", pe.String())...)
|
||||
}
|
||||
observedRHS.Insert(pe, child)
|
||||
rhsOrder = append(rhsOrder, pe)
|
||||
}
|
||||
}
|
||||
|
||||
// Then merge with LHS children.
|
||||
observedLHS := fieldpath.MakePathElementSet(lLen)
|
||||
// First, collect all LHS children.
|
||||
observedLHS := fieldpath.MakePathElementValueMap(lLen)
|
||||
if lhs != nil {
|
||||
for i := 0; i < lhs.Length(); i++ {
|
||||
child := lhs.At(i)
|
||||
@ -212,15 +187,36 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
||||
// this element.
|
||||
continue
|
||||
}
|
||||
if observedLHS.Has(pe) {
|
||||
if _, ok := observedLHS.Get(pe); ok {
|
||||
errs = append(errs, errorf("lhs: duplicate entries for key %v", pe.String())...)
|
||||
}
|
||||
observedLHS.Insert(pe, child)
|
||||
lhsOrder = append(lhsOrder, pe)
|
||||
}
|
||||
}
|
||||
|
||||
// Then merge with RHS children.
|
||||
observedRHS := fieldpath.MakePathElementSet(rLen)
|
||||
if rhs != nil {
|
||||
for i := 0; i < rhs.Length(); i++ {
|
||||
child := rhs.At(i)
|
||||
pe, err := listItemToPathElement(w.allocator, w.schema, t, i, child)
|
||||
if err != nil {
|
||||
errs = append(errs, errorf("rhs: element %v: %v", i, err.Error())...)
|
||||
// If we can't construct the path element, we can't
|
||||
// even report errors deeper in the schema, so bail on
|
||||
// this element.
|
||||
continue
|
||||
}
|
||||
observedLHS.Insert(pe)
|
||||
if observedRHS.Has(pe) {
|
||||
errs = append(errs, errorf("rhs: duplicate entries for key %v", pe.String())...)
|
||||
continue
|
||||
}
|
||||
observedRHS.Insert(pe)
|
||||
w2 := w.prepareDescent(pe, t.ElementType)
|
||||
w2.lhs = value.Value(child)
|
||||
if rchild, ok := observedRHS.Get(pe); ok {
|
||||
w2.rhs = rchild
|
||||
w2.rhs = child
|
||||
if lchild, ok := observedLHS.Get(pe); ok {
|
||||
w2.lhs = lchild
|
||||
}
|
||||
errs = append(errs, w2.merge(pe.String)...)
|
||||
if w2.out != nil {
|
||||
@ -230,13 +226,13 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
||||
}
|
||||
}
|
||||
|
||||
for _, pe := range rhsOrder {
|
||||
if observedLHS.Has(pe) {
|
||||
for _, pe := range lhsOrder {
|
||||
if observedRHS.Has(pe) {
|
||||
continue
|
||||
}
|
||||
value, _ := observedRHS.Get(pe)
|
||||
value, _ := observedLHS.Get(pe)
|
||||
w2 := w.prepareDescent(pe, t.ElementType)
|
||||
w2.rhs = value
|
||||
w2.lhs = value
|
||||
errs = append(errs, w2.merge(pe.String)...)
|
||||
if w2.out != nil {
|
||||
out = append(out, *w2.out)
|
||||
|
4
vendor/sigs.k8s.io/yaml/.gitignore
generated
vendored
4
vendor/sigs.k8s.io/yaml/.gitignore
generated
vendored
@ -6,6 +6,10 @@
|
||||
.project
|
||||
.settings/**
|
||||
|
||||
# Idea files
|
||||
.idea/**
|
||||
.idea/
|
||||
|
||||
# Emacs save files
|
||||
*~
|
||||
|
||||
|
7
vendor/sigs.k8s.io/yaml/.travis.yml
generated
vendored
7
vendor/sigs.k8s.io/yaml/.travis.yml
generated
vendored
@ -1,8 +1,7 @@
|
||||
language: go
|
||||
dist: xenial
|
||||
go:
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
arch: arm64
|
||||
dist: focal
|
||||
go: 1.15.x
|
||||
script:
|
||||
- diff -u <(echo -n) <(gofmt -d *.go)
|
||||
- diff -u <(echo -n) <(golint $(go list -e ./...) | grep -v YAMLToJSON)
|
||||
|
2
vendor/sigs.k8s.io/yaml/README.md
generated
vendored
2
vendor/sigs.k8s.io/yaml/README.md
generated
vendored
@ -107,8 +107,8 @@ func main() {
|
||||
}
|
||||
fmt.Println(string(y))
|
||||
/* Output:
|
||||
name: John
|
||||
age: 30
|
||||
name: John
|
||||
*/
|
||||
j2, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
|
2
vendor/sigs.k8s.io/yaml/go.mod
generated
vendored
2
vendor/sigs.k8s.io/yaml/go.mod
generated
vendored
@ -4,5 +4,5 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
9
vendor/sigs.k8s.io/yaml/go.sum
generated
vendored
9
vendor/sigs.k8s.io/yaml/go.sum
generated
vendored
@ -1,9 +1,6 @@
|
||||
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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
Reference in New Issue
Block a user