mirror of https://github.com/k3s-io/k3s
Merge pull request #40234 from emaildanwilson/fedTargetClusterByLabel
Automatic merge from submit-queue (batch tested with PRs 40234, 45885, 42975)
Fed target cluster by label for sync controller
[use clusterselector w/ federated configmap deploys](667dc77444
)
**What this PR does / why we need it**: adds the ability to indicate objects are sent to subsets of federated clusters ref #29887
**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes
**Special notes for your reviewer**:
**Release note**:
```release-note
```
pull/6/head
commit
ca75521199
|
@ -28,6 +28,7 @@ limitations under the License.
|
|||
Cluster
|
||||
ClusterCondition
|
||||
ClusterList
|
||||
ClusterSelectorRequirement
|
||||
ClusterSpec
|
||||
ClusterStatus
|
||||
ServerAddressByClientCIDR
|
||||
|
@ -68,24 +69,31 @@ func (m *ClusterList) Reset() { *m = ClusterList{} }
|
|||
func (*ClusterList) ProtoMessage() {}
|
||||
func (*ClusterList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} }
|
||||
|
||||
func (m *ClusterSelectorRequirement) Reset() { *m = ClusterSelectorRequirement{} }
|
||||
func (*ClusterSelectorRequirement) ProtoMessage() {}
|
||||
func (*ClusterSelectorRequirement) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptorGenerated, []int{3}
|
||||
}
|
||||
|
||||
func (m *ClusterSpec) Reset() { *m = ClusterSpec{} }
|
||||
func (*ClusterSpec) ProtoMessage() {}
|
||||
func (*ClusterSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} }
|
||||
func (*ClusterSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} }
|
||||
|
||||
func (m *ClusterStatus) Reset() { *m = ClusterStatus{} }
|
||||
func (*ClusterStatus) ProtoMessage() {}
|
||||
func (*ClusterStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} }
|
||||
func (*ClusterStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} }
|
||||
|
||||
func (m *ServerAddressByClientCIDR) Reset() { *m = ServerAddressByClientCIDR{} }
|
||||
func (*ServerAddressByClientCIDR) ProtoMessage() {}
|
||||
func (*ServerAddressByClientCIDR) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptorGenerated, []int{5}
|
||||
return fileDescriptorGenerated, []int{6}
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Cluster)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.Cluster")
|
||||
proto.RegisterType((*ClusterCondition)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ClusterCondition")
|
||||
proto.RegisterType((*ClusterList)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ClusterList")
|
||||
proto.RegisterType((*ClusterSelectorRequirement)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ClusterSelectorRequirement")
|
||||
proto.RegisterType((*ClusterSpec)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ClusterSpec")
|
||||
proto.RegisterType((*ClusterStatus)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ClusterStatus")
|
||||
proto.RegisterType((*ServerAddressByClientCIDR)(nil), "k8s.io.kubernetes.federation.apis.federation.v1beta1.ServerAddressByClientCIDR")
|
||||
|
@ -220,6 +228,47 @@ func (m *ClusterList) MarshalTo(dAtA []byte) (int, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ClusterSelectorRequirement) 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 *ClusterSelectorRequirement) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key)))
|
||||
i += copy(dAtA[i:], m.Key)
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Operator)))
|
||||
i += copy(dAtA[i:], m.Operator)
|
||||
if len(m.Values) > 0 {
|
||||
for _, s := range m.Values {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
l = len(s)
|
||||
for l >= 1<<7 {
|
||||
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
|
||||
l >>= 7
|
||||
i++
|
||||
}
|
||||
dAtA[i] = uint8(l)
|
||||
i++
|
||||
i += copy(dAtA[i:], s)
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ClusterSpec) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
|
@ -406,6 +455,22 @@ func (m *ClusterList) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *ClusterSelectorRequirement) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Key)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
l = len(m.Operator)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
if len(m.Values) > 0 {
|
||||
for _, s := range m.Values {
|
||||
l = len(s)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ClusterSpec) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
|
@ -503,6 +568,18 @@ func (this *ClusterList) String() string {
|
|||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *ClusterSelectorRequirement) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&ClusterSelectorRequirement{`,
|
||||
`Key:` + fmt.Sprintf("%v", this.Key) + `,`,
|
||||
`Operator:` + fmt.Sprintf("%v", this.Operator) + `,`,
|
||||
`Values:` + fmt.Sprintf("%v", this.Values) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *ClusterSpec) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
|
@ -1022,6 +1099,143 @@ func (m *ClusterList) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ClusterSelectorRequirement) 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 ErrIntOverflowGenerated
|
||||
}
|
||||
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: ClusterSelectorRequirement: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ClusterSelectorRequirement: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
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 ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Key = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
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 ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Operator = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
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 ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Values = append(m.Values, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ClusterSpec) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
@ -1493,56 +1707,60 @@ func init() {
|
|||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 809 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6e, 0xeb, 0x44,
|
||||
0x14, 0x8e, 0xf3, 0xdb, 0x4c, 0x09, 0x54, 0x23, 0x90, 0x42, 0x16, 0x4e, 0x15, 0x21, 0xd4, 0x22,
|
||||
0xb0, 0x69, 0x40, 0xa8, 0x12, 0x02, 0xa9, 0x4e, 0x85, 0x54, 0xa9, 0x55, 0xd1, 0xb4, 0x62, 0x51,
|
||||
0x21, 0xc1, 0xc4, 0x39, 0x71, 0x4d, 0xe2, 0x1f, 0x79, 0x26, 0x11, 0xe9, 0x8a, 0x07, 0x60, 0xc1,
|
||||
0x43, 0xf0, 0x06, 0xac, 0xd9, 0x77, 0x77, 0xbb, 0xb8, 0x8b, 0xae, 0xa2, 0xdb, 0xdc, 0xb7, 0xe8,
|
||||
0xea, 0x6a, 0xc6, 0x13, 0xc7, 0xbe, 0x49, 0x7a, 0x7b, 0xdb, 0x9d, 0xe7, 0xf8, 0x9c, 0xef, 0xfb,
|
||||
0xe6, 0x7c, 0x73, 0x0e, 0x3a, 0x1c, 0xec, 0x33, 0xc3, 0x0d, 0xcc, 0xc1, 0xa8, 0x0b, 0x91, 0x0f,
|
||||
0x1c, 0x98, 0xd9, 0x87, 0x1e, 0x44, 0x94, 0xbb, 0x81, 0x6f, 0xd2, 0xd0, 0xcd, 0x9c, 0xc7, 0x7b,
|
||||
0x5d, 0xe0, 0x74, 0xcf, 0x74, 0xc0, 0x17, 0x21, 0xe8, 0x19, 0x61, 0x14, 0xf0, 0x00, 0x7f, 0x1b,
|
||||
0xa3, 0x18, 0x0b, 0x14, 0x63, 0x51, 0x65, 0x08, 0x94, 0xf4, 0x59, 0xa1, 0x34, 0xbe, 0x72, 0x5c,
|
||||
0x7e, 0x39, 0xea, 0x1a, 0x76, 0xe0, 0x99, 0x4e, 0xe0, 0x04, 0xa6, 0x04, 0xeb, 0x8e, 0xfa, 0xf2,
|
||||
0x24, 0x0f, 0xf2, 0x2b, 0x26, 0x69, 0x28, 0x12, 0x21, 0xca, 0xa3, 0xf6, 0xa5, 0xeb, 0x43, 0x34,
|
||||
0x31, 0xc3, 0x81, 0x13, 0xab, 0xf4, 0x80, 0x53, 0x73, 0xbc, 0x24, 0xad, 0x61, 0xae, 0xab, 0x8a,
|
||||
0x46, 0x3e, 0x77, 0x3d, 0x58, 0x2a, 0xf8, 0xee, 0x5d, 0x05, 0xcc, 0xbe, 0x04, 0x8f, 0x2e, 0xd5,
|
||||
0x7d, 0xb3, 0xae, 0x6e, 0xc4, 0xdd, 0xa1, 0xe9, 0xfa, 0x9c, 0xf1, 0x68, 0xa9, 0x28, 0x75, 0x27,
|
||||
0x06, 0xd1, 0x18, 0xa2, 0xc5, 0x85, 0xe0, 0x4f, 0xea, 0x85, 0x43, 0x58, 0x75, 0xa7, 0x2f, 0x97,
|
||||
0x4d, 0x53, 0x65, 0x2b, 0xb2, 0x5b, 0xff, 0xe7, 0x51, 0xa5, 0x33, 0x1c, 0x31, 0x0e, 0x11, 0xfe,
|
||||
0x1d, 0x6d, 0x88, 0x46, 0xf5, 0x28, 0xa7, 0x75, 0x6d, 0x5b, 0xdb, 0xd9, 0x6c, 0x7f, 0x6d, 0x28,
|
||||
0xef, 0xd2, 0xba, 0x8d, 0x70, 0xe0, 0xc4, 0xb6, 0x89, 0x6c, 0x63, 0xbc, 0x67, 0x9c, 0x76, 0xff,
|
||||
0x00, 0x9b, 0x9f, 0x00, 0xa7, 0x16, 0xbe, 0x9e, 0x36, 0x73, 0xb3, 0x69, 0x13, 0x2d, 0x62, 0x24,
|
||||
0x41, 0xc5, 0x36, 0x2a, 0xb2, 0x10, 0xec, 0x7a, 0x5e, 0xa2, 0x1f, 0x18, 0x4f, 0x79, 0x19, 0x86,
|
||||
0x92, 0x7b, 0x16, 0x82, 0x6d, 0x7d, 0xa0, 0xe8, 0x8a, 0xe2, 0x44, 0x24, 0x38, 0x1e, 0xa0, 0x32,
|
||||
0xe3, 0x94, 0x8f, 0x58, 0xbd, 0x20, 0x69, 0x3a, 0xcf, 0xa3, 0x91, 0x50, 0xd6, 0x87, 0x8a, 0xa8,
|
||||
0x1c, 0x9f, 0x89, 0xa2, 0x68, 0xdd, 0x16, 0xd0, 0x96, 0xca, 0xec, 0x04, 0x7e, 0xcf, 0x15, 0x10,
|
||||
0x78, 0x1f, 0x15, 0xf9, 0x24, 0x04, 0xd9, 0xc4, 0xaa, 0xf5, 0xd9, 0x5c, 0xe3, 0xf9, 0x24, 0x84,
|
||||
0xfb, 0x69, 0xf3, 0xe3, 0xb7, 0xf3, 0x45, 0x9c, 0xc8, 0x0a, 0xfc, 0x4b, 0xa2, 0x3d, 0x2f, 0x6b,
|
||||
0x7f, 0xcc, 0xd2, 0xde, 0x4f, 0x9b, 0x0f, 0xda, 0x6b, 0x24, 0x98, 0x59, 0x99, 0xd8, 0x41, 0xb5,
|
||||
0x21, 0x65, 0xfc, 0xe7, 0x28, 0xe8, 0xc2, 0xb9, 0xeb, 0x81, 0x6a, 0xcd, 0x17, 0x8f, 0xf3, 0x57,
|
||||
0x54, 0x58, 0x9f, 0x28, 0x29, 0xb5, 0xe3, 0x34, 0x10, 0xc9, 0xe2, 0xe2, 0x31, 0xc2, 0x22, 0x70,
|
||||
0x1e, 0x51, 0x9f, 0xc5, 0x97, 0x13, 0x6c, 0xc5, 0xf7, 0x66, 0x6b, 0x28, 0x36, 0x7c, 0xbc, 0x84,
|
||||
0x46, 0x56, 0x30, 0xe0, 0xcf, 0x51, 0x39, 0x02, 0xca, 0x02, 0xbf, 0x5e, 0x92, 0x8d, 0x4b, 0xfc,
|
||||
0x22, 0x32, 0x4a, 0xd4, 0x5f, 0xbc, 0x8b, 0x2a, 0x1e, 0x30, 0x46, 0x1d, 0xa8, 0x97, 0x65, 0xe2,
|
||||
0x47, 0x2a, 0xb1, 0x72, 0x12, 0x87, 0xc9, 0xfc, 0x7f, 0xeb, 0x85, 0x86, 0x36, 0x95, 0x55, 0xc7,
|
||||
0x2e, 0xe3, 0xf8, 0xd7, 0xa5, 0xf1, 0x30, 0x1e, 0x77, 0x21, 0x51, 0x2d, 0x87, 0x63, 0x4b, 0x71,
|
||||
0x6d, 0xcc, 0x23, 0xa9, 0xd1, 0xe8, 0xa2, 0x92, 0xcb, 0xc1, 0x13, 0xc6, 0x17, 0x76, 0x36, 0xdb,
|
||||
0x3f, 0x3c, 0xeb, 0xd1, 0x5a, 0x35, 0xc5, 0x54, 0x3a, 0x12, 0x98, 0x24, 0x86, 0x6e, 0xfd, 0x9b,
|
||||
0x4f, 0x6e, 0x24, 0xe6, 0x05, 0xff, 0xa7, 0xa1, 0x46, 0xbc, 0x59, 0x0e, 0x7a, 0xbd, 0x08, 0x18,
|
||||
0xb3, 0x26, 0x9d, 0xa1, 0x0b, 0x3e, 0xef, 0x1c, 0x1d, 0x12, 0x56, 0xd7, 0xa4, 0x92, 0xd3, 0xa7,
|
||||
0x29, 0x39, 0x5b, 0x87, 0x6b, 0xb5, 0x94, 0xb6, 0xc6, 0xda, 0x14, 0x46, 0x1e, 0x90, 0x85, 0x7f,
|
||||
0x43, 0x55, 0x06, 0x76, 0x04, 0x9c, 0x40, 0x5f, 0x6d, 0x92, 0xf6, 0x0a, 0x8d, 0xca, 0x06, 0x69,
|
||||
0x40, 0x60, 0xd3, 0x61, 0xbc, 0x90, 0x08, 0xf4, 0x21, 0x02, 0xdf, 0x06, 0xab, 0x36, 0x9b, 0x36,
|
||||
0xab, 0x67, 0x73, 0x20, 0xb2, 0xc0, 0x6c, 0xbd, 0xd4, 0x50, 0x2d, 0x33, 0xfd, 0xf8, 0x0a, 0x21,
|
||||
0x7b, 0x3e, 0x59, 0xf3, 0xbe, 0xfc, 0xf4, 0x2c, 0x87, 0x92, 0x41, 0x5d, 0x6c, 0xcc, 0x24, 0xc4,
|
||||
0x48, 0x8a, 0x0d, 0x37, 0x51, 0xe9, 0x2a, 0xf0, 0x81, 0xd5, 0x4b, 0xdb, 0x85, 0x9d, 0xaa, 0x55,
|
||||
0x15, 0xae, 0x5e, 0x88, 0x00, 0x89, 0xe3, 0xf1, 0xd3, 0x77, 0xdc, 0xc0, 0x57, 0x2f, 0x3a, 0xf5,
|
||||
0xf4, 0x45, 0x94, 0xa8, 0xbf, 0xad, 0xbf, 0x35, 0xf4, 0xe9, 0xda, 0x96, 0xe3, 0x36, 0x42, 0x76,
|
||||
0x72, 0x52, 0x9b, 0x6b, 0x21, 0x2d, 0xf9, 0x43, 0x52, 0x59, 0xf8, 0x7b, 0x54, 0xcb, 0xf8, 0xa4,
|
||||
0x96, 0x56, 0xb2, 0x29, 0x32, 0x6c, 0x24, 0x9b, 0x6b, 0xed, 0x5e, 0xdf, 0xe9, 0xb9, 0x9b, 0x3b,
|
||||
0x3d, 0x77, 0x7b, 0xa7, 0xe7, 0xfe, 0x9a, 0xe9, 0xda, 0xf5, 0x4c, 0xd7, 0x6e, 0x66, 0xba, 0xf6,
|
||||
0x6a, 0xa6, 0x6b, 0xff, 0xbc, 0xd6, 0x73, 0x17, 0x15, 0xd5, 0xb3, 0x37, 0x01, 0x00, 0x00, 0xff,
|
||||
0xff, 0x1d, 0x7e, 0xd9, 0xbe, 0x88, 0x08, 0x00, 0x00,
|
||||
// 879 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcf, 0x6e, 0xe3, 0x44,
|
||||
0x18, 0x8f, 0x9b, 0x26, 0x6d, 0xa6, 0x04, 0x56, 0x23, 0x90, 0x42, 0x24, 0x1c, 0x64, 0x21, 0xd4,
|
||||
0x45, 0x8b, 0x4d, 0x0b, 0x42, 0x2b, 0x21, 0x90, 0xd6, 0x59, 0x21, 0xad, 0xe8, 0xaa, 0x68, 0x5a,
|
||||
0xed, 0x61, 0x85, 0x04, 0x13, 0xe7, 0xab, 0x6b, 0x62, 0x7b, 0xcc, 0xcc, 0x38, 0x22, 0x7b, 0xe2,
|
||||
0x01, 0x40, 0xe2, 0x21, 0x78, 0x03, 0xce, 0xdc, 0x7b, 0x63, 0x0f, 0x1c, 0xf6, 0x14, 0xd1, 0xf0,
|
||||
0x16, 0x7b, 0x42, 0x33, 0x9e, 0x38, 0x36, 0x69, 0x96, 0xdd, 0xf6, 0xe6, 0xf9, 0xf9, 0xfb, 0x7e,
|
||||
0xbf, 0xef, 0x3f, 0xba, 0x3f, 0xb9, 0x2b, 0xdc, 0x88, 0x79, 0x93, 0x7c, 0x04, 0x3c, 0x05, 0x09,
|
||||
0xc2, 0x3b, 0x83, 0x31, 0x70, 0x2a, 0x23, 0x96, 0x7a, 0x34, 0x8b, 0x6a, 0xef, 0xe9, 0xc1, 0x08,
|
||||
0x24, 0x3d, 0xf0, 0x42, 0x48, 0x15, 0x04, 0x63, 0x37, 0xe3, 0x4c, 0x32, 0xfc, 0x49, 0xc1, 0xe2,
|
||||
0xae, 0x58, 0xdc, 0x95, 0x97, 0xab, 0x58, 0xaa, 0x6f, 0xc3, 0xd2, 0xff, 0x30, 0x8c, 0xe4, 0x79,
|
||||
0x3e, 0x72, 0x03, 0x96, 0x78, 0x21, 0x0b, 0x99, 0xa7, 0xc9, 0x46, 0xf9, 0x99, 0x7e, 0xe9, 0x87,
|
||||
0xfe, 0x2a, 0x44, 0xfa, 0x46, 0x44, 0x05, 0x95, 0xd0, 0xe0, 0x3c, 0x4a, 0x81, 0xcf, 0xbc, 0x6c,
|
||||
0x12, 0x16, 0x51, 0x26, 0x20, 0xa9, 0x37, 0x5d, 0x0b, 0xad, 0xef, 0x6d, 0xf2, 0xe2, 0x79, 0x2a,
|
||||
0xa3, 0x04, 0xd6, 0x1c, 0x3e, 0xfd, 0x3f, 0x07, 0x11, 0x9c, 0x43, 0x42, 0xd7, 0xfc, 0x3e, 0xde,
|
||||
0xe4, 0x97, 0xcb, 0x28, 0xf6, 0xa2, 0x54, 0x0a, 0xc9, 0xd7, 0x9c, 0x2a, 0x39, 0x09, 0xe0, 0x53,
|
||||
0xe0, 0xab, 0x84, 0xe0, 0x47, 0x9a, 0x64, 0x31, 0x5c, 0x95, 0xd3, 0x9d, 0xf5, 0xa6, 0x19, 0xb7,
|
||||
0x2b, 0xac, 0x9d, 0x3f, 0xb6, 0xd0, 0xce, 0x30, 0xce, 0x85, 0x04, 0x8e, 0xbf, 0x43, 0xbb, 0xaa,
|
||||
0x50, 0x63, 0x2a, 0x69, 0xcf, 0x7a, 0xd7, 0xda, 0xdf, 0x3b, 0xfc, 0xc8, 0x35, 0xbd, 0xab, 0xc6,
|
||||
0xed, 0x66, 0x93, 0xb0, 0x68, 0x9b, 0xb2, 0x76, 0xa7, 0x07, 0xee, 0xf1, 0xe8, 0x7b, 0x08, 0xe4,
|
||||
0x43, 0x90, 0xd4, 0xc7, 0x17, 0xf3, 0x41, 0x63, 0x31, 0x1f, 0xa0, 0x15, 0x46, 0x4a, 0x56, 0x1c,
|
||||
0xa0, 0x6d, 0x91, 0x41, 0xd0, 0xdb, 0xd2, 0xec, 0xf7, 0xdc, 0xeb, 0x4c, 0x86, 0x6b, 0xc2, 0x3d,
|
||||
0xc9, 0x20, 0xf0, 0x5f, 0x33, 0x72, 0xdb, 0xea, 0x45, 0x34, 0x39, 0x9e, 0xa0, 0xb6, 0x90, 0x54,
|
||||
0xe6, 0xa2, 0xd7, 0xd4, 0x32, 0xc3, 0x9b, 0xc9, 0x68, 0x2a, 0xff, 0x75, 0x23, 0xd4, 0x2e, 0xde,
|
||||
0xc4, 0x48, 0x38, 0xcf, 0x9a, 0xe8, 0x96, 0xb1, 0x1c, 0xb2, 0x74, 0x1c, 0x29, 0x0a, 0x7c, 0x17,
|
||||
0x6d, 0xcb, 0x59, 0x06, 0xba, 0x88, 0x1d, 0xff, 0xbd, 0x65, 0x8c, 0xa7, 0xb3, 0x0c, 0x9e, 0xcf,
|
||||
0x07, 0x6f, 0xfe, 0xd7, 0x5e, 0xe1, 0x44, 0x7b, 0xe0, 0x47, 0x65, 0xec, 0x5b, 0xda, 0xf7, 0x8b,
|
||||
0xba, 0xec, 0xf3, 0xf9, 0xe0, 0x85, 0xed, 0x75, 0x4b, 0xce, 0x7a, 0x98, 0x38, 0x44, 0xdd, 0x98,
|
||||
0x0a, 0xf9, 0x35, 0x67, 0x23, 0x38, 0x8d, 0x12, 0x30, 0xa5, 0xf9, 0xe0, 0xe5, 0xfa, 0xab, 0x3c,
|
||||
0xfc, 0xb7, 0x4c, 0x28, 0xdd, 0xa3, 0x2a, 0x11, 0xa9, 0xf3, 0xe2, 0x29, 0xc2, 0x0a, 0x38, 0xe5,
|
||||
0x34, 0x15, 0x45, 0x72, 0x4a, 0x6d, 0xfb, 0x95, 0xd5, 0xfa, 0x46, 0x0d, 0x1f, 0xad, 0xb1, 0x91,
|
||||
0x2b, 0x14, 0xf0, 0xfb, 0xa8, 0xcd, 0x81, 0x0a, 0x96, 0xf6, 0x5a, 0xba, 0x70, 0x65, 0xbf, 0x88,
|
||||
0x46, 0x89, 0xf9, 0x8b, 0x6f, 0xa3, 0x9d, 0x04, 0x84, 0xa0, 0x21, 0xf4, 0xda, 0xda, 0xf0, 0x0d,
|
||||
0x63, 0xb8, 0xf3, 0xb0, 0x80, 0xc9, 0xf2, 0xbf, 0xf3, 0xa7, 0x85, 0xf6, 0x4c, 0xab, 0x8e, 0x22,
|
||||
0x21, 0xf1, 0x37, 0x6b, 0xeb, 0xe1, 0xbe, 0x5c, 0x42, 0xca, 0x5b, 0x2f, 0xc7, 0x2d, 0xa3, 0xb5,
|
||||
0xbb, 0x44, 0x2a, 0xab, 0x31, 0x42, 0xad, 0x48, 0x42, 0xa2, 0x1a, 0xdf, 0xdc, 0xdf, 0x3b, 0xfc,
|
||||
0xfc, 0x46, 0x43, 0xeb, 0x77, 0x8d, 0x52, 0xeb, 0x81, 0xe2, 0x24, 0x05, 0xb5, 0xf3, 0x8b, 0x85,
|
||||
0xfa, 0xcb, 0xb1, 0x86, 0x18, 0x02, 0xc9, 0x38, 0x81, 0x1f, 0xf2, 0x88, 0x43, 0x02, 0xa9, 0xc4,
|
||||
0xef, 0xa0, 0xe6, 0x04, 0x66, 0x66, 0x6a, 0xf7, 0x0c, 0x43, 0xf3, 0x2b, 0x98, 0x11, 0x85, 0xe3,
|
||||
0x3b, 0x68, 0x97, 0x65, 0x4a, 0x90, 0x71, 0x33, 0x9d, 0x65, 0x3e, 0xc7, 0x06, 0x27, 0xa5, 0x05,
|
||||
0x76, 0x50, 0x7b, 0x4a, 0xe3, 0x1c, 0xd4, 0x16, 0x36, 0xf7, 0x3b, 0x3e, 0x52, 0xcd, 0x78, 0xa4,
|
||||
0x11, 0x62, 0xfe, 0x38, 0xbf, 0x6d, 0x95, 0x15, 0x56, 0xfb, 0x8b, 0x7f, 0xb7, 0x50, 0xbf, 0xb8,
|
||||
0x74, 0xf7, 0xc6, 0x63, 0x0e, 0x42, 0xf8, 0xb3, 0x61, 0x1c, 0x41, 0x2a, 0x87, 0x0f, 0xee, 0x13,
|
||||
0xd1, 0xb3, 0x74, 0x65, 0x8e, 0xaf, 0x57, 0x99, 0x93, 0x4d, 0xbc, 0xbe, 0x63, 0xb2, 0xe8, 0x6f,
|
||||
0x34, 0x11, 0xe4, 0x05, 0x61, 0xe1, 0x6f, 0x51, 0x47, 0x40, 0xc0, 0x41, 0x12, 0x38, 0x33, 0x97,
|
||||
0xed, 0xf0, 0x8a, 0x18, 0xcd, 0x58, 0xe8, 0x81, 0x60, 0x01, 0x8d, 0x8b, 0x03, 0x49, 0xe0, 0x0c,
|
||||
0x38, 0xa4, 0x01, 0xf8, 0xdd, 0xc5, 0x7c, 0xd0, 0x39, 0x59, 0x12, 0x91, 0x15, 0xa7, 0xf3, 0x97,
|
||||
0x85, 0xba, 0xb5, 0x6b, 0x84, 0x9f, 0x20, 0x14, 0x2c, 0x37, 0x7d, 0x59, 0x97, 0x2f, 0x6f, 0x34,
|
||||
0x31, 0xe5, 0xe1, 0x58, 0x5d, 0xf0, 0x12, 0x12, 0xa4, 0xa2, 0x86, 0x07, 0xa8, 0xf5, 0x84, 0xa5,
|
||||
0x20, 0x7a, 0x2d, 0xdd, 0xd7, 0x8e, 0x9a, 0xb2, 0xc7, 0x0a, 0x20, 0x05, 0x5e, 0xac, 0x62, 0x18,
|
||||
0xb1, 0xd4, 0x6c, 0x58, 0x65, 0x15, 0x15, 0x4a, 0xcc, 0x5f, 0xe7, 0x67, 0x0b, 0xbd, 0xbd, 0xb1,
|
||||
0xe4, 0xf8, 0x10, 0xa1, 0xa0, 0x7c, 0x99, 0x99, 0x5c, 0x85, 0x56, 0xfe, 0x21, 0x15, 0x2b, 0xfc,
|
||||
0x19, 0xea, 0xd6, 0xfa, 0x64, 0xc6, 0xb4, 0xbc, 0x5c, 0x35, 0x35, 0x52, 0xb7, 0xf5, 0x6f, 0x5f,
|
||||
0x5c, 0xda, 0x8d, 0xa7, 0x97, 0x76, 0xe3, 0xd9, 0xa5, 0xdd, 0xf8, 0x69, 0x61, 0x5b, 0x17, 0x0b,
|
||||
0xdb, 0x7a, 0xba, 0xb0, 0xad, 0xbf, 0x17, 0xb6, 0xf5, 0xeb, 0x3f, 0x76, 0xe3, 0xf1, 0x8e, 0xa9,
|
||||
0xd9, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x8a, 0x4c, 0xa8, 0x18, 0x09, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -83,6 +83,27 @@ message ClusterList {
|
|||
repeated Cluster items = 2;
|
||||
}
|
||||
|
||||
// ClusterSelectorRequirement contains values, a key, and an operator that relates the key and values.
|
||||
// The zero value of ClusterSelectorRequirement is invalid.
|
||||
// ClusterSelectorRequirement implements both set based match and exact match
|
||||
message ClusterSelectorRequirement {
|
||||
// +patchMergeKey=key
|
||||
// +patchStrategy=merge
|
||||
optional string key = 1;
|
||||
|
||||
// The Operator defines how the Key is matched to the Values. One of "in", "notin",
|
||||
// "exists", "!", "=", "!=", "gt" or "lt".
|
||||
optional string operator = 2;
|
||||
|
||||
// An array of string values. If the operator is "in" or "notin",
|
||||
// the values array must be non-empty. If the operator is "exists" or "!",
|
||||
// the values array must be empty. If the operator is "gt" or "lt", the values
|
||||
// array must have a single element, which will be interpreted as an integer.
|
||||
// This array is replaced during a strategic merge patch.
|
||||
// +optional
|
||||
repeated string values = 3;
|
||||
}
|
||||
|
||||
// ClusterSpec describes the attributes of a kubernetes cluster.
|
||||
message ClusterSpec {
|
||||
// A map of client CIDR to server address.
|
||||
|
|
|
@ -2111,6 +2111,331 @@ func (x *ClusterList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
||||
func (x ClusterSelector) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
if x == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yym1 := z.EncBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(x) {
|
||||
} else {
|
||||
h.encClusterSelector((ClusterSelector)(x), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClusterSelector) CodecDecodeSelf(d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
yym1 := z.DecBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(x) {
|
||||
} else {
|
||||
h.decClusterSelector((*ClusterSelector)(x), d)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClusterSelectorRequirement) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
if x == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yym1 := z.EncBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(x) {
|
||||
} else {
|
||||
yysep2 := !z.EncBinary()
|
||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||
var yyq2 [3]bool
|
||||
_, _, _ = yysep2, yyq2, yy2arr2
|
||||
const yyr2 bool = false
|
||||
yyq2[2] = len(x.Values) != 0
|
||||
var yynn2 int
|
||||
if yyr2 || yy2arr2 {
|
||||
r.EncodeArrayStart(3)
|
||||
} else {
|
||||
yynn2 = 2
|
||||
for _, b := range yyq2 {
|
||||
if b {
|
||||
yynn2++
|
||||
}
|
||||
}
|
||||
r.EncodeMapStart(yynn2)
|
||||
yynn2 = 0
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
yym4 := z.EncBinary()
|
||||
_ = yym4
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(x.Key))
|
||||
}
|
||||
} else {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("key"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
yym5 := z.EncBinary()
|
||||
_ = yym5
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(x.Key))
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
yym7 := z.EncBinary()
|
||||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(x.Operator))
|
||||
}
|
||||
} else {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("operator"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
yym8 := z.EncBinary()
|
||||
_ = yym8
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferC_UTF81234, string(x.Operator))
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if yyq2[2] {
|
||||
if x.Values == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yym10 := z.EncBinary()
|
||||
_ = yym10
|
||||
if false {
|
||||
} else {
|
||||
z.F.EncSliceStringV(x.Values, false, e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r.EncodeNil()
|
||||
}
|
||||
} else {
|
||||
if yyq2[2] {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("values"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
if x.Values == nil {
|
||||
r.EncodeNil()
|
||||
} else {
|
||||
yym11 := z.EncBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else {
|
||||
z.F.EncSliceStringV(x.Values, false, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
} else {
|
||||
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClusterSelectorRequirement) CodecDecodeSelf(d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
yym1 := z.DecBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(x) {
|
||||
} else {
|
||||
yyct2 := r.ContainerType()
|
||||
if yyct2 == codecSelferValueTypeMap1234 {
|
||||
yyl2 := r.ReadMapStart()
|
||||
if yyl2 == 0 {
|
||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
||||
} else {
|
||||
x.codecDecodeSelfFromMap(yyl2, d)
|
||||
}
|
||||
} else if yyct2 == codecSelferValueTypeArray1234 {
|
||||
yyl2 := r.ReadArrayStart()
|
||||
if yyl2 == 0 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
} else {
|
||||
x.codecDecodeSelfFromArray(yyl2, d)
|
||||
}
|
||||
} else {
|
||||
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClusterSelectorRequirement) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
|
||||
_ = yys3Slc
|
||||
var yyhl3 bool = l >= 0
|
||||
for yyj3 := 0; ; yyj3++ {
|
||||
if yyhl3 {
|
||||
if yyj3 >= l {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if r.CheckBreak() {
|
||||
break
|
||||
}
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerMapKey1234)
|
||||
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
|
||||
yys3 := string(yys3Slc)
|
||||
z.DecSendContainerState(codecSelfer_containerMapValue1234)
|
||||
switch yys3 {
|
||||
case "key":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Key = ""
|
||||
} else {
|
||||
yyv4 := &x.Key
|
||||
yym5 := z.DecBinary()
|
||||
_ = yym5
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv4)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
case "operator":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Operator = ""
|
||||
} else {
|
||||
yyv6 := &x.Operator
|
||||
yym7 := z.DecBinary()
|
||||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv6)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
case "values":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Values = nil
|
||||
} else {
|
||||
yyv8 := &x.Values
|
||||
yym9 := z.DecBinary()
|
||||
_ = yym9
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecSliceStringX(yyv8, false, d)
|
||||
}
|
||||
}
|
||||
default:
|
||||
z.DecStructFieldNotFound(-1, yys3)
|
||||
} // end switch yys3
|
||||
} // end for yyj3
|
||||
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
|
||||
}
|
||||
|
||||
func (x *ClusterSelectorRequirement) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj10 int
|
||||
var yyb10 bool
|
||||
var yyhl10 bool = l >= 0
|
||||
yyj10++
|
||||
if yyhl10 {
|
||||
yyb10 = yyj10 > l
|
||||
} else {
|
||||
yyb10 = r.CheckBreak()
|
||||
}
|
||||
if yyb10 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Key = ""
|
||||
} else {
|
||||
yyv11 := &x.Key
|
||||
yym12 := z.DecBinary()
|
||||
_ = yym12
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv11)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj10++
|
||||
if yyhl10 {
|
||||
yyb10 = yyj10 > l
|
||||
} else {
|
||||
yyb10 = r.CheckBreak()
|
||||
}
|
||||
if yyb10 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Operator = ""
|
||||
} else {
|
||||
yyv13 := &x.Operator
|
||||
yym14 := z.DecBinary()
|
||||
_ = yym14
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv13)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj10++
|
||||
if yyhl10 {
|
||||
yyb10 = yyj10 > l
|
||||
} else {
|
||||
yyb10 = r.CheckBreak()
|
||||
}
|
||||
if yyb10 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Values = nil
|
||||
} else {
|
||||
yyv15 := &x.Values
|
||||
yym16 := z.DecBinary()
|
||||
_ = yym16
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecSliceStringX(yyv15, false, d)
|
||||
}
|
||||
}
|
||||
for {
|
||||
yyj10++
|
||||
if yyhl10 {
|
||||
yyb10 = yyj10 > l
|
||||
} else {
|
||||
yyb10 = r.CheckBreak()
|
||||
}
|
||||
if yyb10 {
|
||||
break
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
z.DecStructFieldNotFound(yyj10-1, "")
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) encSliceServerAddressByClientCIDR(v []ServerAddressByClientCIDR, e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
|
@ -2467,3 +2792,122 @@ func (x codecSelfer1234) decSliceCluster(v *[]Cluster, d *codec1978.Decoder) {
|
|||
*v = yyv1
|
||||
}
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) encClusterSelector(v ClusterSelector, e *codec1978.Encoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
r.EncodeArrayStart(len(v))
|
||||
for _, yyv1 := range v {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
yy2 := &yyv1
|
||||
yy2.CodecEncodeSelf(e)
|
||||
}
|
||||
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
||||
func (x codecSelfer1234) decClusterSelector(v *ClusterSelector, d *codec1978.Decoder) {
|
||||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
|
||||
yyv1 := *v
|
||||
yyh1, yyl1 := z.DecSliceHelperStart()
|
||||
var yyc1 bool
|
||||
_ = yyc1
|
||||
if yyl1 == 0 {
|
||||
if yyv1 == nil {
|
||||
yyv1 = []ClusterSelectorRequirement{}
|
||||
yyc1 = true
|
||||
} else if len(yyv1) != 0 {
|
||||
yyv1 = yyv1[:0]
|
||||
yyc1 = true
|
||||
}
|
||||
} else if yyl1 > 0 {
|
||||
var yyrr1, yyrl1 int
|
||||
var yyrt1 bool
|
||||
_, _ = yyrl1, yyrt1
|
||||
yyrr1 = yyl1 // len(yyv1)
|
||||
if yyl1 > cap(yyv1) {
|
||||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 56)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
} else {
|
||||
yyv1 = make([]ClusterSelectorRequirement, yyrl1)
|
||||
}
|
||||
} else {
|
||||
yyv1 = make([]ClusterSelectorRequirement, yyrl1)
|
||||
}
|
||||
yyc1 = true
|
||||
yyrr1 = len(yyv1)
|
||||
if yyrg1 {
|
||||
copy(yyv1, yyv21)
|
||||
}
|
||||
} else if yyl1 != len(yyv1) {
|
||||
yyv1 = yyv1[:yyl1]
|
||||
yyc1 = true
|
||||
}
|
||||
yyj1 := 0
|
||||
for ; yyj1 < yyrr1; yyj1++ {
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = ClusterSelectorRequirement{}
|
||||
} else {
|
||||
yyv2 := &yyv1[yyj1]
|
||||
yyv2.CodecDecodeSelf(d)
|
||||
}
|
||||
|
||||
}
|
||||
if yyrt1 {
|
||||
for ; yyj1 < yyl1; yyj1++ {
|
||||
yyv1 = append(yyv1, ClusterSelectorRequirement{})
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = ClusterSelectorRequirement{}
|
||||
} else {
|
||||
yyv3 := &yyv1[yyj1]
|
||||
yyv3.CodecDecodeSelf(d)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
yyj1 := 0
|
||||
for ; !r.CheckBreak(); yyj1++ {
|
||||
|
||||
if yyj1 >= len(yyv1) {
|
||||
yyv1 = append(yyv1, ClusterSelectorRequirement{}) // var yyz1 ClusterSelectorRequirement
|
||||
yyc1 = true
|
||||
}
|
||||
yyh1.ElemContainerState(yyj1)
|
||||
if yyj1 < len(yyv1) {
|
||||
if r.TryDecodeAsNil() {
|
||||
yyv1[yyj1] = ClusterSelectorRequirement{}
|
||||
} else {
|
||||
yyv4 := &yyv1[yyj1]
|
||||
yyv4.CodecDecodeSelf(d)
|
||||
}
|
||||
|
||||
} else {
|
||||
z.DecSwallow()
|
||||
}
|
||||
|
||||
}
|
||||
if yyj1 < len(yyv1) {
|
||||
yyv1 = yyv1[:yyj1]
|
||||
yyc1 = true
|
||||
} else if yyj1 == 0 && yyv1 == nil {
|
||||
yyv1 = []ClusterSelectorRequirement{}
|
||||
yyc1 = true
|
||||
}
|
||||
}
|
||||
yyh1.End()
|
||||
if yyc1 {
|
||||
*v = yyv1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,32 @@ type ClusterList struct {
|
|||
Items []Cluster `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// Expressed as value of annotation for selecting the clusters on which a resource is created.
|
||||
type ClusterSelector []ClusterSelectorRequirement
|
||||
|
||||
// ClusterSelectorRequirement contains values, a key, and an operator that relates the key and values.
|
||||
// The zero value of ClusterSelectorRequirement is invalid.
|
||||
// ClusterSelectorRequirement implements both set based match and exact match
|
||||
type ClusterSelectorRequirement struct {
|
||||
// +patchMergeKey=key
|
||||
// +patchStrategy=merge
|
||||
Key string `json:"key" patchStrategy:"merge" patchMergeKey:"key" protobuf:"bytes,1,opt,name=key"`
|
||||
// The Operator defines how the Key is matched to the Values. One of "in", "notin",
|
||||
// "exists", "!", "=", "!=", "gt" or "lt".
|
||||
Operator string `json:"operator" protobuf:"bytes,2,opt,name=operator"`
|
||||
// An array of string values. If the operator is "in" or "notin",
|
||||
// the values array must be non-empty. If the operator is "exists" or "!",
|
||||
// the values array must be empty. If the operator is "gt" or "lt", the values
|
||||
// array must have a single element, which will be interpreted as an integer.
|
||||
// This array is replaced during a strategic merge patch.
|
||||
// +optional
|
||||
Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"`
|
||||
}
|
||||
|
||||
const (
|
||||
// FederationNamespaceSystem is the system namespace where we place federation control plane components.
|
||||
FederationNamespaceSystem string = "federation-system"
|
||||
|
||||
// FederationClusterSelectorAnnotation is used to determine placement of objects on federated clusters
|
||||
FederationClusterSelectorAnnotation string = "federation.alpha.kubernetes.io/cluster-selector"
|
||||
)
|
||||
|
|
|
@ -62,6 +62,16 @@ func (ClusterList) SwaggerDoc() map[string]string {
|
|||
return map_ClusterList
|
||||
}
|
||||
|
||||
var map_ClusterSelectorRequirement = map[string]string{
|
||||
"": "ClusterSelectorRequirement contains values, a key, and an operator that relates the key and values. The zero value of ClusterSelectorRequirement is invalid. ClusterSelectorRequirement implements both set based match and exact match",
|
||||
"operator": "The Operator defines how the Key is matched to the Values. One of \"in\", \"notin\", \"exists\", \"!\", \"=\", \"!=\", \"gt\" or \"lt\".",
|
||||
"values": "An array of string values. If the operator is \"in\" or \"notin\", the values array must be non-empty. If the operator is \"exists\" or \"!\", the values array must be empty. If the operator is \"gt\" or \"lt\", the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.",
|
||||
}
|
||||
|
||||
func (ClusterSelectorRequirement) SwaggerDoc() map[string]string {
|
||||
return map_ClusterSelectorRequirement
|
||||
}
|
||||
|
||||
var map_ClusterSpec = map[string]string{
|
||||
"": "ClusterSpec describes the attributes of a kubernetes cluster.",
|
||||
"serverAddressByClientCIDRs": "A map of client CIDR to server address. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR.",
|
||||
|
|
|
@ -39,6 +39,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_Cluster, InType: reflect.TypeOf(&Cluster{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ClusterCondition, InType: reflect.TypeOf(&ClusterCondition{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ClusterList, InType: reflect.TypeOf(&ClusterList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ClusterSelectorRequirement, InType: reflect.TypeOf(&ClusterSelectorRequirement{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ClusterSpec, InType: reflect.TypeOf(&ClusterSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ClusterStatus, InType: reflect.TypeOf(&ClusterStatus{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_ServerAddressByClientCIDR, InType: reflect.TypeOf(&ServerAddressByClientCIDR{})},
|
||||
|
@ -97,6 +98,21 @@ func DeepCopy_v1beta1_ClusterList(in interface{}, out interface{}, c *conversion
|
|||
}
|
||||
}
|
||||
|
||||
// DeepCopy_v1beta1_ClusterSelectorRequirement is an autogenerated deepcopy function.
|
||||
func DeepCopy_v1beta1_ClusterSelectorRequirement(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*ClusterSelectorRequirement)
|
||||
out := out.(*ClusterSelectorRequirement)
|
||||
*out = *in
|
||||
if in.Values != nil {
|
||||
in, out := &in.Values, &out.Values
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy_v1beta1_ClusterSpec is an autogenerated deepcopy function.
|
||||
func DeepCopy_v1beta1_ClusterSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ go_library(
|
|||
"//federation/client/clientset_generated/federation_clientset:go_default_library",
|
||||
"//federation/pkg/federatedtypes:go_default_library",
|
||||
"//federation/pkg/federation-controller/util:go_default_library",
|
||||
"//federation/pkg/federation-controller/util/clusterselector:go_default_library",
|
||||
"//federation/pkg/federation-controller/util/deletionhelper:go_default_library",
|
||||
"//federation/pkg/federation-controller/util/eventsink:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
|
|
|
@ -37,6 +37,7 @@ import (
|
|||
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||
"k8s.io/kubernetes/federation/pkg/federatedtypes"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util/clusterselector"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util/deletionhelper"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util/eventsink"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
@ -356,10 +357,15 @@ func (s *FederationSyncController) reconcile(namespacedName types.NamespacedName
|
|||
}
|
||||
|
||||
operationsAccessor := func(adapter federatedtypes.FederatedTypeAdapter, clusters []*federationapi.Cluster, obj pkgruntime.Object) ([]util.FederatedOperation, error) {
|
||||
return clusterOperations(adapter, clusters, obj, func(clusterName string) (interface{}, bool, error) {
|
||||
operations, err := clusterOperations(adapter, clusters, obj, key, func(clusterName string) (interface{}, bool, error) {
|
||||
return s.informer.GetTargetStore().GetByKey(clusterName, key)
|
||||
})
|
||||
}, clusterselector.SendToCluster)
|
||||
if err != nil {
|
||||
s.eventRecorder.Eventf(obj, api.EventTypeWarning, "FedClusterOperationsError", "Error obtaining sync operations for %s: %s error: %s", kind, key, err.Error())
|
||||
}
|
||||
return operations, err
|
||||
}
|
||||
|
||||
return syncToClusters(
|
||||
s.informer.GetReadyClusters,
|
||||
operationsAccessor,
|
||||
|
@ -451,11 +457,16 @@ func syncToClusters(clustersAccessor clustersAccessorFunc, operationsAccessor op
|
|||
}
|
||||
|
||||
type clusterObjectAccessorFunc func(clusterName string) (interface{}, bool, error)
|
||||
type clusterSelectorFunc func(map[string]string, map[string]string) (bool, error)
|
||||
|
||||
// clusterOperations returns the list of operations needed to synchronize the state of the given object to the provided clusters
|
||||
func clusterOperations(adapter federatedtypes.FederatedTypeAdapter, clusters []*federationapi.Cluster, obj pkgruntime.Object, accessor clusterObjectAccessorFunc) ([]util.FederatedOperation, error) {
|
||||
key := federatedtypes.ObjectKey(adapter, obj)
|
||||
func clusterOperations(adapter federatedtypes.FederatedTypeAdapter, clusters []*federationapi.Cluster, obj pkgruntime.Object, key string, accessor clusterObjectAccessorFunc, selector clusterSelectorFunc) ([]util.FederatedOperation, error) {
|
||||
// The data should not be modified.
|
||||
desiredObj := adapter.Copy(obj)
|
||||
objMeta := adapter.ObjectMeta(desiredObj)
|
||||
kind := adapter.Kind()
|
||||
operations := make([]util.FederatedOperation, 0)
|
||||
|
||||
for _, cluster := range clusters {
|
||||
clusterObj, found, err := accessor(cluster.Name)
|
||||
if err != nil {
|
||||
|
@ -463,18 +474,28 @@ func clusterOperations(adapter federatedtypes.FederatedTypeAdapter, clusters []*
|
|||
runtime.HandleError(wrappedErr)
|
||||
return nil, wrappedErr
|
||||
}
|
||||
// The data should not be modified.
|
||||
desiredObj := adapter.Copy(obj)
|
||||
|
||||
send, err := selector(cluster.Labels, objMeta.Annotations)
|
||||
if err != nil {
|
||||
glog.Errorf("Error processing ClusterSelector cluster: %s for %s map: %s error: %s", cluster.Name, kind, key, err.Error())
|
||||
return nil, err
|
||||
} else if !send {
|
||||
glog.V(5).Infof("Skipping cluster: %s for %s: %s reason: cluster selectors do not match: %-v %-v", cluster.Name, kind, key, cluster.ObjectMeta.Labels, objMeta.Annotations[federationapi.FederationClusterSelectorAnnotation])
|
||||
}
|
||||
|
||||
var operationType util.FederatedOperationType = ""
|
||||
if found {
|
||||
switch {
|
||||
case found && send:
|
||||
clusterObj := clusterObj.(pkgruntime.Object)
|
||||
if !adapter.Equivalent(desiredObj, clusterObj) {
|
||||
operationType = util.OperationTypeUpdate
|
||||
}
|
||||
} else {
|
||||
case found && !send:
|
||||
operationType = util.OperationTypeDelete
|
||||
case !found && send:
|
||||
operationType = util.OperationTypeAdd
|
||||
}
|
||||
|
||||
if len(operationType) > 0 {
|
||||
operations = append(operations, util.FederatedOperation{
|
||||
Type: operationType,
|
||||
|
|
|
@ -101,34 +101,55 @@ func TestClusterOperations(t *testing.T) {
|
|||
federatedtypes.SetAnnotation(adapter, differingObj, "foo", "bar")
|
||||
|
||||
testCases := map[string]struct {
|
||||
clusterObject pkgruntime.Object
|
||||
expectedErr bool
|
||||
clusterObject pkgruntime.Object
|
||||
expectedErr bool
|
||||
expectedSendErr bool
|
||||
sendToCluster bool
|
||||
|
||||
operationType util.FederatedOperationType
|
||||
}{
|
||||
"Accessor error returned": {
|
||||
expectedErr: true,
|
||||
},
|
||||
"sendToCluster error returned": {
|
||||
expectedSendErr: true,
|
||||
},
|
||||
"Missing cluster object should result in add operation": {
|
||||
operationType: util.OperationTypeAdd,
|
||||
sendToCluster: true,
|
||||
},
|
||||
"Differing cluster object should result in update operation": {
|
||||
clusterObject: differingObj,
|
||||
operationType: util.OperationTypeUpdate,
|
||||
sendToCluster: true,
|
||||
},
|
||||
"Matching object and not matching ClusterSelector should result in delete operation": {
|
||||
clusterObject: obj,
|
||||
operationType: util.OperationTypeDelete,
|
||||
sendToCluster: false,
|
||||
},
|
||||
"Matching cluster object should not result in an operation": {
|
||||
clusterObject: obj,
|
||||
sendToCluster: true,
|
||||
},
|
||||
}
|
||||
for testName, testCase := range testCases {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
clusters := []*federationapi.Cluster{fedtest.NewCluster("cluster1", apiv1.ConditionTrue)}
|
||||
operations, err := clusterOperations(adapter, clusters, obj, func(string) (interface{}, bool, error) {
|
||||
key := federatedtypes.ObjectKey(adapter, obj)
|
||||
|
||||
operations, err := clusterOperations(adapter, clusters, obj, key, func(string) (interface{}, bool, error) {
|
||||
if testCase.expectedErr {
|
||||
return nil, false, awfulError
|
||||
}
|
||||
return testCase.clusterObject, (testCase.clusterObject != nil), nil
|
||||
}, func(map[string]string, map[string]string) (bool, error) {
|
||||
if testCase.expectedSendErr {
|
||||
return false, awfulError
|
||||
}
|
||||
return testCase.sendToCluster, nil
|
||||
})
|
||||
if testCase.expectedErr {
|
||||
if testCase.expectedErr || testCase.expectedSendErr {
|
||||
require.Error(t, err, "An error was expected")
|
||||
} else {
|
||||
require.NoError(t, err, "An error was not expected")
|
||||
|
|
|
@ -88,6 +88,7 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//federation/pkg/federation-controller/util/clusterselector:all-srcs",
|
||||
"//federation/pkg/federation-controller/util/deletionhelper:all-srcs",
|
||||
"//federation/pkg/federation-controller/util/eventsink:all-srcs",
|
||||
"//federation/pkg/federation-controller/util/finalizers:all-srcs",
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["clusterselector_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//federation/apis/federation/v1beta1:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["clusterselector.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//federation/apis/federation/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clusterselector
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
federation_v1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
)
|
||||
|
||||
// Parses the cluster selector annotation to find out if the object with that annotation should be forwarded to a cluster with the given clusterLabels.
|
||||
func SendToCluster(clusterLabels map[string]string, annotations map[string]string) (bool, error) {
|
||||
// Check if a ClusterSelector annotation exists and send to all clusters when it does not exist
|
||||
val, ok := annotations[federation_v1beta1.FederationClusterSelectorAnnotation]
|
||||
if !ok {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
selector, err := getSelector(val)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return selector.Matches(labels.Set(clusterLabels)), nil
|
||||
}
|
||||
|
||||
func getSelector(annotation string) (labels.Selector, error) {
|
||||
selector := labels.NewSelector()
|
||||
requirements := make([]federation_v1beta1.ClusterSelectorRequirement, 0)
|
||||
err := json.Unmarshal([]byte(annotation), &requirements)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, requirement := range requirements {
|
||||
r, err := labels.NewRequirement(requirement.Key, ConvertOperator(requirement.Operator), requirement.Values)
|
||||
if err != nil {
|
||||
// Stop processing and assume failure since we have no way of knowing the end users intent for this or any other clusters.
|
||||
return nil, err
|
||||
}
|
||||
selector = selector.Add(*r)
|
||||
}
|
||||
|
||||
return selector, nil
|
||||
}
|
||||
|
||||
// ConvertOperator converts a string operator into selection.Operator type
|
||||
func ConvertOperator(source string) selection.Operator {
|
||||
var op selection.Operator
|
||||
switch source {
|
||||
case "!", "DoesNotExist":
|
||||
op = selection.DoesNotExist
|
||||
case "=":
|
||||
op = selection.Equals
|
||||
case "==":
|
||||
op = selection.DoubleEquals
|
||||
case "in", "In":
|
||||
op = selection.In
|
||||
case "!=":
|
||||
op = selection.NotEquals
|
||||
case "notin", "NotIn":
|
||||
op = selection.NotIn
|
||||
case "exists", "Exists":
|
||||
op = selection.Exists
|
||||
case "gt", "Gt", ">":
|
||||
op = selection.GreaterThan
|
||||
case "lt", "Lt", "<":
|
||||
op = selection.LessThan
|
||||
}
|
||||
return op
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clusterselector
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
federationapi "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
)
|
||||
|
||||
func TestSendToCluster(t *testing.T) {
|
||||
|
||||
clusterLabels := map[string]string{
|
||||
"location": "europe",
|
||||
"environment": "prod",
|
||||
"version": "15",
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
objectAnnotations map[string]string
|
||||
expectedResult bool
|
||||
expectedErr bool
|
||||
}{
|
||||
"match with single annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "location", "operator": "in", "values": ["europe"]}]`,
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
"match on multiple annotations": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "location", "operator": "in", "values": ["europe"]}, {"key": "environment", "operator": "==", "values": ["prod"]}]`,
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
"mismatch on one annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "location", "operator": "in", "values": ["europe"]}, {"key": "environment", "operator": "==", "values": ["test"]}]`,
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
"match on not equal annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "location", "operator": "!=", "values": ["usa"]}, {"key": "environment", "operator": "in", "values": ["prod"]}]`,
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
"match on greater than annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "version", "operator": ">", "values": ["14"]}]`,
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
"mismatch on greater than annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"key": "version", "operator": ">", "values": ["15"]}]`,
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
"unable to parse annotation": {
|
||||
objectAnnotations: map[string]string{
|
||||
federationapi.FederationClusterSelectorAnnotation: `[{"not able to parse",}]`,
|
||||
},
|
||||
expectedResult: false,
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for testName, testCase := range testCases {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
result, err := SendToCluster(clusterLabels, testCase.objectAnnotations)
|
||||
|
||||
if testCase.expectedErr {
|
||||
require.Error(t, err, "An error was expected")
|
||||
} else {
|
||||
require.NoError(t, err, "An error was not expected")
|
||||
}
|
||||
|
||||
require.Equal(t, testCase.expectedResult, result, "Unexpected response from SendToCluster")
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue