diff --git a/api/mesh/v1alpha1/selector.pb.go b/api/mesh/v1alpha1/selector.pb.go new file mode 100644 index 000000000000..c95d5182099b --- /dev/null +++ b/api/mesh/v1alpha1/selector.pb.go @@ -0,0 +1,465 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: mesh/v1alpha1/selector.proto + +package v1alpha1 + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// Selector defines structure for selecting tags for given dataplane +type Selector struct { + // Tags to match, can be used for both source and destinations + Match map[string]string `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Selector) Reset() { *m = Selector{} } +func (m *Selector) String() string { return proto.CompactTextString(m) } +func (*Selector) ProtoMessage() {} +func (*Selector) Descriptor() ([]byte, []int) { + return fileDescriptor_95def39c1d383442, []int{0} +} +func (m *Selector) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Selector) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Selector.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Selector) XXX_Merge(src proto.Message) { + xxx_messageInfo_Selector.Merge(m, src) +} +func (m *Selector) XXX_Size() int { + return m.Size() +} +func (m *Selector) XXX_DiscardUnknown() { + xxx_messageInfo_Selector.DiscardUnknown(m) +} + +var xxx_messageInfo_Selector proto.InternalMessageInfo + +func (m *Selector) GetMatch() map[string]string { + if m != nil { + return m.Match + } + return nil +} + +func init() { + proto.RegisterType((*Selector)(nil), "kuma.mesh.v1alpha1.Selector") + proto.RegisterMapType((map[string]string)(nil), "kuma.mesh.v1alpha1.Selector.MatchEntry") +} + +func init() { proto.RegisterFile("mesh/v1alpha1/selector.proto", fileDescriptor_95def39c1d383442) } + +var fileDescriptor_95def39c1d383442 = []byte{ + // 174 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xc9, 0x4d, 0x2d, 0xce, + 0xd0, 0x2f, 0x33, 0x4c, 0xcc, 0x29, 0xc8, 0x48, 0x34, 0xd4, 0x2f, 0x4e, 0xcd, 0x49, 0x4d, 0x2e, + 0xc9, 0x2f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xca, 0x2e, 0xcd, 0x4d, 0xd4, 0x03, + 0x29, 0xd1, 0x83, 0x29, 0x51, 0x6a, 0x66, 0xe4, 0xe2, 0x08, 0x86, 0x2a, 0x13, 0xb2, 0xe5, 0x62, + 0xcd, 0x4d, 0x2c, 0x49, 0xce, 0x90, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x52, 0xd7, 0xc3, 0xd4, + 0xa0, 0x07, 0x53, 0xac, 0xe7, 0x0b, 0x52, 0xe9, 0x9a, 0x57, 0x52, 0x54, 0x19, 0x04, 0xd1, 0x25, + 0x65, 0xc1, 0xc5, 0x85, 0x10, 0x14, 0x12, 0xe0, 0x62, 0xce, 0x4e, 0xad, 0x94, 0x60, 0x54, 0x60, + 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x85, 0x44, 0xb8, 0x58, 0xcb, 0x12, 0x73, 0x4a, 0x53, 0x25, 0x98, + 0xc0, 0x62, 0x10, 0x8e, 0x15, 0x93, 0x05, 0xa3, 0x93, 0xd8, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, + 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0xc5, 0x01, 0xb3, 0x2c, 0x89, 0x0d, 0xec, 0x70, 0x63, + 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x57, 0x6f, 0x1e, 0xd8, 0x00, 0x00, 0x00, +} + +func (m *Selector) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Selector) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Match) > 0 { + for k, _ := range m.Match { + dAtA[i] = 0xa + i++ + v := m.Match[k] + mapSize := 1 + len(k) + sovSelector(uint64(len(k))) + 1 + len(v) + sovSelector(uint64(len(v))) + i = encodeVarintSelector(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintSelector(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintSelector(dAtA, i, uint64(len(v))) + i += copy(dAtA[i:], v) + } + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil +} + +func encodeVarintSelector(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Selector) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Match) > 0 { + for k, v := range m.Match { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovSelector(uint64(len(k))) + 1 + len(v) + sovSelector(uint64(len(v))) + n += mapEntrySize + 1 + sovSelector(uint64(mapEntrySize)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func sovSelector(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozSelector(x uint64) (n int) { + return sovSelector(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Selector) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSelector + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Selector: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Selector: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Match", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSelector + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthSelector + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthSelector + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Match == nil { + m.Match = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSelector + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSelector + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthSelector + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthSelector + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSelector + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthSelector + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthSelector + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipSelector(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSelector + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Match[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSelector(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSelector + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthSelector + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipSelector(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSelector + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSelector + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSelector + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthSelector + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthSelector + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSelector + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipSelector(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthSelector + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthSelector = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowSelector = fmt.Errorf("proto: integer overflow") +) diff --git a/api/mesh/v1alpha1/selector.proto b/api/mesh/v1alpha1/selector.proto new file mode 100644 index 000000000000..a22ad6f51dc0 --- /dev/null +++ b/api/mesh/v1alpha1/selector.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package kuma.mesh.v1alpha1; + +option go_package = "v1alpha1"; + +// Selector defines structure for selecting tags for given dataplane +message Selector { + // Tags to match, can be used for both source and destinations + map match = 1; +} diff --git a/api/mesh/v1alpha1/traffic_log.pb.go b/api/mesh/v1alpha1/traffic_log.pb.go new file mode 100644 index 000000000000..ed99d0264e95 --- /dev/null +++ b/api/mesh/v1alpha1/traffic_log.pb.go @@ -0,0 +1,849 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: mesh/v1alpha1/traffic_log.proto + +package v1alpha1 + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type TrafficLog struct { + Rules []*TrafficLog_Rule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrafficLog) Reset() { *m = TrafficLog{} } +func (m *TrafficLog) String() string { return proto.CompactTextString(m) } +func (*TrafficLog) ProtoMessage() {} +func (*TrafficLog) Descriptor() ([]byte, []int) { + return fileDescriptor_47c4f4c9c894eeed, []int{0} +} +func (m *TrafficLog) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrafficLog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrafficLog.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrafficLog) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrafficLog.Merge(m, src) +} +func (m *TrafficLog) XXX_Size() int { + return m.Size() +} +func (m *TrafficLog) XXX_DiscardUnknown() { + xxx_messageInfo_TrafficLog.DiscardUnknown(m) +} + +var xxx_messageInfo_TrafficLog proto.InternalMessageInfo + +func (m *TrafficLog) GetRules() []*TrafficLog_Rule { + if m != nil { + return m.Rules + } + return nil +} + +type TrafficLog_Rule struct { + Sources []*Selector `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` + Destinations []*Selector `protobuf:"bytes,2,rep,name=destinations,proto3" json:"destinations,omitempty"` + Conf *TrafficLog_Rule_Conf `protobuf:"bytes,3,opt,name=conf,proto3" json:"conf,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrafficLog_Rule) Reset() { *m = TrafficLog_Rule{} } +func (m *TrafficLog_Rule) String() string { return proto.CompactTextString(m) } +func (*TrafficLog_Rule) ProtoMessage() {} +func (*TrafficLog_Rule) Descriptor() ([]byte, []int) { + return fileDescriptor_47c4f4c9c894eeed, []int{0, 0} +} +func (m *TrafficLog_Rule) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrafficLog_Rule) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrafficLog_Rule.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrafficLog_Rule) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrafficLog_Rule.Merge(m, src) +} +func (m *TrafficLog_Rule) XXX_Size() int { + return m.Size() +} +func (m *TrafficLog_Rule) XXX_DiscardUnknown() { + xxx_messageInfo_TrafficLog_Rule.DiscardUnknown(m) +} + +var xxx_messageInfo_TrafficLog_Rule proto.InternalMessageInfo + +func (m *TrafficLog_Rule) GetSources() []*Selector { + if m != nil { + return m.Sources + } + return nil +} + +func (m *TrafficLog_Rule) GetDestinations() []*Selector { + if m != nil { + return m.Destinations + } + return nil +} + +func (m *TrafficLog_Rule) GetConf() *TrafficLog_Rule_Conf { + if m != nil { + return m.Conf + } + return nil +} + +type TrafficLog_Rule_Conf struct { + Backend string `protobuf:"bytes,1,opt,name=backend,proto3" json:"backend,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrafficLog_Rule_Conf) Reset() { *m = TrafficLog_Rule_Conf{} } +func (m *TrafficLog_Rule_Conf) String() string { return proto.CompactTextString(m) } +func (*TrafficLog_Rule_Conf) ProtoMessage() {} +func (*TrafficLog_Rule_Conf) Descriptor() ([]byte, []int) { + return fileDescriptor_47c4f4c9c894eeed, []int{0, 0, 0} +} +func (m *TrafficLog_Rule_Conf) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrafficLog_Rule_Conf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrafficLog_Rule_Conf.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrafficLog_Rule_Conf) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrafficLog_Rule_Conf.Merge(m, src) +} +func (m *TrafficLog_Rule_Conf) XXX_Size() int { + return m.Size() +} +func (m *TrafficLog_Rule_Conf) XXX_DiscardUnknown() { + xxx_messageInfo_TrafficLog_Rule_Conf.DiscardUnknown(m) +} + +var xxx_messageInfo_TrafficLog_Rule_Conf proto.InternalMessageInfo + +func (m *TrafficLog_Rule_Conf) GetBackend() string { + if m != nil { + return m.Backend + } + return "" +} + +func init() { + proto.RegisterType((*TrafficLog)(nil), "kuma.mesh.v1alpha1.TrafficLog") + proto.RegisterType((*TrafficLog_Rule)(nil), "kuma.mesh.v1alpha1.TrafficLog.Rule") + proto.RegisterType((*TrafficLog_Rule_Conf)(nil), "kuma.mesh.v1alpha1.TrafficLog.Rule.Conf") +} + +func init() { proto.RegisterFile("mesh/v1alpha1/traffic_log.proto", fileDescriptor_47c4f4c9c894eeed) } + +var fileDescriptor_47c4f4c9c894eeed = []byte{ + // 252 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0x4d, 0x2d, 0xce, + 0xd0, 0x2f, 0x33, 0x4c, 0xcc, 0x29, 0xc8, 0x48, 0x34, 0xd4, 0x2f, 0x29, 0x4a, 0x4c, 0x4b, 0xcb, + 0x4c, 0x8e, 0xcf, 0xc9, 0x4f, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xca, 0x2e, 0xcd, + 0x4d, 0xd4, 0x03, 0xa9, 0xd2, 0x83, 0xa9, 0x92, 0x92, 0x41, 0xd5, 0x54, 0x9c, 0x9a, 0x93, 0x9a, + 0x5c, 0x92, 0x5f, 0x04, 0xd1, 0xa1, 0xb4, 0x8a, 0x89, 0x8b, 0x2b, 0x04, 0x62, 0x8e, 0x4f, 0x7e, + 0xba, 0x90, 0x25, 0x17, 0x6b, 0x51, 0x69, 0x4e, 0x6a, 0xb1, 0x04, 0xa3, 0x02, 0xb3, 0x06, 0xb7, + 0x91, 0xb2, 0x1e, 0xa6, 0x81, 0x7a, 0x08, 0xe5, 0x7a, 0x41, 0xa5, 0x39, 0xa9, 0x41, 0x10, 0x1d, + 0x52, 0x0f, 0x18, 0xb9, 0x58, 0x40, 0x7c, 0x21, 0x33, 0x2e, 0xf6, 0xe2, 0xfc, 0xd2, 0xa2, 0x64, + 0xb8, 0x29, 0x32, 0xd8, 0x4c, 0x09, 0x86, 0xba, 0x23, 0x08, 0xa6, 0x58, 0xc8, 0x81, 0x8b, 0x27, + 0x25, 0xb5, 0xb8, 0x24, 0x33, 0x2f, 0xb1, 0x24, 0x33, 0x3f, 0xaf, 0x58, 0x82, 0x89, 0x08, 0xcd, + 0x28, 0x3a, 0x84, 0x6c, 0xb8, 0x58, 0x92, 0xf3, 0xf3, 0xd2, 0x24, 0x98, 0x15, 0x18, 0x35, 0xb8, + 0x8d, 0x34, 0x88, 0x70, 0xbc, 0x9e, 0x73, 0x7e, 0x5e, 0x5a, 0x10, 0x58, 0x97, 0x94, 0x02, 0x17, + 0x0b, 0x88, 0x27, 0x24, 0xc1, 0xc5, 0x9e, 0x94, 0x98, 0x9c, 0x9d, 0x9a, 0x97, 0x22, 0xc1, 0xa8, + 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe3, 0x3a, 0x89, 0x9d, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, + 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x51, 0x1c, 0x30, 0x43, 0x93, 0xd8, 0xc0, 0x61, 0x69, 0x0c, 0x08, + 0x00, 0x00, 0xff, 0xff, 0x2d, 0x11, 0x5e, 0x6a, 0xa0, 0x01, 0x00, 0x00, +} + +func (m *TrafficLog) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrafficLog) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Rules) > 0 { + for _, msg := range m.Rules { + dAtA[i] = 0xa + i++ + i = encodeVarintTrafficLog(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil +} + +func (m *TrafficLog_Rule) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrafficLog_Rule) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Sources) > 0 { + for _, msg := range m.Sources { + dAtA[i] = 0xa + i++ + i = encodeVarintTrafficLog(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Destinations) > 0 { + for _, msg := range m.Destinations { + dAtA[i] = 0x12 + i++ + i = encodeVarintTrafficLog(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.Conf != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTrafficLog(dAtA, i, uint64(m.Conf.Size())) + n1, err := m.Conf.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil +} + +func (m *TrafficLog_Rule_Conf) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrafficLog_Rule_Conf) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Backend) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTrafficLog(dAtA, i, uint64(len(m.Backend))) + i += copy(dAtA[i:], m.Backend) + } + if m.XXX_unrecognized != nil { + i += copy(dAtA[i:], m.XXX_unrecognized) + } + return i, nil +} + +func encodeVarintTrafficLog(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *TrafficLog) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Rules) > 0 { + for _, e := range m.Rules { + l = e.Size() + n += 1 + l + sovTrafficLog(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *TrafficLog_Rule) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Sources) > 0 { + for _, e := range m.Sources { + l = e.Size() + n += 1 + l + sovTrafficLog(uint64(l)) + } + } + if len(m.Destinations) > 0 { + for _, e := range m.Destinations { + l = e.Size() + n += 1 + l + sovTrafficLog(uint64(l)) + } + } + if m.Conf != nil { + l = m.Conf.Size() + n += 1 + l + sovTrafficLog(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *TrafficLog_Rule_Conf) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Backend) + if l > 0 { + n += 1 + l + sovTrafficLog(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func sovTrafficLog(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozTrafficLog(x uint64) (n int) { + return sovTrafficLog(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *TrafficLog) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TrafficLog: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TrafficLog: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTrafficLog + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTrafficLog + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Rules = append(m.Rules, &TrafficLog_Rule{}) + if err := m.Rules[len(m.Rules)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTrafficLog(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TrafficLog_Rule) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Rule: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Rule: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sources", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTrafficLog + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTrafficLog + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sources = append(m.Sources, &Selector{}) + if err := m.Sources[len(m.Sources)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Destinations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTrafficLog + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTrafficLog + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Destinations = append(m.Destinations, &Selector{}) + if err := m.Destinations[len(m.Destinations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Conf", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTrafficLog + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTrafficLog + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Conf == nil { + m.Conf = &TrafficLog_Rule_Conf{} + } + if err := m.Conf.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTrafficLog(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TrafficLog_Rule_Conf) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Conf: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Conf: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Backend", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTrafficLog + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTrafficLog + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Backend = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTrafficLog(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTrafficLog + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTrafficLog(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTrafficLog + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthTrafficLog + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrafficLog + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipTrafficLog(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthTrafficLog + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthTrafficLog = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTrafficLog = fmt.Errorf("proto: integer overflow") +) diff --git a/api/mesh/v1alpha1/traffic_log.proto b/api/mesh/v1alpha1/traffic_log.proto new file mode 100644 index 000000000000..bd0e2a997a75 --- /dev/null +++ b/api/mesh/v1alpha1/traffic_log.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package kuma.mesh.v1alpha1; + +option go_package = "v1alpha1"; + +import "mesh/v1alpha1/selector.proto"; + +message TrafficLog { + message Rule { + + repeated Selector sources = 1; + repeated Selector destinations = 2; + + message Conf { string backend = 1; } + + Conf conf = 3; + } + + repeated Rule rules = 1; +} diff --git a/api/mesh/v1alpha1/traffic_permission.pb.go b/api/mesh/v1alpha1/traffic_permission.pb.go index cc6ee1fa6bf2..6e04d2156a34 100644 --- a/api/mesh/v1alpha1/traffic_permission.pb.go +++ b/api/mesh/v1alpha1/traffic_permission.pb.go @@ -69,11 +69,11 @@ func (m *TrafficPermission) GetRules() []*TrafficPermission_Rule { } type TrafficPermission_Rule struct { - Sources []*TrafficPermission_Rule_Selector `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` - Destinations []*TrafficPermission_Rule_Selector `protobuf:"bytes,2,rep,name=destinations,proto3" json:"destinations,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Sources []*Selector `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` + Destinations []*Selector `protobuf:"bytes,2,rep,name=destinations,proto3" json:"destinations,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *TrafficPermission_Rule) Reset() { *m = TrafficPermission_Rule{} } @@ -109,72 +109,23 @@ func (m *TrafficPermission_Rule) XXX_DiscardUnknown() { var xxx_messageInfo_TrafficPermission_Rule proto.InternalMessageInfo -func (m *TrafficPermission_Rule) GetSources() []*TrafficPermission_Rule_Selector { +func (m *TrafficPermission_Rule) GetSources() []*Selector { if m != nil { return m.Sources } return nil } -func (m *TrafficPermission_Rule) GetDestinations() []*TrafficPermission_Rule_Selector { +func (m *TrafficPermission_Rule) GetDestinations() []*Selector { if m != nil { return m.Destinations } return nil } -type TrafficPermission_Rule_Selector struct { - Match map[string]string `protobuf:"bytes,1,rep,name=match,proto3" json:"match,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *TrafficPermission_Rule_Selector) Reset() { *m = TrafficPermission_Rule_Selector{} } -func (m *TrafficPermission_Rule_Selector) String() string { return proto.CompactTextString(m) } -func (*TrafficPermission_Rule_Selector) ProtoMessage() {} -func (*TrafficPermission_Rule_Selector) Descriptor() ([]byte, []int) { - return fileDescriptor_7871a84a653f4288, []int{0, 0, 0} -} -func (m *TrafficPermission_Rule_Selector) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *TrafficPermission_Rule_Selector) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_TrafficPermission_Rule_Selector.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *TrafficPermission_Rule_Selector) XXX_Merge(src proto.Message) { - xxx_messageInfo_TrafficPermission_Rule_Selector.Merge(m, src) -} -func (m *TrafficPermission_Rule_Selector) XXX_Size() int { - return m.Size() -} -func (m *TrafficPermission_Rule_Selector) XXX_DiscardUnknown() { - xxx_messageInfo_TrafficPermission_Rule_Selector.DiscardUnknown(m) -} - -var xxx_messageInfo_TrafficPermission_Rule_Selector proto.InternalMessageInfo - -func (m *TrafficPermission_Rule_Selector) GetMatch() map[string]string { - if m != nil { - return m.Match - } - return nil -} - func init() { proto.RegisterType((*TrafficPermission)(nil), "kuma.mesh.v1alpha1.TrafficPermission") proto.RegisterType((*TrafficPermission_Rule)(nil), "kuma.mesh.v1alpha1.TrafficPermission.Rule") - proto.RegisterType((*TrafficPermission_Rule_Selector)(nil), "kuma.mesh.v1alpha1.TrafficPermission.Rule.Selector") - proto.RegisterMapType((map[string]string)(nil), "kuma.mesh.v1alpha1.TrafficPermission.Rule.Selector.MatchEntry") } func init() { @@ -182,25 +133,20 @@ func init() { } var fileDescriptor_7871a84a653f4288 = []byte{ - // 273 bytes of a gzipped FileDescriptorProto + // 207 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcb, 0x4d, 0x2d, 0xce, 0xd0, 0x2f, 0x33, 0x4c, 0xcc, 0x29, 0xc8, 0x48, 0x34, 0xd4, 0x2f, 0x29, 0x4a, 0x4c, 0x4b, 0xcb, 0x4c, 0x8e, 0x2f, 0x48, 0x2d, 0xca, 0xcd, 0x2c, 0x2e, 0xce, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, - 0x2f, 0xc9, 0x17, 0x12, 0xca, 0x2e, 0xcd, 0x4d, 0xd4, 0x03, 0x29, 0xd6, 0x83, 0x29, 0x56, 0x5a, - 0xcc, 0xcc, 0x25, 0x18, 0x02, 0xd1, 0x10, 0x00, 0x57, 0x2f, 0xe4, 0xc0, 0xc5, 0x5a, 0x54, 0x9a, - 0x93, 0x5a, 0x2c, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa5, 0x87, 0xa9, 0x53, 0x0f, 0x43, - 0x97, 0x5e, 0x50, 0x69, 0x4e, 0x6a, 0x10, 0x44, 0xa3, 0xd4, 0x69, 0x26, 0x2e, 0x16, 0x10, 0x5f, - 0xc8, 0x97, 0x8b, 0xbd, 0x38, 0xbf, 0xb4, 0x28, 0x19, 0x6e, 0x98, 0x31, 0xf1, 0x86, 0xe9, 0x05, - 0xa7, 0xe6, 0xa4, 0x26, 0x97, 0xe4, 0x17, 0x05, 0xc1, 0xcc, 0x10, 0x0a, 0xe7, 0xe2, 0x49, 0x49, - 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0x96, 0x60, 0x22, 0xdf, 0x4c, 0x14, - 0x83, 0xa4, 0x66, 0x31, 0x72, 0x71, 0xc0, 0xa4, 0x84, 0x42, 0xb8, 0x58, 0x73, 0x13, 0x4b, 0x92, - 0x33, 0xa0, 0x4e, 0xb6, 0x23, 0xc3, 0x78, 0x3d, 0x5f, 0x90, 0x01, 0xae, 0x79, 0x25, 0x45, 0x95, - 0x41, 0x10, 0xc3, 0xa4, 0x2c, 0xb8, 0xb8, 0x10, 0x82, 0x42, 0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, - 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x20, 0xa6, 0x90, 0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, - 0x69, 0xaa, 0x04, 0x13, 0x58, 0x0c, 0xc2, 0xb1, 0x62, 0xb2, 0x60, 0x74, 0x12, 0x3b, 0xf1, 0x48, - 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0xa3, 0x38, 0x60, 0x6e, 0x48, 0x62, - 0x03, 0x47, 0xac, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x82, 0x1b, 0xe4, 0xa4, 0x02, 0x02, 0x00, - 0x00, + 0x2f, 0xc9, 0x17, 0x12, 0xca, 0x2e, 0xcd, 0x4d, 0xd4, 0x03, 0x29, 0xd6, 0x83, 0x29, 0x96, 0x92, + 0x41, 0xd5, 0x5b, 0x9c, 0x9a, 0x93, 0x9a, 0x5c, 0x92, 0x5f, 0x04, 0xd1, 0xa1, 0x74, 0x83, 0x91, + 0x4b, 0x30, 0x04, 0x62, 0x5c, 0x00, 0xdc, 0x34, 0x21, 0x07, 0x2e, 0xd6, 0xa2, 0xd2, 0x9c, 0xd4, + 0x62, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x2d, 0x3d, 0x4c, 0x73, 0xf5, 0x30, 0x74, 0xe9, + 0x05, 0x95, 0xe6, 0xa4, 0x06, 0x41, 0x34, 0x4a, 0x35, 0x30, 0x72, 0xb1, 0x80, 0xf8, 0x42, 0x66, + 0x5c, 0xec, 0xc5, 0xf9, 0xa5, 0x45, 0xc9, 0x70, 0xc3, 0x64, 0xb0, 0x19, 0x16, 0x0c, 0x75, 0x55, + 0x10, 0x4c, 0xb1, 0x90, 0x03, 0x17, 0x4f, 0x4a, 0x6a, 0x71, 0x49, 0x66, 0x5e, 0x62, 0x49, 0x66, + 0x7e, 0x5e, 0xb1, 0x04, 0x13, 0x11, 0x9a, 0x51, 0x74, 0x38, 0x89, 0x9d, 0x78, 0x24, 0xc7, 0x78, + 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x51, 0x1c, 0x30, 0xe5, 0x49, 0x6c, 0x60, 0x9f, + 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x36, 0xc9, 0xb9, 0x9c, 0x55, 0x01, 0x00, 0x00, } func (m *TrafficPermission) Marshal() (dAtA []byte, err error) { @@ -281,44 +227,6 @@ func (m *TrafficPermission_Rule) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *TrafficPermission_Rule_Selector) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *TrafficPermission_Rule_Selector) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Match) > 0 { - for k, _ := range m.Match { - dAtA[i] = 0xa - i++ - v := m.Match[k] - mapSize := 1 + len(k) + sovTrafficPermission(uint64(len(k))) + 1 + len(v) + sovTrafficPermission(uint64(len(v))) - i = encodeVarintTrafficPermission(dAtA, i, uint64(mapSize)) - dAtA[i] = 0xa - i++ - i = encodeVarintTrafficPermission(dAtA, i, uint64(len(k))) - i += copy(dAtA[i:], k) - dAtA[i] = 0x12 - i++ - i = encodeVarintTrafficPermission(dAtA, i, uint64(len(v))) - i += copy(dAtA[i:], v) - } - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - func encodeVarintTrafficPermission(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -370,26 +278,6 @@ func (m *TrafficPermission_Rule) Size() (n int) { return n } -func (m *TrafficPermission_Rule_Selector) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Match) > 0 { - for k, v := range m.Match { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sovTrafficPermission(uint64(len(k))) + 1 + len(v) + sovTrafficPermission(uint64(len(v))) - n += mapEntrySize + 1 + sovTrafficPermission(uint64(mapEntrySize)) - } - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - func sovTrafficPermission(x uint64) (n int) { for { n++ @@ -549,7 +437,7 @@ func (m *TrafficPermission_Rule) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Sources = append(m.Sources, &TrafficPermission_Rule_Selector{}) + m.Sources = append(m.Sources, &Selector{}) if err := m.Sources[len(m.Sources)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -583,7 +471,7 @@ func (m *TrafficPermission_Rule) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Destinations = append(m.Destinations, &TrafficPermission_Rule_Selector{}) + m.Destinations = append(m.Destinations, &Selector{}) if err := m.Destinations[len(m.Destinations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -613,187 +501,6 @@ func (m *TrafficPermission_Rule) Unmarshal(dAtA []byte) error { } return nil } -func (m *TrafficPermission_Rule_Selector) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTrafficPermission - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Selector: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Selector: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Match", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTrafficPermission - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTrafficPermission - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTrafficPermission - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Match == nil { - m.Match = make(map[string]string) - } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTrafficPermission - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTrafficPermission - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTrafficPermission - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLengthTrafficPermission - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTrafficPermission - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTrafficPermission - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue < 0 { - return ErrInvalidLengthTrafficPermission - } - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTrafficPermission(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTrafficPermission - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.Match[mapkey] = mapvalue - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTrafficPermission(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTrafficPermission - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthTrafficPermission - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipTrafficPermission(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/api/mesh/v1alpha1/traffic_permission.proto b/api/mesh/v1alpha1/traffic_permission.proto index a89a745a82b0..21eb28b50ef9 100644 --- a/api/mesh/v1alpha1/traffic_permission.proto +++ b/api/mesh/v1alpha1/traffic_permission.proto @@ -4,9 +4,10 @@ package kuma.mesh.v1alpha1; option go_package = "v1alpha1"; +import "mesh/v1alpha1/selector.proto"; + message TrafficPermission { message Rule { - message Selector { map match = 1; } repeated Selector sources = 1; repeated Selector destinations = 2; diff --git a/app/kumactl/cmd/get/get.go b/app/kumactl/cmd/get/get.go index 437e24886728..786d7183b429 100644 --- a/app/kumactl/cmd/get/get.go +++ b/app/kumactl/cmd/get/get.go @@ -29,5 +29,6 @@ func NewGetCmd(pctx *kumactl_cmd.RootContext) *cobra.Command { cmd.AddCommand(newGetDataplanesCmd(ctx)) cmd.AddCommand(newGetProxyTemplatesCmd(ctx)) cmd.AddCommand(newGetTrafficPermissionsCmd(ctx)) + cmd.AddCommand(newGetTrafficLogsCmd(ctx)) return cmd } diff --git a/app/kumactl/cmd/get/get_traffic_logs.go b/app/kumactl/cmd/get/get_traffic_logs.go new file mode 100644 index 000000000000..62dfddad4815 --- /dev/null +++ b/app/kumactl/cmd/get/get_traffic_logs.go @@ -0,0 +1,67 @@ +package get + +import ( + "context" + "io" + + "github.com/Kong/kuma/app/kumactl/pkg/output" + "github.com/Kong/kuma/app/kumactl/pkg/output/printers" + "github.com/Kong/kuma/pkg/core/resources/apis/mesh" + rest_types "github.com/Kong/kuma/pkg/core/resources/model/rest" + core_store "github.com/Kong/kuma/pkg/core/resources/store" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func newGetTrafficLogsCmd(pctx *getContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "traffic-logs", + Short: "Show TrafficLogs", + Long: `Show TrafficLog entities.`, + RunE: func(cmd *cobra.Command, _ []string) error { + rs, err := pctx.CurrentResourceStore() + if err != nil { + return err + } + + trafficLogging := mesh.TrafficLogResourceList{} + if err := rs.List(context.Background(), &trafficLogging, core_store.ListByMesh(pctx.CurrentMesh())); err != nil { + return errors.Wrapf(err, "failed to list TrafficLog") + } + + switch format := output.Format(pctx.args.outputFormat); format { + case output.TableFormat: + return printTrafficLog(&trafficLogging, cmd.OutOrStdout()) + default: + printer, err := printers.NewGenericPrinter(format) + if err != nil { + return err + } + return printer.Print(rest_types.From.ResourceList(&trafficLogging), cmd.OutOrStdout()) + } + }, + } + return cmd +} + +func printTrafficLog(trafficLogging *mesh.TrafficLogResourceList, out io.Writer) error { + data := printers.Table{ + Headers: []string{"MESH", "NAME"}, + NextRow: func() func() []string { + i := 0 + return func() []string { + defer func() { i++ }() + if len(trafficLogging.Items) <= i { + return nil + } + trafficLogging := trafficLogging.Items[i] + + return []string{ + trafficLogging.GetMeta().GetMesh(), // MESH + trafficLogging.GetMeta().GetName(), // NAME + } + } + }(), + } + return printers.NewTablePrinter().Print(data, out) +} diff --git a/app/kumactl/cmd/get/get_traffic_logs_test.go b/app/kumactl/cmd/get/get_traffic_logs_test.go new file mode 100644 index 000000000000..20ad097d35c5 --- /dev/null +++ b/app/kumactl/cmd/get/get_traffic_logs_test.go @@ -0,0 +1,178 @@ +package get_test + +import ( + "bytes" + "context" + "io/ioutil" + "path/filepath" + "strings" + "time" + + "github.com/Kong/kuma/api/mesh/v1alpha1" + "github.com/Kong/kuma/app/kumactl/cmd" + kumactl_cmd "github.com/Kong/kuma/app/kumactl/pkg/cmd" + config_proto "github.com/Kong/kuma/pkg/config/app/kumactl/v1alpha1" + "github.com/Kong/kuma/pkg/core/resources/apis/mesh" + core_model "github.com/Kong/kuma/pkg/core/resources/model" + core_store "github.com/Kong/kuma/pkg/core/resources/store" + memory_resources "github.com/Kong/kuma/pkg/plugins/resources/memory" + test_model "github.com/Kong/kuma/pkg/test/resources/model" + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + gomega_types "github.com/onsi/gomega/types" + "github.com/spf13/cobra" +) + +var _ = Describe("kumactl get traffic-logs", func() { + + trafficLoggingResources := []*mesh.TrafficLogResource{ + { + Spec: v1alpha1.TrafficLog{ + Rules: []*v1alpha1.TrafficLog_Rule{ + { + Sources: []*v1alpha1.Selector{ + { + Match: map[string]string{ + "service": "web1", + "version": "1.0", + }, + }, + }, + Destinations: []*v1alpha1.Selector{ + { + Match: map[string]string{ + "service": "backend1", + "env": "dev", + }, + }, + }, + Conf: &v1alpha1.TrafficLog_Rule_Conf{ + Backend: "file", + }, + }, + }, + }, + Meta: &test_model.ResourceMeta{ + Mesh: "default", + Name: "web1-to-backend1", + Namespace: "", + }, + }, + { + Spec: v1alpha1.TrafficLog{ + Rules: []*v1alpha1.TrafficLog_Rule{ + { + Sources: []*v1alpha1.Selector{ + { + Match: map[string]string{ + "service": "web2", + "version": "1.0", + }, + }, + }, + Destinations: []*v1alpha1.Selector{ + { + Match: map[string]string{ + "service": "backend2", + "env": "dev", + }, + }, + }, + Conf: &v1alpha1.TrafficLog_Rule_Conf{ + Backend: "logstash", + }, + }, + }, + }, + Meta: &test_model.ResourceMeta{ + Mesh: "default", + Name: "web2-to-backend2", + Namespace: "", + }, + }, + } + + Describe("GetTrafficLogCmd", func() { + + var rootCtx *kumactl_cmd.RootContext + var rootCmd *cobra.Command + var buf *bytes.Buffer + var store core_store.ResourceStore + + BeforeEach(func() { + // setup + rootCtx = &kumactl_cmd.RootContext{ + Runtime: kumactl_cmd.RootRuntime{ + Now: func() time.Time { return time.Now() }, + NewResourceStore: func(*config_proto.ControlPlaneCoordinates_ApiServer) (core_store.ResourceStore, error) { + return store, nil + }, + }, + } + + store = memory_resources.NewStore() + + for _, ds := range trafficLoggingResources { + err := store.Create(context.Background(), ds, core_store.CreateBy(core_model.MetaToResourceKey(ds.GetMeta()))) + Expect(err).ToNot(HaveOccurred()) + } + + rootCmd = cmd.NewRootCmd(rootCtx) + buf = &bytes.Buffer{} + rootCmd.SetOut(buf) + }) + + type testCase struct { + outputFormat string + goldenFile string + matcher func(interface{}) gomega_types.GomegaMatcher + } + + DescribeTable("kumactl get traffic-logs -o table|json|yaml", + func(given testCase) { + // given + rootCmd.SetArgs(append([]string{ + "--config-file", filepath.Join("..", "testdata", "sample-kumactl.config.yaml"), + "get", "traffic-logs"}, given.outputFormat)) + + // when + err := rootCmd.Execute() + // then + Expect(err).ToNot(HaveOccurred()) + + // when + expected, err := ioutil.ReadFile(filepath.Join("testdata", given.goldenFile)) + // then + Expect(err).ToNot(HaveOccurred()) + // and + Expect(buf.String()).To(given.matcher(expected)) + }, + Entry("should support Table output by default", testCase{ + outputFormat: "", + goldenFile: "get-traffic-logs.golden.txt", + matcher: func(expected interface{}) gomega_types.GomegaMatcher { + return WithTransform(strings.TrimSpace, Equal(strings.TrimSpace(string(expected.([]byte))))) + }, + }), + Entry("should support Table output explicitly", testCase{ + outputFormat: "-otable", + goldenFile: "get-traffic-logs.golden.txt", + matcher: func(expected interface{}) gomega_types.GomegaMatcher { + return WithTransform(strings.TrimSpace, Equal(strings.TrimSpace(string(expected.([]byte))))) + }, + }), + Entry("should support JSON output", testCase{ + outputFormat: "-ojson", + goldenFile: "get-traffic-logs.golden.json", + matcher: MatchJSON, + }), + Entry("should support YAML output", testCase{ + outputFormat: "-oyaml", + goldenFile: "get-traffic-logs.golden.yaml", + matcher: MatchYAML, + }), + ) + }) + +}) diff --git a/app/kumactl/cmd/get/get_trafficpermissions_test.go b/app/kumactl/cmd/get/get_trafficpermissions_test.go index 123dd64e7ff5..697e419428a9 100644 --- a/app/kumactl/cmd/get/get_trafficpermissions_test.go +++ b/app/kumactl/cmd/get/get_trafficpermissions_test.go @@ -31,7 +31,7 @@ var _ = Describe("kumactl get traffic-permissions", func() { Spec: v1alpha1.TrafficPermission{ Rules: []*v1alpha1.TrafficPermission_Rule{ { - Sources: []*v1alpha1.TrafficPermission_Rule_Selector{ + Sources: []*v1alpha1.Selector{ { Match: map[string]string{ "service": "web1", @@ -39,7 +39,7 @@ var _ = Describe("kumactl get traffic-permissions", func() { }, }, }, - Destinations: []*v1alpha1.TrafficPermission_Rule_Selector{ + Destinations: []*v1alpha1.Selector{ { Match: map[string]string{ "service": "backend1", @@ -60,7 +60,7 @@ var _ = Describe("kumactl get traffic-permissions", func() { Spec: v1alpha1.TrafficPermission{ Rules: []*v1alpha1.TrafficPermission_Rule{ { - Sources: []*v1alpha1.TrafficPermission_Rule_Selector{ + Sources: []*v1alpha1.Selector{ { Match: map[string]string{ "service": "web2", @@ -68,7 +68,7 @@ var _ = Describe("kumactl get traffic-permissions", func() { }, }, }, - Destinations: []*v1alpha1.TrafficPermission_Rule_Selector{ + Destinations: []*v1alpha1.Selector{ { Match: map[string]string{ "service": "backend2", diff --git a/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.json b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.json new file mode 100644 index 000000000000..0b75205d8089 --- /dev/null +++ b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.json @@ -0,0 +1,60 @@ +{ + "items": [ + { + "mesh": "default", + "name": "web1-to-backend1", + "rules": [ + { + "sources": [ + { + "match": { + "service": "web1", + "version": "1.0" + } + } + ], + "destinations": [ + { + "match": { + "service": "backend1", + "env": "dev" + } + } + ], + "conf": { + "backend": "file" + } + } + ], + "type": "TrafficLog" + }, + { + "mesh": "default", + "name": "web2-to-backend2", + "rules": [ + { + "sources": [ + { + "match": { + "service": "web2", + "version": "1.0" + } + } + ], + "destinations": [ + { + "match": { + "service": "backend2", + "env": "dev" + } + } + ], + "conf": { + "backend": "logstash" + } + } + ], + "type": "TrafficLog" + } + ] +} diff --git a/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.txt b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.txt new file mode 100644 index 000000000000..5291a25da97c --- /dev/null +++ b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.txt @@ -0,0 +1,3 @@ +MESH NAME +default web1-to-backend1 +default web2-to-backend2 diff --git a/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.yaml b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.yaml new file mode 100644 index 000000000000..a9e87732139a --- /dev/null +++ b/app/kumactl/cmd/get/testdata/get-traffic-logs.golden.yaml @@ -0,0 +1,29 @@ +items: + - mesh: default + name: web1-to-backend1 + rules: + - destinations: + - match: + env: dev + service: backend1 + sources: + - match: + service: web1 + version: "1.0" + conf: + backend: file + type: TrafficLog + - mesh: default + name: web2-to-backend2 + rules: + - destinations: + - match: + env: dev + service: backend2 + sources: + - match: + service: web2 + version: "1.0" + conf: + backend: logstash + type: TrafficLog diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml index 4e653e825cfe..b437b3c38455 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml @@ -1626,6 +1626,395 @@ status: --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: trafficlogs.kuma.io +spec: + group: kuma.io + names: + kind: TrafficLog + plural: trafficlogs + scope: "" + validation: + openAPIV3Schema: + description: TrafficLog is the Schema for the trafficlogs API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored with + a resource that may be set by external tools to store and retrieve + arbitrary metadata. They are not queryable and should be preserved + when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + clusterName: + description: The name of the cluster which the object belongs to. This + is used to distinguish resources with same name and namespace in different + clusters. This field is not set anywhere right now and apiserver is + going to ignore it if set in create or update request. + type: string + creationTimestamp: + description: "CreationTimestamp is a timestamp representing the server + time when this object was created. It is not guaranteed to be set + in happens-before order across separate operations. Clients may not + set this value. It is represented in RFC3339 form and is in UTC. \n + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + deletionGracePeriodSeconds: + description: Number of seconds allowed for this object to gracefully + terminate before it will be removed from the system. Only set when + deletionTimestamp is also set. May only be shortened. Read-only. + format: int64 + type: integer + deletionTimestamp: + description: "DeletionTimestamp is RFC 3339 date and time at which this + resource will be deleted. This field is set by the server when a graceful + deletion is requested by the user, and is not directly settable by + a client. The resource is expected to be deleted (no longer visible + from resource lists, and not reachable by name) after the time in + this field, once the finalizers list is empty. As long as the finalizers + list contains items, deletion is blocked. Once the deletionTimestamp + is set, this value may not be unset or be set further into the future, + although it may be shortened or the resource may be deleted prior + to this time. For example, a user may request that a pod is deleted + in 30 seconds. The Kubelet will react by sending a graceful termination + signal to the containers in the pod. After that 30 seconds, the Kubelet + will send a hard termination signal (SIGKILL) to the container and + after cleanup, remove the pod from the API. In the presence of network + partitions, this object may still exist after this timestamp, until + an administrator or automated process can determine the resource is + fully terminated. If not set, graceful deletion of the object has + not been requested. \n Populated by the system when a graceful deletion + is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + finalizers: + description: Must be empty before the object is deleted from the registry. + Each entry is an identifier for the responsible component that will + remove the entry from the list. If the deletionTimestamp of the object + is non-nil, entries in this list can only be removed. + items: + type: string + type: array + generateName: + description: "GenerateName is an optional prefix, used by the server, + to generate a unique name ONLY IF the Name field has not been provided. + If this field is used, the name returned to the client will be different + than the name passed. This value will also be combined with a unique + suffix. The provided value has the same validation rules as the Name + field, and may be truncated by the length of the suffix required to + make the value unique on the server. \n If this field is specified + and the generated name exists, the server will NOT return a 409 - + instead, it will either return 201 Created or 500 with Reason ServerTimeout + indicating a unique name could not be found in the time allotted, + and the client should retry (optionally after the time indicated in + the Retry-After header). \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + type: string + generation: + description: A sequence number representing a specific generation of + the desired state. Populated by the system. Read-only. + format: int64 + type: integer + initializers: + description: "An initializer is a controller which enforces some system + invariant at object creation time. This field is a list of initializers + that have not yet acted on this object. If nil or empty, this object + has been completely initialized. Otherwise, the object is considered + uninitialized and is hidden (in list/watch and get calls) from clients + that haven't explicitly asked to observe uninitialized objects. \n + When an object is created, the system will populate this list with + the current set of initializers. Only privileged users may set or + modify this list. Once it is empty, it may not be modified further + by any user. \n DEPRECATED - initializers are an alpha field and will + be removed in v1.15." + properties: + pending: + description: Pending is a list of initializers that must execute + in order before this object is visible. When the last pending + initializer is removed, and no failing result is set, the initializers + struct will be set to nil and the object is considered as initialized + and visible to all clients. + items: + properties: + name: + description: name of the process that is responsible for initializing + this object. + type: string + required: + - name + type: object + type: array + result: + description: If result is set with the Failure field, the object + will be persisted to storage and then deleted, ensuring that other + clients can observe the deletion. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + code: + description: Suggested HTTP return code for this status, 0 if + not set. + format: int32 + type: integer + details: + description: Extended data associated with the reason. Each + reason may define its own extended details. This field is + optional and the data returned is not guaranteed to conform + to any schema except that defined by the reason type. + properties: + causes: + description: The Causes array includes more details associated + with the StatusReason failure. Not all StatusReasons may + provide detailed causes. + items: + properties: + field: + description: "The field of the resource that has caused + this error, as named by its JSON serialization. + May include dot and postfix notation for nested + attributes. Arrays are zero-indexed. Fields may + appear more than once in an array of causes due + to fields having multiple errors. Optional. \n Examples: + \ \"name\" - the field \"name\" on the current + resource \"items[0].name\" - the field \"name\" + on the first array entry in \"items\"" + type: string + message: + description: A human-readable description of the cause + of the error. This field may be presented as-is + to a reader. + type: string + reason: + description: A machine-readable description of the + cause of the error. If this value is empty there + is no information available. + type: string + type: object + type: array + group: + description: The group attribute of the resource associated + with the status StatusReason. + type: string + kind: + description: 'The kind attribute of the resource associated + with the status StatusReason. On some operations may differ + from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: The name attribute of the resource associated + with the status StatusReason (when there is a single name + which can be described). + type: string + retryAfterSeconds: + description: If specified, the time in seconds before the + operation should be retried. Some errors may indicate + the client must take an alternate action - for those errors + this field may indicate how long to wait before taking + the alternate action. + format: int32 + type: integer + uid: + description: 'UID of the resource. (when there is a single + resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + type: object + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + message: + description: A human-readable description of the status of this + operation. + type: string + metadata: + description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + properties: + continue: + description: continue may be set if the user set a limit + on the number of items returned, and indicates that the + server has more data available. The value is opaque and + may be used to issue another request to the endpoint that + served this list to retrieve the next set of available + objects. Continuing a consistent list may not be possible + if the server configuration has changed or more than a + few minutes have passed. The resourceVersion field returned + when using this continue value will be identical to the + value in the first response, unless you have received + this token from an error message. + type: string + resourceVersion: + description: 'String that identifies the server''s internal + version of this object that can be used by clients to + determine when objects have changed. Value must be treated + as opaque by clients and passed unmodified back to the + server. Populated by the system. Read-only. More info: + https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' + type: string + selfLink: + description: selfLink is a URL representing this object. + Populated by the system. Read-only. + type: string + type: object + reason: + description: A machine-readable description of why this operation + is in the "Failure" status. If this value is empty there is + no information available. A Reason clarifies an HTTP status + code but does not override it. + type: string + type: object + required: + - pending + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used to organize + and categorize (scope and select) objects. May match selectors of + replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + managedFields: + description: "ManagedFields maps workflow-id and version to the set + of fields that are managed by that workflow. This is mostly for internal + housekeeping, and users typically shouldn't need to set or understand + this field. A workflow can be the user's name, a controller's name, + or the name of a specific apply path like \"ci-cd\". The set of fields + is always in the version that the workflow used when modifying the + object. \n This field is alpha and can be changed or removed without + notice." + items: + properties: + apiVersion: + description: APIVersion defines the version of this resource that + this field set applies to. The format is "group/version" just + like the top-level APIVersion field. It is necessary to track + the version of a field set because it cannot be automatically + converted. + type: string + fields: + additionalProperties: true + description: Fields identifies a set of fields. + type: object + manager: + description: Manager is an identifier of the workflow managing + these fields. + type: string + operation: + description: Operation is the type of operation which lead to + this ManagedFieldsEntry being created. The only valid values + for this field are 'Apply' and 'Update'. + type: string + time: + description: Time is timestamp of when these fields were set. + It should always be empty if Operation is 'Apply' + format: date-time + type: string + type: object + type: array + name: + description: 'Name must be unique within a namespace. Is required when + creating resources, although some resources may allow a client to + request the generation of an appropriate name automatically. Name + is primarily intended for creation idempotence and configuration definition. + Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + namespace: + description: "Namespace defines the space within each name must be unique. + An empty namespace is equivalent to the \"default\" namespace, but + \"default\" is the canonical representation. Not all objects are required + to be scoped to a namespace - the value of this field for those objects + will be empty. \n Must be a DNS_LABEL. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/namespaces" + type: string + ownerReferences: + description: List of objects depended by this object. If ALL objects + in the list have been deleted, this object will be garbage collected. + If this object is managed by a controller, then an entry in this list + will point to this controller, with the controller field set to true. + There cannot be more than one managing controller. + items: + properties: + apiVersion: + description: API version of the referent. + type: string + blockOwnerDeletion: + description: If true, AND if the owner has the "foregroundDeletion" + finalizer, then the owner cannot be deleted from the key-value + store until this reference is removed. Defaults to false. To + set this field, a user needs "delete" permission of the owner, + otherwise 422 (Unprocessable Entity) will be returned. + type: boolean + controller: + description: If true, this reference points to the managing controller. + type: boolean + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + uid: + description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + required: + - apiVersion + - kind + - name + - uid + type: object + type: array + resourceVersion: + description: "An opaque value that represents the internal version of + this object that can be used by clients to determine when objects + have changed. May be used for optimistic concurrency, change detection, + and the watch operation on a resource or set of resources. Clients + must treat these values as opaque and passed unmodified back to the + server. They may only be valid for a particular resource or set of + resources. \n Populated by the system. Read-only. Value must be treated + as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + type: string + selfLink: + description: SelfLink is a URL representing this object. Populated by + the system. Read-only. + type: string + uid: + description: "UID is the unique in time and space value for this object. + It is typically generated by the server on successful creation of + a resource and is not allowed to change on PUT operations. \n Populated + by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + type: string + type: object + mesh: + type: string + spec: + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: creationTimestamp: null name: trafficpermissions.kuma.io @@ -2069,6 +2458,14 @@ rules: - get - list - watch +- apiGroups: + - kuma.io + resources: + - trafficlogs + verbs: + - get + - list + - watch # validate k8s token before issueing mTLS cert - apiGroups: - authentication.k8s.io diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml index e6419e1b6619..af265efa222f 100644 --- a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml +++ b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml @@ -1626,6 +1626,395 @@ status: --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: trafficlogs.kuma.io +spec: + group: kuma.io + names: + kind: TrafficLog + plural: trafficlogs + scope: "" + validation: + openAPIV3Schema: + description: TrafficLog is the Schema for the trafficlogs API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored with + a resource that may be set by external tools to store and retrieve + arbitrary metadata. They are not queryable and should be preserved + when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + clusterName: + description: The name of the cluster which the object belongs to. This + is used to distinguish resources with same name and namespace in different + clusters. This field is not set anywhere right now and apiserver is + going to ignore it if set in create or update request. + type: string + creationTimestamp: + description: "CreationTimestamp is a timestamp representing the server + time when this object was created. It is not guaranteed to be set + in happens-before order across separate operations. Clients may not + set this value. It is represented in RFC3339 form and is in UTC. \n + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + deletionGracePeriodSeconds: + description: Number of seconds allowed for this object to gracefully + terminate before it will be removed from the system. Only set when + deletionTimestamp is also set. May only be shortened. Read-only. + format: int64 + type: integer + deletionTimestamp: + description: "DeletionTimestamp is RFC 3339 date and time at which this + resource will be deleted. This field is set by the server when a graceful + deletion is requested by the user, and is not directly settable by + a client. The resource is expected to be deleted (no longer visible + from resource lists, and not reachable by name) after the time in + this field, once the finalizers list is empty. As long as the finalizers + list contains items, deletion is blocked. Once the deletionTimestamp + is set, this value may not be unset or be set further into the future, + although it may be shortened or the resource may be deleted prior + to this time. For example, a user may request that a pod is deleted + in 30 seconds. The Kubelet will react by sending a graceful termination + signal to the containers in the pod. After that 30 seconds, the Kubelet + will send a hard termination signal (SIGKILL) to the container and + after cleanup, remove the pod from the API. In the presence of network + partitions, this object may still exist after this timestamp, until + an administrator or automated process can determine the resource is + fully terminated. If not set, graceful deletion of the object has + not been requested. \n Populated by the system when a graceful deletion + is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + finalizers: + description: Must be empty before the object is deleted from the registry. + Each entry is an identifier for the responsible component that will + remove the entry from the list. If the deletionTimestamp of the object + is non-nil, entries in this list can only be removed. + items: + type: string + type: array + generateName: + description: "GenerateName is an optional prefix, used by the server, + to generate a unique name ONLY IF the Name field has not been provided. + If this field is used, the name returned to the client will be different + than the name passed. This value will also be combined with a unique + suffix. The provided value has the same validation rules as the Name + field, and may be truncated by the length of the suffix required to + make the value unique on the server. \n If this field is specified + and the generated name exists, the server will NOT return a 409 - + instead, it will either return 201 Created or 500 with Reason ServerTimeout + indicating a unique name could not be found in the time allotted, + and the client should retry (optionally after the time indicated in + the Retry-After header). \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + type: string + generation: + description: A sequence number representing a specific generation of + the desired state. Populated by the system. Read-only. + format: int64 + type: integer + initializers: + description: "An initializer is a controller which enforces some system + invariant at object creation time. This field is a list of initializers + that have not yet acted on this object. If nil or empty, this object + has been completely initialized. Otherwise, the object is considered + uninitialized and is hidden (in list/watch and get calls) from clients + that haven't explicitly asked to observe uninitialized objects. \n + When an object is created, the system will populate this list with + the current set of initializers. Only privileged users may set or + modify this list. Once it is empty, it may not be modified further + by any user. \n DEPRECATED - initializers are an alpha field and will + be removed in v1.15." + properties: + pending: + description: Pending is a list of initializers that must execute + in order before this object is visible. When the last pending + initializer is removed, and no failing result is set, the initializers + struct will be set to nil and the object is considered as initialized + and visible to all clients. + items: + properties: + name: + description: name of the process that is responsible for initializing + this object. + type: string + required: + - name + type: object + type: array + result: + description: If result is set with the Failure field, the object + will be persisted to storage and then deleted, ensuring that other + clients can observe the deletion. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + code: + description: Suggested HTTP return code for this status, 0 if + not set. + format: int32 + type: integer + details: + description: Extended data associated with the reason. Each + reason may define its own extended details. This field is + optional and the data returned is not guaranteed to conform + to any schema except that defined by the reason type. + properties: + causes: + description: The Causes array includes more details associated + with the StatusReason failure. Not all StatusReasons may + provide detailed causes. + items: + properties: + field: + description: "The field of the resource that has caused + this error, as named by its JSON serialization. + May include dot and postfix notation for nested + attributes. Arrays are zero-indexed. Fields may + appear more than once in an array of causes due + to fields having multiple errors. Optional. \n Examples: + \ \"name\" - the field \"name\" on the current + resource \"items[0].name\" - the field \"name\" + on the first array entry in \"items\"" + type: string + message: + description: A human-readable description of the cause + of the error. This field may be presented as-is + to a reader. + type: string + reason: + description: A machine-readable description of the + cause of the error. If this value is empty there + is no information available. + type: string + type: object + type: array + group: + description: The group attribute of the resource associated + with the status StatusReason. + type: string + kind: + description: 'The kind attribute of the resource associated + with the status StatusReason. On some operations may differ + from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: The name attribute of the resource associated + with the status StatusReason (when there is a single name + which can be described). + type: string + retryAfterSeconds: + description: If specified, the time in seconds before the + operation should be retried. Some errors may indicate + the client must take an alternate action - for those errors + this field may indicate how long to wait before taking + the alternate action. + format: int32 + type: integer + uid: + description: 'UID of the resource. (when there is a single + resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + type: object + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + message: + description: A human-readable description of the status of this + operation. + type: string + metadata: + description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + properties: + continue: + description: continue may be set if the user set a limit + on the number of items returned, and indicates that the + server has more data available. The value is opaque and + may be used to issue another request to the endpoint that + served this list to retrieve the next set of available + objects. Continuing a consistent list may not be possible + if the server configuration has changed or more than a + few minutes have passed. The resourceVersion field returned + when using this continue value will be identical to the + value in the first response, unless you have received + this token from an error message. + type: string + resourceVersion: + description: 'String that identifies the server''s internal + version of this object that can be used by clients to + determine when objects have changed. Value must be treated + as opaque by clients and passed unmodified back to the + server. Populated by the system. Read-only. More info: + https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' + type: string + selfLink: + description: selfLink is a URL representing this object. + Populated by the system. Read-only. + type: string + type: object + reason: + description: A machine-readable description of why this operation + is in the "Failure" status. If this value is empty there is + no information available. A Reason clarifies an HTTP status + code but does not override it. + type: string + type: object + required: + - pending + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used to organize + and categorize (scope and select) objects. May match selectors of + replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + managedFields: + description: "ManagedFields maps workflow-id and version to the set + of fields that are managed by that workflow. This is mostly for internal + housekeeping, and users typically shouldn't need to set or understand + this field. A workflow can be the user's name, a controller's name, + or the name of a specific apply path like \"ci-cd\". The set of fields + is always in the version that the workflow used when modifying the + object. \n This field is alpha and can be changed or removed without + notice." + items: + properties: + apiVersion: + description: APIVersion defines the version of this resource that + this field set applies to. The format is "group/version" just + like the top-level APIVersion field. It is necessary to track + the version of a field set because it cannot be automatically + converted. + type: string + fields: + additionalProperties: true + description: Fields identifies a set of fields. + type: object + manager: + description: Manager is an identifier of the workflow managing + these fields. + type: string + operation: + description: Operation is the type of operation which lead to + this ManagedFieldsEntry being created. The only valid values + for this field are 'Apply' and 'Update'. + type: string + time: + description: Time is timestamp of when these fields were set. + It should always be empty if Operation is 'Apply' + format: date-time + type: string + type: object + type: array + name: + description: 'Name must be unique within a namespace. Is required when + creating resources, although some resources may allow a client to + request the generation of an appropriate name automatically. Name + is primarily intended for creation idempotence and configuration definition. + Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + namespace: + description: "Namespace defines the space within each name must be unique. + An empty namespace is equivalent to the \"default\" namespace, but + \"default\" is the canonical representation. Not all objects are required + to be scoped to a namespace - the value of this field for those objects + will be empty. \n Must be a DNS_LABEL. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/namespaces" + type: string + ownerReferences: + description: List of objects depended by this object. If ALL objects + in the list have been deleted, this object will be garbage collected. + If this object is managed by a controller, then an entry in this list + will point to this controller, with the controller field set to true. + There cannot be more than one managing controller. + items: + properties: + apiVersion: + description: API version of the referent. + type: string + blockOwnerDeletion: + description: If true, AND if the owner has the "foregroundDeletion" + finalizer, then the owner cannot be deleted from the key-value + store until this reference is removed. Defaults to false. To + set this field, a user needs "delete" permission of the owner, + otherwise 422 (Unprocessable Entity) will be returned. + type: boolean + controller: + description: If true, this reference points to the managing controller. + type: boolean + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + uid: + description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + required: + - apiVersion + - kind + - name + - uid + type: object + type: array + resourceVersion: + description: "An opaque value that represents the internal version of + this object that can be used by clients to determine when objects + have changed. May be used for optimistic concurrency, change detection, + and the watch operation on a resource or set of resources. Clients + must treat these values as opaque and passed unmodified back to the + server. They may only be valid for a particular resource or set of + resources. \n Populated by the system. Read-only. Value must be treated + as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + type: string + selfLink: + description: SelfLink is a URL representing this object. Populated by + the system. Read-only. + type: string + uid: + description: "UID is the unique in time and space value for this object. + It is typically generated by the server on successful creation of + a resource and is not allowed to change on PUT operations. \n Populated + by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + type: string + type: object + mesh: + type: string + spec: + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: creationTimestamp: null name: trafficpermissions.kuma.io @@ -2069,6 +2458,14 @@ rules: - get - list - watch +- apiGroups: + - kuma.io + resources: + - trafficlogs + verbs: + - get + - list + - watch # validate k8s token before issueing mTLS cert - apiGroups: - authentication.k8s.io diff --git a/app/kumactl/data/install/k8s/control-plane/crds/kuma.io_trafficlogs.yaml b/app/kumactl/data/install/k8s/control-plane/crds/kuma.io_trafficlogs.yaml new file mode 100644 index 000000000000..be51941d7cf0 --- /dev/null +++ b/app/kumactl/data/install/k8s/control-plane/crds/kuma.io_trafficlogs.yaml @@ -0,0 +1,390 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: trafficlogs.kuma.io +spec: + group: kuma.io + names: + kind: TrafficLog + plural: trafficlogs + scope: "" + validation: + openAPIV3Schema: + description: TrafficLog is the Schema for the trafficlogs API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored with + a resource that may be set by external tools to store and retrieve + arbitrary metadata. They are not queryable and should be preserved + when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + clusterName: + description: The name of the cluster which the object belongs to. This + is used to distinguish resources with same name and namespace in different + clusters. This field is not set anywhere right now and apiserver is + going to ignore it if set in create or update request. + type: string + creationTimestamp: + description: "CreationTimestamp is a timestamp representing the server + time when this object was created. It is not guaranteed to be set + in happens-before order across separate operations. Clients may not + set this value. It is represented in RFC3339 form and is in UTC. \n + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + deletionGracePeriodSeconds: + description: Number of seconds allowed for this object to gracefully + terminate before it will be removed from the system. Only set when + deletionTimestamp is also set. May only be shortened. Read-only. + format: int64 + type: integer + deletionTimestamp: + description: "DeletionTimestamp is RFC 3339 date and time at which this + resource will be deleted. This field is set by the server when a graceful + deletion is requested by the user, and is not directly settable by + a client. The resource is expected to be deleted (no longer visible + from resource lists, and not reachable by name) after the time in + this field, once the finalizers list is empty. As long as the finalizers + list contains items, deletion is blocked. Once the deletionTimestamp + is set, this value may not be unset or be set further into the future, + although it may be shortened or the resource may be deleted prior + to this time. For example, a user may request that a pod is deleted + in 30 seconds. The Kubelet will react by sending a graceful termination + signal to the containers in the pod. After that 30 seconds, the Kubelet + will send a hard termination signal (SIGKILL) to the container and + after cleanup, remove the pod from the API. In the presence of network + partitions, this object may still exist after this timestamp, until + an administrator or automated process can determine the resource is + fully terminated. If not set, graceful deletion of the object has + not been requested. \n Populated by the system when a graceful deletion + is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + finalizers: + description: Must be empty before the object is deleted from the registry. + Each entry is an identifier for the responsible component that will + remove the entry from the list. If the deletionTimestamp of the object + is non-nil, entries in this list can only be removed. + items: + type: string + type: array + generateName: + description: "GenerateName is an optional prefix, used by the server, + to generate a unique name ONLY IF the Name field has not been provided. + If this field is used, the name returned to the client will be different + than the name passed. This value will also be combined with a unique + suffix. The provided value has the same validation rules as the Name + field, and may be truncated by the length of the suffix required to + make the value unique on the server. \n If this field is specified + and the generated name exists, the server will NOT return a 409 - + instead, it will either return 201 Created or 500 with Reason ServerTimeout + indicating a unique name could not be found in the time allotted, + and the client should retry (optionally after the time indicated in + the Retry-After header). \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + type: string + generation: + description: A sequence number representing a specific generation of + the desired state. Populated by the system. Read-only. + format: int64 + type: integer + initializers: + description: "An initializer is a controller which enforces some system + invariant at object creation time. This field is a list of initializers + that have not yet acted on this object. If nil or empty, this object + has been completely initialized. Otherwise, the object is considered + uninitialized and is hidden (in list/watch and get calls) from clients + that haven't explicitly asked to observe uninitialized objects. \n + When an object is created, the system will populate this list with + the current set of initializers. Only privileged users may set or + modify this list. Once it is empty, it may not be modified further + by any user. \n DEPRECATED - initializers are an alpha field and will + be removed in v1.15." + properties: + pending: + description: Pending is a list of initializers that must execute + in order before this object is visible. When the last pending + initializer is removed, and no failing result is set, the initializers + struct will be set to nil and the object is considered as initialized + and visible to all clients. + items: + properties: + name: + description: name of the process that is responsible for initializing + this object. + type: string + required: + - name + type: object + type: array + result: + description: If result is set with the Failure field, the object + will be persisted to storage and then deleted, ensuring that other + clients can observe the deletion. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + code: + description: Suggested HTTP return code for this status, 0 if + not set. + format: int32 + type: integer + details: + description: Extended data associated with the reason. Each + reason may define its own extended details. This field is + optional and the data returned is not guaranteed to conform + to any schema except that defined by the reason type. + properties: + causes: + description: The Causes array includes more details associated + with the StatusReason failure. Not all StatusReasons may + provide detailed causes. + items: + properties: + field: + description: "The field of the resource that has caused + this error, as named by its JSON serialization. + May include dot and postfix notation for nested + attributes. Arrays are zero-indexed. Fields may + appear more than once in an array of causes due + to fields having multiple errors. Optional. \n Examples: + \ \"name\" - the field \"name\" on the current + resource \"items[0].name\" - the field \"name\" + on the first array entry in \"items\"" + type: string + message: + description: A human-readable description of the cause + of the error. This field may be presented as-is + to a reader. + type: string + reason: + description: A machine-readable description of the + cause of the error. If this value is empty there + is no information available. + type: string + type: object + type: array + group: + description: The group attribute of the resource associated + with the status StatusReason. + type: string + kind: + description: 'The kind attribute of the resource associated + with the status StatusReason. On some operations may differ + from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: The name attribute of the resource associated + with the status StatusReason (when there is a single name + which can be described). + type: string + retryAfterSeconds: + description: If specified, the time in seconds before the + operation should be retried. Some errors may indicate + the client must take an alternate action - for those errors + this field may indicate how long to wait before taking + the alternate action. + format: int32 + type: integer + uid: + description: 'UID of the resource. (when there is a single + resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + type: object + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + message: + description: A human-readable description of the status of this + operation. + type: string + metadata: + description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + properties: + continue: + description: continue may be set if the user set a limit + on the number of items returned, and indicates that the + server has more data available. The value is opaque and + may be used to issue another request to the endpoint that + served this list to retrieve the next set of available + objects. Continuing a consistent list may not be possible + if the server configuration has changed or more than a + few minutes have passed. The resourceVersion field returned + when using this continue value will be identical to the + value in the first response, unless you have received + this token from an error message. + type: string + resourceVersion: + description: 'String that identifies the server''s internal + version of this object that can be used by clients to + determine when objects have changed. Value must be treated + as opaque by clients and passed unmodified back to the + server. Populated by the system. Read-only. More info: + https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' + type: string + selfLink: + description: selfLink is a URL representing this object. + Populated by the system. Read-only. + type: string + type: object + reason: + description: A machine-readable description of why this operation + is in the "Failure" status. If this value is empty there is + no information available. A Reason clarifies an HTTP status + code but does not override it. + type: string + type: object + required: + - pending + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used to organize + and categorize (scope and select) objects. May match selectors of + replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + managedFields: + description: "ManagedFields maps workflow-id and version to the set + of fields that are managed by that workflow. This is mostly for internal + housekeeping, and users typically shouldn't need to set or understand + this field. A workflow can be the user's name, a controller's name, + or the name of a specific apply path like \"ci-cd\". The set of fields + is always in the version that the workflow used when modifying the + object. \n This field is alpha and can be changed or removed without + notice." + items: + properties: + apiVersion: + description: APIVersion defines the version of this resource that + this field set applies to. The format is "group/version" just + like the top-level APIVersion field. It is necessary to track + the version of a field set because it cannot be automatically + converted. + type: string + fields: + additionalProperties: true + description: Fields identifies a set of fields. + type: object + manager: + description: Manager is an identifier of the workflow managing + these fields. + type: string + operation: + description: Operation is the type of operation which lead to + this ManagedFieldsEntry being created. The only valid values + for this field are 'Apply' and 'Update'. + type: string + time: + description: Time is timestamp of when these fields were set. + It should always be empty if Operation is 'Apply' + format: date-time + type: string + type: object + type: array + name: + description: 'Name must be unique within a namespace. Is required when + creating resources, although some resources may allow a client to + request the generation of an appropriate name automatically. Name + is primarily intended for creation idempotence and configuration definition. + Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + namespace: + description: "Namespace defines the space within each name must be unique. + An empty namespace is equivalent to the \"default\" namespace, but + \"default\" is the canonical representation. Not all objects are required + to be scoped to a namespace - the value of this field for those objects + will be empty. \n Must be a DNS_LABEL. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/namespaces" + type: string + ownerReferences: + description: List of objects depended by this object. If ALL objects + in the list have been deleted, this object will be garbage collected. + If this object is managed by a controller, then an entry in this list + will point to this controller, with the controller field set to true. + There cannot be more than one managing controller. + items: + properties: + apiVersion: + description: API version of the referent. + type: string + blockOwnerDeletion: + description: If true, AND if the owner has the "foregroundDeletion" + finalizer, then the owner cannot be deleted from the key-value + store until this reference is removed. Defaults to false. To + set this field, a user needs "delete" permission of the owner, + otherwise 422 (Unprocessable Entity) will be returned. + type: boolean + controller: + description: If true, this reference points to the managing controller. + type: boolean + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + uid: + description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + required: + - apiVersion + - kind + - name + - uid + type: object + type: array + resourceVersion: + description: "An opaque value that represents the internal version of + this object that can be used by clients to determine when objects + have changed. May be used for optimistic concurrency, change detection, + and the watch operation on a resource or set of resources. Clients + must treat these values as opaque and passed unmodified back to the + server. They may only be valid for a particular resource or set of + resources. \n Populated by the system. Read-only. Value must be treated + as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + type: string + selfLink: + description: SelfLink is a URL representing this object. Populated by + the system. Read-only. + type: string + uid: + description: "UID is the unique in time and space value for this object. + It is typically generated by the server on successful creation of + a resource and is not allowed to change on PUT operations. \n Populated + by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + type: string + type: object + mesh: + type: string + spec: + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/app/kumactl/data/install/k8s/control-plane/kuma-cp/rbac.yaml b/app/kumactl/data/install/k8s/control-plane/kuma-cp/rbac.yaml index b417604aae14..d271abfe245a 100644 --- a/app/kumactl/data/install/k8s/control-plane/kuma-cp/rbac.yaml +++ b/app/kumactl/data/install/k8s/control-plane/kuma-cp/rbac.yaml @@ -56,6 +56,14 @@ rules: - get - list - watch +- apiGroups: + - kuma.io + resources: + - trafficlogs + verbs: + - get + - list + - watch # validate k8s token before issueing mTLS cert - apiGroups: - authentication.k8s.io diff --git a/app/kumactl/pkg/install/k8s/control-plane/templates_vfsdata.go b/app/kumactl/pkg/install/k8s/control-plane/templates_vfsdata.go index ec7869bd85a8..e175d36d7a15 100644 --- a/app/kumactl/pkg/install/k8s/control-plane/templates_vfsdata.go +++ b/app/kumactl/pkg/install/k8s/control-plane/templates_vfsdata.go @@ -29,7 +29,7 @@ var Templates = func() http.FileSystem { }, "/control-plane/crds": &vfsgen۰DirInfo{ name: "crds", - modTime: time.Date(2019, 9, 10, 9, 59, 52, 149121595, time.UTC), + modTime: time.Date(2019, 9, 20, 12, 28, 51, 621203938, time.UTC), }, "/control-plane/crds/kuma.io_dataplaneinsights.yaml": &vfsgen۰CompressedFileInfo{ name: "kuma.io_dataplaneinsights.yaml", @@ -59,6 +59,13 @@ var Templates = func() http.FileSystem { compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5c\xeb\x73\xdb\x38\x92\xff\x9e\xbf\xa2\xcb\xfb\xc1\x49\x95\x24\x27\x93\xdd\xab\x5b\x7f\xf3\x39\xc9\x9c\x6f\xf2\xaa\xd8\x99\xab\xab\xcd\xd6\x15\x44\xb6\x24\xac\x29\x80\x03\x80\xb6\x35\x7f\xfd\x55\x77\x03\x7c\x88\x0f\xc9\x89\x67\xea\xf8\xcd\x32\xd9\x04\xfa\xf9\xeb\x07\xf8\x6c\x3e\x9f\x3f\x53\xa5\xfe\x15\x9d\xd7\xd6\x9c\x83\x2a\x35\x3e\x04\x34\xf4\x97\x5f\xdc\xfe\xbb\x5f\x68\x7b\x76\xf7\x6a\x89\x41\xbd\x7a\x76\xab\x4d\x7e\x0e\x97\x95\x0f\x76\xfb\x05\xbd\xad\x5c\x86\x6f\x70\xa5\x8d\x0e\xda\x9a\x67\x5b\x0c\x2a\x57\x41\x9d\x3f\x03\xc8\x1c\x2a\xfa\xf1\x46\x6f\xd1\x07\xb5\x2d\xcf\xc1\x54\x45\xf1\x0c\xc0\xa8\x2d\x9e\x43\xe9\xec\xc3\x2e\xe0\xb6\x2c\x54\x40\xbf\xb8\xad\xb6\x6a\xa1\xed\x33\x5f\x62\x46\x8f\xaf\x9d\xad\xca\x73\x48\x3f\xcb\x53\x9e\xfe\x03\x20\xab\xf8\x4c\x04\x6e\x22\x01\xfe\xbd\x2c\x2a\xa7\x8a\x7d\xd2\xcf\x00\x7c\x66\x4b\x3c\x87\x93\x93\x67\x00\x77\xaa\xd0\x39\xaf\x4c\x88\xd9\x12\xcd\xc5\xe7\xab\x5f\x5f\x5f\x67\x1b\xdc\x2a\xf9\x11\x20\x47\x9f\x39\x5d\xf2\x7d\xdd\x57\x81\xf6\x10\x36\x08\x72\x3f\xac\xac\xe3\x3f\xbb\x2f\x85\x8b\xcf\x57\x91\x52\xe9\x6c\x89\x2e\xe8\xb4\x7a\xba\x5a\x0c\xaf\x7f\xdb\x7b\xe7\x29\x2d\x4a\xee\x81\x9c\x58\x8c\xf2\xda\x3b\xf9\x0d\x73\xf0\xb2\x00\xbb\x82\xb0\xd1\x1e\x1c\x96\x0e\x3d\x9a\xc0\x9b\x6b\x91\x05\xba\x45\x19\xb0\xcb\x7f\x61\x16\x16\x70\x8d\x8e\x88\x80\xdf\xd8\xaa\xc8\x21\xb3\xe6\x0e\x5d\x00\x87\x99\x5d\x1b\xfd\x7b\x4d\xd9\x43\xb0\xfc\x4a\xde\x51\xe8\x50\xd4\x26\xa0\x33\xaa\x20\x76\x56\x38\x03\x65\x72\xd8\xaa\x1d\x38\xa4\x77\x40\x65\x5a\xd4\xf8\x16\xbf\x80\x0f\xd6\x21\x68\xb3\xb2\xe7\xb0\x09\xa1\xf4\xe7\x67\x67\x6b\x1d\x92\x8a\x65\x76\xbb\xad\x8c\x0e\xbb\xb3\xcc\x9a\xe0\xf4\xb2\x0a\xd6\xf9\xb3\x1c\xef\xb0\x38\x53\xa5\x9e\xf3\x3a\x4d\x60\xb5\xdc\xe6\x7f\x71\x51\xfd\xfc\x69\x6b\x61\x61\x47\x72\xf6\xc1\x69\xb3\xae\x7f\x66\x75\x19\x65\xf3\x2f\xda\xe4\x24\x52\x15\x1f\x93\xe5\x36\xdc\xa4\x9f\x88\x09\x5f\xde\x5e\xdf\x40\x7a\x29\x73\xbc\xcb\x62\x66\x6e\xf3\x98\x6f\xf8\x4c\x7c\xd1\x66\x85\x4e\xe4\xb4\x72\x76\xcb\x14\xd1\xe4\xa5\xd5\x26\xf0\x1f\x59\xa1\xd1\x74\x79\xec\xab\xe5\x56\x07\x12\xec\x6f\x15\xfa\x40\xe2\x58\xc0\xa5\x32\xc6\x06\x58\x22\x54\x65\xae\x02\xe6\x0b\xb8\x32\x70\xa9\xb6\x58\x5c\x2a\x8f\x4f\xcd\x65\x62\xa8\x9f\x13\x07\x0f\xf3\xb9\x6d\xfd\xe9\x1a\x52\x7e\x36\x00\xda\x05\x2b\xea\xde\x3f\x00\x54\x9e\xb3\x37\x51\xc5\xe7\x91\x87\x47\x57\x30\x68\x46\xcd\x9b\x58\xcc\x06\x2a\xe3\x83\xab\xb2\x50\x39\xcc\xe1\x16\x77\x51\xe2\x5b\x55\x82\x0f\x96\x7e\xbc\xd7\x61\xd3\x7b\xa3\x6a\x4b\x5f\x05\x16\xeb\x12\xc1\x63\x80\xe5\x0e\xc8\x67\xb2\x41\x04\x6b\x0b\xb6\x1c\xa6\xc5\x86\xe1\x30\x38\x8d\x77\xd8\x27\xe9\x96\x3a\x38\xe5\x76\x35\xef\x16\x70\xb3\xc1\x1d\x28\x87\x40\x62\xfe\xad\x42\xb7\x53\xcb\x42\xe8\x44\x83\x5d\x92\xb3\x41\x4f\xda\x95\xf7\x48\xde\x6f\xd0\xc0\xd6\xe6\x7a\xb5\x23\xcd\x15\xb5\xec\x1b\xdf\xf9\xd9\xd9\x6d\xb5\x44\x67\x90\x9c\xaf\xb6\x67\xb9\xcd\xfc\x59\xe5\xd1\xcd\xd7\x95\xce\xf1\xac\x25\xa0\xd3\x67\x43\xac\x17\xca\x9d\x7f\x65\x45\xe5\x03\xba\x8f\xe4\xdf\xa7\x64\x72\xb3\x41\x76\xe7\xe2\xba\x30\x3d\x07\xf7\x1b\x9d\x6d\xf8\x97\x68\x4d\x4b\x2c\xac\x59\x8b\xe2\xdf\xec\x5b\x1c\x5d\xda\x43\xe5\x31\x27\x76\xe7\xda\x93\xad\x56\xda\x6f\x6a\x41\x79\x96\x24\x78\x7a\x17\xbf\x90\xb8\xc8\x81\xa4\x54\x19\xb1\x03\x72\xbd\x5a\xa1\xdb\xb7\xbc\xd6\x66\xbc\xbc\x19\x56\x1a\x0b\xf6\x13\x24\x16\x92\xb9\x32\xbb\xfb\x0d\x3a\x04\xa7\xd7\x9b\x00\xc6\xde\x33\x75\x55\x6a\x96\x8c\x83\x81\xe5\xae\x2d\x7b\x13\x0b\x7a\x6d\x58\x1e\x01\xf4\x8a\xa9\x69\x23\x01\x13\xc1\xba\x68\xd9\xc9\xee\x17\x83\xec\x1f\xd0\xfc\x7e\xc4\x9d\x12\xc2\xc9\xe5\xfe\xed\xe2\x05\x43\xfd\x67\xcf\x05\xca\xc6\xfa\xa6\xa8\xb7\x28\x7a\xc7\xfe\x2d\xca\xee\x5e\xf9\xb8\x25\x72\x51\x21\xb1\x6e\x5d\x29\xa7\x4c\x40\x11\x9a\xd8\x4f\x5f\xac\x06\x36\xaa\x2c\xd1\xf8\xf9\x12\x57\xc4\x29\xeb\x72\x74\xa0\x32\x67\xbd\x07\x8f\xa5\x72\xcc\xab\x12\x9d\xe8\xe8\x02\x2e\xd9\x81\x8a\xb7\x35\xb6\x4f\x93\xb8\xcc\xeb\x63\x6b\x4f\x4b\xaa\xf7\x88\x39\xbd\xf5\xcb\xbb\xcb\xd7\xaf\x5f\xff\x9d\x82\xfa\x96\xc5\xa9\x3d\xfd\xfc\xf5\xe6\x72\x01\xdf\x4c\x8f\xe6\x67\x5b\x56\x14\x1c\x73\xf2\x00\xcc\xa1\x9d\x0f\xb8\x5d\xc0\x17\x54\xf9\xdc\x9a\x62\xb7\x80\x8f\x55\x51\x30\x48\x28\xb4\x1f\x30\xc4\x1f\xf4\xcf\xc9\x6f\x9c\xec\xad\x8d\x36\xa0\xc2\x39\x90\x22\xcd\x49\x40\xc7\x2a\x51\x8e\x05\x12\xf5\x9f\x9d\xca\xf0\x33\x3a\x6d\xf3\x6b\xcc\xac\xc9\x7b\x3e\xb8\xa3\x4d\x1f\xab\xed\x12\x1d\x19\xb4\x97\xbb\x41\x15\x85\xbd\xc7\x3c\xe2\xa3\x46\x2f\x82\x85\x35\xd1\x5e\x55\x45\xb1\xeb\xeb\x12\xba\xad\x36\x24\xdb\x28\x78\x1d\xe0\x5e\x17\x05\x69\x8a\xc3\xad\xbd\x23\x8a\x29\x80\x26\x6e\x7f\x32\xc5\x8e\xe5\x4b\x4a\xd8\x23\x99\x76\xd4\xd5\xf3\xc2\x5b\x7a\x64\x01\x1f\xd4\x0e\x48\x52\xac\x8b\x1b\xeb\x02\x1a\xd2\xd8\x46\x82\x23\x9c\xd5\x26\xfc\xdb\x5f\x07\xb9\x4a\xd8\x68\xbd\x67\x27\xbd\x45\x4c\xdb\xe6\x9b\xa1\x35\x7f\x79\x77\x09\xac\x9d\xec\x1d\x48\x3b\xd9\xf2\x54\xa8\x1d\xe7\x80\xcb\xa9\x63\x56\xe2\x22\xaf\x84\x76\xd8\x75\x6b\x31\x8c\x35\x66\x2e\x16\xad\x6a\x61\x8d\xf2\x55\xcc\x88\x5d\x55\x63\x08\x14\x49\x66\xc9\x82\xc8\xee\x73\xed\x30\x0b\x22\xa7\xc0\x11\x6d\xd9\x97\xbe\x8a\x30\x88\xa3\x60\xb3\x74\xed\x01\x1f\x4a\xcc\x42\xed\x34\xe2\x26\xe0\xb9\xb1\x40\x21\x02\x1d\xdc\x69\xaf\x97\x45\x3f\xc6\xb2\xb6\xd4\xa4\xd8\x08\x65\x61\xb4\x2a\x87\x2a\xdb\xc4\xd5\x70\x60\x78\x01\x6a\x15\x50\x10\x3d\x73\x57\xf7\x15\x2a\xd4\x8c\x9b\x81\x35\x0c\x07\x10\x56\xda\xa8\x42\xff\x4e\x78\x8f\xde\xc1\x6b\xde\x96\x61\xb7\x80\x0b\xcf\x4b\x04\xe5\xf7\x6e\xec\x11\xe6\x07\xc9\xee\x95\x26\xb0\x12\x70\xeb\x67\x1d\x36\x2f\x0b\x9b\xdd\x92\xec\x3e\xa5\xd7\xf6\xf4\x6a\x28\x44\x7a\x0c\xb3\x96\xef\x4b\x2e\x92\x41\xa4\x21\xc1\x5b\x97\x90\xcc\xaa\x72\x61\x43\xc1\xcb\x44\xec\xbf\xaa\x08\x27\xcd\xfa\xa2\x2a\xc2\xc6\x56\xeb\x0d\x19\x68\x42\x42\xc9\x7a\x20\xa6\x44\x35\xd7\xe3\x0d\x49\x6a\xa5\xd3\x76\x20\x8c\x58\x59\x23\xb1\x7d\x01\xef\xac\x03\x7c\x50\xdb\xb2\xa0\xec\x82\xf5\x29\x26\x18\xac\x69\x02\xc1\x14\x94\x96\x35\x2c\x52\x1e\x0a\x24\xaf\x5f\x26\x97\x24\x5a\xf5\x4b\xb5\xa4\x9b\xc5\x1e\x48\xfe\xac\xf7\x1e\x4d\x4e\x61\xae\xd1\xf7\xda\x15\xed\x27\x53\x74\x79\xbd\x16\xac\x27\xf8\x45\x44\x46\xb2\xd7\x46\x92\x41\x9b\x2f\xe0\x22\x6a\x92\x0a\xad\x45\xcc\xf8\xff\x71\x11\x7d\xf4\x46\x8b\xa2\xb5\x80\x82\x8d\x72\x79\x7b\x11\xe9\xa5\xcf\xaf\xaf\x7e\xfe\xe5\xea\xfd\xfb\x17\xbd\xd7\x93\x5a\xf7\x05\xc5\xab\xc8\x0a\x54\xa6\x2a\x67\xd1\x89\xa6\x45\x36\xbe\xf4\xe2\xf3\x15\x67\x12\x92\xca\x52\x48\xcc\x18\x9f\x19\x0c\xf7\xd6\xdd\xf6\xc8\x96\xca\x05\x86\xe9\x7e\xd6\x71\xef\x24\x23\x1f\x68\x1b\xf8\x40\xea\x9c\xcc\x29\x0a\x96\x75\x74\x06\x95\x09\xba\xef\x51\x94\x01\x95\x6f\xb5\xd1\x3e\x38\x15\xac\x23\x3d\x52\x55\xb0\x5b\x25\x5a\x63\x33\xf4\x1e\x32\x45\x09\xb1\x30\x06\xbb\x7a\x36\xe0\xff\x38\xcc\x34\x61\x85\xb0\xc8\x2a\x61\xb8\x59\x23\xec\xda\xca\x22\x24\x8d\xbb\xd9\xa8\x3e\x45\xb1\x1c\x34\x8d\xd3\x23\x6c\x30\x86\x05\xf6\xdd\x68\xfd\xa6\x21\x43\x6d\x51\x6c\x21\x88\xff\xe7\x88\xa1\x71\x68\x93\x31\xed\x43\xe5\xd9\xe3\xb0\x57\x4c\xd1\xbd\xc5\xea\xc6\x8a\x1b\xa5\x74\xb8\x26\x5d\xe8\xc5\x60\x80\xb7\x2a\xdb\x00\x9a\xe0\x76\x31\xa9\xd3\x39\xed\x71\xa5\xd1\xd5\x15\x19\x87\xbe\xb4\x86\xa3\x02\x64\x76\x5b\x5a\x83\x26\x3a\x0e\xb2\xb3\x81\x50\x59\x9b\x86\x50\xae\xd7\x41\x8e\x99\x15\x67\xd0\xe5\x76\x75\x66\x48\xae\xc6\x9a\xb9\xd1\xc5\x8c\xe9\x6a\x8c\x6e\x42\xc7\x50\x41\x0a\x9d\x10\x48\xc4\x38\xfb\x1b\xe6\x58\xf0\xa8\x24\x58\xfe\xa5\x9c\x53\xdd\x30\xbb\x46\x43\x98\x19\x0f\x26\x69\x27\x3f\xb7\xee\x8c\x4c\xb6\xa5\x24\xe6\xe4\x21\x56\xfa\x61\x26\xc9\x57\x07\x36\xf4\x23\x05\x01\xbe\x48\x8a\x1c\xb9\xd1\xbf\x55\x31\x1b\xfb\xf4\xf1\xfd\xff\xc0\xd5\x3b\x7e\x9a\xdf\x22\x68\x64\xa3\x7c\x63\x64\xa5\xb3\x77\x3a\xef\x73\x04\x44\x1c\x6d\x08\x43\x8b\x11\xf7\xca\xd4\x1d\x86\xca\x19\x81\x0c\x4d\x85\xa5\xc1\x41\xa3\x99\x5f\xd8\x28\xd3\x90\x29\x95\xf7\x35\x5c\x92\xf8\xc9\x24\x18\x41\x2e\x59\xb3\x96\xda\xc4\xa2\x41\xbd\xc1\x7e\xc4\xa8\x56\x2b\xfd\x20\x21\x28\xed\x29\x92\xdb\x44\x64\xc0\x69\x6a\x53\x9e\x04\x57\x15\xe8\x13\x6c\x20\xfe\xf4\x9d\x9b\x80\x90\x54\x7c\x5b\x22\x04\x57\x99\xac\xed\x85\x0a\x34\xeb\xb0\x49\x2a\x2a\xab\x60\x3f\xa3\x1d\xb3\xa6\x47\x73\xab\x6e\xc5\x06\x64\x71\x51\x5e\xd6\xb4\x64\xcc\xfe\xae\xc7\x7e\x5f\x62\x46\x06\x38\x10\x82\x08\xaa\x6e\xb0\x56\x03\xc9\xc1\x25\x40\xc4\x80\x98\x30\x27\x71\xf6\xe3\xa7\x9b\x28\x3c\x50\xf0\xd7\x97\x7f\x87\xf9\x40\x5c\xf7\x01\x55\x3e\xab\xd3\x03\xd4\x0c\x5b\xe2\x63\x3f\xbd\x7c\x05\x97\x92\x7b\x52\x0c\xf9\xdb\xcb\x97\x22\x9d\x2f\xa8\xbc\x35\xb1\x30\x47\xf6\x6b\xab\xa1\xe4\x33\xd7\x99\x0a\x82\x06\xda\xea\x9a\x71\xf5\x25\x02\xa7\x95\xad\x4c\x9e\xc2\xbd\xe0\xf0\xa2\xb0\x21\x60\x3e\x80\x95\xe2\xfe\xa3\x06\xc6\x32\x8e\x43\xf2\x31\xcf\x93\x4d\x15\xbb\x3e\xf4\xe4\x85\x70\x66\x3a\xa0\xa4\x08\x5f\x88\xc2\x5c\x60\xc6\x06\x55\x8e\xee\x05\x8b\xe6\xa2\x2c\x0b\x4d\x5b\x27\xa7\xa2\x57\x90\x2c\x98\xc3\x5e\x92\x52\xdf\xa0\x9e\x36\xce\xe8\x1c\xb7\xa5\x0d\x68\xb2\xdd\x7e\xa8\x19\x75\x5b\x51\x41\xf6\xca\xe2\xb0\xef\x9a\x2e\xc0\x53\xa0\x24\x84\x62\x24\xef\xec\x94\x2a\x54\xda\x64\xd6\x22\x08\x76\x35\xc8\xc3\x1c\x3d\x5b\x82\x0f\x2a\xe0\xe2\x98\x8c\xfe\x49\xf2\x41\xee\x98\x1c\x13\x36\x4f\x2e\x4c\xfb\x66\xa9\xd1\xb0\x04\x6c\x51\xd4\x35\x33\x34\x2b\xcb\xf5\x2e\x6f\xb7\x69\xcd\x03\x8a\x7d\xa7\x9c\x56\x26\x50\xca\x18\xa3\x6e\xaa\x19\x45\xd4\xdd\xcd\x09\x95\xc4\x27\xbb\xea\x2c\x77\xc8\x5f\x12\x52\xba\x93\x92\xe5\x0e\x03\x28\x4e\xd5\x6c\xa7\x20\x24\xc0\x4b\x17\x64\x90\x8c\x01\x3a\xb8\xb1\x47\x94\x9c\x22\x07\x00\x8a\xdc\x04\x0b\x48\x95\xeb\x55\x50\x0a\x44\x06\x7f\xaf\x3d\xce\xf6\x50\x44\x46\x31\x3f\x47\x37\xe0\x88\x2a\xd3\x22\x91\xb2\xd3\x8d\xce\x73\x34\xf0\x5c\x1b\xde\xee\xd9\xbd\x0a\xd9\x86\xff\xb9\x46\x0a\xce\x45\xe1\x5f\x08\x14\x10\xfb\x9d\x60\x80\x39\x0d\x94\xa9\x16\x3a\xd3\x94\xea\x2a\x7f\x2b\xe1\xc7\x2e\xd9\xbf\xed\xbd\xbf\xae\xcd\x0e\x54\x96\xfe\x9b\x51\xa3\x69\x6f\x4b\xfc\xd9\xac\x83\x2d\xc9\xf5\x95\x51\x65\x5b\x88\x62\xb0\x7e\xcd\x1e\xa8\x72\x8e\x5d\x10\xf6\xc4\x1a\xcb\x28\xa5\xd3\x77\xba\xc0\x35\xe6\x9c\x73\x49\x3d\x4d\x72\xc4\x7e\xa8\xe0\x32\x73\xf3\xde\x98\x97\xea\x26\xfb\x9d\xa5\xf4\x30\x7a\x4d\x7e\x82\x5c\x53\xcc\x33\x7b\x24\x97\x3b\x50\x66\xc7\xaf\x66\x57\xf6\xe6\xed\xe7\x2f\x6f\x2f\x2f\x6e\xde\xbe\x81\x79\x67\xb9\x5c\x22\xa7\x84\xa1\x28\x37\x2a\xaa\x2c\xc9\x6c\x10\xd9\xb5\x8a\x47\xda\xc0\xdd\xab\xc5\xab\xbf\x2d\xf6\x9d\xd2\x58\xa7\x82\xff\x27\xd9\x61\xff\x1f\xfb\x7d\xc2\x98\x45\x8e\xda\x4e\xec\x1c\x10\x14\xc6\x07\xcc\xaa\xd0\x8f\xe9\x20\x69\xab\x14\x3c\x6b\x98\xdc\x24\x58\x84\x42\xa4\xd4\xb1\x10\x2d\x91\x0e\x9d\x0f\x69\x95\x23\x14\x3b\x2e\x24\x72\x23\x15\x42\x60\xa5\x74\x41\x0b\x77\xe8\xab\x22\xb4\x6a\x06\x38\x6d\xfa\x74\x49\x33\xa5\xc6\x55\x5c\x67\xb5\x6c\xe9\x29\xee\x0d\xd9\x26\xe1\x9a\x96\x31\x0c\x52\xa6\xe7\xe3\x5e\x89\xa4\x2a\x8a\x64\x82\xfd\xe0\x35\x8a\x91\x0f\xc9\x56\x2e\x33\x00\x87\x9b\xab\x23\xe4\x76\xe7\x22\xe5\xa4\x2c\x56\xe6\x6b\x93\x72\x50\x1a\x52\xef\x70\x4c\x2e\x72\xb5\xdd\xe4\xe8\x6d\x13\x60\x5f\xae\x84\xea\x86\xf7\x31\xe7\x85\x0f\xfe\x6b\xb4\xa1\xd3\xfe\x77\x3f\x95\x90\x77\x92\xc2\x1c\x34\x8c\xab\x55\x57\xb5\x04\x8e\x11\x07\xdf\x29\x5d\x54\x0e\x13\x94\x9d\xc8\xa3\x20\xd5\x47\x96\x08\x25\x3a\xaf\x7d\xac\x07\xfa\x60\x9d\x5a\x63\x52\x37\x93\xf2\x48\x4a\xb7\x7c\xe5\xa4\x7b\x41\x21\x6f\xd0\xe3\x00\xf7\x7a\xa4\x77\xc0\x99\x58\xf4\xd5\xed\x54\x6f\x48\x28\x87\x74\x6a\xb8\xc5\x3f\xca\xa1\xc7\xb6\xfb\x47\xd5\xa4\x3b\x06\xf0\xd8\xd6\xff\x28\xd9\xc1\x91\x80\xc7\x8c\x01\x8c\x52\xfe\x13\xc7\x03\xda\xd7\x41\x73\xca\x6c\x3e\xea\x12\x3a\xa2\xbb\xae\xd6\x6b\x29\x7e\xff\xe7\xcd\xcd\xe7\x94\x83\xd0\xe3\x4d\xf3\x83\xe0\x65\xe5\x67\xf0\x12\x74\x1f\x87\xa6\x2b\x96\xa5\xc6\x5c\x40\x0b\x69\xbe\xfe\x69\x72\x57\x43\x88\xb3\x59\x7a\x50\xba\x18\x75\x84\x9d\x9d\xbd\x7d\x08\x68\x28\x51\xcd\x55\x50\xa0\xbc\xb7\x99\x66\x70\x5c\x9b\xaf\xe3\x8c\x6a\x21\x05\x99\x09\x9d\xe4\xbc\x8b\x34\x43\x74\x1b\x74\xf0\x60\xef\x0d\xb7\xcd\xe5\x0d\xb2\xac\x3d\x08\x3a\x4a\xb1\xae\x44\xa4\x18\xc3\x2b\xac\x53\xfe\xc1\x66\x63\x66\x09\x25\xf7\x71\x71\xcd\x3b\xcb\xd8\x23\xda\x19\x3e\x64\x58\xc6\x72\x91\x2c\xba\xce\x09\xe2\x76\x88\xd7\x63\xb2\x3a\x1c\x71\x00\x32\x55\xf9\xa9\xff\x0f\x74\xcd\x2f\xf9\x11\xf1\xc5\xa0\x4d\x56\x54\x39\x7a\xd8\x92\xe5\x44\x06\xb6\xa4\x34\x41\x18\x1a\x09\x5e\xb3\x66\xc6\xcc\x78\x25\xde\x78\x01\x1f\x6d\xe0\x78\xdb\xfe\x2f\x63\xc1\x49\xa2\xb1\xb0\x11\xd7\x82\x79\xdc\xe2\x78\x4c\x9b\x8c\xda\x2d\xaa\x07\x79\x29\x17\xab\xcd\xa1\x9b\xf6\x13\xac\x9b\x4d\x2a\x3c\xc5\xa0\xde\x1d\xf3\xa0\x44\x84\xb7\x31\xcd\x4f\xb9\xd8\xd6\xd1\x39\xeb\x66\x04\x70\x28\xe2\xb2\xd6\x90\xba\xff\xd7\xf5\xa7\x8f\xe0\xd1\x31\x1e\x50\x63\x61\x65\xff\xfa\xd0\x08\x1a\x72\x12\x8a\xc9\xa1\xb4\x3e\xac\xf4\x03\xa4\x09\x0d\x76\x33\x86\x5d\xd0\x11\x14\x55\x10\xf7\x49\x3e\xf7\x82\x14\x49\xb0\xf4\xef\xe8\xec\x5c\x9b\x1c\x1f\x28\xbb\x82\x77\xc4\x91\xc3\x12\x8f\x24\xcb\x12\x95\x13\x3d\xe4\xea\x19\xb7\xc5\x34\x67\x30\xa2\xab\x76\x15\x75\x01\xf2\x81\xe2\xd8\x00\x23\xad\xc8\xc4\x53\x5e\x45\x11\x7c\x5b\x15\x41\x97\x05\x0a\x77\x29\x5b\x89\x1e\x80\xd3\x84\xb7\xd2\x29\x3a\xa8\x20\x74\x7d\x03\xf8\x76\x42\x92\xf9\x76\x02\xf3\xd8\x92\x23\xe9\xd7\x3f\xc6\x5a\x57\xcc\x95\x8e\xa0\x58\x2b\x0c\x51\x66\x85\xfe\xc7\xcb\x7f\x2e\x26\x5e\x71\x04\xcd\xb8\x88\x95\x76\x3e\x44\x1e\xc6\x72\xb7\x49\x2f\xf9\x76\x72\x98\xd0\xc1\x28\xd7\x5c\x5b\xf4\x5e\xad\x27\x50\x70\xba\xf6\x6a\x31\x9b\x6a\xab\xcc\xdc\xa1\xca\xb9\x91\xda\xfa\x6f\x3d\xdf\x43\x92\x3f\x66\xcf\x72\x3b\x4b\x78\x01\xed\x48\x10\xab\x9b\xcd\xac\x86\xf2\xf3\x89\xe8\xd0\xda\xbf\xe5\xb9\x2d\x95\xa3\x3b\x6c\x6d\x8f\x60\x96\x84\x80\x47\xf3\x6a\xab\xb2\x8d\x36\x38\xc5\xad\x23\x36\xc5\xfc\xdc\xe3\x56\x2a\xc7\x4a\xd5\x36\xe5\xdf\x74\x87\x3b\x86\x24\x07\x4c\x46\x5f\x84\x31\x68\x35\xea\x4e\xe9\x82\xd6\xf8\x84\x7c\x3b\x90\x68\x74\x6f\x1b\x4e\x38\xd2\x25\xf3\xc1\x8f\x89\x9d\xfc\x44\xe3\xfd\x7a\xde\xfe\xb1\x81\x53\x20\x5d\x27\x42\x4e\xb1\xea\x28\x26\xed\x8f\xaa\x4e\x6e\xea\x94\x76\x45\x4f\xfc\xc1\x9b\x82\x4f\x46\xea\x8a\xcd\xb8\x95\x40\x39\xee\xa0\x4c\xd2\x6d\x75\xf2\xd2\x80\x48\xbd\xb4\x5f\xb4\xc9\xff\xa4\x71\xd5\xef\x92\xc5\x74\x49\x60\x6c\xa4\xf1\x0f\x15\x05\x3c\x8f\x63\x76\xe8\x30\xce\x2c\x6b\xb3\x2e\x70\x3c\xb5\xaf\xa9\x72\x99\x98\xf2\xdb\x65\x72\x3a\x4b\xcc\x5f\xfc\xb0\xc2\x72\x13\x83\x3b\x10\x23\x53\x62\xa3\x1c\xbb\x5a\x35\xbd\x88\x59\xbb\xe9\x51\x4f\x90\x35\x3d\xe2\xc9\xad\xd5\x5a\xd9\x9a\x8f\x95\x89\xdb\x7c\x01\xd7\xa4\xb7\x02\x19\xe2\x1c\xb6\xf4\x54\xa6\xdd\x54\xd3\xab\xe1\x52\x5d\x50\xb7\xb1\xd6\xc8\xd9\x6e\x40\x50\x19\xbf\x70\x1e\x13\x3c\xeb\xd3\x4b\x0e\xd0\xed\x04\xb4\xb4\x16\xd8\xd8\x7b\x19\x11\x0a\x16\xee\x95\x0e\xf5\xce\xd5\xed\x41\x8f\xba\xc1\xde\xb2\xa6\x84\x7a\x4c\x0e\x09\x47\xe5\x91\x74\x55\xfa\x11\xde\xea\xeb\xd5\x9b\x7d\x9b\x58\x8c\x29\xf4\xe4\x9e\x9b\x91\xb6\x11\xa5\x7e\xf4\xb0\x73\x33\x3c\xe0\xff\x52\xe9\x1f\xf6\x1d\x07\xc3\xdc\x94\x9b\x7f\x82\xd3\x09\xe3\x19\x6e\xab\x8e\xfc\x3d\x27\x15\x26\x08\x37\xdd\xcd\xef\x39\xb5\x30\x4a\xf8\x4f\x0f\x0f\x07\xc5\x7b\x00\x26\x3f\x1a\x1c\x47\x37\x7f\xa8\xac\x57\x7b\xb9\x31\x5e\x1d\xb1\xf0\xfe\xf1\x8c\xd1\x95\x9f\x5e\x07\x65\x72\xe5\x72\x69\x63\x34\xc7\x13\xfe\x74\x81\x1c\x55\x49\xb1\x64\x09\xd5\xf1\xe1\x3a\x3d\xd0\x3e\xc4\xa1\x57\xf5\xe4\xaa\x0c\xf8\x43\xa1\xb7\x7a\x3a\xff\x8b\x59\x9a\xa9\xa7\x9f\x39\x31\xab\xeb\x50\x71\x02\x36\xfa\xf9\xd8\x26\x38\x14\xcf\xe2\x28\xc4\x46\xa5\xc2\x0e\xd7\xde\x6a\x34\xce\x50\xa3\x46\xf9\xb6\x54\xbf\x55\x38\x38\xf8\xd7\xbe\xe2\x36\xd3\x59\x09\xed\x3d\x3f\x64\xe3\xd0\x44\x1c\xa9\xb4\xfb\xc7\x92\xd4\xf4\xee\xe5\x08\x4a\xab\xef\x18\x6c\x7d\xd6\x45\xf8\x82\x0f\x75\xaf\xb1\xde\xc1\x34\x43\x53\x4f\xf4\x52\x24\x24\xfd\x7c\x6e\x1b\xf9\x40\xee\x45\xd4\xb1\xe9\x28\x96\xd6\x0f\xcf\xfd\xb6\xaf\x28\xda\xc8\xd9\xcc\x9a\x95\x5e\x57\x11\x34\x70\x7d\x67\xa3\xcc\x5a\x66\x45\x9a\x1a\x86\x9a\x46\xb6\x78\x0f\x5b\x6d\x2a\x12\x2b\xf7\xbe\x9b\x39\xa1\x26\xbe\xa5\x82\xbe\xc4\xfc\xa4\x15\x07\x80\x1a\x1a\xa8\xbc\xf8\x75\xe9\x98\x89\xa6\xb6\x46\x8f\x96\x18\xc7\xdd\xb2\x7a\x06\x75\x92\x66\xd4\x96\x76\x45\x21\x36\xaa\x70\x06\x95\x29\xd0\x7b\xd8\xd9\x4a\xf6\xe1\x30\x43\x3d\x74\xb2\xa8\x7d\xc9\x3c\xa7\xbd\x45\x23\x41\x42\x19\xc1\x3f\xc9\x3b\x3e\x01\xae\xec\x70\xf0\x78\x94\x71\x1d\x9a\x86\x4f\x1d\xd6\x7d\x4b\xfc\xa7\xa7\xbe\x6e\x5b\x4c\x73\x2d\x0a\x2f\x9d\xaf\x4c\xe7\x17\x88\x72\xc4\x1c\x69\xfc\x2d\xf5\x8f\x06\xc6\xa9\xba\x2b\x4d\x53\xab\x2c\xe5\xa8\xeb\xc2\xf6\xa8\x82\x0b\xf8\x55\x46\xb4\xe3\xb4\x64\x90\xae\xff\x24\x59\x55\xbb\x81\xd6\x52\xb8\x4e\xc8\x2a\x09\x95\xa9\xdb\xee\x4b\x95\xdd\x1e\xa3\x31\x69\xce\xeb\x98\x03\x2e\x4d\x44\x98\x24\xf9\x04\xd1\x22\xb3\x46\x8a\x72\xd9\x6e\x1e\x47\x60\xe6\xca\xe4\xf3\xda\x3d\x64\xbb\x1f\xce\xfa\x3c\x16\xab\xf7\xda\xdc\x1e\xad\x71\xe9\x01\x41\x69\x5f\xbf\xbc\xdf\x07\x67\x47\xb4\x76\xe1\xb8\xb3\x44\x7f\x30\x2a\x9d\xae\x69\x3d\xb2\x92\x75\xbf\x89\x83\x21\x35\x70\x19\x5d\xbd\xae\xc7\xe6\x4f\x62\x37\xf8\x24\xa2\xa2\xe9\xb2\xd6\x54\x7f\x68\xb4\x98\x05\x17\x69\x0a\x30\x2b\x94\x13\xe7\xa0\x8c\x74\xee\xe4\xa5\x13\x28\x23\x47\x58\x56\x01\x72\x8b\xd2\x5f\xb2\x77\xe8\x9c\xce\x11\xf4\xa8\x70\x0f\x0a\x46\x5e\x7a\x34\x28\xab\xb1\x62\xab\x1c\xb3\x80\x4f\x06\xc1\xae\xce\xe1\xe4\xba\xca\x32\xf4\xfe\x64\x68\x5c\x27\x5d\x35\x97\x9f\x1a\xcd\x51\x3e\xcf\x06\x29\x7b\xfa\x4e\x88\x3d\xa1\xa7\x63\x13\x0e\xf3\x91\xd9\x97\x51\x52\x85\x5a\x62\xbf\x07\xfa\xc4\x27\x8f\x3f\x28\x1e\x0d\x8f\x89\xdb\x2d\xee\xc4\x2b\x4b\xbf\xbb\x1f\x47\x82\x05\xeb\xd6\xca\xe8\xdf\x07\x0e\x0a\x9b\x1c\x08\x42\xae\xad\xd3\xbf\x23\x3c\xe7\x0f\x1a\xc8\x99\x60\x2c\x30\x0b\x2f\x5a\x07\x7d\xd5\x0e\xb6\x3c\xc2\x26\xff\xb2\xce\x0f\xcd\x3e\x3a\x2c\x0b\x1e\x73\x25\x4b\xa8\xc7\x09\x7d\xa4\xe9\xee\x74\x36\xd0\x93\x3f\x98\x48\x0b\x5f\x8f\x3e\x30\xbc\x55\x46\xad\x31\x97\x5e\xd3\xf4\x18\xe4\x87\xf6\xad\xb0\x55\xa5\x87\x7b\xeb\x6e\x57\x85\xbd\x9f\x6b\x19\xfd\x4a\x01\x3b\xe2\xd8\xa1\x83\xa5\x76\x95\xda\x4a\x72\x7e\xc8\x61\x5a\x83\x78\x5d\x15\x6a\xaa\xb1\x13\xad\x09\x85\xfb\x50\xec\xe2\x3c\xcf\x08\x70\xd8\xd8\xca\xe3\x2d\x62\xa9\xcd\x5a\x50\xbf\x4c\xcf\x85\x5d\x49\x28\xad\xd8\xc5\xe2\x94\x39\x0d\x60\x62\x3f\x3a\x9e\xbc\xaa\x4c\x8e\xce\x87\x21\x08\xdf\x14\x8c\xc8\x6f\xa5\x95\x25\xad\x49\xd9\xca\xa9\x34\x1a\x67\x9d\xc1\xd0\xf4\x63\x9f\x05\xae\x99\x6d\x27\x58\xde\x0c\xcb\xaa\xb2\x2c\x76\x50\xaa\xb0\x81\x42\xdf\x22\x7c\x3b\xc9\xf4\x3c\xcb\xbf\x9d\x08\xa8\x8d\x38\x5e\xf8\xd7\x23\xcb\x67\x2a\xef\xd5\xae\xf6\xe5\xb5\x34\x62\xce\xd3\x2c\x9f\xb5\x7d\xef\x9c\xfa\x10\x20\x49\x43\x2b\xdf\xcc\xfe\x5c\x2a\xcf\xfc\x89\x4d\x30\x27\x5a\xf8\x3d\xcd\xf9\xdd\xeb\xb0\x19\x9a\xee\x36\x36\xe8\x0c\x7b\xd3\x7f\x23\x6d\xe8\xe9\xe4\xf3\xd0\x88\x4f\x37\x64\x4e\xce\xf7\xb4\xbe\xe2\xd1\x6a\x3e\x8f\x39\xd0\x86\x1b\x9c\xa8\xf2\xb8\x77\x3a\x25\x8f\xb1\xc6\x47\x8c\x3a\xe1\x9e\xc7\x59\x7c\xc7\x09\xfc\xab\xf2\x63\x34\x59\xe2\x5c\x85\xb5\xe5\xbc\x20\x0f\xdf\x5e\x71\xd4\xc1\x78\x8c\x1b\x29\xc4\x28\xb7\x63\x4b\x73\x2a\xeb\x9f\x0e\x4b\xeb\xec\xec\x4f\xb5\xd6\xbc\x44\x69\x62\x69\xf6\x81\x31\x97\x8b\x67\xbd\xc4\x60\x46\x68\xc6\x91\xa5\xa1\xf9\x75\x38\x1c\x5b\x56\x83\x9e\x46\xae\x41\xef\x0f\xc1\x8d\xf4\xab\x3b\xc2\x8d\x6e\xa9\x95\x70\xa8\xae\xbd\x4c\xad\x76\x14\x92\x89\x6b\x72\x47\x28\x97\x78\x47\xd7\x3f\x0b\x15\xa1\x42\x6d\x7b\x4c\x72\x02\x23\x6e\xd0\xe3\x11\x4b\x1e\x65\x70\x8d\x49\x8e\x58\xf4\xa7\xba\x70\x1f\xbf\xa8\x43\xb4\x69\xc5\x4d\x45\x5f\x2a\xbc\x05\xaa\xc1\xa3\x2a\x69\xcd\xda\x43\x27\x3c\xbc\xe5\x46\xf9\x12\xc9\xb1\xd4\x9f\x20\x20\xcb\xe0\x03\x11\x7c\xc2\x26\x46\xe1\x11\x92\xf5\xd8\x56\x9c\x2b\x76\x08\xa7\x17\xe4\x1d\x4f\xd9\xeb\x9c\x7e\xe5\x22\xe6\xe9\x77\x71\x28\xe8\xb1\xb6\x52\xb7\xa1\xa4\xe5\xcc\x46\x68\x9f\x32\x4b\xc5\xf2\x5a\x46\x70\x4f\x38\x78\x62\x66\xec\xaa\x3e\x6e\x12\xbd\x73\x7d\x02\x4f\xaf\xba\x02\x88\x1b\x1c\xa4\x73\xe8\x6c\xe0\x11\x1b\x9f\x50\xf5\xb1\x76\xef\x50\x03\xae\x8b\xb0\xf8\x60\x4b\x4a\x95\xe3\x51\x1d\x72\xfc\xda\x80\x6a\xbe\xf3\xb1\x80\x2b\xdf\x1c\x79\x1a\xfc\x46\x80\x1c\x83\x90\x01\x68\x19\x1b\x9c\x35\x27\x9c\xb9\xf7\xd9\x7c\x52\x64\xab\x76\xf2\x71\x83\xfa\xb8\xfa\x90\x6e\x36\xe7\x94\xb1\x7b\x0a\x85\x1b\x49\x25\x05\x16\xa7\x55\x48\x5d\xc3\xb6\xe7\x5b\x0c\x1f\xf6\xd2\x1e\x4a\xa7\xb7\xca\x69\x3e\x0a\x11\xe7\xe6\x48\x55\xeb\x43\x1c\xcd\x99\x1b\x01\x87\xdd\x4a\x57\x5e\x7f\xa8\xab\xaf\x2d\x03\x05\xfa\x1f\x69\xa2\x30\xef\x87\x61\xe0\x80\x7e\xd4\x92\x9a\x86\x80\x1f\xeb\x0f\xb7\xb4\x03\xa8\xfc\x12\xa5\x8e\x2a\xdb\x08\x47\xbb\x5a\xd1\xdf\xf0\x85\x89\x76\xd0\xfa\x1c\x8c\x07\x52\x92\x3b\x55\x88\x4c\x99\xfc\xb7\x93\x1c\x57\xaa\x2a\xc2\xb7\x93\xe6\xd6\x19\xa5\x81\x3d\x92\xed\x5b\xa3\x47\xcb\x94\xb1\x86\xcb\x74\xdd\xb1\xdc\x66\xc0\x2e\x15\x81\xc8\xc7\x24\x1d\xed\x1b\x8f\x7c\x29\x85\x40\x7f\x2e\x23\x2d\xcd\xaa\xe7\xad\xc3\x7a\xb6\x73\x26\xaf\xe9\x4d\xc6\x97\xf4\xe8\xa6\x6a\x62\xfc\x52\xc1\x37\x53\x9f\xd2\x55\xf0\xe6\xe3\xf5\xff\xbe\xbf\xf8\x8f\xb7\xef\x07\xbb\x37\x13\x45\x9f\xa3\x94\xa5\x5e\xbf\x3f\xfa\x70\x98\xbd\x37\xe8\xbe\x20\x1f\xda\xcc\xfa\x80\xac\xa3\x2b\xef\xe3\xd9\x8b\xc4\xdd\x1c\x4b\x31\x97\xe5\xae\x77\x26\xe9\xe2\xfd\xfb\x51\x06\x45\x2c\xcb\x45\x67\x2e\xd3\xf1\x91\xa4\x7a\xbe\xbc\xf3\xbd\x9b\xc8\xcb\xb5\x72\x4b\xb5\x46\xc8\x08\x86\x67\x83\x40\xe5\x6a\xb5\x7f\xa2\xa3\x95\x84\xb4\x41\xfc\x4c\xe6\xd9\x95\x69\x66\xbf\xea\x62\xfb\xb0\x30\x63\xe5\xde\x36\xc5\xe3\x44\xa9\x9e\x2b\x68\x1d\x1e\x6b\xf0\x18\x23\xb9\x21\x3b\xb9\xe1\x4a\x4b\x83\xd1\xda\x33\x7e\x58\xc3\x89\x16\xd1\x23\x8f\x2e\x3f\x2d\xb2\xee\xc2\x68\xb2\x24\x39\xdb\xfb\x5d\x11\x9a\xbf\xb2\xf1\x89\xb4\x2d\x7d\x86\xe5\x88\x45\x90\x4c\x5d\x85\x33\xb8\xf8\xf8\x26\xf5\x1b\x58\x63\xeb\xe3\xbd\x27\x2b\xeb\x90\x00\xb9\xc9\x13\xdd\xb1\xf9\xbd\xfa\x48\x7d\x54\x80\x86\x58\x23\x88\xde\x61\xf9\x5b\xdc\xcd\xd9\x0d\x8c\x10\x95\xef\x91\xf1\x97\x17\x52\xaa\x11\x6d\xa9\x75\x22\x68\x01\x6f\xc4\x87\xf1\xa4\xff\x4a\x15\x1e\x17\x70\x33\x06\xbd\xea\x6f\x2a\xa5\x83\xc8\xd2\x3d\xa3\x04\xd7\xc3\x89\xac\xf0\x04\x4a\x74\x5b\xed\xdb\xe2\xe1\xbd\xf4\x53\x53\xb9\x6c\x3a\xd8\x07\x7f\xfd\xe9\x27\x78\xfe\xd5\xc4\x43\x36\x5c\x65\x7c\x6b\x82\x0e\xbb\x17\xad\x6f\x02\x49\x4f\x65\x4a\xd0\x4b\x6b\x0b\x54\x43\xf5\xc7\x46\x6b\x1f\x23\xe1\x3d\xe6\xb1\xc9\xd5\x07\x23\x8e\xb0\x88\xe3\xd6\x36\x3e\x23\x30\x30\x21\xb0\xaf\xf6\x7f\x76\x9b\xf6\x80\x45\x8d\x8f\x52\x0d\xe0\xb9\x43\x7b\xf9\x71\x20\x72\xd4\x9a\x47\x67\x5b\x26\xa6\x5a\x9e\x62\xc5\xe3\xf3\x27\x93\x0b\x1e\x3f\xfc\x35\x6f\x79\xd3\x81\x7f\x92\x54\x07\x7e\x1e\x9c\x28\x9b\x13\x57\x9e\x02\xda\x1f\x68\xef\xf5\x4e\x40\xc7\xfe\x96\xa0\x1c\xae\x28\x35\xe3\x2b\xf1\x94\x62\x3a\x88\x54\x07\x82\xe1\x6a\xda\x51\x5d\xbc\x91\x4e\x5d\x1f\xea\x74\x3a\x77\x1f\x5a\x4d\x76\xc2\x5e\xb6\x0c\x7a\xab\x7d\xd0\x19\xb4\x3a\x57\xb3\xf8\x00\xbf\x83\xe7\xb5\xc6\x3f\x18\x20\x47\x91\x9b\x74\xd8\x9a\xf6\x57\x28\xad\x4b\x35\x86\x3a\x39\xa9\x3f\x83\xd7\x23\x29\x83\x6c\x94\x28\xc4\x04\x32\x96\xa1\x55\x7b\x86\xe0\x91\x1d\xc3\xd4\x25\xe4\x4f\x56\x6e\x5b\xdf\x51\x93\x14\x9b\x78\xa0\xe4\x43\x41\x59\x55\x28\x37\xb0\xf2\x01\x35\xae\x77\x32\xfe\x4d\x9d\x4e\xfb\xf1\xb8\x7e\xe9\x68\x8f\xf4\xa9\x5d\xe5\x11\x3d\xca\xa3\x11\xef\x58\x2f\xb2\x7b\xfa\xec\xf8\xfe\x63\x87\x9f\x03\xe6\x71\x44\xcf\x71\x74\xad\x03\xee\xb2\x6b\xc5\xe4\x28\x63\x56\x14\x33\x75\x6d\xe2\x87\x33\x4c\x1e\xb3\x38\xb1\xef\xbd\x2f\x06\x0e\xe0\x67\xc6\xcc\x4d\x69\xbd\xf9\xae\x48\xf7\x0b\x76\xd6\x80\x97\x7e\xd8\xaa\x2a\x9a\x2c\x79\x40\xed\x5a\x56\xd5\xfa\x66\x5d\xfa\x84\x61\xb0\xc9\x66\xad\x81\xcf\x5f\x6f\x3a\xdf\x9d\x6c\xab\x69\x8f\xee\x31\x5d\xf3\xef\x0b\x11\x47\x2a\xd1\xa0\x6f\xde\xa2\xdf\x9c\xf7\x6e\xda\x7b\x36\x7d\x88\x7b\x92\x52\xbf\x79\x39\x70\xdb\xde\x4f\xd1\x43\xf3\x53\xf3\xf8\x31\xf0\xbb\x57\x5c\xd3\x7f\xc5\x4f\xc8\x58\x51\xab\xf4\x1a\x0f\xf8\xc6\x5f\x9a\x77\xaa\x2c\xc3\x32\x60\xfe\x71\xff\xd3\xe0\xf1\x60\x4c\xfa\x1e\x38\xff\x99\x59\x23\xf5\x5d\x7f\x0e\xff\xf8\xe7\xb3\x88\x87\xf3\x5f\xd3\x6a\xe8\xc7\xff\x0b\x00\x00\xff\xff\x2f\xcb\x27\x69\x0d\x5d\x00\x00"), }, + "/control-plane/crds/kuma.io_trafficlogs.yaml": &vfsgen۰CompressedFileInfo{ + name: "kuma.io_trafficlogs.yaml", + modTime: time.Date(2019, 9, 20, 12, 28, 51, 621240861, time.UTC), + uncompressedSize: 23401, + + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5c\xeb\x73\xdb\x48\x72\xff\xee\xbf\xa2\x4b\xf7\x41\x76\x15\x49\xdb\xbb\x77\xa9\x9c\xbe\x29\xb2\xf7\xa2\xac\x5f\x65\x69\x2f\x95\x8a\x53\xa9\x21\xd0\x20\xe7\x04\xce\x60\x67\x06\x92\xb8\x7f\x7d\xaa\xbb\x67\xf0\x20\x1e\xa4\xd6\xba\xad\xe0\x9b\x28\xa0\x31\xd3\xcf\x5f\x3f\x06\x2f\x96\xcb\xe5\x0b\x55\xe9\xbf\xa3\xf3\xda\x9a\x0b\x50\x95\xc6\xc7\x80\x86\xfe\xf2\xab\xbb\x7f\xf5\x2b\x6d\x5f\xdf\xbf\x5d\x63\x50\x6f\x5f\xdc\x69\x93\x5f\xc0\x55\xed\x83\xdd\x7d\x45\x6f\x6b\x97\xe1\x3b\x2c\xb4\xd1\x41\x5b\xf3\x62\x87\x41\xe5\x2a\xa8\x8b\x17\x00\x99\x43\x45\x3f\xde\xea\x1d\xfa\xa0\x76\xd5\x05\x98\xba\x2c\x5f\x00\x18\xb5\xc3\x0b\x08\x4e\x15\x85\xce\x4a\xbb\xf1\xab\xbb\x7a\xa7\x56\xda\xbe\xf0\x15\x66\xf4\xec\xc6\xd9\xba\xba\x80\xf4\xb3\x3c\xe2\xe9\x3f\x00\xb2\x84\x5b\x79\xfa\x83\xdd\xf0\x8f\x55\x59\x3b\x55\xf6\x88\xbe\x00\xf0\x99\xad\xf0\x02\xce\xce\x5e\x00\xdc\xab\x52\xe7\xbc\x20\x21\x63\x2b\x34\x97\x5f\xae\xff\xfe\xe3\x4d\xb6\xc5\x9d\x92\x1f\x01\x72\xf4\x99\xd3\x15\xdf\xd7\x79\x09\x68\x0f\x61\x8b\x20\x37\x43\x61\x1d\xff\xd9\x79\x1d\x5c\x7e\xb9\x8e\x34\x2a\x67\x2b\x74\x41\xa7\x15\xd3\xd5\xe1\x70\xf3\xdb\xc1\xdb\xce\x69\x39\x72\x0f\xe4\xc4\x53\x94\x77\xde\xcb\x6f\x98\x83\x97\xb7\xdb\x02\xc2\x56\x7b\x70\x58\x39\xf4\x68\x02\x6f\xab\x43\x16\xe8\x16\x65\xc0\xae\xff\x81\x59\x58\xc1\x0d\x3a\x22\x02\x7e\x6b\xeb\x32\x87\xcc\x9a\x7b\x74\x01\x1c\x66\x76\x63\xf4\x6f\x0d\x65\x0f\xc1\xf2\x2b\x4b\x15\xd0\x87\x1e\x45\x6d\x02\x3a\xa3\x4a\x62\x64\x8d\x0b\x50\x26\x87\x9d\xda\x83\x43\x7a\x07\xd4\xa6\x43\x8d\x6f\xf1\x2b\xf8\x68\x1d\x82\x36\x85\xbd\x80\x6d\x08\x95\xbf\x78\xfd\x7a\xa3\x43\xd2\xa9\xcc\xee\x76\xb5\xd1\x61\xff\x3a\xb3\x26\x38\xbd\xae\x83\x75\xfe\x75\x8e\xf7\x58\xbe\x56\x95\x5e\xf2\x3a\x4d\x60\x3d\xdc\xe5\x7f\x72\x51\xdf\xfc\x79\x67\x61\x61\x4f\x12\xf6\xc1\x69\xb3\x69\x7e\x66\x15\x99\x64\xf3\xcf\xda\xe4\x24\x4f\x15\x1f\x93\xe5\xb6\xdc\xa4\x9f\x88\x09\x5f\xdf\xdf\xdc\x42\x7a\x29\x73\xbc\xcf\x62\x66\x6e\xfb\x98\x6f\xf9\x4c\x7c\xd1\xa6\x40\x27\x72\x2a\x9c\xdd\x31\x45\x34\x79\x65\xb5\x09\xfc\x47\x56\x6a\x34\x7d\x1e\xfb\x7a\xbd\xd3\x81\x04\xfb\x6b\x8d\x3e\x90\x38\x56\x70\xa5\x8c\xb1\x01\xd6\x08\x75\x95\xab\x80\xf9\x0a\xae\x0d\x5c\xa9\x1d\x96\x57\xca\xe3\x73\x73\x99\x18\xea\x97\xc4\xc1\xe3\x7c\xee\x9a\x7b\xba\xc6\x94\x9f\x0d\x80\x76\xc1\x8a\x7a\xf0\x0f\x00\x95\xe7\xec\x3e\x54\xf9\x65\xe2\xe1\xc9\x15\x8c\x9a\x51\xfb\x26\x16\xb3\x81\xda\xf8\xe0\xea\x2c\xd4\x0e\x73\xb8\xc3\x7d\x94\xf8\x4e\x55\xe0\x83\xa5\x1f\x1f\x74\xd8\x0e\xde\xa8\xba\xd2\x57\x81\xc5\xba\x46\xf0\x18\x60\xbd\x07\x72\x92\x6c\x10\xc1\xda\x92\x2d\x87\x69\xb1\x61\x38\x0c\x4e\xe3\x3d\x0e\x49\xba\xb5\x0e\x4e\xb9\x7d\xc3\xbb\x15\xdc\x6e\x71\x0f\xca\x21\x90\x98\x7f\xad\xd1\xed\xd5\xba\x14\x3a\xd1\x60\xd7\x08\xac\x64\xee\x1e\xf3\x01\xc9\x87\x2d\x1a\xd8\xd9\x5c\x17\x7b\xd2\x5c\x51\xcb\xa1\xf1\x5d\xbc\x7e\x7d\x57\xaf\xd1\x19\x0c\xc8\x8a\x91\xdb\xcc\xbf\xae\x3d\xba\xe5\xa6\xd6\x39\xbe\xee\x08\xe8\xfc\xc5\x18\xeb\x85\x72\xef\x5f\x59\x59\xfb\x80\xee\x13\x39\xf4\x39\x99\xdc\x6e\x91\x5d\xb8\xb8\x2e\x4c\xcf\xc1\xc3\x56\x67\x5b\xfe\x25\x5a\xd3\x1a\x4b\x6b\x36\xa2\xf8\xb7\x87\x16\x47\x97\xf6\x50\x7b\xcc\x89\xdd\xb9\xf6\x64\xab\xb5\xf6\xdb\x46\x50\x9e\x25\x09\x9e\xde\xc5\x2f\x24\x2e\x72\xf0\xa8\x54\x46\xec\x80\x5c\x17\x05\xba\x43\xcb\xeb\x6c\xc6\xcb\x9b\xa1\xd0\x58\xb2\x9f\x20\xb1\x90\xcc\x95\xd9\x3f\x6c\xd1\x21\x38\xbd\xd9\x06\x30\xf6\x81\xa9\xab\x4a\xb3\x64\x1c\x8c\x2c\x77\x63\xd9\x9b\x58\xd0\x1b\xc3\xf2\x08\xa0\x0b\xa6\xa6\x8d\x44\x48\x04\xeb\xa2\x65\x27\xbb\x5f\x8d\xb2\x7f\x44\xf3\x87\x21\x76\x4e\x08\x67\x57\x87\xb7\x8b\x17\x0c\xcd\x9f\x03\x17\x28\x1b\x1b\x9a\xa2\xde\xa1\xe8\x1d\xfb\xb7\x28\xbb\x07\xe5\xe3\x96\xc8\x45\x85\xc4\xba\x4d\xad\x9c\x32\x01\x45\x68\x62\x3f\x43\xb1\x1a\xd8\xaa\xaa\x42\xe3\x97\x6b\x2c\x88\x53\xd6\xe5\xe8\x40\x65\xce\x7a\x0f\x1e\x2b\xe5\x98\x57\x15\x3a\xd1\xd1\x15\x5c\xb1\x03\x15\x6f\x6b\xec\x90\x26\x71\x99\xd7\xc7\xd6\x9e\x96\xd4\xec\x11\x73\x7a\xeb\xd7\x9f\xae\x7e\xfc\xf1\xc7\xbf\x52\x44\xdf\xb1\x38\xb5\xa7\x9f\x7f\xb9\xbd\x5a\xc1\x37\x33\xa0\xf9\xc5\x56\x35\x05\xc7\x9c\x3c\x00\x73\x68\xef\x03\xee\x56\xf0\x15\x55\xbe\xb4\xa6\xdc\xaf\xe0\x53\x5d\x96\x8c\x10\x4a\xed\x47\x0c\xf1\x3b\xfd\x73\xf2\x1b\x67\x07\x6b\xa3\x0d\xa8\x70\x01\xa4\x48\x4b\x12\xd0\xa9\x4a\x94\x63\x89\x44\xfd\x6f\x4e\x65\xf8\x05\x9d\xb6\xf9\x0d\x66\xd6\xe4\x03\x1f\xdc\xd3\xa6\x4f\xf5\x6e\x8d\x8e\x0c\xda\xcb\xdd\xa0\xca\xd2\x3e\x60\x1e\xc1\x51\xab\x17\xc1\xc2\x86\x68\x17\x75\x59\xee\x87\xba\x84\x6e\xa7\x0d\xc9\x36\x0a\x5e\x07\x78\xd0\x65\x49\x9a\xe2\x70\x67\xef\x89\x62\x0a\xa0\x89\xdb\x9f\x4d\xb9\x67\xf9\x92\x12\x0e\x48\xa6\x1d\xf5\xf5\xbc\xf4\x96\x1e\x59\xc1\x47\xb5\x07\x92\x14\xeb\xe2\xd6\xba\x80\x86\x34\xb6\x95\xe0\x04\x67\xb5\x09\xff\xf2\xe7\x51\xae\x12\x36\xda\x1c\xd8\xc9\x60\x11\xf3\xb6\xf9\x6e\x6c\xcd\x5f\x7f\xba\x02\xd6\x4e\xf6\x0e\xa4\x9d\x6c\x79\x2a\x34\x8e\x73\xc4\xe5\x34\x31\x2b\x71\x91\x57\x42\x3b\xec\xbb\xb5\x18\xc6\x5a\x33\x17\x8b\x56\x8d\xb0\x26\xf9\x2a\x66\xc4\xae\xaa\x35\x04\x8a\x24\x8b\x64\x41\x64\xf7\xb9\x76\x98\x05\x91\x53\xe0\x88\xb6\x1e\x4a\x5f\x45\x18\xc4\x51\xb0\x5d\xba\xf6\x80\x8f\x15\x66\xa1\x71\x1a\x71\x13\xf0\xd2\x58\xa0\x10\x81\x0e\xee\xb5\xd7\xeb\x72\x18\x63\x59\x5b\x1a\x52\x6c\x84\xb2\x30\x5a\x95\x43\x95\x6d\xe3\x6a\x38\x30\xbc\x02\x55\x04\x8c\x70\x9e\xb8\xab\x87\x0a\x15\x1a\xc6\x2d\xc0\x1a\x86\x03\x08\x85\x36\xaa\xd4\xbf\x11\xde\xa3\x77\xf0\x9a\x77\x55\xd8\xaf\xe0\xd2\xf3\x12\x41\xf9\x83\x1b\x07\x84\xf9\x41\xb2\x7b\xa5\x09\xac\x04\xdc\xf9\x45\x8f\xcd\xeb\xd2\x66\x77\x24\xbb\xcf\xe9\xb5\x03\xbd\x1a\x0b\x91\x1e\xc3\xa2\xe3\xfb\x92\x8b\x64\x10\x69\x48\xf0\xd6\x25\x24\x53\xd4\x2e\x6c\x29\x78\x99\x88\xfd\x8b\x9a\x70\xd2\x62\x28\xaa\x32\x6c\x6d\xbd\xd9\x92\x81\x26\x24\x94\xac\x07\x62\x3e\xd4\x70\x3d\xde\x90\xa4\x56\x39\x6d\x47\xc2\x88\x95\x35\x12\xdb\x57\xf0\x93\x75\x80\x8f\x6a\x57\x95\x94\x5d\xb0\x3e\xc5\x04\x83\x35\x4d\x20\x98\x82\xca\xb2\x86\x45\xca\x63\x81\xe4\xc7\x37\xc9\x25\x89\x56\xfd\x5c\xaf\xe9\x66\xb1\x07\x92\x3f\xeb\xbd\x47\x93\x53\x98\x6b\xf5\xbd\x71\x45\x87\xc9\x14\x5d\x5e\x6f\x04\xeb\x09\x7e\x11\x91\x91\xec\xb5\xe1\x5f\x2a\x9b\xaf\xe0\x32\x6a\x92\x0a\x9d\x45\x2c\xf8\xff\x71\x11\x43\xf4\x46\x8b\xa2\xb5\x80\x82\xad\x72\x79\x77\x11\xe9\xa5\x2f\x6f\xae\xff\xf6\xf3\xf5\x87\x0f\xaf\x06\xaf\x27\xb5\x1e\x0a\x8a\x57\x91\x95\xa8\x4c\x5d\x2d\xa2\x13\x4d\x8b\x6c\x7d\xe9\xe5\x97\x6b\xce\x24\xf8\x1f\x1c\x12\x33\xc6\x67\x06\xc3\x83\x75\x77\x03\xb2\x95\x72\x81\x61\xba\x5f\xf4\xdc\x3b\xc9\xc8\x07\xda\x06\x3e\x92\x3a\x27\x73\x8a\x82\x65\x1d\x5d\x40\x6d\x82\x1e\x7a\x14\x65\x40\xe5\x3b\x6d\xb4\x0f\x4e\x05\xeb\x48\x8f\x54\x1d\xec\x4e\x89\xd6\xd8\x0c\xbd\x87\x4c\x51\x42\x2c\x8c\xc1\xbe\x9e\x8d\xf8\x3f\x0e\x33\x6d\x58\x21\x2c\x52\x24\x0c\xb7\x68\x85\xdd\x58\x59\x84\xa4\x71\x37\x5b\x35\xa4\x28\x96\x83\xa6\x75\x7a\x84\x0d\xa6\xb0\xc0\xa1\x1b\x6d\xde\x34\x66\xa8\x1d\x8a\x1d\x04\xf1\xff\x1c\x31\xb4\x0e\x6d\x36\xa6\x7d\xac\x3d\x7b\x1c\xf6\x8a\x29\xba\x77\x58\xdd\x5a\x71\xab\x94\x0e\x37\xa4\x0b\x83\x18\x0c\xf0\x5e\x65\x5b\x40\x13\xdc\x3e\x26\x75\x3a\xa7\x3d\x16\x1a\x5d\x53\x8e\x71\xe8\x2b\x6b\x38\x2a\x40\x66\x77\x95\x35\x68\xa2\xe3\x20\x3b\x1b\x09\x95\x8d\x69\x08\xe5\x66\x1d\xe4\x98\x59\x71\x46\x5d\x6e\x5f\x67\xc6\xe4\x6a\xac\x59\x1a\x5d\x2e\x98\xae\xc6\xe8\x26\x74\x0c\x15\xa4\xd0\x09\x81\x44\x8c\x73\xb8\x61\x8e\x05\x4f\x4a\x82\xe5\x5f\xca\x39\xd5\x0f\xb3\x1b\x34\x84\x99\xf1\x68\x92\x76\xf6\xb7\xce\x9d\x91\xc9\xb6\x92\xc4\x9c\x3c\x44\xa1\x1f\x17\x92\x7c\xf5\x60\xc3\x30\x52\x10\xe0\x8b\xa4\xc8\x91\x1b\xfd\x6b\x1d\xb3\xb1\xcf\x9f\x3e\xfc\x17\x5c\xff\xc4\x4f\xf3\x5b\x04\x8d\x6c\x95\x6f\x8d\xac\x72\xf6\x5e\xe7\x43\x8e\x80\x88\xa3\x0b\x61\x68\x31\xe2\x5e\x99\xba\xc3\x50\x3b\x23\x90\xa1\xad\xb0\xb4\x38\x68\x32\xf3\x0b\x5b\x65\x5a\x32\x95\xf2\xbe\x81\x4b\x12\x3f\x99\x04\x23\xc8\x35\x6b\xd6\x5a\x9b\x58\x34\x68\x36\x38\x8c\x18\x75\x51\xe8\x47\x09\x41\x69\x4f\x91\xdc\x36\x22\x03\x4e\x53\xdb\xc2\x24\xb8\xba\x44\x9f\x60\x03\xf1\x67\xe8\xdc\x04\x84\xa4\xe2\xdb\x1a\x21\xb8\xda\x64\x5d\x2f\x54\xa2\xd9\x84\x6d\x52\x51\x59\x05\xfb\x19\xed\x98\x35\x03\x9a\x3b\x75\x27\x36\x20\x8b\x8b\xf2\xb2\xa6\x23\x63\xf6\x77\x03\xf6\xfb\x0a\x33\x32\xc0\x91\x10\x44\x50\x75\x8b\x8d\x1a\x48\x0e\x2e\x01\x22\x06\xc4\x84\x39\x89\xb3\x9f\x3e\xdf\x46\xe1\x81\x82\x3f\xbf\xf9\x2b\x2c\x47\xe2\xba\x0f\xa8\xf2\x45\x93\x1e\xa0\x66\xd8\x12\x1f\xfb\xe1\xcd\x5b\xb8\x92\xdc\x93\x62\xc8\x5f\xde\xbc\x11\xe9\x7c\x45\xe5\xad\x89\x85\x39\xb2\x5f\x5b\x8f\x25\x9f\xb9\xce\x54\x10\x34\xd0\x55\xd7\x8c\xab\x2f\x11\x38\x15\xb6\x36\x79\x0a\xf7\x82\xc3\xcb\xd2\x86\x80\xf9\x08\x56\x8a\xfb\x8f\x1a\x18\xcb\x38\x0e\xc9\xc7\xbc\x4c\x36\x55\xee\x87\xd0\x93\x17\xc2\x99\xe9\x88\x92\x22\x7c\x25\x0a\x4b\x81\x19\x5b\x54\x39\xba\x57\x2c\x9a\xcb\xaa\x2a\x35\x6d\x9d\x9c\x8a\x2e\x20\x59\x30\x87\xbd\x24\xa5\xa1\x41\x3d\x6f\x9c\xd1\x39\xee\x2a\x1b\xd0\x64\xfb\xc3\x50\x33\xe9\xb6\xa2\x82\x1c\x94\xc5\xe1\xd0\x35\x5d\x82\xa7\x40\x49\x08\xc5\x48\xde\xd9\x2b\x55\xa8\xb4\xc9\xac\x43\x10\x6c\x31\xca\xc3\x1c\x3d\x5b\x82\x0f\x2a\xe0\xea\x94\x8c\xfe\x59\xf2\x41\x6e\x91\x9c\x12\x36\xcf\x2e\x4d\xf7\x66\xa9\xd1\xb0\x04\x6c\x59\x36\x35\x33\x34\x85\xe5\x7a\x97\xb7\xbb\xb4\xe6\x11\xc5\xbe\x57\x4e\x2b\x13\x28\x65\x8c\x51\x37\xd5\x8c\x22\xea\xee\xe7\x84\x4a\xe2\x93\x2d\x7a\xcb\x1d\xf3\x97\x84\x94\xee\xa5\x64\xb9\xc7\x00\x8a\x53\x35\xdb\x2b\x08\x09\xf0\xd2\x25\x19\x24\x63\x80\x1e\x6e\x1c\x10\x25\xa7\xc8\x01\x80\x22\x37\xc1\x02\x52\xe5\x66\x15\x94\x02\x91\xc1\x3f\x68\x8f\x8b\x03\x14\x91\x51\xcc\xcf\xd1\x8d\x38\xa2\xda\x74\x48\xa4\xec\x74\xab\xf3\x1c\x0d\xbc\xd4\x86\xb7\xfb\xfa\x41\x85\x6c\xcb\xff\xdc\x20\x05\xe7\xb2\xf4\xaf\x04\x0a\x88\xfd\xce\x30\xc0\x9c\x07\xca\x54\x4b\x9d\x69\x4a\x75\x95\xbf\x93\xf0\x63\xd7\xec\xdf\x0e\xde\xdf\xd4\x66\x47\x2a\x4b\xff\xc9\xa8\xd1\x74\xb7\x25\xfe\x6c\xd1\xc3\x96\xe4\xfa\xaa\xa8\xb2\x1d\x44\x31\x5a\xbf\x66\x0f\x54\x3b\xc7\x2e\x08\x07\x62\x8d\x65\x94\xca\xe9\x7b\x5d\xe2\x06\x73\xce\xb9\xa4\x9e\x26\x39\xe2\x30\x54\x70\x99\xb9\x7d\x6f\xcc\x4b\x75\x9b\xfd\x2e\x52\x7a\x18\xbd\x26\x3f\x41\xae\x29\xe6\x99\x03\x92\xeb\x3d\x28\xb3\xe7\x57\xb3\x2b\x7b\xf7\xfe\xcb\xd7\xf7\x57\x97\xb7\xef\xdf\xc1\xb2\xb7\x5c\x2e\x91\x53\xc2\x50\x56\x5b\x15\x55\x96\x64\x36\x8a\xec\x3a\xc5\x23\x6d\xe0\xfe\xed\xea\xed\x5f\x56\x87\x4e\x69\xaa\x53\xc1\xff\x93\xec\x70\xf8\x8f\x03\x63\xfd\x12\xb3\xc8\x49\xdb\x89\x9d\x03\x82\xc2\xf8\x88\x59\x1d\x86\x31\x1d\x24\x6d\x95\x82\x67\x03\x93\xdb\x04\x8b\x50\x88\x94\x3a\x56\xa2\x25\xd2\xa1\xf3\x21\xad\x72\x82\x62\xcf\x85\x44\x6e\xa4\x42\x08\x14\x4a\x97\xb4\x70\x87\xbe\x2e\x43\xa7\x66\x80\xf3\xa6\x4f\x97\x34\x53\x1a\x5c\xc5\x75\x56\xcb\x96\x9e\xe2\xde\x98\x6d\x12\xae\xe9\x18\xc3\x28\x65\x7a\x3e\xee\x95\x48\xaa\xb2\x4c\x26\x38\x0c\x5e\x93\x18\xf9\x98\x6c\xe5\x32\x23\x70\xb8\xbd\x7a\x42\xee\x76\x2e\x52\x4e\xca\x62\x65\xbe\xb6\x29\x07\xa5\x21\xcd\x0e\xa7\xe4\x22\x57\xd7\x4d\x4e\xde\x36\x03\xf6\xe5\x4a\xa8\x6e\x7c\x1f\x4b\x5e\xf8\xe8\xbf\x26\x1b\x3a\xdd\x7f\x0f\x53\x09\x79\x27\x29\xcc\x51\xc3\xb8\x2e\xfa\xaa\x25\x70\x8c\x38\xf8\x93\xd2\x65\xed\x30\x41\xd9\x99\x3c\x0a\x52\x7d\x64\x8d\x50\xa1\xf3\xda\xc7\x7a\xa0\x0f\xd6\xa9\x0d\x26\x75\x33\x29\x8f\xa4\x74\xcb\xd7\x4e\xba\x17\x14\xf2\x46\x3d\x0e\x70\xaf\x47\x7a\x07\x9c\x89\x45\x5f\xdd\x4d\xf5\xc6\x84\x72\x4c\xa7\xc6\x5b\xfc\x93\x1c\x7a\x6a\xbb\x7f\x52\x4d\xfa\x63\x00\x4f\x6d\xfd\x4f\x92\x1d\x1d\x09\x78\xca\x18\xc0\x24\xe5\x3f\x70\x3c\xa0\x7b\x1d\x35\xa7\xcc\xe6\x93\x2e\xa1\x27\xba\x9b\x7a\xb3\x91\xe2\xf7\xbf\xdf\xde\x7e\x49\x39\x08\x3d\xde\x36\x3f\x08\x5e\xd6\x7e\x01\x6f\x40\x0f\x71\x68\xba\x62\x59\x6a\xca\x05\x74\x90\xe6\x8f\x3f\xcc\xee\x6a\x0c\x71\xb6\x4b\x0f\x4a\x97\x93\x8e\xb0\xb7\xb3\xf7\x8f\x01\x0d\x25\xaa\xb9\x0a\x0a\x94\xf7\x36\xd3\x0c\x8e\x1b\xf3\x75\x9c\x51\xad\xa4\x20\x33\xa3\x93\x9c\x77\x91\x66\x88\x6e\x83\x0e\x1e\xec\x83\xe1\xb6\xb9\xbc\x41\x96\x75\x00\x41\x27\x29\x36\x95\x88\x14\x63\x78\x85\x4d\xca\x3f\xda\x6c\xcc\x2c\xa1\xe4\x21\x2e\x6e\x78\x67\x19\x7b\x44\x3b\xc3\xc7\x0c\xab\x58\x2e\x92\x45\x37\x39\x41\xdc\x0e\xf1\x7a\x4a\x56\xc7\x23\x0e\x40\xa6\x6a\x3f\xf7\xff\x91\xae\xf9\x15\x3f\x22\xbe\x18\xb4\xc9\xca\x3a\x47\x0f\x3b\xb2\x9c\xc8\xc0\x8e\x94\x66\x08\x43\x2b\xc1\x1b\xd6\xcc\x98\x19\x17\xe2\x8d\x57\xf0\xc9\x06\x8e\xb7\xdd\xff\x32\x16\x9c\x25\x1a\x0b\x1b\x71\x2d\x98\xc7\x2d\x4e\xc7\xb4\xd9\xa8\xdd\xa1\x7a\x94\x97\x72\xb1\xda\x1c\xbb\xe9\x30\xc1\xba\xdd\xa6\xc2\x53\x0c\xea\xfd\x31\x0f\x4a\x44\x78\x1b\xf3\xfc\x94\x8b\x6d\x1d\x9d\xb3\x6e\x41\x00\x87\x22\x2e\x6b\x0d\xa9\xfb\x7f\xdc\x7c\xfe\x04\x1e\x1d\xe3\x01\x35\x15\x56\x0e\xaf\x8f\xad\xa0\x21\x27\xa1\x98\x1c\x2a\xeb\x43\xa1\x1f\x21\x4d\x68\xb0\x9b\x31\xec\x82\x4e\xa0\xa8\x82\xb8\x4f\xf2\xb9\x97\xa4\x48\x82\xa5\x7f\x43\x67\x97\xda\xe4\xf8\x48\xd9\x15\xfc\x44\x1c\x39\x2e\xf1\x48\xb2\xaa\x50\x39\xd1\x43\xae\x9e\x71\x5b\x4c\x73\x06\x23\xba\x6a\x8b\xa8\x0b\x90\x8f\x14\xc7\x46\x18\x69\x45\x26\x9e\xf2\x2a\x8a\xe0\xbb\xba\x0c\xba\x2a\x51\xb8\x4b\xd9\x4a\xf4\x00\x9c\x26\xbc\x97\x4e\xd1\x51\x05\xa1\xeb\x1b\xc0\xb7\x33\x92\xcc\xb7\x33\x58\xc6\x96\x1c\x49\xbf\xf9\x31\xd6\xba\x62\xae\x74\x02\xc5\x46\x61\x88\x32\x2b\xf4\x7f\xbf\xf9\x9f\xd5\xcc\x2b\x4e\xa0\x19\x17\x51\x68\xe7\x43\xe4\x61\x2c\x77\x9b\xf4\x92\x6f\x67\xc7\x09\x1d\x8d\x72\xed\xb5\x43\xef\xd5\x66\x06\x05\xa7\xeb\xa0\x16\xb3\xad\x77\xca\x2c\x1d\xaa\x9c\x1b\xa9\x9d\xff\x36\xf3\x3d\x24\xf9\x53\xf6\x2c\xb7\xb3\x84\x57\xd0\x8d\x04\xb1\xba\xd9\xce\x6a\x28\xbf\x9c\x89\x0e\x9d\xfd\x5b\x9e\xdb\x52\x39\xba\xe3\xd6\xf6\x04\x66\x49\x08\x78\x32\xaf\x76\x2a\xdb\x6a\x83\x73\xdc\x3a\x61\x53\xcc\xcf\x03\x6e\xa5\x72\xac\x54\x6d\x53\xfe\x4d\x77\xb8\x53\x48\x72\xc0\x64\xf4\x45\x18\x83\x56\xa3\xee\x95\x2e\x69\x8d\xcf\xc8\xb7\x23\x89\x46\xff\xb6\xf1\x84\x23\x5d\x32\x13\xfc\x94\xd8\xc9\x4f\xb4\xde\x6f\xe0\xed\x9f\x1a\x38\x05\xd2\xf5\x22\xe4\x1c\xab\x4e\x62\xd2\xe1\xa8\xea\xec\xa6\xce\x69\x57\xf4\xc4\x3f\x79\x53\xf0\xd9\x48\x5d\xb1\x1d\xb7\x12\x28\xc7\x1d\x94\x59\xba\x9d\x4e\x5e\x1a\x10\x69\x96\xf6\xb3\x36\xf9\x1f\x34\xae\xfa\xbb\x64\x31\x5f\x12\x98\x1a\x69\xfc\xa7\x8a\x02\x5e\xc6\x31\x3b\x74\x18\x67\x96\xb5\xd9\x94\x38\x9d\xda\x37\x54\xb9\x4c\x4c\xf9\xed\x3a\x39\x9d\x35\xe6\xaf\xbe\x5b\x61\xb9\x89\xc1\x1d\x88\x89\x29\xb1\x49\x8e\x5d\x17\x6d\x2f\x62\xd1\x6d\x7a\x34\x13\x64\x6d\x8f\x78\x76\x6b\x8d\x56\x76\xe6\x63\x65\xe2\x36\x5f\xc1\x0d\xe9\xad\x40\x86\x38\x87\x2d\x3d\x95\x79\x37\xd5\xf6\x6a\xb8\x54\x17\xd4\x5d\xac\x35\x72\xb6\x1b\x10\x54\xc6\x2f\x5c\xc6\x04\xcf\xfa\xf4\x92\x23\x74\x7b\x01\x2d\xad\x05\xb6\xf6\x41\x46\x84\x82\x85\x07\xa5\x43\xb3\x73\x75\x77\xd4\xa3\x6e\x71\xb0\xac\x39\xa1\x9e\x92\x43\xc2\x49\x79\x24\x5d\xb5\x7e\x82\xb7\xfa\xe5\xfa\xdd\xa1\x4d\xac\xa6\x14\x7a\x76\xcf\xed\x48\xdb\x84\x52\x3f\x79\xd8\xb9\x1d\x1e\xf0\x7f\xaa\xf5\x77\xfb\x8e\xa3\x61\x6e\xce\xcd\x3f\xc3\xe9\x84\xe9\x0c\xb7\x53\x47\xfe\x3d\x27\x15\x66\x08\xb7\xdd\xcd\xdf\x73\x6a\x61\x92\xf0\x1f\x1e\x1e\x8e\x8a\xf7\x08\x4c\x7e\x32\x38\x8e\x6e\xfe\x58\x59\xaf\xf1\x72\x53\xbc\x3a\x61\xe1\xc3\xe3\x19\x93\x2b\x3f\xbf\x09\xca\xe4\xca\xe5\xd2\xc6\x68\x8f\x27\xfc\xe1\x02\x39\xa9\x92\x62\xc9\x12\xea\xd3\xc3\x75\x7a\xa0\x7b\x88\x43\x17\xcd\xe4\xaa\x0c\xf8\x43\xa9\x77\x7a\x3e\xff\x8b\x59\x9a\x69\xa6\x9f\x39\x31\x6b\xea\x50\x71\x02\x36\xfa\xf9\xd8\x26\x38\x16\xcf\xe2\x28\xc4\x56\xa5\xc2\x0e\xd7\xde\x1a\x34\xce\x50\xa3\x41\xf9\xb6\x52\xbf\xd6\x38\x3a\xf8\xd7\xbd\xe2\x36\xd3\x59\x09\xed\x3d\x3f\x64\xe3\xd0\x44\x1c\xa9\xb4\x87\xc7\x92\xd4\xfc\xee\xe5\x08\x4a\xa7\xef\x18\x6c\x73\xd6\x45\xf8\x82\x8f\x4d\xaf\xb1\xd9\xc1\x3c\x43\x53\x4f\xf4\x4a\x24\x24\xfd\x7c\x6e\x1b\xf9\x40\xee\x45\xd4\xb1\xed\x28\x56\xd6\x8f\xcf\xfd\x76\xaf\x28\xda\xc8\xd9\xcc\x9a\x42\x6f\xea\x08\x1a\xb8\xbe\xb3\x55\x66\x23\xb3\x22\x6d\x0d\x43\xcd\x23\x5b\x7c\x80\x9d\x36\x35\x89\x95\x7b\xdf\xed\x9c\x50\x1b\xdf\x52\x41\x5f\x62\x7e\xd2\x8a\x23\x40\x0d\x0d\xd4\x5e\xfc\xba\x74\xcc\x44\x53\x3b\xa3\x47\x6b\x8c\xe3\x6e\x59\x33\x83\x3a\x4b\x33\x6a\x4b\xb7\xa2\x10\x1b\x55\xb8\x80\xda\x94\xe8\x3d\xec\x6d\x2d\xfb\x70\x98\xa1\x1e\x3b\x59\xd4\xbd\x64\x9e\xd3\xde\xa1\x91\x20\xa1\x8c\xe0\x9f\xe4\x1d\x9f\x01\x57\xf6\x38\x78\x3a\xca\xb8\x09\x6d\xc3\xa7\x09\xeb\xbe\x23\xfe\xf3\x73\xdf\xb4\x2d\xe6\xb9\x16\x85\x97\xce\x57\xa6\xf3\x0b\x44\x39\x62\x8e\x34\xfe\x96\xfa\x47\x23\xe3\x54\xfd\x95\xa6\xa9\x55\x96\x72\xd4\x75\x61\x7b\x54\xc1\x15\xfc\x5d\x46\xb4\xe3\xb4\x64\x90\xae\xff\x2c\x59\xd5\xb8\x81\xce\x52\xb8\x4e\xc8\x2a\x09\xb5\x69\xda\xee\x6b\x95\xdd\x9d\xa2\x31\x69\xce\xeb\x94\x03\x2e\x6d\x44\x98\x25\xf9\x0c\xd1\x22\xb3\x46\x8a\x72\xd9\x7e\x19\x47\x60\x96\xca\xe4\xcb\xc6\x3d\x64\xfb\xef\xce\xfa\x3c\x96\xc5\x07\x6d\xee\x4e\xd6\xb8\xf4\x80\xa0\xb4\x5f\xbe\x7e\x38\x04\x67\x27\xb4\x76\xe1\xb4\xb3\x44\xff\x64\x54\x3a\x5f\xd3\x7a\x62\x25\xeb\x61\x1b\x07\x43\x1a\xe0\x32\xb9\x7a\xdd\x8c\xcd\x9f\xc5\x6e\xf0\x59\x44\x45\xf3\x65\xad\xb9\xfe\xd0\x64\x31\x0b\x2e\xd3\x14\x60\x56\x2a\x27\xce\x41\x19\xe9\xdc\xc9\x4b\x67\x50\x46\x8e\xb0\xae\x03\xe4\x16\xa5\xbf\x64\xef\xd1\x39\x9d\x23\xe8\x49\xe1\x1e\x11\xcc\x8c\x50\xa6\xda\xf9\xcb\x89\x41\x8f\x49\x52\xa5\x5a\xe3\xb0\xe1\xf7\xcc\xc7\x6c\x3f\x2a\x9e\x83\x8e\x59\xca\x1d\xee\xc5\x05\x49\x73\x77\xe8\x34\x83\x05\xeb\x36\xca\xe8\xdf\x46\x4e\xc5\x9a\x1c\x08\x2f\x6d\xac\xd3\xbf\x21\xbc\xe4\x73\xfb\x72\x00\x16\x4b\xcc\xc2\xab\xce\xa9\x56\xb5\x87\x1d\xcf\x6b\xc9\xbf\x28\xcd\x1f\x19\xf4\x73\x58\x95\x3c\xd3\x49\x62\x6f\x66\xe7\x7c\xa4\xe9\xee\x75\x36\xd2\x80\x3e\x9a\x35\x0a\x5f\x4f\x3e\x1d\xbb\x53\x46\x6d\x30\x97\xc6\xca\xfc\xcc\xdf\xc7\xee\xad\xb0\x53\x95\x87\x07\xeb\xee\x8a\xd2\x3e\x2c\xb5\xcc\x39\xa5\xe8\x14\x41\xdb\xd8\x29\x4a\x5b\xa4\x1e\x8a\x1c\x96\x71\x98\xd6\x20\x2e\x46\x85\x86\x6a\x6c\xbb\x6a\x82\x9c\x3e\x94\xfb\x38\xbc\x32\x11\x25\xb7\xb6\xf6\x78\x87\x58\x69\xb3\x11\x88\x2b\xa3\x62\x61\x5f\x11\x24\x29\xf7\xb1\x12\x63\xce\x03\x98\xd8\x7c\x8d\xc7\x8c\x6a\x93\xa3\xf3\x61\x0c\xaf\xb6\xd5\x11\x32\xd2\xb4\xb2\xa4\x35\x09\x9a\x9f\x4b\x57\x6d\xd1\x9b\x82\x4c\x3f\x0e\x59\xe0\xda\x41\x6e\xc2\xa0\xed\x64\xa8\xaa\xaa\x72\x0f\x95\x0a\x5b\x28\xf5\x1d\xc2\xb7\xb3\x4c\x2f\xb3\xfc\xdb\x99\x20\xb8\x08\x5a\x85\x7f\x03\xb2\x7c\x80\xf0\x41\xed\x1b\xc7\xd5\x48\x23\x02\xfc\x76\xf9\xac\xed\x07\x87\xb2\xc7\xa2\x6f\x9a\xd0\xf8\x66\x0e\x87\x30\x79\xc0\x4d\x6c\x82\x39\xd1\x01\xab\x69\xa8\xed\x41\x87\xed\xd8\x28\xb3\xb1\x41\x67\x38\x18\x75\x9b\xe8\xb9\xce\x67\x5a\xc7\xe6\x59\xfa\xf1\x61\x76\x98\xa5\xf3\xc9\x8a\x4e\xa7\x75\xca\x81\xb6\xdc\xe0\xac\x8c\x67\x9b\xd3\x91\x70\x8c\x05\x2d\x62\xd4\x19\x17\xf8\x5f\xc7\x77\x9c\xc1\x3f\x6a\x3f\x45\x93\x25\xce\x25\x47\x5b\x2d\x4b\x82\x1b\xdd\x15\x47\x1d\x8c\x67\x96\x31\x23\x48\xeb\xf6\x6c\x69\x4e\x65\xc3\xa3\x50\x69\x9d\xbd\xfd\xa9\xce\x9a\xd7\x28\x1d\x1b\xcd\x3e\x30\x26\x2e\xf1\x60\x93\x18\xcc\x04\xcd\x38\x9f\x33\x36\xac\x0d\xc7\x63\x4b\x31\xea\x69\xe4\x1a\xf5\xfe\x10\xdc\x44\x73\xb6\x27\xdc\xe8\x96\x3a\xe8\x5a\xf5\xed\x65\x6e\xb5\x93\xf8\x43\x5c\x93\x3b\x41\xb9\xc4\x3b\xba\xe1\xc1\x9f\x58\x51\x69\x6c\x8f\x49\xce\x00\xa2\x2d\x7a\x3c\x61\xc9\x93\x0c\x6e\xa0\xcd\x09\x8b\xfe\xdc\x54\xa9\xe3\xb7\x63\x88\x36\xad\xb8\x2d\x5f\x4b\x39\xb3\x44\x35\x7a\x2e\x23\xad\x59\x7b\xe8\x85\x87\xf7\xdc\x15\x5e\x23\x39\x96\xe6\xbc\x3d\x59\x06\x4f\xff\xf3\x71\x92\x18\x85\x27\x48\x36\x33\x4a\x71\x88\xd6\x21\x9c\x5f\x92\x77\x3c\x67\xaf\x73\xfe\x0b\x57\xec\xce\x7f\x17\x87\x82\x9e\xea\xa1\xf4\xbb\x27\x5a\x0e\x28\x84\xee\x91\xaa\x54\x19\x6e\x64\x04\x0f\x04\xfa\x66\x06\xa4\xae\x9b\xb3\x15\xd1\x3b\x37\xc7\xcd\x74\xd1\x17\x40\xdc\xe0\x28\x9d\x63\x07\xe1\x4e\xd8\xf8\x8c\xaa\x4f\xf5\x36\xc7\xba\x4d\x7d\x84\xc5\xa7\x38\x52\x5e\x18\xcf\xa5\x90\xe3\xd7\x06\x54\xfb\x51\x8b\x15\x5c\xfb\xf6\x7c\xcf\xe8\x81\x78\x99\xf9\x97\x69\x5f\x99\x91\x5b\xb4\xc7\x79\xb9\xd1\xd7\x7e\x3f\x63\xa7\xf6\x72\x92\xbf\x39\x9b\x3d\xa6\x9b\xed\xa1\x5c\xec\x1f\xb9\xe0\xae\x49\x45\x81\xc5\x69\x15\x52\x8b\xac\xeb\xf9\x56\xe3\x27\x9b\xb4\x87\xca\xe9\x9d\x72\x9a\xe7\xfe\xe3\x90\x18\xa9\x6a\x73\x62\xa1\x3d\x60\x22\xe0\xb0\x5f\xd6\xc9\x9b\xcf\x50\x0d\xb5\x65\xa4\x1a\xfd\x3d\x1d\x03\xe6\xfd\x38\x0c\x1c\xd1\x8f\x46\x52\xf3\x10\xf0\x53\xf3\x95\x92\x6e\x00\x95\x5f\xa2\xd4\x51\x65\x5b\xe1\x68\x5f\x2b\x86\x1b\xbe\x34\xd1\x0e\x3a\xdf\x3e\xf1\x40\x4a\x72\xaf\x4a\x91\x29\x93\xff\x76\x96\x63\xa1\xea\x32\x7c\x3b\x6b\x6f\x5d\x50\xce\x33\x20\xd9\xbd\x35\x7a\xb4\x4c\x19\x6b\xb8\x26\xd5\x9f\x41\x6d\xa7\xc9\x52\xc5\x83\x7c\x4c\xd2\xd1\xa1\xf1\xc8\x67\x41\x08\xf4\xe7\x32\xbf\xd1\xae\x7a\xd9\x39\x99\x66\x7b\x07\xd0\xda\x46\x5c\x7c\xc9\x80\x6e\x2a\x9d\xc5\x63\xf9\xdf\x4c\x73\x24\x55\xc1\xbb\x4f\x37\xff\xfb\xe1\xf2\xdf\xde\x7f\x18\x6d\x55\xcc\x54\x38\x4e\x52\x96\x66\xfd\xfe\xe4\x93\x50\xf6\xc1\xa0\xfb\x8a\x7c\x42\x31\x1b\x02\xb2\x9e\xae\x7c\x88\x07\x0d\x12\x77\x73\xac\xc4\x5c\xd6\xfb\xc1\x01\x9c\xcb\x0f\x1f\x26\x19\x14\xb1\x2c\x57\x58\xb9\x26\xc5\xe7\x6f\x9a\x61\xea\xde\xc7\x5d\x22\x2f\x37\xca\xad\xd5\x06\x21\x23\x18\x9e\x8d\x02\x95\xeb\xe2\xf0\xf8\x42\x27\x09\xe9\x82\xf8\x85\x0c\x6f\x2b\xd3\x0e\x3a\x35\x95\xe5\x71\x61\xc6\x32\xb5\x6d\x2b\xa5\x89\x52\xd3\x44\xef\x9c\x94\x6a\xf1\x18\x23\xb9\x31\x3b\xb9\xe5\xb2\x42\x8b\xd1\xba\x03\x6d\xd8\xc0\x89\x0e\xd1\x13\xcf\xe9\x3e\x2f\xb2\xee\xc3\x68\xb2\x24\x39\xc8\xfa\xbb\x22\x34\x7f\x52\xe2\x33\x69\x5b\xfa\xe6\xc8\x09\x8b\x20\x99\xba\x1a\x17\x70\xf9\xe9\x5d\x2a\xae\xb3\xc6\x36\x67\x59\xcf\x0a\xeb\x90\x00\xb9\xc9\x13\xdd\xa9\x61\xb5\xe6\xfc\x78\x54\x80\x96\x58\x2b\x88\xc1\xc9\xf0\x3b\xdc\x2f\xd9\x0d\x4c\x10\x95\x8f\x6f\xf1\x67\x06\x52\xaa\x11\x6d\xa9\x73\xfc\x65\x05\xef\xc4\x87\xf1\x58\x7b\xa1\x4a\x8f\x2b\xb8\x9d\x82\x5e\xcd\x07\x84\xd2\xa9\x5b\x69\x15\x51\x82\xeb\xe1\x4c\x56\x78\x06\x15\xba\x9d\xf6\x5d\xf1\xf0\x5e\x86\xa9\xa9\x5c\x36\x9d\x62\x83\x3f\xff\xf0\x03\xbc\xfc\xc5\xc4\x13\x25\x5c\x52\x7b\x6f\x82\x0e\xfb\x57\x9d\x0f\xe0\x48\x03\x61\x4e\xd0\x6b\x6b\x4b\x54\x63\xc5\xb6\x56\x6b\x9f\x22\xe1\x03\xe6\xb1\xc9\x35\xa7\x00\x4e\xb0\x88\xd3\xd6\x36\xdd\x10\x1f\x69\x87\x1f\xaa\xfd\x1f\xdd\x93\x3c\x62\x51\xd3\x73\x43\x23\x78\xee\xd8\x5e\xbe\x1f\x88\x9c\xb4\xe6\xc9\x41\x8e\x99\x11\x8e\xe7\x58\xf1\xf4\xb0\xc5\xec\x82\xa7\x4f\x3a\x2d\x3b\xde\x74\xe4\x9f\x24\xd5\x91\x9f\x47\xc7\xa7\x96\xc4\x95\xe7\x80\xf6\x47\x7a\x59\x83\xe3\xbe\xb1\x99\x23\x28\x87\x2b\x4a\xed\xac\x46\x3c\x92\x97\x4e\xdd\x34\x81\x60\xbc\x9a\x76\x52\xcb\x6a\xa2\x2d\x35\x84\x3a\xbd\x36\xd5\xc7\x4e\x47\x99\xb0\x97\xad\x82\xde\x69\x1f\x74\x06\x9d\x36\xcd\x22\x3e\xc0\xef\xe0\xe1\xa4\xe9\xd3\xf1\x72\xee\xb6\x4d\x87\xad\xe9\x7e\x72\xd1\xba\x54\x63\x68\x92\x93\xe6\x9b\x6f\x03\x92\x32\xb5\x45\x89\x42\x4c\x20\x63\x19\x5a\x75\x1b\xe6\x4f\x6c\x8f\xa5\x96\x18\x7f\x9f\x71\xd7\xf9\x68\x98\xa4\xd8\xc4\x03\x25\x5f\xc5\xc9\xea\x52\xb9\x91\x95\x8f\xa8\x71\xb3\x93\xe9\x0f\xc8\xf4\x7a\x6d\xa7\x35\x07\x27\x1b\x82\xcf\xed\x2a\x4f\x68\xc8\x9d\x8c\x78\xa7\x1a\x6f\xfd\xa3\x56\xa7\x37\xdb\x7a\xfc\x1c\x31\x8f\x13\x1a\x6c\x93\x6b\x1d\x71\x97\x7d\x2b\x26\x47\x19\xb3\xa2\x98\xa9\x6b\x13\xbf\x12\x61\xf2\x98\xc5\x89\x7d\x1f\x7c\x1e\x6f\x04\x3f\x33\x66\x6e\x4b\xeb\xed\x47\x34\xfa\x9f\x6b\xb3\x06\x7c\x9d\x11\x76\x28\xea\xb2\xcd\x92\x47\xd4\xae\x63\x55\x9d\x0f\xb4\xa5\xef\xf5\x05\x9b\x6c\xd6\x1a\xf8\xf2\xcb\x6d\xef\x23\x8b\x5d\x35\x1d\xd0\x3d\xa5\x45\xfc\xfb\x42\xc4\x89\x4a\x34\xea\x9b\x77\xe8\xb7\x17\x83\x9b\x0e\x9e\x4d\x5f\x9a\x9e\xa1\x74\xf0\x53\x74\xbd\x0c\xe8\x97\xf1\x1b\xd6\xf7\x6f\xb9\x58\xff\x96\x9f\x90\xe1\x98\x4e\x4d\x35\x1e\x53\x8d\xbf\xfc\x5f\x00\x00\x00\xff\xff\x2e\xae\x3b\x78\x69\x5b\x00\x00"), + }, "/control-plane/crds/kuma.io_trafficpermissions.yaml": &vfsgen۰CompressedFileInfo{ name: "kuma.io_trafficpermissions.yaml", modTime: time.Date(2019, 9, 10, 9, 59, 52, 147143742, time.UTC), @@ -68,7 +75,7 @@ var Templates = func() http.FileSystem { }, "/control-plane/kuma-cp": &vfsgen۰DirInfo{ name: "kuma-cp", - modTime: time.Date(2019, 9, 10, 9, 59, 52, 73934267, time.UTC), + modTime: time.Date(2019, 9, 20, 12, 28, 51, 569596824, time.UTC), }, "/control-plane/kuma-cp/app.yaml": &vfsgen۰CompressedFileInfo{ name: "app.yaml", @@ -79,10 +86,10 @@ var Templates = func() http.FileSystem { }, "/control-plane/kuma-cp/rbac.yaml": &vfsgen۰CompressedFileInfo{ name: "rbac.yaml", - modTime: time.Date(2019, 9, 10, 9, 59, 52, 73992002, time.UTC), - uncompressedSize: 1687, + modTime: time.Date(2019, 9, 20, 12, 28, 51, 569735482, time.UTC), + uncompressedSize: 1777, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x54\x41\x8f\xd3\x4c\x0c\xbd\xe7\x57\x58\xfb\x9d\x93\xd5\x77\x5b\xe5\x06\x1c\xb8\x20\x0e\xbb\x88\xbb\x3b\x71\x5b\x93\xc9\xcc\xc8\xf6\x64\x81\xd5\xfe\x77\x34\x49\x8b\x28\x81\x92\x16\x24\x38\xc5\x13\x8f\xfd\x9e\xad\xf7\xa6\xaa\xeb\xba\xc2\xc4\xef\x49\x94\x63\x68\x41\x36\xe8\x1a\xcc\xb6\x8f\xc2\x9f\xd1\x38\x86\xa6\xbf\xd3\x86\xe3\xed\xf8\x7f\xd5\x73\xe8\x5a\x78\xe5\xb3\x1a\xc9\x7d\xf4\x54\x0d\x64\xd8\xa1\x61\x5b\x01\x04\x1c\xa8\x85\x3e\x0f\xd8\xba\x18\x4c\xa2\xaf\x93\xc7\x40\x95\x64\x4f\xda\x56\x35\x60\xe2\xd7\x12\x73\xd2\x72\xbd\x86\x9b\x9b\x0a\x40\x48\x63\x16\x47\x87\x7f\x29\x76\x3a\x05\x4a\x32\xb2\xa3\x72\x18\x49\x36\x87\xf4\x8e\x6c\xfa\x7a\xd6\x39\x78\x44\x73\xfb\x65\xeb\xc2\xa2\xe1\xb8\xec\x5f\xc8\x4e\xac\xf4\xf4\xc8\x41\x79\xb7\xb7\xf9\xef\x40\xba\x5f\x89\x5c\x22\x27\x84\x46\x53\x98\x53\x77\x0c\xd3\xd7\x7c\x47\x9e\x8c\x2e\x20\x99\x24\x7e\xfc\x64\x34\x24\x8f\xf6\xef\xf0\xb8\x55\x43\xcb\x3f\xa1\xb3\x00\x5c\x8f\x62\x82\xdb\x2d\xbb\x44\x32\xb0\x16\x15\xae\x9b\xf8\x3f\x18\xd1\x73\x41\x85\xfe\x4e\xc1\x62\x4f\x01\x36\xb4\x8d\x42\xc0\xaa\x99\x38\xec\x60\x78\xf7\xe6\x01\x1c\x89\x2d\xf9\x14\x91\x53\x30\x76\xdf\xaa\xfc\x07\xec\x4a\x5f\xa1\x91\xe9\xf1\x3b\x5e\x87\x75\xff\x9e\x83\x5e\x72\xe8\x38\xec\x56\x1a\x29\x7a\xba\xa7\x6d\xb9\x73\x1c\xe6\x0c\x5e\x05\xb0\x34\xec\x99\xee\x9a\x37\x1f\xc8\xd9\xe4\xd4\xb9\xf0\x61\xf6\xe0\x0b\xe7\x62\x0e\x76\x52\x5b\x9f\xd6\xce\x29\x4d\xe8\xa8\x85\xa7\x27\x68\xde\x1e\x8f\xf0\xfc\x7c\xcd\x8a\xd6\xbf\x2e\xe7\xa1\x2f\x79\x7b\x94\x9c\x90\xfd\x79\xbf\x5d\x37\xfd\x45\xca\xf8\xc5\x12\xae\xd3\xcd\xdf\x13\xcc\x97\x00\x00\x00\xff\xff\x91\x58\x4c\x36\x97\x06\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x54\xc1\x8e\xd4\x30\x0c\xbd\xe7\x2b\xac\xe5\xdc\xae\xb8\xad\x7a\x03\x0e\x5c\x10\x87\x5d\xc4\x3d\x93\x7a\x3a\xa6\x69\x12\xd9\x4e\x17\x58\xed\xbf\xa3\xb4\x33\x88\xa1\x30\x74\x86\x91\xe0\x54\xbb\x8e\xfd\x9e\x13\x3f\x9b\xaa\xaa\x8c\x4d\xf4\x11\x59\x28\x86\x06\x78\x63\x5d\x6d\xb3\xee\x22\xd3\x57\xab\x14\x43\xdd\xdf\x49\x4d\xf1\x76\x7c\x69\x7a\x0a\x6d\x03\x6f\x7c\x16\x45\xbe\x8f\x1e\xcd\x80\x6a\x5b\xab\xb6\x31\x00\xc1\x0e\xd8\x40\x9f\x07\xdb\xb8\x18\x94\xa3\xaf\x92\xb7\x01\x0d\x67\x8f\xd2\x98\x0a\x6c\xa2\xb7\x1c\x73\x92\x72\xbc\x82\x9b\x1b\x03\xc0\x28\x31\xb3\xc3\xfd\xbf\x14\x5b\x99\x0c\x41\x1e\xc9\x61\x71\x46\xe4\xcd\x3e\xdc\xa1\x4e\x5f\x4f\x32\x1b\x8f\x56\xdd\x6e\x59\xba\xb0\xa8\x29\x2e\xeb\x17\xb2\x13\x2b\x39\x76\x29\x08\x75\x3b\x9d\xff\x0e\x28\xbb\x95\xc8\xc5\x72\x8c\x56\x71\x32\x73\x6a\x0f\x66\xfa\x1e\x6f\xd1\xa3\xe2\x19\x24\x13\xc7\xcf\x5f\x14\x87\xe4\xad\xfe\x3f\x3c\x6e\x45\xad\xe6\xdf\xd0\x59\x00\xae\x47\x51\xb6\xdb\x2d\xb9\x84\x3c\x90\x94\x29\xbc\xf6\x9b\xef\x01\x7c\xec\xd6\x55\x7e\x01\xa3\xf5\x54\xfa\x81\xfe\x4e\x40\x63\x8f\x01\x36\xb8\x8d\x8c\x40\x22\x19\x29\x74\x30\x7c\x78\xf7\x00\x0e\x59\x97\x44\x8a\x7c\x30\x28\xb9\x1f\xf5\xf3\x0b\x5a\xa5\x2e\xe3\x48\xf8\xf8\x13\xaf\xfd\x43\xfe\x9d\x36\x5f\x53\x68\x29\x74\x2b\x25\x1a\x3d\xde\xe3\xb6\x9c\x39\x34\x73\x02\xcf\x00\x2c\x57\xc1\x89\xea\x92\x37\x9f\xd0\xe9\xb4\x03\xe6\xc4\x87\x59\xdd\xaf\x9c\x8b\x39\xe8\x51\x6e\x75\x9c\x3b\x87\x24\x59\x87\x0d\x3c\x3d\x41\xfd\xfe\xe0\xc2\xf3\xf3\x25\x57\xb4\x7e\x6f\x9d\x86\x3e\x67\xab\x09\x3a\x46\xbd\xbe\x92\x2f\xeb\xfe\xac\xc9\xf8\xc3\x25\x5c\x36\x37\xff\x6e\x60\xbe\x05\x00\x00\xff\xff\x8d\xe5\x47\xee\xf1\x06\x00\x00"), }, "/control-plane/kuma-injector": &vfsgen۰DirInfo{ name: "kuma-injector", @@ -115,6 +122,7 @@ var Templates = func() http.FileSystem { fs["/control-plane/crds/kuma.io_dataplanes.yaml"].(os.FileInfo), fs["/control-plane/crds/kuma.io_meshes.yaml"].(os.FileInfo), fs["/control-plane/crds/kuma.io_proxytemplates.yaml"].(os.FileInfo), + fs["/control-plane/crds/kuma.io_trafficlogs.yaml"].(os.FileInfo), fs["/control-plane/crds/kuma.io_trafficpermissions.yaml"].(os.FileInfo), } fs["/control-plane/kuma-cp"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/app/kumactl/pkg/install/universal/control-plane/postgres/schema_vfsdata.go b/app/kumactl/pkg/install/universal/control-plane/postgres/schema_vfsdata.go index 4b03aeb76269..26dcba938e37 100644 --- a/app/kumactl/pkg/install/universal/control-plane/postgres/schema_vfsdata.go +++ b/app/kumactl/pkg/install/universal/control-plane/postgres/schema_vfsdata.go @@ -21,11 +21,11 @@ var Schema = func() http.FileSystem { fs := vfsgen۰FS{ "/": &vfsgen۰DirInfo{ name: "/", - modTime: time.Date(2019, 9, 10, 18, 34, 23, 778284305, time.UTC), + modTime: time.Date(2019, 9, 20, 12, 28, 17, 9931543, time.UTC), }, "/resource.sql": &vfsgen۰CompressedFileInfo{ name: "resource.sql", - modTime: time.Date(2019, 9, 10, 18, 34, 23, 777829185, time.UTC), + modTime: time.Date(2019, 9, 20, 12, 28, 17, 9974172, time.UTC), uncompressedSize: 299, compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x8e\x4f\x0b\x82\x40\x10\x47\xef\x7e\x8a\xdf\x51\x61\x0f\x76\xee\x64\xb1\x81\x64\x16\xba\x41\x1e\x97\x65\x48\x0f\xea\xb2\xb3\x49\x7d\xfb\x68\xfb\x07\x1d\xc2\x39\x0e\x6f\xde\xbc\x75\x25\x33\x25\xa1\xb2\x55\x21\x91\x6f\x50\xee\x15\xe4\x29\xaf\x55\x0d\x47\x3c\x5e\x9c\x21\x46\x1c\x01\xc0\xa0\x7b\xc2\x6b\x26\xed\x4c\xab\x5d\xbc\x48\xd3\x24\xdc\x94\xc7\xa2\x10\x1f\x8c\xad\x36\xf4\x1f\xeb\x89\xdb\x19\x36\x7f\xb3\x73\x9e\x4e\xe4\xb8\x1b\x87\x80\x75\x83\xa7\x33\xb9\x1f\x82\x2d\x99\xb7\xc8\xd3\xd5\x3f\xb7\x87\x2a\xdf\x65\x55\x83\xad\x6c\x10\x3f\xca\xc5\xb7\x5f\x84\x46\x11\x12\x92\x28\x59\xde\x03\x00\x00\xff\xff\x88\x1c\x8d\x52\x2b\x01\x00\x00"), diff --git a/docs/cmd/kumactl/HELP.md b/docs/cmd/kumactl/HELP.md index 8683b10515e2..cf761995ead5 100644 --- a/docs/cmd/kumactl/HELP.md +++ b/docs/cmd/kumactl/HELP.md @@ -272,6 +272,7 @@ Available Commands: dataplanes Show Dataplanes meshes Show Meshes proxytemplates Show ProxyTemplates + traffic-logs Show TrafficLogs traffic-permissions Show TrafficPermissions Flags: diff --git a/examples/minikube/kumactl_workflow.sh b/examples/minikube/kumactl_workflow.sh index c4bb365a2191..b4f2453a6ca3 100755 --- a/examples/minikube/kumactl_workflow.sh +++ b/examples/minikube/kumactl_workflow.sh @@ -46,6 +46,8 @@ run kumactl get proxytemplates run kumactl get traffic-permissions +run kumactl get traffic-logs + run kumactl inspect dataplanes run kumactl inspect dataplanes -otable diff --git a/pkg/api-server/definitions/all.go b/pkg/api-server/definitions/all.go index de13d3d22d0c..6e476a1bcba4 100644 --- a/pkg/api-server/definitions/all.go +++ b/pkg/api-server/definitions/all.go @@ -6,4 +6,5 @@ var All = []ResourceWsDefinition{ DataplaneInsightWsDefinition, ProxyTemplateWsDefinition, TrafficPermissionWsDefinition, + TrafficLogWsDefinition, } diff --git a/pkg/api-server/definitions/traffic_log.go b/pkg/api-server/definitions/traffic_log.go new file mode 100644 index 000000000000..f81c0e73e8f4 --- /dev/null +++ b/pkg/api-server/definitions/traffic_log.go @@ -0,0 +1,17 @@ +package definitions + +import ( + "github.com/Kong/kuma/pkg/core/resources/apis/mesh" + "github.com/Kong/kuma/pkg/core/resources/model" +) + +var TrafficLogWsDefinition = ResourceWsDefinition{ + Name: "Traffic Logging", + Path: "traffic-logs", + ResourceFactory: func() model.Resource { + return &mesh.TrafficLogResource{} + }, + ResourceListFactory: func() model.ResourceList { + return &mesh.TrafficLogResourceList{} + }, +} diff --git a/pkg/api-server/definitions/traffic_permission.go b/pkg/api-server/definitions/traffic_permission.go index 8193baab7871..670b072f559a 100644 --- a/pkg/api-server/definitions/traffic_permission.go +++ b/pkg/api-server/definitions/traffic_permission.go @@ -7,7 +7,7 @@ import ( var TrafficPermissionWsDefinition = ResourceWsDefinition{ Name: "Traffic Permission", - Path: "traffic-permission", + Path: "traffic-permissions", ResourceFactory: func() model.Resource { return &mesh.TrafficPermissionResource{} }, diff --git a/pkg/core/permissions/matcher_test.go b/pkg/core/permissions/matcher_test.go index d7e32783c9cc..6b6e8c35f405 100644 --- a/pkg/core/permissions/matcher_test.go +++ b/pkg/core/permissions/matcher_test.go @@ -40,14 +40,14 @@ var _ = Describe("Matcher", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "mobile", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "api-gateway", @@ -67,14 +67,14 @@ var _ = Describe("Matcher", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { // relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "mobile", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "backend", @@ -83,14 +83,14 @@ var _ = Describe("Matcher", func() { }, }, { // not relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "mobile", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "stats", @@ -110,14 +110,14 @@ var _ = Describe("Matcher", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { // relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "load-balancer", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "web", @@ -126,14 +126,14 @@ var _ = Describe("Matcher", func() { }, }, { // not relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "load-balancer", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "mobile", @@ -163,14 +163,14 @@ var _ = Describe("Matcher", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { // relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "mobile", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "backend", @@ -197,14 +197,14 @@ var _ = Describe("Matcher", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { // relevant rule - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "load-balancer", }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "web", diff --git a/pkg/core/resources/apis/mesh/traffic_log.go b/pkg/core/resources/apis/mesh/traffic_log.go new file mode 100644 index 000000000000..a7bb6381f634 --- /dev/null +++ b/pkg/core/resources/apis/mesh/traffic_log.go @@ -0,0 +1,74 @@ +package mesh + +import ( + "errors" + mesh_proto "github.com/Kong/kuma/api/mesh/v1alpha1" + "github.com/Kong/kuma/pkg/core/resources/model" + "github.com/Kong/kuma/pkg/core/resources/registry" +) + +const ( + TrafficLogType model.ResourceType = "TrafficLog" +) + +var _ model.Resource = &TrafficLogResource{} + +type TrafficLogResource struct { + Meta model.ResourceMeta + Spec mesh_proto.TrafficLog +} + +func (t *TrafficLogResource) GetType() model.ResourceType { + return TrafficLogType +} +func (t *TrafficLogResource) GetMeta() model.ResourceMeta { + return t.Meta +} +func (t *TrafficLogResource) SetMeta(m model.ResourceMeta) { + t.Meta = m +} +func (t *TrafficLogResource) GetSpec() model.ResourceSpec { + return &t.Spec +} +func (t *TrafficLogResource) SetSpec(spec model.ResourceSpec) error { + status, ok := spec.(*mesh_proto.TrafficLog) + if !ok { + return errors.New("invalid type of spec") + } else { + t.Spec = *status + return nil + } +} + +var _ model.ResourceList = &TrafficLogResourceList{} + +type TrafficLogResourceList struct { + Items []*TrafficLogResource +} + +func (l *TrafficLogResourceList) GetItems() []model.Resource { + res := make([]model.Resource, len(l.Items)) + for i, elem := range l.Items { + res[i] = elem + } + return res +} +func (l *TrafficLogResourceList) GetItemType() model.ResourceType { + return TrafficLogType +} +func (l *TrafficLogResourceList) NewItem() model.Resource { + return &TrafficLogResource{} +} +func (l *TrafficLogResourceList) AddItem(r model.Resource) error { + if trr, ok := r.(*TrafficLogResource); ok { + l.Items = append(l.Items, trr) + return nil + } else { + return model.ErrorInvalidItemType((*TrafficLogResource)(nil), r) + } +} + +func init() { + registry.RegisterType(&TrafficLogResource{}) + registry.RegistryListType(&TrafficLogResourceList{}) +} diff --git a/pkg/plugins/resources/k8s/native/PROJECT b/pkg/plugins/resources/k8s/native/PROJECT index 083873f75ba6..9f342916cc36 100644 --- a/pkg/plugins/resources/k8s/native/PROJECT +++ b/pkg/plugins/resources/k8s/native/PROJECT @@ -8,3 +8,6 @@ resources: - group: mesh version: v1alpha1 kind: Mesh +- group: mesh + version: v1alpha1 + kind: TrafficLog diff --git a/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types.go b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types.go new file mode 100644 index 000000000000..ad3ff1753f3f --- /dev/null +++ b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types.go @@ -0,0 +1,47 @@ +/* +Copyright 2019 Kuma 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// TrafficLogSpec defines the desired state of TrafficLog +type TrafficLogSpec = map[string]interface{} + +// TrafficLog is the Schema for the trafficlogs API +type TrafficLog struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Mesh string `json:"mesh,omitempty"` + + Spec TrafficLogSpec `json:"spec,omitempty"` +} + +// TrafficLogList contains a list of TrafficLog +type TrafficLogList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TrafficLog `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TrafficLog{}, &TrafficLogList{}) +} diff --git a/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_deepcopy.go b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_deepcopy.go new file mode 100644 index 000000000000..e6c4db56c979 --- /dev/null +++ b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_deepcopy.go @@ -0,0 +1,83 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 Kuma 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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficLog) DeepCopyInto(out *TrafficLog) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficLog. +func (in *TrafficLog) DeepCopy() *TrafficLog { + if in == nil { + return nil + } + out := new(TrafficLog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficLog) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficLogList) DeepCopyInto(out *TrafficLogList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TrafficLog, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficLogList. +func (in *TrafficLogList) DeepCopy() *TrafficLogList { + if in == nil { + return nil + } + out := new(TrafficLogList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficLogList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_helpers.go b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_helpers.go new file mode 100644 index 000000000000..9e93fc40c85d --- /dev/null +++ b/pkg/plugins/resources/k8s/native/api/v1alpha1/trafficlogging_types_helpers.go @@ -0,0 +1,45 @@ +package v1alpha1 + +import ( + proto "github.com/Kong/kuma/api/mesh/v1alpha1" + "github.com/Kong/kuma/pkg/plugins/resources/k8s/native/pkg/model" + "github.com/Kong/kuma/pkg/plugins/resources/k8s/native/pkg/registry" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (tp *TrafficLog) GetObjectMeta() *metav1.ObjectMeta { + return &tp.ObjectMeta +} + +func (tp *TrafficLog) SetObjectMeta(m *metav1.ObjectMeta) { + tp.ObjectMeta = *m +} + +func (tp *TrafficLog) GetMesh() string { + return tp.Mesh +} + +func (tp *TrafficLog) SetMesh(mesh string) { + tp.Mesh = mesh +} + +func (tp *TrafficLog) GetSpec() map[string]interface{} { + return tp.Spec +} + +func (tp *TrafficLog) SetSpec(spec map[string]interface{}) { + tp.Spec = spec +} + +func (l *TrafficLogList) GetItems() []model.KubernetesObject { + result := make([]model.KubernetesObject, len(l.Items)) + for i := range l.Items { + result[i] = &l.Items[i] + } + return result +} + +func init() { + registry.RegisterObjectType(&proto.TrafficLog{}, &TrafficLog{}) + registry.RegisterListType(&proto.TrafficLog{}, &TrafficLogList{}) +} diff --git a/pkg/plugins/resources/k8s/native/config/crd/bases/kuma.io_trafficlogs.yaml b/pkg/plugins/resources/k8s/native/config/crd/bases/kuma.io_trafficlogs.yaml new file mode 100644 index 000000000000..be51941d7cf0 --- /dev/null +++ b/pkg/plugins/resources/k8s/native/config/crd/bases/kuma.io_trafficlogs.yaml @@ -0,0 +1,390 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: trafficlogs.kuma.io +spec: + group: kuma.io + names: + kind: TrafficLog + plural: trafficlogs + scope: "" + validation: + openAPIV3Schema: + description: TrafficLog is the Schema for the trafficlogs API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map stored with + a resource that may be set by external tools to store and retrieve + arbitrary metadata. They are not queryable and should be preserved + when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + clusterName: + description: The name of the cluster which the object belongs to. This + is used to distinguish resources with same name and namespace in different + clusters. This field is not set anywhere right now and apiserver is + going to ignore it if set in create or update request. + type: string + creationTimestamp: + description: "CreationTimestamp is a timestamp representing the server + time when this object was created. It is not guaranteed to be set + in happens-before order across separate operations. Clients may not + set this value. It is represented in RFC3339 form and is in UTC. \n + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + deletionGracePeriodSeconds: + description: Number of seconds allowed for this object to gracefully + terminate before it will be removed from the system. Only set when + deletionTimestamp is also set. May only be shortened. Read-only. + format: int64 + type: integer + deletionTimestamp: + description: "DeletionTimestamp is RFC 3339 date and time at which this + resource will be deleted. This field is set by the server when a graceful + deletion is requested by the user, and is not directly settable by + a client. The resource is expected to be deleted (no longer visible + from resource lists, and not reachable by name) after the time in + this field, once the finalizers list is empty. As long as the finalizers + list contains items, deletion is blocked. Once the deletionTimestamp + is set, this value may not be unset or be set further into the future, + although it may be shortened or the resource may be deleted prior + to this time. For example, a user may request that a pod is deleted + in 30 seconds. The Kubelet will react by sending a graceful termination + signal to the containers in the pod. After that 30 seconds, the Kubelet + will send a hard termination signal (SIGKILL) to the container and + after cleanup, remove the pod from the API. In the presence of network + partitions, this object may still exist after this timestamp, until + an administrator or automated process can determine the resource is + fully terminated. If not set, graceful deletion of the object has + not been requested. \n Populated by the system when a graceful deletion + is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + format: date-time + type: string + finalizers: + description: Must be empty before the object is deleted from the registry. + Each entry is an identifier for the responsible component that will + remove the entry from the list. If the deletionTimestamp of the object + is non-nil, entries in this list can only be removed. + items: + type: string + type: array + generateName: + description: "GenerateName is an optional prefix, used by the server, + to generate a unique name ONLY IF the Name field has not been provided. + If this field is used, the name returned to the client will be different + than the name passed. This value will also be combined with a unique + suffix. The provided value has the same validation rules as the Name + field, and may be truncated by the length of the suffix required to + make the value unique on the server. \n If this field is specified + and the generated name exists, the server will NOT return a 409 - + instead, it will either return 201 Created or 500 with Reason ServerTimeout + indicating a unique name could not be found in the time allotted, + and the client should retry (optionally after the time indicated in + the Retry-After header). \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + type: string + generation: + description: A sequence number representing a specific generation of + the desired state. Populated by the system. Read-only. + format: int64 + type: integer + initializers: + description: "An initializer is a controller which enforces some system + invariant at object creation time. This field is a list of initializers + that have not yet acted on this object. If nil or empty, this object + has been completely initialized. Otherwise, the object is considered + uninitialized and is hidden (in list/watch and get calls) from clients + that haven't explicitly asked to observe uninitialized objects. \n + When an object is created, the system will populate this list with + the current set of initializers. Only privileged users may set or + modify this list. Once it is empty, it may not be modified further + by any user. \n DEPRECATED - initializers are an alpha field and will + be removed in v1.15." + properties: + pending: + description: Pending is a list of initializers that must execute + in order before this object is visible. When the last pending + initializer is removed, and no failing result is set, the initializers + struct will be set to nil and the object is considered as initialized + and visible to all clients. + items: + properties: + name: + description: name of the process that is responsible for initializing + this object. + type: string + required: + - name + type: object + type: array + result: + description: If result is set with the Failure field, the object + will be persisted to storage and then deleted, ensuring that other + clients can observe the deletion. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + code: + description: Suggested HTTP return code for this status, 0 if + not set. + format: int32 + type: integer + details: + description: Extended data associated with the reason. Each + reason may define its own extended details. This field is + optional and the data returned is not guaranteed to conform + to any schema except that defined by the reason type. + properties: + causes: + description: The Causes array includes more details associated + with the StatusReason failure. Not all StatusReasons may + provide detailed causes. + items: + properties: + field: + description: "The field of the resource that has caused + this error, as named by its JSON serialization. + May include dot and postfix notation for nested + attributes. Arrays are zero-indexed. Fields may + appear more than once in an array of causes due + to fields having multiple errors. Optional. \n Examples: + \ \"name\" - the field \"name\" on the current + resource \"items[0].name\" - the field \"name\" + on the first array entry in \"items\"" + type: string + message: + description: A human-readable description of the cause + of the error. This field may be presented as-is + to a reader. + type: string + reason: + description: A machine-readable description of the + cause of the error. If this value is empty there + is no information available. + type: string + type: object + type: array + group: + description: The group attribute of the resource associated + with the status StatusReason. + type: string + kind: + description: 'The kind attribute of the resource associated + with the status StatusReason. On some operations may differ + from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: The name attribute of the resource associated + with the status StatusReason (when there is a single name + which can be described). + type: string + retryAfterSeconds: + description: If specified, the time in seconds before the + operation should be retried. Some errors may indicate + the client must take an alternate action - for those errors + this field may indicate how long to wait before taking + the alternate action. + format: int32 + type: integer + uid: + description: 'UID of the resource. (when there is a single + resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + type: object + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + message: + description: A human-readable description of the status of this + operation. + type: string + metadata: + description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + properties: + continue: + description: continue may be set if the user set a limit + on the number of items returned, and indicates that the + server has more data available. The value is opaque and + may be used to issue another request to the endpoint that + served this list to retrieve the next set of available + objects. Continuing a consistent list may not be possible + if the server configuration has changed or more than a + few minutes have passed. The resourceVersion field returned + when using this continue value will be identical to the + value in the first response, unless you have received + this token from an error message. + type: string + resourceVersion: + description: 'String that identifies the server''s internal + version of this object that can be used by clients to + determine when objects have changed. Value must be treated + as opaque by clients and passed unmodified back to the + server. Populated by the system. Read-only. More info: + https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' + type: string + selfLink: + description: selfLink is a URL representing this object. + Populated by the system. Read-only. + type: string + type: object + reason: + description: A machine-readable description of why this operation + is in the "Failure" status. If this value is empty there is + no information available. A Reason clarifies an HTTP status + code but does not override it. + type: string + type: object + required: + - pending + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used to organize + and categorize (scope and select) objects. May match selectors of + replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + managedFields: + description: "ManagedFields maps workflow-id and version to the set + of fields that are managed by that workflow. This is mostly for internal + housekeeping, and users typically shouldn't need to set or understand + this field. A workflow can be the user's name, a controller's name, + or the name of a specific apply path like \"ci-cd\". The set of fields + is always in the version that the workflow used when modifying the + object. \n This field is alpha and can be changed or removed without + notice." + items: + properties: + apiVersion: + description: APIVersion defines the version of this resource that + this field set applies to. The format is "group/version" just + like the top-level APIVersion field. It is necessary to track + the version of a field set because it cannot be automatically + converted. + type: string + fields: + additionalProperties: true + description: Fields identifies a set of fields. + type: object + manager: + description: Manager is an identifier of the workflow managing + these fields. + type: string + operation: + description: Operation is the type of operation which lead to + this ManagedFieldsEntry being created. The only valid values + for this field are 'Apply' and 'Update'. + type: string + time: + description: Time is timestamp of when these fields were set. + It should always be empty if Operation is 'Apply' + format: date-time + type: string + type: object + type: array + name: + description: 'Name must be unique within a namespace. Is required when + creating resources, although some resources may allow a client to + request the generation of an appropriate name automatically. Name + is primarily intended for creation idempotence and configuration definition. + Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + namespace: + description: "Namespace defines the space within each name must be unique. + An empty namespace is equivalent to the \"default\" namespace, but + \"default\" is the canonical representation. Not all objects are required + to be scoped to a namespace - the value of this field for those objects + will be empty. \n Must be a DNS_LABEL. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/namespaces" + type: string + ownerReferences: + description: List of objects depended by this object. If ALL objects + in the list have been deleted, this object will be garbage collected. + If this object is managed by a controller, then an entry in this list + will point to this controller, with the controller field set to true. + There cannot be more than one managing controller. + items: + properties: + apiVersion: + description: API version of the referent. + type: string + blockOwnerDeletion: + description: If true, AND if the owner has the "foregroundDeletion" + finalizer, then the owner cannot be deleted from the key-value + store until this reference is removed. Defaults to false. To + set this field, a user needs "delete" permission of the owner, + otherwise 422 (Unprocessable Entity) will be returned. + type: boolean + controller: + description: If true, this reference points to the managing controller. + type: boolean + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names' + type: string + uid: + description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids' + type: string + required: + - apiVersion + - kind + - name + - uid + type: object + type: array + resourceVersion: + description: "An opaque value that represents the internal version of + this object that can be used by clients to determine when objects + have changed. May be used for optimistic concurrency, change detection, + and the watch operation on a resource or set of resources. Clients + must treat these values as opaque and passed unmodified back to the + server. They may only be valid for a particular resource or set of + resources. \n Populated by the system. Read-only. Value must be treated + as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + type: string + selfLink: + description: SelfLink is a URL representing this object. Populated by + the system. Read-only. + type: string + uid: + description: "UID is the unique in time and space value for this object. + It is typically generated by the server on successful creation of + a resource and is not allowed to change on PUT operations. \n Populated + by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + type: string + type: object + mesh: + type: string + spec: + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/pkg/plugins/resources/k8s/native/config/crd/patches/cainjection_in_trafficlogs.yaml b/pkg/plugins/resources/k8s/native/config/crd/patches/cainjection_in_trafficlogs.yaml new file mode 100644 index 000000000000..9806e1dd4288 --- /dev/null +++ b/pkg/plugins/resources/k8s/native/config/crd/patches/cainjection_in_trafficlogs.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: trafficlogs.kuma.io diff --git a/pkg/plugins/resources/k8s/native/config/crd/patches/webhook_in_trafficlogs.yaml b/pkg/plugins/resources/k8s/native/config/crd/patches/webhook_in_trafficlogs.yaml new file mode 100644 index 000000000000..6df4330ab043 --- /dev/null +++ b/pkg/plugins/resources/k8s/native/config/crd/patches/webhook_in_trafficlogs.yaml @@ -0,0 +1,17 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: trafficlogs.kuma.io +spec: + conversion: + strategy: Webhook + webhookClientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/pkg/plugins/resources/k8s/native/config/samples/mesh_v1alpha1_trafficlogging.yaml b/pkg/plugins/resources/k8s/native/config/samples/mesh_v1alpha1_trafficlogging.yaml new file mode 100644 index 000000000000..a9a6e6e82e9a --- /dev/null +++ b/pkg/plugins/resources/k8s/native/config/samples/mesh_v1alpha1_trafficlogging.yaml @@ -0,0 +1,17 @@ +apiVersion: kuma.io/v1alpha1 +kind: TrafficLog +mesh: default +metadata: + namespace: default + name: logging-1 +spec: + rules: + - sources: + - match: + service: backend + destinations: + - match: + service: redis + version: "5.0" + conf: + backend: file \ No newline at end of file diff --git a/pkg/plugins/resources/k8s/native/main.go b/pkg/plugins/resources/k8s/native/main.go index 987a3f3efdf1..d4731cba609a 100644 --- a/pkg/plugins/resources/k8s/native/main.go +++ b/pkg/plugins/resources/k8s/native/main.go @@ -36,7 +36,7 @@ var ( func init() { - meshv1alpha1.AddToScheme(scheme) + _ = meshv1alpha1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } diff --git a/pkg/xds/envoy/envoy_test.go b/pkg/xds/envoy/envoy_test.go index e05796a1455d..48405f494525 100644 --- a/pkg/xds/envoy/envoy_test.go +++ b/pkg/xds/envoy/envoy_test.go @@ -333,7 +333,7 @@ var _ = Describe("Envoy", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "web1", @@ -341,7 +341,7 @@ var _ = Describe("Envoy", func() { }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "backend1", diff --git a/pkg/xds/generator/inbound_proxy_generator_test.go b/pkg/xds/generator/inbound_proxy_generator_test.go index bbd5ee879804..21645f16e7f8 100644 --- a/pkg/xds/generator/inbound_proxy_generator_test.go +++ b/pkg/xds/generator/inbound_proxy_generator_test.go @@ -64,7 +64,7 @@ var _ = Describe("InboundProxyGenerator", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "web1", @@ -72,7 +72,7 @@ var _ = Describe("InboundProxyGenerator", func() { }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "backend1", diff --git a/pkg/xds/server/snapshot_generator_test.go b/pkg/xds/server/snapshot_generator_test.go index 64e8cfdc582c..b041ba1d6a61 100644 --- a/pkg/xds/server/snapshot_generator_test.go +++ b/pkg/xds/server/snapshot_generator_test.go @@ -68,7 +68,7 @@ var _ = Describe("Reconcile", func() { Spec: mesh_proto.TrafficPermission{ Rules: []*mesh_proto.TrafficPermission_Rule{ { - Sources: []*mesh_proto.TrafficPermission_Rule_Selector{ + Sources: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "web1", @@ -76,7 +76,7 @@ var _ = Describe("Reconcile", func() { }, }, }, - Destinations: []*mesh_proto.TrafficPermission_Rule_Selector{ + Destinations: []*mesh_proto.Selector{ { Match: map[string]string{ "service": "backend1",